diff --git a/.github/CODE_OF_CONDUCT.md b/.github/CODE_OF_CONDUCT.md new file mode 100644 index 000000000..ea7e1ce81 --- /dev/null +++ b/.github/CODE_OF_CONDUCT.md @@ -0,0 +1,46 @@ +# Contributor Covenant Code of Conduct + +## Our Pledge + +In the interest of fostering an open and welcoming environment, we as contributors and maintainers pledge to making participation in our project and our community a harassment-free experience for everyone, regardless of age, body size, disability, ethnicity, gender identity and expression, level of experience, nationality, personal appearance, race, religion, or sexual identity and orientation. + +## Our Standards + +Examples of behavior that contributes to creating a positive environment include: + +* Using welcoming and inclusive language +* Being respectful of differing viewpoints and experiences +* Gracefully accepting constructive criticism +* Focusing on what is best for the community +* Showing empathy towards other community members + +Examples of unacceptable behavior by participants include: + +* The use of sexualized language or imagery and unwelcome sexual attention or advances +* Trolling, insulting/derogatory comments, and personal or political attacks +* Public or private harassment +* Publishing others' private information, such as a physical or electronic address, without explicit permission +* Other conduct which could reasonably be considered inappropriate in a professional setting + +## Our Responsibilities + +Project maintainers are responsible for clarifying the standards of acceptable behavior and are expected to take appropriate and fair corrective action in response to any instances of unacceptable behavior. + +Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, or to ban temporarily or permanently any contributor for other behaviors that they deem inappropriate, threatening, offensive, or harmful. + +## Scope + +This Code of Conduct applies both within project spaces and in public spaces when an individual is representing the project or its community. Examples of representing a project or community include using an official project e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event. Representation of a project may be further defined and clarified by project maintainers. + +## Enforcement + +Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting the project team at love@v2ray.com. The project team will review and investigate all complaints, and will respond in a way that it deems appropriate to the circumstances. The project team is obligated to maintain confidentiality with regard to the reporter of an incident. Further details of specific enforcement policies may be posted separately. + +Project maintainers who do not follow or enforce the Code of Conduct in good faith may face temporary or permanent repercussions as determined by other members of the project's leadership. + +## Attribution + +This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, available at [http://contributor-covenant.org/version/1/4][version] + +[homepage]: http://contributor-covenant.org +[version]: http://contributor-covenant.org/version/1/4/ diff --git a/.github/ISSUE_TEMPLATE b/.github/ISSUE_TEMPLATE index ab8178ea4..fe94ec31d 100644 --- a/.github/ISSUE_TEMPLATE +++ b/.github/ISSUE_TEMPLATE @@ -1,44 +1,94 @@ -提交 Issue 之前请先阅读 [Issue 指引](https://www.v2ray.com/zh_cn/chapter_01/issue.html),然后回答下面的问题,谢谢。 -Please read the [instruction](https://www.v2ray.com/en/get_started/issue.html) and answer the following questions before submitting your issue. Thank you. +Please skip to the English section below if you don't write Chinese. + +中文: +提交 Issue 之前请先阅读 [Issue 指引](https://www.v2ray.com/chapter_01/issue.html),然后回答下面的问题,谢谢。 +除非特殊情况,请完整填写所有问题。不按模板发的 issue 将直接被关闭。 1) 你正在使用哪个版本的 V2Ray?(如果服务器和客户端使用了不同版本,请注明) - What version of V2Ray are you using (If you deploy different version on server and client, please explicitly point out)? 2) 你的使用场景是什么?比如使用 Chrome 通过 Socks/VMess 代理观看 YouTube 视频。 - What's your scenario of using V2Ray? E.g., Watching YouTube videos in Chrome via Socks/VMess proxy. -3) 你看到的不正常的现象是什么? - What did you see? +3) 你看到的不正常的现象是什么?(请描述具体现象,比如访问超时,TLS 证书错误等) 4) 你期待看到的正确表现是怎样的? - What's your expectation? -5) 请附上你的配置文件(提交 Issue 前请隐藏服务器端IP地址)。 - Please attach your configuration file (**Mask IP addresses before submit this issue**). - - Server Configuration File(服务器端配置文件): +5) 请附上你的配置(提交 Issue 前请隐藏服务器端IP地址)。 + + 服务器端配置: ```javascript // 在这里附上服务器端配置文件 - // Please attach your server configuration file here. ``` - Client Configuration File(客户端配置文件): + 客户端配置: ```javascript - // 在这里附上客户端配置文件 - // Please attach your client configuration file here. + // 在这里附上客户端配置 ``` -6) 请附上出错时软件输出的日志。在 Linux 中,日志通常在 `/var/log/v2ray/error.log` 文件中。 - Please attach the log file, especially the bottom lines if the file is large. Log file is usually `/var/log/v2ray/error.log` on Linux. +6) 请附上出错时软件输出的错误日志。在 Linux 中,日志通常在 `/var/log/v2ray/error.log` 文件中。 - Server Log File(服务器端日志): + 服务器端错误日志: ``` // 在这里附上服务器端日志 - // Please attach your server log here. ``` - Client Log File(客户端日志): + 客户端错误日志: ``` // 在这里附上客户端日志 - // Please attach your client log here. ``` + +7) 请附上访问日志。在 Linux 中,日志通常在 `/var/log/v2ray/error.log` 文件中。 +``` + // 在这里附上服务器端日志 +``` + +8) 其它相关的配置文件(如 Nginx)和相关日志。 + +请预览一下你填的内容再提交。 + +如果你已经填完上面的问卷,请把下面的英文部份删除,再提交 Issue。 +Please remove the Chinese section above. + +English: +Please read the [instruction](https://www.v2ray.com/en/get_started/issue.html) and answer the following questions before submitting your issue. Thank you. +Please answer all the questions with enough information. All issues not following this template will be closed immediately. + +1) What version of V2Ray are you using (If you deploy different version on server and client, please explicitly point out)? + +2) What's your scenario of using V2Ray? E.g., Watching YouTube videos in Chrome via Socks/VMess proxy. + +3) What did you see? (Please describe in detail, such as timeout, fake TLS certificate etc) + +4) What's your expectation? + +5) Please attach your configuration file (**Mask IP addresses before submit this issue**). + + Server configuration: +```javascript + // Please attach your server configuration here. +``` + + Client configuration: +```javascript + // Please attach your client configuration here. +``` + +6) Please attach error logs, especially the bottom lines if the file is large. Error log file is usually at `/var/log/v2ray/error.log` on Linux. + + Server error log: +``` + // Please attach your server error log here. +``` + Client error log: +``` + // Please attach your client error log here. +``` + +7) Please attach access log. Access log is usually at '/var/log/v2ray/access.log' on Linux. +``` + // Please attach your server access log here. +``` + +Please review your issue before submitting. + +8) Other configurations (such as Nginx) and logs. + diff --git a/.github/SUPPORT.md b/.github/SUPPORT.md new file mode 100644 index 000000000..36212225f --- /dev/null +++ b/.github/SUPPORT.md @@ -0,0 +1,63 @@ +# V2Ray 用户支持 (User Support) + +**English reader please skip to the [English section](#way-to-get-support) below** + +## 获得帮助信息的途径 + +您可以从以下渠道获取帮助: + +1. 官方网站:[v2ray.com](https://www.v2ray.com) +1. Github:[Issues](https://github.com/v2ray/v2ray-core/issues) +1. Telegram:[主群](https://t.me/projectv2ray) + +## Github Issue 规则 + +1. 请按模板填写 issue; +1. 配置文件内容使用格式化代码段进行修饰(见下面的解释); +1. 在提交 issue 前尝试减化配置文件,比如删除不必要 inbound / outbound 模块; +1. 在提交 issue 前尝试确定问题所在,比如将 socks 代理换成 http 再次观察问题是否能重现; +1. 配置文件必须结构完整,即除了必要的隐私信息之外,配置文件可以直接拿来运行。 + +**不按模板填写的 issue 将直接被关闭** + +## 格式化代码段 + +在配置文件上下加入 Markdown 特定的修饰符,如下: + +\`\`\`javascript + +{ + // 配置文件内容 +} + +\`\`\` + +## Way to Get Support + +You may get help in the following ways: + +1. Office Site: [v2ray.com](https://www.v2ray.com) +1. Github: [Issues](https://github.com/v2ray/v2ray-core/issues) +1. Telegram: [Main Group](https://t.me/projectv2ray) + +## Github Issue Rules + +1. Please fill in the issue template. +1. Decorate config file with Markdown formatter (See below). +1. Try to simplify config file before submitting the issue, such as removing unnecessary inbound / outbound blocks. +1. Try to determine the cause of the issue, for example, replacing socks inbound with http inbound to see if the issue still exists. +1. Config file must be structurally complete. + +**Any issue not following the issue template will be closed immediately.** + +## Code formatter + +Add the following Markdown decorator to config file content: + +\`\`\`javascript + +{ + // config file +} + +\`\`\` diff --git a/.gitmodules b/.gitmodules index 803988f56..02e8083b0 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,3 +1,9 @@ [submodule "vendor/h12.me/socks"] path = vendor/h12.me/socks url = https://github.com/h12w/socks +[submodule "vendor/github.com/shadowsocks/go-shadowsocks2"] + path = vendor/github.com/shadowsocks/go-shadowsocks2 + url = https://github.com/shadowsocks/go-shadowsocks2 +[submodule "vendor/github.com/Yawning/chacha20"] + path = vendor/github.com/Yawning/chacha20 + url = https://github.com/Yawning/chacha20 diff --git a/.travis.yml b/.travis.yml index 8a488682d..df4b91faa 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,7 +1,7 @@ sudo: required language: go go: -- 1.9 +- 1.9.2 go_import_path: v2ray.com/core git: depth: 5 diff --git a/.vscode/tasks.json b/.vscode/tasks.json index 9a035c9de..b49cfb5b7 100644 --- a/.vscode/tasks.json +++ b/.vscode/tasks.json @@ -1,13 +1,18 @@ { - "version": "0.1.0", + "version": "2.0.0", "command": "go", - "isShellCommand": true, - "showOutput": "always", + "type": "shell", + "presentation": { + "echo": true, + "reveal": "always", + "focus": false, + "panel": "shared" + }, "tasks": [ { - "taskName": "build", + "label": "build", "args": ["v2ray.com/core/..."], - "isBuildCommand": true, + "group": "build", "problemMatcher": { "owner": "go", "fileLocation": ["relative", "${workspaceRoot}"], @@ -20,9 +25,9 @@ } }, { - "taskName": "test", + "label": "test", "args": ["-p", "1", "v2ray.com/core/..."], - "isBuildCommand": false + "group": "test" } ] } \ No newline at end of file diff --git a/README.md b/README.md index 29ba73975..c23b0016c 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# Project V2Ray +# Project V [![Build Status][1]][2] [![codecov.io][3]][4] [![Go Report][5]][6] [![GoDoc][7]][8] [![codebeat][9]][10] @@ -13,11 +13,21 @@ [9]: https://codebeat.co/badges/f2354ca8-3e24-463d-a2e3-159af73b2477 "Codebeat badge" [10]: https://codebeat.co/projects/github-com-v2ray-v2ray-core-master "Codebeat" -V2Ray 是一个模块化的代理软件包,它的目标是提供常用的代理软件模块,简化网络代理软件的开发。 +V 是一个模块化的代理软件包,它的目标是提供常用的代理软件模块,简化网络代理软件的开发。 [官方网站](https://www.v2ray.com/) -V2Ray provides building blocks for network proxy development. Read our [Wiki](https://www.v2ray.com/en/index.html) for more information. +V provides building blocks for network proxy development. Read our [Wiki](https://www.v2ray.com/en/index.html) for more information. ## License [The MIT License (MIT)](https://raw.githubusercontent.com/v2ray/v2ray-core/master/LICENSE) + +## Credits + +This repo relies on the following third-party projects: + +* In production: + * [miekg/dns](https://github.com/miekg/dns) + * [gorilla/websocket](https://github.com/gorilla/websocket) +* For testing only: + * [h12w/socks](https://github.com/h12w/socks) diff --git a/app/dispatcher/impl/default.go b/app/dispatcher/impl/default.go index 89bc5570c..e9e5c0804 100644 --- a/app/dispatcher/impl/default.go +++ b/app/dispatcher/impl/default.go @@ -39,7 +39,7 @@ func NewDefaultDispatcher(ctx context.Context, config *dispatcher.Config) (*Defa return nil, newError("no space in context") } d := &DefaultDispatcher{} - space.OnInitialize(func() error { + space.On(app.SpaceInitializing, func(interface{}) error { d.ohm = proxyman.OutboundHandlerManagerFromSpace(space) if d.ohm == nil { return newError("OutboundHandlerManager is not found in the space") diff --git a/app/dispatcher/impl/sniffer_test.go b/app/dispatcher/impl/sniffer_test.go index 6b10c17a3..9ae7eac8b 100644 --- a/app/dispatcher/impl/sniffer_test.go +++ b/app/dispatcher/impl/sniffer_test.go @@ -3,12 +3,14 @@ package impl_test import ( "testing" + "v2ray.com/core/app/proxyman" + . "v2ray.com/core/app/dispatcher/impl" - "v2ray.com/core/testing/assert" + . "v2ray.com/ext/assert" ) func TestHTTPHeaders(t *testing.T) { - assert := assert.On(t) + assert := With(t) cases := []struct { input string @@ -94,13 +96,13 @@ first_name=John&last_name=Doe&action=Submit`, for _, test := range cases { domain, err := SniffHTTP([]byte(test.input)) - assert.String(domain).Equals(test.domain) - assert.Error(err).Equals(test.err) + assert(domain, Equals, test.domain) + assert(err, Equals, test.err) } } func TestTLSHeaders(t *testing.T) { - assert := assert.On(t) + assert := With(t) cases := []struct { input []byte @@ -180,7 +182,13 @@ func TestTLSHeaders(t *testing.T) { for _, test := range cases { domain, err := SniffTLS(test.input) - assert.String(domain).Equals(test.domain) - assert.Error(err).Equals(test.err) + assert(domain, Equals, test.domain) + assert(err, Equals, test.err) } } + +func TestUnknownSniffer(t *testing.T) { + assert := With(t) + + assert(func() { NewSniffer([]proxyman.KnownProtocols{proxyman.KnownProtocols(-1)}) }, Panics) +} diff --git a/app/dns/server/nameserver.go b/app/dns/server/nameserver.go index 2dc7bb22f..ad007b2bc 100644 --- a/app/dns/server/nameserver.go +++ b/app/dns/server/nameserver.go @@ -8,6 +8,7 @@ import ( "github.com/miekg/dns" "v2ray.com/core/app/dispatcher" "v2ray.com/core/app/log" + "v2ray.com/core/common" "v2ray.com/core/common/buf" "v2ray.com/core/common/dice" "v2ray.com/core/common/net" @@ -15,13 +16,16 @@ import ( ) const ( - DefaultTTL = uint32(3600) CleanupInterval = time.Second * 120 CleanupThreshold = 512 ) var ( - pseudoDestination = net.UDPDestination(net.LocalHostIP, net.Port(53)) + multiQuestionDNS = map[net.Address]bool{ + net.IPAddress([]byte{8, 8, 8, 8}): true, + net.IPAddress([]byte{8, 8, 4, 4}): true, + net.IPAddress([]byte{9, 9, 9, 9}): true, + } ) type ARecord struct { @@ -55,54 +59,52 @@ func NewUDPNameServer(address net.Destination, dispatcher dispatcher.Interface) return s } -// Private: Visible for testing. -func (v *UDPNameServer) Cleanup() { +func (s *UDPNameServer) Cleanup() { expiredRequests := make([]uint16, 0, 16) now := time.Now() - v.Lock() - for id, r := range v.requests { + s.Lock() + for id, r := range s.requests { if r.expire.Before(now) { expiredRequests = append(expiredRequests, id) close(r.response) } } for _, id := range expiredRequests { - delete(v.requests, id) + delete(s.requests, id) } - v.Unlock() - expiredRequests = nil + s.Unlock() } -// Private: Visible for testing. -func (v *UDPNameServer) AssignUnusedID(response chan<- *ARecord) uint16 { +func (s *UDPNameServer) AssignUnusedID(response chan<- *ARecord) uint16 { var id uint16 - v.Lock() - if len(v.requests) > CleanupThreshold && v.nextCleanup.Before(time.Now()) { - v.nextCleanup = time.Now().Add(CleanupInterval) - go v.Cleanup() + s.Lock() + if len(s.requests) > CleanupThreshold && s.nextCleanup.Before(time.Now()) { + s.nextCleanup = time.Now().Add(CleanupInterval) + go s.Cleanup() } for { id = dice.RollUint16() - if _, found := v.requests[id]; found { + if _, found := s.requests[id]; found { continue } log.Trace(newError("add pending request id ", id).AtDebug()) - v.requests[id] = &PendingRequest{ + s.requests[id] = &PendingRequest{ expire: time.Now().Add(time.Second * 8), response: response, } break } - v.Unlock() + s.Unlock() return id } -// Private: Visible for testing. -func (v *UDPNameServer) HandleResponse(payload *buf.Buffer) { +func (s *UDPNameServer) HandleResponse(payload *buf.Buffer) { msg := new(dns.Msg) err := msg.Unpack(payload.Bytes()) - if err != nil { + if err == dns.ErrTruncated { + log.Trace(newError("truncated message received. DNS server should still work. If you see anything abnormal, please submit an issue to v2ray-core.").AtWarning()) + } else if err != nil { log.Trace(newError("failed to parse DNS response").Base(err).AtWarning()) return } @@ -110,17 +112,17 @@ func (v *UDPNameServer) HandleResponse(payload *buf.Buffer) { IPs: make([]net.IP, 0, 16), } id := msg.Id - ttl := DefaultTTL - log.Trace(newError("handling response for id ", id, " content: ", msg.String()).AtDebug()) + ttl := uint32(3600) // an hour + log.Trace(newError("handling response for id ", id, " content: ", msg).AtDebug()) - v.Lock() - request, found := v.requests[id] + s.Lock() + request, found := s.requests[id] if !found { - v.Unlock() + s.Unlock() return } - delete(v.requests, id) - v.Unlock() + delete(s.requests, id) + s.Unlock() for _, rr := range msg.Answer { switch rr := rr.(type) { @@ -142,8 +144,7 @@ func (v *UDPNameServer) HandleResponse(payload *buf.Buffer) { close(request.response) } -func (v *UDPNameServer) BuildQueryA(domain string, id uint16) *buf.Buffer { - +func (s *UDPNameServer) BuildQueryA(domain string, id uint16) *buf.Buffer { msg := new(dns.Msg) msg.Id = id msg.RecursionDesired = true @@ -153,34 +154,40 @@ func (v *UDPNameServer) BuildQueryA(domain string, id uint16) *buf.Buffer { Qtype: dns.TypeA, Qclass: dns.ClassINET, }} + if multiQuestionDNS[s.address.Address] { + msg.Question = append(msg.Question, dns.Question{ + Name: dns.Fqdn(domain), + Qtype: dns.TypeAAAA, + Qclass: dns.ClassINET, + }) + } buffer := buf.New() - buffer.AppendSupplier(func(b []byte) (int, error) { + common.Must(buffer.Reset(func(b []byte) (int, error) { writtenBuffer, err := msg.PackBuffer(b) return len(writtenBuffer), err - }) + })) return buffer } -func (v *UDPNameServer) QueryA(domain string) <-chan *ARecord { +func (s *UDPNameServer) QueryA(domain string) <-chan *ARecord { response := make(chan *ARecord, 1) - id := v.AssignUnusedID(response) + id := s.AssignUnusedID(response) - ctx, cancel := context.WithTimeout(context.Background(), time.Second*8) - v.udpServer.Dispatch(ctx, v.address, v.BuildQueryA(domain, id), v.HandleResponse) + ctx, cancel := context.WithCancel(context.Background()) + s.udpServer.Dispatch(ctx, s.address, s.BuildQueryA(domain, id), s.HandleResponse) go func() { for i := 0; i < 2; i++ { time.Sleep(time.Second) - v.Lock() - _, found := v.requests[id] - v.Unlock() - if found { - v.udpServer.Dispatch(ctx, v.address, v.BuildQueryA(domain, id), v.HandleResponse) - } else { + s.Lock() + _, found := s.requests[id] + s.Unlock() + if !found { break } + s.udpServer.Dispatch(ctx, s.address, s.BuildQueryA(domain, id), s.HandleResponse) } cancel() }() @@ -191,7 +198,7 @@ func (v *UDPNameServer) QueryA(domain string) <-chan *ARecord { type LocalNameServer struct { } -func (v *LocalNameServer) QueryA(domain string) <-chan *ARecord { +func (*LocalNameServer) QueryA(domain string) <-chan *ARecord { response := make(chan *ARecord, 1) go func() { @@ -205,7 +212,7 @@ func (v *LocalNameServer) QueryA(domain string) <-chan *ARecord { response <- &ARecord{ IPs: ips, - Expire: time.Now().Add(time.Second * time.Duration(DefaultTTL)), + Expire: time.Now().Add(time.Hour), } }() diff --git a/app/dns/server/server.go b/app/dns/server/server.go index 2fedbedf5..904feec7a 100644 --- a/app/dns/server/server.go +++ b/app/dns/server/server.go @@ -21,11 +21,22 @@ const ( ) type DomainRecord struct { - A *ARecord + IP []net.IP + Expire time.Time + LastAccess time.Time +} + +func (r *DomainRecord) Expired() bool { + return r.Expire.Before(time.Now()) +} + +func (r *DomainRecord) Inactive() bool { + now := time.Now() + return r.Expire.Before(now) || r.LastAccess.Add(time.Minute*5).Before(now) } type CacheServer struct { - sync.RWMutex + sync.Mutex hosts map[string]net.IP records map[string]*DomainRecord servers []NameServer @@ -41,7 +52,7 @@ func NewCacheServer(ctx context.Context, config *dns.Config) (*CacheServer, erro servers: make([]NameServer, len(config.NameServers)), hosts: config.GetInternalHosts(), } - space.OnInitialize(func() error { + space.On(app.SpaceInitializing, func(interface{}) error { disp := dispatcher.FromSpace(space) if disp == nil { return newError("dispatcher is not found in the space") @@ -79,15 +90,33 @@ func (*CacheServer) Start() error { func (*CacheServer) Close() {} func (s *CacheServer) GetCached(domain string) []net.IP { - s.RLock() - defer s.RUnlock() + s.Lock() + defer s.Unlock() - if record, found := s.records[domain]; found && record.A.Expire.After(time.Now()) { - return record.A.IPs + if record, found := s.records[domain]; found && !record.Expired() { + record.LastAccess = time.Now() + return record.IP } return nil } +func (s *CacheServer) tryCleanup() { + s.Lock() + defer s.Unlock() + + if len(s.records) > 256 { + domains := make([]string, 0, 256) + for d, r := range s.records { + if r.Expired() { + domains = append(domains, d) + } + } + for _, d := range domains { + delete(s.records, d) + } + } +} + func (s *CacheServer) Get(domain string) []net.IP { if ip, found := s.hosts[domain]; found { return []net.IP{ip} @@ -99,6 +128,8 @@ func (s *CacheServer) Get(domain string) []net.IP { return ips } + s.tryCleanup() + for _, server := range s.servers { response := server.QueryA(domain) select { @@ -108,7 +139,9 @@ func (s *CacheServer) Get(domain string) []net.IP { } s.Lock() s.records[domain] = &DomainRecord{ - A: a, + IP: a.IPs, + Expire: a.Expire, + LastAccess: time.Now(), } s.Unlock() log.Trace(newError("returning ", len(a.IPs), " IPs for domain ", domain).AtDebug()) diff --git a/app/dns/server/server_test.go b/app/dns/server/server_test.go new file mode 100644 index 000000000..daaae9db8 --- /dev/null +++ b/app/dns/server/server_test.go @@ -0,0 +1,105 @@ +package server_test + +import ( + "context" + "testing" + + "v2ray.com/core/app" + "v2ray.com/core/app/dispatcher" + _ "v2ray.com/core/app/dispatcher/impl" + . "v2ray.com/core/app/dns" + _ "v2ray.com/core/app/dns/server" + "v2ray.com/core/app/policy" + _ "v2ray.com/core/app/policy/manager" + "v2ray.com/core/app/proxyman" + _ "v2ray.com/core/app/proxyman/outbound" + "v2ray.com/core/common" + "v2ray.com/core/common/net" + "v2ray.com/core/common/serial" + "v2ray.com/core/proxy/freedom" + "v2ray.com/core/testing/servers/udp" + . "v2ray.com/ext/assert" + + "github.com/miekg/dns" +) + +type staticHandler struct { +} + +func (*staticHandler) ServeDNS(w dns.ResponseWriter, r *dns.Msg) { + ans := new(dns.Msg) + ans.Id = r.Id + for _, q := range r.Question { + if q.Name == "google.com." && q.Qtype == dns.TypeA { + rr, _ := dns.NewRR("google.com. IN A 8.8.8.8") + ans.Answer = append(ans.Answer, rr) + } else if q.Name == "facebook.com." && q.Qtype == dns.TypeA { + rr, _ := dns.NewRR("facebook.com. IN A 9.9.9.9") + ans.Answer = append(ans.Answer, rr) + } + } + w.WriteMsg(ans) +} + +func TestUDPServer(t *testing.T) { + assert := With(t) + + port := udp.PickPort() + + dnsServer := dns.Server{ + Addr: "127.0.0.1:" + port.String(), + Net: "udp", + Handler: &staticHandler{}, + UDPSize: 1200, + } + + go dnsServer.ListenAndServe() + + config := &Config{ + NameServers: []*net.Endpoint{ + { + Network: net.Network_UDP, + Address: &net.IPOrDomain{ + Address: &net.IPOrDomain_Ip{ + Ip: []byte{127, 0, 0, 1}, + }, + }, + Port: uint32(port), + }, + }, + } + + ctx := context.Background() + space := app.NewSpace() + + ctx = app.ContextWithSpace(ctx, space) + common.Must(app.AddApplicationToSpace(ctx, config)) + common.Must(app.AddApplicationToSpace(ctx, &dispatcher.Config{})) + common.Must(app.AddApplicationToSpace(ctx, &proxyman.OutboundConfig{})) + common.Must(app.AddApplicationToSpace(ctx, &policy.Config{})) + + om := proxyman.OutboundHandlerManagerFromSpace(space) + om.AddHandler(ctx, &proxyman.OutboundHandlerConfig{ + ProxySettings: serial.ToTypedMessage(&freedom.Config{}), + }) + + common.Must(space.Initialize()) + common.Must(space.Start()) + + server := FromSpace(space) + assert(server, IsNotNil) + + ips := server.Get("google.com") + assert(len(ips), Equals, 1) + assert([]byte(ips[0]), Equals, []byte{8, 8, 8, 8}) + + ips = server.Get("facebook.com") + assert(len(ips), Equals, 1) + assert([]byte(ips[0]), Equals, []byte{9, 9, 9, 9}) + + dnsServer.Shutdown() + + ips = server.Get("google.com") + assert(len(ips), Equals, 1) + assert([]byte(ips[0]), Equals, []byte{8, 8, 8, 8}) +} diff --git a/app/log/internal/log_entry_test.go b/app/log/internal/log_entry_test.go index c20b45eb5..c67185a03 100644 --- a/app/log/internal/log_entry_test.go +++ b/app/log/internal/log_entry_test.go @@ -4,11 +4,11 @@ import ( "testing" . "v2ray.com/core/app/log/internal" - "v2ray.com/core/testing/assert" + . "v2ray.com/ext/assert" ) func TestAccessLog(t *testing.T) { - assert := assert.On(t) + assert := With(t) entry := &AccessLog{ From: "test_from", @@ -18,8 +18,8 @@ func TestAccessLog(t *testing.T) { } entryStr := entry.String() - assert.String(entryStr).Contains("test_from") - assert.String(entryStr).Contains("test_to") - assert.String(entryStr).Contains("test_reason") - assert.String(entryStr).Contains("Accepted") + assert(entryStr, HasSubstring, "test_from") + assert(entryStr, HasSubstring, "test_to") + assert(entryStr, HasSubstring, "test_reason") + assert(entryStr, HasSubstring, "Accepted") } diff --git a/app/policy/config.go b/app/policy/config.go new file mode 100644 index 000000000..2e07c53b4 --- /dev/null +++ b/app/policy/config.go @@ -0,0 +1,26 @@ +package policy + +import ( + "time" +) + +func (s *Second) Duration() time.Duration { + return time.Second * time.Duration(s.Value) +} + +func (p *Policy) OverrideWith(another *Policy) { + if another.Timeout != nil { + if another.Timeout.Handshake != nil { + p.Timeout.Handshake = another.Timeout.Handshake + } + if another.Timeout.ConnectionIdle != nil { + p.Timeout.ConnectionIdle = another.Timeout.ConnectionIdle + } + if another.Timeout.UplinkOnly != nil { + p.Timeout.UplinkOnly = another.Timeout.UplinkOnly + } + if another.Timeout.DownlinkOnly != nil { + p.Timeout.DownlinkOnly = another.Timeout.DownlinkOnly + } + } +} diff --git a/app/policy/config.pb.go b/app/policy/config.pb.go new file mode 100644 index 000000000..98063a4b9 --- /dev/null +++ b/app/policy/config.pb.go @@ -0,0 +1,140 @@ +package policy + +import proto "github.com/golang/protobuf/proto" +import fmt "fmt" +import math "math" + +// Reference imports to suppress errors if they are not otherwise used. +var _ = proto.Marshal +var _ = fmt.Errorf +var _ = math.Inf + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the proto package it is being compiled against. +// A compilation error at this line likely means your copy of the +// proto package needs to be updated. +const _ = proto.ProtoPackageIsVersion2 // please upgrade the proto package + +type Second struct { + Value uint32 `protobuf:"varint,1,opt,name=value" json:"value,omitempty"` +} + +func (m *Second) Reset() { *m = Second{} } +func (m *Second) String() string { return proto.CompactTextString(m) } +func (*Second) ProtoMessage() {} +func (*Second) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{0} } + +func (m *Second) GetValue() uint32 { + if m != nil { + return m.Value + } + return 0 +} + +type Policy struct { + Timeout *Policy_Timeout `protobuf:"bytes,1,opt,name=timeout" json:"timeout,omitempty"` +} + +func (m *Policy) Reset() { *m = Policy{} } +func (m *Policy) String() string { return proto.CompactTextString(m) } +func (*Policy) ProtoMessage() {} +func (*Policy) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{1} } + +func (m *Policy) GetTimeout() *Policy_Timeout { + if m != nil { + return m.Timeout + } + return nil +} + +// Timeout is a message for timeout settings in various stages, in seconds. +type Policy_Timeout struct { + Handshake *Second `protobuf:"bytes,1,opt,name=handshake" json:"handshake,omitempty"` + ConnectionIdle *Second `protobuf:"bytes,2,opt,name=connection_idle,json=connectionIdle" json:"connection_idle,omitempty"` + UplinkOnly *Second `protobuf:"bytes,3,opt,name=uplink_only,json=uplinkOnly" json:"uplink_only,omitempty"` + DownlinkOnly *Second `protobuf:"bytes,4,opt,name=downlink_only,json=downlinkOnly" json:"downlink_only,omitempty"` +} + +func (m *Policy_Timeout) Reset() { *m = Policy_Timeout{} } +func (m *Policy_Timeout) String() string { return proto.CompactTextString(m) } +func (*Policy_Timeout) ProtoMessage() {} +func (*Policy_Timeout) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{1, 0} } + +func (m *Policy_Timeout) GetHandshake() *Second { + if m != nil { + return m.Handshake + } + return nil +} + +func (m *Policy_Timeout) GetConnectionIdle() *Second { + if m != nil { + return m.ConnectionIdle + } + return nil +} + +func (m *Policy_Timeout) GetUplinkOnly() *Second { + if m != nil { + return m.UplinkOnly + } + return nil +} + +func (m *Policy_Timeout) GetDownlinkOnly() *Second { + if m != nil { + return m.DownlinkOnly + } + return nil +} + +type Config struct { + Level map[uint32]*Policy `protobuf:"bytes,1,rep,name=level" json:"level,omitempty" protobuf_key:"varint,1,opt,name=key" protobuf_val:"bytes,2,opt,name=value"` +} + +func (m *Config) Reset() { *m = Config{} } +func (m *Config) String() string { return proto.CompactTextString(m) } +func (*Config) ProtoMessage() {} +func (*Config) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{2} } + +func (m *Config) GetLevel() map[uint32]*Policy { + if m != nil { + return m.Level + } + return nil +} + +func init() { + proto.RegisterType((*Second)(nil), "v2ray.core.app.policy.Second") + proto.RegisterType((*Policy)(nil), "v2ray.core.app.policy.Policy") + proto.RegisterType((*Policy_Timeout)(nil), "v2ray.core.app.policy.Policy.Timeout") + proto.RegisterType((*Config)(nil), "v2ray.core.app.policy.Config") +} + +func init() { proto.RegisterFile("v2ray.com/core/app/policy/config.proto", fileDescriptor0) } + +var fileDescriptor0 = []byte{ + // 349 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x8c, 0x92, 0xc1, 0x4a, 0xeb, 0x40, + 0x14, 0x86, 0x49, 0x7a, 0x9b, 0x72, 0x4f, 0x6f, 0xaf, 0x32, 0x58, 0x88, 0x05, 0xa5, 0x14, 0x94, + 0xae, 0x26, 0x90, 0x6e, 0x44, 0xb1, 0x62, 0x45, 0x41, 0x10, 0x2c, 0x51, 0x14, 0xdc, 0x94, 0x71, + 0x32, 0xda, 0xd0, 0xe9, 0x9c, 0x21, 0xa6, 0x95, 0xbc, 0x86, 0x6f, 0xe0, 0xd6, 0x87, 0xf2, 0x59, + 0x24, 0x99, 0x84, 0x6c, 0x5a, 0xe9, 0x6e, 0x72, 0xf8, 0xfe, 0x8f, 0x43, 0xfe, 0x03, 0x87, 0x4b, + 0x3f, 0x66, 0x29, 0xe5, 0x38, 0xf7, 0x38, 0xc6, 0xc2, 0x63, 0x5a, 0x7b, 0x1a, 0x65, 0xc4, 0x53, + 0x8f, 0xa3, 0x7a, 0x89, 0x5e, 0xa9, 0x8e, 0x31, 0x41, 0xd2, 0x2e, 0xb9, 0x58, 0x50, 0xa6, 0x35, + 0x35, 0x4c, 0x6f, 0x1f, 0x9c, 0x3b, 0xc1, 0x51, 0x85, 0x64, 0x07, 0xea, 0x4b, 0x26, 0x17, 0xc2, + 0xb5, 0xba, 0x56, 0xbf, 0x15, 0x98, 0x8f, 0xde, 0xb7, 0x0d, 0xce, 0x38, 0x47, 0xc9, 0x19, 0x34, + 0x92, 0x68, 0x2e, 0x70, 0x91, 0xe4, 0x48, 0xd3, 0x3f, 0xa0, 0x2b, 0x9d, 0xd4, 0xf0, 0xf4, 0xde, + 0xc0, 0x41, 0x99, 0xea, 0x7c, 0xd8, 0xd0, 0x28, 0x86, 0xe4, 0x04, 0xfe, 0x4e, 0x99, 0x0a, 0xdf, + 0xa6, 0x6c, 0x26, 0x0a, 0xdd, 0xde, 0x1a, 0x9d, 0xd9, 0x2f, 0xa8, 0x78, 0x72, 0x05, 0x5b, 0x1c, + 0x95, 0x12, 0x3c, 0x89, 0x50, 0x4d, 0xa2, 0x50, 0x0a, 0xd7, 0xde, 0x44, 0xf1, 0xbf, 0x4a, 0x5d, + 0x87, 0x52, 0x90, 0x21, 0x34, 0x17, 0x5a, 0x46, 0x6a, 0x36, 0x41, 0x25, 0x53, 0xb7, 0xb6, 0x89, + 0x03, 0x4c, 0xe2, 0x56, 0xc9, 0x94, 0x8c, 0xa0, 0x15, 0xe2, 0xbb, 0xaa, 0x0c, 0x7f, 0x36, 0x31, + 0xfc, 0x2b, 0x33, 0x99, 0xa3, 0xf7, 0x69, 0x81, 0x73, 0x91, 0x17, 0x45, 0x86, 0x50, 0x97, 0x62, + 0x29, 0xa4, 0x6b, 0x75, 0x6b, 0xfd, 0xa6, 0xdf, 0x5f, 0xa3, 0x31, 0x34, 0xbd, 0xc9, 0xd0, 0x4b, + 0x95, 0xc4, 0x69, 0x60, 0x62, 0x9d, 0x47, 0x80, 0x6a, 0x48, 0xb6, 0xa1, 0x36, 0x13, 0x69, 0xd1, + 0x66, 0xf6, 0x24, 0x83, 0xb2, 0xe1, 0xdf, 0x7f, 0x96, 0xa9, 0xaf, 0x38, 0x80, 0x63, 0xfb, 0xc8, + 0x1a, 0x9d, 0xc2, 0x2e, 0xc7, 0xf9, 0x6a, 0x7c, 0x6c, 0x3d, 0x39, 0xe6, 0xf5, 0x65, 0xb7, 0x1f, + 0xfc, 0x80, 0x65, 0x0b, 0xc6, 0x82, 0x9e, 0x6b, 0x5d, 0x98, 0x9e, 0x9d, 0xfc, 0x02, 0x07, 0x3f, + 0x01, 0x00, 0x00, 0xff, 0xff, 0xcf, 0x25, 0x25, 0xc2, 0xab, 0x02, 0x00, 0x00, +} diff --git a/app/policy/config.proto b/app/policy/config.proto new file mode 100644 index 000000000..b00aefc5c --- /dev/null +++ b/app/policy/config.proto @@ -0,0 +1,27 @@ +syntax = "proto3"; + +package v2ray.core.app.policy; +option csharp_namespace = "V2Ray.Core.App.Policy"; +option go_package = "policy"; +option java_package = "com.v2ray.core.app.policy"; +option java_multiple_files = true; + +message Second { + uint32 value = 1; +} + +message Policy { + // Timeout is a message for timeout settings in various stages, in seconds. + message Timeout { + Second handshake = 1; + Second connection_idle = 2; + Second uplink_only = 3; + Second downlink_only = 4; + } + + Timeout timeout = 1; +} + +message Config { + map level = 1; +} diff --git a/app/policy/manager/manager.go b/app/policy/manager/manager.go new file mode 100644 index 000000000..6a339d9aa --- /dev/null +++ b/app/policy/manager/manager.go @@ -0,0 +1,66 @@ +package manager + +import ( + "context" + + "v2ray.com/core/app/policy" + "v2ray.com/core/common" +) + +type Instance struct { + levels map[uint32]*policy.Policy +} + +func New(ctx context.Context, config *policy.Config) (*Instance, error) { + levels := config.Level + if levels == nil { + levels = make(map[uint32]*policy.Policy) + } + for _, p := range levels { + g := global() + g.OverrideWith(p) + *p = g + } + return &Instance{ + levels: levels, + }, nil +} + +func global() policy.Policy { + return policy.Policy{ + Timeout: &policy.Policy_Timeout{ + Handshake: &policy.Second{Value: 4}, + ConnectionIdle: &policy.Second{Value: 300}, + UplinkOnly: &policy.Second{Value: 5}, + DownlinkOnly: &policy.Second{Value: 30}, + }, + } +} + +// GetPolicy implements policy.Manager. +func (m *Instance) GetPolicy(level uint32) policy.Policy { + if p, ok := m.levels[level]; ok { + return *p + } + return global() +} + +// Start implements app.Application.Start(). +func (m *Instance) Start() error { + return nil +} + +// Close implements app.Application.Close(). +func (m *Instance) Close() { +} + +// Interface implement app.Application.Interface(). +func (m *Instance) Interface() interface{} { + return (*policy.Manager)(nil) +} + +func init() { + common.Must(common.RegisterConfig((*policy.Config)(nil), func(ctx context.Context, config interface{}) (interface{}, error) { + return New(ctx, config.(*policy.Config)) + })) +} diff --git a/app/policy/policy.go b/app/policy/policy.go new file mode 100644 index 000000000..f67e736e9 --- /dev/null +++ b/app/policy/policy.go @@ -0,0 +1,20 @@ +package policy + +import ( + "v2ray.com/core/app" +) + +// Manager is an utility to manage policy per user level. +type Manager interface { + // GetPolicy returns the Policy for the given user level. + GetPolicy(level uint32) Policy +} + +// FromSpace returns the policy.Manager in a space. +func FromSpace(space app.Space) Manager { + app := space.GetApplication((*Manager)(nil)) + if app == nil { + return nil + } + return app.(Manager) +} diff --git a/app/proxyman/inbound/worker.go b/app/proxyman/inbound/worker.go index 5783d970b..4b74b5417 100644 --- a/app/proxyman/inbound/worker.go +++ b/app/proxyman/inbound/worker.go @@ -172,6 +172,11 @@ func (*udpConn) SetWriteDeadline(time.Time) error { return nil } +type connId struct { + src net.Destination + dest net.Destination +} + type udpWorker struct { sync.RWMutex @@ -185,39 +190,43 @@ type udpWorker struct { ctx context.Context cancel context.CancelFunc - activeConn map[net.Destination]*udpConn + activeConn map[connId]*udpConn } -func (w *udpWorker) getConnection(src net.Destination) (*udpConn, bool) { +func (w *udpWorker) getConnection(id connId) (*udpConn, bool) { w.Lock() defer w.Unlock() - if conn, found := w.activeConn[src]; found { + if conn, found := w.activeConn[id]; found { return conn, true } conn := &udpConn{ input: make(chan *buf.Buffer, 32), output: func(b []byte) (int, error) { - return w.hub.WriteTo(b, src) + return w.hub.WriteTo(b, id.src) }, remote: &net.UDPAddr{ - IP: src.Address.IP(), - Port: int(src.Port), + IP: id.src.Address.IP(), + Port: int(id.src.Port), }, local: &net.UDPAddr{ IP: w.address.IP(), Port: int(w.port), }, } - w.activeConn[src] = conn + w.activeConn[id] = conn conn.updateActivity() return conn, false } func (w *udpWorker) callback(b *buf.Buffer, source net.Destination, originalDest net.Destination) { - conn, existing := w.getConnection(source) + id := connId{ + src: source, + dest: originalDest, + } + conn, existing := w.getConnection(id) select { case conn.input <- b: default: @@ -240,20 +249,20 @@ func (w *udpWorker) callback(b *buf.Buffer, source net.Destination, originalDest if err := w.proxy.Process(ctx, net.Network_UDP, conn, w.dispatcher); err != nil { log.Trace(newError("connection ends").Base(err)) } - w.removeConn(source) + w.removeConn(id) cancel() }() } } -func (w *udpWorker) removeConn(src net.Destination) { +func (w *udpWorker) removeConn(id connId) { w.Lock() - delete(w.activeConn, src) + delete(w.activeConn, id) w.Unlock() } func (w *udpWorker) Start() error { - w.activeConn = make(map[net.Destination]*udpConn) + w.activeConn = make(map[connId]*udpConn, 16) ctx, cancel := context.WithCancel(context.Background()) w.ctx = ctx w.cancel = cancel diff --git a/app/proxyman/mux/frame.go b/app/proxyman/mux/frame.go index 74cabda23..462dd0da4 100644 --- a/app/proxyman/mux/frame.go +++ b/app/proxyman/mux/frame.go @@ -1,8 +1,10 @@ package mux import ( + "v2ray.com/core/common/bitmask" "v2ray.com/core/common/buf" "v2ray.com/core/common/net" + "v2ray.com/core/common/protocol" "v2ray.com/core/common/serial" ) @@ -15,24 +17,10 @@ const ( SessionStatusKeepAlive SessionStatus = 0x04 ) -type Option byte - const ( - OptionData Option = 0x01 + OptionData bitmask.Byte = 0x01 ) -func (o Option) Has(x Option) bool { - return (o & x) == x -} - -func (o *Option) Add(x Option) { - *o = (*o | x) -} - -func (o *Option) Clear(x Option) { - *o = (*o & (^x)) -} - type TargetNetwork byte const ( @@ -40,14 +28,6 @@ const ( TargetNetworkUDP TargetNetwork = 0x02 ) -type AddressType byte - -const ( - AddressTypeIPv4 AddressType = 0x01 - AddressTypeDomain AddressType = 0x02 - AddressTypeIPv6 AddressType = 0x03 -) - /* Frame format 2 bytes - length @@ -62,10 +42,10 @@ n bytes - address */ type FrameMetadata struct { - SessionID uint16 - SessionStatus SessionStatus Target net.Destination - Option Option + SessionID uint16 + Option bitmask.Byte + SessionStatus SessionStatus } func (f FrameMetadata) AsSupplier() buf.Supplier { @@ -92,17 +72,21 @@ func (f FrameMetadata) AsSupplier() buf.Supplier { addr := f.Target.Address switch addr.Family() { case net.AddressFamilyIPv4: - b = append(b, byte(AddressTypeIPv4)) + b = append(b, byte(protocol.AddressTypeIPv4)) b = append(b, addr.IP()...) length += 5 case net.AddressFamilyIPv6: - b = append(b, byte(AddressTypeIPv6)) + b = append(b, byte(protocol.AddressTypeIPv6)) b = append(b, addr.IP()...) length += 17 case net.AddressFamilyDomain: - nDomain := len(addr.Domain()) - b = append(b, byte(AddressTypeDomain), byte(nDomain)) - b = append(b, addr.Domain()...) + domain := addr.Domain() + if protocol.IsDomainTooLong(domain) { + return 0, newError("domain name too long: ", domain) + } + nDomain := len(domain) + b = append(b, byte(protocol.AddressTypeDomain), byte(nDomain)) + b = append(b, domain...) length += nDomain + 2 } } @@ -120,7 +104,7 @@ func ReadFrameFrom(b []byte) (*FrameMetadata, error) { f := &FrameMetadata{ SessionID: serial.BytesToUint16(b[:2]), SessionStatus: SessionStatus(b[2]), - Option: Option(b[3]), + Option: bitmask.Byte(b[3]), } b = b[4:] @@ -128,18 +112,18 @@ func ReadFrameFrom(b []byte) (*FrameMetadata, error) { if f.SessionStatus == SessionStatusNew { network := TargetNetwork(b[0]) port := net.PortFromBytes(b[1:3]) - addrType := AddressType(b[3]) + addrType := protocol.AddressType(b[3]) b = b[4:] var addr net.Address switch addrType { - case AddressTypeIPv4: + case protocol.AddressTypeIPv4: addr = net.IPAddress(b[0:4]) b = b[4:] - case AddressTypeIPv6: + case protocol.AddressTypeIPv6: addr = net.IPAddress(b[0:16]) b = b[16:] - case AddressTypeDomain: + case protocol.AddressTypeDomain: nDomain := int(b[0]) addr = net.DomainAddress(string(b[1 : 1+nDomain])) b = b[nDomain+1:] diff --git a/app/proxyman/mux/mux.go b/app/proxyman/mux/mux.go index 39e7a825b..4acbb2569 100644 --- a/app/proxyman/mux/mux.go +++ b/app/proxyman/mux/mux.go @@ -90,7 +90,19 @@ func NewClient(p proxy.Outbound, dialer proxy.Dialer, m *ClientManager) (*Client ctx, cancel := context.WithCancel(context.Background()) ctx = proxy.ContextWithTarget(ctx, net.TCPDestination(muxCoolAddress, muxCoolPort)) pipe := ray.NewRay(ctx) - go p.Process(ctx, pipe, dialer) + + go func() { + if err := p.Process(ctx, pipe, dialer); err != nil { + cancel() + + traceErr := errors.New("failed to handler mux client connection").Base(err) + if err != io.EOF && err != context.Canceled { + traceErr = traceErr.AtWarning() + } + log.Trace(traceErr) + } + }() + c := &Client{ sessionManager: NewSessionManager(), inboundRay: pipe, @@ -104,6 +116,7 @@ func NewClient(p proxy.Outbound, dialer proxy.Dialer, m *ClientManager) (*Client return c, nil } +// Closed returns true if this Client is closed. func (m *Client) Closed() bool { select { case <-m.ctx.Done(): @@ -148,7 +161,7 @@ func fetchInput(ctx context.Context, s *Session, output buf.Writer) { log.Trace(newError("dispatching request to ", dest)) data, _ := s.input.ReadTimeout(time.Millisecond * 500) - if err := writer.Write(data); err != nil { + if err := writer.WriteMultiBuffer(data); err != nil { log.Trace(newError("failed to write first payload").Base(err)) return } @@ -179,26 +192,25 @@ func (m *Client) Dispatch(ctx context.Context, outboundRay ray.OutboundRay) bool return true } -func drain(reader io.Reader) error { - buf.Copy(NewStreamReader(reader), buf.Discard) - return nil +func drain(reader *buf.BufferedReader) error { + return buf.Copy(NewStreamReader(reader), buf.Discard) } -func (m *Client) handleStatueKeepAlive(meta *FrameMetadata, reader io.Reader) error { +func (m *Client) handleStatueKeepAlive(meta *FrameMetadata, reader *buf.BufferedReader) error { if meta.Option.Has(OptionData) { return drain(reader) } return nil } -func (m *Client) handleStatusNew(meta *FrameMetadata, reader io.Reader) error { +func (m *Client) handleStatusNew(meta *FrameMetadata, reader *buf.BufferedReader) error { if meta.Option.Has(OptionData) { return drain(reader) } return nil } -func (m *Client) handleStatusKeep(meta *FrameMetadata, reader io.Reader) error { +func (m *Client) handleStatusKeep(meta *FrameMetadata, reader *buf.BufferedReader) error { if !meta.Option.Has(OptionData) { return nil } @@ -209,7 +221,7 @@ func (m *Client) handleStatusKeep(meta *FrameMetadata, reader io.Reader) error { return drain(reader) } -func (m *Client) handleStatusEnd(meta *FrameMetadata, reader io.Reader) error { +func (m *Client) handleStatusEnd(meta *FrameMetadata, reader *buf.BufferedReader) error { if s, found := m.sessionManager.Get(meta.SessionID); found { s.Close() } @@ -222,11 +234,10 @@ func (m *Client) handleStatusEnd(meta *FrameMetadata, reader io.Reader) error { func (m *Client) fetchOutput() { defer m.cancel() - reader := buf.ToBytesReader(m.inboundRay.InboundOutput()) - metaReader := NewMetadataReader(reader) + reader := buf.NewBufferedReader(m.inboundRay.InboundOutput()) for { - meta, err := metaReader.Read() + meta, err := ReadMetadata(reader) if err != nil { if errors.Cause(err) != io.EOF { log.Trace(newError("failed to read metadata").Base(err)) @@ -263,7 +274,7 @@ type Server struct { func NewServer(ctx context.Context) *Server { s := &Server{} space := app.SpaceFromContext(ctx) - space.OnInitialize(func() error { + space.On(app.SpaceInitializing, func(interface{}) error { d := dispatcher.FromSpace(space) if d == nil { return newError("no dispatcher in space") @@ -304,14 +315,14 @@ func handle(ctx context.Context, s *Session, output buf.Writer) { s.Close() } -func (w *ServerWorker) handleStatusKeepAlive(meta *FrameMetadata, reader io.Reader) error { +func (w *ServerWorker) handleStatusKeepAlive(meta *FrameMetadata, reader *buf.BufferedReader) error { if meta.Option.Has(OptionData) { return drain(reader) } return nil } -func (w *ServerWorker) handleStatusNew(ctx context.Context, meta *FrameMetadata, reader io.Reader) error { +func (w *ServerWorker) handleStatusNew(ctx context.Context, meta *FrameMetadata, reader *buf.BufferedReader) error { log.Trace(newError("received request for ", meta.Target)) inboundRay, err := w.dispatcher.Dispatch(ctx, meta.Target) if err != nil { @@ -338,7 +349,7 @@ func (w *ServerWorker) handleStatusNew(ctx context.Context, meta *FrameMetadata, return nil } -func (w *ServerWorker) handleStatusKeep(meta *FrameMetadata, reader io.Reader) error { +func (w *ServerWorker) handleStatusKeep(meta *FrameMetadata, reader *buf.BufferedReader) error { if !meta.Option.Has(OptionData) { return nil } @@ -348,7 +359,7 @@ func (w *ServerWorker) handleStatusKeep(meta *FrameMetadata, reader io.Reader) e return drain(reader) } -func (w *ServerWorker) handleStatusEnd(meta *FrameMetadata, reader io.Reader) error { +func (w *ServerWorker) handleStatusEnd(meta *FrameMetadata, reader *buf.BufferedReader) error { if s, found := w.sessionManager.Get(meta.SessionID); found { s.Close() } @@ -358,9 +369,8 @@ func (w *ServerWorker) handleStatusEnd(meta *FrameMetadata, reader io.Reader) er return nil } -func (w *ServerWorker) handleFrame(ctx context.Context, reader io.Reader) error { - metaReader := NewMetadataReader(reader) - meta, err := metaReader.Read() +func (w *ServerWorker) handleFrame(ctx context.Context, reader *buf.BufferedReader) error { + meta, err := ReadMetadata(reader) if err != nil { return newError("failed to read metadata").Base(err) } @@ -386,7 +396,7 @@ func (w *ServerWorker) handleFrame(ctx context.Context, reader io.Reader) error func (w *ServerWorker) run(ctx context.Context) { input := w.outboundRay.OutboundInput() - reader := buf.ToBytesReader(input) + reader := buf.NewBufferedReader(input) defer w.sessionManager.Close() diff --git a/app/proxyman/mux/mux_test.go b/app/proxyman/mux/mux_test.go index f7977cf35..bb6425c60 100644 --- a/app/proxyman/mux/mux_test.go +++ b/app/proxyman/mux/mux_test.go @@ -9,14 +9,14 @@ import ( "v2ray.com/core/common/buf" "v2ray.com/core/common/net" "v2ray.com/core/common/protocol" - "v2ray.com/core/testing/assert" "v2ray.com/core/transport/ray" + . "v2ray.com/ext/assert" ) func readAll(reader buf.Reader) (buf.MultiBuffer, error) { - mb := buf.NewMultiBuffer() + var mb buf.MultiBuffer for { - b, err := reader.Read() + b, err := reader.ReadMultiBuffer() if err == io.EOF { break } @@ -29,7 +29,7 @@ func readAll(reader buf.Reader) (buf.MultiBuffer, error) { } func TestReaderWriter(t *testing.T) { - assert := assert.On(t) + assert := With(t) stream := ray.NewStream(context.Background()) @@ -45,98 +45,98 @@ func TestReaderWriter(t *testing.T) { writePayload := func(writer *Writer, payload ...byte) error { b := buf.New() b.Append(payload) - return writer.Write(buf.NewMultiBufferValue(b)) + return writer.WriteMultiBuffer(buf.NewMultiBufferValue(b)) } - assert.Error(writePayload(writer, 'a', 'b', 'c', 'd')).IsNil() - assert.Error(writePayload(writer2)).IsNil() + assert(writePayload(writer, 'a', 'b', 'c', 'd'), IsNil) + assert(writePayload(writer2), IsNil) - assert.Error(writePayload(writer, 'e', 'f', 'g', 'h')).IsNil() - assert.Error(writePayload(writer3, 'x')).IsNil() + assert(writePayload(writer, 'e', 'f', 'g', 'h'), IsNil) + assert(writePayload(writer3, 'x'), IsNil) writer.Close() writer3.Close() - assert.Error(writePayload(writer2, 'y')).IsNil() + assert(writePayload(writer2, 'y'), IsNil) writer2.Close() - bytesReader := buf.ToBytesReader(stream) - metaReader := NewMetadataReader(bytesReader) + bytesReader := buf.NewBufferedReader(stream) streamReader := NewStreamReader(bytesReader) - meta, err := metaReader.Read() - assert.Error(err).IsNil() - assert.Uint16(meta.SessionID).Equals(1) - assert.Byte(byte(meta.SessionStatus)).Equals(byte(SessionStatusNew)) - assert.Destination(meta.Target).Equals(dest) - assert.Byte(byte(meta.Option)).Equals(byte(OptionData)) + meta, err := ReadMetadata(bytesReader) + assert(err, IsNil) + assert(meta.SessionID, Equals, uint16(1)) + assert(byte(meta.SessionStatus), Equals, byte(SessionStatusNew)) + assert(meta.Target, Equals, dest) + assert(byte(meta.Option), Equals, byte(OptionData)) data, err := readAll(streamReader) - assert.Error(err).IsNil() - assert.Int(len(data)).Equals(1) - assert.String(data[0].String()).Equals("abcd") + assert(err, IsNil) + assert(len(data), Equals, 1) + assert(data[0].String(), Equals, "abcd") - meta, err = metaReader.Read() - assert.Error(err).IsNil() - assert.Byte(byte(meta.SessionStatus)).Equals(byte(SessionStatusNew)) - assert.Uint16(meta.SessionID).Equals(2) - assert.Byte(byte(meta.Option)).Equals(0) - assert.Destination(meta.Target).Equals(dest2) + meta, err = ReadMetadata(bytesReader) + assert(err, IsNil) + assert(byte(meta.SessionStatus), Equals, byte(SessionStatusNew)) + assert(meta.SessionID, Equals, uint16(2)) + assert(byte(meta.Option), Equals, byte(0)) + assert(meta.Target, Equals, dest2) - meta, err = metaReader.Read() - assert.Error(err).IsNil() - assert.Byte(byte(meta.SessionStatus)).Equals(byte(SessionStatusKeep)) - assert.Uint16(meta.SessionID).Equals(1) - assert.Byte(byte(meta.Option)).Equals(1) + meta, err = ReadMetadata(bytesReader) + assert(err, IsNil) + assert(byte(meta.SessionStatus), Equals, byte(SessionStatusKeep)) + assert(meta.SessionID, Equals, uint16(1)) + assert(byte(meta.Option), Equals, byte(1)) data, err = readAll(streamReader) - assert.Error(err).IsNil() - assert.Int(len(data)).Equals(1) - assert.String(data[0].String()).Equals("efgh") + assert(err, IsNil) + assert(len(data), Equals, 1) + assert(data[0].String(), Equals, "efgh") - meta, err = metaReader.Read() - assert.Error(err).IsNil() - assert.Byte(byte(meta.SessionStatus)).Equals(byte(SessionStatusNew)) - assert.Uint16(meta.SessionID).Equals(3) - assert.Byte(byte(meta.Option)).Equals(1) - assert.Destination(meta.Target).Equals(dest3) + meta, err = ReadMetadata(bytesReader) + assert(err, IsNil) + assert(byte(meta.SessionStatus), Equals, byte(SessionStatusNew)) + assert(meta.SessionID, Equals, uint16(3)) + assert(byte(meta.Option), Equals, byte(1)) + assert(meta.Target, Equals, dest3) data, err = readAll(streamReader) - assert.Error(err).IsNil() - assert.Int(len(data)).Equals(1) - assert.String(data[0].String()).Equals("x") + assert(err, IsNil) + assert(len(data), Equals, 1) + assert(data[0].String(), Equals, "x") - meta, err = metaReader.Read() - assert.Error(err).IsNil() - assert.Byte(byte(meta.SessionStatus)).Equals(byte(SessionStatusEnd)) - assert.Uint16(meta.SessionID).Equals(1) - assert.Byte(byte(meta.Option)).Equals(0) + meta, err = ReadMetadata(bytesReader) + assert(err, IsNil) + assert(byte(meta.SessionStatus), Equals, byte(SessionStatusEnd)) + assert(meta.SessionID, Equals, uint16(1)) + assert(byte(meta.Option), Equals, byte(0)) - meta, err = metaReader.Read() - assert.Error(err).IsNil() - assert.Byte(byte(meta.SessionStatus)).Equals(byte(SessionStatusEnd)) - assert.Uint16(meta.SessionID).Equals(3) - assert.Byte(byte(meta.Option)).Equals(0) + meta, err = ReadMetadata(bytesReader) + assert(err, IsNil) + assert(byte(meta.SessionStatus), Equals, byte(SessionStatusEnd)) + assert(meta.SessionID, Equals, uint16(3)) + assert(byte(meta.Option), Equals, byte(0)) - meta, err = metaReader.Read() - assert.Error(err).IsNil() - assert.Byte(byte(meta.SessionStatus)).Equals(byte(SessionStatusKeep)) - assert.Uint16(meta.SessionID).Equals(2) - assert.Byte(byte(meta.Option)).Equals(1) + meta, err = ReadMetadata(bytesReader) + assert(err, IsNil) + assert(byte(meta.SessionStatus), Equals, byte(SessionStatusKeep)) + assert(meta.SessionID, Equals, uint16(2)) + assert(byte(meta.Option), Equals, byte(1)) data, err = readAll(streamReader) - assert.Error(err).IsNil() - assert.Int(len(data)).Equals(1) - assert.String(data[0].String()).Equals("y") + assert(err, IsNil) + assert(len(data), Equals, 1) + assert(data[0].String(), Equals, "y") - meta, err = metaReader.Read() - assert.Error(err).IsNil() - assert.Byte(byte(meta.SessionStatus)).Equals(byte(SessionStatusEnd)) - assert.Uint16(meta.SessionID).Equals(2) - assert.Byte(byte(meta.Option)).Equals(0) + meta, err = ReadMetadata(bytesReader) + assert(err, IsNil) + assert(byte(meta.SessionStatus), Equals, byte(SessionStatusEnd)) + assert(meta.SessionID, Equals, uint16(2)) + assert(byte(meta.Option), Equals, byte(0)) stream.Close() - meta, err = metaReader.Read() - assert.Error(err).IsNotNil() + meta, err = ReadMetadata(bytesReader) + assert(err, IsNotNil) + assert(meta, IsNil) } diff --git a/app/proxyman/mux/reader.go b/app/proxyman/mux/reader.go index d309f8df8..df13ed2bf 100644 --- a/app/proxyman/mux/reader.go +++ b/app/proxyman/mux/reader.go @@ -7,20 +7,9 @@ import ( "v2ray.com/core/common/serial" ) -type MetadataReader struct { - reader io.Reader - buffer []byte -} - -func NewMetadataReader(reader io.Reader) *MetadataReader { - return &MetadataReader{ - reader: reader, - buffer: make([]byte, 1024), - } -} - -func (r *MetadataReader) Read() (*FrameMetadata, error) { - metaLen, err := serial.ReadUint16(r.reader) +// ReadMetadata reads FrameMetadata from the given reader. +func ReadMetadata(reader io.Reader) (*FrameMetadata, error) { + metaLen, err := serial.ReadUint16(reader) if err != nil { return nil, err } @@ -28,17 +17,22 @@ func (r *MetadataReader) Read() (*FrameMetadata, error) { return nil, newError("invalid metalen ", metaLen).AtWarning() } - if _, err := io.ReadFull(r.reader, r.buffer[:metaLen]); err != nil { + b := buf.New() + defer b.Release() + + if err := b.Reset(buf.ReadFullFrom(reader, int(metaLen))); err != nil { return nil, err } - return ReadFrameFrom(r.buffer) + return ReadFrameFrom(b.Bytes()) } +// PacketReader is an io.Reader that reads whole chunk of Mux frames every time. type PacketReader struct { reader io.Reader eof bool } +// NewPacketReader creates a new PacketReader. func NewPacketReader(reader io.Reader) *PacketReader { return &PacketReader{ reader: reader, @@ -46,7 +40,8 @@ func NewPacketReader(reader io.Reader) *PacketReader { } } -func (r *PacketReader) Read() (buf.MultiBuffer, error) { +// ReadMultiBuffer implements buf.Reader. +func (r *PacketReader) ReadMultiBuffer() (buf.MultiBuffer, error) { if r.eof { return nil, io.EOF } @@ -70,19 +65,22 @@ func (r *PacketReader) Read() (buf.MultiBuffer, error) { return buf.NewMultiBufferValue(b), nil } +// StreamReader reads Mux frame as a stream. type StreamReader struct { - reader io.Reader + reader *buf.BufferedReader leftOver int } -func NewStreamReader(reader io.Reader) *StreamReader { +// NewStreamReader creates a new StreamReader. +func NewStreamReader(reader *buf.BufferedReader) *StreamReader { return &StreamReader{ reader: reader, leftOver: -1, } } -func (r *StreamReader) Read() (buf.MultiBuffer, error) { +// ReadMultiBuffer implmenets buf.Reader. +func (r *StreamReader) ReadMultiBuffer() (buf.MultiBuffer, error) { if r.leftOver == 0 { r.leftOver = -1 return nil, io.EOF @@ -96,24 +94,7 @@ func (r *StreamReader) Read() (buf.MultiBuffer, error) { r.leftOver = int(size) } - mb := buf.NewMultiBuffer() - for r.leftOver > 0 { - readLen := buf.Size - if r.leftOver < readLen { - readLen = r.leftOver - } - b := buf.New() - if err := b.AppendSupplier(func(bb []byte) (int, error) { - return r.reader.Read(bb[:readLen]) - }); err != nil { - mb.Release() - return nil, err - } - r.leftOver -= b.Len() - mb.Append(b) - if b.Len() < readLen { - break - } - } - return mb, nil + mb, err := r.reader.ReadAtMost(r.leftOver) + r.leftOver -= mb.Len() + return mb, err } diff --git a/app/proxyman/mux/session.go b/app/proxyman/mux/session.go index 60816dd11..66e1b7290 100644 --- a/app/proxyman/mux/session.go +++ b/app/proxyman/mux/session.go @@ -1,7 +1,6 @@ package mux import ( - "io" "sync" "v2ray.com/core/common/buf" @@ -19,7 +18,7 @@ type SessionManager struct { func NewSessionManager() *SessionManager { return &SessionManager{ count: 0, - sessions: make(map[uint16]*Session, 32), + sessions: make(map[uint16]*Session, 16), } } @@ -58,6 +57,10 @@ func (m *SessionManager) Add(s *Session) { m.Lock() defer m.Unlock() + if m.closed { + return + } + m.sessions[s.ID] = s } @@ -65,6 +68,10 @@ func (m *SessionManager) Remove(id uint16) { m.Lock() defer m.Unlock() + if m.closed { + return + } + delete(m.sessions, id) } @@ -111,9 +118,10 @@ func (m *SessionManager) Close() { s.output.Close() } - m.sessions = make(map[uint16]*Session) + m.sessions = nil } +// Session represents a client connection in a Mux connection. type Session struct { input ray.InputStream output ray.OutputStream @@ -122,13 +130,15 @@ type Session struct { transferType protocol.TransferType } +// Close closes all resources associated with this session. func (s *Session) Close() { s.output.Close() s.input.Close() s.parent.Remove(s.ID) } -func (s *Session) NewReader(reader io.Reader) buf.Reader { +// NewReader creates a buf.Reader based on the transfer type of this Session. +func (s *Session) NewReader(reader *buf.BufferedReader) buf.Reader { if s.transferType == protocol.TransferTypeStream { return NewStreamReader(reader) } diff --git a/app/proxyman/mux/session_test.go b/app/proxyman/mux/session_test.go index addff874c..4acffd8f0 100644 --- a/app/proxyman/mux/session_test.go +++ b/app/proxyman/mux/session_test.go @@ -4,34 +4,36 @@ import ( "testing" . "v2ray.com/core/app/proxyman/mux" - "v2ray.com/core/testing/assert" + . "v2ray.com/ext/assert" ) func TestSessionManagerAdd(t *testing.T) { - assert := assert.On(t) + assert := With(t) m := NewSessionManager() s := m.Allocate() - assert.Uint16(s.ID).Equals(1) + assert(s.ID, Equals, uint16(1)) + assert(m.Size(), Equals, 1) s = m.Allocate() - assert.Uint16(s.ID).Equals(2) + assert(s.ID, Equals, uint16(2)) + assert(m.Size(), Equals, 2) s = &Session{ ID: 4, } m.Add(s) - assert.Uint16(s.ID).Equals(4) + assert(s.ID, Equals, uint16(4)) } func TestSessionManagerClose(t *testing.T) { - assert := assert.On(t) + assert := With(t) m := NewSessionManager() s := m.Allocate() - assert.Bool(m.CloseIfNoSession()).IsFalse() + assert(m.CloseIfNoSession(), IsFalse) m.Remove(s.ID) - assert.Bool(m.CloseIfNoSession()).IsTrue() + assert(m.CloseIfNoSession(), IsTrue) } diff --git a/app/proxyman/mux/writer.go b/app/proxyman/mux/writer.go index 47c419145..64c290bdf 100644 --- a/app/proxyman/mux/writer.go +++ b/app/proxyman/mux/writer.go @@ -1,8 +1,7 @@ package mux import ( - "runtime" - + "v2ray.com/core/common" "v2ray.com/core/common/buf" "v2ray.com/core/common/net" "v2ray.com/core/common/protocol" @@ -10,9 +9,9 @@ import ( ) type Writer struct { - id uint16 dest net.Destination writer buf.Writer + id uint16 followup bool transferType protocol.TransferType } @@ -54,51 +53,47 @@ func (w *Writer) getNextFrameMeta() FrameMetadata { func (w *Writer) writeMetaOnly() error { meta := w.getNextFrameMeta() b := buf.New() - if err := b.AppendSupplier(meta.AsSupplier()); err != nil { + if err := b.Reset(meta.AsSupplier()); err != nil { return err } - runtime.KeepAlive(meta) - return w.writer.Write(buf.NewMultiBufferValue(b)) + return w.writer.WriteMultiBuffer(buf.NewMultiBufferValue(b)) } func (w *Writer) writeData(mb buf.MultiBuffer) error { meta := w.getNextFrameMeta() - meta.Option.Add(OptionData) + meta.Option.Set(OptionData) frame := buf.New() - if err := frame.AppendSupplier(meta.AsSupplier()); err != nil { + if err := frame.Reset(meta.AsSupplier()); err != nil { return err } - runtime.KeepAlive(meta) if err := frame.AppendSupplier(serial.WriteUint16(uint16(mb.Len()))); err != nil { return err } - mb2 := buf.NewMultiBuffer() + mb2 := buf.NewMultiBufferCap(len(mb) + 1) mb2.Append(frame) mb2.AppendMulti(mb) - return w.writer.Write(mb2) + return w.writer.WriteMultiBuffer(mb2) } -// Write implements buf.MultiBufferWriter. -func (w *Writer) Write(mb buf.MultiBuffer) error { +// WriteMultiBuffer implements buf.Writer. +func (w *Writer) WriteMultiBuffer(mb buf.MultiBuffer) error { + defer mb.Release() + if mb.IsEmpty() { return w.writeMetaOnly() } - if w.transferType == protocol.TransferTypeStream { - const chunkSize = 8 * 1024 - for !mb.IsEmpty() { - slice := mb.SliceBySize(chunkSize) - if err := w.writeData(slice); err != nil { - return err - } + for !mb.IsEmpty() { + var chunk buf.MultiBuffer + if w.transferType == protocol.TransferTypeStream { + chunk = mb.SliceBySize(8 * 1024) + } else { + chunk = buf.NewMultiBufferValue(mb.SplitFirst()) } - } else { - for _, b := range mb { - if err := w.writeData(buf.NewMultiBufferValue(b)); err != nil { - return err - } + if err := w.writeData(chunk); err != nil { + return err } } @@ -112,8 +107,7 @@ func (w *Writer) Close() { } frame := buf.New() - frame.AppendSupplier(meta.AsSupplier()) - runtime.KeepAlive(meta) + common.Must(frame.Reset(meta.AsSupplier())) - w.writer.Write(buf.NewMultiBufferValue(frame)) + w.writer.WriteMultiBuffer(buf.NewMultiBufferValue(frame)) } diff --git a/app/proxyman/outbound/handler.go b/app/proxyman/outbound/handler.go index d9d7d86b7..422f23fb6 100644 --- a/app/proxyman/outbound/handler.go +++ b/app/proxyman/outbound/handler.go @@ -33,7 +33,7 @@ func NewHandler(ctx context.Context, config *proxyman.OutboundHandlerConfig) (*H if space == nil { return nil, newError("no space in context") } - space.OnInitialize(func() error { + space.On(app.SpaceInitializing, func(interface{}) error { ohm := proxyman.OutboundHandlerManagerFromSpace(space) if ohm == nil { return newError("no OutboundManager in space") @@ -78,6 +78,7 @@ func (h *Handler) Dispatch(ctx context.Context, outboundRay ray.OutboundRay) { err := h.mux.Dispatch(ctx, outboundRay) if err != nil { log.Trace(newError("failed to process outbound traffic").Base(err)) + outboundRay.OutboundOutput().CloseError() } } else { err := h.proxy.Process(ctx, outboundRay, h) @@ -122,8 +123,8 @@ func (h *Handler) Dial(ctx context.Context, dest net.Destination) (internet.Conn } var ( - _ buf.MultiBufferReader = (*Connection)(nil) - _ buf.MultiBufferWriter = (*Connection)(nil) + _ buf.Reader = (*Connection)(nil) + _ buf.Writer = (*Connection)(nil) ) type Connection struct { @@ -132,9 +133,8 @@ type Connection struct { localAddr net.Addr remoteAddr net.Addr - bytesReader io.Reader - reader buf.Reader - writer buf.Writer + reader *buf.BufferedReader + writer buf.Writer } func NewConnection(stream ray.Ray) *Connection { @@ -148,9 +148,8 @@ func NewConnection(stream ray.Ray) *Connection { IP: []byte{0, 0, 0, 0}, Port: 0, }, - bytesReader: buf.ToBytesReader(stream.InboundOutput()), - reader: stream.InboundOutput(), - writer: stream.InboundInput(), + reader: buf.NewBufferedReader(stream.InboundOutput()), + writer: stream.InboundInput(), } } @@ -159,11 +158,11 @@ func (v *Connection) Read(b []byte) (int, error) { if v.closed { return 0, io.EOF } - return v.bytesReader.Read(b) + return v.reader.Read(b) } func (v *Connection) ReadMultiBuffer() (buf.MultiBuffer, error) { - return v.reader.Read() + return v.reader.ReadMultiBuffer() } // Write implements net.Conn.Write(). @@ -171,14 +170,19 @@ func (v *Connection) Write(b []byte) (int, error) { if v.closed { return 0, io.ErrClosedPipe } - return buf.ToBytesWriter(v.writer).Write(b) + + l := len(b) + mb := buf.NewMultiBufferCap(l/buf.Size + 1) + mb.Write(b) + return l, v.writer.WriteMultiBuffer(mb) } func (v *Connection) WriteMultiBuffer(mb buf.MultiBuffer) error { if v.closed { return io.ErrClosedPipe } - return v.writer.Write(mb) + + return v.writer.WriteMultiBuffer(mb) } // Close implements net.Conn.Close(). diff --git a/app/router/condition.go b/app/router/condition.go index 0da9ebf7e..40797cfcb 100644 --- a/app/router/condition.go +++ b/app/router/condition.go @@ -4,6 +4,8 @@ import ( "context" "regexp" "strings" + "sync" + "time" "v2ray.com/core/common/net" "v2ray.com/core/common/protocol" @@ -64,13 +66,123 @@ func (v *AnyCondition) Len() int { return len(*v) } -type PlainDomainMatcher string - -func NewPlainDomainMatcher(pattern string) Condition { - return PlainDomainMatcher(pattern) +type timedResult struct { + timestamp time.Time + result bool } -func (v PlainDomainMatcher) Apply(ctx context.Context) bool { +type CachableDomainMatcher struct { + sync.Mutex + matchers []domainMatcher + cache map[string]timedResult + lastScan time.Time +} + +func NewCachableDomainMatcher() *CachableDomainMatcher { + return &CachableDomainMatcher{ + matchers: make([]domainMatcher, 0, 64), + cache: make(map[string]timedResult, 512), + } +} + +func (m *CachableDomainMatcher) Add(domain *Domain) error { + switch domain.Type { + case Domain_Plain: + m.matchers = append(m.matchers, NewPlainDomainMatcher(domain.Value)) + case Domain_Regex: + rm, err := NewRegexpDomainMatcher(domain.Value) + if err != nil { + return err + } + m.matchers = append(m.matchers, rm) + case Domain_Domain: + m.matchers = append(m.matchers, NewSubDomainMatcher(domain.Value)) + default: + return newError("unknown domain type: ", domain.Type).AtError() + } + return nil +} + +func (m *CachableDomainMatcher) applyInternal(domain string) bool { + for _, matcher := range m.matchers { + if matcher.Apply(domain) { + return true + } + } + + return false +} + +type cacheResult int + +const ( + cacheMiss cacheResult = iota + cacheHitTrue + cacheHitFalse +) + +func (m *CachableDomainMatcher) findInCache(domain string) cacheResult { + m.Lock() + defer m.Unlock() + + r, f := m.cache[domain] + if !f { + return cacheMiss + } + r.timestamp = time.Now() + m.cache[domain] = r + + if r.result { + return cacheHitTrue + } + return cacheHitFalse +} + +func (m *CachableDomainMatcher) ApplyDomain(domain string) bool { + if len(m.matchers) < 64 { + return m.applyInternal(domain) + } + + cr := m.findInCache(domain) + + if cr == cacheHitTrue { + return true + } + + if cr == cacheHitFalse { + return false + } + + r := m.applyInternal(domain) + m.Lock() + defer m.Unlock() + + m.cache[domain] = timedResult{ + result: r, + timestamp: time.Now(), + } + + now := time.Now() + if len(m.cache) > 256 && now.Sub(m.lastScan)/time.Second > 5 { + remove := make([]string, 0, 128) + + now := time.Now() + + for k, v := range m.cache { + if now.Sub(v.timestamp)/time.Second > 60 { + remove = append(remove, k) + } + } + for _, v := range remove { + delete(m.cache, v) + } + m.lastScan = now + } + + return r +} + +func (m *CachableDomainMatcher) Apply(ctx context.Context) bool { dest, ok := proxy.TargetFromContext(ctx) if !ok { return false @@ -79,7 +191,20 @@ func (v PlainDomainMatcher) Apply(ctx context.Context) bool { if !dest.Address.Family().IsDomain() { return false } - domain := dest.Address.Domain() + return m.ApplyDomain(dest.Address.Domain()) +} + +type domainMatcher interface { + Apply(domain string) bool +} + +type PlainDomainMatcher string + +func NewPlainDomainMatcher(pattern string) PlainDomainMatcher { + return PlainDomainMatcher(pattern) +} + +func (v PlainDomainMatcher) Apply(domain string) bool { return strings.Contains(domain, string(v)) } @@ -97,33 +222,17 @@ func NewRegexpDomainMatcher(pattern string) (*RegexpDomainMatcher, error) { }, nil } -func (v *RegexpDomainMatcher) Apply(ctx context.Context) bool { - dest, ok := proxy.TargetFromContext(ctx) - if !ok { - return false - } - if !dest.Address.Family().IsDomain() { - return false - } - domain := dest.Address.Domain() +func (v *RegexpDomainMatcher) Apply(domain string) bool { return v.pattern.MatchString(strings.ToLower(domain)) } type SubDomainMatcher string -func NewSubDomainMatcher(p string) Condition { +func NewSubDomainMatcher(p string) SubDomainMatcher { return SubDomainMatcher(p) } -func (m SubDomainMatcher) Apply(ctx context.Context) bool { - dest, ok := proxy.TargetFromContext(ctx) - if !ok { - return false - } - if !dest.Address.Family().IsDomain() { - return false - } - domain := dest.Address.Domain() +func (m SubDomainMatcher) Apply(domain string) bool { pattern := string(m) if !strings.HasSuffix(domain, pattern) { return false @@ -149,8 +258,9 @@ func NewCIDRMatcher(ip []byte, mask uint32, onSource bool) (*CIDRMatcher, error) func (v *CIDRMatcher) Apply(ctx context.Context) bool { ips := make([]net.IP, 0, 4) - if resolveIPs, ok := proxy.ResolvedIPsFromContext(ctx); ok { - for _, rip := range resolveIPs { + if resolver, ok := proxy.ResolvedIPsFromContext(ctx); ok { + resolvedIPs := resolver.Resolve() + for _, rip := range resolvedIPs { if !rip.Family().IsIPv6() { continue } @@ -192,8 +302,9 @@ func NewIPv4Matcher(ipnet *net.IPNetTable, onSource bool) *IPv4Matcher { func (v *IPv4Matcher) Apply(ctx context.Context) bool { ips := make([]net.IP, 0, 4) - if resolveIPs, ok := proxy.ResolvedIPsFromContext(ctx); ok { - for _, rip := range resolveIPs { + if resolver, ok := proxy.ResolvedIPsFromContext(ctx); ok { + resolvedIPs := resolver.Resolve() + for _, rip := range resolvedIPs { if !rip.Family().IsIPv4() { continue } diff --git a/app/router/condition_test.go b/app/router/condition_test.go index 1fec521fe..eaeac8861 100644 --- a/app/router/condition_test.go +++ b/app/router/condition_test.go @@ -2,57 +2,66 @@ package router_test import ( "context" + "os" + "path/filepath" + "strconv" "testing" + "time" + proto "github.com/golang/protobuf/proto" . "v2ray.com/core/app/router" + "v2ray.com/core/common" + "v2ray.com/core/common/errors" "v2ray.com/core/common/net" + "v2ray.com/core/common/platform" "v2ray.com/core/common/protocol" "v2ray.com/core/proxy" - "v2ray.com/core/testing/assert" + . "v2ray.com/ext/assert" + "v2ray.com/ext/sysio" ) func TestSubDomainMatcher(t *testing.T) { - assert := assert.On(t) + assert := With(t) cases := []struct { pattern string - input context.Context + input string output bool }{ { pattern: "v2ray.com", - input: proxy.ContextWithTarget(context.Background(), net.TCPDestination(net.DomainAddress("www.v2ray.com"), 80)), + input: "www.v2ray.com", output: true, }, { pattern: "v2ray.com", - input: proxy.ContextWithTarget(context.Background(), net.TCPDestination(net.DomainAddress("v2ray.com"), 80)), + input: "v2ray.com", output: true, }, { pattern: "v2ray.com", - input: proxy.ContextWithTarget(context.Background(), net.TCPDestination(net.DomainAddress("www.v3ray.com"), 80)), + input: "www.v3ray.com", output: false, }, { pattern: "v2ray.com", - input: proxy.ContextWithTarget(context.Background(), net.TCPDestination(net.DomainAddress("2ray.com"), 80)), + input: "2ray.com", output: false, }, { pattern: "v2ray.com", - input: proxy.ContextWithTarget(context.Background(), net.TCPDestination(net.DomainAddress("xv2ray.com"), 80)), + input: "xv2ray.com", output: false, }, } for _, test := range cases { matcher := NewSubDomainMatcher(test.pattern) - assert.Bool(matcher.Apply(test.input) == test.output).IsTrue() + assert(matcher.Apply(test.input) == test.output, IsTrue) } } func TestRoutingRule(t *testing.T) { - assert := assert.On(t) + assert := With(t) type ruleTest struct { input context.Context @@ -172,10 +181,56 @@ func TestRoutingRule(t *testing.T) { for _, test := range cases { cond, err := test.rule.BuildCondition() - assert.Error(err).IsNil() + assert(err, IsNil) for _, t := range test.test { - assert.Bool(cond.Apply(t.input)).Equals(t.output) + assert(cond.Apply(t.input), Equals, t.output) } } } + +func loadGeoSite(country string) ([]*Domain, error) { + geositeBytes, err := sysio.ReadAsset("geosite.dat") + if err != nil { + return nil, err + } + var geositeList GeoSiteList + if err := proto.Unmarshal(geositeBytes, &geositeList); err != nil { + return nil, err + } + + for _, site := range geositeList.Entry { + if site.CountryCode == country { + return site.Domain, nil + } + } + + return nil, errors.New("country not found: " + country) +} + +func TestChinaSites(t *testing.T) { + assert := With(t) + + common.Must(sysio.CopyFile(platform.GetAssetLocation("geosite.dat"), filepath.Join(os.Getenv("GOPATH"), "src", "v2ray.com", "core", "tools", "release", "config", "geosite.dat"))) + + domains, err := loadGeoSite("CN") + assert(err, IsNil) + + matcher := NewCachableDomainMatcher() + for _, d := range domains { + assert(matcher.Add(d), IsNil) + } + + assert(matcher.ApplyDomain("163.com"), IsTrue) + assert(matcher.ApplyDomain("163.com"), IsTrue) + assert(matcher.ApplyDomain("164.com"), IsFalse) + assert(matcher.ApplyDomain("164.com"), IsFalse) + + for i := 0; i < 1024; i++ { + assert(matcher.ApplyDomain(strconv.Itoa(i)+".not-exists.com"), IsFalse) + } + time.Sleep(time.Second * 10) + for i := 0; i < 1024; i++ { + assert(matcher.ApplyDomain(strconv.Itoa(i)+".not-exists2.com"), IsFalse) + } +} diff --git a/app/router/config.go b/app/router/config.go index 048f602f1..05ff36614 100644 --- a/app/router/config.go +++ b/app/router/config.go @@ -52,24 +52,11 @@ func (rr *RoutingRule) BuildCondition() (Condition, error) { conds := NewConditionChan() if len(rr.Domain) > 0 { - anyCond := NewAnyCondition() + matcher := NewCachableDomainMatcher() for _, domain := range rr.Domain { - switch domain.Type { - case Domain_Plain: - anyCond.Add(NewPlainDomainMatcher(domain.Value)) - case Domain_Regex: - matcher, err := NewRegexpDomainMatcher(domain.Value) - if err != nil { - return nil, err - } - anyCond.Add(matcher) - case Domain_Domain: - anyCond.Add(NewSubDomainMatcher(domain.Value)) - default: - panic("Unknown domain type.") - } + matcher.Add(domain) } - conds.Add(anyCond) + conds.Add(matcher) } if len(rr.Cidr) > 0 { diff --git a/app/router/config.pb.go b/app/router/config.pb.go index 9dcd027cc..d43c5700f 100644 --- a/app/router/config.pb.go +++ b/app/router/config.pb.go @@ -54,23 +54,27 @@ const ( Config_UseIp Config_DomainStrategy = 1 // Resolve to IP if the domain doesn't match any rules. Config_IpIfNonMatch Config_DomainStrategy = 2 + // Resolve to IP if any rule requires IP matching. + Config_IpOnDemand Config_DomainStrategy = 3 ) var Config_DomainStrategy_name = map[int32]string{ 0: "AsIs", 1: "UseIp", 2: "IpIfNonMatch", + 3: "IpOnDemand", } var Config_DomainStrategy_value = map[string]int32{ "AsIs": 0, "UseIp": 1, "IpIfNonMatch": 2, + "IpOnDemand": 3, } func (x Config_DomainStrategy) String() string { return proto.EnumName(Config_DomainStrategy_name, int32(x)) } -func (Config_DomainStrategy) EnumDescriptor() ([]byte, []int) { return fileDescriptor0, []int{3, 0} } +func (Config_DomainStrategy) EnumDescriptor() ([]byte, []int) { return fileDescriptor0, []int{7, 0} } // Domain for routing decision. type Domain struct { @@ -126,6 +130,86 @@ func (m *CIDR) GetPrefix() uint32 { return 0 } +type GeoIP struct { + CountryCode string `protobuf:"bytes,1,opt,name=country_code,json=countryCode" json:"country_code,omitempty"` + Cidr []*CIDR `protobuf:"bytes,2,rep,name=cidr" json:"cidr,omitempty"` +} + +func (m *GeoIP) Reset() { *m = GeoIP{} } +func (m *GeoIP) String() string { return proto.CompactTextString(m) } +func (*GeoIP) ProtoMessage() {} +func (*GeoIP) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{2} } + +func (m *GeoIP) GetCountryCode() string { + if m != nil { + return m.CountryCode + } + return "" +} + +func (m *GeoIP) GetCidr() []*CIDR { + if m != nil { + return m.Cidr + } + return nil +} + +type GeoIPList struct { + Entry []*GeoIP `protobuf:"bytes,1,rep,name=entry" json:"entry,omitempty"` +} + +func (m *GeoIPList) Reset() { *m = GeoIPList{} } +func (m *GeoIPList) String() string { return proto.CompactTextString(m) } +func (*GeoIPList) ProtoMessage() {} +func (*GeoIPList) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{3} } + +func (m *GeoIPList) GetEntry() []*GeoIP { + if m != nil { + return m.Entry + } + return nil +} + +type GeoSite struct { + CountryCode string `protobuf:"bytes,1,opt,name=country_code,json=countryCode" json:"country_code,omitempty"` + Domain []*Domain `protobuf:"bytes,2,rep,name=domain" json:"domain,omitempty"` +} + +func (m *GeoSite) Reset() { *m = GeoSite{} } +func (m *GeoSite) String() string { return proto.CompactTextString(m) } +func (*GeoSite) ProtoMessage() {} +func (*GeoSite) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{4} } + +func (m *GeoSite) GetCountryCode() string { + if m != nil { + return m.CountryCode + } + return "" +} + +func (m *GeoSite) GetDomain() []*Domain { + if m != nil { + return m.Domain + } + return nil +} + +type GeoSiteList struct { + Entry []*GeoSite `protobuf:"bytes,1,rep,name=entry" json:"entry,omitempty"` +} + +func (m *GeoSiteList) Reset() { *m = GeoSiteList{} } +func (m *GeoSiteList) String() string { return proto.CompactTextString(m) } +func (*GeoSiteList) ProtoMessage() {} +func (*GeoSiteList) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{5} } + +func (m *GeoSiteList) GetEntry() []*GeoSite { + if m != nil { + return m.Entry + } + return nil +} + type RoutingRule struct { Tag string `protobuf:"bytes,1,opt,name=tag" json:"tag,omitempty"` Domain []*Domain `protobuf:"bytes,2,rep,name=domain" json:"domain,omitempty"` @@ -140,7 +224,7 @@ type RoutingRule struct { func (m *RoutingRule) Reset() { *m = RoutingRule{} } func (m *RoutingRule) String() string { return proto.CompactTextString(m) } func (*RoutingRule) ProtoMessage() {} -func (*RoutingRule) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{2} } +func (*RoutingRule) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{6} } func (m *RoutingRule) GetTag() string { if m != nil { @@ -206,7 +290,7 @@ type Config struct { func (m *Config) Reset() { *m = Config{} } func (m *Config) String() string { return proto.CompactTextString(m) } func (*Config) ProtoMessage() {} -func (*Config) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{3} } +func (*Config) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{7} } func (m *Config) GetDomainStrategy() Config_DomainStrategy { if m != nil { @@ -225,6 +309,10 @@ func (m *Config) GetRule() []*RoutingRule { func init() { proto.RegisterType((*Domain)(nil), "v2ray.core.app.router.Domain") proto.RegisterType((*CIDR)(nil), "v2ray.core.app.router.CIDR") + proto.RegisterType((*GeoIP)(nil), "v2ray.core.app.router.GeoIP") + proto.RegisterType((*GeoIPList)(nil), "v2ray.core.app.router.GeoIPList") + proto.RegisterType((*GeoSite)(nil), "v2ray.core.app.router.GeoSite") + proto.RegisterType((*GeoSiteList)(nil), "v2ray.core.app.router.GeoSiteList") proto.RegisterType((*RoutingRule)(nil), "v2ray.core.app.router.RoutingRule") proto.RegisterType((*Config)(nil), "v2ray.core.app.router.Config") proto.RegisterEnum("v2ray.core.app.router.Domain_Type", Domain_Type_name, Domain_Type_value) @@ -234,39 +322,45 @@ func init() { func init() { proto.RegisterFile("v2ray.com/core/app/router/config.proto", fileDescriptor0) } var fileDescriptor0 = []byte{ - // 538 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x84, 0x93, 0xc1, 0x6e, 0xd4, 0x30, - 0x10, 0x86, 0x49, 0x76, 0x1b, 0xba, 0x93, 0xb2, 0x44, 0x16, 0x45, 0xa1, 0xa8, 0x22, 0x8a, 0x10, - 0xe4, 0x80, 0x12, 0x69, 0x11, 0x70, 0x01, 0xa1, 0xb2, 0xed, 0x61, 0x25, 0xa8, 0x2a, 0xd3, 0x72, - 0xe0, 0x12, 0xb9, 0x59, 0x37, 0x58, 0x24, 0xb6, 0xe5, 0x38, 0xa5, 0x7b, 0xe3, 0x05, 0x78, 0x11, - 0x9e, 0x86, 0x47, 0x42, 0xb6, 0x53, 0xd1, 0xa2, 0x2e, 0xdc, 0x66, 0x9c, 0xef, 0x9f, 0x19, 0x8f, - 0xff, 0xc0, 0x93, 0xf3, 0x99, 0x22, 0xab, 0xbc, 0x12, 0x6d, 0x51, 0x09, 0x45, 0x0b, 0x22, 0x65, - 0xa1, 0x44, 0xaf, 0xa9, 0x2a, 0x2a, 0xc1, 0xcf, 0x58, 0x9d, 0x4b, 0x25, 0xb4, 0x40, 0xdb, 0x97, - 0x9c, 0xa2, 0x39, 0x91, 0x32, 0x77, 0xcc, 0xce, 0xe3, 0xbf, 0xe4, 0x95, 0x68, 0x5b, 0xc1, 0x0b, - 0x4e, 0x75, 0x21, 0x85, 0xd2, 0x4e, 0xbc, 0xf3, 0x74, 0x3d, 0xc5, 0xa9, 0xfe, 0x26, 0xd4, 0x57, - 0x07, 0xa6, 0xdf, 0x3d, 0x08, 0xf6, 0x45, 0x4b, 0x18, 0x47, 0x2f, 0x61, 0xac, 0x57, 0x92, 0xc6, - 0x5e, 0xe2, 0x65, 0xd3, 0x59, 0x9a, 0xdf, 0xd8, 0x3f, 0x77, 0x70, 0x7e, 0xbc, 0x92, 0x14, 0x5b, - 0x1e, 0xdd, 0x83, 0x8d, 0x73, 0xd2, 0xf4, 0x34, 0xf6, 0x13, 0x2f, 0x9b, 0x60, 0x97, 0xa4, 0x19, - 0x8c, 0x0d, 0x83, 0x26, 0xb0, 0x71, 0xd4, 0x10, 0xc6, 0xa3, 0x5b, 0x26, 0xc4, 0xb4, 0xa6, 0x17, - 0x91, 0x87, 0xe0, 0xb2, 0x6b, 0xe4, 0xa7, 0x39, 0x8c, 0xe7, 0x8b, 0x7d, 0x8c, 0xa6, 0xe0, 0x33, - 0x69, 0xbb, 0x6f, 0x61, 0x9f, 0x49, 0x74, 0x1f, 0x02, 0xa9, 0xe8, 0x19, 0xbb, 0xb0, 0x85, 0xef, - 0xe0, 0x21, 0x4b, 0x7f, 0x8c, 0x20, 0xc4, 0xa2, 0xd7, 0x8c, 0xd7, 0xb8, 0x6f, 0x28, 0x8a, 0x60, - 0xa4, 0x49, 0x6d, 0x85, 0x13, 0x6c, 0x42, 0xf4, 0x02, 0x82, 0xa5, 0xad, 0x1e, 0xfb, 0xc9, 0x28, - 0x0b, 0x67, 0xbb, 0xff, 0xbc, 0x0b, 0x1e, 0x60, 0x54, 0xc0, 0xb8, 0x62, 0x4b, 0x15, 0x8f, 0xac, - 0xe8, 0xe1, 0x1a, 0x91, 0x99, 0x15, 0x5b, 0x10, 0xbd, 0x05, 0x30, 0x3b, 0x2f, 0x15, 0xe1, 0x35, - 0x8d, 0xc7, 0x89, 0x97, 0x85, 0xb3, 0xe4, 0xaa, 0xcc, 0xad, 0x3d, 0xe7, 0x54, 0xe7, 0x47, 0x42, - 0x69, 0x6c, 0x38, 0x3c, 0x91, 0x97, 0x21, 0x3a, 0x80, 0xad, 0xe1, 0x39, 0xca, 0x86, 0x75, 0x3a, - 0xde, 0xb0, 0x25, 0xd2, 0x35, 0x25, 0x0e, 0x1d, 0xfa, 0x9e, 0x75, 0x1a, 0x87, 0xfc, 0x4f, 0x82, - 0x5e, 0x43, 0xd8, 0x89, 0x5e, 0x55, 0xb4, 0xb4, 0xf3, 0x07, 0xff, 0x9f, 0x1f, 0x1c, 0x3f, 0x37, - 0xb7, 0xd8, 0x05, 0xe8, 0x3b, 0xaa, 0x4a, 0xda, 0x12, 0xd6, 0xc4, 0xb7, 0x93, 0x51, 0x36, 0xc1, - 0x13, 0x73, 0x72, 0x60, 0x0e, 0xd0, 0x23, 0x08, 0x19, 0x3f, 0x15, 0x3d, 0x5f, 0x96, 0x66, 0xcd, - 0x9b, 0xf6, 0x3b, 0x0c, 0x47, 0xc7, 0xa4, 0x4e, 0x7f, 0x79, 0x10, 0xcc, 0xad, 0x73, 0xd1, 0x09, - 0xdc, 0x75, 0xbb, 0x2c, 0x3b, 0xad, 0x88, 0xa6, 0xf5, 0x6a, 0x70, 0xd3, 0xb3, 0x75, 0xc3, 0x38, - 0xc7, 0xbb, 0x87, 0xf8, 0x38, 0x68, 0xf0, 0x74, 0x79, 0x2d, 0x37, 0xce, 0x54, 0x7d, 0x43, 0x87, - 0xd7, 0x5c, 0xe7, 0xcc, 0x2b, 0x9e, 0xc0, 0x96, 0x4f, 0x5f, 0xc1, 0xf4, 0x7a, 0x65, 0xb4, 0x09, - 0xe3, 0xbd, 0x6e, 0xd1, 0x39, 0x33, 0x9e, 0x74, 0x74, 0x21, 0x23, 0x0f, 0x45, 0xb0, 0xb5, 0x90, - 0x8b, 0xb3, 0x43, 0xc1, 0x3f, 0x10, 0x5d, 0x7d, 0x89, 0xfc, 0x77, 0x6f, 0xe0, 0x41, 0x25, 0xda, - 0x9b, 0xfb, 0x1c, 0x79, 0x9f, 0x03, 0x17, 0xfd, 0xf4, 0xb7, 0x3f, 0xcd, 0x30, 0x59, 0xe5, 0x73, - 0x43, 0xec, 0x49, 0x69, 0x47, 0xa0, 0xea, 0x34, 0xb0, 0xff, 0xd6, 0xf3, 0xdf, 0x01, 0x00, 0x00, - 0xff, 0xff, 0xa7, 0x6a, 0x97, 0x93, 0xeb, 0x03, 0x00, 0x00, + // 640 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x9c, 0x94, 0xcd, 0x6e, 0xd4, 0x3a, + 0x14, 0xc7, 0x6f, 0xe6, 0xab, 0x9d, 0x93, 0xb9, 0x73, 0x23, 0xeb, 0x16, 0x0d, 0x85, 0xc2, 0x10, + 0x21, 0x98, 0x05, 0x4a, 0xa4, 0xe1, 0x63, 0x05, 0xaa, 0xca, 0xb4, 0xaa, 0x22, 0x41, 0x19, 0xb9, + 0x2d, 0x0b, 0x58, 0x44, 0x6e, 0xe2, 0x86, 0x88, 0x89, 0x6d, 0x39, 0x4e, 0xe9, 0xec, 0x78, 0x01, + 0x5e, 0x84, 0xa7, 0xe2, 0x51, 0x90, 0xed, 0x0c, 0xb4, 0xa8, 0x81, 0x8a, 0x9d, 0xed, 0xfc, 0xfe, + 0xe7, 0xfc, 0x73, 0x7c, 0x8e, 0xe1, 0xc1, 0xd9, 0x54, 0x92, 0x65, 0x90, 0xf0, 0x22, 0x4c, 0xb8, + 0xa4, 0x21, 0x11, 0x22, 0x94, 0xbc, 0x52, 0x54, 0x86, 0x09, 0x67, 0xa7, 0x79, 0x16, 0x08, 0xc9, + 0x15, 0x47, 0x1b, 0x2b, 0x4e, 0xd2, 0x80, 0x08, 0x11, 0x58, 0x66, 0xf3, 0xfe, 0x2f, 0xf2, 0x84, + 0x17, 0x05, 0x67, 0x21, 0xa3, 0x2a, 0x14, 0x5c, 0x2a, 0x2b, 0xde, 0x7c, 0xd8, 0x4c, 0x31, 0xaa, + 0x3e, 0x71, 0xf9, 0xd1, 0x82, 0xfe, 0x67, 0x07, 0x7a, 0xbb, 0xbc, 0x20, 0x39, 0x43, 0xcf, 0xa0, + 0xa3, 0x96, 0x82, 0x8e, 0x9c, 0xb1, 0x33, 0x19, 0x4e, 0xfd, 0xe0, 0xca, 0xfc, 0x81, 0x85, 0x83, + 0xa3, 0xa5, 0xa0, 0xd8, 0xf0, 0xe8, 0x7f, 0xe8, 0x9e, 0x91, 0x45, 0x45, 0x47, 0xad, 0xb1, 0x33, + 0xe9, 0x63, 0xbb, 0xf1, 0x27, 0xd0, 0xd1, 0x0c, 0xea, 0x43, 0x77, 0xbe, 0x20, 0x39, 0xf3, 0xfe, + 0xd1, 0x4b, 0x4c, 0x33, 0x7a, 0xee, 0x39, 0x08, 0x56, 0x59, 0xbd, 0x96, 0x1f, 0x40, 0x67, 0x16, + 0xed, 0x62, 0x34, 0x84, 0x56, 0x2e, 0x4c, 0xf6, 0x01, 0x6e, 0xe5, 0x02, 0xdd, 0x80, 0x9e, 0x90, + 0xf4, 0x34, 0x3f, 0x37, 0x81, 0xff, 0xc5, 0xf5, 0xce, 0x7f, 0x0f, 0xdd, 0x7d, 0xca, 0xa3, 0x39, + 0xba, 0x07, 0x83, 0x84, 0x57, 0x4c, 0xc9, 0x65, 0x9c, 0xf0, 0xd4, 0x1a, 0xef, 0x63, 0xb7, 0x3e, + 0x9b, 0xf1, 0x94, 0xa2, 0x10, 0x3a, 0x49, 0x9e, 0xca, 0x51, 0x6b, 0xdc, 0x9e, 0xb8, 0xd3, 0x5b, + 0x0d, 0xff, 0xa4, 0xd3, 0x63, 0x03, 0xfa, 0xdb, 0xd0, 0x37, 0xc1, 0x5f, 0xe5, 0xa5, 0x42, 0x53, + 0xe8, 0x52, 0x1d, 0x6a, 0xe4, 0x18, 0xf9, 0xed, 0x06, 0xb9, 0x11, 0x60, 0x8b, 0xfa, 0x09, 0xac, + 0xed, 0x53, 0x7e, 0x98, 0x2b, 0x7a, 0x1d, 0x7f, 0x4f, 0xa1, 0x97, 0x9a, 0x3a, 0xd4, 0x0e, 0xb7, + 0x7e, 0x5b, 0x75, 0x5c, 0xc3, 0xfe, 0x0c, 0xdc, 0x3a, 0x89, 0xf1, 0xf9, 0xe4, 0xb2, 0xcf, 0x3b, + 0xcd, 0x3e, 0xb5, 0x64, 0xe5, 0xf4, 0x4b, 0x1b, 0x5c, 0xcc, 0x2b, 0x95, 0xb3, 0x0c, 0x57, 0x0b, + 0x8a, 0x3c, 0x68, 0x2b, 0x92, 0xd5, 0x2e, 0xf5, 0xf2, 0x2f, 0xdd, 0xfd, 0x28, 0x7a, 0xfb, 0x9a, + 0x45, 0x47, 0xdb, 0x00, 0xba, 0x77, 0x63, 0x49, 0x58, 0x46, 0x47, 0x9d, 0xb1, 0x33, 0x71, 0xa7, + 0xe3, 0x8b, 0x32, 0xdb, 0xbe, 0x01, 0xa3, 0x2a, 0x98, 0x73, 0xa9, 0xb0, 0xe6, 0x70, 0x5f, 0xac, + 0x96, 0x68, 0x0f, 0x06, 0x75, 0x5b, 0xc7, 0x8b, 0xbc, 0x54, 0xa3, 0xae, 0x09, 0xe1, 0x37, 0x84, + 0x38, 0xb0, 0xa8, 0x2e, 0x1d, 0x76, 0xd9, 0xcf, 0x0d, 0x7a, 0x0e, 0x6e, 0xc9, 0x2b, 0x99, 0xd0, + 0xd8, 0xf8, 0xef, 0xfd, 0xd9, 0x3f, 0x58, 0x7e, 0xa6, 0xff, 0x62, 0x0b, 0xa0, 0x2a, 0xa9, 0x8c, + 0x69, 0x41, 0xf2, 0xc5, 0x68, 0x6d, 0xdc, 0x9e, 0xf4, 0x71, 0x5f, 0x9f, 0xec, 0xe9, 0x03, 0x74, + 0x17, 0xdc, 0x9c, 0x9d, 0xf0, 0x8a, 0xa5, 0xb1, 0x2e, 0xf3, 0xba, 0xf9, 0x0e, 0xf5, 0xd1, 0x11, + 0xc9, 0xfc, 0x6f, 0x0e, 0xf4, 0x66, 0xe6, 0x05, 0x40, 0xc7, 0xf0, 0x9f, 0xad, 0x65, 0x5c, 0x2a, + 0x49, 0x14, 0xcd, 0x96, 0xf5, 0x54, 0x3e, 0x6a, 0x32, 0x63, 0x5f, 0x0e, 0x7b, 0x11, 0x87, 0xb5, + 0x06, 0x0f, 0xd3, 0x4b, 0x7b, 0x3d, 0xe1, 0xb2, 0x5a, 0xd0, 0xfa, 0x36, 0x9b, 0x26, 0xfc, 0x42, + 0x4f, 0x60, 0xc3, 0xfb, 0xfb, 0x30, 0xbc, 0x1c, 0x19, 0xad, 0x43, 0x67, 0xa7, 0x8c, 0x4a, 0x3b, + 0xd4, 0xc7, 0x25, 0x8d, 0x84, 0xe7, 0x20, 0x0f, 0x06, 0x91, 0x88, 0x4e, 0x0f, 0x38, 0x7b, 0x4d, + 0x54, 0xf2, 0xc1, 0x6b, 0xa1, 0x21, 0x40, 0x24, 0xde, 0xb0, 0x5d, 0x5a, 0x10, 0x96, 0x7a, 0xed, + 0x97, 0x2f, 0xe0, 0x66, 0xc2, 0x8b, 0xab, 0xf3, 0xce, 0x9d, 0x77, 0x3d, 0xbb, 0xfa, 0xda, 0xda, + 0x78, 0x3b, 0xc5, 0x64, 0x19, 0xcc, 0x34, 0xb1, 0x23, 0x84, 0xb1, 0x44, 0xe5, 0x49, 0xcf, 0xbc, + 0x59, 0x8f, 0xbf, 0x07, 0x00, 0x00, 0xff, 0xff, 0x53, 0x7c, 0xa8, 0x94, 0x43, 0x05, 0x00, 0x00, } diff --git a/app/router/config.proto b/app/router/config.proto index 410cd9c30..a33bf668d 100644 --- a/app/router/config.proto +++ b/app/router/config.proto @@ -37,6 +37,24 @@ message CIDR { uint32 prefix = 2; } +message GeoIP { + string country_code = 1; + repeated CIDR cidr = 2; +} + +message GeoIPList { + repeated GeoIP entry = 1; +} + +message GeoSite { + string country_code = 1; + repeated Domain domain = 2; +} + +message GeoSiteList{ + repeated GeoSite entry = 1; +} + message RoutingRule { string tag = 1; repeated Domain domain = 2; @@ -58,6 +76,9 @@ message Config { // Resolve to IP if the domain doesn't match any rules. IpIfNonMatch = 2; + + // Resolve to IP if any rule requires IP matching. + IpOnDemand = 3; } DomainStrategy domain_strategy = 1; repeated RoutingRule rule = 2; diff --git a/app/router/router.go b/app/router/router.go index 15837e97a..33d6aa912 100644 --- a/app/router/router.go +++ b/app/router/router.go @@ -33,7 +33,7 @@ func NewRouter(ctx context.Context, config *Config) (*Router, error) { rules: make([]Rule, len(config.Rule)), } - space.OnInitialize(func() error { + space.On(app.SpaceInitializing, func(interface{}) error { for idx, rule := range config.Rule { r.rules[idx].Tag = rule.Tag cond, err := rule.BuildCondition() @@ -52,19 +52,42 @@ func NewRouter(ctx context.Context, config *Config) (*Router, error) { return r, nil } -func (r *Router) resolveIP(dest net.Destination) []net.Address { - ips := r.dnsServer.Get(dest.Address.Domain()) +type ipResolver struct { + ip []net.Address + domain string + resolved bool + dnsServer dns.Server +} + +func (r *ipResolver) Resolve() []net.Address { + if r.resolved { + return r.ip + } + + log.Trace(newError("looking for IP for domain: ", r.domain)) + r.resolved = true + ips := r.dnsServer.Get(r.domain) if len(ips) == 0 { return nil } - dests := make([]net.Address, len(ips)) - for idx, ip := range ips { - dests[idx] = net.IPAddress(ip) + r.ip = make([]net.Address, len(ips)) + for i, ip := range ips { + r.ip[i] = net.IPAddress(ip) } - return dests + return r.ip } func (r *Router) TakeDetour(ctx context.Context) (string, error) { + resolver := &ipResolver{ + dnsServer: r.dnsServer, + } + if r.domainStrategy == Config_IpOnDemand { + if dest, ok := proxy.TargetFromContext(ctx); ok && dest.Address.Family().IsDomain() { + resolver.domain = dest.Address.Domain() + ctx = proxy.ContextWithResolveIPs(ctx, resolver) + } + } + for _, rule := range r.rules { if rule.Apply(ctx) { return rule.Tag, nil @@ -77,10 +100,10 @@ func (r *Router) TakeDetour(ctx context.Context) (string, error) { } if r.domainStrategy == Config_IpIfNonMatch && dest.Address.Family().IsDomain() { - log.Trace(newError("looking up IP for ", dest)) - ipDests := r.resolveIP(dest) - if ipDests != nil { - ctx = proxy.ContextWithResolveIPs(ctx, ipDests) + resolver.domain = dest.Address.Domain() + ips := resolver.Resolve() + if len(ips) > 0 { + ctx = proxy.ContextWithResolveIPs(ctx, resolver) for _, rule := range r.rules { if rule.Apply(ctx) { return rule.Tag, nil diff --git a/app/router/router_test.go b/app/router/router_test.go index e3db5cd0e..12350fb94 100644 --- a/app/router/router_test.go +++ b/app/router/router_test.go @@ -14,11 +14,11 @@ import ( . "v2ray.com/core/app/router" "v2ray.com/core/common/net" "v2ray.com/core/proxy" - "v2ray.com/core/testing/assert" + . "v2ray.com/ext/assert" ) func TestSimpleRouter(t *testing.T) { - assert := assert.On(t) + assert := With(t) config := &Config{ Rule: []*RoutingRule{ @@ -33,16 +33,16 @@ func TestSimpleRouter(t *testing.T) { space := app.NewSpace() ctx := app.ContextWithSpace(context.Background(), space) - assert.Error(app.AddApplicationToSpace(ctx, new(dns.Config))).IsNil() - assert.Error(app.AddApplicationToSpace(ctx, new(dispatcher.Config))).IsNil() - assert.Error(app.AddApplicationToSpace(ctx, new(proxyman.OutboundConfig))).IsNil() - assert.Error(app.AddApplicationToSpace(ctx, config)).IsNil() - assert.Error(space.Initialize()).IsNil() + assert(app.AddApplicationToSpace(ctx, new(dns.Config)), IsNil) + assert(app.AddApplicationToSpace(ctx, new(dispatcher.Config)), IsNil) + assert(app.AddApplicationToSpace(ctx, new(proxyman.OutboundConfig)), IsNil) + assert(app.AddApplicationToSpace(ctx, config), IsNil) + assert(space.Initialize(), IsNil) r := FromSpace(space) ctx = proxy.ContextWithTarget(ctx, net.TCPDestination(net.DomainAddress("v2ray.com"), 80)) tag, err := r.TakeDetour(ctx) - assert.Error(err).IsNil() - assert.String(tag).Equals("test") + assert(err, IsNil) + assert(tag, Equals, "test") } diff --git a/app/space.go b/app/space.go index 09629b697..f30775ce2 100644 --- a/app/space.go +++ b/app/space.go @@ -5,6 +5,7 @@ import ( "reflect" "v2ray.com/core/common" + "v2ray.com/core/common/event" ) type Application interface { @@ -13,8 +14,6 @@ type Application interface { Close() } -type InitializationCallback func() error - func CreateAppFromConfig(ctx context.Context, config interface{}) (Application, error) { application, err := common.CreateObject(ctx, config) if err != nil { @@ -29,46 +28,47 @@ func CreateAppFromConfig(ctx context.Context, config interface{}) (Application, } // A Space contains all apps that may be available in a V2Ray runtime. -// Caller must check the availability of an app by calling HasXXX before getting its instance. type Space interface { + event.Registry GetApplication(appInterface interface{}) Application AddApplication(application Application) error Initialize() error - OnInitialize(InitializationCallback) Start() error Close() } +const ( + // SpaceInitializing is an event to be fired when Space is being initialized. + SpaceInitializing event.Event = iota +) + type spaceImpl struct { - initialized bool + event.Listener cache map[reflect.Type]Application - appInit []InitializationCallback + initialized bool } +// NewSpace creates a new Space. func NewSpace() Space { return &spaceImpl{ - cache: make(map[reflect.Type]Application), - appInit: make([]InitializationCallback, 0, 32), + cache: make(map[reflect.Type]Application), } } -func (s *spaceImpl) OnInitialize(f InitializationCallback) { - if s.initialized { - f() - } else { - s.appInit = append(s.appInit, f) +func (s *spaceImpl) On(e event.Event, h event.Handler) { + if e == SpaceInitializing && s.initialized { + _ = h(nil) // Ignore error + return } + s.Listener.On(e, h) } func (s *spaceImpl) Initialize() error { - for _, f := range s.appInit { - if err := f(); err != nil { - return err - } + if s.initialized { + return nil } - s.appInit = nil s.initialized = true - return nil + return s.Fire(SpaceInitializing, nil) } func (s *spaceImpl) GetApplication(appInterface interface{}) Application { diff --git a/app/vpndialer/config.pb.go b/app/vpndialer/config.pb.go deleted file mode 100644 index f2cc5e9ec..000000000 --- a/app/vpndialer/config.pb.go +++ /dev/null @@ -1,52 +0,0 @@ -package vpndialer - -import proto "github.com/golang/protobuf/proto" -import fmt "fmt" -import math "math" - -// Reference imports to suppress errors if they are not otherwise used. -var _ = proto.Marshal -var _ = fmt.Errorf -var _ = math.Inf - -// This is a compile-time assertion to ensure that this generated file -// is compatible with the proto package it is being compiled against. -// A compilation error at this line likely means your copy of the -// proto package needs to be updated. -const _ = proto.ProtoPackageIsVersion2 // please upgrade the proto package - -type Config struct { - Address string `protobuf:"bytes,1,opt,name=address" json:"address,omitempty"` -} - -func (m *Config) Reset() { *m = Config{} } -func (m *Config) String() string { return proto.CompactTextString(m) } -func (*Config) ProtoMessage() {} -func (*Config) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{0} } - -func (m *Config) GetAddress() string { - if m != nil { - return m.Address - } - return "" -} - -func init() { - proto.RegisterType((*Config)(nil), "v2ray.core.app.vpndialer.Config") -} - -func init() { proto.RegisterFile("v2ray.com/core/app/vpndialer/config.proto", fileDescriptor0) } - -var fileDescriptor0 = []byte{ - // 150 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0xd2, 0x2c, 0x33, 0x2a, 0x4a, - 0xac, 0xd4, 0x4b, 0xce, 0xcf, 0xd5, 0x4f, 0xce, 0x2f, 0x4a, 0xd5, 0x4f, 0x2c, 0x28, 0xd0, 0x2f, - 0x2b, 0xc8, 0x4b, 0xc9, 0x4c, 0xcc, 0x49, 0x2d, 0xd2, 0x4f, 0xce, 0xcf, 0x4b, 0xcb, 0x4c, 0xd7, - 0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x17, 0x92, 0x80, 0x29, 0x2d, 0x4a, 0xd5, 0x4b, 0x2c, 0x28, 0xd0, - 0x83, 0x2b, 0x53, 0x52, 0xe2, 0x62, 0x73, 0x06, 0xab, 0x14, 0x92, 0xe0, 0x62, 0x4f, 0x4c, 0x49, - 0x29, 0x4a, 0x2d, 0x2e, 0x96, 0x60, 0x54, 0x60, 0xd4, 0xe0, 0x0c, 0x82, 0x71, 0x9d, 0xdc, 0xb8, - 0x64, 0x92, 0xf3, 0x73, 0xf5, 0x70, 0x99, 0x11, 0xc0, 0x18, 0xc5, 0x09, 0xe7, 0xac, 0x62, 0x92, - 0x08, 0x33, 0x0a, 0x4a, 0xac, 0xd4, 0x73, 0x06, 0xa9, 0x73, 0x2c, 0x28, 0xd0, 0x0b, 0x2b, 0xc8, - 0x73, 0x01, 0x4b, 0x25, 0xb1, 0x81, 0x1d, 0x63, 0x0c, 0x08, 0x00, 0x00, 0xff, 0xff, 0x97, 0xfc, - 0x09, 0x70, 0xb9, 0x00, 0x00, 0x00, -} diff --git a/app/vpndialer/config.proto b/app/vpndialer/config.proto deleted file mode 100644 index b5b801fbc..000000000 --- a/app/vpndialer/config.proto +++ /dev/null @@ -1,11 +0,0 @@ -syntax = "proto3"; - -package v2ray.core.app.vpndialer; -option csharp_namespace = "V2Ray.Core.App.VpnDialer"; -option go_package = "vpndialer"; -option java_package = "com.v2ray.core.app.vpndialer"; -option java_multiple_files = true; - -message Config { - string address = 1; -} diff --git a/app/vpndialer/unix/errors.generated.go b/app/vpndialer/unix/errors.generated.go deleted file mode 100644 index d58739017..000000000 --- a/app/vpndialer/unix/errors.generated.go +++ /dev/null @@ -1,7 +0,0 @@ -package unix - -import "v2ray.com/core/common/errors" - -func newError(values ...interface{}) *errors.Error { - return errors.New(values...).Path("App", "VPNDialer", "Unix") -} diff --git a/app/vpndialer/unix/unix.go b/app/vpndialer/unix/unix.go deleted file mode 100644 index 47e9906f8..000000000 --- a/app/vpndialer/unix/unix.go +++ /dev/null @@ -1,217 +0,0 @@ -package unix - -import ( - "context" - "os" - "sync" - - "golang.org/x/sys/unix" - "v2ray.com/core/app/vpndialer" - "v2ray.com/core/common" - "v2ray.com/core/common/net" - "v2ray.com/core/common/serial" - "v2ray.com/core/transport/internet" -) - -//go:generate go run $GOPATH/src/v2ray.com/core/tools/generrorgen/main.go -pkg unix -path App,VPNDialer,Unix - -type status int - -const ( - statusNew status = iota - statusOK - statusFail -) - -type fdStatus struct { - status status - fd int - callback chan<- error -} - -type protector struct { - sync.Mutex - address string - conn *net.UnixConn - status chan fdStatus -} - -func readFrom(conn *net.UnixConn, schan chan<- fdStatus) { - var payload [6]byte - for { - _, err := conn.Read(payload[:]) - if err != nil { - break - } - fd := serial.BytesToInt(payload[1:5]) - s := status(payload[5]) - schan <- fdStatus{ - fd: fd, - status: s, - } - } -} - -func (m *protector) dial() (*net.UnixConn, error) { - m.Lock() - defer m.Unlock() - - if m.conn != nil { - return m.conn, nil - } - - conn, err := net.DialUnix("unix", nil, &net.UnixAddr{ - Name: m.address, - Net: "unix", - }) - if err != nil { - return nil, err - } - m.conn = conn - m.status = make(chan fdStatus, 32) - go readFrom(conn, m.status) - go m.monitor(conn) - return conn, nil -} - -func (m *protector) close() { - m.Lock() - defer m.Unlock() - if m.conn == nil { - return - } - m.conn.Close() - m.conn = nil -} - -func (m *protector) monitor(c *net.UnixConn) { - pendingFd := make(map[int]chan<- error, 32) - for s := range m.status { - switch s.status { - case statusNew: - pendingFd[s.fd] = s.callback - case statusOK: - if c, f := pendingFd[s.fd]; f { - close(c) - delete(pendingFd, s.fd) - } - case statusFail: - if c, f := pendingFd[s.fd]; f { - c <- newError("failed to protect fd") - close(c) - delete(pendingFd, s.fd) - } - } - } -} - -func (m *protector) protect(fd int) error { - conn, err := m.dial() - if err != nil { - return err - } - - var payload [6]byte - serial.IntToBytes(fd, payload[1:1]) - payload[5] = byte(statusNew) - if _, err := conn.Write(payload[:]); err != nil { - return err - } - - wait := make(chan error) - m.status <- fdStatus{ - status: statusNew, - fd: fd, - callback: wait, - } - return <-wait -} - -type App struct { - protector *protector - dialer *Dialer -} - -func NewApp(ctx context.Context, config *vpndialer.Config) (*App, error) { - a := &App{ - dialer: &Dialer{}, - protector: &protector{ - address: config.Address, - }, - } - a.dialer.protect = a.protector.protect - return a, nil -} - -func (*App) Interface() interface{} { - return (*App)(nil) -} - -func (a *App) Start() error { - internet.UseAlternativeSystemDialer(a.dialer) - return nil -} - -func (a *App) Close() { - internet.UseAlternativeSystemDialer(nil) -} - -type Dialer struct { - protect func(fd int) error -} - -func socket(dest net.Destination) (int, error) { - switch dest.Network { - case net.Network_TCP: - return unix.Socket(unix.AF_INET6, unix.SOCK_STREAM, unix.IPPROTO_TCP) - case net.Network_UDP: - return unix.Socket(unix.AF_INET6, unix.SOCK_DGRAM, unix.IPPROTO_UDP) - default: - return 0, newError("unknown network ", dest.Network) - } -} - -func getIP(addr net.Address) (net.IP, error) { - if addr.Family().Either(net.AddressFamilyIPv4, net.AddressFamilyIPv6) { - return addr.IP(), nil - } - ips, err := net.LookupIP(addr.Domain()) - if err != nil { - return nil, err - } - return ips[0], nil -} - -func (d *Dialer) Dial(ctx context.Context, source net.Address, dest net.Destination) (net.Conn, error) { - fd, err := socket(dest) - if err != nil { - return nil, err - } - if err := d.protect(fd); err != nil { - return nil, err - } - - ip, err := getIP(dest.Address) - if err != nil { - return nil, err - } - - addr := &unix.SockaddrInet6{ - Port: int(dest.Port), - ZoneId: 0, - } - copy(addr.Addr[:], ip.To16()) - - if err := unix.Connect(fd, addr); err != nil { - return nil, err - } - - file := os.NewFile(uintptr(fd), "Socket") - return net.FileConn(file) -} - -func init() { - common.Must(common.RegisterConfig((*vpndialer.Config)(nil), func(ctx context.Context, config interface{}) (interface{}, error) { - return NewApp(ctx, config.(*vpndialer.Config)) - })) -} diff --git a/app/vpndialer/vpndialer.go b/app/vpndialer/vpndialer.go deleted file mode 100644 index a4a3ea927..000000000 --- a/app/vpndialer/vpndialer.go +++ /dev/null @@ -1 +0,0 @@ -package vpndialer diff --git a/common/bitmask/byte.go b/common/bitmask/byte.go new file mode 100644 index 000000000..8dcc5c0c8 --- /dev/null +++ b/common/bitmask/byte.go @@ -0,0 +1,21 @@ +package bitmask + +// Byte is a bitmask in byte. +type Byte byte + +// Has returns true if this bitmask contains another bitmask. +func (b Byte) Has(bb Byte) bool { + return (b & bb) != 0 +} + +func (b *Byte) Set(bb Byte) { + *b |= bb +} + +func (b *Byte) Clear(bb Byte) { + *b &= ^bb +} + +func (b *Byte) Toggle(bb Byte) { + *b ^= bb +} diff --git a/common/bitmask/byte_test.go b/common/bitmask/byte_test.go new file mode 100644 index 000000000..2ca2a7e32 --- /dev/null +++ b/common/bitmask/byte_test.go @@ -0,0 +1,27 @@ +package bitmask_test + +import ( + "testing" + + . "v2ray.com/core/common/bitmask" + . "v2ray.com/ext/assert" +) + +func TestBitmaskByte(t *testing.T) { + assert := With(t) + + b := Byte(0) + b.Set(Byte(1)) + assert(b.Has(1), IsTrue) + + b.Set(Byte(2)) + assert(b.Has(2), IsTrue) + assert(b.Has(1), IsTrue) + + b.Clear(Byte(1)) + assert(b.Has(2), IsTrue) + assert(b.Has(1), IsFalse) + + b.Toggle(Byte(2)) + assert(b.Has(2), IsFalse) +} diff --git a/common/buf/buffer_pool.go b/common/buf/buffer_pool.go index be94ad46e..d66047305 100644 --- a/common/buf/buffer_pool.go +++ b/common/buf/buffer_pool.go @@ -1,10 +1,7 @@ package buf import ( - "runtime" "sync" - - "v2ray.com/core/common/platform" ) // Pool provides functionality to generate and recycle buffers on demand. @@ -45,79 +42,11 @@ func (p *SyncPool) Free(buffer *Buffer) { } } -// BufferPool is a Pool that utilizes an internal cache. -type BufferPool struct { - chain chan []byte - sub Pool -} - -// NewBufferPool creates a new BufferPool with given buffer size, and internal cache size. -func NewBufferPool(bufferSize, poolSize uint32) *BufferPool { - pool := &BufferPool{ - chain: make(chan []byte, poolSize), - sub: NewSyncPool(bufferSize), - } - for i := uint32(0); i < poolSize; i++ { - pool.chain <- make([]byte, bufferSize) - } - return pool -} - -// Allocate implements Pool.Allocate(). -func (p *BufferPool) Allocate() *Buffer { - select { - case b := <-p.chain: - return &Buffer{ - v: b, - pool: p, - } - default: - return p.sub.Allocate() - } -} - -// Free implements Pool.Free(). -func (p *BufferPool) Free(buffer *Buffer) { - if buffer.v == nil { - return - } - select { - case p.chain <- buffer.v: - default: - p.sub.Free(buffer) - } -} - const ( // Size of a regular buffer. Size = 2 * 1024 - - poolSizeEnvKey = "v2ray.buffer.size" ) var ( - mediumPool Pool + mediumPool Pool = NewSyncPool(Size) ) - -func getDefaultPoolSize() int { - switch runtime.GOARCH { - case "amd64", "386": - return 20 - default: - return 5 - } -} - -func init() { - f := platform.EnvFlag{ - Name: poolSizeEnvKey, - AltName: platform.NormalizeEnvName(poolSizeEnvKey), - } - size := f.GetValueAsInt(getDefaultPoolSize()) - if size > 0 { - totalByteSize := uint32(size) * 1024 * 1024 - mediumPool = NewBufferPool(Size, totalByteSize/Size) - } else { - mediumPool = NewSyncPool(Size) - } -} diff --git a/common/buf/buffer_test.go b/common/buf/buffer_test.go index 6c0d2a50f..af05057ec 100644 --- a/common/buf/buffer_test.go +++ b/common/buf/buffer_test.go @@ -6,64 +6,64 @@ import ( . "v2ray.com/core/common/buf" "v2ray.com/core/common/serial" - "v2ray.com/core/testing/assert" + . "v2ray.com/ext/assert" ) func TestBufferClear(t *testing.T) { - assert := assert.On(t) + assert := With(t) buffer := New() defer buffer.Release() payload := "Bytes" buffer.Append([]byte(payload)) - assert.Int(buffer.Len()).Equals(len(payload)) + assert(buffer.Len(), Equals, len(payload)) buffer.Clear() - assert.Int(buffer.Len()).Equals(0) + assert(buffer.Len(), Equals, 0) } func TestBufferIsEmpty(t *testing.T) { - assert := assert.On(t) + assert := With(t) buffer := New() defer buffer.Release() - assert.Bool(buffer.IsEmpty()).IsTrue() + assert(buffer.IsEmpty(), IsTrue) } func TestBufferString(t *testing.T) { - assert := assert.On(t) + assert := With(t) buffer := New() defer buffer.Release() - assert.Error(buffer.AppendSupplier(serial.WriteString("Test String"))).IsNil() - assert.String(buffer.String()).Equals("Test String") + assert(buffer.AppendSupplier(serial.WriteString("Test String")), IsNil) + assert(buffer.String(), Equals, "Test String") } func TestBufferWrite(t *testing.T) { - assert := assert.On(t) + assert := With(t) buffer := NewLocal(8) nBytes, err := buffer.Write([]byte("abcd")) - assert.Error(err).IsNil() - assert.Int(nBytes).Equals(4) + assert(err, IsNil) + assert(nBytes, Equals, 4) nBytes, err = buffer.Write([]byte("abcde")) - assert.Error(err).IsNil() - assert.Int(nBytes).Equals(4) - assert.String(buffer.String()).Equals("abcdabcd") + assert(err, IsNil) + assert(nBytes, Equals, 4) + assert(buffer.String(), Equals, "abcdabcd") } func TestSyncPool(t *testing.T) { - assert := assert.On(t) + assert := With(t) p := NewSyncPool(32) b := p.Allocate() - assert.Int(b.Len()).Equals(0) + assert(b.Len(), Equals, 0) - assert.Error(b.AppendSupplier(ReadFrom(rand.Reader))).IsNil() - assert.Int(b.Len()).Equals(32) + assert(b.AppendSupplier(ReadFrom(rand.Reader)), IsNil) + assert(b.Len(), Equals, 32) b.Release() } diff --git a/common/buf/buffered_reader.go b/common/buf/buffered_reader.go deleted file mode 100644 index 8c7630ec8..000000000 --- a/common/buf/buffered_reader.go +++ /dev/null @@ -1,53 +0,0 @@ -package buf - -import ( - "io" -) - -// BufferedReader is a reader with internal cache. -type BufferedReader struct { - reader io.Reader - buffer *Buffer - buffered bool -} - -// NewBufferedReader creates a new BufferedReader based on an io.Reader. -func NewBufferedReader(rawReader io.Reader) *BufferedReader { - return &BufferedReader{ - reader: rawReader, - buffer: NewLocal(1024), - buffered: true, - } -} - -// IsBuffered returns true if the internal cache is effective. -func (v *BufferedReader) IsBuffered() bool { - return v.buffered -} - -// SetBuffered is to enable or disable internal cache. If cache is disabled, -// Read() calls will be delegated to the underlying io.Reader directly. -func (v *BufferedReader) SetBuffered(cached bool) { - v.buffered = cached -} - -// Read implements io.Reader.Read(). -func (v *BufferedReader) Read(b []byte) (int, error) { - if !v.buffered || v.buffer == nil { - if !v.buffer.IsEmpty() { - return v.buffer.Read(b) - } - return v.reader.Read(b) - } - if v.buffer.IsEmpty() { - if err := v.buffer.Reset(ReadFrom(v.reader)); err != nil { - return 0, err - } - } - - if v.buffer.IsEmpty() { - return 0, nil - } - - return v.buffer.Read(b) -} diff --git a/common/buf/buffered_reader_test.go b/common/buf/buffered_reader_test.go deleted file mode 100644 index 1c0731535..000000000 --- a/common/buf/buffered_reader_test.go +++ /dev/null @@ -1,36 +0,0 @@ -package buf_test - -import ( - "crypto/rand" - "testing" - - . "v2ray.com/core/common/buf" - "v2ray.com/core/testing/assert" -) - -func TestBufferedReader(t *testing.T) { - assert := assert.On(t) - - content := New() - assert.Error(content.AppendSupplier(ReadFrom(rand.Reader))).IsNil() - - len := content.Len() - - reader := NewBufferedReader(content) - assert.Bool(reader.IsBuffered()).IsTrue() - - payload := make([]byte, 16) - - nBytes, err := reader.Read(payload) - assert.Int(nBytes).Equals(16) - assert.Error(err).IsNil() - - len2 := content.Len() - assert.Int(len - len2).GreaterThan(16) - - nBytes, err = reader.Read(payload) - assert.Int(nBytes).Equals(16) - assert.Error(err).IsNil() - - assert.Int(content.Len()).Equals(len2) -} diff --git a/common/buf/buffered_writer.go b/common/buf/buffered_writer.go deleted file mode 100644 index 2ab504dbf..000000000 --- a/common/buf/buffered_writer.go +++ /dev/null @@ -1,72 +0,0 @@ -package buf - -import "io" - -// BufferedWriter is an io.Writer with internal buffer. It writes to underlying writer when buffer is full or on demand. -// This type is not thread safe. -type BufferedWriter struct { - writer io.Writer - buffer *Buffer - buffered bool -} - -// NewBufferedWriter creates a new BufferedWriter. -func NewBufferedWriter(writer io.Writer) *BufferedWriter { - return NewBufferedWriterSize(writer, 1024) -} - -func NewBufferedWriterSize(writer io.Writer, size uint32) *BufferedWriter { - return &BufferedWriter{ - writer: writer, - buffer: NewLocal(int(size)), - buffered: true, - } -} - -// Write implements io.Writer. -func (w *BufferedWriter) Write(b []byte) (int, error) { - if !w.buffered || w.buffer == nil { - return w.writer.Write(b) - } - bytesWritten := 0 - for bytesWritten < len(b) { - nBytes, err := w.buffer.Write(b[bytesWritten:]) - if err != nil { - return bytesWritten, err - } - bytesWritten += nBytes - if w.buffer.IsFull() { - if err := w.Flush(); err != nil { - return bytesWritten, err - } - } - } - return bytesWritten, nil -} - -// Flush writes all buffered content into underlying writer, if any. -func (w *BufferedWriter) Flush() error { - defer w.buffer.Clear() - for !w.buffer.IsEmpty() { - nBytes, err := w.writer.Write(w.buffer.Bytes()) - if err != nil { - return err - } - w.buffer.SliceFrom(nBytes) - } - return nil -} - -// IsBuffered returns true if this BufferedWriter holds a buffer. -func (w *BufferedWriter) IsBuffered() bool { - return w.buffered -} - -// SetBuffered controls whether the BufferedWriter holds a buffer for writing. If not buffered, any write() calls into underlying writer directly. -func (w *BufferedWriter) SetBuffered(cached bool) error { - w.buffered = cached - if !cached && !w.buffer.IsEmpty() { - return w.Flush() - } - return nil -} diff --git a/common/buf/buffered_writer_test.go b/common/buf/buffered_writer_test.go deleted file mode 100644 index c2254dd54..000000000 --- a/common/buf/buffered_writer_test.go +++ /dev/null @@ -1,53 +0,0 @@ -package buf_test - -import ( - "crypto/rand" - "testing" - - . "v2ray.com/core/common/buf" - "v2ray.com/core/testing/assert" -) - -func TestBufferedWriter(t *testing.T) { - assert := assert.On(t) - - content := New() - - writer := NewBufferedWriter(content) - assert.Bool(writer.IsBuffered()).IsTrue() - - payload := make([]byte, 16) - - nBytes, err := writer.Write(payload) - assert.Int(nBytes).Equals(16) - assert.Error(err).IsNil() - - assert.Bool(content.IsEmpty()).IsTrue() - - assert.Error(writer.SetBuffered(false)).IsNil() - assert.Int(content.Len()).Equals(16) -} - -func TestBufferedWriterLargePayload(t *testing.T) { - assert := assert.On(t) - - content := NewLocal(128 * 1024) - - writer := NewBufferedWriter(content) - assert.Bool(writer.IsBuffered()).IsTrue() - - payload := make([]byte, 64*1024) - rand.Read(payload) - - nBytes, err := writer.Write(payload[:512]) - assert.Int(nBytes).Equals(512) - assert.Error(err).IsNil() - - assert.Bool(content.IsEmpty()).IsTrue() - - nBytes, err = writer.Write(payload[512:]) - assert.Error(err).IsNil() - assert.Error(writer.Flush()).IsNil() - assert.Int(nBytes).Equals(64*1024 - 512) - assert.Bytes(content.Bytes()).Equals(payload) -} diff --git a/common/buf/copy.go b/common/buf/copy.go index 873e187aa..d4f65235d 100644 --- a/common/buf/copy.go +++ b/common/buf/copy.go @@ -17,7 +17,7 @@ type copyHandler struct { } func (h *copyHandler) readFrom(reader Reader) (MultiBuffer, error) { - mb, err := reader.Read() + mb, err := reader.ReadMultiBuffer() if err != nil { for _, handler := range h.onReadError { err = handler(err) @@ -27,7 +27,7 @@ func (h *copyHandler) readFrom(reader Reader) (MultiBuffer, error) { } func (h *copyHandler) writeTo(writer Writer, mb MultiBuffer) error { - err := writer.Write(mb) + err := writer.WriteMultiBuffer(mb) if err != nil { for _, handler := range h.onWriteError { err = handler(err) @@ -36,8 +36,14 @@ func (h *copyHandler) writeTo(writer Writer, mb MultiBuffer) error { return err } +type SizeCounter struct { + Size int64 +} + +// CopyOption is an option for copying data. type CopyOption func(*copyHandler) +// IgnoreReaderError is a CopyOption that ignores errors from reader. Copy will continue in such case. func IgnoreReaderError() CopyOption { return func(handler *copyHandler) { handler.onReadError = append(handler.onReadError, func(err error) error { @@ -46,6 +52,7 @@ func IgnoreReaderError() CopyOption { } } +// IgnoreWriterError is a CopyOption that ignores errors from writer. Copy will continue in such case. func IgnoreWriterError() CopyOption { return func(handler *copyHandler) { handler.onWriteError = append(handler.onWriteError, func(err error) error { @@ -54,6 +61,7 @@ func IgnoreWriterError() CopyOption { } } +// UpdateActivity is a CopyOption to update activity on each data copy operation. func UpdateActivity(timer signal.ActivityUpdater) CopyOption { return func(handler *copyHandler) { handler.onData = append(handler.onData, func(MultiBuffer) { @@ -62,31 +70,34 @@ func UpdateActivity(timer signal.ActivityUpdater) CopyOption { } } +// CountSize is a CopyOption that sums the total size of data copied into the given SizeCounter. +func CountSize(sc *SizeCounter) CopyOption { + return func(handler *copyHandler) { + handler.onData = append(handler.onData, func(b MultiBuffer) { + sc.Size += int64(b.Len()) + }) + } +} + func copyInternal(reader Reader, writer Writer, handler *copyHandler) error { for { buffer, err := handler.readFrom(reader) - if err != nil { - return err - } + if !buffer.IsEmpty() { + for _, handler := range handler.onData { + handler(buffer) + } - if buffer.IsEmpty() { - buffer.Release() - continue - } - - for _, handler := range handler.onData { - handler(buffer) - } - - if err := handler.writeTo(writer, buffer); err != nil { - buffer.Release() + if werr := handler.writeTo(writer, buffer); werr != nil { + buffer.Release() + return werr + } + } else if err != nil { return err } } } -// Copy dumps all payload from reader to writer or stops when an error occurs. -// ActivityTimer gets updated as soon as there is a payload. +// Copy dumps all payload from reader to writer or stops when an error occurs. It returns nil when EOF. func Copy(reader Reader, writer Writer, options ...CopyOption) error { handler := new(copyHandler) for _, option := range options { diff --git a/common/buf/io.go b/common/buf/io.go index 0fe9e4f9e..17debb2b5 100644 --- a/common/buf/io.go +++ b/common/buf/io.go @@ -5,22 +5,24 @@ import ( "time" ) -// Reader extends io.Reader with alloc.Buffer. +// Reader extends io.Reader with MultiBuffer. type Reader interface { - // Read reads content from underlying reader, and put it into an alloc.Buffer. - Read() (MultiBuffer, error) + // ReadMultiBuffer reads content from underlying reader, and put it into a MultiBuffer. + ReadMultiBuffer() (MultiBuffer, error) } +// ErrReadTimeout is an error that happens with IO timeout. var ErrReadTimeout = newError("IO timeout") +// TimeoutReader is a reader that returns error if Read() operation takes longer than the given timeout. type TimeoutReader interface { ReadTimeout(time.Duration) (MultiBuffer, error) } -// Writer extends io.Writer with alloc.Buffer. +// Writer extends io.Writer with MultiBuffer. type Writer interface { - // Write writes an alloc.Buffer into underlying writer. - Write(MultiBuffer) error + // WriteMultiBuffer writes a MultiBuffer into underlying writer. + WriteMultiBuffer(MultiBuffer) error } // ReadFrom creates a Supplier to read from a given io.Reader. @@ -47,57 +49,21 @@ func ReadAtLeastFrom(reader io.Reader, size int) Supplier { // NewReader creates a new Reader. // The Reader instance doesn't take the ownership of reader. func NewReader(reader io.Reader) Reader { - if mr, ok := reader.(MultiBufferReader); ok { - return &readerAdpater{ - MultiBufferReader: mr, - } + if mr, ok := reader.(Reader); ok { + return mr } - return &BytesToBufferReader{ - reader: reader, - buffer: make([]byte, 32*1024), - } -} - -func NewMergingReader(reader io.Reader) Reader { - return NewMergingReaderSize(reader, 32*1024) -} - -func NewMergingReaderSize(reader io.Reader, size uint32) Reader { - return &BytesToBufferReader{ - reader: reader, - buffer: make([]byte, size), - } -} - -// ToBytesReader converts a Reaaer to io.Reader. -func ToBytesReader(stream Reader) io.Reader { - return &bufferToBytesReader{ - stream: stream, - } + return NewBytesToBufferReader(reader) } // NewWriter creates a new Writer. func NewWriter(writer io.Writer) Writer { - if mw, ok := writer.(MultiBufferWriter); ok { - return &writerAdapter{ - writer: mw, - } + if mw, ok := writer.(Writer); ok { + return mw } return &BufferToBytesWriter{ - writer: writer, - } -} - -func NewMergingWriter(writer io.Writer) Writer { - return NewMergingWriterSize(writer, 4096) -} - -func NewMergingWriterSize(writer io.Writer, size uint32) Writer { - return &mergingWriter{ - writer: writer, - buffer: make([]byte, size), + Writer: writer, } } @@ -106,10 +72,3 @@ func NewSequentialWriter(writer io.Writer) Writer { writer: writer, } } - -// ToBytesWriter converts a Writer to io.Writer -func ToBytesWriter(writer Writer) io.Writer { - return &bytesToBufferWriter{ - writer: writer, - } -} diff --git a/common/buf/multi_buffer.go b/common/buf/multi_buffer.go index 82f1f030c..2c8e95858 100644 --- a/common/buf/multi_buffer.go +++ b/common/buf/multi_buffer.go @@ -1,21 +1,53 @@ package buf -import "net" +import ( + "io" + "net" -type MultiBufferWriter interface { - WriteMultiBuffer(MultiBuffer) error + "v2ray.com/core/common" + "v2ray.com/core/common/errors" +) + +// ReadAllToMultiBuffer reads all content from the reader into a MultiBuffer, until EOF. +func ReadAllToMultiBuffer(reader io.Reader) (MultiBuffer, error) { + mb := NewMultiBufferCap(128) + + for { + b := New() + err := b.Reset(ReadFrom(reader)) + if b.IsEmpty() { + b.Release() + } else { + mb.Append(b) + } + if err != nil { + if errors.Cause(err) == io.EOF { + return mb, nil + } + mb.Release() + return nil, err + } + } } -type MultiBufferReader interface { - ReadMultiBuffer() (MultiBuffer, error) +// ReadAllToBytes reads all content from the reader into a byte array, until EOF. +func ReadAllToBytes(reader io.Reader) ([]byte, error) { + mb, err := ReadAllToMultiBuffer(reader) + if err != nil { + return nil, err + } + b := make([]byte, mb.Len()) + common.Must2(mb.Read(b)) + mb.Release() + return b, nil } // MultiBuffer is a list of Buffers. The order of Buffer matters. type MultiBuffer []*Buffer -// NewMultiBuffer creates a new MultiBuffer instance. -func NewMultiBuffer() MultiBuffer { - return MultiBuffer(make([]*Buffer, 0, 128)) +// NewMultiBufferCap creates a new MultiBuffer instance. +func NewMultiBufferCap(capacity int) MultiBuffer { + return MultiBuffer(make([]*Buffer, 0, capacity)) } // NewMultiBufferValue wraps a list of Buffers into MultiBuffer. @@ -23,14 +55,17 @@ func NewMultiBufferValue(b ...*Buffer) MultiBuffer { return MultiBuffer(b) } +// Append appends buffer to the end of this MultiBuffer func (mb *MultiBuffer) Append(buf *Buffer) { *mb = append(*mb, buf) } +// AppendMulti appends a MultiBuffer to the end of this one. func (mb *MultiBuffer) AppendMulti(buf MultiBuffer) { *mb = append(*mb, buf...) } +// Copy copied the begining part of the MultiBuffer into the given byte array. func (mb MultiBuffer) Copy(b []byte) int { total := 0 for _, bb := range mb { @@ -43,6 +78,7 @@ func (mb MultiBuffer) Copy(b []byte) int { return total } +// Read implements io.Reader. func (mb *MultiBuffer) Read(b []byte) (int, error) { endIndex := len(*mb) totalBytes := 0 @@ -52,6 +88,7 @@ func (mb *MultiBuffer) Read(b []byte) (int, error) { b = b[nBytes:] if bb.IsEmpty() { bb.Release() + (*mb)[i] = nil } else { endIndex = i break @@ -61,6 +98,7 @@ func (mb *MultiBuffer) Read(b []byte) (int, error) { return totalBytes, nil } +// Write implements io.Writer. func (mb *MultiBuffer) Write(b []byte) { n := len(*mb) if n > 0 && !(*mb)[n-1].IsFull() { @@ -96,11 +134,12 @@ func (mb MultiBuffer) IsEmpty() bool { } // Release releases all Buffers in the MultiBuffer. -func (mb MultiBuffer) Release() { - for i, b := range mb { +func (mb *MultiBuffer) Release() { + for i, b := range *mb { b.Release() - mb[i] = nil + (*mb)[i] = nil } + *mb = nil } // ToNetBuffers converts this MultiBuffer to net.Buffers. The return net.Buffers points to the same content of the MultiBuffer. @@ -112,8 +151,9 @@ func (mb MultiBuffer) ToNetBuffers() net.Buffers { return bs } +// SliceBySize splits the begining of this MultiBuffer into another one, for at most size bytes. func (mb *MultiBuffer) SliceBySize(size int) MultiBuffer { - slice := NewMultiBuffer() + slice := NewMultiBufferCap(10) sliceSize := 0 endIndex := len(*mb) for i, b := range *mb { @@ -123,16 +163,24 @@ func (mb *MultiBuffer) SliceBySize(size int) MultiBuffer { } sliceSize += b.Len() slice.Append(b) + (*mb)[i] = nil } *mb = (*mb)[endIndex:] + if endIndex == 0 && len(*mb) > 0 { + b := New() + common.Must(b.Reset(ReadFullFrom((*mb)[0], size))) + return NewMultiBufferValue(b) + } return slice } +// SplitFirst splits out the first Buffer in this MultiBuffer. func (mb *MultiBuffer) SplitFirst() *Buffer { if len(*mb) == 0 { return nil } b := (*mb)[0] + (*mb)[0] = nil *mb = (*mb)[1:] return b } diff --git a/common/buf/multi_buffer_test.go b/common/buf/multi_buffer_test.go index bf7059d44..92df32f02 100644 --- a/common/buf/multi_buffer_test.go +++ b/common/buf/multi_buffer_test.go @@ -4,11 +4,11 @@ import ( "testing" . "v2ray.com/core/common/buf" - "v2ray.com/core/testing/assert" + . "v2ray.com/ext/assert" ) func TestMultiBufferRead(t *testing.T) { - assert := assert.On(t) + assert := With(t) b1 := New() b1.AppendBytes('a', 'b') @@ -19,17 +19,17 @@ func TestMultiBufferRead(t *testing.T) { bs := make([]byte, 32) nBytes, err := mb.Read(bs) - assert.Error(err).IsNil() - assert.Int(nBytes).Equals(4) - assert.Bytes(bs[:nBytes]).Equals([]byte("abcd")) + assert(err, IsNil) + assert(nBytes, Equals, 4) + assert(bs[:nBytes], Equals, []byte("abcd")) } func TestMultiBufferAppend(t *testing.T) { - assert := assert.On(t) + assert := With(t) var mb MultiBuffer b := New() b.AppendBytes('a', 'b') mb.Append(b) - assert.Int(mb.Len()).Equals(2) + assert(mb.Len(), Equals, 2) } diff --git a/common/buf/reader.go b/common/buf/reader.go index fce13c9ba..f7b425e85 100644 --- a/common/buf/reader.go +++ b/common/buf/reader.go @@ -6,38 +6,86 @@ import ( "v2ray.com/core/common/errors" ) +var ( + _ Reader = (*BytesToBufferReader)(nil) + _ io.Reader = (*BytesToBufferReader)(nil) +) + // BytesToBufferReader is a Reader that adjusts its reading speed automatically. type BytesToBufferReader struct { - reader io.Reader + io.Reader buffer []byte } -// Read implements Reader.Read(). -func (r *BytesToBufferReader) Read() (MultiBuffer, error) { - nBytes, err := r.reader.Read(r.buffer) - if err != nil { - return nil, err +func NewBytesToBufferReader(reader io.Reader) Reader { + return &BytesToBufferReader{ + Reader: reader, + } +} + +func (r *BytesToBufferReader) readSmall() (MultiBuffer, error) { + b := New() + err := b.Reset(ReadFrom(r.Reader)) + if b.IsFull() { + r.buffer = make([]byte, 32*1024) + } + if !b.IsEmpty() { + return NewMultiBufferValue(b), nil + } + b.Release() + return nil, err +} + +// ReadMultiBuffer implements Reader. +func (r *BytesToBufferReader) ReadMultiBuffer() (MultiBuffer, error) { + if r.buffer == nil { + return r.readSmall() } - mb := NewMultiBuffer() - mb.Write(r.buffer[:nBytes]) - return mb, nil + nBytes, err := r.Reader.Read(r.buffer) + if nBytes > 0 { + mb := NewMultiBufferCap(nBytes/Size + 1) + mb.Write(r.buffer[:nBytes]) + return mb, nil + } + return nil, err } -type readerAdpater struct { - MultiBufferReader -} +var ( + _ Reader = (*BufferedReader)(nil) + _ io.Reader = (*BufferedReader)(nil) + _ io.ByteReader = (*BufferedReader)(nil) + _ io.WriterTo = (*BufferedReader)(nil) +) -func (r *readerAdpater) Read() (MultiBuffer, error) { - return r.ReadMultiBuffer() -} - -type bufferToBytesReader struct { +type BufferedReader struct { stream Reader leftOver MultiBuffer + buffered bool } -func (r *bufferToBytesReader) Read(b []byte) (int, error) { +func NewBufferedReader(reader Reader) *BufferedReader { + return &BufferedReader{ + stream: reader, + buffered: true, + } +} + +func (r *BufferedReader) SetBuffered(f bool) { + r.buffered = f +} + +func (r *BufferedReader) IsBuffered() bool { + return r.buffered +} + +func (r *BufferedReader) ReadByte() (byte, error) { + var b [1]byte + _, err := r.Read(b[:]) + return b[0], err +} + +func (r *BufferedReader) Read(b []byte) (int, error) { if r.leftOver != nil { nBytes, _ := r.leftOver.Read(b) if r.leftOver.IsEmpty() { @@ -47,51 +95,75 @@ func (r *bufferToBytesReader) Read(b []byte) (int, error) { return nBytes, nil } - mb, err := r.stream.Read() - if err != nil { - return 0, err + if !r.buffered { + if reader, ok := r.stream.(io.Reader); ok { + return reader.Read(b) + } } - nBytes, _ := mb.Read(b) - if !mb.IsEmpty() { - r.leftOver = mb + mb, err := r.stream.ReadMultiBuffer() + if mb != nil { + nBytes, _ := mb.Read(b) + if !mb.IsEmpty() { + r.leftOver = mb + } + return nBytes, err } - return nBytes, nil + return 0, err } -func (r *bufferToBytesReader) ReadMultiBuffer() (MultiBuffer, error) { +func (r *BufferedReader) ReadMultiBuffer() (MultiBuffer, error) { if r.leftOver != nil { mb := r.leftOver r.leftOver = nil return mb, nil } - return r.stream.Read() + return r.stream.ReadMultiBuffer() } -func (r *bufferToBytesReader) writeToInternal(writer io.Writer) (int64, error) { +// ReadAtMost returns a MultiBuffer with at most size. +func (r *BufferedReader) ReadAtMost(size int) (MultiBuffer, error) { + if r.leftOver == nil { + mb, err := r.stream.ReadMultiBuffer() + if mb.IsEmpty() && err != nil { + return nil, err + } + r.leftOver = mb + } + + mb := r.leftOver.SliceBySize(size) + if r.leftOver.IsEmpty() { + r.leftOver = nil + } + return mb, nil +} + +func (r *BufferedReader) writeToInternal(writer io.Writer) (int64, error) { mbWriter := NewWriter(writer) totalBytes := int64(0) if r.leftOver != nil { - if err := mbWriter.Write(r.leftOver); err != nil { + totalBytes += int64(r.leftOver.Len()) + if err := mbWriter.WriteMultiBuffer(r.leftOver); err != nil { return 0, err } - totalBytes += int64(r.leftOver.Len()) } for { - mb, err := r.stream.Read() - if err != nil { - return totalBytes, err + mb, err := r.stream.ReadMultiBuffer() + if mb != nil { + totalBytes += int64(mb.Len()) + if werr := mbWriter.WriteMultiBuffer(mb); werr != nil { + return totalBytes, err + } } - totalBytes += int64(mb.Len()) - if err := mbWriter.Write(mb); err != nil { + if err != nil { return totalBytes, err } } } -func (r *bufferToBytesReader) WriteTo(writer io.Writer) (int64, error) { +func (r *BufferedReader) WriteTo(writer io.Writer) (int64, error) { nBytes, err := r.writeToInternal(writer) if errors.Cause(err) == io.EOF { return nBytes, nil diff --git a/common/buf/reader_test.go b/common/buf/reader_test.go index cb1e6567f..35c144323 100644 --- a/common/buf/reader_test.go +++ b/common/buf/reader_test.go @@ -7,64 +7,66 @@ import ( "testing" . "v2ray.com/core/common/buf" - "v2ray.com/core/testing/assert" "v2ray.com/core/transport/ray" + . "v2ray.com/ext/assert" ) func TestAdaptiveReader(t *testing.T) { - assert := assert.On(t) + assert := With(t) - rawContent := make([]byte, 1024*1024) - buffer := bytes.NewBuffer(rawContent) + reader := NewReader(bytes.NewReader(make([]byte, 1024*1024))) + b, err := reader.ReadMultiBuffer() + assert(err, IsNil) + assert(b.Len(), Equals, 2*1024) - reader := NewReader(buffer) - b, err := reader.Read() - assert.Error(err).IsNil() - assert.Int(b.Len()).Equals(32 * 1024) + b, err = reader.ReadMultiBuffer() + assert(err, IsNil) + assert(b.Len(), Equals, 32*1024) } func TestBytesReaderWriteTo(t *testing.T) { - assert := assert.On(t) + assert := With(t) stream := ray.NewStream(context.Background()) - reader := ToBytesReader(stream) + reader := NewBufferedReader(stream) b1 := New() b1.AppendBytes('a', 'b', 'c') b2 := New() b2.AppendBytes('e', 'f', 'g') - assert.Error(stream.Write(NewMultiBufferValue(b1, b2))).IsNil() + assert(stream.WriteMultiBuffer(NewMultiBufferValue(b1, b2)), IsNil) stream.Close() stream2 := ray.NewStream(context.Background()) - writer := ToBytesWriter(stream2) + writer := NewBufferedWriter(stream2) + writer.SetBuffered(false) nBytes, err := io.Copy(writer, reader) - assert.Error(err).IsNil() - assert.Int64(nBytes).Equals(6) + assert(err, IsNil) + assert(nBytes, Equals, int64(6)) - mb, err := stream2.Read() - assert.Error(err).IsNil() - assert.Int(len(mb)).Equals(2) - assert.String(mb[0].String()).Equals("abc") - assert.String(mb[1].String()).Equals("efg") + mb, err := stream2.ReadMultiBuffer() + assert(err, IsNil) + assert(len(mb), Equals, 2) + assert(mb[0].String(), Equals, "abc") + assert(mb[1].String(), Equals, "efg") } func TestBytesReaderMultiBuffer(t *testing.T) { - assert := assert.On(t) + assert := With(t) stream := ray.NewStream(context.Background()) - reader := ToBytesReader(stream) + reader := NewBufferedReader(stream) b1 := New() b1.AppendBytes('a', 'b', 'c') b2 := New() b2.AppendBytes('e', 'f', 'g') - assert.Error(stream.Write(NewMultiBufferValue(b1, b2))).IsNil() + assert(stream.WriteMultiBuffer(NewMultiBufferValue(b1, b2)), IsNil) stream.Close() mbReader := NewReader(reader) - mb, err := mbReader.Read() - assert.Error(err).IsNil() - assert.Int(len(mb)).Equals(2) - assert.String(mb[0].String()).Equals("abc") - assert.String(mb[1].String()).Equals("efg") + mb, err := mbReader.ReadMultiBuffer() + assert(err, IsNil) + assert(len(mb), Equals, 2) + assert(mb[0].String(), Equals, "abc") + assert(mb[1].String(), Equals, "efg") } diff --git a/common/buf/writer.go b/common/buf/writer.go index 084598e70..6dbc886e3 100644 --- a/common/buf/writer.go +++ b/common/buf/writer.go @@ -1,52 +1,164 @@ package buf -import "io" +import ( + "io" + + "v2ray.com/core/common/errors" +) + +var ( + _ io.ReaderFrom = (*BufferToBytesWriter)(nil) + _ io.Writer = (*BufferToBytesWriter)(nil) + _ Writer = (*BufferToBytesWriter)(nil) +) // BufferToBytesWriter is a Writer that writes alloc.Buffer into underlying writer. type BufferToBytesWriter struct { - writer io.Writer + io.Writer } -// Write implements Writer.Write(). Write() takes ownership of the given buffer. -func (w *BufferToBytesWriter) Write(mb MultiBuffer) error { +func NewBufferToBytesWriter(writer io.Writer) *BufferToBytesWriter { + return &BufferToBytesWriter{ + Writer: writer, + } +} + +// WriteMultiBuffer implements Writer. This method takes ownership of the given buffer. +func (w *BufferToBytesWriter) WriteMultiBuffer(mb MultiBuffer) error { defer mb.Release() bs := mb.ToNetBuffers() - _, err := bs.WriteTo(w.writer) + _, err := bs.WriteTo(w) return err } -type writerAdapter struct { - writer MultiBufferWriter +// ReadFrom implements io.ReaderFrom. +func (w *BufferToBytesWriter) ReadFrom(reader io.Reader) (int64, error) { + var sc SizeCounter + err := Copy(NewReader(reader), w, CountSize(&sc)) + return sc.Size, err } -// Write implements buf.MultiBufferWriter. -func (w *writerAdapter) Write(mb MultiBuffer) error { - return w.writer.WriteMultiBuffer(mb) +var ( + _ io.ReaderFrom = (*BufferedWriter)(nil) + _ io.Writer = (*BufferedWriter)(nil) + _ Writer = (*BufferedWriter)(nil) + _ io.ByteWriter = (*BufferedWriter)(nil) +) + +// BufferedWriter is a Writer with internal buffer. +type BufferedWriter struct { + writer Writer + buffer *Buffer + buffered bool } -type mergingWriter struct { - writer io.Writer - buffer []byte +// NewBufferedWriter creates a new BufferedWriter. +func NewBufferedWriter(writer Writer) *BufferedWriter { + return &BufferedWriter{ + writer: writer, + buffer: New(), + buffered: true, + } } -func (w *mergingWriter) Write(mb MultiBuffer) error { - defer mb.Release() +func (w *BufferedWriter) WriteByte(c byte) error { + _, err := w.Write([]byte{c}) + return err +} - for !mb.IsEmpty() { - nBytes, _ := mb.Read(w.buffer) - if _, err := w.writer.Write(w.buffer[:nBytes]); err != nil { +// Write implements io.Writer. +func (w *BufferedWriter) Write(b []byte) (int, error) { + if !w.buffered { + if writer, ok := w.writer.(io.Writer); ok { + return writer.Write(b) + } + } + + totalBytes := 0 + for len(b) > 0 { + if w.buffer == nil { + w.buffer = New() + } + + nBytes, err := w.buffer.Write(b) + totalBytes += nBytes + if err != nil { + return totalBytes, err + } + if !w.buffered || w.buffer.IsFull() { + if err := w.Flush(); err != nil { + return totalBytes, err + } + } + b = b[nBytes:] + } + + return totalBytes, nil +} + +// WriteMultiBuffer implements Writer. It takes ownership of the given MultiBuffer. +func (w *BufferedWriter) WriteMultiBuffer(b MultiBuffer) error { + if !w.buffered { + return w.writer.WriteMultiBuffer(b) + } + + defer b.Release() + + for !b.IsEmpty() { + if err := w.buffer.AppendSupplier(ReadFrom(&b)); err != nil { return err } + if w.buffer.IsFull() { + if err := w.Flush(); err != nil { + return err + } + } + } + + return nil +} + +// Flush flushes buffered content into underlying writer. +func (w *BufferedWriter) Flush() error { + if !w.buffer.IsEmpty() { + if err := w.writer.WriteMultiBuffer(NewMultiBufferValue(w.buffer)); err != nil { + return err + } + + if w.buffered { + w.buffer = New() + } else { + w.buffer = nil + } } return nil } +func (w *BufferedWriter) SetBuffered(f bool) error { + w.buffered = f + if !f { + return w.Flush() + } + return nil +} + +// ReadFrom implements io.ReaderFrom. +func (w *BufferedWriter) ReadFrom(reader io.Reader) (int64, error) { + if err := w.SetBuffered(false); err != nil { + return 0, err + } + + var sc SizeCounter + err := Copy(NewReader(reader), w, CountSize(&sc)) + return sc.Size, err +} + type seqWriter struct { writer io.Writer } -func (w *seqWriter) Write(mb MultiBuffer) error { +func (w *seqWriter) WriteMultiBuffer(mb MultiBuffer) error { defer mb.Release() for _, b := range mb { @@ -61,54 +173,38 @@ func (w *seqWriter) Write(mb MultiBuffer) error { return nil } -var ( - _ MultiBufferWriter = (*bytesToBufferWriter)(nil) -) - -type bytesToBufferWriter struct { - writer Writer -} - -// Write implements io.Writer. -func (w *bytesToBufferWriter) Write(payload []byte) (int, error) { - mb := NewMultiBuffer() - mb.Write(payload) - if err := w.writer.Write(mb); err != nil { - return 0, err - } - return len(payload), nil -} - -func (w *bytesToBufferWriter) WriteMultiBuffer(mb MultiBuffer) error { - return w.writer.Write(mb) -} - -func (w *bytesToBufferWriter) ReadFrom(reader io.Reader) (int64, error) { - mbReader := NewReader(reader) - totalBytes := int64(0) - eof := false - for !eof { - mb, err := mbReader.Read() - if err == io.EOF { - eof = true - } else if err != nil { - return totalBytes, err - } - totalBytes += int64(mb.Len()) - if err := w.writer.Write(mb); err != nil { - return totalBytes, err - } - } - return totalBytes, nil -} - type noOpWriter struct{} -func (noOpWriter) Write(b MultiBuffer) error { +func (noOpWriter) WriteMultiBuffer(b MultiBuffer) error { b.Release() return nil } +func (noOpWriter) Write(b []byte) (int, error) { + return len(b), nil +} + +func (noOpWriter) ReadFrom(reader io.Reader) (int64, error) { + b := New() + defer b.Release() + + totalBytes := int64(0) + for { + err := b.Reset(ReadFrom(reader)) + totalBytes += int64(b.Len()) + if err != nil { + if errors.Cause(err) == io.EOF { + return totalBytes, nil + } + return totalBytes, err + } + } +} + var ( + // Discard is a Writer that swallows all contents written in. Discard Writer = noOpWriter{} + + // DiscardBytes is an io.Writer that swallows all contents written in. + DiscardBytes io.Writer = noOpWriter{} ) diff --git a/common/buf/writer_test.go b/common/buf/writer_test.go index afa0d8cd2..0e6b15db8 100644 --- a/common/buf/writer_test.go +++ b/common/buf/writer_test.go @@ -9,37 +9,67 @@ import ( "context" "io" + "v2ray.com/core/common" . "v2ray.com/core/common/buf" - "v2ray.com/core/testing/assert" "v2ray.com/core/transport/ray" + . "v2ray.com/ext/assert" ) func TestWriter(t *testing.T) { - assert := assert.On(t) + assert := With(t) lb := New() - assert.Error(lb.AppendSupplier(ReadFrom(rand.Reader))).IsNil() + assert(lb.AppendSupplier(ReadFrom(rand.Reader)), IsNil) expectedBytes := append([]byte(nil), lb.Bytes()...) writeBuffer := bytes.NewBuffer(make([]byte, 0, 1024*1024)) - writer := NewWriter(NewBufferedWriter(writeBuffer)) - err := writer.Write(NewMultiBufferValue(lb)) - assert.Error(err).IsNil() - assert.Bytes(expectedBytes).Equals(writeBuffer.Bytes()) + writer := NewBufferedWriter(NewWriter(writeBuffer)) + writer.SetBuffered(false) + err := writer.WriteMultiBuffer(NewMultiBufferValue(lb)) + assert(err, IsNil) + assert(writer.Flush(), IsNil) + assert(expectedBytes, Equals, writeBuffer.Bytes()) } func TestBytesWriterReadFrom(t *testing.T) { - assert := assert.On(t) + assert := With(t) cache := ray.NewStream(context.Background()) - reader := bufio.NewReader(io.LimitReader(rand.Reader, 8192)) - _, err := reader.WriteTo(ToBytesWriter(cache)) - assert.Error(err).IsNil() + const size = 50000 + reader := bufio.NewReader(io.LimitReader(rand.Reader, size)) + writer := NewBufferedWriter(cache) + writer.SetBuffered(false) + nBytes, err := reader.WriteTo(writer) + assert(nBytes, Equals, int64(size)) + assert(err, IsNil) - mb, err := cache.Read() - assert.Error(err).IsNil() - assert.Int(mb.Len()).Equals(8192) - assert.Int(len(mb)).Equals(4) + mb, err := cache.ReadMultiBuffer() + assert(err, IsNil) + assert(mb.Len(), Equals, size) +} + +func TestDiscardBytes(t *testing.T) { + assert := With(t) + + b := New() + common.Must(b.Reset(ReadFullFrom(rand.Reader, Size))) + + nBytes, err := io.Copy(DiscardBytes, b) + assert(nBytes, Equals, int64(Size)) + assert(err, IsNil) +} + +func TestDiscardBytesMultiBuffer(t *testing.T) { + assert := With(t) + + const size = 10240*1024 + 1 + buffer := bytes.NewBuffer(make([]byte, 0, size)) + common.Must2(buffer.ReadFrom(io.LimitReader(rand.Reader, size))) + + r := NewReader(buffer) + nBytes, err := io.Copy(DiscardBytes, NewBufferedReader(r)) + assert(nBytes, Equals, int64(size)) + assert(err, IsNil) } diff --git a/common/common.go b/common/common.go index 47d47dbde..36b654900 100644 --- a/common/common.go +++ b/common/common.go @@ -11,6 +11,7 @@ func Must(err error) { } } +// Must2 panics if the second parameter is not nil. func Must2(v interface{}, err error) { if err != nil { panic(err) diff --git a/common/crypto/auth.go b/common/crypto/auth.go index d268809f2..192396b74 100644 --- a/common/crypto/auth.go +++ b/common/crypto/auth.go @@ -29,6 +29,26 @@ func (v StaticBytesGenerator) Next() []byte { return v.Content } +type IncreasingAEADNonceGenerator struct { + nonce []byte +} + +func NewIncreasingAEADNonceGenerator() *IncreasingAEADNonceGenerator { + return &IncreasingAEADNonceGenerator{ + nonce: []byte{0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}, + } +} + +func (g *IncreasingAEADNonceGenerator) Next() []byte { + for i := range g.nonce { + g.nonce[i]++ + if g.nonce[i] != 0 { + break + } + } + return g.nonce +} + type Authenticator interface { NonceSize() int Overhead() int @@ -48,7 +68,10 @@ func (v *AEADAuthenticator) Open(dst, cipherText []byte) ([]byte, error) { return nil, newError("invalid AEAD nonce size: ", len(iv)) } - additionalData := v.AdditionalDataGenerator.Next() + var additionalData []byte + if v.AdditionalDataGenerator != nil { + additionalData = v.AdditionalDataGenerator.Next() + } return v.AEAD.Open(dst, iv, cipherText, additionalData) } @@ -58,7 +81,10 @@ func (v *AEADAuthenticator) Seal(dst, plainText []byte) ([]byte, error) { return nil, newError("invalid AEAD nonce size: ", len(iv)) } - additionalData := v.AdditionalDataGenerator.Next() + var additionalData []byte + if v.AdditionalDataGenerator != nil { + additionalData = v.AdditionalDataGenerator.Next() + } return v.AEAD.Seal(dst, iv, plainText, additionalData), nil } @@ -93,7 +119,12 @@ func (r *AuthenticationReader) readSize() error { sizeBytes := r.sizeParser.SizeBytes() if r.buffer.Len() < sizeBytes { - r.buffer.Reset(buf.ReadFrom(r.buffer)) + if r.buffer.IsEmpty() { + r.buffer.Clear() + } else { + common.Must(r.buffer.Reset(buf.ReadFrom(r.buffer))) + } + delta := sizeBytes - r.buffer.Len() if err := r.buffer.AppendSupplier(buf.ReadAtLeastFrom(r.reader, delta)); err != nil { return err @@ -146,18 +177,18 @@ func (r *AuthenticationReader) readChunk(waitForData bool) ([]byte, error) { return b, nil } -func (r *AuthenticationReader) Read() (buf.MultiBuffer, error) { +func (r *AuthenticationReader) ReadMultiBuffer() (buf.MultiBuffer, error) { b, err := r.readChunk(true) if err != nil { return nil, err } - mb := buf.NewMultiBuffer() + var mb buf.MultiBuffer if r.transferType == protocol.TransferTypeStream { mb.Write(b) } else { var bb *buf.Buffer - if len(b) < buf.Size { + if len(b) <= buf.Size { bb = buf.New() } else { bb = buf.NewLocal(len(b)) @@ -175,7 +206,7 @@ func (r *AuthenticationReader) Read() (buf.MultiBuffer, error) { mb.Write(b) } else { var bb *buf.Buffer - if len(b) < buf.Size { + if len(b) <= buf.Size { bb = buf.New() } else { bb = buf.NewLocal(len(b)) @@ -190,79 +221,92 @@ func (r *AuthenticationReader) Read() (buf.MultiBuffer, error) { type AuthenticationWriter struct { auth Authenticator - buffer []byte - payload []byte - writer *buf.BufferedWriter + writer buf.Writer sizeParser ChunkSizeEncoder transferType protocol.TransferType } func NewAuthenticationWriter(auth Authenticator, sizeParser ChunkSizeEncoder, writer io.Writer, transferType protocol.TransferType) *AuthenticationWriter { - const payloadSize = 1024 return &AuthenticationWriter{ auth: auth, - buffer: make([]byte, payloadSize+sizeParser.SizeBytes()+auth.Overhead()), - payload: make([]byte, payloadSize), - writer: buf.NewBufferedWriterSize(writer, readerBufferSize), + writer: buf.NewWriter(writer), sizeParser: sizeParser, transferType: transferType, } } -func (w *AuthenticationWriter) append(b []byte) error { - encryptedSize := len(b) + w.auth.Overhead() - buffer := w.sizeParser.Encode(uint16(encryptedSize), w.buffer[:0]) +func (w *AuthenticationWriter) seal(b *buf.Buffer) (*buf.Buffer, error) { + encryptedSize := b.Len() + w.auth.Overhead() - buffer, err := w.auth.Seal(buffer, b) - if err != nil { - return err + eb := buf.New() + common.Must(eb.Reset(func(bb []byte) (int, error) { + w.sizeParser.Encode(uint16(encryptedSize), bb[:0]) + return w.sizeParser.SizeBytes(), nil + })) + if err := eb.AppendSupplier(func(bb []byte) (int, error) { + _, err := w.auth.Seal(bb[:0], b.Bytes()) + return encryptedSize, err + }); err != nil { + eb.Release() + return nil, err } - if _, err := w.writer.Write(buffer); err != nil { - return err - } - - return nil + return eb, nil } func (w *AuthenticationWriter) writeStream(mb buf.MultiBuffer) error { defer mb.Release() + payloadSize := buf.Size - w.auth.Overhead() - w.sizeParser.SizeBytes() + mb2Write := buf.NewMultiBufferCap(len(mb) + 10) + for { - n, _ := mb.Read(w.payload) - if err := w.append(w.payload[:n]); err != nil { + b := buf.New() + common.Must(b.Reset(func(bb []byte) (int, error) { + return mb.Read(bb[:payloadSize]) + })) + eb, err := w.seal(b) + b.Release() + + if err != nil { + mb2Write.Release() return err } + mb2Write.Append(eb) if mb.IsEmpty() { break } } - return w.writer.Flush() + return w.writer.WriteMultiBuffer(mb2Write) } func (w *AuthenticationWriter) writePacket(mb buf.MultiBuffer) error { defer mb.Release() + mb2Write := buf.NewMultiBufferCap(len(mb) * 2) + for { b := mb.SplitFirst() if b == nil { b = buf.New() } - if err := w.append(b.Bytes()); err != nil { - b.Release() + eb, err := w.seal(b) + b.Release() + if err != nil { + mb2Write.Release() return err } - b.Release() + mb2Write.Append(eb) if mb.IsEmpty() { break } } - return w.writer.Flush() + return w.writer.WriteMultiBuffer(mb2Write) } -func (w *AuthenticationWriter) Write(mb buf.MultiBuffer) error { +func (w *AuthenticationWriter) WriteMultiBuffer(mb buf.MultiBuffer) error { if w.transferType == protocol.TransferTypeStream { return w.writeStream(mb) } diff --git a/common/crypto/auth_test.go b/common/crypto/auth_test.go index a44ecfbf3..58d256e42 100644 --- a/common/crypto/auth_test.go +++ b/common/crypto/auth_test.go @@ -10,19 +10,19 @@ import ( "v2ray.com/core/common/buf" . "v2ray.com/core/common/crypto" "v2ray.com/core/common/protocol" - "v2ray.com/core/testing/assert" + . "v2ray.com/ext/assert" ) func TestAuthenticationReaderWriter(t *testing.T) { - assert := assert.On(t) + assert := With(t) key := make([]byte, 16) rand.Read(key) block, err := aes.NewCipher(key) - assert.Error(err).IsNil() + assert(err, IsNil) aead, err := cipher.NewGCM(block) - assert.Error(err).IsNil() + assert(err, IsNil) rawPayload := make([]byte, 8192*10) rand.Read(rawPayload) @@ -42,10 +42,10 @@ func TestAuthenticationReaderWriter(t *testing.T) { AdditionalDataGenerator: &NoOpBytesGenerator{}, }, PlainChunkSizeParser{}, cache, protocol.TransferTypeStream) - assert.Error(writer.Write(buf.NewMultiBufferValue(payload))).IsNil() - assert.Int(cache.Len()).Equals(83360) - assert.Error(writer.Write(buf.NewMultiBuffer())).IsNil() - assert.Error(err).IsNil() + assert(writer.WriteMultiBuffer(buf.NewMultiBufferValue(payload)), IsNil) + assert(cache.Len(), Equals, 82658) + assert(writer.WriteMultiBuffer(buf.MultiBuffer{}), IsNil) + assert(err, IsNil) reader := NewAuthenticationReader(&AEADAuthenticator{ AEAD: aead, @@ -55,33 +55,33 @@ func TestAuthenticationReaderWriter(t *testing.T) { AdditionalDataGenerator: &NoOpBytesGenerator{}, }, PlainChunkSizeParser{}, cache, protocol.TransferTypeStream) - mb := buf.NewMultiBuffer() + var mb buf.MultiBuffer for mb.Len() < len(rawPayload) { - mb2, err := reader.Read() - assert.Error(err).IsNil() + mb2, err := reader.ReadMultiBuffer() + assert(err, IsNil) mb.AppendMulti(mb2) } mbContent := make([]byte, 8192*10) mb.Read(mbContent) - assert.Bytes(mbContent).Equals(rawPayload) + assert(mbContent, Equals, rawPayload) - _, err = reader.Read() - assert.Error(err).Equals(io.EOF) + _, err = reader.ReadMultiBuffer() + assert(err, Equals, io.EOF) } func TestAuthenticationReaderWriterPacket(t *testing.T) { - assert := assert.On(t) + assert := With(t) key := make([]byte, 16) rand.Read(key) block, err := aes.NewCipher(key) - assert.Error(err).IsNil() + assert(err, IsNil) aead, err := cipher.NewGCM(block) - assert.Error(err).IsNil() + assert(err, IsNil) cache := buf.NewLocal(1024) iv := make([]byte, 12) @@ -95,7 +95,7 @@ func TestAuthenticationReaderWriterPacket(t *testing.T) { AdditionalDataGenerator: &NoOpBytesGenerator{}, }, PlainChunkSizeParser{}, cache, protocol.TransferTypePacket) - payload := buf.NewMultiBuffer() + var payload buf.MultiBuffer pb1 := buf.New() pb1.Append([]byte("abcd")) payload.Append(pb1) @@ -104,10 +104,10 @@ func TestAuthenticationReaderWriterPacket(t *testing.T) { pb2.Append([]byte("efgh")) payload.Append(pb2) - assert.Error(writer.Write(payload)).IsNil() - assert.Int(cache.Len()).GreaterThan(0) - assert.Error(writer.Write(buf.NewMultiBuffer())).IsNil() - assert.Error(err).IsNil() + assert(writer.WriteMultiBuffer(payload), IsNil) + assert(cache.Len(), GreaterThan, 0) + assert(writer.WriteMultiBuffer(buf.MultiBuffer{}), IsNil) + assert(err, IsNil) reader := NewAuthenticationReader(&AEADAuthenticator{ AEAD: aead, @@ -117,15 +117,15 @@ func TestAuthenticationReaderWriterPacket(t *testing.T) { AdditionalDataGenerator: &NoOpBytesGenerator{}, }, PlainChunkSizeParser{}, cache, protocol.TransferTypePacket) - mb, err := reader.Read() - assert.Error(err).IsNil() + mb, err := reader.ReadMultiBuffer() + assert(err, IsNil) b1 := mb.SplitFirst() - assert.String(b1.String()).Equals("abcd") + assert(b1.String(), Equals, "abcd") b2 := mb.SplitFirst() - assert.String(b2.String()).Equals("efgh") - assert.Bool(mb.IsEmpty()).IsTrue() + assert(b2.String(), Equals, "efgh") + assert(mb.IsEmpty(), IsTrue) - _, err = reader.Read() - assert.Error(err).Equals(io.EOF) + _, err = reader.ReadMultiBuffer() + assert(err, Equals, io.EOF) } diff --git a/common/crypto/chacha20_test.go b/common/crypto/chacha20_test.go index 7bca32a91..40ea44c3b 100644 --- a/common/crypto/chacha20_test.go +++ b/common/crypto/chacha20_test.go @@ -7,7 +7,7 @@ import ( "v2ray.com/core/common" . "v2ray.com/core/common/crypto" - "v2ray.com/core/testing/assert" + . "v2ray.com/ext/assert" ) func mustDecodeHex(s string) []byte { @@ -17,7 +17,7 @@ func mustDecodeHex(s string) []byte { } func TestChaCha20Stream(t *testing.T) { - assert := assert.On(t) + assert := With(t) var cases = []struct { key []byte @@ -51,12 +51,12 @@ func TestChaCha20Stream(t *testing.T) { input := make([]byte, len(c.output)) actualOutout := make([]byte, len(c.output)) s.XORKeyStream(actualOutout, input) - assert.Bytes(c.output).Equals(actualOutout) + assert(c.output, Equals, actualOutout) } } func TestChaCha20Decoding(t *testing.T) { - assert := assert.On(t) + assert := With(t) key := make([]byte, 32) rand.Read(key) @@ -72,5 +72,5 @@ func TestChaCha20Decoding(t *testing.T) { stream2 := NewChaCha20Stream(key, iv) stream2.XORKeyStream(x, x) - assert.Bytes(x).Equals(payload) + assert(x, Equals, payload) } diff --git a/common/crypto/chunk.go b/common/crypto/chunk.go index 5b44640cb..e54119984 100644 --- a/common/crypto/chunk.go +++ b/common/crypto/chunk.go @@ -3,15 +3,18 @@ package crypto import ( "io" + "v2ray.com/core/common" "v2ray.com/core/common/buf" "v2ray.com/core/common/serial" ) +// ChunkSizeDecoder is an utility class to decode size value from bytes. type ChunkSizeDecoder interface { SizeBytes() int Decode([]byte) (uint16, error) } +// ChunkSizeEncoder is an utility class to encode size value into bytes. type ChunkSizeEncoder interface { SizeBytes() int Encode(uint16, []byte) []byte @@ -31,50 +34,53 @@ func (PlainChunkSizeParser) Decode(b []byte) (uint16, error) { return serial.BytesToUint16(b), nil } +type AEADChunkSizeParser struct { + Auth *AEADAuthenticator +} + +func (p *AEADChunkSizeParser) SizeBytes() int { + return 2 + p.Auth.Overhead() +} + +func (p *AEADChunkSizeParser) Encode(size uint16, b []byte) []byte { + b = serial.Uint16ToBytes(size-uint16(p.Auth.Overhead()), b) + b, err := p.Auth.Seal(b[:0], b) + common.Must(err) + return b +} + +func (p *AEADChunkSizeParser) Decode(b []byte) (uint16, error) { + b, err := p.Auth.Open(b[:0], b) + if err != nil { + return 0, err + } + return serial.BytesToUint16(b) + uint16(p.Auth.Overhead()), nil +} + type ChunkStreamReader struct { sizeDecoder ChunkSizeDecoder - reader buf.Reader + reader *buf.BufferedReader buffer []byte - leftOver buf.MultiBuffer leftOverSize int } func NewChunkStreamReader(sizeDecoder ChunkSizeDecoder, reader io.Reader) *ChunkStreamReader { return &ChunkStreamReader{ sizeDecoder: sizeDecoder, - reader: buf.NewReader(reader), + reader: buf.NewBufferedReader(buf.NewReader(reader)), buffer: make([]byte, sizeDecoder.SizeBytes()), } } -func (r *ChunkStreamReader) readAtLeast(size int) error { - mb := r.leftOver - r.leftOver = nil - for mb.Len() < size { - extra, err := r.reader.Read() - if err != nil { - mb.Release() - return err - } - mb.AppendMulti(extra) - } - r.leftOver = mb - - return nil -} - func (r *ChunkStreamReader) readSize() (uint16, error) { - if r.sizeDecoder.SizeBytes() > r.leftOver.Len() { - if err := r.readAtLeast(r.sizeDecoder.SizeBytes() - r.leftOver.Len()); err != nil { - return 0, err - } + if _, err := io.ReadFull(r.reader, r.buffer); err != nil { + return 0, err } - r.leftOver.Read(r.buffer) return r.sizeDecoder.Decode(r.buffer) } -func (r *ChunkStreamReader) Read() (buf.MultiBuffer, error) { +func (r *ChunkStreamReader) ReadMultiBuffer() (buf.MultiBuffer, error) { size := r.leftOverSize if size == 0 { nextSize, err := r.readSize() @@ -86,29 +92,14 @@ func (r *ChunkStreamReader) Read() (buf.MultiBuffer, error) { } size = int(nextSize) } + r.leftOverSize = size - if r.leftOver.IsEmpty() { - if err := r.readAtLeast(1); err != nil { - return nil, err - } - } - - if size >= r.leftOver.Len() { - mb := r.leftOver - r.leftOverSize = size - r.leftOver.Len() - r.leftOver = nil + mb, err := r.reader.ReadAtMost(size) + if !mb.IsEmpty() { + r.leftOverSize -= mb.Len() return mb, nil } - - mb := r.leftOver.SliceBySize(size) - if mb.Len() != size { - b := buf.New() - b.AppendSupplier(buf.ReadFullFrom(&r.leftOver, size-mb.Len())) - mb.Append(b) - } - - r.leftOverSize = 0 - return mb, nil + return nil, err } type ChunkStreamWriter struct { @@ -123,18 +114,19 @@ func NewChunkStreamWriter(sizeEncoder ChunkSizeEncoder, writer io.Writer) *Chunk } } -func (w *ChunkStreamWriter) Write(mb buf.MultiBuffer) error { - mb2Write := buf.NewMultiBuffer() +func (w *ChunkStreamWriter) WriteMultiBuffer(mb buf.MultiBuffer) error { const sliceSize = 8192 + mbLen := mb.Len() + mb2Write := buf.NewMultiBufferCap(mbLen/buf.Size + mbLen/sliceSize + 2) for { slice := mb.SliceBySize(sliceSize) b := buf.New() - b.AppendSupplier(func(buffer []byte) (int, error) { + common.Must(b.Reset(func(buffer []byte) (int, error) { w.sizeEncoder.Encode(uint16(slice.Len()), buffer[:0]) return w.sizeEncoder.SizeBytes(), nil - }) + })) mb2Write.Append(b) mb2Write.AppendMulti(slice) @@ -143,5 +135,5 @@ func (w *ChunkStreamWriter) Write(mb buf.MultiBuffer) error { } } - return w.writer.Write(mb2Write) + return w.writer.WriteMultiBuffer(mb2Write) } diff --git a/common/crypto/chunk_test.go b/common/crypto/chunk_test.go index e9f399b0f..4131ebfb2 100644 --- a/common/crypto/chunk_test.go +++ b/common/crypto/chunk_test.go @@ -6,11 +6,11 @@ import ( "v2ray.com/core/common/buf" . "v2ray.com/core/common/crypto" - "v2ray.com/core/testing/assert" + . "v2ray.com/ext/assert" ) func TestChunkStreamIO(t *testing.T) { - assert := assert.On(t) + assert := With(t) cache := buf.NewLocal(8192) @@ -19,26 +19,26 @@ func TestChunkStreamIO(t *testing.T) { b := buf.New() b.AppendBytes('a', 'b', 'c', 'd') - assert.Error(writer.Write(buf.NewMultiBufferValue(b))).IsNil() + assert(writer.WriteMultiBuffer(buf.NewMultiBufferValue(b)), IsNil) b = buf.New() b.AppendBytes('e', 'f', 'g') - assert.Error(writer.Write(buf.NewMultiBufferValue(b))).IsNil() + assert(writer.WriteMultiBuffer(buf.NewMultiBufferValue(b)), IsNil) - assert.Error(writer.Write(buf.NewMultiBuffer())).IsNil() + assert(writer.WriteMultiBuffer(buf.MultiBuffer{}), IsNil) - assert.Int(cache.Len()).Equals(13) + assert(cache.Len(), Equals, 13) - mb, err := reader.Read() - assert.Error(err).IsNil() - assert.Int(mb.Len()).Equals(4) - assert.Bytes(mb[0].Bytes()).Equals([]byte("abcd")) + mb, err := reader.ReadMultiBuffer() + assert(err, IsNil) + assert(mb.Len(), Equals, 4) + assert(mb[0].Bytes(), Equals, []byte("abcd")) - mb, err = reader.Read() - assert.Error(err).IsNil() - assert.Int(mb.Len()).Equals(3) - assert.Bytes(mb[0].Bytes()).Equals([]byte("efg")) + mb, err = reader.ReadMultiBuffer() + assert(err, IsNil) + assert(mb.Len(), Equals, 3) + assert(mb[0].Bytes(), Equals, []byte("efg")) - _, err = reader.Read() - assert.Error(err).Equals(io.EOF) + _, err = reader.ReadMultiBuffer() + assert(err, Equals, io.EOF) } diff --git a/common/crypto/io.go b/common/crypto/io.go index 60e593e52..295ba4725 100644 --- a/common/crypto/io.go +++ b/common/crypto/io.go @@ -28,7 +28,7 @@ func (r *CryptionReader) Read(data []byte) (int, error) { } var ( - _ buf.MultiBufferWriter = (*CryptionWriter)(nil) + _ buf.Writer = (*CryptionWriter)(nil) ) type CryptionWriter struct { @@ -51,6 +51,8 @@ func (w *CryptionWriter) Write(data []byte) (int, error) { } func (w *CryptionWriter) WriteMultiBuffer(mb buf.MultiBuffer) error { + defer mb.Release() + bs := mb.ToNetBuffers() for _, b := range bs { w.stream.XORKeyStream(b, b) diff --git a/common/errors/errors_test.go b/common/errors/errors_test.go index cb385fbd9..337e3c9d2 100644 --- a/common/errors/errors_test.go +++ b/common/errors/errors_test.go @@ -5,29 +5,29 @@ import ( "testing" . "v2ray.com/core/common/errors" - "v2ray.com/core/testing/assert" + . "v2ray.com/ext/assert" ) func TestError(t *testing.T) { - assert := assert.On(t) + assert := With(t) err := New("TestError") - assert.Bool(GetSeverity(err) == SeverityInfo).IsTrue() + assert(GetSeverity(err), Equals, SeverityInfo) err = New("TestError2").Base(io.EOF) - assert.Bool(GetSeverity(err) == SeverityInfo).IsTrue() + assert(GetSeverity(err), Equals, SeverityInfo) err = New("TestError3").Base(io.EOF).AtWarning() - assert.Bool(GetSeverity(err) == SeverityWarning).IsTrue() + assert(GetSeverity(err), Equals, SeverityWarning) err = New("TestError4").Base(io.EOF).AtWarning() err = New("TestError5").Base(err) - assert.Bool(GetSeverity(err) == SeverityWarning).IsTrue() - assert.String(err.Error()).Contains("EOF") + assert(GetSeverity(err), Equals, SeverityWarning) + assert(err.Error(), HasSubstring, "EOF") } func TestErrorMessage(t *testing.T) { - assert := assert.On(t) + assert := With(t) data := []struct { err error @@ -44,6 +44,6 @@ func TestErrorMessage(t *testing.T) { } for _, d := range data { - assert.String(d.err.Error()).Equals(d.msg) + assert(d.err.Error(), Equals, d.msg) } } diff --git a/common/event/event.go b/common/event/event.go new file mode 100644 index 000000000..36a58db50 --- /dev/null +++ b/common/event/event.go @@ -0,0 +1,46 @@ +package event + +import "sync" + +type Event uint16 + +type Handler func(data interface{}) error + +type Registry interface { + On(Event, Handler) +} + +type Listener struct { + sync.RWMutex + events map[Event][]Handler +} + +func (l *Listener) On(e Event, h Handler) { + l.Lock() + defer l.Unlock() + + if l.events == nil { + l.events = make(map[Event][]Handler) + } + + handlers := l.events[e] + handlers = append(handlers, h) + l.events[e] = handlers +} + +func (l *Listener) Fire(e Event, data interface{}) error { + l.RLock() + defer l.RUnlock() + + if l.events == nil { + return nil + } + + for _, h := range l.events[e] { + if err := h(data); err != nil { + return err + } + } + + return nil +} diff --git a/common/net/address.go b/common/net/address.go index 583cebf89..993bf814b 100644 --- a/common/net/address.go +++ b/common/net/address.go @@ -73,6 +73,12 @@ type Address interface { // ParseAddress parses a string into an Address. The return value will be an IPAddress when // the string is in the form of IPv4 or IPv6 address, or a DomainAddress otherwise. func ParseAddress(addr string) Address { + // Handle IPv6 address in form as "[2001:4860:0:2001::68]" + lenAddr := len(addr) + if lenAddr > 0 && addr[0] == '[' && addr[lenAddr-1] == ']' { + addr = addr[1 : lenAddr-1] + } + ip := net.ParseIP(addr) if ip != nil { return IPAddress(ip) diff --git a/common/net/address_test.go b/common/net/address_test.go index 424727314..9c2ab9c8a 100644 --- a/common/net/address_test.go +++ b/common/net/address_test.go @@ -5,24 +5,25 @@ import ( "testing" . "v2ray.com/core/common/net" - "v2ray.com/core/testing/assert" + . "v2ray.com/core/common/net/testing" + . "v2ray.com/ext/assert" ) func TestIPv4Address(t *testing.T) { - assert := assert.On(t) + assert := With(t) ip := []byte{byte(1), byte(2), byte(3), byte(4)} addr := IPAddress(ip) - assert.Address(addr).IsIPv4() - assert.Address(addr).IsNotIPv6() - assert.Address(addr).IsNotDomain() - assert.Bytes(addr.IP()).Equals(ip) - assert.Address(addr).EqualsString("1.2.3.4") + assert(addr, IsIPv4) + assert(addr, Not(IsIPv6)) + assert(addr, Not(IsDomain)) + assert([]byte(addr.IP()), Equals, ip) + assert(addr.String(), Equals, "1.2.3.4") } func TestIPv6Address(t *testing.T) { - assert := assert.On(t) + assert := With(t) ip := []byte{ byte(1), byte(2), byte(3), byte(4), @@ -32,15 +33,15 @@ func TestIPv6Address(t *testing.T) { } addr := IPAddress(ip) - assert.Address(addr).IsIPv6() - assert.Address(addr).IsNotIPv4() - assert.Address(addr).IsNotDomain() - assert.IP(addr.IP()).Equals(net.IP(ip)) - assert.Address(addr).EqualsString("[102:304:102:304:102:304:102:304]") + assert(addr, IsIPv6) + assert(addr, Not(IsIPv4)) + assert(addr, Not(IsDomain)) + assert(addr.IP(), Equals, net.IP(ip)) + assert(addr.String(), Equals, "[102:304:102:304:102:304:102:304]") } func TestIPv4Asv6(t *testing.T) { - assert := assert.On(t) + assert := With(t) ip := []byte{ byte(0), byte(0), byte(0), byte(0), byte(0), byte(0), byte(0), byte(0), @@ -48,27 +49,55 @@ func TestIPv4Asv6(t *testing.T) { byte(1), byte(2), byte(3), byte(4), } addr := IPAddress(ip) - assert.Address(addr).EqualsString("1.2.3.4") + assert(addr.String(), Equals, "1.2.3.4") } func TestDomainAddress(t *testing.T) { - assert := assert.On(t) + assert := With(t) domain := "v2ray.com" addr := DomainAddress(domain) - assert.Address(addr).IsDomain() - assert.Address(addr).IsNotIPv6() - assert.Address(addr).IsNotIPv4() - assert.String(addr.Domain()).Equals(domain) - assert.Address(addr).EqualsString("v2ray.com") + assert(addr, IsDomain) + assert(addr, Not(IsIPv6)) + assert(addr, Not(IsIPv4)) + assert(addr.Domain(), Equals, domain) + assert(addr.String(), Equals, "v2ray.com") } func TestNetIPv4Address(t *testing.T) { - assert := assert.On(t) + assert := With(t) ip := net.IPv4(1, 2, 3, 4) addr := IPAddress(ip) - assert.Address(addr).IsIPv4() - assert.Address(addr).EqualsString("1.2.3.4") + assert(addr, IsIPv4) + assert(addr.String(), Equals, "1.2.3.4") +} + +func TestParseIPv6Address(t *testing.T) { + assert := With(t) + + ip := ParseAddress("[2001:4860:0:2001::68]") + assert(ip, IsIPv6) + assert(ip.String(), Equals, "[2001:4860:0:2001::68]") + + ip = ParseAddress("[::ffff:123.151.71.143]") + assert(ip, IsIPv4) + assert(ip.String(), Equals, "123.151.71.143") +} + +func TestInvalidAddressConvertion(t *testing.T) { + assert := With(t) + + assert(func() { ParseAddress("8.8.8.8").Domain() }, Panics) + assert(func() { ParseAddress("2001:4860:0:2001::68").Domain() }, Panics) + assert(func() { ParseAddress("v2ray.com").IP() }, Panics) +} + +func TestIPOrDomain(t *testing.T) { + assert := With(t) + + assert(NewIPOrDomain(ParseAddress("v2ray.com")).AsAddress(), Equals, ParseAddress("v2ray.com")) + assert(NewIPOrDomain(ParseAddress("8.8.8.8")).AsAddress(), Equals, ParseAddress("8.8.8.8")) + assert(NewIPOrDomain(ParseAddress("2001:4860:0:2001::68")).AsAddress(), Equals, ParseAddress("2001:4860:0:2001::68")) } diff --git a/common/net/destination.go b/common/net/destination.go index 7709b5c95..f7f5b720b 100644 --- a/common/net/destination.go +++ b/common/net/destination.go @@ -41,14 +41,17 @@ func UDPDestination(address Address, port Port) Destination { } } +// NetAddr returns the network address in this Destination in string form. func (d Destination) NetAddr() string { return d.Address.String() + ":" + d.Port.String() } +// String returns the strings form of this Destination. func (d Destination) String() string { return d.Network.URLPrefix() + ":" + d.NetAddr() } +// IsValid returns true if this Destination is valid. func (d Destination) IsValid() bool { return d.Network != Network_Unknown } diff --git a/common/net/destination_test.go b/common/net/destination_test.go index f3b0f1317..b68e9ccbe 100644 --- a/common/net/destination_test.go +++ b/common/net/destination_test.go @@ -4,23 +4,24 @@ import ( "testing" . "v2ray.com/core/common/net" - "v2ray.com/core/testing/assert" + . "v2ray.com/core/common/net/testing" + . "v2ray.com/ext/assert" ) func TestTCPDestination(t *testing.T) { - assert := assert.On(t) + assert := With(t) dest := TCPDestination(IPAddress([]byte{1, 2, 3, 4}), 80) - assert.Destination(dest).IsTCP() - assert.Destination(dest).IsNotUDP() - assert.Destination(dest).EqualsString("tcp:1.2.3.4:80") + assert(dest, IsTCP) + assert(dest, Not(IsUDP)) + assert(dest.String(), Equals, "tcp:1.2.3.4:80") } func TestUDPDestination(t *testing.T) { - assert := assert.On(t) + assert := With(t) dest := UDPDestination(IPAddress([]byte{0x20, 0x01, 0x48, 0x60, 0x48, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x88, 0x88}), 53) - assert.Destination(dest).IsNotTCP() - assert.Destination(dest).IsUDP() - assert.Destination(dest).EqualsString("udp:[2001:4860:4860::8888]:53") + assert(dest, Not(IsTCP)) + assert(dest, IsUDP) + assert(dest.String(), Equals, "udp:[2001:4860:4860::8888]:53") } diff --git a/common/net/ipnet.go b/common/net/ipnet.go index 530d3b1b7..c30f2e882 100644 --- a/common/net/ipnet.go +++ b/common/net/ipnet.go @@ -44,6 +44,7 @@ func (n *IPNetTable) Add(ipNet *net.IPNet) { func (n *IPNetTable) AddIP(ip []byte, mask byte) { k := ipToUint32(ip) + k = (k >> (32 - mask)) << (32 - mask) // normalize ip existing, found := n.cache[k] if !found || existing > mask { n.cache[k] = mask diff --git a/common/net/ipnet_test.go b/common/net/ipnet_test.go index e92616037..2943e59a6 100644 --- a/common/net/ipnet_test.go +++ b/common/net/ipnet_test.go @@ -2,11 +2,19 @@ package net_test import ( "net" + "os" + "path/filepath" "testing" + proto "github.com/golang/protobuf/proto" + "v2ray.com/core/app/router" + "v2ray.com/core/common/platform" + + "v2ray.com/ext/sysio" + "v2ray.com/core/common" . "v2ray.com/core/common/net" - "v2ray.com/core/testing/assert" + . "v2ray.com/ext/assert" ) func parseCIDR(str string) *net.IPNet { @@ -16,7 +24,7 @@ func parseCIDR(str string) *net.IPNet { } func TestIPNet(t *testing.T) { - assert := assert.On(t) + assert := With(t) ipNet := NewIPNetTable() ipNet.Add(parseCIDR(("0.0.0.0/8"))) @@ -32,12 +40,94 @@ func TestIPNet(t *testing.T) { ipNet.Add(parseCIDR(("198.51.100.0/24"))) ipNet.Add(parseCIDR(("203.0.113.0/24"))) ipNet.Add(parseCIDR(("8.8.8.8/32"))) - assert.Bool(ipNet.Contains(ParseIP("192.168.1.1"))).IsTrue() - assert.Bool(ipNet.Contains(ParseIP("192.0.0.0"))).IsTrue() - assert.Bool(ipNet.Contains(ParseIP("192.0.1.0"))).IsFalse() - assert.Bool(ipNet.Contains(ParseIP("0.1.0.0"))).IsTrue() - assert.Bool(ipNet.Contains(ParseIP("1.0.0.1"))).IsFalse() - assert.Bool(ipNet.Contains(ParseIP("8.8.8.7"))).IsFalse() - assert.Bool(ipNet.Contains(ParseIP("8.8.8.8"))).IsTrue() - assert.Bool(ipNet.Contains(ParseIP("2001:cdba::3257:9652"))).IsFalse() + ipNet.AddIP(net.ParseIP("91.108.4.0"), 16) + assert(ipNet.Contains(ParseIP("192.168.1.1")), IsTrue) + assert(ipNet.Contains(ParseIP("192.0.0.0")), IsTrue) + assert(ipNet.Contains(ParseIP("192.0.1.0")), IsFalse) + assert(ipNet.Contains(ParseIP("0.1.0.0")), IsTrue) + assert(ipNet.Contains(ParseIP("1.0.0.1")), IsFalse) + assert(ipNet.Contains(ParseIP("8.8.8.7")), IsFalse) + assert(ipNet.Contains(ParseIP("8.8.8.8")), IsTrue) + assert(ipNet.Contains(ParseIP("2001:cdba::3257:9652")), IsFalse) + assert(ipNet.Contains(ParseIP("91.108.255.254")), IsTrue) +} + +func TestGeoIPCN(t *testing.T) { + assert := With(t) + common.Must(sysio.CopyFile(platform.GetAssetLocation("geoip.dat"), filepath.Join(os.Getenv("GOPATH"), "src", "v2ray.com", "core", "tools", "release", "config", "geoip.dat"))) + + ips, err := loadGeoIP("CN") + common.Must(err) + + ipNet := NewIPNetTable() + for _, ip := range ips { + ipNet.AddIP(ip.Ip, byte(ip.Prefix)) + } + + assert(ipNet.Contains([]byte{8, 8, 8, 8}), IsFalse) +} + +func loadGeoIP(country string) ([]*router.CIDR, error) { + geoipBytes, err := sysio.ReadAsset("geoip.dat") + if err != nil { + return nil, err + } + var geoipList router.GeoIPList + if err := proto.Unmarshal(geoipBytes, &geoipList); err != nil { + return nil, err + } + + for _, geoip := range geoipList.Entry { + if geoip.CountryCode == country { + return geoip.Cidr, nil + } + } + + panic("country not found: " + country) +} + +func BenchmarkIPNetQuery(b *testing.B) { + common.Must(sysio.CopyFile(platform.GetAssetLocation("geoip.dat"), filepath.Join(os.Getenv("GOPATH"), "src", "v2ray.com", "core", "tools", "release", "config", "geoip.dat"))) + + ips, err := loadGeoIP("CN") + common.Must(err) + + ipNet := NewIPNetTable() + for _, ip := range ips { + ipNet.AddIP(ip.Ip, byte(ip.Prefix)) + } + + b.ResetTimer() + + for i := 0; i < b.N; i++ { + ipNet.Contains([]byte{8, 8, 8, 8}) + } +} + +func BenchmarkCIDRQuery(b *testing.B) { + common.Must(sysio.CopyFile(platform.GetAssetLocation("geoip.dat"), filepath.Join(os.Getenv("GOPATH"), "src", "v2ray.com", "core", "tools", "release", "config", "geoip.dat"))) + + ips, err := loadGeoIP("CN") + common.Must(err) + + ipNet := make([]*net.IPNet, 0, 1024) + for _, ip := range ips { + if len(ip.Ip) != 4 { + continue + } + ipNet = append(ipNet, &net.IPNet{ + IP: net.IP(ip.Ip), + Mask: net.CIDRMask(int(ip.Prefix), 32), + }) + } + + b.ResetTimer() + + for i := 0; i < b.N; i++ { + for _, n := range ipNet { + if n.Contains([]byte{8, 8, 8, 8}) { + break + } + } + } } diff --git a/common/net/net.go b/common/net/net.go index bd0188c26..4d41e90af 100644 --- a/common/net/net.go +++ b/common/net/net.go @@ -1,4 +1,4 @@ -// Package net contains common network utilities. +// Package net is a drop-in replacement to Golang's net package, with some more functionalities. package net //go:generate go run $GOPATH/src/v2ray.com/core/tools/generrorgen/main.go -pkg net -path Net diff --git a/common/net/port_test.go b/common/net/port_test.go index a1f1f4e21..187cdf1f3 100644 --- a/common/net/port_test.go +++ b/common/net/port_test.go @@ -4,15 +4,15 @@ import ( "testing" . "v2ray.com/core/common/net" - "v2ray.com/core/testing/assert" + . "v2ray.com/ext/assert" ) func TestPortRangeContains(t *testing.T) { - assert := assert.On(t) + assert := With(t) portRange := &PortRange{ From: 53, To: 53, } - assert.Bool(portRange.Contains(Port(53))).IsTrue() + assert(portRange.Contains(Port(53)), IsTrue) } diff --git a/common/net/system.go b/common/net/system.go index da2289a5d..65d7b8bb0 100644 --- a/common/net/system.go +++ b/common/net/system.go @@ -2,6 +2,7 @@ package net import "net" +// DialTCP is an injectable function. Default to net.DialTCP var DialTCP = net.DialTCP var DialUDP = net.DialUDP var DialUnix = net.DialUnix @@ -31,6 +32,7 @@ type UDPConn = net.UDPConn type UnixAddr = net.UnixAddr type UnixConn = net.UnixConn +// IP is an alias for net.IP. type IP = net.IP type IPMask = net.IPMask type IPNet = net.IPNet diff --git a/common/net/testing/assert.go b/common/net/testing/assert.go new file mode 100644 index 000000000..b6eb2fb9c --- /dev/null +++ b/common/net/testing/assert.go @@ -0,0 +1,48 @@ +package testing + +import ( + "v2ray.com/core/common/net" + "v2ray.com/ext/assert" +) + +var IsIPv4 = assert.CreateMatcher(func(a net.Address) bool { + return a.Family().IsIPv4() +}, "is IPv4") + +var IsIPv6 = assert.CreateMatcher(func(a net.Address) bool { + return a.Family().IsIPv6() +}, "is IPv6") + +var IsIP = assert.CreateMatcher(func(a net.Address) bool { + return a.Family().IsIPv4() || a.Family().IsIPv6() +}, "is IP") + +var IsTCP = assert.CreateMatcher(func(a net.Destination) bool { + return a.Network == net.Network_TCP +}, "is TCP") + +var IsUDP = assert.CreateMatcher(func(a net.Destination) bool { + return a.Network == net.Network_UDP +}, "is UDP") + +var IsDomain = assert.CreateMatcher(func(a net.Address) bool { + return a.Family().IsDomain() +}, "is Domain") + +func init() { + assert.RegisterEqualsMatcher(func(a, b net.Address) bool { + return a == b + }) + + assert.RegisterEqualsMatcher(func(a, b net.Destination) bool { + return a == b + }) + + assert.RegisterEqualsMatcher(func(a, b net.Port) bool { + return a == b + }) + + assert.RegisterEqualsMatcher(func(a, b net.IP) bool { + return a.Equal(b) + }) +} diff --git a/common/platform/others.go b/common/platform/others.go index 0bd7ee77d..e93f5af6b 100644 --- a/common/platform/others.go +++ b/common/platform/others.go @@ -4,6 +4,7 @@ package platform import ( "os" + "path/filepath" ) func ExpandEnv(s string) string { @@ -13,3 +14,9 @@ func ExpandEnv(s string) string { func LineSeparator() string { return "\n" } + +func GetToolLocation(file string) string { + const name = "v2ray.location.tool" + toolPath := EnvFlag{Name: name, AltName: NormalizeEnvName(name)}.GetValue(getExecutableDir) + return filepath.Join(toolPath, file) +} diff --git a/common/platform/platform.go b/common/platform/platform.go index 2327ad665..b827cdc00 100644 --- a/common/platform/platform.go +++ b/common/platform/platform.go @@ -2,6 +2,7 @@ package platform import ( "os" + "path/filepath" "strconv" "strings" ) @@ -11,7 +12,7 @@ type EnvFlag struct { AltName string } -func (f EnvFlag) GetValue(defaultValue string) string { +func (f EnvFlag) GetValue(defaultValue func() string) string { if v, found := os.LookupEnv(f.Name); found { return v } @@ -21,13 +22,16 @@ func (f EnvFlag) GetValue(defaultValue string) string { } } - return defaultValue + return defaultValue() } func (f EnvFlag) GetValueAsInt(defaultValue int) int { - const PlaceHolder = "xxxxxx" - s := f.GetValue(PlaceHolder) - if s == PlaceHolder { + useDefaultValue := false + s := f.GetValue(func() string { + useDefaultValue = true + return "" + }) + if useDefaultValue { return defaultValue } v, err := strconv.ParseInt(s, 10, 32) @@ -40,3 +44,29 @@ func (f EnvFlag) GetValueAsInt(defaultValue int) int { func NormalizeEnvName(name string) string { return strings.Replace(strings.ToUpper(strings.TrimSpace(name)), ".", "_", -1) } + +func getExecutableDir() string { + exec, err := os.Executable() + if err != nil { + return "" + } + return filepath.Dir(exec) +} + +func getExecuableSubDir(dir string) func() string { + return func() string { + return filepath.Join(getExecutableDir(), dir) + } +} + +func GetAssetLocation(file string) string { + const name = "v2ray.location.asset" + assetPath := EnvFlag{Name: name, AltName: NormalizeEnvName(name)}.GetValue(getExecutableDir) + return filepath.Join(assetPath, file) +} + +func GetPluginDirectory() string { + const name = "v2ray.location.plugin" + pluginDir := EnvFlag{Name: name, AltName: NormalizeEnvName(name)}.GetValue(getExecuableSubDir("plugins")) + return pluginDir +} diff --git a/common/platform/platform_test.go b/common/platform/platform_test.go index 4b3d6e6fe..bfe0445bc 100644 --- a/common/platform/platform_test.go +++ b/common/platform/platform_test.go @@ -1,14 +1,16 @@ package platform_test import ( + "os" + "path/filepath" "testing" . "v2ray.com/core/common/platform" - "v2ray.com/core/testing/assert" + . "v2ray.com/ext/assert" ) func TestNormalizeEnvName(t *testing.T) { - assert := assert.On(t) + assert := With(t) cases := []struct { input string @@ -28,14 +30,27 @@ func TestNormalizeEnvName(t *testing.T) { }, } for _, test := range cases { - assert.String(NormalizeEnvName(test.input)).Equals(test.output) + assert(NormalizeEnvName(test.input), Equals, test.output) } } func TestEnvFlag(t *testing.T) { - assert := assert.On(t) + assert := With(t) - assert.Int(EnvFlag{ + assert(EnvFlag{ Name: "xxxxx.y", - }.GetValueAsInt(10)).Equals(10) + }.GetValueAsInt(10), Equals, 10) +} + +func TestGetAssetLocation(t *testing.T) { + assert := With(t) + + exec, err := os.Executable() + assert(err, IsNil) + + loc := GetAssetLocation("t") + assert(filepath.Dir(loc), Equals, filepath.Dir(exec)) + + os.Setenv("v2ray.location.asset", "/v2ray") + assert(GetAssetLocation("t"), Equals, "/v2ray/t") } diff --git a/common/platform/windows.go b/common/platform/windows.go index 7fc1f90d7..c311ef5c0 100644 --- a/common/platform/windows.go +++ b/common/platform/windows.go @@ -2,6 +2,8 @@ package platform +import "path/filepath" + func ExpandEnv(s string) string { // TODO return s @@ -10,3 +12,9 @@ func ExpandEnv(s string) string { func LineSeparator() string { return "\r\n" } + +func GetToolLocation(file string) string { + const name = "v2ray.location.tool" + toolPath := EnvFlag{Name: name, AltName: NormalizeEnvName(name)}.GetValue(getExecutableDir) + return filepath.Join(toolPath, file+".exe") +} diff --git a/common/protocol/headers.go b/common/protocol/headers.go index b9ecd1a9f..1304a7e4d 100644 --- a/common/protocol/headers.go +++ b/common/protocol/headers.go @@ -3,6 +3,7 @@ package protocol import ( "runtime" + "v2ray.com/core/common/bitmask" "v2ray.com/core/common/net" "v2ray.com/core/common/uuid" ) @@ -24,35 +25,20 @@ func (c RequestCommand) TransferType() TransferType { return TransferTypePacket } -// RequestOption is the options of a request. -type RequestOption byte - const ( // RequestOptionChunkStream indicates request payload is chunked. Each chunk consists of length, authentication and payload. - RequestOptionChunkStream = RequestOption(0x01) + RequestOptionChunkStream bitmask.Byte = 0x01 // RequestOptionConnectionReuse indicates client side expects to reuse the connection. - RequestOptionConnectionReuse = RequestOption(0x02) + RequestOptionConnectionReuse bitmask.Byte = 0x02 - RequestOptionChunkMasking = RequestOption(0x04) + RequestOptionChunkMasking bitmask.Byte = 0x04 ) -func (v RequestOption) Has(option RequestOption) bool { - return (v & option) == option -} - -func (v *RequestOption) Set(option RequestOption) { - *v = (*v | option) -} - -func (v *RequestOption) Clear(option RequestOption) { - *v = (*v & (^option)) -} - type Security byte -func (v Security) Is(t SecurityType) bool { - return v == Security(t) +func (s Security) Is(t SecurityType) bool { + return s == Security(t) } func NormSecurity(s Security) Security { @@ -65,42 +51,28 @@ func NormSecurity(s Security) Security { type RequestHeader struct { Version byte Command RequestCommand - Option RequestOption + Option bitmask.Byte Security Security Port net.Port Address net.Address User *User } -func (v *RequestHeader) Destination() net.Destination { - if v.Command == RequestCommandUDP { - return net.UDPDestination(v.Address, v.Port) +func (h *RequestHeader) Destination() net.Destination { + if h.Command == RequestCommandUDP { + return net.UDPDestination(h.Address, h.Port) } - return net.TCPDestination(v.Address, v.Port) + return net.TCPDestination(h.Address, h.Port) } -type ResponseOption byte - const ( - ResponseOptionConnectionReuse = ResponseOption(0x01) + ResponseOptionConnectionReuse bitmask.Byte = 0x01 ) -func (v *ResponseOption) Set(option ResponseOption) { - *v = (*v | option) -} - -func (v ResponseOption) Has(option ResponseOption) bool { - return (v & option) == option -} - -func (v *ResponseOption) Clear(option ResponseOption) { - *v = (*v & (^option)) -} - type ResponseCommand interface{} type ResponseHeader struct { - Option ResponseOption + Option bitmask.Byte Command ResponseCommand } @@ -108,20 +80,21 @@ type CommandSwitchAccount struct { Host net.Address Port net.Port ID *uuid.UUID - AlterIds uint16 Level uint32 + AlterIds uint16 ValidMin byte } -func (v *SecurityConfig) AsSecurity() Security { - if v == nil { - return Security(SecurityType_LEGACY) - } - if v.Type == SecurityType_AUTO { +func (sc *SecurityConfig) AsSecurity() Security { + if sc == nil || sc.Type == SecurityType_AUTO { if runtime.GOARCH == "amd64" || runtime.GOARCH == "s390x" { return Security(SecurityType_AES128_GCM) } return Security(SecurityType_CHACHA20_POLY1305) } - return NormSecurity(Security(v.Type)) + return NormSecurity(Security(sc.Type)) +} + +func IsDomainTooLong(domain string) bool { + return len(domain) > 256 } diff --git a/common/protocol/headers_test.go b/common/protocol/headers_test.go deleted file mode 100644 index 5ecbdd8ab..000000000 --- a/common/protocol/headers_test.go +++ /dev/null @@ -1,34 +0,0 @@ -package protocol_test - -import ( - "testing" - - . "v2ray.com/core/common/protocol" - "v2ray.com/core/testing/assert" -) - -func TestRequestOptionSet(t *testing.T) { - assert := assert.On(t) - - var option RequestOption - assert.Bool(option.Has(RequestOptionChunkStream)).IsFalse() - - option.Set(RequestOptionChunkStream) - assert.Bool(option.Has(RequestOptionChunkStream)).IsTrue() - - option.Set(RequestOptionChunkMasking) - assert.Bool(option.Has(RequestOptionChunkMasking)).IsTrue() - assert.Bool(option.Has(RequestOptionChunkStream)).IsTrue() -} - -func TestRequestOptionClear(t *testing.T) { - assert := assert.On(t) - - var option RequestOption - option.Set(RequestOptionChunkStream) - option.Set(RequestOptionChunkMasking) - - option.Clear(RequestOptionChunkStream) - assert.Bool(option.Has(RequestOptionChunkStream)).IsFalse() - assert.Bool(option.Has(RequestOptionChunkMasking)).IsTrue() -} diff --git a/common/protocol/id_test.go b/common/protocol/id_test.go index 12788529a..81bf50638 100644 --- a/common/protocol/id_test.go +++ b/common/protocol/id_test.go @@ -6,12 +6,12 @@ import ( "v2ray.com/core/common/predicate" . "v2ray.com/core/common/protocol" "v2ray.com/core/common/uuid" - "v2ray.com/core/testing/assert" + . "v2ray.com/ext/assert" ) func TestCmdKey(t *testing.T) { - assert := assert.On(t) + assert := With(t) id := NewID(uuid.New()) - assert.Bool(predicate.BytesAll(id.CmdKey(), 0)).IsFalse() + assert(predicate.BytesAll(id.CmdKey(), 0), IsFalse) } diff --git a/common/protocol/payload.go b/common/protocol/payload.go index 822143014..03eced677 100644 --- a/common/protocol/payload.go +++ b/common/protocol/payload.go @@ -6,3 +6,11 @@ const ( TransferTypeStream TransferType = 0 TransferTypePacket TransferType = 1 ) + +type AddressType byte + +const ( + AddressTypeIPv4 AddressType = 1 + AddressTypeDomain AddressType = 2 + AddressTypeIPv6 AddressType = 3 +) diff --git a/common/protocol/server_picker_test.go b/common/protocol/server_picker_test.go index 2b1bd6fe5..72e789ee8 100644 --- a/common/protocol/server_picker_test.go +++ b/common/protocol/server_picker_test.go @@ -6,30 +6,30 @@ import ( "v2ray.com/core/common/net" . "v2ray.com/core/common/protocol" - "v2ray.com/core/testing/assert" + . "v2ray.com/ext/assert" ) func TestServerList(t *testing.T) { - assert := assert.On(t) + assert := With(t) list := NewServerList() list.AddServer(NewServerSpec(net.TCPDestination(net.LocalHostIP, net.Port(1)), AlwaysValid())) - assert.Uint32(list.Size()).Equals(1) + assert(list.Size(), Equals, uint32(1)) list.AddServer(NewServerSpec(net.TCPDestination(net.LocalHostIP, net.Port(2)), BeforeTime(time.Now().Add(time.Second)))) - assert.Uint32(list.Size()).Equals(2) + assert(list.Size(), Equals, uint32(2)) server := list.GetServer(1) - assert.Port(server.Destination().Port).Equals(2) + assert(server.Destination().Port, Equals, net.Port(2)) time.Sleep(2 * time.Second) server = list.GetServer(1) - assert.Pointer(server).IsNil() + assert(server, IsNil) server = list.GetServer(0) - assert.Port(server.Destination().Port).Equals(1) + assert(server.Destination().Port, Equals, net.Port(1)) } func TestServerPicker(t *testing.T) { - assert := assert.On(t) + assert := With(t) list := NewServerList() list.AddServer(NewServerSpec(net.TCPDestination(net.LocalHostIP, net.Port(1)), AlwaysValid())) @@ -38,17 +38,17 @@ func TestServerPicker(t *testing.T) { picker := NewRoundRobinServerPicker(list) server := picker.PickServer() - assert.Port(server.Destination().Port).Equals(1) + assert(server.Destination().Port, Equals, net.Port(1)) server = picker.PickServer() - assert.Port(server.Destination().Port).Equals(2) + assert(server.Destination().Port, Equals, net.Port(2)) server = picker.PickServer() - assert.Port(server.Destination().Port).Equals(3) + assert(server.Destination().Port, Equals, net.Port(3)) server = picker.PickServer() - assert.Port(server.Destination().Port).Equals(1) + assert(server.Destination().Port, Equals, net.Port(1)) time.Sleep(2 * time.Second) server = picker.PickServer() - assert.Port(server.Destination().Port).Equals(1) + assert(server.Destination().Port, Equals, net.Port(1)) server = picker.PickServer() - assert.Port(server.Destination().Port).Equals(1) + assert(server.Destination().Port, Equals, net.Port(1)) } diff --git a/common/protocol/server_spec_test.go b/common/protocol/server_spec_test.go index beca89b9c..0c1a6252b 100644 --- a/common/protocol/server_spec_test.go +++ b/common/protocol/server_spec_test.go @@ -5,27 +5,27 @@ import ( "time" . "v2ray.com/core/common/protocol" - "v2ray.com/core/testing/assert" + . "v2ray.com/ext/assert" ) func TestAlwaysValidStrategy(t *testing.T) { - assert := assert.On(t) + assert := With(t) strategy := AlwaysValid() - assert.Bool(strategy.IsValid()).IsTrue() + assert(strategy.IsValid(), IsTrue) strategy.Invalidate() - assert.Bool(strategy.IsValid()).IsTrue() + assert(strategy.IsValid(), IsTrue) } func TestTimeoutValidStrategy(t *testing.T) { - assert := assert.On(t) + assert := With(t) strategy := BeforeTime(time.Now().Add(2 * time.Second)) - assert.Bool(strategy.IsValid()).IsTrue() + assert(strategy.IsValid(), IsTrue) time.Sleep(3 * time.Second) - assert.Bool(strategy.IsValid()).IsFalse() + assert(strategy.IsValid(), IsFalse) strategy = BeforeTime(time.Now().Add(2 * time.Second)) strategy.Invalidate() - assert.Bool(strategy.IsValid()).IsFalse() + assert(strategy.IsValid(), IsFalse) } diff --git a/common/protocol/time_test.go b/common/protocol/time_test.go index 1ee1084f9..42b1c99dd 100644 --- a/common/protocol/time_test.go +++ b/common/protocol/time_test.go @@ -5,11 +5,11 @@ import ( "time" . "v2ray.com/core/common/protocol" - "v2ray.com/core/testing/assert" + . "v2ray.com/ext/assert" ) func TestGenerateRandomInt64InRange(t *testing.T) { - assert := assert.On(t) + assert := With(t) base := time.Now().Unix() delta := 100 @@ -17,7 +17,7 @@ func TestGenerateRandomInt64InRange(t *testing.T) { for i := 0; i < 100; i++ { val := int64(generator()) - assert.Int64(val).AtMost(base + int64(delta)) - assert.Int64(val).AtLeast(base - int64(delta)) + assert(val, AtMost, base+int64(delta)) + assert(val, AtLeast, base-int64(delta)) } } diff --git a/common/protocol/user.go b/common/protocol/user.go index 3ae450191..07f08ef94 100644 --- a/common/protocol/user.go +++ b/common/protocol/user.go @@ -1,7 +1,5 @@ package protocol -import "time" - func (u *User) GetTypedAccount() (Account, error) { if u.GetAccount() == nil { return nil, newError("Account missing").AtWarning() @@ -19,20 +17,3 @@ func (u *User) GetTypedAccount() (Account, error) { } return nil, newError("Unknown account type: ", u.Account.Type) } - -func (u *User) GetSettings() UserSettings { - settings := UserSettings{} - switch u.Level { - case 0: - settings.PayloadTimeout = time.Second * 30 - case 1: - settings.PayloadTimeout = time.Minute * 2 - default: - settings.PayloadTimeout = time.Minute * 5 - } - return settings -} - -type UserSettings struct { - PayloadTimeout time.Duration -} diff --git a/common/retry/retry_test.go b/common/retry/retry_test.go index 23dd249ee..a08ec8411 100644 --- a/common/retry/retry_test.go +++ b/common/retry/retry_test.go @@ -6,7 +6,7 @@ import ( "v2ray.com/core/common/errors" . "v2ray.com/core/common/retry" - "v2ray.com/core/testing/assert" + . "v2ray.com/ext/assert" ) var ( @@ -14,7 +14,7 @@ var ( ) func TestNoRetry(t *testing.T) { - assert := assert.On(t) + assert := With(t) startTime := time.Now().Unix() err := Timed(10, 100000).On(func() error { @@ -22,12 +22,12 @@ func TestNoRetry(t *testing.T) { }) endTime := time.Now().Unix() - assert.Error(err).IsNil() - assert.Int64(endTime - startTime).AtLeast(0) + assert(err, IsNil) + assert(endTime-startTime, AtLeast, int64(0)) } func TestRetryOnce(t *testing.T) { - assert := assert.On(t) + assert := With(t) startTime := time.Now() called := 0 @@ -40,12 +40,12 @@ func TestRetryOnce(t *testing.T) { }) duration := time.Since(startTime) - assert.Error(err).IsNil() - assert.Int64(int64(duration / time.Millisecond)).AtLeast(900) + assert(err, IsNil) + assert(int64(duration/time.Millisecond), AtLeast, int64(900)) } func TestRetryMultiple(t *testing.T) { - assert := assert.On(t) + assert := With(t) startTime := time.Now() called := 0 @@ -58,12 +58,12 @@ func TestRetryMultiple(t *testing.T) { }) duration := time.Since(startTime) - assert.Error(err).IsNil() - assert.Int64(int64(duration / time.Millisecond)).AtLeast(4900) + assert(err, IsNil) + assert(int64(duration/time.Millisecond), AtLeast, int64(4900)) } func TestRetryExhausted(t *testing.T) { - assert := assert.On(t) + assert := With(t) startTime := time.Now() called := 0 @@ -73,12 +73,12 @@ func TestRetryExhausted(t *testing.T) { }) duration := time.Since(startTime) - assert.Error(errors.Cause(err)).Equals(ErrRetryFailed) - assert.Int64(int64(duration / time.Millisecond)).AtLeast(1900) + assert(errors.Cause(err), Equals, ErrRetryFailed) + assert(int64(duration/time.Millisecond), AtLeast, int64(1900)) } func TestExponentialBackoff(t *testing.T) { - assert := assert.On(t) + assert := With(t) startTime := time.Now() called := 0 @@ -88,6 +88,6 @@ func TestExponentialBackoff(t *testing.T) { }) duration := time.Since(startTime) - assert.Error(errors.Cause(err)).Equals(ErrRetryFailed) - assert.Int64(int64(duration / time.Millisecond)).AtLeast(4000) + assert(errors.Cause(err), Equals, ErrRetryFailed) + assert(int64(duration/time.Millisecond), AtLeast, int64(4000)) } diff --git a/common/serial/bytes_test.go b/common/serial/bytes_test.go index a873395c7..65245f9e0 100644 --- a/common/serial/bytes_test.go +++ b/common/serial/bytes_test.go @@ -4,11 +4,11 @@ import ( "testing" . "v2ray.com/core/common/serial" - "v2ray.com/core/testing/assert" + . "v2ray.com/ext/assert" ) func TestBytesToHex(t *testing.T) { - assert := assert.On(t) + assert := With(t) cases := []struct { input []byte @@ -21,15 +21,15 @@ func TestBytesToHex(t *testing.T) { } for _, test := range cases { - assert.String(test.output).Equals(BytesToHexString(test.input)) + assert(test.output, Equals, BytesToHexString(test.input)) } } func TestInt64(t *testing.T) { - assert := assert.On(t) + assert := With(t) x := int64(375134875348) b := Int64ToBytes(x, []byte{}) v := BytesToInt64(b) - assert.Int64(x).Equals(v) + assert(x, Equals, v) } diff --git a/common/serial/numbers_test.go b/common/serial/numbers_test.go index 9464df5b4..7d67f1edf 100644 --- a/common/serial/numbers_test.go +++ b/common/serial/numbers_test.go @@ -6,15 +6,15 @@ import ( "v2ray.com/core/common" "v2ray.com/core/common/buf" . "v2ray.com/core/common/serial" - "v2ray.com/core/testing/assert" + . "v2ray.com/ext/assert" ) func TestUint32(t *testing.T) { - assert := assert.On(t) + assert := With(t) x := uint32(458634234) s1 := Uint32ToBytes(x, []byte{}) s2 := buf.New() common.Must(s2.AppendSupplier(WriteUint32(x))) - assert.Bytes(s1).Equals(s2.Bytes()) + assert(s1, Equals, s2.Bytes()) } diff --git a/common/serial/typed_message_test.go b/common/serial/typed_message_test.go index 74da1b906..4bf7c540a 100644 --- a/common/serial/typed_message_test.go +++ b/common/serial/typed_message_test.go @@ -4,13 +4,13 @@ import ( "testing" . "v2ray.com/core/common/serial" - "v2ray.com/core/testing/assert" + . "v2ray.com/ext/assert" ) func TestGetInstance(t *testing.T) { - assert := assert.On(t) + assert := With(t) p, err := GetInstance("") - assert.Pointer(p).IsNil() - assert.Error(err).IsNotNil() + assert(p, IsNil) + assert(err, IsNotNil) } diff --git a/common/signal/exec_test.go b/common/signal/exec_test.go index e335054fb..d6bac83b5 100644 --- a/common/signal/exec_test.go +++ b/common/signal/exec_test.go @@ -6,11 +6,11 @@ import ( "testing" . "v2ray.com/core/common/signal" - "v2ray.com/core/testing/assert" + . "v2ray.com/ext/assert" ) func TestErrorOrFinish2_Error(t *testing.T) { - assert := assert.On(t) + assert := With(t) c1 := make(chan error, 1) c2 := make(chan error, 2) @@ -22,11 +22,11 @@ func TestErrorOrFinish2_Error(t *testing.T) { c1 <- errors.New("test") err := <-c - assert.String(err.Error()).Equals("test") + assert(err.Error(), Equals, "test") } func TestErrorOrFinish2_Error2(t *testing.T) { - assert := assert.On(t) + assert := With(t) c1 := make(chan error, 1) c2 := make(chan error, 2) @@ -38,11 +38,11 @@ func TestErrorOrFinish2_Error2(t *testing.T) { c2 <- errors.New("test") err := <-c - assert.String(err.Error()).Equals("test") + assert(err.Error(), Equals, "test") } func TestErrorOrFinish2_NoneError(t *testing.T) { - assert := assert.On(t) + assert := With(t) c1 := make(chan error, 1) c2 := make(chan error, 2) @@ -61,11 +61,11 @@ func TestErrorOrFinish2_NoneError(t *testing.T) { close(c2) err := <-c - assert.Error(err).IsNil() + assert(err, IsNil) } func TestErrorOrFinish2_NoneError2(t *testing.T) { - assert := assert.On(t) + assert := With(t) c1 := make(chan error, 1) c2 := make(chan error, 2) @@ -84,5 +84,5 @@ func TestErrorOrFinish2_NoneError2(t *testing.T) { close(c1) err := <-c - assert.Error(err).IsNil() + assert(err, IsNil) } diff --git a/common/signal/timer.go b/common/signal/timer.go index 21837027c..6d1d82133 100644 --- a/common/signal/timer.go +++ b/common/signal/timer.go @@ -12,8 +12,6 @@ type ActivityUpdater interface { type ActivityTimer struct { updated chan bool timeout chan time.Duration - ctx context.Context - cancel context.CancelFunc } func (t *ActivityTimer) Update() { @@ -27,7 +25,7 @@ func (t *ActivityTimer) SetTimeout(timeout time.Duration) { t.timeout <- timeout } -func (t *ActivityTimer) run() { +func (t *ActivityTimer) run(ctx context.Context, cancel context.CancelFunc) { ticker := time.NewTicker(<-t.timeout) defer func() { ticker.Stop() @@ -36,32 +34,35 @@ func (t *ActivityTimer) run() { for { select { case <-ticker.C: - case <-t.ctx.Done(): + case <-ctx.Done(): return case timeout := <-t.timeout: + if timeout == 0 { + cancel() + return + } + ticker.Stop() ticker = time.NewTicker(timeout) + continue } select { case <-t.updated: // Updated keep waiting. default: - t.cancel() + cancel() return } } } -func CancelAfterInactivity(ctx context.Context, timeout time.Duration) (context.Context, *ActivityTimer) { - ctx, cancel := context.WithCancel(ctx) +func CancelAfterInactivity(ctx context.Context, cancel context.CancelFunc, timeout time.Duration) *ActivityTimer { timer := &ActivityTimer{ - ctx: ctx, - cancel: cancel, timeout: make(chan time.Duration, 1), updated: make(chan bool, 1), } timer.timeout <- timeout - go timer.run() - return ctx, timer + go timer.run(ctx, cancel) + return timer } diff --git a/common/signal/timer_test.go b/common/signal/timer_test.go index 8c5f57e6b..a34cfbc19 100644 --- a/common/signal/timer_test.go +++ b/common/signal/timer_test.go @@ -7,26 +7,28 @@ import ( "time" . "v2ray.com/core/common/signal" - "v2ray.com/core/testing/assert" + . "v2ray.com/ext/assert" ) func TestActivityTimer(t *testing.T) { - assert := assert.On(t) + assert := With(t) - ctx, timer := CancelAfterInactivity(context.Background(), time.Second*5) + ctx, cancel := context.WithCancel(context.Background()) + timer := CancelAfterInactivity(ctx, cancel, time.Second*5) time.Sleep(time.Second * 6) - assert.Error(ctx.Err()).IsNotNil() + assert(ctx.Err(), IsNotNil) runtime.KeepAlive(timer) } func TestActivityTimerUpdate(t *testing.T) { - assert := assert.On(t) + assert := With(t) - ctx, timer := CancelAfterInactivity(context.Background(), time.Second*10) + ctx, cancel := context.WithCancel(context.Background()) + timer := CancelAfterInactivity(ctx, cancel, time.Second*10) time.Sleep(time.Second * 3) - assert.Error(ctx.Err()).IsNil() + assert(ctx.Err(), IsNil) timer.SetTimeout(time.Second * 1) time.Sleep(time.Second * 2) - assert.Error(ctx.Err()).IsNotNil() + assert(ctx.Err(), IsNotNil) runtime.KeepAlive(timer) } diff --git a/common/uuid/uuid_test.go b/common/uuid/uuid_test.go index 27d1e1499..f8b90085e 100644 --- a/common/uuid/uuid_test.go +++ b/common/uuid/uuid_test.go @@ -4,74 +4,74 @@ import ( "testing" . "v2ray.com/core/common/uuid" - "v2ray.com/core/testing/assert" + . "v2ray.com/ext/assert" ) func TestParseBytes(t *testing.T) { - assert := assert.On(t) + assert := With(t) str := "2418d087-648d-4990-86e8-19dca1d006d3" bytes := []byte{0x24, 0x18, 0xd0, 0x87, 0x64, 0x8d, 0x49, 0x90, 0x86, 0xe8, 0x19, 0xdc, 0xa1, 0xd0, 0x06, 0xd3} uuid, err := ParseBytes(bytes) - assert.Error(err).IsNil() - assert.String(uuid.String()).Equals(str) + assert(err, IsNil) + assert(uuid.String(), Equals, str) _, err = ParseBytes([]byte{1, 3, 2, 4}) - assert.Error(err).IsNotNil() + assert(err, IsNotNil) } func TestParseString(t *testing.T) { - assert := assert.On(t) + assert := With(t) str := "2418d087-648d-4990-86e8-19dca1d006d3" expectedBytes := []byte{0x24, 0x18, 0xd0, 0x87, 0x64, 0x8d, 0x49, 0x90, 0x86, 0xe8, 0x19, 0xdc, 0xa1, 0xd0, 0x06, 0xd3} uuid, err := ParseString(str) - assert.Error(err).IsNil() - assert.Bytes(uuid.Bytes()).Equals(expectedBytes) + assert(err, IsNil) + assert(uuid.Bytes(), Equals, expectedBytes) uuid, err = ParseString("2418d087") - assert.Error(err).IsNotNil() + assert(err, IsNotNil) uuid, err = ParseString("2418d087-648k-4990-86e8-19dca1d006d3") - assert.Error(err).IsNotNil() + assert(err, IsNotNil) } func TestNewUUID(t *testing.T) { - assert := assert.On(t) + assert := With(t) uuid := New() uuid2, err := ParseString(uuid.String()) - assert.Error(err).IsNil() - assert.String(uuid.String()).Equals(uuid2.String()) - assert.Bytes(uuid.Bytes()).Equals(uuid2.Bytes()) + assert(err, IsNil) + assert(uuid.String(), Equals, uuid2.String()) + assert(uuid.Bytes(), Equals, uuid2.Bytes()) } func TestRandom(t *testing.T) { - assert := assert.On(t) + assert := With(t) uuid := New() uuid2 := New() - assert.String(uuid.String()).NotEquals(uuid2.String()) - assert.Bytes(uuid.Bytes()).NotEquals(uuid2.Bytes()) + assert(uuid.String(), NotEquals, uuid2.String()) + assert(uuid.Bytes(), NotEquals, uuid2.Bytes()) } func TestEquals(t *testing.T) { - assert := assert.On(t) + assert := With(t) var uuid *UUID = nil var uuid2 *UUID = nil - assert.Bool(uuid.Equals(uuid2)).IsTrue() - assert.Bool(uuid.Equals(New())).IsFalse() + assert(uuid.Equals(uuid2), IsTrue) + assert(uuid.Equals(New()), IsFalse) } func TestNext(t *testing.T) { - assert := assert.On(t) + assert := With(t) uuid := New() uuid2 := uuid.Next() - assert.Bool(uuid.Equals(uuid2)).IsFalse() + assert(uuid.Equals(uuid2), IsFalse) } diff --git a/core.go b/core.go index f8c04ae0e..f59caa62d 100644 --- a/core.go +++ b/core.go @@ -18,9 +18,9 @@ import ( ) var ( - version = "2.41" + version = "3.1" build = "Custom" - codename = "One for all" + codename = "die Commanderin" intro = "An unified platform for anti-censorship." ) diff --git a/loader.go b/loader.go index 07ef279cc..40ebb6fc9 100644 --- a/loader.go +++ b/loader.go @@ -2,10 +2,11 @@ package core import ( "io" - "io/ioutil" + + "v2ray.com/core/common" + "v2ray.com/core/common/buf" "github.com/golang/protobuf/proto" - "v2ray.com/core/common" ) // ConfigLoader is an utility to load V2Ray config from external source. @@ -30,7 +31,10 @@ func LoadConfig(format ConfigFormat, input io.Reader) (*Config, error) { func loadProtobufConfig(input io.Reader) (*Config, error) { config := new(Config) - data, _ := ioutil.ReadAll(input) + data, err := buf.ReadAllToBytes(input) + if err != nil { + return nil, err + } if err := proto.Unmarshal(data, config); err != nil { return nil, err } diff --git a/main/config_json.go b/main/config_json.go index bf0093df4..6a826d7ac 100644 --- a/main/config_json.go +++ b/main/config_json.go @@ -1,5 +1,47 @@ -// +build json - package main -import _ "v2ray.com/core/tools/conf" +import ( + "io" + "os" + "os/exec" + + "v2ray.com/core" + "v2ray.com/core/common/platform" +) + +func jsonToProto(input io.Reader) (*core.Config, error) { + v2ctl := platform.GetToolLocation("v2ctl") + _, err := os.Stat(v2ctl) + if err != nil { + return nil, err + } + cmd := exec.Command(v2ctl, "config") + cmd.Stdin = input + cmd.Stderr = os.Stderr + + stdoutReader, err := cmd.StdoutPipe() + if err != nil { + return nil, err + } + defer stdoutReader.Close() + + if err := cmd.Start(); err != nil { + return nil, err + } + + config, err := core.LoadConfig(core.ConfigFormat_Protobuf, stdoutReader) + + cmd.Wait() + + return config, err +} + +func init() { + core.RegisterConfigLoader(core.ConfigFormat_JSON, func(input io.Reader) (*core.Config, error) { + config, err := jsonToProto(input) + if err != nil { + return nil, newError("failed to execute v2ctl to convert config file.").Base(err) + } + return config, nil + }) +} diff --git a/main/distro/all/all.go b/main/distro/all/all.go index 8b51f1d13..800853bb7 100644 --- a/main/distro/all/all.go +++ b/main/distro/all/all.go @@ -4,6 +4,7 @@ import ( // The following are necessary as they register handlers in their init functions. _ "v2ray.com/core/app/dispatcher/impl" _ "v2ray.com/core/app/dns/server" + _ "v2ray.com/core/app/policy/manager" _ "v2ray.com/core/app/proxyman/inbound" _ "v2ray.com/core/app/proxyman/outbound" _ "v2ray.com/core/app/router" diff --git a/main/main.go b/main/main.go index de5bdb40e..84bc1bf96 100644 --- a/main/main.go +++ b/main/main.go @@ -22,6 +22,7 @@ var ( version = flag.Bool("version", false, "Show current version of V2Ray.") test = flag.Bool("test", false, "Test config file only, without launching V2Ray server.") format = flag.String("format", "json", "Format of input file.") + plugin = flag.Bool("plugin", false, "True to load plugins.") ) func init() { @@ -67,7 +68,7 @@ func startV2Ray() (core.Server, error) { server, err := core.New(config) if err != nil { - return nil, newError("failed to create initialize").Base(err) + return nil, newError("failed to create server").Base(err) } return server, nil @@ -82,19 +83,27 @@ func main() { return } + if *plugin { + if err := core.LoadPlugins(); err != nil { + fmt.Println("Failed to load plugins:", err.Error()) + os.Exit(-1) + } + } + server, err := startV2Ray() if err != nil { fmt.Println(err.Error()) - return + os.Exit(-1) } if *test { fmt.Println("Configuration OK.") - return + os.Exit(0) } if err := server.Start(); err != nil { fmt.Println("Failed to start", err) + os.Exit(-1) } osSignals := make(chan os.Signal, 1) diff --git a/plugin.go b/plugin.go new file mode 100644 index 000000000..8d4388e42 --- /dev/null +++ b/plugin.go @@ -0,0 +1,18 @@ +package core + +// PluginMetadata contains some brief information regarding a plugin. +type PluginMetadata struct { + // Name of the plugin + Name string +} + +// GetMetadataFuncName is the name of the function in the plugin to return PluginMetadata. +const GetMetadataFuncName = "GetPluginMetadata" + +// GetMetadataFunc is the type of the function in the plugin to return PluginMetadata. +type GetMetadataFunc func() PluginMetadata + +// LoadPlugins loads all possible plugins in the 'plugin' directory. +func LoadPlugins() error { + return loadPluginsInternal() +} diff --git a/plugin_linux.go b/plugin_linux.go new file mode 100644 index 000000000..72673b9ed --- /dev/null +++ b/plugin_linux.go @@ -0,0 +1,47 @@ +// +build linux + +package core + +import ( + "os" + "path/filepath" + "plugin" + "strings" + + "v2ray.com/core/app/log" + "v2ray.com/core/common/platform" +) + +func loadPluginsInternal() error { + pluginPath := platform.GetPluginDirectory() + + dir, err := os.Open(pluginPath) + if err != nil { + return err + } + defer dir.Close() + + files, err := dir.Readdir(-1) + if err != nil { + return err + } + + for _, file := range files { + if !file.IsDir() && strings.HasSuffix(file.Name(), ".so") { + p, err := plugin.Open(filepath.Join(pluginPath, file.Name())) + if err != nil { + return err + } + f, err := p.Lookup(GetMetadataFuncName) + if err != nil { + return err + } + if gmf, ok := f.(GetMetadataFunc); ok { + metadata := gmf() + log.Trace(newError("plugin (", metadata.Name, ") loaded.")) + } + } + } + + return nil +} diff --git a/plugin_other.go b/plugin_other.go new file mode 100644 index 000000000..183869a67 --- /dev/null +++ b/plugin_other.go @@ -0,0 +1,7 @@ +// +build !linux + +package core + +func loadPluginsInternal() error { + return nil +} diff --git a/proxy/blackhole/blackhole.go b/proxy/blackhole/blackhole.go index ce3fe63a1..b324a97ab 100644 --- a/proxy/blackhole/blackhole.go +++ b/proxy/blackhole/blackhole.go @@ -29,8 +29,8 @@ func New(ctx context.Context, config *Config) (*Handler, error) { } // Process implements OutboundHandler.Dispatch(). -func (v *Handler) Process(ctx context.Context, outboundRay ray.OutboundRay, dialer proxy.Dialer) error { - v.response.WriteTo(outboundRay.OutboundOutput()) +func (h *Handler) Process(ctx context.Context, outboundRay ray.OutboundRay, dialer proxy.Dialer) error { + h.response.WriteTo(outboundRay.OutboundOutput()) // Sleep a little here to make sure the response is sent to client. time.Sleep(time.Second) outboundRay.OutboundOutput().CloseError() diff --git a/proxy/blackhole/config.go b/proxy/blackhole/config.go index 2c27a344d..5bfd3290e 100644 --- a/proxy/blackhole/config.go +++ b/proxy/blackhole/config.go @@ -1,6 +1,7 @@ package blackhole import ( + "v2ray.com/core/common" "v2ray.com/core/common/buf" "v2ray.com/core/common/serial" ) @@ -27,8 +28,8 @@ func (*NoneResponse) WriteTo(buf.Writer) {} // WriteTo implements ResponseConfig.WriteTo(). func (*HTTPResponse) WriteTo(writer buf.Writer) { b := buf.NewLocal(512) - b.AppendSupplier(serial.WriteString(http403response)) - writer.Write(buf.NewMultiBufferValue(b)) + common.Must(b.AppendSupplier(serial.WriteString(http403response))) + writer.WriteMultiBuffer(buf.NewMultiBufferValue(b)) } // GetInternalResponse converts response settings from proto to internal data structure. diff --git a/proxy/blackhole/config_test.go b/proxy/blackhole/config_test.go index 7678d7cf6..1e5ad3525 100644 --- a/proxy/blackhole/config_test.go +++ b/proxy/blackhole/config_test.go @@ -7,11 +7,11 @@ import ( "v2ray.com/core/common/buf" . "v2ray.com/core/proxy/blackhole" - "v2ray.com/core/testing/assert" + . "v2ray.com/ext/assert" ) func TestHTTPResponse(t *testing.T) { - assert := assert.On(t) + assert := With(t) buffer := buf.New() @@ -20,6 +20,6 @@ func TestHTTPResponse(t *testing.T) { reader := bufio.NewReader(buffer) response, err := http.ReadResponse(reader, nil) - assert.Error(err).IsNil() - assert.Int(response.StatusCode).Equals(403) + assert(err, IsNil) + assert(response.StatusCode, Equals, 403) } diff --git a/proxy/context.go b/proxy/context.go index f0400a65c..c3a1378c1 100644 --- a/proxy/context.go +++ b/proxy/context.go @@ -17,10 +17,12 @@ const ( resolvedIPsKey ) +// ContextWithSource creates a new context with given source. func ContextWithSource(ctx context.Context, src net.Destination) context.Context { return context.WithValue(ctx, sourceKey, src) } +// SourceFromContext retreives source from the given context. func SourceFromContext(ctx context.Context) (net.Destination, bool) { v, ok := ctx.Value(sourceKey).(net.Destination) return v, ok @@ -62,11 +64,15 @@ func InboundTagFromContext(ctx context.Context) (string, bool) { return v, ok } -func ContextWithResolveIPs(ctx context.Context, ips []net.Address) context.Context { - return context.WithValue(ctx, resolvedIPsKey, ips) +type IPResolver interface { + Resolve() []net.Address } -func ResolvedIPsFromContext(ctx context.Context) ([]net.Address, bool) { - ips, ok := ctx.Value(resolvedIPsKey).([]net.Address) +func ContextWithResolveIPs(ctx context.Context, f IPResolver) context.Context { + return context.WithValue(ctx, resolvedIPsKey, f) +} + +func ResolvedIPsFromContext(ctx context.Context) (IPResolver, bool) { + ips, ok := ctx.Value(resolvedIPsKey).(IPResolver) return ips, ok } diff --git a/proxy/dokodemo/config.pb.go b/proxy/dokodemo/config.pb.go index f4e8d36ff..c55306b8f 100644 --- a/proxy/dokodemo/config.pb.go +++ b/proxy/dokodemo/config.pb.go @@ -23,6 +23,7 @@ type Config struct { NetworkList *v2ray_core_common_net1.NetworkList `protobuf:"bytes,3,opt,name=network_list,json=networkList" json:"network_list,omitempty"` Timeout uint32 `protobuf:"varint,4,opt,name=timeout" json:"timeout,omitempty"` FollowRedirect bool `protobuf:"varint,5,opt,name=follow_redirect,json=followRedirect" json:"follow_redirect,omitempty"` + UserLevel uint32 `protobuf:"varint,6,opt,name=user_level,json=userLevel" json:"user_level,omitempty"` } func (m *Config) Reset() { *m = Config{} } @@ -65,6 +66,13 @@ func (m *Config) GetFollowRedirect() bool { return false } +func (m *Config) GetUserLevel() uint32 { + if m != nil { + return m.UserLevel + } + return 0 +} + func init() { proto.RegisterType((*Config)(nil), "v2ray.core.proxy.dokodemo.Config") } @@ -72,23 +80,25 @@ func init() { func init() { proto.RegisterFile("v2ray.com/core/proxy/dokodemo/config.proto", fileDescriptor0) } var fileDescriptor0 = []byte{ - // 286 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x7c, 0x90, 0xcf, 0x4a, 0x03, 0x31, - 0x10, 0x87, 0x49, 0xad, 0x6d, 0x49, 0xfd, 0x03, 0x39, 0xa5, 0x82, 0x50, 0x7b, 0x69, 0xf1, 0x90, - 0x40, 0x3d, 0x7a, 0xb3, 0x15, 0x11, 0x44, 0x97, 0x1c, 0x3c, 0x78, 0x29, 0x6b, 0x36, 0x95, 0xd0, - 0x4d, 0x66, 0x99, 0x8d, 0xd6, 0x7d, 0x25, 0x5f, 0xcb, 0x17, 0x11, 0xb3, 0xbb, 0x28, 0x42, 0xbd, - 0xcd, 0x4c, 0xbe, 0x7c, 0x33, 0xfc, 0xe8, 0xf9, 0xdb, 0x1c, 0xd3, 0x4a, 0x68, 0x70, 0x52, 0x03, - 0x1a, 0x59, 0x20, 0xbc, 0x57, 0x32, 0x83, 0x0d, 0x64, 0xc6, 0x81, 0xd4, 0xe0, 0xd7, 0xf6, 0x45, - 0x14, 0x08, 0x01, 0xd8, 0xa8, 0x65, 0xd1, 0x88, 0xc8, 0x89, 0x96, 0x3b, 0x99, 0xfe, 0xd1, 0x68, - 0x70, 0x0e, 0xbc, 0xf4, 0x26, 0xc8, 0x34, 0xcb, 0xd0, 0x94, 0x65, 0xed, 0xf8, 0x0f, 0xf4, 0x26, - 0x6c, 0x01, 0x37, 0x35, 0x38, 0xf9, 0x24, 0xb4, 0xb7, 0x88, 0xdb, 0xd9, 0x25, 0xed, 0x37, 0x12, - 0x4e, 0xc6, 0x64, 0x36, 0x9c, 0x9f, 0x89, 0x5f, 0x97, 0xd4, 0x06, 0xe1, 0x4d, 0x10, 0xb7, 0xc9, - 0x03, 0x2e, 0xc1, 0xa5, 0xd6, 0xab, 0xf6, 0x07, 0x63, 0xb4, 0x5b, 0x00, 0x06, 0xde, 0x19, 0x93, - 0xd9, 0xa1, 0x8a, 0x35, 0xbb, 0xa6, 0x07, 0xcd, 0xb2, 0x55, 0x6e, 0xcb, 0xc0, 0xf7, 0xa2, 0x75, - 0xb2, 0xc3, 0x7a, 0x5f, 0xa3, 0x77, 0xb6, 0x0c, 0x6a, 0xe8, 0x7f, 0x1a, 0xc6, 0x69, 0x3f, 0x58, - 0x67, 0xe0, 0x35, 0xf0, 0x6e, 0xb4, 0xb7, 0x2d, 0x9b, 0xd2, 0xe3, 0x35, 0xe4, 0x39, 0x6c, 0x57, - 0x68, 0x32, 0x8b, 0x46, 0x07, 0xbe, 0x3f, 0x26, 0xb3, 0x81, 0x3a, 0xaa, 0xc7, 0xaa, 0x99, 0x5e, - 0xdd, 0xd0, 0x53, 0x0d, 0x4e, 0xec, 0x0c, 0x36, 0x21, 0x4f, 0x83, 0xb6, 0xfe, 0xe8, 0x8c, 0x1e, - 0xe7, 0x2a, 0xad, 0xc4, 0xe2, 0x9b, 0x4b, 0x22, 0xb7, 0x6c, 0xde, 0x9e, 0x7b, 0x31, 0xb5, 0x8b, - 0xaf, 0x00, 0x00, 0x00, 0xff, 0xff, 0xf9, 0x1c, 0xb0, 0xd9, 0xd0, 0x01, 0x00, 0x00, + // 310 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x7c, 0x90, 0xcf, 0x4e, 0xc2, 0x40, + 0x10, 0x87, 0xd3, 0x8a, 0x80, 0x8b, 0x7f, 0x92, 0x3d, 0x2d, 0x46, 0x12, 0xe4, 0x02, 0xf1, 0xb0, + 0x4d, 0xf0, 0xe8, 0x0d, 0x30, 0xc6, 0x84, 0x28, 0xd9, 0x83, 0x07, 0x2f, 0xa4, 0xb6, 0x83, 0x69, + 0xe8, 0xee, 0x90, 0xe9, 0x02, 0xf6, 0x05, 0x7c, 0x18, 0x9f, 0xd2, 0x74, 0xdb, 0x46, 0x63, 0x82, + 0xb7, 0xd9, 0xdf, 0x7e, 0xf3, 0xcd, 0x64, 0xd8, 0xcd, 0x6e, 0x4c, 0x61, 0x2e, 0x23, 0xd4, 0x41, + 0x84, 0x04, 0xc1, 0x86, 0xf0, 0x23, 0x0f, 0x62, 0x5c, 0x63, 0x0c, 0x1a, 0x83, 0x08, 0xcd, 0x2a, + 0x79, 0x97, 0x1b, 0x42, 0x8b, 0xbc, 0x5b, 0xb3, 0x04, 0xd2, 0x71, 0xb2, 0xe6, 0x2e, 0x87, 0x7f, + 0x34, 0x11, 0x6a, 0x8d, 0x26, 0x30, 0x60, 0x83, 0x30, 0x8e, 0x09, 0xb2, 0xac, 0x74, 0xfc, 0x07, + 0x1a, 0xb0, 0x7b, 0xa4, 0x75, 0x09, 0x0e, 0x3e, 0x7d, 0xd6, 0x9c, 0xba, 0xe9, 0xfc, 0x8e, 0xb5, + 0x2a, 0x89, 0xf0, 0xfa, 0xde, 0xa8, 0x33, 0xbe, 0x96, 0xbf, 0x36, 0x29, 0x0d, 0xd2, 0x80, 0x95, + 0x8f, 0x8b, 0x67, 0x9a, 0xa1, 0x0e, 0x13, 0xa3, 0xea, 0x0e, 0xce, 0x59, 0x63, 0x83, 0x64, 0x85, + 0xdf, 0xf7, 0x46, 0x67, 0xca, 0xd5, 0xfc, 0x9e, 0x9d, 0x56, 0xc3, 0x96, 0x69, 0x92, 0x59, 0x71, + 0xe4, 0xac, 0x83, 0x03, 0xd6, 0xa7, 0x12, 0x9d, 0x27, 0x99, 0x55, 0x1d, 0xf3, 0xf3, 0xe0, 0x57, + 0xac, 0x65, 0x13, 0x0d, 0xb8, 0xb5, 0xa2, 0x51, 0xd8, 0x27, 0xbe, 0xf0, 0x54, 0x1d, 0xf1, 0x21, + 0xbb, 0x58, 0x61, 0x9a, 0xe2, 0x7e, 0x49, 0x10, 0x27, 0x04, 0x91, 0x15, 0xc7, 0x7d, 0x6f, 0xd4, + 0x56, 0xe7, 0x65, 0xac, 0xaa, 0x94, 0xf7, 0x18, 0xdb, 0x66, 0x40, 0xcb, 0x14, 0x76, 0x90, 0x8a, + 0xa6, 0xdb, 0xf3, 0xa4, 0x48, 0xe6, 0x45, 0x30, 0x79, 0x60, 0xbd, 0x08, 0xb5, 0x3c, 0x78, 0xfb, + 0x85, 0xf7, 0xda, 0xae, 0xeb, 0x2f, 0xbf, 0xfb, 0x32, 0x56, 0x61, 0x2e, 0xa7, 0x05, 0xb7, 0x70, + 0xdc, 0xac, 0xfa, 0x7b, 0x6b, 0xba, 0xc3, 0xde, 0x7e, 0x07, 0x00, 0x00, 0xff, 0xff, 0x33, 0x8e, + 0x70, 0xce, 0xf3, 0x01, 0x00, 0x00, } diff --git a/proxy/dokodemo/config.proto b/proxy/dokodemo/config.proto index d3cd6df16..19a07dcb3 100644 --- a/proxy/dokodemo/config.proto +++ b/proxy/dokodemo/config.proto @@ -13,6 +13,7 @@ message Config { v2ray.core.common.net.IPOrDomain address = 1; uint32 port = 2; v2ray.core.common.net.NetworkList network_list = 3; - uint32 timeout = 4; + uint32 timeout = 4 [deprecated = true]; bool follow_redirect = 5; + uint32 user_level = 6; } \ No newline at end of file diff --git a/proxy/dokodemo/dokodemo.go b/proxy/dokodemo/dokodemo.go index 23819e2b5..8c1c0083f 100644 --- a/proxy/dokodemo/dokodemo.go +++ b/proxy/dokodemo/dokodemo.go @@ -4,24 +4,25 @@ package dokodemo import ( "context" - "runtime" - "time" "v2ray.com/core/app" "v2ray.com/core/app/dispatcher" "v2ray.com/core/app/log" + "v2ray.com/core/app/policy" "v2ray.com/core/common" "v2ray.com/core/common/buf" "v2ray.com/core/common/net" "v2ray.com/core/common/signal" "v2ray.com/core/proxy" "v2ray.com/core/transport/internet" + "v2ray.com/core/transport/internet/udp" ) type DokodemoDoor struct { config *Config address net.Address port net.Port + policy policy.Policy } func New(ctx context.Context, config *Config) (*DokodemoDoor, error) { @@ -37,6 +38,17 @@ func New(ctx context.Context, config *Config) (*DokodemoDoor, error) { address: config.GetPredefinedAddress(), port: net.Port(config.Port), } + space.On(app.SpaceInitializing, func(interface{}) error { + pm := policy.FromSpace(space) + if pm == nil { + return newError("Policy not found in space.") + } + d.policy = pm.GetPolicy(config.UserLevel) + if config.Timeout > 0 && config.UserLevel == 0 { + d.policy.Timeout.ConnectionIdle.Value = config.Timeout + } + return nil + }) return d, nil } @@ -60,11 +72,8 @@ func (d *DokodemoDoor) Process(ctx context.Context, network net.Network, conn in return newError("unable to get destination") } - timeout := time.Second * time.Duration(d.config.Timeout) - if timeout == 0 { - timeout = time.Minute * 5 - } - ctx, timer := signal.CancelAfterInactivity(ctx, timeout) + ctx, cancel := context.WithCancel(ctx) + timer := signal.CancelAfterInactivity(ctx, cancel, d.policy.Timeout.ConnectionIdle.Duration()) inboundRay, err := dispatcher.Dispatch(ctx, dest) if err != nil { @@ -80,6 +89,8 @@ func (d *DokodemoDoor) Process(ctx context.Context, network net.Network, conn in return newError("failed to transport request").Base(err) } + timer.SetTimeout(d.policy.Timeout.DownlinkOnly.Duration()) + return nil }) @@ -88,14 +99,24 @@ func (d *DokodemoDoor) Process(ctx context.Context, network net.Network, conn in if network == net.Network_TCP { writer = buf.NewWriter(conn) } else { - writer = buf.NewSequentialWriter(conn) + //if we are in TPROXY mode, use linux's udp forging functionality + if !d.config.FollowRedirect { + writer = buf.NewSequentialWriter(conn) + } else { + srca := net.UDPAddr{IP: dest.Address.IP(), Port: int(dest.Port.Value())} + origsend, err := udp.TransmitSocket(&srca, conn.RemoteAddr()) + if err != nil { + return err + } + writer = buf.NewSequentialWriter(origsend) + } } if err := buf.Copy(inboundRay.InboundOutput(), writer, buf.UpdateActivity(timer)); err != nil { return newError("failed to transport response").Base(err) } - timer.SetTimeout(time.Second * 2) + timer.SetTimeout(d.policy.Timeout.UplinkOnly.Duration()) return nil }) @@ -106,8 +127,6 @@ func (d *DokodemoDoor) Process(ctx context.Context, network net.Network, conn in return newError("connection ends").Base(err) } - runtime.KeepAlive(timer) - return nil } diff --git a/proxy/freedom/config.pb.go b/proxy/freedom/config.pb.go index cd1e925dd..7da98e3e7 100644 --- a/proxy/freedom/config.pb.go +++ b/proxy/freedom/config.pb.go @@ -57,6 +57,7 @@ type Config struct { DomainStrategy Config_DomainStrategy `protobuf:"varint,1,opt,name=domain_strategy,json=domainStrategy,enum=v2ray.core.proxy.freedom.Config_DomainStrategy" json:"domain_strategy,omitempty"` Timeout uint32 `protobuf:"varint,2,opt,name=timeout" json:"timeout,omitempty"` DestinationOverride *DestinationOverride `protobuf:"bytes,3,opt,name=destination_override,json=destinationOverride" json:"destination_override,omitempty"` + UserLevel uint32 `protobuf:"varint,4,opt,name=user_level,json=userLevel" json:"user_level,omitempty"` } func (m *Config) Reset() { *m = Config{} } @@ -85,6 +86,13 @@ func (m *Config) GetDestinationOverride() *DestinationOverride { return nil } +func (m *Config) GetUserLevel() uint32 { + if m != nil { + return m.UserLevel + } + return 0 +} + func init() { proto.RegisterType((*DestinationOverride)(nil), "v2ray.core.proxy.freedom.DestinationOverride") proto.RegisterType((*Config)(nil), "v2ray.core.proxy.freedom.Config") @@ -94,25 +102,27 @@ func init() { func init() { proto.RegisterFile("v2ray.com/core/proxy/freedom/config.proto", fileDescriptor0) } var fileDescriptor0 = []byte{ - // 318 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x74, 0x90, 0xcf, 0x4a, 0xc3, 0x40, - 0x10, 0xc6, 0x4d, 0xc5, 0x14, 0x47, 0xac, 0x65, 0xeb, 0x21, 0x88, 0x87, 0xd2, 0x8b, 0x55, 0x70, - 0x23, 0xf1, 0x09, 0xec, 0x1f, 0xa1, 0x27, 0x4b, 0x82, 0xa2, 0x5e, 0x62, 0xcc, 0x4e, 0xcb, 0x82, - 0xd9, 0x09, 0x9b, 0xb5, 0x98, 0x27, 0xf0, 0x5d, 0x7c, 0x4a, 0x71, 0x93, 0xa2, 0x55, 0x73, 0xdb, - 0x99, 0xfd, 0x7d, 0xdf, 0xcc, 0x37, 0x70, 0xba, 0x0a, 0x74, 0x52, 0xf2, 0x94, 0x32, 0x3f, 0x25, - 0x8d, 0x7e, 0xae, 0xe9, 0xad, 0xf4, 0x17, 0x1a, 0x51, 0xd8, 0x96, 0x5a, 0xc8, 0x25, 0xcf, 0x35, - 0x19, 0x62, 0xde, 0x1a, 0xd5, 0xc8, 0x2d, 0xc6, 0x6b, 0xec, 0xe8, 0xe2, 0x97, 0x49, 0x4a, 0x59, - 0x46, 0xca, 0xb7, 0xb2, 0x94, 0x5e, 0xfc, 0x02, 0xf5, 0x0a, 0x75, 0x5c, 0xe4, 0x98, 0x56, 0x5e, - 0x83, 0x07, 0xe8, 0x4d, 0xb0, 0x30, 0x52, 0x25, 0x46, 0x92, 0xba, 0x59, 0xa1, 0xd6, 0x52, 0x20, - 0x1b, 0x81, 0x5b, 0xb1, 0x9e, 0xd3, 0x77, 0x86, 0x7b, 0xc1, 0x19, 0xff, 0x31, 0xb3, 0x72, 0xe5, - 0x6b, 0x57, 0x1e, 0x59, 0x72, 0xaa, 0x44, 0x4e, 0x52, 0x99, 0xb0, 0x56, 0x0e, 0xde, 0x5b, 0xe0, - 0x8e, 0xed, 0xde, 0xec, 0x1e, 0x0e, 0x04, 0x65, 0x89, 0x54, 0x71, 0x61, 0x74, 0x62, 0x70, 0x59, - 0x5a, 0xdf, 0x4e, 0xe0, 0xf3, 0xa6, 0x2c, 0xbc, 0x92, 0xf2, 0x89, 0xd5, 0x45, 0xb5, 0x2c, 0xec, - 0x88, 0x8d, 0x9a, 0x79, 0xd0, 0x36, 0x32, 0x43, 0x7a, 0x35, 0x5e, 0xab, 0xef, 0x0c, 0xf7, 0xc3, - 0x75, 0xc9, 0x9e, 0xe0, 0x50, 0x7c, 0x27, 0x8b, 0xa9, 0x8e, 0xe6, 0x6d, 0xdb, 0x40, 0xe7, 0xcd, - 0x83, 0xff, 0xb9, 0x47, 0xd8, 0x13, 0x7f, 0x9b, 0x83, 0x13, 0xe8, 0x6c, 0x6e, 0xc7, 0x76, 0x61, - 0xe7, 0x2a, 0x8a, 0x67, 0x51, 0x77, 0x8b, 0x01, 0xb8, 0xb7, 0xd1, 0x34, 0x9e, 0xcd, 0xbb, 0xce, - 0x68, 0x02, 0xc7, 0x29, 0x65, 0x8d, 0x13, 0xe7, 0xce, 0x63, 0xbb, 0x7e, 0x7e, 0xb4, 0xbc, 0xbb, - 0x20, 0x4c, 0x4a, 0x3e, 0xfe, 0xa2, 0xe6, 0x96, 0xba, 0xae, 0xbe, 0x9e, 0x5d, 0x7b, 0xf0, 0xcb, - 0xcf, 0x00, 0x00, 0x00, 0xff, 0xff, 0x45, 0xb3, 0x84, 0x2e, 0x2a, 0x02, 0x00, 0x00, + // 340 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x74, 0x91, 0x6f, 0x4b, 0x83, 0x50, + 0x14, 0xc6, 0xd3, 0xca, 0xb1, 0x13, 0xad, 0xe1, 0x7a, 0x21, 0xb1, 0x60, 0xec, 0x4d, 0x2b, 0xe8, + 0x1a, 0xf6, 0x09, 0xda, 0x9f, 0x60, 0x10, 0x34, 0x94, 0xa2, 0x7a, 0x63, 0xa6, 0x67, 0x43, 0x98, + 0xf7, 0xc8, 0xf5, 0x4e, 0xf2, 0x2b, 0xed, 0x53, 0x86, 0x57, 0x47, 0x2d, 0xb6, 0x77, 0xfa, 0xf8, + 0x7b, 0x9e, 0x73, 0x9e, 0x23, 0x5c, 0xe7, 0x8e, 0x08, 0x0a, 0x16, 0x52, 0x62, 0x87, 0x24, 0xd0, + 0x4e, 0x05, 0x7d, 0x17, 0xf6, 0x5c, 0x20, 0x46, 0x4a, 0xe2, 0xf3, 0x78, 0xc1, 0x52, 0x41, 0x92, + 0x4c, 0x6b, 0x83, 0x0a, 0x64, 0x0a, 0x63, 0x35, 0x76, 0x71, 0xf7, 0x2f, 0x24, 0xa4, 0x24, 0x21, + 0x6e, 0x2b, 0x5b, 0x48, 0x4b, 0x3b, 0x43, 0x91, 0xa3, 0xf0, 0xb3, 0x14, 0xc3, 0x2a, 0xab, 0xff, + 0x0e, 0x9d, 0x31, 0x66, 0x32, 0xe6, 0x81, 0x8c, 0x89, 0x3f, 0xe7, 0x28, 0x44, 0x1c, 0xa1, 0x39, + 0x04, 0xa3, 0x62, 0x2d, 0xad, 0xa7, 0x0d, 0x4e, 0x9c, 0x1b, 0xf6, 0x67, 0x66, 0x95, 0xca, 0x36, + 0xa9, 0xcc, 0x53, 0xe4, 0x84, 0x47, 0x29, 0xc5, 0x5c, 0xba, 0xb5, 0xb3, 0xbf, 0xd6, 0xc1, 0x18, + 0xa9, 0xbd, 0xcd, 0x37, 0x38, 0x8b, 0x28, 0x09, 0x62, 0xee, 0x67, 0x52, 0x04, 0x12, 0x17, 0x85, + 0xca, 0x6d, 0x39, 0x36, 0xdb, 0xd7, 0x85, 0x55, 0x56, 0x36, 0x56, 0x3e, 0xaf, 0xb6, 0xb9, 0xad, + 0x68, 0xeb, 0xdd, 0xec, 0x42, 0x43, 0xc6, 0x09, 0xd2, 0x4a, 0x5a, 0x7a, 0x4f, 0x1b, 0x9c, 0x0e, + 0x75, 0x4b, 0x73, 0x37, 0x92, 0xf9, 0x09, 0xe7, 0xd1, 0x6f, 0x3b, 0x9f, 0xea, 0x7a, 0xd6, 0xa1, + 0x2a, 0x75, 0xbb, 0x7f, 0xf8, 0x8e, 0x9b, 0xb8, 0x9d, 0x68, 0xc7, 0xa1, 0x2e, 0x01, 0x56, 0x19, + 0x0a, 0x7f, 0x89, 0x39, 0x2e, 0xad, 0xa3, 0x72, 0x05, 0xb7, 0x59, 0x2a, 0x4f, 0xa5, 0xd0, 0xbf, + 0x82, 0xd6, 0x76, 0x01, 0xb3, 0x09, 0xc7, 0x0f, 0x9e, 0x3f, 0xf5, 0xda, 0x07, 0x26, 0x80, 0xf1, + 0xe2, 0x4d, 0xfc, 0xe9, 0xac, 0xad, 0x0d, 0xc7, 0xd0, 0x0d, 0x29, 0xd9, 0xbb, 0xd0, 0x4c, 0xfb, + 0x68, 0xd4, 0x8f, 0x6b, 0xdd, 0x7a, 0x75, 0xdc, 0xa0, 0x60, 0xa3, 0x92, 0x9a, 0x29, 0xea, 0xb1, + 0xfa, 0xf4, 0x65, 0xa8, 0x7f, 0x72, 0xff, 0x13, 0x00, 0x00, 0xff, 0xff, 0xb7, 0x5e, 0xda, 0x4d, + 0x4d, 0x02, 0x00, 0x00, } diff --git a/proxy/freedom/config.proto b/proxy/freedom/config.proto index ec4764e4b..e90c78eba 100644 --- a/proxy/freedom/config.proto +++ b/proxy/freedom/config.proto @@ -18,6 +18,7 @@ message Config { USE_IP = 1; } DomainStrategy domain_strategy = 1; - uint32 timeout = 2; + uint32 timeout = 2 [deprecated = true]; DestinationOverride destination_override = 3; + uint32 user_level = 4; } diff --git a/proxy/freedom/freedom.go b/proxy/freedom/freedom.go index 7df958b7d..0fbe4f400 100644 --- a/proxy/freedom/freedom.go +++ b/proxy/freedom/freedom.go @@ -4,12 +4,11 @@ package freedom import ( "context" - "runtime" - "time" "v2ray.com/core/app" "v2ray.com/core/app/dns" "v2ray.com/core/app/log" + "v2ray.com/core/app/policy" "v2ray.com/core/common" "v2ray.com/core/common/buf" "v2ray.com/core/common/dice" @@ -21,13 +20,16 @@ import ( "v2ray.com/core/transport/ray" ) +// Handler handles Freedom connections. type Handler struct { domainStrategy Config_DomainStrategy timeout uint32 dns dns.Server destOverride *DestinationOverride + policy policy.Policy } +// New creates a new Freedom handler. func New(ctx context.Context, config *Config) (*Handler, error) { space := app.SpaceFromContext(ctx) if space == nil { @@ -38,43 +40,47 @@ func New(ctx context.Context, config *Config) (*Handler, error) { timeout: config.Timeout, destOverride: config.DestinationOverride, } - space.OnInitialize(func() error { + space.On(app.SpaceInitializing, func(interface{}) error { if config.DomainStrategy == Config_USE_IP { f.dns = dns.FromSpace(space) if f.dns == nil { return newError("DNS server is not found in the space") } } + pm := policy.FromSpace(space) + if pm == nil { + return newError("Policy not found in space.") + } + f.policy = pm.GetPolicy(config.UserLevel) + if config.Timeout > 0 && config.UserLevel == 0 { + f.policy.Timeout.ConnectionIdle.Value = config.Timeout + } return nil }) return f, nil } -func (v *Handler) ResolveIP(destination net.Destination) net.Destination { - if !destination.Address.Family().IsDomain() { - return destination +func (h *Handler) resolveIP(ctx context.Context, domain string) net.Address { + if resolver, ok := proxy.ResolvedIPsFromContext(ctx); ok { + ips := resolver.Resolve() + if len(ips) == 0 { + return nil + } + return ips[dice.Roll(len(ips))] } - ips := v.dns.Get(destination.Address.Domain()) + ips := h.dns.Get(domain) if len(ips) == 0 { - log.Trace(newError("DNS returns nil answer. Keep domain as is.")) - return destination + return nil } - - ip := ips[dice.Roll(len(ips))] - newDest := net.Destination{ - Network: destination.Network, - Address: net.IPAddress(ip), - Port: destination.Port, - } - log.Trace(newError("changing destination from ", destination, " to ", newDest)) - return newDest + return net.IPAddress(ips[dice.Roll(len(ips))]) } -func (v *Handler) Process(ctx context.Context, outboundRay ray.OutboundRay, dialer proxy.Dialer) error { +// Process implements proxy.Outbound. +func (h *Handler) Process(ctx context.Context, outboundRay ray.OutboundRay, dialer proxy.Dialer) error { destination, _ := proxy.TargetFromContext(ctx) - if v.destOverride != nil { - server := v.destOverride.Server + if h.destOverride != nil { + server := h.destOverride.Server destination = net.Destination{ Network: destination.Network, Address: server.Address.AsAddress(), @@ -86,11 +92,19 @@ func (v *Handler) Process(ctx context.Context, outboundRay ray.OutboundRay, dial input := outboundRay.OutboundInput() output := outboundRay.OutboundOutput() - var conn internet.Connection - if v.domainStrategy == Config_USE_IP && destination.Address.Family().IsDomain() { - destination = v.ResolveIP(destination) + if h.domainStrategy == Config_USE_IP && destination.Address.Family().IsDomain() { + ip := h.resolveIP(ctx, destination.Address.Domain()) + if ip != nil { + destination = net.Destination{ + Network: destination.Network, + Address: ip, + Port: destination.Port, + } + log.Trace(newError("changing destination to ", destination)) + } } + var conn internet.Connection err := retry.ExponentialBackoff(5, 100).On(func() error { rawConn, err := dialer.Dial(ctx, destination) if err != nil { @@ -104,11 +118,8 @@ func (v *Handler) Process(ctx context.Context, outboundRay ray.OutboundRay, dial } defer conn.Close() - timeout := time.Second * time.Duration(v.timeout) - if timeout == 0 { - timeout = time.Minute * 5 - } - ctx, timer := signal.CancelAfterInactivity(ctx, timeout) + ctx, cancel := context.WithCancel(ctx) + timer := signal.CancelAfterInactivity(ctx, cancel, h.policy.Timeout.ConnectionIdle.Duration()) requestDone := signal.ExecuteAsync(func() error { var writer buf.Writer @@ -120,6 +131,7 @@ func (v *Handler) Process(ctx context.Context, outboundRay ray.OutboundRay, dial if err := buf.Copy(input, writer, buf.UpdateActivity(timer)); err != nil { return newError("failed to process request").Base(err) } + timer.SetTimeout(h.policy.Timeout.DownlinkOnly.Duration()) return nil }) @@ -130,6 +142,7 @@ func (v *Handler) Process(ctx context.Context, outboundRay ray.OutboundRay, dial if err := buf.Copy(v2reader, output, buf.UpdateActivity(timer)); err != nil { return newError("failed to process response").Base(err) } + timer.SetTimeout(h.policy.Timeout.UplinkOnly.Duration()) return nil }) @@ -139,8 +152,6 @@ func (v *Handler) Process(ctx context.Context, outboundRay ray.OutboundRay, dial return newError("connection ends").Base(err) } - runtime.KeepAlive(timer) - return nil } diff --git a/proxy/http/config.go b/proxy/http/config.go index d02cfda64..cbe486d5a 100644 --- a/proxy/http/config.go +++ b/proxy/http/config.go @@ -1 +1,13 @@ package http + +func (sc *ServerConfig) HasAccount(username, password string) bool { + if sc.Accounts == nil { + return false + } + + p, found := sc.Accounts[username] + if !found { + return false + } + return p == password +} diff --git a/proxy/http/config.pb.go b/proxy/http/config.pb.go index 31474746d..3986458fd 100644 --- a/proxy/http/config.pb.go +++ b/proxy/http/config.pb.go @@ -17,7 +17,10 @@ const _ = proto.ProtoPackageIsVersion2 // please upgrade the proto package // Config for HTTP proxy server. type ServerConfig struct { - Timeout uint32 `protobuf:"varint,1,opt,name=timeout" json:"timeout,omitempty"` + Timeout uint32 `protobuf:"varint,1,opt,name=timeout" json:"timeout,omitempty"` + Accounts map[string]string `protobuf:"bytes,2,rep,name=accounts" json:"accounts,omitempty" protobuf_key:"bytes,1,opt,name=key" protobuf_val:"bytes,2,opt,name=value"` + AllowTransparent bool `protobuf:"varint,3,opt,name=allow_transparent,json=allowTransparent" json:"allow_transparent,omitempty"` + UserLevel uint32 `protobuf:"varint,4,opt,name=user_level,json=userLevel" json:"user_level,omitempty"` } func (m *ServerConfig) Reset() { *m = ServerConfig{} } @@ -32,6 +35,27 @@ func (m *ServerConfig) GetTimeout() uint32 { return 0 } +func (m *ServerConfig) GetAccounts() map[string]string { + if m != nil { + return m.Accounts + } + return nil +} + +func (m *ServerConfig) GetAllowTransparent() bool { + if m != nil { + return m.AllowTransparent + } + return false +} + +func (m *ServerConfig) GetUserLevel() uint32 { + if m != nil { + return m.UserLevel + } + return 0 +} + // ClientConfig for HTTP proxy client. type ClientConfig struct { } @@ -49,16 +73,24 @@ func init() { func init() { proto.RegisterFile("v2ray.com/core/proxy/http/config.proto", fileDescriptor0) } var fileDescriptor0 = []byte{ - // 161 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0x52, 0x2b, 0x33, 0x2a, 0x4a, - 0xac, 0xd4, 0x4b, 0xce, 0xcf, 0xd5, 0x4f, 0xce, 0x2f, 0x4a, 0xd5, 0x2f, 0x28, 0xca, 0xaf, 0xa8, - 0xd4, 0xcf, 0x28, 0x29, 0x29, 0xd0, 0x4f, 0xce, 0xcf, 0x4b, 0xcb, 0x4c, 0xd7, 0x2b, 0x28, 0xca, - 0x2f, 0xc9, 0x17, 0x12, 0x85, 0xa9, 0x2b, 0x4a, 0xd5, 0x03, 0xab, 0xd1, 0x03, 0xa9, 0x51, 0xd2, - 0xe0, 0xe2, 0x09, 0x4e, 0x2d, 0x2a, 0x4b, 0x2d, 0x72, 0x06, 0x2b, 0x16, 0x92, 0xe0, 0x62, 0x2f, - 0xc9, 0xcc, 0x4d, 0xcd, 0x2f, 0x2d, 0x91, 0x60, 0x54, 0x60, 0xd4, 0xe0, 0x0d, 0x82, 0x71, 0x95, - 0xf8, 0xb8, 0x78, 0x9c, 0x73, 0x32, 0x53, 0xf3, 0x4a, 0x20, 0x2a, 0x9d, 0xac, 0xb9, 0x24, 0x93, - 0xf3, 0x73, 0xf5, 0xb0, 0x1a, 0x1b, 0xc0, 0x18, 0xc5, 0x02, 0xa2, 0x57, 0x31, 0x89, 0x86, 0x19, - 0x05, 0x25, 0x56, 0xea, 0x39, 0x83, 0xe4, 0x03, 0xc0, 0xf2, 0x1e, 0x25, 0x25, 0x05, 0x49, 0x6c, - 0x60, 0x47, 0x19, 0x03, 0x02, 0x00, 0x00, 0xff, 0xff, 0xc9, 0xae, 0x86, 0xab, 0xbe, 0x00, 0x00, - 0x00, + // 296 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x6c, 0x90, 0xcf, 0x4a, 0x33, 0x31, + 0x14, 0xc5, 0x99, 0x69, 0xbf, 0xcf, 0xf6, 0xda, 0x4a, 0x0d, 0x16, 0x46, 0x51, 0x28, 0x5d, 0x48, + 0x41, 0xc8, 0x60, 0xdd, 0x88, 0x5d, 0xd9, 0x22, 0xb8, 0x50, 0x28, 0x51, 0x5c, 0xb8, 0x29, 0x31, + 0x5c, 0xb5, 0x98, 0x26, 0x43, 0xe6, 0xce, 0xe8, 0xec, 0x7d, 0x1a, 0x9f, 0x52, 0x92, 0x5a, 0xff, + 0x40, 0x57, 0x49, 0x7e, 0xe7, 0xe4, 0xe4, 0x9e, 0xc0, 0x61, 0x39, 0x74, 0xb2, 0xe2, 0xca, 0x2e, + 0x52, 0x65, 0x1d, 0xa6, 0x99, 0xb3, 0x6f, 0x55, 0xfa, 0x4c, 0x94, 0xa5, 0xca, 0x9a, 0xc7, 0xf9, + 0x13, 0xcf, 0x9c, 0x25, 0xcb, 0xba, 0x2b, 0x9f, 0x43, 0x1e, 0x3c, 0xdc, 0x7b, 0xfa, 0xef, 0x31, + 0xb4, 0x6e, 0xd0, 0x95, 0xe8, 0x26, 0xc1, 0xcd, 0xf6, 0x61, 0x83, 0xe6, 0x0b, 0xb4, 0x05, 0x25, + 0x51, 0x2f, 0x1a, 0xb4, 0xc7, 0x71, 0x12, 0x89, 0x15, 0x62, 0xd7, 0xd0, 0x90, 0x4a, 0xd9, 0xc2, + 0x50, 0x9e, 0xc4, 0xbd, 0xda, 0x60, 0x73, 0x78, 0xcc, 0xd7, 0x06, 0xf3, 0xdf, 0xa1, 0xfc, 0xfc, + 0xeb, 0xce, 0x85, 0x21, 0x57, 0x89, 0xef, 0x08, 0x76, 0x04, 0xdb, 0x52, 0x6b, 0xfb, 0x3a, 0x23, + 0x27, 0x4d, 0x9e, 0x49, 0x87, 0x86, 0x92, 0x5a, 0x2f, 0x1a, 0x34, 0x44, 0x27, 0x08, 0xb7, 0x3f, + 0x9c, 0x1d, 0x00, 0x14, 0x39, 0xba, 0x99, 0xc6, 0x12, 0x75, 0x52, 0xf7, 0xc3, 0x89, 0xa6, 0x27, + 0x57, 0x1e, 0xec, 0x8d, 0xa0, 0xfd, 0xe7, 0x19, 0xd6, 0x81, 0xda, 0x0b, 0x56, 0xa1, 0x45, 0x53, + 0xf8, 0x2d, 0xdb, 0x81, 0x7f, 0xa5, 0xd4, 0x05, 0x26, 0x71, 0x60, 0xcb, 0xc3, 0x59, 0x7c, 0x1a, + 0xf5, 0xb7, 0xa0, 0x35, 0xd1, 0x73, 0x34, 0xb4, 0x1c, 0x78, 0x3c, 0x82, 0x5d, 0x65, 0x17, 0xeb, + 0xab, 0x4d, 0xa3, 0xfb, 0xba, 0x5f, 0x3f, 0xe2, 0xee, 0xdd, 0x50, 0xc8, 0x8a, 0x4f, 0xbc, 0x3e, + 0x0d, 0xfa, 0x25, 0x51, 0xf6, 0xf0, 0x3f, 0xfc, 0xf8, 0xc9, 0x67, 0x00, 0x00, 0x00, 0xff, 0xff, + 0x69, 0x94, 0x9f, 0xa7, 0x9b, 0x01, 0x00, 0x00, } diff --git a/proxy/http/config.proto b/proxy/http/config.proto index 5cbfdb83c..995737dd7 100644 --- a/proxy/http/config.proto +++ b/proxy/http/config.proto @@ -8,10 +8,13 @@ option java_multiple_files = true; // Config for HTTP proxy server. message ServerConfig { - uint32 timeout = 1; + uint32 timeout = 1 [deprecated = true]; + map accounts = 2; + bool allow_transparent = 3; + uint32 user_level = 4; } // ClientConfig for HTTP proxy client. message ClientConfig { -} \ No newline at end of file +} diff --git a/proxy/http/server.go b/proxy/http/server.go index b13b75d46..e1f371b67 100644 --- a/proxy/http/server.go +++ b/proxy/http/server.go @@ -3,9 +3,9 @@ package http import ( "bufio" "context" + "encoding/base64" "io" "net/http" - "runtime" "strconv" "strings" "time" @@ -13,6 +13,7 @@ import ( "v2ray.com/core/app" "v2ray.com/core/app/dispatcher" "v2ray.com/core/app/log" + "v2ray.com/core/app/policy" "v2ray.com/core/common" "v2ray.com/core/common/buf" "v2ray.com/core/common/errors" @@ -24,6 +25,7 @@ import ( // Server is a HTTP proxy server. type Server struct { config *ServerConfig + policy policy.Policy } // NewServer creates a new HTTP inbound handler. @@ -35,6 +37,17 @@ func NewServer(ctx context.Context, config *ServerConfig) (*Server, error) { s := &Server{ config: config, } + space.On(app.SpaceInitializing, func(interface{}) error { + pm := policy.FromSpace(space) + if pm == nil { + return newError("Policy not found in space.") + } + s.policy = pm.GetPolicy(config.UserLevel) + if config.Timeout > 0 && config.UserLevel == 0 { + s.policy.Timeout.ConnectionIdle.Value = config.Timeout + } + return nil + }) return s, nil } @@ -53,7 +66,7 @@ func parseHost(rawHost string, defaultPort net.Port) (net.Destination, error) { } else { return net.Destination{}, err } - } else { + } else if len(rawPort) > 0 { intPort, err := strconv.Atoi(rawPort) if err != nil { return net.Destination{}, err @@ -65,15 +78,36 @@ func parseHost(rawHost string, defaultPort net.Port) (net.Destination, error) { } func isTimeout(err error) bool { - nerr, ok := err.(net.Error) + nerr, ok := errors.Cause(err).(net.Error) return ok && nerr.Timeout() } +func parseBasicAuth(auth string) (username, password string, ok bool) { + const prefix = "Basic " + if !strings.HasPrefix(auth, prefix) { + return + } + c, err := base64.StdEncoding.DecodeString(auth[len(prefix):]) + if err != nil { + return + } + cs := string(c) + s := strings.IndexByte(cs, ':') + if s < 0 { + return + } + return cs[:s], cs[s+1:], true +} + +type readerOnly struct { + io.Reader +} + func (s *Server) Process(ctx context.Context, network net.Network, conn internet.Connection, dispatcher dispatcher.Interface) error { - reader := bufio.NewReaderSize(conn, 2048) + reader := bufio.NewReaderSize(readerOnly{conn}, buf.Size) Start: - conn.SetReadDeadline(time.Now().Add(time.Second * 16)) + conn.SetReadDeadline(time.Now().Add(s.policy.Timeout.Handshake.Duration())) request, err := http.ReadRequest(reader) if err != nil { @@ -83,6 +117,19 @@ Start: } return trace } + + if len(s.config.Accounts) > 0 { + user, pass, ok := parseBasicAuth(request.Header.Get("Proxy-Authorization")) + if !ok { + _, err := conn.Write([]byte("HTTP/1.1 407 Proxy Authentication Required\r\n\r\n")) + return err + } + if !s.config.HasAccount(user, pass) { + _, err := conn.Write([]byte("HTTP/1.1 401 UNAUTHORIZED\r\n\r\n")) + return err + } + } + log.Trace(newError("request to Method [", request.Method, "] Host [", request.Host, "] with URL [", request.URL, "]")) conn.SetReadDeadline(time.Time{}) @@ -106,7 +153,7 @@ Start: keepAlive := (strings.TrimSpace(strings.ToLower(request.Header.Get("Proxy-Connection"))) == "keep-alive") - err = s.handlePlainHTTP(ctx, request, reader, conn, dest, dispatcher) + err = s.handlePlainHTTP(ctx, request, conn, dest, dispatcher) if err == errWaitAnother { if keepAlive { goto Start @@ -117,38 +164,44 @@ Start: return err } -func (s *Server) handleConnect(ctx context.Context, request *http.Request, reader io.Reader, writer io.Writer, dest net.Destination, dispatcher dispatcher.Interface) error { - _, err := writer.Write([]byte("HTTP/1.1 200 Connection established\r\n\r\n")) +func (s *Server) handleConnect(ctx context.Context, request *http.Request, reader *bufio.Reader, conn internet.Connection, dest net.Destination, dispatcher dispatcher.Interface) error { + _, err := conn.Write([]byte("HTTP/1.1 200 Connection established\r\n\r\n")) if err != nil { return newError("failed to write back OK response").Base(err) } - timeout := time.Second * time.Duration(s.config.Timeout) - if timeout == 0 { - timeout = time.Minute * 5 - } - ctx, timer := signal.CancelAfterInactivity(ctx, timeout) + ctx, cancel := context.WithCancel(ctx) + timer := signal.CancelAfterInactivity(ctx, cancel, s.policy.Timeout.ConnectionIdle.Duration()) ray, err := dispatcher.Dispatch(ctx, dest) if err != nil { return err } - requestDone := signal.ExecuteAsync(func() error { - defer ray.InboundInput().Close() - - v2reader := buf.NewReader(reader) - if err := buf.Copy(v2reader, ray.InboundInput(), buf.UpdateActivity(timer)); err != nil { + if reader.Buffered() > 0 { + payload := buf.New() + common.Must(payload.Reset(func(b []byte) (int, error) { + return reader.Read(b[:reader.Buffered()]) + })) + if err := ray.InboundInput().WriteMultiBuffer(buf.NewMultiBufferValue(payload)); err != nil { return err } - return nil + reader = nil + } + + requestDone := signal.ExecuteAsync(func() error { + defer ray.InboundInput().Close() + defer timer.SetTimeout(s.policy.Timeout.DownlinkOnly.Duration()) + + v2reader := buf.NewReader(conn) + return buf.Copy(v2reader, ray.InboundInput(), buf.UpdateActivity(timer)) }) responseDone := signal.ExecuteAsync(func() error { - v2writer := buf.NewWriter(writer) + v2writer := buf.NewWriter(conn) if err := buf.Copy(ray.InboundOutput(), v2writer, buf.UpdateActivity(timer)); err != nil { return err } - timer.SetTimeout(time.Second * 2) + timer.SetTimeout(s.policy.Timeout.UplinkOnly.Duration()) return nil }) @@ -158,8 +211,6 @@ func (s *Server) handleConnect(ctx context.Context, request *http.Request, reade return newError("connection ends").Base(err) } - runtime.KeepAlive(timer) - return nil } @@ -185,12 +236,18 @@ func StripHopByHopHeaders(header http.Header) { for _, h := range strings.Split(connections, ",") { header.Del(strings.TrimSpace(h)) } + + // Prevent UA from being set to golang's default ones + if len(header.Get("User-Agent")) == 0 { + header.Set("User-Agent", "") + } } var errWaitAnother = newError("keep alive") -func (s *Server) handlePlainHTTP(ctx context.Context, request *http.Request, reader io.Reader, writer io.Writer, dest net.Destination, dispatcher dispatcher.Interface) error { - if len(request.URL.Host) <= 0 { +func (s *Server) handlePlainHTTP(ctx context.Context, request *http.Request, writer io.Writer, dest net.Destination, dispatcher dispatcher.Interface) error { + if !s.config.AllowTransparent && len(request.URL.Host) <= 0 { + // RFC 2068 (HTTP/1.1) requires URL to be absolute URL in HTTP proxy. response := &http.Response{ Status: "Bad Request", StatusCode: 400, @@ -207,7 +264,9 @@ func (s *Server) handlePlainHTTP(ctx context.Context, request *http.Request, rea return response.Write(writer) } - request.Host = request.URL.Host + if len(request.URL.Host) > 0 { + request.Host = request.URL.Host + } StripHopByHopHeaders(request.Header) ray, err := dispatcher.Dispatch(ctx, dest) @@ -223,15 +282,16 @@ func (s *Server) handlePlainHTTP(ctx context.Context, request *http.Request, rea requestDone := signal.ExecuteAsync(func() error { request.Header.Set("Connection", "close") - requestWriter := buf.ToBytesWriter(ray.InboundInput()) + requestWriter := buf.NewBufferedWriter(ray.InboundInput()) + common.Must(requestWriter.SetBuffered(false)) if err := request.Write(requestWriter); err != nil { - return err + return newError("failed to write whole request").Base(err).AtWarning() } return nil }) responseDone := signal.ExecuteAsync(func() error { - responseReader := bufio.NewReaderSize(buf.ToBytesReader(ray.InboundOutput()), 2048) + responseReader := bufio.NewReaderSize(buf.NewBufferedReader(ray.InboundOutput()), buf.Size) response, err := http.ReadResponse(responseReader, request) if err == nil { StripHopByHopHeaders(response.Header) @@ -261,7 +321,7 @@ func (s *Server) handlePlainHTTP(ctx context.Context, request *http.Request, rea response.Header.Set("Proxy-Connection", "close") } if err := response.Write(writer); err != nil { - return newError("failed to write response").Base(err) + return newError("failed to write response").Base(err).AtWarning() } return nil }) diff --git a/proxy/http/server_test.go b/proxy/http/server_test.go index 2bc370a2e..c4b156f16 100644 --- a/proxy/http/server_test.go +++ b/proxy/http/server_test.go @@ -7,13 +7,13 @@ import ( "testing" . "v2ray.com/core/proxy/http" - "v2ray.com/core/testing/assert" + . "v2ray.com/ext/assert" _ "v2ray.com/core/transport/internet/tcp" ) func TestHopByHopHeadersStrip(t *testing.T) { - assert := assert.On(t) + assert := With(t) rawRequest := `GET /pkg/net/http/ HTTP/1.1 Host: golang.org @@ -22,7 +22,6 @@ Foo: foo Bar: bar Proxy-Connection: keep-alive Proxy-Authenticate: abc -User-Agent: Mozilla/5.0 (Macintosh; U; Intel Mac OS X; de-de) AppleWebKit/523.10.3 (KHTML, like Gecko) Version/3.0.4 Safari/523.10 Accept-Encoding: gzip Accept-Charset: ISO-8859-1,UTF-8;q=0.7,*;q=0.7 Cache-Control: no-cache @@ -31,17 +30,19 @@ Accept-Language: de,en;q=0.7,en-us;q=0.3 ` b := bufio.NewReader(strings.NewReader(rawRequest)) req, err := http.ReadRequest(b) - assert.Error(err).IsNil() - assert.String(req.Header.Get("Foo")).Equals("foo") - assert.String(req.Header.Get("Bar")).Equals("bar") - assert.String(req.Header.Get("Connection")).Equals("keep-alive,Foo, Bar") - assert.String(req.Header.Get("Proxy-Connection")).Equals("keep-alive") - assert.String(req.Header.Get("Proxy-Authenticate")).Equals("abc") + assert(err, IsNil) + assert(req.Header.Get("Foo"), Equals, "foo") + assert(req.Header.Get("Bar"), Equals, "bar") + assert(req.Header.Get("Connection"), Equals, "keep-alive,Foo, Bar") + assert(req.Header.Get("Proxy-Connection"), Equals, "keep-alive") + assert(req.Header.Get("Proxy-Authenticate"), Equals, "abc") + assert(req.Header.Get("User-Agent"), IsEmpty) StripHopByHopHeaders(req.Header) - assert.String(req.Header.Get("Connection")).IsEmpty() - assert.String(req.Header.Get("Foo")).IsEmpty() - assert.String(req.Header.Get("Bar")).IsEmpty() - assert.String(req.Header.Get("Proxy-Connection")).IsEmpty() - assert.String(req.Header.Get("Proxy-Authenticate")).IsEmpty() + assert(req.Header.Get("Connection"), IsEmpty) + assert(req.Header.Get("Foo"), IsEmpty) + assert(req.Header.Get("Bar"), IsEmpty) + assert(req.Header.Get("Proxy-Connection"), IsEmpty) + assert(req.Header.Get("Proxy-Authenticate"), IsEmpty) + assert(req.Header.Get("User-Agent"), IsEmpty) } diff --git a/proxy/shadowsocks/client.go b/proxy/shadowsocks/client.go index 8177fa08d..d86127c21 100644 --- a/proxy/shadowsocks/client.go +++ b/proxy/shadowsocks/client.go @@ -2,10 +2,10 @@ package shadowsocks import ( "context" - "runtime" - "time" + "v2ray.com/core/app" "v2ray.com/core/app/log" + "v2ray.com/core/app/policy" "v2ray.com/core/common" "v2ray.com/core/common/buf" "v2ray.com/core/common/net" @@ -19,7 +19,8 @@ import ( // Client is a inbound handler for Shadowsocks protocol type Client struct { - serverPicker protocol.ServerPicker + serverPicker protocol.ServerPicker + policyManager policy.Manager } // NewClient create a new Shadowsocks client. @@ -34,6 +35,18 @@ func NewClient(ctx context.Context, config *ClientConfig) (*Client, error) { client := &Client{ serverPicker: protocol.NewRoundRobinServerPicker(serverList), } + space := app.SpaceFromContext(ctx) + if space == nil { + return nil, newError("Space not found.") + } + space.On(app.SpaceInitializing, func(interface{}) error { + pm := policy.FromSpace(space) + if pm == nil { + return newError("Policy not found in space.") + } + client.policyManager = pm + return nil + }) return client, nil } @@ -84,17 +97,19 @@ func (v *Client) Process(ctx context.Context, outboundRay ray.OutboundRay, diale if err != nil { return newError("failed to get a valid user account").AtWarning().Base(err) } - account := rawAccount.(*ShadowsocksAccount) + account := rawAccount.(*MemoryAccount) request.User = user if account.OneTimeAuth == Account_Auto || account.OneTimeAuth == Account_Enabled { request.Option |= RequestOptionOneTimeAuth } - ctx, timer := signal.CancelAfterInactivity(ctx, time.Minute*5) + sessionPolicy := v.policyManager.GetPolicy(user.Level) + ctx, cancel := context.WithCancel(ctx) + timer := signal.CancelAfterInactivity(ctx, cancel, sessionPolicy.Timeout.ConnectionIdle.Duration()) if request.Command == protocol.RequestCommandTCP { - bufferedWriter := buf.NewBufferedWriter(conn) + bufferedWriter := buf.NewBufferedWriter(buf.NewWriter(conn)) bodyWriter, err := WriteTCPRequest(request, bufferedWriter) if err != nil { return newError("failed to write request").Base(err) @@ -105,25 +120,20 @@ func (v *Client) Process(ctx context.Context, outboundRay ray.OutboundRay, diale } requestDone := signal.ExecuteAsync(func() error { - if err := buf.Copy(outboundRay.OutboundInput(), bodyWriter, buf.UpdateActivity(timer)); err != nil { - return err - } - return nil + defer timer.SetTimeout(sessionPolicy.Timeout.DownlinkOnly.Duration()) + return buf.Copy(outboundRay.OutboundInput(), bodyWriter, buf.UpdateActivity(timer)) }) responseDone := signal.ExecuteAsync(func() error { defer outboundRay.OutboundOutput().Close() + defer timer.SetTimeout(sessionPolicy.Timeout.UplinkOnly.Duration()) responseReader, err := ReadTCPResponse(user, conn) if err != nil { return err } - if err := buf.Copy(responseReader, outboundRay.OutboundOutput(), buf.UpdateActivity(timer)); err != nil { - return err - } - - return nil + return buf.Copy(responseReader, outboundRay.OutboundOutput(), buf.UpdateActivity(timer)) }) if err := signal.ErrorOrFinish2(ctx, requestDone, responseDone); err != nil { @@ -168,8 +178,6 @@ func (v *Client) Process(ctx context.Context, outboundRay ray.OutboundRay, diale return nil } - runtime.KeepAlive(timer) - return nil } diff --git a/proxy/shadowsocks/config.go b/proxy/shadowsocks/config.go index 15c353330..54de878f0 100644 --- a/proxy/shadowsocks/config.go +++ b/proxy/shadowsocks/config.go @@ -2,28 +2,52 @@ package shadowsocks import ( "bytes" + "crypto/aes" "crypto/cipher" "crypto/md5" + "crypto/sha1" + "io" + "golang.org/x/crypto/chacha20poly1305" + "golang.org/x/crypto/hkdf" + + "v2ray.com/core/common" + "v2ray.com/core/common/buf" "v2ray.com/core/common/crypto" "v2ray.com/core/common/protocol" ) -type ShadowsocksAccount struct { +// MemoryAccount is an account type converted from Account. +type MemoryAccount struct { Cipher Cipher Key []byte OneTimeAuth Account_OneTimeAuth } -func (v *ShadowsocksAccount) Equals(another protocol.Account) bool { - if account, ok := another.(*ShadowsocksAccount); ok { - return bytes.Equal(v.Key, account.Key) +// Equals implements protocol.Account.Equals(). +func (a *MemoryAccount) Equals(another protocol.Account) bool { + if account, ok := another.(*MemoryAccount); ok { + return bytes.Equal(a.Key, account.Key) } return false } -func (v *Account) GetCipher() (Cipher, error) { - switch v.CipherType { +func createAesGcm(key []byte) cipher.AEAD { + block, err := aes.NewCipher(key) + common.Must(err) + gcm, err := cipher.NewGCM(block) + common.Must(err) + return gcm +} + +func createChacha20Poly1305(key []byte) cipher.AEAD { + chacha20, err := chacha20poly1305.New(key) + common.Must(err) + return chacha20 +} + +func (a *Account) getCipher() (Cipher, error) { + switch a.CipherType { case CipherType_AES_128_CFB: return &AesCfb{KeyBytes: 16}, nil case CipherType_AES_256_CFB: @@ -32,42 +56,64 @@ func (v *Account) GetCipher() (Cipher, error) { return &ChaCha20{IVBytes: 8}, nil case CipherType_CHACHA20_IETF: return &ChaCha20{IVBytes: 12}, nil + case CipherType_AES_128_GCM: + return &AEADCipher{ + KeyBytes: 16, + IVBytes: 16, + AEADAuthCreator: createAesGcm, + }, nil + case CipherType_AES_256_GCM: + return &AEADCipher{ + KeyBytes: 32, + IVBytes: 32, + AEADAuthCreator: createAesGcm, + }, nil + case CipherType_CHACHA20_POLY1305: + return &AEADCipher{ + KeyBytes: 32, + IVBytes: 32, + AEADAuthCreator: createChacha20Poly1305, + }, nil + case CipherType_NONE: + return NoneCipher{}, nil default: return nil, newError("Unsupported cipher.") } } -func (v *Account) AsAccount() (protocol.Account, error) { - cipher, err := v.GetCipher() +// AsAccount implements protocol.AsAccount. +func (a *Account) AsAccount() (protocol.Account, error) { + cipher, err := a.getCipher() if err != nil { return nil, newError("failed to get cipher").Base(err) } - return &ShadowsocksAccount{ + return &MemoryAccount{ Cipher: cipher, - Key: v.GetCipherKey(), - OneTimeAuth: v.Ota, + Key: passwordToCipherKey([]byte(a.Password), cipher.KeySize()), + OneTimeAuth: a.Ota, }, nil } -func (v *Account) GetCipherKey() []byte { - ct, err := v.GetCipher() - if err != nil { - return nil - } - return PasswordToCipherKey(v.Password, ct.KeySize()) -} - +// Cipher is an interface for all Shadowsocks ciphers. type Cipher interface { KeySize() int IVSize() int - NewEncodingStream(key []byte, iv []byte) (cipher.Stream, error) - NewDecodingStream(key []byte, iv []byte) (cipher.Stream, error) + NewEncryptionWriter(key []byte, iv []byte, writer io.Writer) (buf.Writer, error) + NewDecryptionReader(key []byte, iv []byte, reader io.Reader) (buf.Reader, error) + IsAEAD() bool + EncodePacket(key []byte, b *buf.Buffer) error + DecodePacket(key []byte, b *buf.Buffer) error } +// AesCfb represents all AES-CFB ciphers. type AesCfb struct { KeyBytes int } +func (*AesCfb) IsAEAD() bool { + return false +} + func (v *AesCfb) KeySize() int { return v.KeyBytes } @@ -76,20 +122,111 @@ func (v *AesCfb) IVSize() int { return 16 } -func (v *AesCfb) NewEncodingStream(key []byte, iv []byte) (cipher.Stream, error) { +func (v *AesCfb) NewEncryptionWriter(key []byte, iv []byte, writer io.Writer) (buf.Writer, error) { stream := crypto.NewAesEncryptionStream(key, iv) - return stream, nil + return buf.NewWriter(crypto.NewCryptionWriter(stream, writer)), nil } -func (v *AesCfb) NewDecodingStream(key []byte, iv []byte) (cipher.Stream, error) { +func (v *AesCfb) NewDecryptionReader(key []byte, iv []byte, reader io.Reader) (buf.Reader, error) { stream := crypto.NewAesDecryptionStream(key, iv) - return stream, nil + return buf.NewReader(crypto.NewCryptionReader(stream, reader)), nil +} + +func (v *AesCfb) EncodePacket(key []byte, b *buf.Buffer) error { + iv := b.BytesTo(v.IVSize()) + stream := crypto.NewAesEncryptionStream(key, iv) + stream.XORKeyStream(b.BytesFrom(v.IVSize()), b.BytesFrom(v.IVSize())) + return nil +} + +func (v *AesCfb) DecodePacket(key []byte, b *buf.Buffer) error { + iv := b.BytesTo(v.IVSize()) + stream := crypto.NewAesDecryptionStream(key, iv) + stream.XORKeyStream(b.BytesFrom(v.IVSize()), b.BytesFrom(v.IVSize())) + b.SliceFrom(v.IVSize()) + return nil +} + +type AEADCipher struct { + KeyBytes int + IVBytes int + AEADAuthCreator func(key []byte) cipher.AEAD +} + +func (*AEADCipher) IsAEAD() bool { + return true +} + +func (c *AEADCipher) KeySize() int { + return c.KeyBytes +} + +func (c *AEADCipher) IVSize() int { + return c.IVBytes +} + +func (c *AEADCipher) createAuthenticator(key []byte, iv []byte) *crypto.AEADAuthenticator { + nonce := crypto.NewIncreasingAEADNonceGenerator() + subkey := make([]byte, c.KeyBytes) + hkdfSHA1(key, iv, subkey) + return &crypto.AEADAuthenticator{ + AEAD: c.AEADAuthCreator(subkey), + NonceGenerator: nonce, + } +} + +func (c *AEADCipher) NewEncryptionWriter(key []byte, iv []byte, writer io.Writer) (buf.Writer, error) { + auth := c.createAuthenticator(key, iv) + return crypto.NewAuthenticationWriter(auth, &crypto.AEADChunkSizeParser{ + Auth: auth, + }, writer, protocol.TransferTypeStream), nil +} + +func (c *AEADCipher) NewDecryptionReader(key []byte, iv []byte, reader io.Reader) (buf.Reader, error) { + auth := c.createAuthenticator(key, iv) + return crypto.NewAuthenticationReader(auth, &crypto.AEADChunkSizeParser{ + Auth: auth, + }, reader, protocol.TransferTypeStream), nil +} + +func (c *AEADCipher) EncodePacket(key []byte, b *buf.Buffer) error { + ivLen := c.IVSize() + payloadLen := b.Len() + auth := c.createAuthenticator(key, b.BytesTo(ivLen)) + return b.Reset(func(bb []byte) (int, error) { + bbb, err := auth.Seal(bb[:ivLen], bb[ivLen:payloadLen]) + if err != nil { + return 0, err + } + return len(bbb), nil + }) +} + +func (c *AEADCipher) DecodePacket(key []byte, b *buf.Buffer) error { + ivLen := c.IVSize() + payloadLen := b.Len() + auth := c.createAuthenticator(key, b.BytesTo(ivLen)) + if err := b.Reset(func(bb []byte) (int, error) { + bbb, err := auth.Open(bb[:ivLen], bb[ivLen:payloadLen]) + if err != nil { + return 0, err + } + return len(bbb), nil + }); err != nil { + return err + } + b.SliceFrom(ivLen) + return nil } type ChaCha20 struct { IVBytes int } +func (*ChaCha20) IsAEAD() bool { + return false +} + func (v *ChaCha20) KeySize() int { return 32 } @@ -98,28 +235,73 @@ func (v *ChaCha20) IVSize() int { return v.IVBytes } -func (v *ChaCha20) NewEncodingStream(key []byte, iv []byte) (cipher.Stream, error) { - return crypto.NewChaCha20Stream(key, iv), nil +func (v *ChaCha20) NewEncryptionWriter(key []byte, iv []byte, writer io.Writer) (buf.Writer, error) { + stream := crypto.NewChaCha20Stream(key, iv) + return buf.NewWriter(crypto.NewCryptionWriter(stream, writer)), nil } -func (v *ChaCha20) NewDecodingStream(key []byte, iv []byte) (cipher.Stream, error) { - return crypto.NewChaCha20Stream(key, iv), nil +func (v *ChaCha20) NewDecryptionReader(key []byte, iv []byte, reader io.Reader) (buf.Reader, error) { + stream := crypto.NewChaCha20Stream(key, iv) + return buf.NewReader(crypto.NewCryptionReader(stream, reader)), nil } -func PasswordToCipherKey(password string, keySize int) []byte { - pwdBytes := []byte(password) +func (v *ChaCha20) EncodePacket(key []byte, b *buf.Buffer) error { + iv := b.BytesTo(v.IVSize()) + stream := crypto.NewChaCha20Stream(key, iv) + stream.XORKeyStream(b.BytesFrom(v.IVSize()), b.BytesFrom(v.IVSize())) + return nil +} + +func (v *ChaCha20) DecodePacket(key []byte, b *buf.Buffer) error { + iv := b.BytesTo(v.IVSize()) + stream := crypto.NewChaCha20Stream(key, iv) + stream.XORKeyStream(b.BytesFrom(v.IVSize()), b.BytesFrom(v.IVSize())) + b.SliceFrom(v.IVSize()) + return nil +} + +type NoneCipher struct{} + +func (NoneCipher) KeySize() int { return 0 } +func (NoneCipher) IVSize() int { return 0 } +func (NoneCipher) IsAEAD() bool { + return true // to avoid OTA +} + +func (NoneCipher) NewDecryptionReader(key []byte, iv []byte, reader io.Reader) (buf.Reader, error) { + return buf.NewReader(reader), nil +} + +func (NoneCipher) NewEncryptionWriter(key []byte, iv []byte, writer io.Writer) (buf.Writer, error) { + return buf.NewWriter(writer), nil +} + +func (NoneCipher) EncodePacket(key []byte, b *buf.Buffer) error { + return nil +} + +func (NoneCipher) DecodePacket(key []byte, b *buf.Buffer) error { + return nil +} + +func passwordToCipherKey(password []byte, keySize int) []byte { key := make([]byte, 0, keySize) - md5Sum := md5.Sum(pwdBytes) + md5Sum := md5.Sum(password) key = append(key, md5Sum[:]...) for len(key) < keySize { md5Hash := md5.New() - md5Hash.Write(md5Sum[:]) - md5Hash.Write(pwdBytes) + common.Must2(md5Hash.Write(md5Sum[:])) + common.Must2(md5Hash.Write(password)) md5Hash.Sum(md5Sum[:0]) key = append(key, md5Sum[:]...) } return key } + +func hkdfSHA1(secret, salt, outkey []byte) { + r := hkdf.New(sha1.New, secret, salt, []byte("ss-subkey")) + common.Must2(io.ReadFull(r, outkey)) +} diff --git a/proxy/shadowsocks/config.pb.go b/proxy/shadowsocks/config.pb.go index 7549ffedb..bd7cd3b64 100644 --- a/proxy/shadowsocks/config.pb.go +++ b/proxy/shadowsocks/config.pb.go @@ -28,6 +28,7 @@ const ( CipherType_AES_128_GCM CipherType = 5 CipherType_AES_256_GCM CipherType = 6 CipherType_CHACHA20_POLY1305 CipherType = 7 + CipherType_NONE CipherType = 8 ) var CipherType_name = map[int32]string{ @@ -39,6 +40,7 @@ var CipherType_name = map[int32]string{ 5: "AES_128_GCM", 6: "AES_256_GCM", 7: "CHACHA20_POLY1305", + 8: "NONE", } var CipherType_value = map[string]int32{ "UNKNOWN": 0, @@ -49,6 +51,7 @@ var CipherType_value = map[string]int32{ "AES_128_GCM": 5, "AES_256_GCM": 6, "CHACHA20_POLY1305": 7, + "NONE": 8, } func (x CipherType) String() string { @@ -163,35 +166,35 @@ func init() { func init() { proto.RegisterFile("v2ray.com/core/proxy/shadowsocks/config.proto", fileDescriptor0) } var fileDescriptor0 = []byte{ - // 470 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x84, 0x91, 0xd1, 0x8e, 0xd2, 0x40, - 0x14, 0x86, 0xb7, 0x80, 0x80, 0xa7, 0xa8, 0xdd, 0x49, 0x4c, 0x08, 0xd9, 0x44, 0xc2, 0x15, 0x6e, - 0xe2, 0x14, 0xba, 0xae, 0xf1, 0xb6, 0x8c, 0xac, 0xbb, 0x51, 0x81, 0x14, 0x56, 0xa3, 0x37, 0x4d, - 0x77, 0x3a, 0x4a, 0x23, 0xed, 0x4c, 0x66, 0xda, 0x5d, 0xfb, 0x20, 0xbe, 0x84, 0x6f, 0xe6, 0x5b, - 0x98, 0x4e, 0x81, 0x6d, 0xbc, 0x60, 0xef, 0x7a, 0x4e, 0xff, 0xff, 0xef, 0x7f, 0xbe, 0xc2, 0xab, - 0x5b, 0x47, 0x06, 0x39, 0xa6, 0x3c, 0xb6, 0x29, 0x97, 0xcc, 0x16, 0x92, 0xff, 0xca, 0x6d, 0xb5, - 0x0e, 0x42, 0x7e, 0xa7, 0x38, 0xfd, 0xa9, 0x6c, 0xca, 0x93, 0xef, 0xd1, 0x0f, 0x2c, 0x24, 0x4f, - 0x39, 0x3a, 0xd9, 0xc9, 0x25, 0xc3, 0x5a, 0x8a, 0x2b, 0xd2, 0xde, 0xcb, 0xff, 0xc2, 0x28, 0x8f, - 0x63, 0x9e, 0xd8, 0xda, 0x4a, 0xf9, 0xc6, 0xce, 0x14, 0x93, 0x65, 0x50, 0x6f, 0xf4, 0x80, 0x54, - 0x31, 0x79, 0xcb, 0xa4, 0xaf, 0x04, 0xa3, 0xa5, 0x63, 0xf0, 0xd7, 0x80, 0x96, 0x4b, 0x29, 0xcf, - 0x92, 0x14, 0xf5, 0xa0, 0x2d, 0x02, 0xa5, 0xee, 0xb8, 0x0c, 0xbb, 0x46, 0xdf, 0x18, 0x3e, 0xf6, - 0xf6, 0x33, 0xba, 0x02, 0x93, 0x46, 0x62, 0xcd, 0xa4, 0x9f, 0xe6, 0x82, 0x75, 0x6b, 0x7d, 0x63, - 0xf8, 0xd4, 0x19, 0xe2, 0x43, 0xc5, 0x31, 0xd1, 0x86, 0x55, 0x2e, 0x98, 0x07, 0x74, 0xff, 0x8c, - 0x08, 0xd4, 0x79, 0x1a, 0x74, 0xeb, 0x3a, 0x62, 0x7c, 0x38, 0x62, 0x5b, 0x0d, 0xcf, 0x13, 0xb6, - 0x8a, 0x62, 0xe6, 0x66, 0xe9, 0xda, 0x2b, 0xdc, 0x03, 0x07, 0xcc, 0xca, 0x0e, 0xb5, 0xa1, 0xe1, - 0x66, 0x29, 0xb7, 0x8e, 0x50, 0x07, 0xda, 0xef, 0x22, 0x15, 0xdc, 0x6c, 0x58, 0x68, 0x19, 0xc8, - 0x84, 0xd6, 0x34, 0x29, 0x87, 0xda, 0x80, 0x41, 0x67, 0xa9, 0x01, 0x10, 0x0d, 0x1f, 0xbd, 0x00, - 0x33, 0x0b, 0x85, 0xcf, 0x4a, 0x81, 0x3e, 0xb9, 0xed, 0x41, 0x16, 0x8a, 0xad, 0x05, 0xbd, 0x86, - 0x46, 0x01, 0x57, 0x5f, 0x6b, 0x3a, 0xfd, 0x6a, 0xd5, 0x92, 0x2c, 0xde, 0x91, 0xc5, 0xd7, 0x8a, - 0x49, 0x4f, 0xab, 0x07, 0x1e, 0x74, 0xc8, 0x26, 0x62, 0x49, 0xba, 0xfd, 0xcc, 0x04, 0x9a, 0x25, - 0xf7, 0xae, 0xd1, 0xaf, 0x0f, 0x4d, 0xe7, 0xf4, 0x50, 0x4e, 0x59, 0x70, 0x9a, 0x84, 0x82, 0x47, - 0x49, 0xea, 0x6d, 0x9d, 0xa7, 0xbf, 0x0d, 0x80, 0x7b, 0x9c, 0xc5, 0x59, 0xd7, 0xb3, 0x0f, 0xb3, - 0xf9, 0x97, 0x99, 0x75, 0x84, 0x9e, 0x81, 0xe9, 0x4e, 0x97, 0xfe, 0xd8, 0x79, 0xeb, 0x93, 0x8b, - 0x89, 0x65, 0xec, 0x16, 0xce, 0xf9, 0x1b, 0xbd, 0xa8, 0x15, 0x4c, 0xc8, 0xa5, 0x4b, 0x2e, 0x5d, - 0x67, 0x64, 0xd5, 0xd1, 0x31, 0x3c, 0xd9, 0x4d, 0xfe, 0xd5, 0x74, 0x75, 0x61, 0x35, 0xaa, 0x11, - 0xef, 0xc9, 0x27, 0xeb, 0x51, 0x35, 0xa2, 0x58, 0x34, 0xd1, 0x73, 0x38, 0xde, 0x9b, 0x16, 0xf3, - 0x8f, 0x5f, 0xc7, 0x67, 0xa3, 0x73, 0xab, 0x35, 0x59, 0x40, 0x9f, 0xf2, 0xf8, 0xe0, 0x3f, 0x5c, - 0x18, 0xdf, 0xcc, 0xca, 0xf8, 0xa7, 0x76, 0xf2, 0xd9, 0xf1, 0x82, 0x1c, 0x93, 0x42, 0xbd, 0xd0, - 0xea, 0xe5, 0xfd, 0xeb, 0x9b, 0xa6, 0x46, 0x71, 0xf6, 0x2f, 0x00, 0x00, 0xff, 0xff, 0x37, 0x7d, - 0x8e, 0xab, 0x43, 0x03, 0x00, 0x00, + // 477 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x84, 0x91, 0x51, 0x8f, 0x93, 0x40, + 0x14, 0x85, 0x97, 0xb6, 0xb6, 0xf5, 0x52, 0x95, 0x9d, 0xc4, 0xa4, 0x69, 0x36, 0xb1, 0xe9, 0x53, + 0xdd, 0xc4, 0xa1, 0x65, 0x5d, 0xe3, 0x2b, 0x45, 0xd6, 0xdd, 0xa8, 0xb4, 0xa1, 0x5d, 0x8d, 0xbe, + 0x10, 0x76, 0x18, 0x2d, 0xb1, 0x30, 0x93, 0x19, 0xd8, 0x95, 0x5f, 0xe3, 0xbb, 0xff, 0xcc, 0x7f, + 0x61, 0x18, 0xda, 0x2e, 0xf1, 0xa1, 0xfb, 0xc6, 0xbd, 0x9c, 0x73, 0x38, 0xf7, 0x03, 0x5e, 0xdd, + 0x5a, 0x22, 0x2c, 0x30, 0x61, 0x89, 0x49, 0x98, 0xa0, 0x26, 0x17, 0xec, 0x57, 0x61, 0xca, 0x75, + 0x18, 0xb1, 0x3b, 0xc9, 0xc8, 0x4f, 0x69, 0x12, 0x96, 0x7e, 0x8f, 0x7f, 0x60, 0x2e, 0x58, 0xc6, + 0xd0, 0xc9, 0x4e, 0x2e, 0x28, 0x56, 0x52, 0x5c, 0x93, 0x0e, 0x5e, 0xfe, 0x17, 0x46, 0x58, 0x92, + 0xb0, 0xd4, 0x54, 0x56, 0xc2, 0x36, 0x66, 0x2e, 0xa9, 0xa8, 0x82, 0x06, 0x93, 0x07, 0xa4, 0x92, + 0x8a, 0x5b, 0x2a, 0x02, 0xc9, 0x29, 0xa9, 0x1c, 0xa3, 0xbf, 0x1a, 0x74, 0x6c, 0x42, 0x58, 0x9e, + 0x66, 0x68, 0x00, 0x5d, 0x1e, 0x4a, 0x79, 0xc7, 0x44, 0xd4, 0xd7, 0x86, 0xda, 0xf8, 0xb1, 0xbf, + 0x9f, 0xd1, 0x15, 0xe8, 0x24, 0xe6, 0x6b, 0x2a, 0x82, 0xac, 0xe0, 0xb4, 0xdf, 0x18, 0x6a, 0xe3, + 0xa7, 0xd6, 0x18, 0x1f, 0x2a, 0x8e, 0x1d, 0x65, 0x58, 0x15, 0x9c, 0xfa, 0x40, 0xf6, 0xcf, 0xc8, + 0x81, 0x26, 0xcb, 0xc2, 0x7e, 0x53, 0x45, 0x4c, 0x0f, 0x47, 0x6c, 0xab, 0xe1, 0x79, 0x4a, 0x57, + 0x71, 0x42, 0xed, 0x3c, 0x5b, 0xfb, 0xa5, 0x7b, 0x64, 0x81, 0x5e, 0xdb, 0xa1, 0x2e, 0xb4, 0xec, + 0x3c, 0x63, 0xc6, 0x11, 0xea, 0x41, 0xf7, 0x5d, 0x2c, 0xc3, 0x9b, 0x0d, 0x8d, 0x0c, 0x0d, 0xe9, + 0xd0, 0x71, 0xd3, 0x6a, 0x68, 0x8c, 0x28, 0xf4, 0x96, 0x0a, 0x80, 0xa3, 0xe0, 0xa3, 0x17, 0xa0, + 0xe7, 0x11, 0x0f, 0x68, 0x25, 0x50, 0x27, 0x77, 0x7d, 0xc8, 0x23, 0xbe, 0xb5, 0xa0, 0xd7, 0xd0, + 0x2a, 0xe1, 0xaa, 0x6b, 0x75, 0x6b, 0x58, 0xaf, 0x5a, 0x91, 0xc5, 0x3b, 0xb2, 0xf8, 0x5a, 0x52, + 0xe1, 0x2b, 0xf5, 0xc8, 0x87, 0x9e, 0xb3, 0x89, 0x69, 0x9a, 0x6d, 0x3f, 0x33, 0x83, 0x76, 0xc5, + 0xbd, 0xaf, 0x0d, 0x9b, 0x63, 0xdd, 0x3a, 0x3d, 0x94, 0x53, 0x15, 0x74, 0xd3, 0x88, 0xb3, 0x38, + 0xcd, 0xfc, 0xad, 0xf3, 0xf4, 0xb7, 0x06, 0x70, 0x8f, 0xb3, 0x3c, 0xeb, 0xda, 0xfb, 0xe0, 0xcd, + 0xbf, 0x78, 0xc6, 0x11, 0x7a, 0x06, 0xba, 0xed, 0x2e, 0x83, 0xa9, 0xf5, 0x36, 0x70, 0x2e, 0x66, + 0x86, 0xb6, 0x5b, 0x58, 0xe7, 0x6f, 0xd4, 0xa2, 0x51, 0x32, 0x71, 0x2e, 0x6d, 0xe7, 0xd2, 0xb6, + 0x26, 0x46, 0x13, 0x1d, 0xc3, 0x93, 0xdd, 0x14, 0x5c, 0xb9, 0xab, 0x0b, 0xa3, 0x55, 0x8f, 0x78, + 0xef, 0x7c, 0x32, 0x1e, 0xd5, 0x23, 0xca, 0x45, 0x1b, 0x3d, 0x87, 0xe3, 0xbd, 0x69, 0x31, 0xff, + 0xf8, 0x75, 0x7a, 0x36, 0x39, 0x37, 0x3a, 0x25, 0x77, 0x6f, 0xee, 0xb9, 0x46, 0x77, 0xb6, 0x80, + 0x21, 0x61, 0xc9, 0xc1, 0xbf, 0xb9, 0xd0, 0xbe, 0xe9, 0xb5, 0xf1, 0x4f, 0xe3, 0xe4, 0xb3, 0xe5, + 0x87, 0x05, 0x76, 0x4a, 0xf5, 0x42, 0xa9, 0x97, 0xf7, 0xaf, 0x6f, 0xda, 0x0a, 0xca, 0xd9, 0xbf, + 0x00, 0x00, 0x00, 0xff, 0xff, 0x02, 0xd5, 0x9f, 0x8c, 0x4d, 0x03, 0x00, 0x00, } diff --git a/proxy/shadowsocks/config.proto b/proxy/shadowsocks/config.proto index fbc2c912e..a9a9fb5a1 100644 --- a/proxy/shadowsocks/config.proto +++ b/proxy/shadowsocks/config.proto @@ -29,6 +29,7 @@ enum CipherType { AES_128_GCM = 5; AES_256_GCM = 6; CHACHA20_POLY1305 = 7; + NONE = 8; } message ServerConfig { @@ -38,4 +39,4 @@ message ServerConfig { message ClientConfig { repeated v2ray.core.common.protocol.ServerEndpoint server = 1; -} \ No newline at end of file +} diff --git a/proxy/shadowsocks/ota.go b/proxy/shadowsocks/ota.go index eb8e37072..3d9396822 100644 --- a/proxy/shadowsocks/ota.go +++ b/proxy/shadowsocks/ota.go @@ -6,6 +6,7 @@ import ( "crypto/sha1" "io" + "v2ray.com/core/common" "v2ray.com/core/common/buf" "v2ray.com/core/common/serial" ) @@ -29,7 +30,7 @@ func NewAuthenticator(keygen KeyGenerator) *Authenticator { func (v *Authenticator) Authenticate(data []byte) buf.Supplier { hasher := hmac.New(sha1.New, v.key()) - hasher.Write(data) + common.Must2(hasher.Write(data)) res := hasher.Sum(nil) return func(b []byte) (int, error) { return copy(b, res[:AuthSize]), nil @@ -68,7 +69,7 @@ func NewChunkReader(reader io.Reader, auth *Authenticator) *ChunkReader { } } -func (v *ChunkReader) Read() (buf.MultiBuffer, error) { +func (v *ChunkReader) ReadMultiBuffer() (buf.MultiBuffer, error) { buffer := buf.New() if err := buffer.AppendSupplier(buf.ReadFullFrom(v.reader, 2)); err != nil { buffer.Release() @@ -117,8 +118,8 @@ func NewChunkWriter(writer io.Writer, auth *Authenticator) *ChunkWriter { } } -// Write implements buf.MultiBufferWriter. -func (w *ChunkWriter) Write(mb buf.MultiBuffer) error { +// WriteMultiBuffer implements buf.Writer. +func (w *ChunkWriter) WriteMultiBuffer(mb buf.MultiBuffer) error { defer mb.Release() for { diff --git a/proxy/shadowsocks/ota_test.go b/proxy/shadowsocks/ota_test.go index dda777e1d..95064444f 100644 --- a/proxy/shadowsocks/ota_test.go +++ b/proxy/shadowsocks/ota_test.go @@ -5,24 +5,24 @@ import ( "v2ray.com/core/common/buf" . "v2ray.com/core/proxy/shadowsocks" - "v2ray.com/core/testing/assert" + . "v2ray.com/ext/assert" ) func TestNormalChunkReading(t *testing.T) { - assert := assert.On(t) + assert := With(t) buffer := buf.New() buffer.AppendBytes( 0, 8, 39, 228, 69, 96, 133, 39, 254, 26, 201, 70, 11, 12, 13, 14, 15, 16, 17, 18) reader := NewChunkReader(buffer, NewAuthenticator(ChunkKeyGenerator( []byte{21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36}))) - payload, err := reader.Read() - assert.Error(err).IsNil() - assert.Bytes(payload[0].Bytes()).Equals([]byte{11, 12, 13, 14, 15, 16, 17, 18}) + payload, err := reader.ReadMultiBuffer() + assert(err, IsNil) + assert(payload[0].Bytes(), Equals, []byte{11, 12, 13, 14, 15, 16, 17, 18}) } func TestNormalChunkWriting(t *testing.T) { - assert := assert.On(t) + assert := With(t) buffer := buf.NewLocal(512) writer := NewChunkWriter(buffer, NewAuthenticator(ChunkKeyGenerator( @@ -30,7 +30,7 @@ func TestNormalChunkWriting(t *testing.T) { b := buf.NewLocal(256) b.Append([]byte{11, 12, 13, 14, 15, 16, 17, 18}) - err := writer.Write(buf.NewMultiBufferValue(b)) - assert.Error(err).IsNil() - assert.Bytes(buffer.Bytes()).Equals([]byte{0, 8, 39, 228, 69, 96, 133, 39, 254, 26, 201, 70, 11, 12, 13, 14, 15, 16, 17, 18}) + err := writer.WriteMultiBuffer(buf.NewMultiBufferValue(b)) + assert(err, IsNil) + assert(buffer.Bytes(), Equals, []byte{0, 8, 39, 228, 69, 96, 133, 39, 254, 26, 201, 70, 11, 12, 13, 14, 15, 16, 17, 18}) } diff --git a/proxy/shadowsocks/protocol.go b/proxy/shadowsocks/protocol.go index a9cd686c3..27f1520e2 100644 --- a/proxy/shadowsocks/protocol.go +++ b/proxy/shadowsocks/protocol.go @@ -5,16 +5,17 @@ import ( "crypto/rand" "io" + "v2ray.com/core/common" + "v2ray.com/core/common/bitmask" "v2ray.com/core/common/buf" - "v2ray.com/core/common/crypto" "v2ray.com/core/common/net" "v2ray.com/core/common/protocol" "v2ray.com/core/common/serial" ) const ( - Version = 1 - RequestOptionOneTimeAuth = protocol.RequestOption(101) + Version = 1 + RequestOptionOneTimeAuth bitmask.Byte = 0x01 AddrTypeIPv4 = 1 AddrTypeIPv6 = 4 @@ -26,23 +27,27 @@ func ReadTCPSession(user *protocol.User, reader io.Reader) (*protocol.RequestHea if err != nil { return nil, nil, newError("failed to parse account").Base(err).AtError() } - account := rawAccount.(*ShadowsocksAccount) + account := rawAccount.(*MemoryAccount) buffer := buf.NewLocal(512) defer buffer.Release() ivLen := account.Cipher.IVSize() - if err := buffer.AppendSupplier(buf.ReadFullFrom(reader, ivLen)); err != nil { - return nil, nil, newError("failed to read IV").Base(err) + var iv []byte + if ivLen > 0 { + if err := buffer.AppendSupplier(buf.ReadFullFrom(reader, ivLen)); err != nil { + return nil, nil, newError("failed to read IV").Base(err) + } + + iv = append([]byte(nil), buffer.BytesTo(ivLen)...) } - iv := append([]byte(nil), buffer.BytesTo(ivLen)...) - - stream, err := account.Cipher.NewDecodingStream(account.Key, iv) + r, err := account.Cipher.NewDecryptionReader(account.Key, iv, reader) if err != nil { return nil, nil, newError("failed to initialize decoding stream").Base(err).AtError() } - reader = crypto.NewCryptionReader(stream, reader) + br := buf.NewBufferedReader(r) + reader = nil authenticator := NewAuthenticator(HeaderKeyGenerator(account.Key, iv)) request := &protocol.RequestHeader{ @@ -51,40 +56,42 @@ func ReadTCPSession(user *protocol.User, reader io.Reader) (*protocol.RequestHea Command: protocol.RequestCommandTCP, } - if err := buffer.Reset(buf.ReadFullFrom(reader, 1)); err != nil { + if err := buffer.Reset(buf.ReadFullFrom(br, 1)); err != nil { return nil, nil, newError("failed to read address type").Base(err) } + if !account.Cipher.IsAEAD() { + if (buffer.Byte(0) & 0x10) == 0x10 { + request.Option.Set(RequestOptionOneTimeAuth) + } + + if request.Option.Has(RequestOptionOneTimeAuth) && account.OneTimeAuth == Account_Disabled { + return nil, nil, newError("rejecting connection with OTA enabled, while server disables OTA") + } + + if !request.Option.Has(RequestOptionOneTimeAuth) && account.OneTimeAuth == Account_Enabled { + return nil, nil, newError("rejecting connection with OTA disabled, while server enables OTA") + } + } + addrType := (buffer.Byte(0) & 0x0F) - if (buffer.Byte(0) & 0x10) == 0x10 { - request.Option.Set(RequestOptionOneTimeAuth) - } - - if request.Option.Has(RequestOptionOneTimeAuth) && account.OneTimeAuth == Account_Disabled { - return nil, nil, newError("rejecting connection with OTA enabled, while server disables OTA") - } - - if !request.Option.Has(RequestOptionOneTimeAuth) && account.OneTimeAuth == Account_Enabled { - return nil, nil, newError("rejecting connection with OTA disabled, while server enables OTA") - } - switch addrType { case AddrTypeIPv4: - if err := buffer.AppendSupplier(buf.ReadFullFrom(reader, 4)); err != nil { + if err := buffer.AppendSupplier(buf.ReadFullFrom(br, 4)); err != nil { return nil, nil, newError("failed to read IPv4 address").Base(err) } request.Address = net.IPAddress(buffer.BytesFrom(-4)) case AddrTypeIPv6: - if err := buffer.AppendSupplier(buf.ReadFullFrom(reader, 16)); err != nil { + if err := buffer.AppendSupplier(buf.ReadFullFrom(br, 16)); err != nil { return nil, nil, newError("failed to read IPv6 address").Base(err) } request.Address = net.IPAddress(buffer.BytesFrom(-16)) case AddrTypeDomain: - if err := buffer.AppendSupplier(buf.ReadFullFrom(reader, 1)); err != nil { + if err := buffer.AppendSupplier(buf.ReadFullFrom(br, 1)); err != nil { return nil, nil, newError("failed to read domain lenth.").Base(err) } domainLength := int(buffer.BytesFrom(-1)[0]) - err = buffer.AppendSupplier(buf.ReadFullFrom(reader, domainLength)) + err = buffer.AppendSupplier(buf.ReadFullFrom(br, domainLength)) if err != nil { return nil, nil, newError("failed to read domain").Base(err) } @@ -93,7 +100,7 @@ func ReadTCPSession(user *protocol.User, reader io.Reader) (*protocol.RequestHea // Check address validity after OTA verification. } - err = buffer.AppendSupplier(buf.ReadFullFrom(reader, 2)) + err = buffer.AppendSupplier(buf.ReadFullFrom(br, 2)) if err != nil { return nil, nil, newError("failed to read port").Base(err) } @@ -103,7 +110,7 @@ func ReadTCPSession(user *protocol.User, reader io.Reader) (*protocol.RequestHea actualAuth := make([]byte, AuthSize) authenticator.Authenticate(buffer.Bytes())(actualAuth) - err := buffer.AppendSupplier(buf.ReadFullFrom(reader, AuthSize)) + err := buffer.AppendSupplier(buf.ReadFullFrom(br, AuthSize)) if err != nil { return nil, nil, newError("Failed to read OTA").Base(err) } @@ -117,11 +124,13 @@ func ReadTCPSession(user *protocol.User, reader io.Reader) (*protocol.RequestHea return nil, nil, newError("invalid remote address.") } + br.SetBuffered(false) + var chunkReader buf.Reader if request.Option.Has(RequestOptionOneTimeAuth) { - chunkReader = NewChunkReader(reader, NewAuthenticator(ChunkKeyGenerator(iv))) + chunkReader = NewChunkReader(br, NewAuthenticator(ChunkKeyGenerator(iv))) } else { - chunkReader = buf.NewReader(reader) + chunkReader = buf.NewReader(br) } return request, chunkReader, nil @@ -133,22 +142,27 @@ func WriteTCPRequest(request *protocol.RequestHeader, writer io.Writer) (buf.Wri if err != nil { return nil, newError("failed to parse account").Base(err).AtError() } - account := rawAccount.(*ShadowsocksAccount) + account := rawAccount.(*MemoryAccount) - iv := make([]byte, account.Cipher.IVSize()) - rand.Read(iv) - _, err = writer.Write(iv) - if err != nil { - return nil, newError("failed to write IV") + if account.Cipher.IsAEAD() { + request.Option.Clear(RequestOptionOneTimeAuth) } - stream, err := account.Cipher.NewEncodingStream(account.Key, iv) + var iv []byte + if account.Cipher.IVSize() > 0 { + iv = make([]byte, account.Cipher.IVSize()) + common.Must2(rand.Read(iv)) + _, err = writer.Write(iv) + if err != nil { + return nil, newError("failed to write IV") + } + } + + w, err := account.Cipher.NewEncryptionWriter(account.Key, iv, writer) if err != nil { return nil, newError("failed to create encoding stream").Base(err).AtError() } - writer = crypto.NewCryptionWriter(stream, writer) - header := buf.NewLocal(512) switch request.Address.Family() { @@ -159,31 +173,34 @@ func WriteTCPRequest(request *protocol.RequestHeader, writer io.Writer) (buf.Wri header.AppendBytes(AddrTypeIPv6) header.Append([]byte(request.Address.IP())) case net.AddressFamilyDomain: - header.AppendBytes(AddrTypeDomain, byte(len(request.Address.Domain()))) - header.Append([]byte(request.Address.Domain())) + domain := request.Address.Domain() + if protocol.IsDomainTooLong(domain) { + return nil, newError("domain name too long: ", domain) + } + header.AppendBytes(AddrTypeDomain, byte(len(domain))) + common.Must(header.AppendSupplier(serial.WriteString(domain))) default: return nil, newError("unsupported address type: ", request.Address.Family()) } - header.AppendSupplier(serial.WriteUint16(uint16(request.Port))) + common.Must(header.AppendSupplier(serial.WriteUint16(uint16(request.Port)))) if request.Option.Has(RequestOptionOneTimeAuth) { header.SetByte(0, header.Byte(0)|0x10) authenticator := NewAuthenticator(HeaderKeyGenerator(account.Key, iv)) - header.AppendSupplier(authenticator.Authenticate(header.Bytes())) + common.Must(header.AppendSupplier(authenticator.Authenticate(header.Bytes()))) } - _, err = writer.Write(header.Bytes()) - if err != nil { + if err := w.WriteMultiBuffer(buf.NewMultiBufferValue(header)); err != nil { return nil, newError("failed to write header").Base(err) } var chunkWriter buf.Writer if request.Option.Has(RequestOptionOneTimeAuth) { - chunkWriter = NewChunkWriter(writer, NewAuthenticator(ChunkKeyGenerator(iv))) + chunkWriter = NewChunkWriter(w.(io.Writer), NewAuthenticator(ChunkKeyGenerator(iv))) } else { - chunkWriter = buf.NewWriter(writer) + chunkWriter = w } return chunkWriter, nil @@ -194,19 +211,18 @@ func ReadTCPResponse(user *protocol.User, reader io.Reader) (buf.Reader, error) if err != nil { return nil, newError("failed to parse account").Base(err).AtError() } - account := rawAccount.(*ShadowsocksAccount) + account := rawAccount.(*MemoryAccount) - iv := make([]byte, account.Cipher.IVSize()) - _, err = io.ReadFull(reader, iv) - if err != nil { - return nil, newError("failed to read IV").Base(err) + var iv []byte + if account.Cipher.IVSize() > 0 { + iv = make([]byte, account.Cipher.IVSize()) + _, err = io.ReadFull(reader, iv) + if err != nil { + return nil, newError("failed to read IV").Base(err) + } } - stream, err := account.Cipher.NewDecodingStream(account.Key, iv) - if err != nil { - return nil, newError("failed to initialize decoding stream").Base(err).AtError() - } - return buf.NewReader(crypto.NewCryptionReader(stream, reader)), nil + return account.Cipher.NewDecryptionReader(account.Key, iv, reader) } func WriteTCPResponse(request *protocol.RequestHeader, writer io.Writer) (buf.Writer, error) { @@ -215,21 +231,19 @@ func WriteTCPResponse(request *protocol.RequestHeader, writer io.Writer) (buf.Wr if err != nil { return nil, newError("failed to parse account.").Base(err).AtError() } - account := rawAccount.(*ShadowsocksAccount) + account := rawAccount.(*MemoryAccount) - iv := make([]byte, account.Cipher.IVSize()) - rand.Read(iv) - _, err = writer.Write(iv) - if err != nil { - return nil, newError("failed to write IV.").Base(err) + var iv []byte + if account.Cipher.IVSize() > 0 { + iv = make([]byte, account.Cipher.IVSize()) + common.Must2(rand.Read(iv)) + _, err = writer.Write(iv) + if err != nil { + return nil, newError("failed to write IV.").Base(err) + } } - stream, err := account.Cipher.NewEncodingStream(account.Key, iv) - if err != nil { - return nil, newError("failed to create encoding stream.").Base(err).AtError() - } - - return buf.NewWriter(crypto.NewCryptionWriter(stream, writer)), nil + return account.Cipher.NewEncryptionWriter(account.Key, iv, writer) } func EncodeUDPPacket(request *protocol.RequestHeader, payload []byte) (*buf.Buffer, error) { @@ -238,11 +252,13 @@ func EncodeUDPPacket(request *protocol.RequestHeader, payload []byte) (*buf.Buff if err != nil { return nil, newError("failed to parse account.").Base(err).AtError() } - account := rawAccount.(*ShadowsocksAccount) + account := rawAccount.(*MemoryAccount) buffer := buf.New() ivLen := account.Cipher.IVSize() - buffer.AppendSupplier(buf.ReadFullFrom(rand.Reader, ivLen)) + if ivLen > 0 { + common.Must(buffer.Reset(buf.ReadFullFrom(rand.Reader, ivLen))) + } iv := buffer.Bytes() switch request.Address.Family() { @@ -259,22 +275,19 @@ func EncodeUDPPacket(request *protocol.RequestHeader, payload []byte) (*buf.Buff return nil, newError("unsupported address type: ", request.Address.Family()).AtError() } - buffer.AppendSupplier(serial.WriteUint16(uint16(request.Port))) + common.Must(buffer.AppendSupplier(serial.WriteUint16(uint16(request.Port)))) buffer.Append(payload) - if request.Option.Has(RequestOptionOneTimeAuth) { + if !account.Cipher.IsAEAD() && request.Option.Has(RequestOptionOneTimeAuth) { authenticator := NewAuthenticator(HeaderKeyGenerator(account.Key, iv)) buffer.SetByte(ivLen, buffer.Byte(ivLen)|0x10) - buffer.AppendSupplier(authenticator.Authenticate(buffer.BytesFrom(ivLen))) + common.Must(buffer.AppendSupplier(authenticator.Authenticate(buffer.BytesFrom(ivLen)))) + } + if err := account.Cipher.EncodePacket(account.Key, buffer); err != nil { + return nil, newError("failed to encrypt UDP payload").Base(err) } - stream, err := account.Cipher.NewEncodingStream(account.Key, iv) - if err != nil { - return nil, newError("failed to create encoding stream").Base(err).AtError() - } - - stream.XORKeyStream(buffer.BytesFrom(ivLen), buffer.BytesFrom(ivLen)) return buffer, nil } @@ -283,53 +296,55 @@ func DecodeUDPPacket(user *protocol.User, payload *buf.Buffer) (*protocol.Reques if err != nil { return nil, nil, newError("failed to parse account").Base(err).AtError() } - account := rawAccount.(*ShadowsocksAccount) + account := rawAccount.(*MemoryAccount) - ivLen := account.Cipher.IVSize() - iv := payload.BytesTo(ivLen) - payload.SliceFrom(ivLen) - - stream, err := account.Cipher.NewDecodingStream(account.Key, iv) - if err != nil { - return nil, nil, newError("failed to initialize decoding stream").Base(err).AtError() + var iv []byte + if !account.Cipher.IsAEAD() && account.Cipher.IVSize() > 0 { + // Keep track of IV as it gets removed from payload in DecodePacket. + iv = make([]byte, account.Cipher.IVSize()) + copy(iv, payload.BytesTo(account.Cipher.IVSize())) + } + + if err := account.Cipher.DecodePacket(account.Key, payload); err != nil { + return nil, nil, newError("failed to decrypt UDP payload").Base(err) } - stream.XORKeyStream(payload.Bytes(), payload.Bytes()) - authenticator := NewAuthenticator(HeaderKeyGenerator(account.Key, iv)) request := &protocol.RequestHeader{ Version: Version, User: user, Command: protocol.RequestCommandUDP, } - addrType := (payload.Byte(0) & 0x0F) - if (payload.Byte(0) & 0x10) == 0x10 { - request.Option |= RequestOptionOneTimeAuth - } - - if request.Option.Has(RequestOptionOneTimeAuth) && account.OneTimeAuth == Account_Disabled { - return nil, nil, newError("rejecting packet with OTA enabled, while server disables OTA").AtWarning() - } - - if !request.Option.Has(RequestOptionOneTimeAuth) && account.OneTimeAuth == Account_Enabled { - return nil, nil, newError("rejecting packet with OTA disabled, while server enables OTA").AtWarning() - } - - if request.Option.Has(RequestOptionOneTimeAuth) { - payloadLen := payload.Len() - AuthSize - authBytes := payload.BytesFrom(payloadLen) - - actualAuth := make([]byte, AuthSize) - authenticator.Authenticate(payload.BytesTo(payloadLen))(actualAuth) - if !bytes.Equal(actualAuth, authBytes) { - return nil, nil, newError("invalid OTA") + if !account.Cipher.IsAEAD() { + if (payload.Byte(0) & 0x10) == 0x10 { + request.Option |= RequestOptionOneTimeAuth } - payload.Slice(0, payloadLen) + if request.Option.Has(RequestOptionOneTimeAuth) && account.OneTimeAuth == Account_Disabled { + return nil, nil, newError("rejecting packet with OTA enabled, while server disables OTA").AtWarning() + } + + if !request.Option.Has(RequestOptionOneTimeAuth) && account.OneTimeAuth == Account_Enabled { + return nil, nil, newError("rejecting packet with OTA disabled, while server enables OTA").AtWarning() + } + + if request.Option.Has(RequestOptionOneTimeAuth) { + payloadLen := payload.Len() - AuthSize + authBytes := payload.BytesFrom(payloadLen) + + authenticator := NewAuthenticator(HeaderKeyGenerator(account.Key, iv)) + actualAuth := make([]byte, AuthSize) + authenticator.Authenticate(payload.BytesTo(payloadLen))(actualAuth) + if !bytes.Equal(actualAuth, authBytes) { + return nil, nil, newError("invalid OTA") + } + + payload.Slice(0, payloadLen) + } } + addrType := (payload.Byte(0) & 0x0F) payload.SliceFrom(1) - switch addrType { case AddrTypeIPv4: request.Address = net.IPAddress(payload.BytesTo(4)) @@ -356,7 +371,7 @@ type UDPReader struct { User *protocol.User } -func (v *UDPReader) Read() (buf.MultiBuffer, error) { +func (v *UDPReader) ReadMultiBuffer() (buf.MultiBuffer, error) { buffer := buf.New() err := buffer.AppendSupplier(buf.ReadFrom(v.Reader)) if err != nil { diff --git a/proxy/shadowsocks/protocol_test.go b/proxy/shadowsocks/protocol_test.go index 5371868c8..f2cb3c0a3 100644 --- a/proxy/shadowsocks/protocol_test.go +++ b/proxy/shadowsocks/protocol_test.go @@ -8,11 +8,11 @@ import ( "v2ray.com/core/common/protocol" "v2ray.com/core/common/serial" . "v2ray.com/core/proxy/shadowsocks" - "v2ray.com/core/testing/assert" + . "v2ray.com/ext/assert" ) func TestUDPEncoding(t *testing.T) { - assert := assert.On(t) + assert := With(t) request := &protocol.RequestHeader{ Version: Version, @@ -32,17 +32,17 @@ func TestUDPEncoding(t *testing.T) { data := buf.NewLocal(256) data.AppendSupplier(serial.WriteString("test string")) encodedData, err := EncodeUDPPacket(request, data.Bytes()) - assert.Error(err).IsNil() + assert(err, IsNil) decodedRequest, decodedData, err := DecodeUDPPacket(request.User, encodedData) - assert.Error(err).IsNil() - assert.Bytes(decodedData.Bytes()).Equals(data.Bytes()) - assert.Address(decodedRequest.Address).Equals(request.Address) - assert.Port(decodedRequest.Port).Equals(request.Port) + assert(err, IsNil) + assert(decodedData.Bytes(), Equals, data.Bytes()) + assert(decodedRequest.Address, Equals, request.Address) + assert(decodedRequest.Port, Equals, request.Port) } func TestTCPRequest(t *testing.T) { - assert := assert.On(t) + assert := With(t) cases := []struct { request *protocol.RequestHeader @@ -110,18 +110,18 @@ func TestTCPRequest(t *testing.T) { defer cache.Release() writer, err := WriteTCPRequest(request, cache) - assert.Error(err).IsNil() + assert(err, IsNil) - assert.Error(writer.Write(buf.NewMultiBufferValue(data))).IsNil() + assert(writer.WriteMultiBuffer(buf.NewMultiBufferValue(data)), IsNil) decodedRequest, reader, err := ReadTCPSession(request.User, cache) - assert.Error(err).IsNil() - assert.Address(decodedRequest.Address).Equals(request.Address) - assert.Port(decodedRequest.Port).Equals(request.Port) + assert(err, IsNil) + assert(decodedRequest.Address, Equals, request.Address) + assert(decodedRequest.Port, Equals, request.Port) - decodedData, err := reader.Read() - assert.Error(err).IsNil() - assert.String(decodedData[0].String()).Equals(string(payload)) + decodedData, err := reader.ReadMultiBuffer() + assert(err, IsNil) + assert(decodedData[0].String(), Equals, string(payload)) } for _, test := range cases { @@ -131,7 +131,7 @@ func TestTCPRequest(t *testing.T) { } func TestUDPReaderWriter(t *testing.T) { - assert := assert.On(t) + assert := With(t) user := &protocol.User{ Account: serial.ToTypedMessage(&Account{ @@ -158,19 +158,19 @@ func TestUDPReaderWriter(t *testing.T) { b := buf.New() b.AppendSupplier(serial.WriteString("test payload")) - err := writer.Write(buf.NewMultiBufferValue(b)) - assert.Error(err).IsNil() + err := writer.WriteMultiBuffer(buf.NewMultiBufferValue(b)) + assert(err, IsNil) - payload, err := reader.Read() - assert.Error(err).IsNil() - assert.String(payload[0].String()).Equals("test payload") + payload, err := reader.ReadMultiBuffer() + assert(err, IsNil) + assert(payload[0].String(), Equals, "test payload") b = buf.New() b.AppendSupplier(serial.WriteString("test payload 2")) - err = writer.Write(buf.NewMultiBufferValue(b)) - assert.Error(err).IsNil() + err = writer.WriteMultiBuffer(buf.NewMultiBufferValue(b)) + assert(err, IsNil) - payload, err = reader.Read() - assert.Error(err).IsNil() - assert.String(payload[0].String()).Equals("test payload 2") + payload, err = reader.ReadMultiBuffer() + assert(err, IsNil) + assert(payload[0].String(), Equals, "test payload 2") } diff --git a/proxy/shadowsocks/server.go b/proxy/shadowsocks/server.go index 509291dc3..52434fcb5 100644 --- a/proxy/shadowsocks/server.go +++ b/proxy/shadowsocks/server.go @@ -2,12 +2,12 @@ package shadowsocks import ( "context" - "runtime" "time" "v2ray.com/core/app" "v2ray.com/core/app/dispatcher" "v2ray.com/core/app/log" + "v2ray.com/core/app/policy" "v2ray.com/core/common" "v2ray.com/core/common/buf" "v2ray.com/core/common/net" @@ -19,9 +19,10 @@ import ( ) type Server struct { - config *ServerConfig - user *protocol.User - account *ShadowsocksAccount + config *ServerConfig + user *protocol.User + account *MemoryAccount + policyManager policy.Manager } // NewServer create a new Shadowsocks server. @@ -38,7 +39,7 @@ func NewServer(ctx context.Context, config *ServerConfig) (*Server, error) { if err != nil { return nil, newError("failed to get user account").Base(err) } - account := rawAccount.(*ShadowsocksAccount) + account := rawAccount.(*MemoryAccount) s := &Server{ config: config, @@ -46,6 +47,15 @@ func NewServer(ctx context.Context, config *ServerConfig) (*Server, error) { account: account, } + space.On(app.SpaceInitializing, func(interface{}) error { + pm := policy.FromSpace(space) + if pm == nil { + return newError("Policy not found in space.") + } + s.policyManager = pm + return nil + }) + return s, nil } @@ -75,7 +85,7 @@ func (s *Server) handlerUDPPayload(ctx context.Context, conn internet.Connection reader := buf.NewReader(conn) for { - mpayload, err := reader.Read() + mpayload, err := reader.ReadMultiBuffer() if err != nil { break } @@ -129,8 +139,9 @@ func (s *Server) handlerUDPPayload(ctx context.Context, conn internet.Connection } func (s *Server) handleConnection(ctx context.Context, conn internet.Connection, dispatcher dispatcher.Interface) error { - conn.SetReadDeadline(time.Now().Add(time.Second * 8)) - bufferedReader := buf.NewBufferedReader(conn) + sessionPolicy := s.policyManager.GetPolicy(s.user.Level) + conn.SetReadDeadline(time.Now().Add(sessionPolicy.Timeout.Handshake.Duration())) + bufferedReader := buf.NewBufferedReader(buf.NewReader(conn)) request, bodyReader, err := ReadTCPSession(s.user, bufferedReader) if err != nil { log.Access(conn.RemoteAddr(), "", log.AccessRejected, err) @@ -146,25 +157,25 @@ func (s *Server) handleConnection(ctx context.Context, conn internet.Connection, ctx = protocol.ContextWithUser(ctx, request.User) - userSettings := s.user.GetSettings() - ctx, timer := signal.CancelAfterInactivity(ctx, userSettings.PayloadTimeout) + ctx, cancel := context.WithCancel(ctx) + timer := signal.CancelAfterInactivity(ctx, cancel, sessionPolicy.Timeout.ConnectionIdle.Duration()) ray, err := dispatcher.Dispatch(ctx, dest) if err != nil { return err } responseDone := signal.ExecuteAsync(func() error { - bufferedWriter := buf.NewBufferedWriter(conn) + bufferedWriter := buf.NewBufferedWriter(buf.NewWriter(conn)) responseWriter, err := WriteTCPResponse(request, bufferedWriter) if err != nil { return newError("failed to write response").Base(err) } - payload, err := ray.InboundOutput().Read() + payload, err := ray.InboundOutput().ReadMultiBuffer() if err != nil { return err } - if err := responseWriter.Write(payload); err != nil { + if err := responseWriter.WriteMultiBuffer(payload); err != nil { return err } payload.Release() @@ -177,7 +188,7 @@ func (s *Server) handleConnection(ctx context.Context, conn internet.Connection, return newError("failed to transport all TCP response").Base(err) } - timer.SetTimeout(time.Second * 2) + timer.SetTimeout(sessionPolicy.Timeout.UplinkOnly.Duration()) return nil }) @@ -188,6 +199,7 @@ func (s *Server) handleConnection(ctx context.Context, conn internet.Connection, if err := buf.Copy(bodyReader, ray.InboundInput(), buf.UpdateActivity(timer)); err != nil { return newError("failed to transport all TCP request").Base(err) } + timer.SetTimeout(sessionPolicy.Timeout.DownlinkOnly.Duration()) return nil }) @@ -197,8 +209,6 @@ func (s *Server) handleConnection(ctx context.Context, conn internet.Connection, return newError("connection ends").Base(err) } - runtime.KeepAlive(timer) - return nil } diff --git a/proxy/socks/client.go b/proxy/socks/client.go index e227e3b28..ea97b8362 100644 --- a/proxy/socks/client.go +++ b/proxy/socks/client.go @@ -2,7 +2,6 @@ package socks import ( "context" - "runtime" "time" "v2ray.com/core/common" @@ -84,7 +83,8 @@ func (c *Client) Process(ctx context.Context, ray ray.OutboundRay, dialer proxy. return newError("failed to establish connection to server").AtWarning().Base(err) } - ctx, timer := signal.CancelAfterInactivity(ctx, time.Minute*5) + ctx, cancel := context.WithCancel(ctx) + timer := signal.CancelAfterInactivity(ctx, cancel, time.Minute*5) var requestFunc func() error var responseFunc func() error @@ -118,8 +118,6 @@ func (c *Client) Process(ctx context.Context, ray ray.OutboundRay, dialer proxy. return newError("connection ends").Base(err) } - runtime.KeepAlive(timer) - return nil } diff --git a/proxy/socks/config.pb.go b/proxy/socks/config.pb.go index 74942bdc5..3b664de9b 100644 --- a/proxy/socks/config.pb.go +++ b/proxy/socks/config.pb.go @@ -68,6 +68,7 @@ type ServerConfig struct { Address *v2ray_core_common_net.IPOrDomain `protobuf:"bytes,3,opt,name=address" json:"address,omitempty"` UdpEnabled bool `protobuf:"varint,4,opt,name=udp_enabled,json=udpEnabled" json:"udp_enabled,omitempty"` Timeout uint32 `protobuf:"varint,5,opt,name=timeout" json:"timeout,omitempty"` + UserLevel uint32 `protobuf:"varint,6,opt,name=user_level,json=userLevel" json:"user_level,omitempty"` } func (m *ServerConfig) Reset() { *m = ServerConfig{} } @@ -110,6 +111,13 @@ func (m *ServerConfig) GetTimeout() uint32 { return 0 } +func (m *ServerConfig) GetUserLevel() uint32 { + if m != nil { + return m.UserLevel + } + return 0 +} + type ClientConfig struct { Server []*v2ray_core_common_protocol1.ServerEndpoint `protobuf:"bytes,1,rep,name=server" json:"server,omitempty"` } @@ -136,34 +144,35 @@ func init() { func init() { proto.RegisterFile("v2ray.com/core/proxy/socks/config.proto", fileDescriptor0) } var fileDescriptor0 = []byte{ - // 449 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x74, 0x91, 0xd1, 0x6e, 0xd3, 0x3e, - 0x14, 0xc6, 0xff, 0x49, 0xff, 0x5d, 0xb3, 0xd3, 0x0e, 0x55, 0x16, 0x9a, 0xa2, 0xdc, 0x10, 0x2a, - 0x21, 0xa2, 0x5d, 0x38, 0x28, 0xdc, 0x20, 0x26, 0x90, 0xb2, 0xae, 0x12, 0xdc, 0xac, 0x95, 0x3b, - 0x40, 0xe2, 0xa6, 0xf2, 0x1c, 0xc3, 0xa2, 0x35, 0x76, 0x64, 0x3b, 0x85, 0xbc, 0x12, 0x8f, 0xc3, - 0x13, 0xa1, 0xda, 0xc9, 0x34, 0x50, 0x77, 0x77, 0x4e, 0xce, 0x77, 0xbe, 0x9c, 0xef, 0x67, 0x78, - 0xb9, 0xcb, 0x14, 0x6d, 0x31, 0x93, 0x55, 0xca, 0xa4, 0xe2, 0x69, 0xad, 0xe4, 0xcf, 0x36, 0xd5, - 0x92, 0xdd, 0xe9, 0x94, 0x49, 0xf1, 0xad, 0xfc, 0x8e, 0x6b, 0x25, 0x8d, 0x44, 0xa7, 0xbd, 0x50, - 0x71, 0x6c, 0x45, 0xd8, 0x8a, 0xa2, 0x7f, 0x0d, 0x98, 0xac, 0x2a, 0x29, 0x52, 0xc1, 0x4d, 0x4a, - 0x8b, 0x42, 0x71, 0xad, 0x9d, 0x41, 0xf4, 0xea, 0xb0, 0xd0, 0x0e, 0x99, 0xdc, 0xa6, 0x9a, 0xab, - 0x1d, 0x57, 0x1b, 0x5d, 0x73, 0xe6, 0x36, 0x66, 0x39, 0x8c, 0x72, 0xc6, 0x64, 0x23, 0x0c, 0x8a, - 0x20, 0x68, 0x34, 0x57, 0x82, 0x56, 0x3c, 0xf4, 0x62, 0x2f, 0x39, 0x26, 0xf7, 0xfd, 0x7e, 0x56, - 0x53, 0xad, 0x7f, 0x48, 0x55, 0x84, 0xbe, 0x9b, 0xf5, 0xfd, 0xec, 0xb7, 0x0f, 0x93, 0xb5, 0x35, - 0x9e, 0xdb, 0x30, 0xe8, 0x1d, 0x1c, 0xd3, 0xc6, 0xdc, 0x6e, 0x4c, 0x5b, 0x3b, 0xa7, 0x27, 0x59, - 0x8c, 0x0f, 0x47, 0xc3, 0x79, 0x63, 0x6e, 0xaf, 0xdb, 0x9a, 0x93, 0x80, 0x76, 0x15, 0xba, 0x82, - 0x80, 0xba, 0x93, 0x74, 0xe8, 0xc7, 0x83, 0x64, 0x9c, 0x65, 0x8f, 0x6d, 0x3f, 0xfc, 0x2d, 0xee, - 0x72, 0xe8, 0x85, 0x30, 0xaa, 0x25, 0xf7, 0x1e, 0xe8, 0x1c, 0x46, 0x1d, 0xa5, 0x70, 0x10, 0x7b, - 0xc9, 0x38, 0x7b, 0xfe, 0xd0, 0xce, 0x21, 0xc2, 0x82, 0x1b, 0xfc, 0x71, 0xb5, 0x54, 0x97, 0xb2, - 0xa2, 0xa5, 0x20, 0xfd, 0x06, 0x7a, 0x06, 0xe3, 0xa6, 0xa8, 0x37, 0x5c, 0xd0, 0x9b, 0x2d, 0x2f, - 0xc2, 0xff, 0x63, 0x2f, 0x09, 0x08, 0x34, 0x45, 0xbd, 0x70, 0x5f, 0x50, 0x08, 0x23, 0x53, 0x56, - 0x5c, 0x36, 0x26, 0x1c, 0xc6, 0x5e, 0x72, 0x42, 0xfa, 0x36, 0x3a, 0x87, 0x93, 0xbf, 0x4e, 0x42, - 0x53, 0x18, 0xdc, 0xf1, 0xb6, 0x63, 0xbb, 0x2f, 0xd1, 0x53, 0x18, 0xee, 0xe8, 0xb6, 0xe1, 0x1d, - 0x53, 0xd7, 0xbc, 0xf5, 0xdf, 0x78, 0x33, 0x02, 0x93, 0xf9, 0xb6, 0xe4, 0xc2, 0x74, 0x4c, 0x2f, - 0xe0, 0xc8, 0x3d, 0x5e, 0xe8, 0x59, 0x24, 0x67, 0x07, 0x32, 0xf4, 0xcf, 0xdc, 0x61, 0x59, 0x88, - 0xa2, 0x96, 0xa5, 0x30, 0xa4, 0xdb, 0x3c, 0x7b, 0x01, 0x41, 0x8f, 0x1b, 0x8d, 0x61, 0x74, 0xb5, - 0xdc, 0xe4, 0x9f, 0xae, 0x3f, 0x4c, 0xff, 0x43, 0x13, 0x08, 0x56, 0xf9, 0x7a, 0xfd, 0x65, 0x49, - 0x2e, 0xa7, 0xde, 0xc5, 0x7b, 0x88, 0x98, 0xac, 0x1e, 0x41, 0xbe, 0xf2, 0xbe, 0x0e, 0x6d, 0xf1, - 0xcb, 0x3f, 0xfd, 0x9c, 0x11, 0xda, 0xe2, 0xf9, 0x5e, 0xb1, 0xb2, 0x8a, 0xf5, 0x7e, 0x70, 0x73, - 0x64, 0xef, 0x78, 0xfd, 0x27, 0x00, 0x00, 0xff, 0xff, 0x57, 0x01, 0x54, 0x95, 0xf7, 0x02, 0x00, - 0x00, + // 470 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x74, 0x52, 0x5d, 0x8b, 0xd3, 0x40, + 0x14, 0x75, 0xb2, 0xb6, 0x4d, 0x6f, 0xbb, 0x52, 0x06, 0x59, 0x42, 0x51, 0x8c, 0x05, 0xb1, 0xec, + 0xc3, 0x44, 0xe2, 0x8b, 0xb8, 0x28, 0xb4, 0xdd, 0x82, 0x82, 0x6c, 0xcb, 0x74, 0x55, 0xf0, 0x25, + 0xcc, 0x4e, 0x46, 0x37, 0x6c, 0x32, 0x13, 0x66, 0x26, 0xd5, 0xfc, 0x25, 0xff, 0x9f, 0xef, 0x92, + 0xaf, 0x65, 0x95, 0xee, 0xdb, 0xfd, 0x38, 0xf7, 0xcc, 0x3d, 0xe7, 0x0e, 0xbc, 0xdc, 0x87, 0x9a, + 0x95, 0x84, 0xab, 0x2c, 0xe0, 0x4a, 0x8b, 0x20, 0xd7, 0xea, 0x57, 0x19, 0x18, 0xc5, 0x6f, 0x4c, + 0xc0, 0x95, 0xfc, 0x9e, 0xfc, 0x20, 0xb9, 0x56, 0x56, 0xe1, 0x93, 0x0e, 0xa8, 0x05, 0xa9, 0x41, + 0xa4, 0x06, 0x4d, 0xff, 0x27, 0xe0, 0x2a, 0xcb, 0x94, 0x0c, 0xa4, 0xb0, 0x01, 0x8b, 0x63, 0x2d, + 0x8c, 0x69, 0x08, 0xa6, 0xaf, 0x0e, 0x03, 0xeb, 0x26, 0x57, 0x69, 0x60, 0x84, 0xde, 0x0b, 0x1d, + 0x99, 0x5c, 0xf0, 0x66, 0x62, 0xb6, 0x80, 0xc1, 0x82, 0x73, 0x55, 0x48, 0x8b, 0xa7, 0xe0, 0x16, + 0x46, 0x68, 0xc9, 0x32, 0xe1, 0x21, 0x1f, 0xcd, 0x87, 0xf4, 0x36, 0xaf, 0x7a, 0x39, 0x33, 0xe6, + 0xa7, 0xd2, 0xb1, 0xe7, 0x34, 0xbd, 0x2e, 0x9f, 0xfd, 0x71, 0x60, 0xbc, 0xab, 0x89, 0x57, 0xb5, + 0x18, 0xfc, 0x0e, 0x86, 0xac, 0xb0, 0xd7, 0x91, 0x2d, 0xf3, 0x86, 0xe9, 0x51, 0xe8, 0x93, 0xc3, + 0xd2, 0xc8, 0xa2, 0xb0, 0xd7, 0x97, 0x65, 0x2e, 0xa8, 0xcb, 0xda, 0x08, 0x5f, 0x80, 0xcb, 0x9a, + 0x95, 0x8c, 0xe7, 0xf8, 0x47, 0xf3, 0x51, 0x18, 0xde, 0x37, 0x7d, 0xf7, 0x59, 0xd2, 0xea, 0x30, + 0x6b, 0x69, 0x75, 0x49, 0x6f, 0x39, 0xf0, 0x19, 0x0c, 0x5a, 0x97, 0xbc, 0x23, 0x1f, 0xcd, 0x47, + 0xe1, 0xf3, 0xbb, 0x74, 0x8d, 0x45, 0x44, 0x0a, 0x4b, 0x3e, 0x6e, 0x37, 0xfa, 0x5c, 0x65, 0x2c, + 0x91, 0xb4, 0x9b, 0xc0, 0xcf, 0x60, 0x54, 0xc4, 0x79, 0x24, 0x24, 0xbb, 0x4a, 0x45, 0xec, 0x3d, + 0xf4, 0xd1, 0xdc, 0xa5, 0x50, 0xc4, 0xf9, 0xba, 0xa9, 0xe0, 0x27, 0x30, 0xb0, 0x49, 0x26, 0x54, + 0x61, 0xbd, 0x9e, 0x8f, 0xe6, 0xc7, 0x4b, 0xc7, 0x43, 0xb4, 0x2b, 0xe1, 0xa7, 0x00, 0x95, 0x87, + 0x51, 0x2a, 0xf6, 0x22, 0xf5, 0xfa, 0x15, 0x80, 0x0e, 0xab, 0xca, 0xa7, 0xaa, 0x30, 0x3d, 0x83, + 0xe3, 0x7f, 0xb6, 0xc6, 0x13, 0x38, 0xba, 0x11, 0x65, 0x6b, 0x7f, 0x15, 0xe2, 0xc7, 0xd0, 0xdb, + 0xb3, 0xb4, 0x10, 0xad, 0xed, 0x4d, 0xf2, 0xd6, 0x79, 0x83, 0x66, 0x14, 0xc6, 0xab, 0x34, 0x11, + 0xd2, 0xb6, 0xb6, 0x2f, 0xa1, 0xdf, 0xdc, 0xd7, 0x43, 0xb5, 0x6b, 0xa7, 0x07, 0x64, 0x76, 0x3f, + 0xa1, 0x75, 0x6e, 0x2d, 0xe3, 0x5c, 0x25, 0xd2, 0xd2, 0x76, 0xf2, 0xf4, 0x05, 0xb8, 0xdd, 0x45, + 0xf0, 0x08, 0x06, 0x17, 0x9b, 0x68, 0xf1, 0xf9, 0xf2, 0xc3, 0xe4, 0x01, 0x1e, 0x83, 0xbb, 0x5d, + 0xec, 0x76, 0x5f, 0x37, 0xf4, 0x7c, 0x82, 0x96, 0xef, 0x61, 0xca, 0x55, 0x76, 0xcf, 0x55, 0xb6, + 0xe8, 0x5b, 0xaf, 0x0e, 0x7e, 0x3b, 0x27, 0x5f, 0x42, 0xca, 0x4a, 0xb2, 0xaa, 0x10, 0xdb, 0x1a, + 0xb1, 0xab, 0x1a, 0x57, 0xfd, 0x7a, 0x8f, 0xd7, 0x7f, 0x03, 0x00, 0x00, 0xff, 0xff, 0x23, 0xac, + 0x72, 0x71, 0x1a, 0x03, 0x00, 0x00, } diff --git a/proxy/socks/config.proto b/proxy/socks/config.proto index f6121c5e5..0d69862b4 100644 --- a/proxy/socks/config.proto +++ b/proxy/socks/config.proto @@ -24,9 +24,10 @@ message ServerConfig { map accounts = 2; v2ray.core.common.net.IPOrDomain address = 3; bool udp_enabled = 4; - uint32 timeout = 5; + uint32 timeout = 5 [deprecated = true]; + uint32 user_level = 6; } message ClientConfig { repeated v2ray.core.common.protocol.ServerEndpoint server = 1; -} \ No newline at end of file +} diff --git a/proxy/socks/protocol.go b/proxy/socks/protocol.go index d1432bb81..f5f255203 100644 --- a/proxy/socks/protocol.go +++ b/proxy/socks/protocol.go @@ -3,6 +3,7 @@ package socks import ( "io" + "v2ray.com/core/common" "v2ray.com/core/common/buf" "v2ray.com/core/common/net" "v2ray.com/core/common/protocol" @@ -253,14 +254,13 @@ func appendAddress(buffer *buf.Buffer, address net.Address, port net.Port) error buffer.AppendBytes(0x04) buffer.Append(address.IP()) case net.AddressFamilyDomain: - n := byte(len(address.Domain())) - if int(n) != len(address.Domain()) { - return newError("Super long domain is not supported in Socks protocol. ", address.Domain()) + if protocol.IsDomainTooLong(address.Domain()) { + return newError("Super long domain is not supported in Socks protocol: ", address.Domain()) } buffer.AppendBytes(0x03, byte(len(address.Domain()))) - buffer.AppendSupplier(serial.WriteString(address.Domain())) + common.Must(buffer.AppendSupplier(serial.WriteString(address.Domain()))) } - buffer.AppendSupplier(serial.WriteUint16(port.Value())) + common.Must(buffer.AppendSupplier(serial.WriteUint16(port.Value()))) return nil } @@ -352,7 +352,7 @@ func NewUDPReader(reader io.Reader) *UDPReader { return &UDPReader{reader: reader} } -func (r *UDPReader) Read() (buf.MultiBuffer, error) { +func (r *UDPReader) ReadMultiBuffer() (buf.MultiBuffer, error) { b := buf.New() if err := b.AppendSupplier(buf.ReadFrom(r.reader)); err != nil { return nil, err diff --git a/proxy/socks/protocol_test.go b/proxy/socks/protocol_test.go index f0111abc4..a5cb18cfb 100644 --- a/proxy/socks/protocol_test.go +++ b/proxy/socks/protocol_test.go @@ -7,11 +7,11 @@ import ( "v2ray.com/core/common/net" "v2ray.com/core/common/protocol" . "v2ray.com/core/proxy/socks" - "v2ray.com/core/testing/assert" + . "v2ray.com/ext/assert" ) func TestUDPEncoding(t *testing.T) { - assert := assert.On(t) + assert := With(t) b := buf.New() @@ -24,11 +24,11 @@ func TestUDPEncoding(t *testing.T) { content := []byte{'a'} payload := buf.New() payload.Append(content) - assert.Error(writer.Write(buf.NewMultiBufferValue(payload))).IsNil() + assert(writer.WriteMultiBuffer(buf.NewMultiBufferValue(payload)), IsNil) reader := NewUDPReader(b) - decodedPayload, err := reader.Read() - assert.Error(err).IsNil() - assert.Bytes(decodedPayload[0].Bytes()).Equals(content) + decodedPayload, err := reader.ReadMultiBuffer() + assert(err, IsNil) + assert(decodedPayload[0].Bytes(), Equals, content) } diff --git a/proxy/socks/server.go b/proxy/socks/server.go index 3bef8f5c9..8dca11245 100644 --- a/proxy/socks/server.go +++ b/proxy/socks/server.go @@ -3,12 +3,12 @@ package socks import ( "context" "io" - "runtime" "time" "v2ray.com/core/app" "v2ray.com/core/app/dispatcher" "v2ray.com/core/app/log" + "v2ray.com/core/app/policy" "v2ray.com/core/common" "v2ray.com/core/common/buf" "v2ray.com/core/common/net" @@ -22,6 +22,7 @@ import ( // Server is a SOCKS 5 proxy server type Server struct { config *ServerConfig + policy policy.Policy } // NewServer creates a new Server object. @@ -33,6 +34,17 @@ func NewServer(ctx context.Context, config *ServerConfig) (*Server, error) { s := &Server{ config: config, } + space.On(app.SpaceInitializing, func(interface{}) error { + pm := policy.FromSpace(space) + if pm == nil { + return newError("Policy not found in space.") + } + s.policy = pm.GetPolicy(config.UserLevel) + if config.Timeout > 0 && config.UserLevel == 0 { + s.policy.Timeout.ConnectionIdle.Value = config.Timeout + } + return nil + }) return s, nil } @@ -58,8 +70,8 @@ func (s *Server) Process(ctx context.Context, network net.Network, conn internet } func (s *Server) processTCP(ctx context.Context, conn internet.Connection, dispatcher dispatcher.Interface) error { - conn.SetReadDeadline(time.Now().Add(time.Second * 8)) - reader := buf.NewBufferedReader(conn) + conn.SetReadDeadline(time.Now().Add(s.policy.Timeout.Handshake.Duration())) + reader := buf.NewBufferedReader(buf.NewReader(conn)) inboundDest, ok := proxy.InboundEntryPointFromContext(ctx) if !ok { @@ -90,27 +102,22 @@ func (s *Server) processTCP(ctx context.Context, conn internet.Connection, dispa } if request.Command == protocol.RequestCommandUDP { - return s.handleUDP() + return s.handleUDP(conn) } return nil } -func (*Server) handleUDP() error { - // The TCP connection closes after v method returns. We need to wait until +func (*Server) handleUDP(c net.Conn) error { + // The TCP connection closes after this method returns. We need to wait until // the client closes it. - // TODO: get notified from UDP part - time.Sleep(5 * time.Minute) - - return nil + _, err := io.Copy(buf.DiscardBytes, c) + return err } func (v *Server) transport(ctx context.Context, reader io.Reader, writer io.Writer, dest net.Destination, dispatcher dispatcher.Interface) error { - timeout := time.Second * time.Duration(v.config.Timeout) - if timeout == 0 { - timeout = time.Minute * 5 - } - ctx, timer := signal.CancelAfterInactivity(ctx, timeout) + ctx, cancel := context.WithCancel(ctx) + timer := signal.CancelAfterInactivity(ctx, cancel, v.policy.Timeout.ConnectionIdle.Duration()) ray, err := dispatcher.Dispatch(ctx, dest) if err != nil { @@ -127,6 +134,7 @@ func (v *Server) transport(ctx context.Context, reader io.Reader, writer io.Writ if err := buf.Copy(v2reader, input, buf.UpdateActivity(timer)); err != nil { return newError("failed to transport all TCP request").Base(err) } + timer.SetTimeout(v.policy.Timeout.DownlinkOnly.Duration()) return nil }) @@ -135,7 +143,7 @@ func (v *Server) transport(ctx context.Context, reader io.Reader, writer io.Writ if err := buf.Copy(output, v2writer, buf.UpdateActivity(timer)); err != nil { return newError("failed to transport all TCP response").Base(err) } - timer.SetTimeout(time.Second * 2) + timer.SetTimeout(v.policy.Timeout.UplinkOnly.Duration()) return nil }) @@ -145,8 +153,6 @@ func (v *Server) transport(ctx context.Context, reader io.Reader, writer io.Writ return newError("connection ends").Base(err) } - runtime.KeepAlive(timer) - return nil } @@ -159,7 +165,7 @@ func (v *Server) handleUDPPayload(ctx context.Context, conn internet.Connection, reader := buf.NewReader(conn) for { - mpayload, err := reader.Read() + mpayload, err := reader.ReadMultiBuffer() if err != nil { return err } diff --git a/proxy/vmess/encoding/auth_test.go b/proxy/vmess/encoding/auth_test.go index a160fdea9..c8abb584b 100644 --- a/proxy/vmess/encoding/auth_test.go +++ b/proxy/vmess/encoding/auth_test.go @@ -6,11 +6,11 @@ import ( "v2ray.com/core/common" . "v2ray.com/core/proxy/vmess/encoding" - "v2ray.com/core/testing/assert" + . "v2ray.com/ext/assert" ) func TestFnvAuth(t *testing.T) { - assert := assert.On(t) + assert := With(t) fnvAuth := new(FnvAuthenticator) expectedText := make([]byte, 256) @@ -20,7 +20,7 @@ func TestFnvAuth(t *testing.T) { buffer := make([]byte, 512) b := fnvAuth.Seal(buffer[:0], nil, expectedText, nil) b, err = fnvAuth.Open(buffer[:0], nil, b, nil) - assert.Error(err).IsNil() - assert.Int(len(b)).Equals(256) - assert.Bytes(b).Equals(expectedText) + assert(err, IsNil) + assert(len(b), Equals, 256) + assert(b, Equals, expectedText) } diff --git a/proxy/vmess/encoding/client.go b/proxy/vmess/encoding/client.go index 0ff3c2bb5..ba2d57e75 100644 --- a/proxy/vmess/encoding/client.go +++ b/proxy/vmess/encoding/client.go @@ -12,6 +12,7 @@ import ( "v2ray.com/core/app/log" "v2ray.com/core/common" + "v2ray.com/core/common/bitmask" "v2ray.com/core/common/buf" "v2ray.com/core/common/crypto" "v2ray.com/core/common/dice" @@ -59,63 +60,69 @@ func NewClientSession(idHash protocol.IDHash) *ClientSession { return session } -func (c *ClientSession) EncodeRequestHeader(header *protocol.RequestHeader, writer io.Writer) { +func (c *ClientSession) EncodeRequestHeader(header *protocol.RequestHeader, writer io.Writer) error { timestamp := protocol.NewTimestampGenerator(protocol.NowTime(), 30)() account, err := header.User.GetTypedAccount() if err != nil { log.Trace(newError("failed to get user account: ", err).AtError()) - return + return nil } idHash := c.idHash(account.(*vmess.InternalAccount).AnyValidID().Bytes()) common.Must2(idHash.Write(timestamp.Bytes(nil))) common.Must2(writer.Write(idHash.Sum(nil))) - buffer := make([]byte, 0, 512) - buffer = append(buffer, Version) - buffer = append(buffer, c.requestBodyIV...) - buffer = append(buffer, c.requestBodyKey...) - buffer = append(buffer, c.responseHeader, byte(header.Option)) + buffer := buf.New() + defer buffer.Release() + + buffer.AppendBytes(Version) + buffer.Append(c.requestBodyIV) + buffer.Append(c.requestBodyKey) + buffer.AppendBytes(c.responseHeader, byte(header.Option)) + padingLen := dice.Roll(16) - if header.Security.Is(protocol.SecurityType_LEGACY) { - // Disable padding in legacy mode for a smooth transition. - padingLen = 0 - } security := byte(padingLen<<4) | byte(header.Security) - buffer = append(buffer, security, byte(0), byte(header.Command)) + buffer.AppendBytes(security, byte(0), byte(header.Command)) if header.Command != protocol.RequestCommandMux { - buffer = header.Port.Bytes(buffer) + common.Must(buffer.AppendSupplier(serial.WriteUint16(header.Port.Value()))) switch header.Address.Family() { case net.AddressFamilyIPv4: - buffer = append(buffer, AddrTypeIPv4) - buffer = append(buffer, header.Address.IP()...) + buffer.AppendBytes(byte(protocol.AddressTypeIPv4)) + buffer.Append(header.Address.IP()) case net.AddressFamilyIPv6: - buffer = append(buffer, AddrTypeIPv6) - buffer = append(buffer, header.Address.IP()...) + buffer.AppendBytes(byte(protocol.AddressTypeIPv6)) + buffer.Append(header.Address.IP()) case net.AddressFamilyDomain: - buffer = append(buffer, AddrTypeDomain, byte(len(header.Address.Domain()))) - buffer = append(buffer, header.Address.Domain()...) + domain := header.Address.Domain() + if protocol.IsDomainTooLong(domain) { + return newError("long domain not supported: ", domain) + } + nDomain := len(domain) + buffer.AppendBytes(byte(protocol.AddressTypeDomain), byte(nDomain)) + common.Must(buffer.AppendSupplier(serial.WriteString(domain))) } } if padingLen > 0 { - pading := make([]byte, padingLen) - common.Must2(rand.Read(pading)) - buffer = append(buffer, pading...) + common.Must(buffer.AppendSupplier(buf.ReadFullFrom(rand.Reader, padingLen))) } fnv1a := fnv.New32a() - common.Must2(fnv1a.Write(buffer)) + common.Must2(fnv1a.Write(buffer.Bytes())) - buffer = fnv1a.Sum(buffer) + common.Must(buffer.AppendSupplier(func(b []byte) (int, error) { + fnv1a.Sum(b[:0]) + return fnv1a.Size(), nil + })) timestampHash := md5.New() common.Must2(timestampHash.Write(hashTimestamp(timestamp))) iv := timestampHash.Sum(nil) aesStream := crypto.NewAesEncryptionStream(account.(*vmess.InternalAccount).ID.CmdKey(), iv) - aesStream.XORKeyStream(buffer, buffer) - common.Must2(writer.Write(buffer)) + aesStream.XORKeyStream(buffer.Bytes(), buffer.Bytes()) + common.Must2(writer.Write(buffer.Bytes())) + return nil } func (c *ClientSession) EncodeRequestBody(request *protocol.RequestHeader, writer io.Writer) buf.Writer { @@ -190,32 +197,31 @@ func (c *ClientSession) DecodeResponseHeader(reader io.Reader) (*protocol.Respon aesStream := crypto.NewAesDecryptionStream(c.responseBodyKey, c.responseBodyIV) c.responseReader = crypto.NewCryptionReader(aesStream, reader) - buffer := make([]byte, 256) + buffer := buf.New() + defer buffer.Release() - _, err := io.ReadFull(c.responseReader, buffer[:4]) - if err != nil { + if err := buffer.AppendSupplier(buf.ReadFullFrom(c.responseReader, 4)); err != nil { log.Trace(newError("failed to read response header").Base(err)) return nil, err } - if buffer[0] != c.responseHeader { - return nil, newError("unexpected response header. Expecting ", int(c.responseHeader), " but actually ", int(buffer[0])) + if buffer.Byte(0) != c.responseHeader { + return nil, newError("unexpected response header. Expecting ", int(c.responseHeader), " but actually ", int(buffer.Byte(0))) } header := &protocol.ResponseHeader{ - Option: protocol.ResponseOption(buffer[1]), + Option: bitmask.Byte(buffer.Byte(1)), } - if buffer[2] != 0 { - cmdID := buffer[2] - dataLen := int(buffer[3]) - _, err := io.ReadFull(c.responseReader, buffer[:dataLen]) - if err != nil { + if buffer.Byte(2) != 0 { + cmdID := buffer.Byte(2) + dataLen := int(buffer.Byte(3)) + + if err := buffer.Reset(buf.ReadFullFrom(c.responseReader, dataLen)); err != nil { log.Trace(newError("failed to read response command").Base(err)) return nil, err } - data := buffer[:dataLen] - command, err := UnmarshalCommand(cmdID, data) + command, err := UnmarshalCommand(cmdID, buffer.Bytes()) if err == nil { header.Command = command } diff --git a/proxy/vmess/encoding/commands_test.go b/proxy/vmess/encoding/commands_test.go index 142c73cb7..f0d93bde5 100644 --- a/proxy/vmess/encoding/commands_test.go +++ b/proxy/vmess/encoding/commands_test.go @@ -7,11 +7,11 @@ import ( "v2ray.com/core/common/protocol" "v2ray.com/core/common/uuid" . "v2ray.com/core/proxy/vmess/encoding" - "v2ray.com/core/testing/assert" + . "v2ray.com/ext/assert" ) func TestSwitchAccount(t *testing.T) { - assert := assert.On(t) + assert := With(t) sa := &protocol.CommandSwitchAccount{ Port: 1234, @@ -23,18 +23,18 @@ func TestSwitchAccount(t *testing.T) { buffer := buf.New() err := MarshalCommand(sa, buffer) - assert.Error(err).IsNil() + assert(err, IsNil) cmd, err := UnmarshalCommand(1, buffer.BytesFrom(2)) - assert.Error(err).IsNil() + assert(err, IsNil) sa2, ok := cmd.(*protocol.CommandSwitchAccount) - assert.Bool(ok).IsTrue() - assert.Pointer(sa.Host).IsNil() - assert.Pointer(sa2.Host).IsNil() - assert.Port(sa.Port).Equals(sa2.Port) - assert.String(sa.ID.String()).Equals(sa2.ID.String()) - assert.Uint16(sa.AlterIds).Equals(sa2.AlterIds) - assert.Byte(byte(sa.Level)).Equals(byte(sa2.Level)) - assert.Byte(sa.ValidMin).Equals(sa2.ValidMin) + assert(ok, IsTrue) + assert(sa.Host, IsNil) + assert(sa2.Host, IsNil) + assert(sa.Port, Equals, sa2.Port) + assert(sa.ID.String(), Equals, sa2.ID.String()) + assert(sa.AlterIds, Equals, sa2.AlterIds) + assert(byte(sa.Level), Equals, byte(sa2.Level)) + assert(sa.ValidMin, Equals, sa2.ValidMin) } diff --git a/proxy/vmess/encoding/const.go b/proxy/vmess/encoding/const.go index 3f2a15031..d9d858787 100644 --- a/proxy/vmess/encoding/const.go +++ b/proxy/vmess/encoding/const.go @@ -2,8 +2,4 @@ package encoding const ( Version = byte(1) - - AddrTypeIPv4 = byte(0x01) - AddrTypeIPv6 = byte(0x03) - AddrTypeDomain = byte(0x02) ) diff --git a/proxy/vmess/encoding/encoding_test.go b/proxy/vmess/encoding/encoding_test.go index a31db21de..6ed0edc1f 100644 --- a/proxy/vmess/encoding/encoding_test.go +++ b/proxy/vmess/encoding/encoding_test.go @@ -4,6 +4,7 @@ import ( "context" "testing" + "v2ray.com/core/common" "v2ray.com/core/common/buf" "v2ray.com/core/common/net" "v2ray.com/core/common/protocol" @@ -11,11 +12,11 @@ import ( "v2ray.com/core/common/uuid" "v2ray.com/core/proxy/vmess" . "v2ray.com/core/proxy/vmess/encoding" - "v2ray.com/core/testing/assert" + . "v2ray.com/ext/assert" ) func TestRequestSerialization(t *testing.T) { - assert := assert.On(t) + assert := With(t) user := &protocol.User{ Level: 0, @@ -38,7 +39,7 @@ func TestRequestSerialization(t *testing.T) { buffer := buf.New() client := NewClientSession(protocol.DefaultIDHash) - client.EncodeRequestHeader(expectedRequest, buffer) + common.Must(client.EncodeRequestHeader(expectedRequest, buffer)) buffer2 := buf.New() buffer2.Append(buffer.Bytes()) @@ -51,18 +52,18 @@ func TestRequestSerialization(t *testing.T) { server := NewServerSession(userValidator, sessionHistory) actualRequest, err := server.DecodeRequestHeader(buffer) - assert.Error(err).IsNil() + assert(err, IsNil) - assert.Byte(expectedRequest.Version).Equals(actualRequest.Version) - assert.Byte(byte(expectedRequest.Command)).Equals(byte(actualRequest.Command)) - assert.Byte(byte(expectedRequest.Option)).Equals(byte(actualRequest.Option)) - assert.Address(expectedRequest.Address).Equals(actualRequest.Address) - assert.Port(expectedRequest.Port).Equals(actualRequest.Port) - assert.Byte(byte(expectedRequest.Security)).Equals(byte(actualRequest.Security)) + assert(expectedRequest.Version, Equals, actualRequest.Version) + assert(byte(expectedRequest.Command), Equals, byte(actualRequest.Command)) + assert(byte(expectedRequest.Option), Equals, byte(actualRequest.Option)) + assert(expectedRequest.Address, Equals, actualRequest.Address) + assert(expectedRequest.Port, Equals, actualRequest.Port) + assert(byte(expectedRequest.Security), Equals, byte(actualRequest.Security)) _, err = server.DecodeRequestHeader(buffer2) // anti replay attack - assert.Error(err).IsNotNil() + assert(err, IsNotNil) cancel() } diff --git a/proxy/vmess/encoding/server.go b/proxy/vmess/encoding/server.go index 257462c59..0859ed822 100644 --- a/proxy/vmess/encoding/server.go +++ b/proxy/vmess/encoding/server.go @@ -12,6 +12,7 @@ import ( "golang.org/x/crypto/chacha20poly1305" "v2ray.com/core/common" + "v2ray.com/core/common/bitmask" "v2ray.com/core/common/buf" "v2ray.com/core/common/crypto" "v2ray.com/core/common/net" @@ -114,14 +115,14 @@ func NewServerSession(validator protocol.UserValidator, sessionHistory *SessionH } func (s *ServerSession) DecodeRequestHeader(reader io.Reader) (*protocol.RequestHeader, error) { - buffer := make([]byte, 512) + buffer := buf.New() + defer buffer.Release() - _, err := io.ReadFull(reader, buffer[:protocol.IDBytesLen]) - if err != nil { + if err := buffer.AppendSupplier(buf.ReadFullFrom(reader, protocol.IDBytesLen)); err != nil { return nil, newError("failed to read request header").Base(err) } - user, timestamp, valid := s.userValidator.Get(buffer[:protocol.IDBytesLen]) + user, timestamp, valid := s.userValidator.Get(buffer.Bytes()) if !valid { return nil, newError("invalid user") } @@ -138,23 +139,21 @@ func (s *ServerSession) DecodeRequestHeader(reader io.Reader) (*protocol.Request aesStream := crypto.NewAesDecryptionStream(vmessAccount.ID.CmdKey(), iv) decryptor := crypto.NewCryptionReader(aesStream, reader) - nBytes, err := io.ReadFull(decryptor, buffer[:41]) - if err != nil { + if err := buffer.Reset(buf.ReadFullFrom(decryptor, 41)); err != nil { return nil, newError("failed to read request header").Base(err) } - bufferLen := nBytes request := &protocol.RequestHeader{ User: user, - Version: buffer[0], + Version: buffer.Byte(0), } if request.Version != Version { return nil, newError("invalid protocol version ", request.Version) } - s.requestBodyIV = append([]byte(nil), buffer[1:17]...) // 16 bytes - s.requestBodyKey = append([]byte(nil), buffer[17:33]...) // 16 bytes + s.requestBodyIV = append([]byte(nil), buffer.BytesRange(1, 17)...) // 16 bytes + s.requestBodyKey = append([]byte(nil), buffer.BytesRange(17, 33)...) // 16 bytes var sid sessionId copy(sid.user[:], vmessAccount.ID.Bytes()) copy(sid.key[:], s.requestBodyKey) @@ -164,66 +163,56 @@ func (s *ServerSession) DecodeRequestHeader(reader io.Reader) (*protocol.Request } s.sessionHistory.add(sid) - s.responseHeader = buffer[33] // 1 byte - request.Option = protocol.RequestOption(buffer[34]) // 1 byte - padingLen := int(buffer[35] >> 4) - request.Security = protocol.NormSecurity(protocol.Security(buffer[35] & 0x0F)) + s.responseHeader = buffer.Byte(33) // 1 byte + request.Option = bitmask.Byte(buffer.Byte(34)) // 1 byte + padingLen := int(buffer.Byte(35) >> 4) + request.Security = protocol.NormSecurity(protocol.Security(buffer.Byte(35) & 0x0F)) // 1 bytes reserved - request.Command = protocol.RequestCommand(buffer[37]) + request.Command = protocol.RequestCommand(buffer.Byte(37)) if request.Command != protocol.RequestCommandMux { - request.Port = net.PortFromBytes(buffer[38:40]) + request.Port = net.PortFromBytes(buffer.BytesRange(38, 40)) - switch buffer[40] { - case AddrTypeIPv4: - _, err = io.ReadFull(decryptor, buffer[41:45]) // 4 bytes - bufferLen += 4 - if err != nil { + switch protocol.AddressType(buffer.Byte(40)) { + case protocol.AddressTypeIPv4: + if err := buffer.AppendSupplier(buf.ReadFullFrom(decryptor, 4)); err != nil { return nil, newError("failed to read IPv4 address").Base(err) } - request.Address = net.IPAddress(buffer[41:45]) - case AddrTypeIPv6: - _, err = io.ReadFull(decryptor, buffer[41:57]) // 16 bytes - bufferLen += 16 - if err != nil { + request.Address = net.IPAddress(buffer.BytesFrom(-4)) + case protocol.AddressTypeIPv6: + if err := buffer.AppendSupplier(buf.ReadFullFrom(decryptor, 16)); err != nil { return nil, newError("failed to read IPv6 address").Base(err) } - request.Address = net.IPAddress(buffer[41:57]) - case AddrTypeDomain: - _, err = io.ReadFull(decryptor, buffer[41:42]) - if err != nil { + request.Address = net.IPAddress(buffer.BytesFrom(-16)) + case protocol.AddressTypeDomain: + if err := buffer.AppendSupplier(buf.ReadFullFrom(decryptor, 1)); err != nil { return nil, newError("failed to read domain address").Base(err) } - domainLength := int(buffer[41]) + domainLength := int(buffer.Byte(buffer.Len() - 1)) if domainLength == 0 { return nil, newError("zero length domain").Base(err) } - _, err = io.ReadFull(decryptor, buffer[42:42+domainLength]) - if err != nil { + if err := buffer.AppendSupplier(buf.ReadFullFrom(decryptor, domainLength)); err != nil { return nil, newError("failed to read domain address").Base(err) } - bufferLen += 1 + domainLength - request.Address = net.DomainAddress(string(buffer[42 : 42+domainLength])) + request.Address = net.DomainAddress(string(buffer.BytesFrom(-domainLength))) } } if padingLen > 0 { - _, err = io.ReadFull(decryptor, buffer[bufferLen:bufferLen+padingLen]) - if err != nil { + if err := buffer.AppendSupplier(buf.ReadFullFrom(decryptor, padingLen)); err != nil { return nil, newError("failed to read padding").Base(err) } - bufferLen += padingLen } - _, err = io.ReadFull(decryptor, buffer[bufferLen:bufferLen+4]) - if err != nil { + if err := buffer.AppendSupplier(buf.ReadFullFrom(decryptor, 4)); err != nil { return nil, newError("failed to read checksum").Base(err) } fnv1a := fnv.New32a() - common.Must2(fnv1a.Write(buffer[:bufferLen])) + common.Must2(fnv1a.Write(buffer.BytesTo(-4))) actualHash := fnv1a.Sum32() - expectedHash := serial.BytesToUint32(buffer[bufferLen : bufferLen+4]) + expectedHash := serial.BytesToUint32(buffer.BytesFrom(-4)) if actualHash != expectedHash { return nil, newError("invalid auth") diff --git a/proxy/vmess/inbound/config.go b/proxy/vmess/inbound/config.go index 5d9f94ea5..37e717ba4 100644 --- a/proxy/vmess/inbound/config.go +++ b/proxy/vmess/inbound/config.go @@ -1,12 +1,12 @@ package inbound // GetDefaultValue returns default settings of DefaultConfig. -func (v *Config) GetDefaultValue() *DefaultConfig { - if v.GetDefault() == nil { +func (c *Config) GetDefaultValue() *DefaultConfig { + if c.GetDefault() == nil { return &DefaultConfig{ AlterId: 32, Level: 0, } } - return v.Default + return c.Default } diff --git a/proxy/vmess/inbound/inbound.go b/proxy/vmess/inbound/inbound.go index 9cc3c2753..9becd2497 100644 --- a/proxy/vmess/inbound/inbound.go +++ b/proxy/vmess/inbound/inbound.go @@ -5,13 +5,13 @@ package inbound import ( "context" "io" - "runtime" "sync" "time" "v2ray.com/core/app" "v2ray.com/core/app/dispatcher" "v2ray.com/core/app/log" + "v2ray.com/core/app/policy" "v2ray.com/core/app/proxyman" "v2ray.com/core/common" "v2ray.com/core/common/buf" @@ -34,7 +34,7 @@ type userByEmail struct { defaultAlterIDs uint16 } -func NewUserByEmail(users []*protocol.User, config *DefaultConfig) *userByEmail { +func newUserByEmail(users []*protocol.User, config *DefaultConfig) *userByEmail { cache := make(map[string]*protocol.User) for _, user := range users { cache[user.Email] = user @@ -79,8 +79,10 @@ type Handler struct { usersByEmail *userByEmail detours *DetourConfig sessionHistory *encoding.SessionHistory + policyManager policy.Manager } +// New creates a new VMess inbound handler. func New(ctx context.Context, config *Config) (*Handler, error) { space := app.SpaceFromContext(ctx) if space == nil { @@ -97,14 +99,18 @@ func New(ctx context.Context, config *Config) (*Handler, error) { handler := &Handler{ clients: allowedClients, detours: config.Detour, - usersByEmail: NewUserByEmail(config.User, config.GetDefaultValue()), + usersByEmail: newUserByEmail(config.User, config.GetDefaultValue()), sessionHistory: encoding.NewSessionHistory(ctx), } - space.OnInitialize(func() error { + space.On(app.SpaceInitializing, func(interface{}) error { handler.inboundHandlerManager = proxyman.InboundHandlerManagerFromSpace(space) if handler.inboundHandlerManager == nil { - return newError("InboundHandlerManager is not found is space") + return newError("InboundHandlerManager is not found is space.") + } + handler.policyManager = policy.FromSpace(space) + if handler.policyManager == nil { + return newError("Policy is not found in space.") } return nil }) @@ -119,10 +125,10 @@ func (*Handler) Network() net.NetworkList { } } -func (v *Handler) GetUser(email string) *protocol.User { - user, existing := v.usersByEmail.Get(email) +func (h *Handler) GetUser(email string) *protocol.User { + user, existing := h.usersByEmail.Get(email) if !existing { - v.clients.Add(user) + h.clients.Add(user) } return user } @@ -143,12 +149,12 @@ func transferResponse(timer signal.ActivityUpdater, session *encoding.ServerSess bodyWriter := session.EncodeResponseBody(request, output) // Optimize for small response packet - data, err := input.Read() + data, err := input.ReadMultiBuffer() if err != nil { return err } - if err := bodyWriter.Write(data); err != nil { + if err := bodyWriter.WriteMultiBuffer(data); err != nil { return err } data.Release() @@ -164,7 +170,7 @@ func transferResponse(timer signal.ActivityUpdater, session *encoding.ServerSess } if request.Option.Has(protocol.RequestOptionChunkStream) { - if err := bodyWriter.Write(buf.NewMultiBuffer()); err != nil { + if err := bodyWriter.WriteMultiBuffer(buf.MultiBuffer{}); err != nil { return err } } @@ -173,14 +179,15 @@ func transferResponse(timer signal.ActivityUpdater, session *encoding.ServerSess } // Process implements proxy.Inbound.Process(). -func (v *Handler) Process(ctx context.Context, network net.Network, connection internet.Connection, dispatcher dispatcher.Interface) error { - if err := connection.SetReadDeadline(time.Now().Add(time.Second * 8)); err != nil { - return err +func (h *Handler) Process(ctx context.Context, network net.Network, connection internet.Connection, dispatcher dispatcher.Interface) error { + sessionPolicy := h.policyManager.GetPolicy(0) + if err := connection.SetReadDeadline(time.Now().Add(sessionPolicy.Timeout.Handshake.Duration())); err != nil { + return newError("unable to set read deadline").Base(err).AtWarning() } - reader := buf.NewBufferedReader(connection) + reader := buf.NewBufferedReader(buf.NewReader(connection)) - session := encoding.NewServerSession(v.clients, v.sessionHistory) + session := encoding.NewServerSession(h.clients, h.sessionHistory) request, err := session.DecodeRequestHeader(reader) if err != nil { @@ -199,13 +206,15 @@ func (v *Handler) Process(ctx context.Context, network net.Network, connection i log.Access(connection.RemoteAddr(), request.Destination(), log.AccessAccepted, "") log.Trace(newError("received request for ", request.Destination())) - common.Must(connection.SetReadDeadline(time.Time{})) - - userSettings := request.User.GetSettings() + if err := connection.SetReadDeadline(time.Time{}); err != nil { + log.Trace(newError("unable to set back read deadline").Base(err)) + } + sessionPolicy = h.policyManager.GetPolicy(request.User.Level) ctx = protocol.ContextWithUser(ctx, request.User) - ctx, timer := signal.CancelAfterInactivity(ctx, userSettings.PayloadTimeout) + ctx, cancel := context.WithCancel(ctx) + timer := signal.CancelAfterInactivity(ctx, cancel, sessionPolicy.Timeout.ConnectionIdle.Duration()) ray, err := dispatcher.Dispatch(ctx, request.Destination()) if err != nil { return newError("failed to dispatch request to ", request.Destination()).Base(err) @@ -214,18 +223,18 @@ func (v *Handler) Process(ctx context.Context, network net.Network, connection i input := ray.InboundInput() output := ray.InboundOutput() - reader.SetBuffered(false) - requestDone := signal.ExecuteAsync(func() error { + defer timer.SetTimeout(sessionPolicy.Timeout.DownlinkOnly.Duration()) return transferRequest(timer, session, request, reader, input) }) responseDone := signal.ExecuteAsync(func() error { - writer := buf.NewBufferedWriter(connection) + writer := buf.NewBufferedWriter(buf.NewWriter(connection)) defer writer.Flush() + defer timer.SetTimeout(sessionPolicy.Timeout.UplinkOnly.Duration()) response := &protocol.ResponseHeader{ - Command: v.generateCommand(ctx, request), + Command: h.generateCommand(ctx, request), } return transferResponse(timer, session, request, response, output, writer) }) @@ -236,16 +245,14 @@ func (v *Handler) Process(ctx context.Context, network net.Network, connection i return newError("connection ends").Base(err) } - runtime.KeepAlive(timer) - return nil } -func (v *Handler) generateCommand(ctx context.Context, request *protocol.RequestHeader) protocol.ResponseCommand { - if v.detours != nil { - tag := v.detours.To - if v.inboundHandlerManager != nil { - handler, err := v.inboundHandlerManager.GetHandler(ctx, tag) +func (h *Handler) generateCommand(ctx context.Context, request *protocol.RequestHeader) protocol.ResponseCommand { + if h.detours != nil { + tag := h.detours.To + if h.inboundHandlerManager != nil { + handler, err := h.inboundHandlerManager.GetHandler(ctx, tag) if err != nil { log.Trace(newError("failed to get detour handler: ", tag, err).AtWarning()) return nil diff --git a/proxy/vmess/outbound/outbound.go b/proxy/vmess/outbound/outbound.go index 27c417769..dd218edfc 100644 --- a/proxy/vmess/outbound/outbound.go +++ b/proxy/vmess/outbound/outbound.go @@ -4,11 +4,11 @@ package outbound import ( "context" - "runtime" "time" "v2ray.com/core/app" "v2ray.com/core/app/log" + "v2ray.com/core/app/policy" "v2ray.com/core/common" "v2ray.com/core/common/buf" "v2ray.com/core/common/net" @@ -24,8 +24,9 @@ import ( // Handler is an outbound connection handler for VMess protocol. type Handler struct { - serverList *protocol.ServerList - serverPicker protocol.ServerPicker + serverList *protocol.ServerList + serverPicker protocol.ServerPicker + policyManager policy.Manager } func New(ctx context.Context, config *Config) (*Handler, error) { @@ -43,6 +44,15 @@ func New(ctx context.Context, config *Config) (*Handler, error) { serverPicker: protocol.NewRoundRobinServerPicker(serverList), } + space.On(app.SpaceInitializing, func(interface{}) error { + pm := policy.FromSpace(space) + if pm == nil { + return newError("Policy is not found in space.") + } + handler.policyManager = pm + return nil + }) + return handler, nil } @@ -76,9 +86,9 @@ func (v *Handler) Process(ctx context.Context, outboundRay ray.OutboundRay, dial if target.Network == net.Network_UDP { command = protocol.RequestCommandUDP } - //if target.Address.Family().IsDomain() && target.Address.Domain() == "v1.mux.com" { - // command = protocol.RequestCommandMux - //} + if target.Address.Family().IsDomain() && target.Address.Domain() == "v1.mux.com" { + command = protocol.RequestCommandMux + } request := &protocol.RequestHeader{ Version: encoding.Version, User: rec.PickUser(), @@ -103,12 +113,16 @@ func (v *Handler) Process(ctx context.Context, outboundRay ray.OutboundRay, dial output := outboundRay.OutboundOutput() session := encoding.NewClientSession(protocol.DefaultIDHash) + sessionPolicy := v.policyManager.GetPolicy(request.User.Level) - ctx, timer := signal.CancelAfterInactivity(ctx, time.Minute*5) + ctx, cancel := context.WithCancel(ctx) + timer := signal.CancelAfterInactivity(ctx, cancel, sessionPolicy.Timeout.ConnectionIdle.Duration()) requestDone := signal.ExecuteAsync(func() error { - writer := buf.NewBufferedWriter(conn) - session.EncodeRequestHeader(request, writer) + writer := buf.NewBufferedWriter(buf.NewWriter(conn)) + if err := session.EncodeRequestHeader(request, writer); err != nil { + return newError("failed to encode request").Base(err).AtWarning() + } bodyWriter := session.EncodeRequestBody(request, writer) firstPayload, err := input.ReadTimeout(time.Millisecond * 500) @@ -116,7 +130,7 @@ func (v *Handler) Process(ctx context.Context, outboundRay ray.OutboundRay, dial return newError("failed to get first payload").Base(err) } if !firstPayload.IsEmpty() { - if err := bodyWriter.Write(firstPayload); err != nil { + if err := bodyWriter.WriteMultiBuffer(firstPayload); err != nil { return newError("failed to write first payload").Base(err) } firstPayload.Release() @@ -131,17 +145,19 @@ func (v *Handler) Process(ctx context.Context, outboundRay ray.OutboundRay, dial } if request.Option.Has(protocol.RequestOptionChunkStream) { - if err := bodyWriter.Write(buf.NewMultiBuffer()); err != nil { + if err := bodyWriter.WriteMultiBuffer(buf.MultiBuffer{}); err != nil { return err } } + timer.SetTimeout(sessionPolicy.Timeout.DownlinkOnly.Duration()) return nil }) responseDone := signal.ExecuteAsync(func() error { defer output.Close() + defer timer.SetTimeout(sessionPolicy.Timeout.UplinkOnly.Duration()) - reader := buf.NewBufferedReader(conn) + reader := buf.NewBufferedReader(buf.NewReader(conn)) header, err := session.DecodeResponseHeader(reader) if err != nil { return err @@ -150,17 +166,12 @@ func (v *Handler) Process(ctx context.Context, outboundRay ray.OutboundRay, dial reader.SetBuffered(false) bodyReader := session.DecodeResponseBody(request, reader) - if err := buf.Copy(bodyReader, output, buf.UpdateActivity(timer)); err != nil { - return err - } - - return nil + return buf.Copy(bodyReader, output, buf.UpdateActivity(timer)) }) if err := signal.ErrorOrFinish2(ctx, requestDone, responseDone); err != nil { return newError("connection ends").Base(err) } - runtime.KeepAlive(timer) return nil } diff --git a/proxy/vmess/vmess.go b/proxy/vmess/vmess.go index 50928046e..47baf2f60 100644 --- a/proxy/vmess/vmess.go +++ b/proxy/vmess/vmess.go @@ -30,7 +30,6 @@ type idEntry struct { type TimedUserValidator struct { sync.RWMutex - ctx context.Context validUsers []*protocol.User userHash map[[16]byte]indexTimePair ids []*idEntry @@ -45,14 +44,13 @@ type indexTimePair struct { func NewTimedUserValidator(ctx context.Context, hasher protocol.IDHash) protocol.UserValidator { tus := &TimedUserValidator{ - ctx: ctx, validUsers: make([]*protocol.User, 0, 16), userHash: make(map[[16]byte]indexTimePair, 512), ids: make([]*idEntry, 0, 512), hasher: hasher, baseTime: protocol.Timestamp(time.Now().Unix() - cacheDurationSec*3), } - go tus.updateUserHash(updateIntervalSec * time.Second) + go tus.updateUserHash(ctx, updateIntervalSec*time.Second) return tus } @@ -80,7 +78,7 @@ func (v *TimedUserValidator) generateNewHashes(nowSec protocol.Timestamp, idx in } } -func (v *TimedUserValidator) updateUserHash(interval time.Duration) { +func (v *TimedUserValidator) updateUserHash(ctx context.Context, interval time.Duration) { for { select { case now := <-time.After(interval): @@ -90,7 +88,7 @@ func (v *TimedUserValidator) updateUserHash(interval time.Duration) { v.generateNewHashes(nowSec, entry.userIdx, entry) } v.Unlock() - case <-v.ctx.Done(): + case <-ctx.Done(): return } } diff --git a/release/install-release.sh b/release/install-release.sh index f5df6c973..3340c7cf9 100755 --- a/release/install-release.sh +++ b/release/install-release.sh @@ -67,14 +67,22 @@ colorEcho(){ echo -e "\033[${COLOR}${@:2}\033[0m" } -sysAcrh(){ +sysArch(){ ARCH=$(uname -m) if [[ "$ARCH" == "i686" ]] || [[ "$ARCH" == "i386" ]]; then VDIS="32" elif [[ "$ARCH" == *"armv7"* ]] || [[ "$ARCH" == "armv6l" ]]; then VDIS="arm" - elif [[ "$ARCH" == *"armv8"* ]]; then + elif [[ "$ARCH" == *"armv8"* ]] || [[ "$ARCH" == "aarch64" ]]; then VDIS="arm64" + elif [[ "$ARCH" == *"mips64le"* ]]; then + VDIS="mips64le" + elif [[ "$ARCH" == *"mips64"* ]]; then + VDIS="mips64" + elif [[ "$ARCH" == *"mipsle"* ]]; then + VDIS="mipsle" + elif [[ "$ARCH" == *"mips"* ]]; then + VDIS="mips" fi return 0 } @@ -171,7 +179,7 @@ stopV2ray(){ SERVICE_CMD=$(command -v service) colorEcho ${BLUE} "Shutting down V2Ray service." - if [[ -n "${SYSTEMCTL_CMD}" ]] || [[ -f "/lib/systemd/system/v2ray.service" ]]; then + if [[ -n "${SYSTEMCTL_CMD}" ]] || [[ -f "/lib/systemd/system/v2ray.service" ]] || [[ -f "/etc/systemd/system/v2ray.service" ]]; then ${SYSTEMCTL_CMD} stop v2ray elif [[ -n "${SERVICE_CMD}" ]] || [[ -f "/etc/init.d/v2ray" ]]; then ${SERVICE_CMD} v2ray stop @@ -185,21 +193,39 @@ startV2ray(){ if [ -n "${SYSTEMCTL_CMD}" ] && [ -f "/lib/systemd/system/v2ray.service" ]; then ${SYSTEMCTL_CMD} start v2ray + elif [ -n "${SYSTEMCTL_CMD}" ] && [ -f "/etc/systemd/system/v2ray.service" ]; then + ${SYSTEMCTL_CMD} start v2ray elif [ -n "${SERVICE_CMD}" ] && [ -f "/etc/init.d/v2ray" ]; then ${SERVICE_CMD} v2ray start fi return 0 } +copyFile() { + NAME=$1 + MANDATE=$2 + ERROR=`cp "/tmp/v2ray/v2ray-${NEW_VER}-linux-${VDIS}/${NAME}" "/usr/bin/v2ray/${NAME}"` + if [[ $? -ne 0 ]]; then + colorEcho ${YELLOW} "${ERROR}" + if [ "$MANDATE" = true ]; then + exit + fi + fi +} + +makeExecutable() { + chmod +x "/usr/bin/v2ray/$1" +} + installV2Ray(){ # Install V2Ray binary to /usr/bin/v2ray mkdir -p /usr/bin/v2ray - ERROR=`cp "/tmp/v2ray/v2ray-${NEW_VER}-linux-${VDIS}/v2ray" "/usr/bin/v2ray/v2ray"` - if [[ $? -ne 0 ]]; then - colorEcho ${YELLOW} "${ERROR}" - exit - fi - chmod +x "/usr/bin/v2ray/v2ray" + copyFile v2ray true + makeExecutable v2ray + copyFile v2ctl false + makeExecutable v2ctl + copyFile geoip.dat false + copyFile geosite.dat false # Install V2Ray server config to /etc/v2ray mkdir -p /etc/v2ray @@ -228,9 +254,11 @@ installInitScrip(){ SERVICE_CMD=$(command -v service) if [[ -n "${SYSTEMCTL_CMD}" ]];then - if [[ ! -f "/lib/systemd/system/v2ray.service" ]]; then - cp "/tmp/v2ray/v2ray-${NEW_VER}-linux-${VDIS}/systemd/v2ray.service" "/lib/systemd/system/" - systemctl enable v2ray.service + if [[ ! -f "/etc/systemd/system/v2ray.service" ]]; then + if [[ ! -f "/lib/systemd/system/v2ray.service" ]]; then + cp "/tmp/v2ray/v2ray-${NEW_VER}-linux-${VDIS}/systemd/v2ray.service" "/etc/systemd/system/" + systemctl enable v2ray.service + fi fi return elif [[ -n "${SERVICE_CMD}" ]] && [[ ! -f "/etc/init.d/v2ray" ]]; then @@ -243,7 +271,7 @@ installInitScrip(){ } Help(){ - echo "./install-release.sh [-h] [-c] [-p proxy] [-f] [-v vx.y.z] [-l file]" + echo "./install-release.sh [-h] [-c] [-p proxy] [-f] [--version vx.y.z] [-l file]" echo " -h, --help Show help" echo " -p, --proxy To download through a proxy server, use -p socks5://127.0.0.1:1080 or -p http://127.0.0.1:3128 etc" echo " -f, --force Force install" @@ -257,7 +285,21 @@ Help(){ remove(){ SYSTEMCTL_CMD=$(command -v systemctl) SERVICE_CMD=$(command -v service) - if [[ -n "${SYSTEMCTL_CMD}" ]] && [[ -f "/lib/systemd/system/v2ray.service" ]];then + if [[ -n "${SYSTEMCTL_CMD}" ]] && [[ -f "/etc/systemd/system/v2ray.service" ]];then + if pgrep "v2ray" > /dev/null ; then + stopV2ray + fi + systemctl disable v2ray.service + rm -rf "/usr/bin/v2ray" "/etc/systemd/system/v2ray.service" + if [[ $? -ne 0 ]]; then + colorEcho ${RED} "Failed to remove V2Ray." + exit + else + colorEcho ${GREEN} "Removed V2Ray successfully." + colorEcho ${GREEN} "If necessary, please remove configuration file and log file manually." + exit + fi + elif [[ -n "${SYSTEMCTL_CMD}" ]] && [[ -f "/lib/systemd/system/v2ray.service" ]];then if pgrep "v2ray" > /dev/null ; then stopV2ray fi @@ -308,7 +350,7 @@ main(){ [[ "$CHECK" == "1" ]] && checkUpdate [[ "$REMOVE" == "1" ]] && remove - sysAcrh + sysArch # extract local file if [[ $LOCAL_INSTALL -eq 1 ]]; then echo "Install V2Ray via local file" diff --git a/testing/assert/address.go b/testing/assert/address.go deleted file mode 100644 index f104851ec..000000000 --- a/testing/assert/address.go +++ /dev/null @@ -1,80 +0,0 @@ -package assert - -import ( - "v2ray.com/core/common/net" -) - -func (v *Assert) Address(value net.Address) *AddressSubject { - return &AddressSubject{ - Subject: Subject{ - disp: value.String(), - a: v, - }, - value: value, - } -} - -type AddressSubject struct { - Subject - value net.Address -} - -func (subject *AddressSubject) NotEquals(another net.Address) { - if subject.value == another { - subject.Fail("not equals to", another.String()) - } -} - -func (subject *AddressSubject) Equals(another net.Address) { - if subject.value != another { - subject.Fail("equals to", another.String()) - } -} - -func (subject *AddressSubject) NotEqualsString(another string) { - if subject.value.String() == another { - subject.Fail("not equals to string", another) - } -} - -func (subject *AddressSubject) EqualsString(another string) { - if subject.value.String() != another { - subject.Fail("equals to string", another) - } -} - -func (subject *AddressSubject) IsIPv4() { - if !subject.value.Family().IsIPv4() { - subject.Fail("is", "an IPv4 address") - } -} - -func (subject *AddressSubject) IsNotIPv4() { - if subject.value.Family().IsIPv4() { - subject.Fail("is not", "an IPv4 address") - } -} - -func (subject *AddressSubject) IsIPv6() { - if !subject.value.Family().IsIPv6() { - subject.Fail("is", "an IPv6 address") - } -} - -func (subject *AddressSubject) IsNotIPv6() { - if subject.value.Family().IsIPv6() { - subject.Fail("is not", "an IPv6 address") - } -} - -func (subject *AddressSubject) IsDomain() { - if !subject.value.Family().IsDomain() { - subject.Fail("is", "a domain address") - } -} - -func (subject *AddressSubject) IsNotDomain() { - if subject.value.Family().IsDomain() { - subject.Fail("is not", "a domain address") - } -} diff --git a/testing/assert/assert.go b/testing/assert/assert.go deleted file mode 100644 index 3e8a1849a..000000000 --- a/testing/assert/assert.go +++ /dev/null @@ -1,70 +0,0 @@ -package assert - -import ( - "bytes" - "fmt" - "runtime" - "strings" - "testing" -) - -func On(t *testing.T) *Assert { - return &Assert{ - t: t, - } -} - -type Assert struct { - t *testing.T -} - -func (v *Assert) Fail(message string) { - fmt.Println(decorate(message)) - v.t.Fail() -} - -func getCaller() (string, int) { - stackLevel := 3 - for { - _, file, line, ok := runtime.Caller(stackLevel) - if strings.Contains(file, "assert") { - stackLevel++ - } else { - if ok { - // Truncate file name at last file name separator. - if index := strings.LastIndex(file, "/"); index >= 0 { - file = file[index+1:] - } else if index = strings.LastIndex(file, "\\"); index >= 0 { - file = file[index+1:] - } - } else { - file = "???" - line = 1 - } - return file, line - } - } -} - -// decorate prefixes the string with the file and line of the call site -// and inserts the final newline if needed and indentation tabs for formatting. -func decorate(s string) string { - file, line := getCaller() - buf := new(bytes.Buffer) - // Every line is indented at least one tab. - buf.WriteString(" ") - fmt.Fprintf(buf, "%s:%d: ", file, line) - lines := strings.Split(s, "\n") - if l := len(lines); l > 1 && lines[l-1] == "" { - lines = lines[:l-1] - } - for i, line := range lines { - if i > 0 { - // Second and subsequent lines are indented an extra tab. - buf.WriteString("\n\t\t") - } - buf.WriteString(line) - } - buf.WriteByte('\n') - return buf.String() -} diff --git a/testing/assert/bool.go b/testing/assert/bool.go deleted file mode 100644 index bd777a7c5..000000000 --- a/testing/assert/bool.go +++ /dev/null @@ -1,42 +0,0 @@ -package assert - -import ( - "strconv" -) - -// Assert on a boolean variable. -func (v *Assert) Bool(value bool) *BoolSubject { - return &BoolSubject{ - Subject: Subject{ - disp: strconv.FormatBool(value), - a: v, - }, - value: value, - } -} - -type BoolSubject struct { - Subject - value bool -} - -// to be equal to another boolean variable. -func (subject *BoolSubject) Equals(expectation bool) { - if subject.value != expectation { - subject.Fail("is equal to", strconv.FormatBool(expectation)) - } -} - -// to be true. -func (subject *BoolSubject) IsTrue() { - if subject.value != true { - subject.Fail("is", "True") - } -} - -// to be false. -func (subject *BoolSubject) IsFalse() { - if subject.value != false { - subject.Fail("is", "False") - } -} diff --git a/testing/assert/byte.go b/testing/assert/byte.go deleted file mode 100644 index 73813cb61..000000000 --- a/testing/assert/byte.go +++ /dev/null @@ -1,38 +0,0 @@ -package assert - -import ( - "v2ray.com/core/common/serial" -) - -func (v *Assert) Byte(value byte) *ByteSubject { - return &ByteSubject{ - Subject: Subject{ - disp: serial.ByteToHexString(value), - a: v, - }, - value: value, - } -} - -type ByteSubject struct { - Subject - value byte -} - -func (subject *ByteSubject) Equals(expectation byte) { - if subject.value != expectation { - subject.Fail("is equal to", serial.ByteToHexString(expectation)) - } -} - -func (subject *ByteSubject) GreaterThan(expectation byte) { - if subject.value <= expectation { - subject.Fail("is greater than", serial.ByteToHexString(expectation)) - } -} - -func (subject *ByteSubject) LessThan(expectation byte) { - if subject.value >= expectation { - subject.Fail("is less than", serial.ByteToHexString(expectation)) - } -} diff --git a/testing/assert/bytes.go b/testing/assert/bytes.go deleted file mode 100644 index 6559735f3..000000000 --- a/testing/assert/bytes.go +++ /dev/null @@ -1,43 +0,0 @@ -package assert - -import ( - "bytes" - - "fmt" - - "v2ray.com/core/common/serial" -) - -func (v *Assert) Bytes(value []byte) *BytesSubject { - return &BytesSubject{ - Subject: Subject{ - disp: serial.BytesToHexString(value), - a: v, - }, - value: value, - } -} - -type BytesSubject struct { - Subject - value []byte -} - -func (subject *BytesSubject) Equals(expectation []byte) { - if len(subject.value) != len(expectation) { - subject.FailWithMessage(fmt.Sprint("Bytes arrays have differen size: expected ", len(expectation), ", actual ", len(subject.value))) - return - } - for idx, b := range expectation { - if subject.value[idx] != b { - subject.FailWithMessage(fmt.Sprint("Bytes are different: ", b, " vs ", subject.value[idx], " at pos ", idx)) - return - } - } -} - -func (subject *BytesSubject) NotEquals(expectation []byte) { - if bytes.Equal(subject.value, expectation) { - subject.Fail("is not equal to", serial.BytesToHexString(expectation)) - } -} diff --git a/testing/assert/destination.go b/testing/assert/destination.go deleted file mode 100644 index a4b2e39e7..000000000 --- a/testing/assert/destination.go +++ /dev/null @@ -1,64 +0,0 @@ -package assert - -import ( - "v2ray.com/core/common/net" -) - -func (v *Assert) Destination(value net.Destination) *DestinationSubject { - return &DestinationSubject{ - Subject: Subject{ - disp: value.String(), - a: v, - }, - value: value, - } -} - -type DestinationSubject struct { - Subject - value net.Destination -} - -func (v *DestinationSubject) IsTCP() { - if v.value.Network != net.Network_TCP { - v.Fail("is", "a TCP destination") - } -} - -func (v *DestinationSubject) IsNotTCP() { - if v.value.Network == net.Network_TCP { - v.Fail("is not", "a TCP destination") - } -} - -func (v *DestinationSubject) IsUDP() { - if v.value.Network != net.Network_UDP { - v.Fail("is", "a UDP destination") - } -} - -func (v *DestinationSubject) IsNotUDP() { - if v.value.Network == net.Network_UDP { - v.Fail("is not", "a UDP destination") - } -} - -func (v *DestinationSubject) EqualsString(another string) { - if v.value.String() != another { - v.Fail("not equals to string", another) - } -} - -func (v *DestinationSubject) Equals(another net.Destination) { - if v.value != another { - v.Fail("not equals to", another.String()) - } -} - -func (v *DestinationSubject) HasAddress() *AddressSubject { - return v.a.Address(v.value.Address) -} - -func (v *DestinationSubject) HasPort() *PortSubject { - return v.a.Port(v.value.Port) -} diff --git a/testing/assert/error.go b/testing/assert/error.go deleted file mode 100644 index 3356db0e5..000000000 --- a/testing/assert/error.go +++ /dev/null @@ -1,38 +0,0 @@ -package assert - -func (v *Assert) Error(value error) *ErrorSubject { - valueStr := "" - if value != nil { - valueStr = value.Error() - } - return &ErrorSubject{ - Subject: Subject{ - a: v, - disp: valueStr, - }, - value: value, - } -} - -type ErrorSubject struct { - Subject - value error -} - -func (subject *ErrorSubject) Equals(expectation error) { - if subject.value != expectation { - subject.Fail("is equal to", expectation.Error()) - } -} - -func (subject *ErrorSubject) IsNil() { - if subject.value != nil { - subject.Fail("is", "nil") - } -} - -func (subject *ErrorSubject) IsNotNil() { - if subject.value == nil { - subject.Fail("is not", "nil") - } -} diff --git a/testing/assert/int64.go b/testing/assert/int64.go deleted file mode 100644 index cf10ea6ce..000000000 --- a/testing/assert/int64.go +++ /dev/null @@ -1,44 +0,0 @@ -package assert - -import ( - "v2ray.com/core/common/serial" -) - -func (v *Assert) Int64(value int64) *Int64Subject { - return &Int64Subject{ - Subject: Subject{ - a: v, - disp: serial.Int64ToString(value), - }, - value: value, - } -} - -type Int64Subject struct { - Subject - value int64 -} - -func (subject *Int64Subject) Equals(expectation int64) { - if subject.value != expectation { - subject.Fail("is equal to", serial.Int64ToString(expectation)) - } -} - -func (subject *Int64Subject) GreaterThan(expectation int64) { - if subject.value <= expectation { - subject.Fail("is greater than", serial.Int64ToString(expectation)) - } -} - -func (subject *Int64Subject) AtMost(expectation int64) { - if subject.value > expectation { - subject.Fail("is at most", serial.Int64ToString(expectation)) - } -} - -func (subject *Int64Subject) AtLeast(expectation int64) { - if subject.value < expectation { - subject.Fail("is at least", serial.Int64ToString(expectation)) - } -} diff --git a/testing/assert/intsubject.go b/testing/assert/intsubject.go deleted file mode 100644 index b688ff607..000000000 --- a/testing/assert/intsubject.go +++ /dev/null @@ -1,38 +0,0 @@ -package assert - -import ( - "v2ray.com/core/common/serial" -) - -func (v *Assert) Int(value int) *IntSubject { - return &IntSubject{ - Subject: Subject{ - a: v, - disp: serial.IntToString(value), - }, - value: value, - } -} - -type IntSubject struct { - Subject - value int -} - -func (subject *IntSubject) Equals(expectation int) { - if subject.value != expectation { - subject.Fail("is equal to", serial.IntToString(expectation)) - } -} - -func (subject *IntSubject) GreaterThan(expectation int) { - if subject.value <= expectation { - subject.Fail("is greater than", serial.IntToString(expectation)) - } -} - -func (subject *IntSubject) LessThan(expectation int) { - if subject.value >= expectation { - subject.Fail("is less than", serial.IntToString(expectation)) - } -} diff --git a/testing/assert/ip.go b/testing/assert/ip.go deleted file mode 100644 index cf3982713..000000000 --- a/testing/assert/ip.go +++ /dev/null @@ -1,33 +0,0 @@ -package assert - -import ( - "bytes" - "net" -) - -func (v *Assert) IP(value net.IP) *IPSubject { - return &IPSubject{ - Subject: Subject{ - a: v, - disp: value.String(), - }, - value: value, - } -} - -type IPSubject struct { - Subject - value net.IP -} - -func (subject *IPSubject) IsNil() { - if subject.value != nil { - subject.Fail("is", "nil") - } -} - -func (subject *IPSubject) Equals(ip net.IP) { - if !bytes.Equal([]byte(subject.value), []byte(ip)) { - subject.Fail("equals to", ip.String()) - } -} diff --git a/testing/assert/pointer.go b/testing/assert/pointer.go deleted file mode 100644 index 9bf8ef991..000000000 --- a/testing/assert/pointer.go +++ /dev/null @@ -1,56 +0,0 @@ -package assert - -import ( - "reflect" - - "v2ray.com/core/common/serial" -) - -func (v *Assert) Pointer(value interface{}) *PointerSubject { - return &PointerSubject{ - Subject: Subject{ - a: v, - disp: serial.ToString(value), - }, - value: value, - } -} - -type PointerSubject struct { - Subject - value interface{} -} - -func (subject *PointerSubject) Equals(expectation interface{}) { - if subject.value != expectation { - subject.Fail("is equal to", serial.ToString(expectation)) - } -} - -func (subject *PointerSubject) IsNil() { - if subject.value == nil { - return - } - - valueType := reflect.TypeOf(subject.value) - nilType := reflect.Zero(valueType) - realValue := reflect.ValueOf(subject.value) - - if nilType != realValue { - subject.Fail("is", "nil") - } -} - -func (subject *PointerSubject) IsNotNil() { - if subject.value == nil { - subject.Fail("is not", "nil") - } - - valueType := reflect.TypeOf(subject.value) - nilType := reflect.Zero(valueType) - realValue := reflect.ValueOf(subject.value) - - if nilType == realValue { - subject.Fail("is not", "nil") - } -} diff --git a/testing/assert/port.go b/testing/assert/port.go deleted file mode 100644 index f53fa4e98..000000000 --- a/testing/assert/port.go +++ /dev/null @@ -1,44 +0,0 @@ -package assert - -import ( - "v2ray.com/core/common/net" -) - -func (v *Assert) Port(value net.Port) *PortSubject { - return &PortSubject{ - Subject: Subject{ - a: v, - disp: value.String(), - }, - value: value, - } -} - -type PortSubject struct { - Subject - value net.Port -} - -func (subject *PortSubject) Equals(expectation net.Port) { - if subject.value.Value() != expectation.Value() { - subject.Fail("is equal to", expectation.String()) - } -} - -func (subject *PortSubject) GreaterThan(expectation net.Port) { - if subject.value.Value() <= expectation.Value() { - subject.Fail("is greater than", expectation.String()) - } -} - -func (subject *PortSubject) LessThan(expectation net.Port) { - if subject.value.Value() >= expectation.Value() { - subject.Fail("is less than", expectation.String()) - } -} - -func (subject *PortSubject) IsValid() { - if subject.value == 0 { - subject.Fail("is", "a valid port") - } -} diff --git a/testing/assert/string.go b/testing/assert/string.go deleted file mode 100644 index 30a6726da..000000000 --- a/testing/assert/string.go +++ /dev/null @@ -1,50 +0,0 @@ -package assert - -import ( - "strings" -) - -func (v *Assert) String(value string) *StringSubject { - return &StringSubject{ - Subject: Subject{ - a: v, - disp: value, - }, - value: value, - } -} - -type StringSubject struct { - Subject - value string -} - -func (subject *StringSubject) Equals(expectation string) { - if subject.value != expectation { - subject.Fail("is equal to", expectation) - } -} - -func (subject *StringSubject) NotEquals(expectation string) { - if subject.value == expectation { - subject.Fail("is not equal to ", expectation) - } -} - -func (subject *StringSubject) Contains(substring string) { - if !strings.Contains(subject.value, substring) { - subject.Fail("contains", substring) - } -} - -func (subject *StringSubject) NotContains(substring string) { - if strings.Contains(subject.value, substring) { - subject.Fail("doesn't contain", substring) - } -} - -func (subject *StringSubject) IsEmpty() { - if len(subject.value) > 0 { - subject.FailWithMessage("is not empty.") - } -} diff --git a/testing/assert/subject.go b/testing/assert/subject.go deleted file mode 100644 index b54e403c1..000000000 --- a/testing/assert/subject.go +++ /dev/null @@ -1,22 +0,0 @@ -package assert - -type Subject struct { - disp string - a *Assert -} - -func (subject *Subject) Fail(verb string, other string) { - subject.FailWithMessage("Not true that " + subject.DisplayString() + " " + verb + " <" + other + ">.") -} - -func (subject *Subject) FailWithMessage(message string) { - subject.a.Fail(message) -} - -func (subject *Subject) DisplayString() string { - value := subject.disp - if len(value) == 0 { - value = "unknown" - } - return "<" + value + ">" -} diff --git a/testing/assert/uint16.go b/testing/assert/uint16.go deleted file mode 100644 index 9244e11b9..000000000 --- a/testing/assert/uint16.go +++ /dev/null @@ -1,50 +0,0 @@ -package assert - -import ( - "v2ray.com/core/common/serial" -) - -func (v *Assert) Uint16(value uint16) *Uint16Subject { - return &Uint16Subject{ - Subject: Subject{ - a: v, - disp: serial.Uint16ToString(value), - }, - value: value, - } -} - -type Uint16Subject struct { - Subject - value uint16 -} - -func (subject *Uint16Subject) Equals(expectation uint16) { - if subject.value != expectation { - subject.Fail("is equal to", serial.Uint16ToString(expectation)) - } -} - -func (subject *Uint16Subject) GreaterThan(expectation uint16) { - if subject.value <= expectation { - subject.Fail("is greater than", serial.Uint16ToString(expectation)) - } -} - -func (subject *Uint16Subject) LessThan(expectation uint16) { - if subject.value >= expectation { - subject.Fail("is less than", serial.Uint16ToString(expectation)) - } -} - -func (subject *Uint16Subject) IsPositive() { - if subject.value <= 0 { - subject.Fail("is", "positive") - } -} - -func (subject *Uint16Subject) IsNegative() { - if subject.value >= 0 { - subject.Fail("is not", "negative") - } -} diff --git a/testing/assert/uint32.go b/testing/assert/uint32.go deleted file mode 100644 index b2f18c0be..000000000 --- a/testing/assert/uint32.go +++ /dev/null @@ -1,50 +0,0 @@ -package assert - -import ( - "v2ray.com/core/common/serial" -) - -func (v *Assert) Uint32(value uint32) *Uint32Subject { - return &Uint32Subject{ - Subject: Subject{ - a: v, - disp: serial.Uint32ToString(value), - }, - value: value, - } -} - -type Uint32Subject struct { - Subject - value uint32 -} - -func (subject *Uint32Subject) Equals(expectation uint32) { - if subject.value != expectation { - subject.Fail("is equal to", serial.Uint32ToString(expectation)) - } -} - -func (subject *Uint32Subject) GreaterThan(expectation uint32) { - if subject.value <= expectation { - subject.Fail("is greater than", serial.Uint32ToString(expectation)) - } -} - -func (subject *Uint32Subject) LessThan(expectation uint32) { - if subject.value >= expectation { - subject.Fail("is less than", serial.Uint32ToString(expectation)) - } -} - -func (subject *Uint32Subject) IsPositive() { - if subject.value <= 0 { - subject.Fail("is", "positive") - } -} - -func (subject *Uint32Subject) IsNegative() { - if subject.value >= 0 { - subject.Fail("is not", "negative") - } -} diff --git a/testing/scenarios/common.go b/testing/scenarios/common.go index bdeec7a88..ed9d9e04b 100644 --- a/testing/scenarios/common.go +++ b/testing/scenarios/common.go @@ -29,18 +29,6 @@ func pickPort() net.Port { return net.Port(addr.Port) } -func pickUDPPort() net.Port { - conn, err := net.ListenUDP("udp4", &net.UDPAddr{ - IP: net.LocalHostIP.IP(), - Port: 0, - }) - common.Must(err) - defer conn.Close() - - addr := conn.LocalAddr().(*net.UDPAddr) - return net.Port(addr.Port) -} - func xor(b []byte) []byte { r := make([]byte, len(b)) for i, v := range b { diff --git a/testing/scenarios/dns_test.go b/testing/scenarios/dns_test.go index aadb66205..665270776 100644 --- a/testing/scenarios/dns_test.go +++ b/testing/scenarios/dns_test.go @@ -14,18 +14,18 @@ import ( "v2ray.com/core/proxy/blackhole" "v2ray.com/core/proxy/freedom" "v2ray.com/core/proxy/socks" - "v2ray.com/core/testing/assert" "v2ray.com/core/testing/servers/tcp" + . "v2ray.com/ext/assert" ) func TestResolveIP(t *testing.T) { - assert := assert.On(t) + assert := With(t) tcpServer := tcp.Server{ MsgProcessor: xor, } dest, err := tcpServer.Start() - assert.Error(err).IsNil() + assert(err, IsNil) defer tcpServer.Close() serverPort := pickPort() @@ -81,24 +81,24 @@ func TestResolveIP(t *testing.T) { } servers, err := InitializeServerConfigs(serverConfig) - assert.Error(err).IsNil() + assert(err, IsNil) { noAuthDialer, err := xproxy.SOCKS5("tcp", net.TCPDestination(net.LocalHostIP, serverPort).NetAddr(), nil, xproxy.Direct) - assert.Error(err).IsNil() + assert(err, IsNil) conn, err := noAuthDialer.Dial("tcp", fmt.Sprintf("google.com:%d", dest.Port)) - assert.Error(err).IsNil() + assert(err, IsNil) payload := "test payload" nBytes, err := conn.Write([]byte(payload)) - assert.Error(err).IsNil() - assert.Int(nBytes).Equals(len(payload)) + assert(err, IsNil) + assert(nBytes, Equals, len(payload)) response := make([]byte, 1024) nBytes, err = conn.Read(response) - assert.Error(err).IsNil() - assert.Bytes(response[:nBytes]).Equals(xor([]byte(payload))) - assert.Error(conn.Close()).IsNil() + assert(err, IsNil) + assert(response[:nBytes], Equals, xor([]byte(payload))) + assert(conn.Close(), IsNil) } CloseAllServers(servers) diff --git a/testing/scenarios/dokodemo_test.go b/testing/scenarios/dokodemo_test.go index a1b07f61b..b7e2d7389 100644 --- a/testing/scenarios/dokodemo_test.go +++ b/testing/scenarios/dokodemo_test.go @@ -15,24 +15,30 @@ import ( "v2ray.com/core/proxy/vmess" "v2ray.com/core/proxy/vmess/inbound" "v2ray.com/core/proxy/vmess/outbound" - "v2ray.com/core/testing/assert" "v2ray.com/core/testing/servers/tcp" "v2ray.com/core/testing/servers/udp" + . "v2ray.com/ext/assert" ) func TestDokodemoTCP(t *testing.T) { - assert := assert.On(t) + assert := With(t) tcpServer := tcp.Server{ MsgProcessor: xor, } dest, err := tcpServer.Start() - assert.Error(err).IsNil() + assert(err, IsNil) defer tcpServer.Close() userID := protocol.NewID(uuid.New()) serverPort := pickPort() serverConfig := &core.Config{ + App: []*serial.TypedMessage{ + serial.ToTypedMessage(&log.Config{ + ErrorLogLevel: log.LogLevel_Debug, + ErrorLogType: log.LogType_Console, + }), + }, Inbound: []*proxyman.InboundHandlerConfig{ { ReceiverSettings: serial.ToTypedMessage(&proxyman.ReceiverConfig{ @@ -55,17 +61,17 @@ func TestDokodemoTCP(t *testing.T) { ProxySettings: serial.ToTypedMessage(&freedom.Config{}), }, }, + } + + clientPort := uint32(pickPort()) + clientPortRange := uint32(5) + clientConfig := &core.Config{ App: []*serial.TypedMessage{ serial.ToTypedMessage(&log.Config{ ErrorLogLevel: log.LogLevel_Debug, ErrorLogType: log.LogType_Console, }), }, - } - - clientPort := uint32(pickPort()) - clientPortRange := uint32(5) - clientConfig := &core.Config{ Inbound: []*proxyman.InboundHandlerConfig{ { ReceiverSettings: serial.ToTypedMessage(&proxyman.ReceiverConfig{ @@ -100,47 +106,41 @@ func TestDokodemoTCP(t *testing.T) { }), }, }, - App: []*serial.TypedMessage{ - serial.ToTypedMessage(&log.Config{ - ErrorLogLevel: log.LogLevel_Debug, - ErrorLogType: log.LogType_Console, - }), - }, } servers, err := InitializeServerConfigs(serverConfig, clientConfig) - assert.Error(err).IsNil() + assert(err, IsNil) for port := clientPort; port <= clientPort+clientPortRange; port++ { conn, err := net.DialTCP("tcp", nil, &net.TCPAddr{ IP: []byte{127, 0, 0, 1}, Port: int(port), }) - assert.Error(err).IsNil() + assert(err, IsNil) payload := "dokodemo request." nBytes, err := conn.Write([]byte(payload)) - assert.Error(err).IsNil() - assert.Int(nBytes).Equals(len(payload)) + assert(err, IsNil) + assert(nBytes, Equals, len(payload)) response := make([]byte, 1024) nBytes, err = conn.Read(response) - assert.Error(err).IsNil() - assert.Bytes(response[:nBytes]).Equals(xor([]byte(payload))) - assert.Error(conn.Close()).IsNil() + assert(err, IsNil) + assert(response[:nBytes], Equals, xor([]byte(payload))) + assert(conn.Close(), IsNil) } CloseAllServers(servers) } func TestDokodemoUDP(t *testing.T) { - assert := assert.On(t) + assert := With(t) udpServer := udp.Server{ MsgProcessor: xor, } dest, err := udpServer.Start() - assert.Error(err).IsNil() + assert(err, IsNil) defer udpServer.Close() userID := protocol.NewID(uuid.New()) @@ -210,25 +210,25 @@ func TestDokodemoUDP(t *testing.T) { } servers, err := InitializeServerConfigs(serverConfig, clientConfig) - assert.Error(err).IsNil() + assert(err, IsNil) for port := clientPort; port <= clientPort+clientPortRange; port++ { conn, err := net.DialUDP("udp", nil, &net.UDPAddr{ IP: []byte{127, 0, 0, 1}, Port: int(port), }) - assert.Error(err).IsNil() + assert(err, IsNil) payload := "dokodemo request." nBytes, err := conn.Write([]byte(payload)) - assert.Error(err).IsNil() - assert.Int(nBytes).Equals(len(payload)) + assert(err, IsNil) + assert(nBytes, Equals, len(payload)) response := make([]byte, 1024) nBytes, err = conn.Read(response) - assert.Error(err).IsNil() - assert.Bytes(response[:nBytes]).Equals(xor([]byte(payload))) - assert.Error(conn.Close()).IsNil() + assert(err, IsNil) + assert(response[:nBytes], Equals, xor([]byte(payload))) + assert(conn.Close(), IsNil) } CloseAllServers(servers) diff --git a/testing/scenarios/feature_test.go b/testing/scenarios/feature_test.go index 282bcbe1a..7d1b84c07 100644 --- a/testing/scenarios/feature_test.go +++ b/testing/scenarios/feature_test.go @@ -24,21 +24,21 @@ import ( "v2ray.com/core/proxy/vmess" "v2ray.com/core/proxy/vmess/inbound" "v2ray.com/core/proxy/vmess/outbound" - "v2ray.com/core/testing/assert" "v2ray.com/core/testing/servers/tcp" "v2ray.com/core/testing/servers/udp" "v2ray.com/core/transport/internet" + . "v2ray.com/ext/assert" ) func TestPassiveConnection(t *testing.T) { - assert := assert.On(t) + assert := With(t) tcpServer := tcp.Server{ MsgProcessor: xor, SendFirst: []byte("send first"), } dest, err := tcpServer.Start() - assert.Error(err).IsNil() + assert(err, IsNil) defer tcpServer.Close() serverPort := pickPort() @@ -66,49 +66,49 @@ func TestPassiveConnection(t *testing.T) { } servers, err := InitializeServerConfigs(serverConfig) - assert.Error(err).IsNil() + assert(err, IsNil) conn, err := net.DialTCP("tcp", nil, &net.TCPAddr{ IP: []byte{127, 0, 0, 1}, Port: int(serverPort), }) - assert.Error(err).IsNil() + assert(err, IsNil) { response := make([]byte, 1024) nBytes, err := conn.Read(response) - assert.Error(err).IsNil() - assert.String(string(response[:nBytes])).Equals("send first") + assert(err, IsNil) + assert(string(response[:nBytes]), Equals, "send first") } payload := "dokodemo request." { nBytes, err := conn.Write([]byte(payload)) - assert.Error(err).IsNil() - assert.Int(nBytes).Equals(len(payload)) + assert(err, IsNil) + assert(nBytes, Equals, len(payload)) } { response := make([]byte, 1024) nBytes, err := conn.Read(response) - assert.Error(err).IsNil() - assert.Bytes(response[:nBytes]).Equals(xor([]byte(payload))) + assert(err, IsNil) + assert(response[:nBytes], Equals, xor([]byte(payload))) } - assert.Error(conn.Close()).IsNil() + assert(conn.Close(), IsNil) CloseAllServers(servers) } func TestProxy(t *testing.T) { - assert := assert.On(t) + assert := With(t) tcpServer := tcp.Server{ MsgProcessor: xor, } dest, err := tcpServer.Start() - assert.Error(err).IsNil() + assert(err, IsNil) defer tcpServer.Close() serverUserID := protocol.NewID(uuid.New()) @@ -227,36 +227,36 @@ func TestProxy(t *testing.T) { } servers, err := InitializeServerConfigs(serverConfig, proxyConfig, clientConfig) - assert.Error(err).IsNil() + assert(err, IsNil) conn, err := net.DialTCP("tcp", nil, &net.TCPAddr{ IP: []byte{127, 0, 0, 1}, Port: int(clientPort), }) - assert.Error(err).IsNil() + assert(err, IsNil) payload := "dokodemo request." nBytes, err := conn.Write([]byte(payload)) - assert.Error(err).IsNil() - assert.Int(nBytes).Equals(len(payload)) + assert(err, IsNil) + assert(nBytes, Equals, len(payload)) response := make([]byte, 1024) nBytes, err = conn.Read(response) - assert.Error(err).IsNil() - assert.Bytes(response[:nBytes]).Equals(xor([]byte(payload))) - assert.Error(conn.Close()).IsNil() + assert(err, IsNil) + assert(response[:nBytes], Equals, xor([]byte(payload))) + assert(conn.Close(), IsNil) CloseAllServers(servers) } func TestProxyOverKCP(t *testing.T) { - assert := assert.On(t) + assert := With(t) tcpServer := tcp.Server{ MsgProcessor: xor, } dest, err := tcpServer.Start() - assert.Error(err).IsNil() + assert(err, IsNil) defer tcpServer.Close() serverUserID := protocol.NewID(uuid.New()) @@ -386,43 +386,43 @@ func TestProxyOverKCP(t *testing.T) { } servers, err := InitializeServerConfigs(serverConfig, proxyConfig, clientConfig) - assert.Error(err).IsNil() + assert(err, IsNil) conn, err := net.DialTCP("tcp", nil, &net.TCPAddr{ IP: []byte{127, 0, 0, 1}, Port: int(clientPort), }) - assert.Error(err).IsNil() + assert(err, IsNil) payload := "dokodemo request." nBytes, err := conn.Write([]byte(payload)) - assert.Error(err).IsNil() - assert.Int(nBytes).Equals(len(payload)) + assert(err, IsNil) + assert(nBytes, Equals, len(payload)) response := make([]byte, 1024) nBytes, err = conn.Read(response) - assert.Error(err).IsNil() - assert.Bytes(response[:nBytes]).Equals(xor([]byte(payload))) - assert.Error(conn.Close()).IsNil() + assert(err, IsNil) + assert(response[:nBytes], Equals, xor([]byte(payload))) + assert(conn.Close(), IsNil) CloseAllServers(servers) } func TestBlackhole(t *testing.T) { - assert := assert.On(t) + assert := With(t) tcpServer := tcp.Server{ MsgProcessor: xor, } dest, err := tcpServer.Start() - assert.Error(err).IsNil() + assert(err, IsNil) defer tcpServer.Close() tcpServer2 := tcp.Server{ MsgProcessor: xor, } dest2, err := tcpServer2.Start() - assert.Error(err).IsNil() + assert(err, IsNil) defer tcpServer2.Close() serverPort := pickPort() @@ -479,41 +479,41 @@ func TestBlackhole(t *testing.T) { } servers, err := InitializeServerConfigs(serverConfig) - assert.Error(err).IsNil() + assert(err, IsNil) conn, err := net.DialTCP("tcp", nil, &net.TCPAddr{ IP: []byte{127, 0, 0, 1}, Port: int(serverPort2), }) - assert.Error(err).IsNil() + assert(err, IsNil) payload := "dokodemo request." { nBytes, err := conn.Write([]byte(payload)) - assert.Error(err).IsNil() - assert.Int(nBytes).Equals(len(payload)) + assert(err, IsNil) + assert(nBytes, Equals, len(payload)) } { response := make([]byte, 1024) _, err := conn.Read(response) - assert.Error(err).IsNotNil() + assert(err, IsNotNil) } - assert.Error(conn.Close()).IsNil() + assert(conn.Close(), IsNil) CloseAllServers(servers) } func TestForward(t *testing.T) { - assert := assert.On(t) + assert := With(t) tcpServer := tcp.Server{ MsgProcessor: xor, } dest, err := tcpServer.Start() - assert.Error(err).IsNil() + assert(err, IsNil) defer tcpServer.Close() serverPort := pickPort() @@ -549,37 +549,37 @@ func TestForward(t *testing.T) { } servers, err := InitializeServerConfigs(serverConfig) - assert.Error(err).IsNil() + assert(err, IsNil) { noAuthDialer, err := xproxy.SOCKS5("tcp", net.TCPDestination(net.LocalHostIP, serverPort).NetAddr(), nil, xproxy.Direct) - assert.Error(err).IsNil() + assert(err, IsNil) conn, err := noAuthDialer.Dial("tcp", "google.com:80") - assert.Error(err).IsNil() + assert(err, IsNil) payload := "test payload" nBytes, err := conn.Write([]byte(payload)) - assert.Error(err).IsNil() - assert.Int(nBytes).Equals(len(payload)) + assert(err, IsNil) + assert(nBytes, Equals, len(payload)) response := make([]byte, 1024) nBytes, err = conn.Read(response) - assert.Error(err).IsNil() - assert.Bytes(response[:nBytes]).Equals(xor([]byte(payload))) - assert.Error(conn.Close()).IsNil() + assert(err, IsNil) + assert(response[:nBytes], Equals, xor([]byte(payload))) + assert(conn.Close(), IsNil) } CloseAllServers(servers) } func TestUDPConnection(t *testing.T) { - assert := assert.On(t) + assert := With(t) udpServer := udp.Server{ MsgProcessor: xor, } dest, err := udpServer.Start() - assert.Error(err).IsNil() + assert(err, IsNil) defer udpServer.Close() clientPort := pickPort() @@ -607,28 +607,28 @@ func TestUDPConnection(t *testing.T) { } servers, err := InitializeServerConfigs(clientConfig) - assert.Error(err).IsNil() + assert(err, IsNil) { conn, err := net.DialUDP("udp", nil, &net.UDPAddr{ IP: []byte{127, 0, 0, 1}, Port: int(clientPort), }) - assert.Error(err).IsNil() + assert(err, IsNil) payload := "dokodemo request." for i := 0; i < 5; i++ { nBytes, err := conn.Write([]byte(payload)) - assert.Error(err).IsNil() - assert.Int(nBytes).Equals(len(payload)) + assert(err, IsNil) + assert(nBytes, Equals, len(payload)) response := make([]byte, 1024) nBytes, err = conn.Read(response) - assert.Error(err).IsNil() - assert.Bytes(response[:nBytes]).Equals(xor([]byte(payload))) + assert(err, IsNil) + assert(response[:nBytes], Equals, xor([]byte(payload))) } - assert.Error(conn.Close()).IsNil() + assert(conn.Close(), IsNil) } time.Sleep(20 * time.Second) @@ -638,25 +638,25 @@ func TestUDPConnection(t *testing.T) { IP: []byte{127, 0, 0, 1}, Port: int(clientPort), }) - assert.Error(err).IsNil() + assert(err, IsNil) payload := "dokodemo request." nBytes, err := conn.Write([]byte(payload)) - assert.Error(err).IsNil() - assert.Int(nBytes).Equals(len(payload)) + assert(err, IsNil) + assert(nBytes, Equals, len(payload)) response := make([]byte, 1024) nBytes, err = conn.Read(response) - assert.Error(err).IsNil() - assert.Bytes(response[:nBytes]).Equals(xor([]byte(payload))) - assert.Error(conn.Close()).IsNil() + assert(err, IsNil) + assert(response[:nBytes], Equals, xor([]byte(payload))) + assert(conn.Close(), IsNil) } CloseAllServers(servers) } func TestDomainSniffing(t *testing.T) { - assert := assert.On(t) + assert := With(t) sniffingPort := pickPort() httpPort := pickPort() @@ -725,7 +725,7 @@ func TestDomainSniffing(t *testing.T) { } servers, err := InitializeServerConfigs(serverConfig) - assert.Error(err).IsNil() + assert(err, IsNil) { transport := &http.Transport{ @@ -739,10 +739,10 @@ func TestDomainSniffing(t *testing.T) { } resp, err := client.Get("https://www.github.com/") - assert.Error(err).IsNil() - assert.Int(resp.StatusCode).Equals(200) + assert(err, IsNil) + assert(resp.StatusCode, Equals, 200) - assert.Error(resp.Write(ioutil.Discard)).IsNil() + assert(resp.Write(ioutil.Discard), IsNil) } CloseAllServers(servers) diff --git a/testing/scenarios/http_test.go b/testing/scenarios/http_test.go index 181cc21cb..d0033deff 100644 --- a/testing/scenarios/http_test.go +++ b/testing/scenarios/http_test.go @@ -1,23 +1,30 @@ package scenarios import ( + "bytes" + "crypto/rand" + "io" "io/ioutil" "net/http" "net/url" "testing" + "v2ray.com/core/common" + "v2ray.com/core/common/buf" + "v2ray.com/core" "v2ray.com/core/app/proxyman" "v2ray.com/core/common/net" "v2ray.com/core/common/serial" "v2ray.com/core/proxy/freedom" v2http "v2ray.com/core/proxy/http" - "v2ray.com/core/testing/assert" v2httptest "v2ray.com/core/testing/servers/http" + "v2ray.com/core/testing/servers/tcp" + . "v2ray.com/ext/assert" ) func TestHttpConformance(t *testing.T) { - assert := assert.On(t) + assert := With(t) httpServerPort := pickPort() httpServer := &v2httptest.Server{ @@ -25,7 +32,7 @@ func TestHttpConformance(t *testing.T) { PathHandler: make(map[string]http.HandlerFunc), } _, err := httpServer.Start() - assert.Error(err).IsNil() + assert(err, IsNil) defer httpServer.Close() serverPort := pickPort() @@ -47,7 +54,7 @@ func TestHttpConformance(t *testing.T) { } servers, err := InitializeServerConfigs(serverConfig) - assert.Error(err).IsNil() + assert(err, IsNil) { transport := &http.Transport{ @@ -61,14 +68,239 @@ func TestHttpConformance(t *testing.T) { } resp, err := client.Get("http://127.0.0.1:" + httpServerPort.String()) - assert.Error(err).IsNil() - assert.Int(resp.StatusCode).Equals(200) + assert(err, IsNil) + assert(resp.StatusCode, Equals, 200) content, err := ioutil.ReadAll(resp.Body) - assert.Error(err).IsNil() - assert.String(string(content)).Equals("Home") + assert(err, IsNil) + assert(string(content), Equals, "Home") } CloseAllServers(servers) } + +func TestHttpConnectMethod(t *testing.T) { + assert := With(t) + + tcpServer := tcp.Server{ + MsgProcessor: xor, + } + dest, err := tcpServer.Start() + assert(err, IsNil) + defer tcpServer.Close() + + serverPort := pickPort() + serverConfig := &core.Config{ + Inbound: []*proxyman.InboundHandlerConfig{ + { + ReceiverSettings: serial.ToTypedMessage(&proxyman.ReceiverConfig{ + PortRange: net.SinglePortRange(serverPort), + Listen: net.NewIPOrDomain(net.LocalHostIP), + }), + ProxySettings: serial.ToTypedMessage(&v2http.ServerConfig{}), + }, + }, + Outbound: []*proxyman.OutboundHandlerConfig{ + { + ProxySettings: serial.ToTypedMessage(&freedom.Config{}), + }, + }, + } + + servers, err := InitializeServerConfigs(serverConfig) + assert(err, IsNil) + + { + transport := &http.Transport{ + Proxy: func(req *http.Request) (*url.URL, error) { + return url.Parse("http://127.0.0.1:" + serverPort.String()) + }, + } + + client := &http.Client{ + Transport: transport, + } + + payload := make([]byte, 1024*64) + common.Must2(rand.Read(payload)) + req, err := http.NewRequest("Connect", "http://"+dest.NetAddr()+"/", bytes.NewReader(payload)) + req.Header.Set("X-a", "b") + req.Header.Set("X-b", "d") + common.Must(err) + + resp, err := client.Do(req) + assert(err, IsNil) + assert(resp.StatusCode, Equals, 200) + + content := make([]byte, len(payload)) + common.Must2(io.ReadFull(resp.Body, content)) + assert(err, IsNil) + assert(content, Equals, xor(payload)) + + } + + CloseAllServers(servers) +} + +func TestHttpPost(t *testing.T) { + assert := With(t) + + httpServerPort := pickPort() + httpServer := &v2httptest.Server{ + Port: httpServerPort, + PathHandler: map[string]http.HandlerFunc{ + "/testpost": func(w http.ResponseWriter, r *http.Request) { + payload, err := buf.ReadAllToBytes(r.Body) + r.Body.Close() + + if err != nil { + w.WriteHeader(500) + w.Write([]byte("Unable to read all payload")) + return + } + payload = xor(payload) + w.Write(payload) + }, + }, + } + + _, err := httpServer.Start() + assert(err, IsNil) + defer httpServer.Close() + + serverPort := pickPort() + serverConfig := &core.Config{ + Inbound: []*proxyman.InboundHandlerConfig{ + { + ReceiverSettings: serial.ToTypedMessage(&proxyman.ReceiverConfig{ + PortRange: net.SinglePortRange(serverPort), + Listen: net.NewIPOrDomain(net.LocalHostIP), + }), + ProxySettings: serial.ToTypedMessage(&v2http.ServerConfig{}), + }, + }, + Outbound: []*proxyman.OutboundHandlerConfig{ + { + ProxySettings: serial.ToTypedMessage(&freedom.Config{}), + }, + }, + } + + servers, err := InitializeServerConfigs(serverConfig) + assert(err, IsNil) + + { + transport := &http.Transport{ + Proxy: func(req *http.Request) (*url.URL, error) { + return url.Parse("http://127.0.0.1:" + serverPort.String()) + }, + } + + client := &http.Client{ + Transport: transport, + } + + payload := make([]byte, 1024*64) + common.Must2(rand.Read(payload)) + + resp, err := client.Post("http://127.0.0.1:"+httpServerPort.String()+"/testpost", "application/x-www-form-urlencoded", bytes.NewReader(payload)) + assert(err, IsNil) + assert(resp.StatusCode, Equals, 200) + + content, err := ioutil.ReadAll(resp.Body) + assert(err, IsNil) + assert(content, Equals, xor(payload)) + + } + + CloseAllServers(servers) +} + +func setProxyBasicAuth(req *http.Request, user, pass string) { + req.SetBasicAuth(user, pass) + req.Header.Set("Proxy-Authorization", req.Header.Get("Authorization")) + req.Header.Del("Authorization") +} + +func TestHttpBasicAuth(t *testing.T) { + assert := With(t) + + httpServerPort := pickPort() + httpServer := &v2httptest.Server{ + Port: httpServerPort, + PathHandler: make(map[string]http.HandlerFunc), + } + _, err := httpServer.Start() + assert(err, IsNil) + defer httpServer.Close() + + serverPort := pickPort() + serverConfig := &core.Config{ + Inbound: []*proxyman.InboundHandlerConfig{ + { + ReceiverSettings: serial.ToTypedMessage(&proxyman.ReceiverConfig{ + PortRange: net.SinglePortRange(serverPort), + Listen: net.NewIPOrDomain(net.LocalHostIP), + }), + ProxySettings: serial.ToTypedMessage(&v2http.ServerConfig{ + Accounts: map[string]string{ + "a": "b", + }, + }), + }, + }, + Outbound: []*proxyman.OutboundHandlerConfig{ + { + ProxySettings: serial.ToTypedMessage(&freedom.Config{}), + }, + }, + } + + servers, err := InitializeServerConfigs(serverConfig) + assert(err, IsNil) + + { + transport := &http.Transport{ + Proxy: func(req *http.Request) (*url.URL, error) { + return url.Parse("http://127.0.0.1:" + serverPort.String()) + }, + } + + client := &http.Client{ + Transport: transport, + } + + { + resp, err := client.Get("http://127.0.0.1:" + httpServerPort.String()) + assert(err, IsNil) + assert(resp.StatusCode, Equals, 407) + } + + { + req, err := http.NewRequest("GET", "http://127.0.0.1:"+httpServerPort.String(), nil) + assert(err, IsNil) + + setProxyBasicAuth(req, "a", "c") + resp, err := client.Do(req) + assert(err, IsNil) + assert(resp.StatusCode, Equals, 401) + } + + { + req, err := http.NewRequest("GET", "http://127.0.0.1:"+httpServerPort.String(), nil) + assert(err, IsNil) + + setProxyBasicAuth(req, "a", "b") + resp, err := client.Do(req) + assert(err, IsNil) + assert(resp.StatusCode, Equals, 200) + + content, err := ioutil.ReadAll(resp.Body) + assert(err, IsNil) + assert(string(content), Equals, "Home") + } + } + + CloseAllServers(servers) +} diff --git a/testing/scenarios/shadowsocks_test.go b/testing/scenarios/shadowsocks_test.go index 73a9a31eb..ae3f611c0 100644 --- a/testing/scenarios/shadowsocks_test.go +++ b/testing/scenarios/shadowsocks_test.go @@ -2,6 +2,7 @@ package scenarios import ( "crypto/rand" + "fmt" "sync" "testing" "time" @@ -9,25 +10,28 @@ import ( "v2ray.com/core" "v2ray.com/core/app/log" "v2ray.com/core/app/proxyman" + "v2ray.com/core/common/buf" "v2ray.com/core/common/net" "v2ray.com/core/common/protocol" "v2ray.com/core/common/serial" "v2ray.com/core/proxy/dokodemo" "v2ray.com/core/proxy/freedom" "v2ray.com/core/proxy/shadowsocks" - "v2ray.com/core/testing/assert" "v2ray.com/core/testing/servers/tcp" "v2ray.com/core/testing/servers/udp" + . "v2ray.com/ext/assert" + + ss "github.com/shadowsocks/go-shadowsocks2/core" ) func TestShadowsocksAES256TCP(t *testing.T) { - assert := assert.On(t) + assert := With(t) tcpServer := tcp.Server{ MsgProcessor: xor, } dest, err := tcpServer.Start() - assert.Error(err).IsNil() + assert(err, IsNil) defer tcpServer.Close() account := serial.ToTypedMessage(&shadowsocks.Account{ @@ -38,6 +42,12 @@ func TestShadowsocksAES256TCP(t *testing.T) { serverPort := pickPort() serverConfig := &core.Config{ + App: []*serial.TypedMessage{ + serial.ToTypedMessage(&log.Config{ + ErrorLogLevel: log.LogLevel_Debug, + ErrorLogType: log.LogType_Console, + }), + }, Inbound: []*proxyman.InboundHandlerConfig{ { ReceiverSettings: serial.ToTypedMessage(&proxyman.ReceiverConfig{ @@ -57,16 +67,16 @@ func TestShadowsocksAES256TCP(t *testing.T) { ProxySettings: serial.ToTypedMessage(&freedom.Config{}), }, }, + } + + clientPort := pickPort() + clientConfig := &core.Config{ App: []*serial.TypedMessage{ serial.ToTypedMessage(&log.Config{ ErrorLogLevel: log.LogLevel_Debug, ErrorLogType: log.LogType_Console, }), }, - } - - clientPort := pickPort() - clientConfig := &core.Config{ Inbound: []*proxyman.InboundHandlerConfig{ { ReceiverSettings: serial.ToTypedMessage(&proxyman.ReceiverConfig{ @@ -99,16 +109,10 @@ func TestShadowsocksAES256TCP(t *testing.T) { }), }, }, - App: []*serial.TypedMessage{ - serial.ToTypedMessage(&log.Config{ - ErrorLogLevel: log.LogLevel_Debug, - ErrorLogType: log.LogType_Console, - }), - }, } servers, err := InitializeServerConfigs(serverConfig, clientConfig) - assert.Error(err).IsNil() + assert(err, IsNil) var wg sync.WaitGroup wg.Add(10) @@ -118,18 +122,18 @@ func TestShadowsocksAES256TCP(t *testing.T) { IP: []byte{127, 0, 0, 1}, Port: int(clientPort), }) - assert.Error(err).IsNil() + assert(err, IsNil) payload := make([]byte, 10240*1024) rand.Read(payload) nBytes, err := conn.Write([]byte(payload)) - assert.Error(err).IsNil() - assert.Int(nBytes).Equals(len(payload)) + assert(err, IsNil) + assert(nBytes, Equals, len(payload)) response := readFrom(conn, time.Second*20, 10240*1024) - assert.Bytes(response).Equals(xor([]byte(payload))) - assert.Error(conn.Close()).IsNil() + assert(response, Equals, xor([]byte(payload))) + assert(conn.Close(), IsNil) wg.Done() }() } @@ -139,13 +143,13 @@ func TestShadowsocksAES256TCP(t *testing.T) { } func TestShadowsocksAES128UDP(t *testing.T) { - assert := assert.On(t) + assert := With(t) udpServer := udp.Server{ MsgProcessor: xor, } dest, err := udpServer.Start() - assert.Error(err).IsNil() + assert(err, IsNil) defer udpServer.Close() account := serial.ToTypedMessage(&shadowsocks.Account{ @@ -156,6 +160,12 @@ func TestShadowsocksAES128UDP(t *testing.T) { serverPort := pickPort() serverConfig := &core.Config{ + App: []*serial.TypedMessage{ + serial.ToTypedMessage(&log.Config{ + ErrorLogLevel: log.LogLevel_Debug, + ErrorLogType: log.LogType_Console, + }), + }, Inbound: []*proxyman.InboundHandlerConfig{ { ReceiverSettings: serial.ToTypedMessage(&proxyman.ReceiverConfig{ @@ -176,16 +186,16 @@ func TestShadowsocksAES128UDP(t *testing.T) { ProxySettings: serial.ToTypedMessage(&freedom.Config{}), }, }, + } + + clientPort := pickPort() + clientConfig := &core.Config{ App: []*serial.TypedMessage{ serial.ToTypedMessage(&log.Config{ ErrorLogLevel: log.LogLevel_Debug, ErrorLogType: log.LogType_Console, }), }, - } - - clientPort := pickPort() - clientConfig := &core.Config{ Inbound: []*proxyman.InboundHandlerConfig{ { ReceiverSettings: serial.ToTypedMessage(&proxyman.ReceiverConfig{ @@ -218,16 +228,10 @@ func TestShadowsocksAES128UDP(t *testing.T) { }), }, }, - App: []*serial.TypedMessage{ - serial.ToTypedMessage(&log.Config{ - ErrorLogLevel: log.LogLevel_Debug, - ErrorLogType: log.LogType_Console, - }), - }, } servers, err := InitializeServerConfigs(serverConfig, clientConfig) - assert.Error(err).IsNil() + assert(err, IsNil) var wg sync.WaitGroup wg.Add(10) @@ -237,18 +241,18 @@ func TestShadowsocksAES128UDP(t *testing.T) { IP: []byte{127, 0, 0, 1}, Port: int(clientPort), }) - assert.Error(err).IsNil() + assert(err, IsNil) payload := make([]byte, 1024) rand.Read(payload) nBytes, err := conn.Write([]byte(payload)) - assert.Error(err).IsNil() - assert.Int(nBytes).Equals(len(payload)) + assert(err, IsNil) + assert(nBytes, Equals, len(payload)) response := readFrom(conn, time.Second*5, 1024) - assert.Bytes(response).Equals(xor([]byte(payload))) - assert.Error(conn.Close()).IsNil() + assert(response, Equals, xor([]byte(payload))) + assert(conn.Close(), IsNil) wg.Done() }() } @@ -258,13 +262,13 @@ func TestShadowsocksAES128UDP(t *testing.T) { } func TestShadowsocksChacha20TCP(t *testing.T) { - assert := assert.On(t) + assert := With(t) tcpServer := tcp.Server{ MsgProcessor: xor, } dest, err := tcpServer.Start() - assert.Error(err).IsNil() + assert(err, IsNil) defer tcpServer.Close() account := serial.ToTypedMessage(&shadowsocks.Account{ @@ -275,6 +279,12 @@ func TestShadowsocksChacha20TCP(t *testing.T) { serverPort := pickPort() serverConfig := &core.Config{ + App: []*serial.TypedMessage{ + serial.ToTypedMessage(&log.Config{ + ErrorLogLevel: log.LogLevel_Debug, + ErrorLogType: log.LogType_Console, + }), + }, Inbound: []*proxyman.InboundHandlerConfig{ { ReceiverSettings: serial.ToTypedMessage(&proxyman.ReceiverConfig{ @@ -294,16 +304,16 @@ func TestShadowsocksChacha20TCP(t *testing.T) { ProxySettings: serial.ToTypedMessage(&freedom.Config{}), }, }, + } + + clientPort := pickPort() + clientConfig := &core.Config{ App: []*serial.TypedMessage{ serial.ToTypedMessage(&log.Config{ ErrorLogLevel: log.LogLevel_Debug, ErrorLogType: log.LogType_Console, }), }, - } - - clientPort := pickPort() - clientConfig := &core.Config{ Inbound: []*proxyman.InboundHandlerConfig{ { ReceiverSettings: serial.ToTypedMessage(&proxyman.ReceiverConfig{ @@ -336,16 +346,10 @@ func TestShadowsocksChacha20TCP(t *testing.T) { }), }, }, - App: []*serial.TypedMessage{ - serial.ToTypedMessage(&log.Config{ - ErrorLogLevel: log.LogLevel_Debug, - ErrorLogType: log.LogType_Console, - }), - }, } servers, err := InitializeServerConfigs(serverConfig, clientConfig) - assert.Error(err).IsNil() + assert(err, IsNil) var wg sync.WaitGroup wg.Add(10) @@ -355,18 +359,492 @@ func TestShadowsocksChacha20TCP(t *testing.T) { IP: []byte{127, 0, 0, 1}, Port: int(clientPort), }) - assert.Error(err).IsNil() + assert(err, IsNil) payload := make([]byte, 10240*1024) rand.Read(payload) nBytes, err := conn.Write([]byte(payload)) - assert.Error(err).IsNil() - assert.Int(nBytes).Equals(len(payload)) + assert(err, IsNil) + assert(nBytes, Equals, len(payload)) response := readFrom(conn, time.Second*20, 10240*1024) - assert.Bytes(response).Equals(xor([]byte(payload))) - assert.Error(conn.Close()).IsNil() + assert(response, Equals, xor([]byte(payload))) + assert(conn.Close(), IsNil) + wg.Done() + }() + } + wg.Wait() + + CloseAllServers(servers) +} + +func TestShadowsocksAES256GCMTCP(t *testing.T) { + assert := With(t) + + tcpServer := tcp.Server{ + MsgProcessor: xor, + } + dest, err := tcpServer.Start() + assert(err, IsNil) + defer tcpServer.Close() + + account := serial.ToTypedMessage(&shadowsocks.Account{ + Password: "shadowsocks-password", + CipherType: shadowsocks.CipherType_AES_256_GCM, + }) + + serverPort := pickPort() + serverConfig := &core.Config{ + App: []*serial.TypedMessage{ + serial.ToTypedMessage(&log.Config{ + ErrorLogLevel: log.LogLevel_Debug, + ErrorLogType: log.LogType_Console, + }), + }, + Inbound: []*proxyman.InboundHandlerConfig{ + { + ReceiverSettings: serial.ToTypedMessage(&proxyman.ReceiverConfig{ + PortRange: net.SinglePortRange(serverPort), + Listen: net.NewIPOrDomain(net.LocalHostIP), + }), + ProxySettings: serial.ToTypedMessage(&shadowsocks.ServerConfig{ + User: &protocol.User{ + Account: account, + Level: 1, + }, + }), + }, + }, + Outbound: []*proxyman.OutboundHandlerConfig{ + { + ProxySettings: serial.ToTypedMessage(&freedom.Config{}), + }, + }, + } + + clientPort := pickPort() + clientConfig := &core.Config{ + App: []*serial.TypedMessage{ + serial.ToTypedMessage(&log.Config{ + ErrorLogLevel: log.LogLevel_Debug, + ErrorLogType: log.LogType_Console, + }), + }, + Inbound: []*proxyman.InboundHandlerConfig{ + { + ReceiverSettings: serial.ToTypedMessage(&proxyman.ReceiverConfig{ + PortRange: net.SinglePortRange(clientPort), + Listen: net.NewIPOrDomain(net.LocalHostIP), + }), + ProxySettings: serial.ToTypedMessage(&dokodemo.Config{ + Address: net.NewIPOrDomain(dest.Address), + Port: uint32(dest.Port), + NetworkList: &net.NetworkList{ + Network: []net.Network{net.Network_TCP}, + }, + }), + }, + }, + Outbound: []*proxyman.OutboundHandlerConfig{ + { + ProxySettings: serial.ToTypedMessage(&shadowsocks.ClientConfig{ + Server: []*protocol.ServerEndpoint{ + { + Address: net.NewIPOrDomain(net.LocalHostIP), + Port: uint32(serverPort), + User: []*protocol.User{ + { + Account: account, + }, + }, + }, + }, + }), + }, + }, + } + + servers, err := InitializeServerConfigs(serverConfig, clientConfig) + assert(err, IsNil) + + var wg sync.WaitGroup + wg.Add(10) + for i := 0; i < 10; i++ { + go func() { + conn, err := net.DialTCP("tcp", nil, &net.TCPAddr{ + IP: []byte{127, 0, 0, 1}, + Port: int(clientPort), + }) + assert(err, IsNil) + + payload := make([]byte, 10240*1024) + rand.Read(payload) + + nBytes, err := conn.Write([]byte(payload)) + assert(err, IsNil) + assert(nBytes, Equals, len(payload)) + + response := readFrom(conn, time.Second*20, 10240*1024) + assert(response, Equals, xor([]byte(payload))) + assert(conn.Close(), IsNil) + wg.Done() + }() + } + wg.Wait() + + CloseAllServers(servers) +} + +func TestShadowsocksAES128GCMUDP(t *testing.T) { + assert := With(t) + + udpServer := udp.Server{ + MsgProcessor: xor, + } + dest, err := udpServer.Start() + assert(err, IsNil) + defer udpServer.Close() + + account := serial.ToTypedMessage(&shadowsocks.Account{ + Password: "shadowsocks-password", + CipherType: shadowsocks.CipherType_AES_128_GCM, + }) + + serverPort := pickPort() + serverConfig := &core.Config{ + App: []*serial.TypedMessage{ + serial.ToTypedMessage(&log.Config{ + ErrorLogLevel: log.LogLevel_Debug, + ErrorLogType: log.LogType_Console, + }), + }, + Inbound: []*proxyman.InboundHandlerConfig{ + { + ReceiverSettings: serial.ToTypedMessage(&proxyman.ReceiverConfig{ + PortRange: net.SinglePortRange(serverPort), + Listen: net.NewIPOrDomain(net.LocalHostIP), + }), + ProxySettings: serial.ToTypedMessage(&shadowsocks.ServerConfig{ + UdpEnabled: true, + User: &protocol.User{ + Account: account, + Level: 1, + }, + }), + }, + }, + Outbound: []*proxyman.OutboundHandlerConfig{ + { + ProxySettings: serial.ToTypedMessage(&freedom.Config{}), + }, + }, + } + + clientPort := pickPort() + clientConfig := &core.Config{ + App: []*serial.TypedMessage{ + serial.ToTypedMessage(&log.Config{ + ErrorLogLevel: log.LogLevel_Debug, + ErrorLogType: log.LogType_Console, + }), + }, + Inbound: []*proxyman.InboundHandlerConfig{ + { + ReceiverSettings: serial.ToTypedMessage(&proxyman.ReceiverConfig{ + PortRange: net.SinglePortRange(clientPort), + Listen: net.NewIPOrDomain(net.LocalHostIP), + }), + ProxySettings: serial.ToTypedMessage(&dokodemo.Config{ + Address: net.NewIPOrDomain(dest.Address), + Port: uint32(dest.Port), + NetworkList: &net.NetworkList{ + Network: []net.Network{net.Network_UDP}, + }, + }), + }, + }, + Outbound: []*proxyman.OutboundHandlerConfig{ + { + ProxySettings: serial.ToTypedMessage(&shadowsocks.ClientConfig{ + Server: []*protocol.ServerEndpoint{ + { + Address: net.NewIPOrDomain(net.LocalHostIP), + Port: uint32(serverPort), + User: []*protocol.User{ + { + Account: account, + }, + }, + }, + }, + }), + }, + }, + } + + servers, err := InitializeServerConfigs(serverConfig, clientConfig) + assert(err, IsNil) + + var wg sync.WaitGroup + wg.Add(10) + for i := 0; i < 10; i++ { + go func() { + conn, err := net.DialUDP("udp", nil, &net.UDPAddr{ + IP: []byte{127, 0, 0, 1}, + Port: int(clientPort), + }) + assert(err, IsNil) + + payload := make([]byte, 1024) + rand.Read(payload) + + nBytes, err := conn.Write([]byte(payload)) + assert(err, IsNil) + assert(nBytes, Equals, len(payload)) + + response := readFrom(conn, time.Second*5, 1024) + assert(response, Equals, xor([]byte(payload))) + assert(conn.Close(), IsNil) + wg.Done() + }() + } + wg.Wait() + + CloseAllServers(servers) +} + +func TestShadowsocksAES256GCMConformance(t *testing.T) { + assert := With(t) + + tcpServer := tcp.Server{ + MsgProcessor: xor, + } + dest, err := tcpServer.Start() + assert(err, IsNil) + defer tcpServer.Close() + + account := serial.ToTypedMessage(&shadowsocks.Account{ + Password: "ss-password", + CipherType: shadowsocks.CipherType_AES_256_GCM, + }) + + serverPort := pickPort() + serverConfig := &core.Config{ + App: []*serial.TypedMessage{ + serial.ToTypedMessage(&log.Config{ + ErrorLogLevel: log.LogLevel_Debug, + ErrorLogType: log.LogType_Console, + }), + }, + Inbound: []*proxyman.InboundHandlerConfig{ + { + ReceiverSettings: serial.ToTypedMessage(&proxyman.ReceiverConfig{ + PortRange: net.SinglePortRange(serverPort), + Listen: net.NewIPOrDomain(net.LocalHostIP), + }), + ProxySettings: serial.ToTypedMessage(&shadowsocks.ServerConfig{ + User: &protocol.User{ + Account: account, + Level: 1, + }, + }), + }, + }, + Outbound: []*proxyman.OutboundHandlerConfig{ + { + ProxySettings: serial.ToTypedMessage(&freedom.Config{}), + }, + }, + } + + servers, err := InitializeServerConfigs(serverConfig) + assert(err, IsNil) + + var wg sync.WaitGroup + wg.Add(10) + for i := 0; i < 10; i++ { + go func() { + cipher, err := ss.PickCipher("AES-256-GCM", nil, "ss-password") + assert(err, IsNil) + conn, err := ss.Dial("tcp", fmt.Sprintf(":%d", serverPort), cipher) + assert(err, IsNil) + _, err = conn.Write([]byte{1, 127, 0, 0, 1}) + assert(err, IsNil) + _, err = conn.Write(serial.Uint16ToBytes(dest.Port.Value(), nil)) + assert(err, IsNil) + + payload := make([]byte, 10240*1024) + rand.Read(payload) + + nBytes, err := conn.Write([]byte(payload)) + assert(err, IsNil) + assert(nBytes, Equals, len(payload)) + + response := readFrom(conn, time.Second*30, 10240*1024) + assert(response, Equals, xor([]byte(payload))) + assert(conn.Close(), IsNil) + wg.Done() + }() + } + wg.Wait() + + CloseAllServers(servers) +} + +func TestShadowsocksChacha20Poly1305UDPConformance(t *testing.T) { + assert := With(t) + + udpServer := udp.Server{ + MsgProcessor: xor, + } + dest, err := udpServer.Start() + assert(err, IsNil) + defer udpServer.Close() + + account := serial.ToTypedMessage(&shadowsocks.Account{ + Password: "ss-password", + CipherType: shadowsocks.CipherType_CHACHA20_POLY1305, + }) + + serverPort := pickPort() + serverConfig := &core.Config{ + App: []*serial.TypedMessage{ + serial.ToTypedMessage(&log.Config{ + ErrorLogLevel: log.LogLevel_Debug, + ErrorLogType: log.LogType_Console, + }), + }, + Inbound: []*proxyman.InboundHandlerConfig{ + { + ReceiverSettings: serial.ToTypedMessage(&proxyman.ReceiverConfig{ + PortRange: net.SinglePortRange(serverPort), + Listen: net.NewIPOrDomain(net.LocalHostIP), + }), + ProxySettings: serial.ToTypedMessage(&shadowsocks.ServerConfig{ + UdpEnabled: true, + User: &protocol.User{ + Account: account, + Level: 1, + }, + }), + }, + }, + Outbound: []*proxyman.OutboundHandlerConfig{ + { + ProxySettings: serial.ToTypedMessage(&freedom.Config{}), + }, + }, + } + + servers, err := InitializeServerConfigs(serverConfig) + assert(err, IsNil) + + cipher, err := ss.PickCipher("CHACHA20-IETF-POLY1305", nil, "ss-password") + assert(err, IsNil) + conn, err := ss.ListenPacket("udp", ":0", cipher) + assert(err, IsNil) + + for i := 0; i < 100; i++ { + + payload := buf.New() + payload.AppendBytes(1, 127, 0, 0, 1) + payload.AppendSupplier(serial.WriteUint16(dest.Port.Value())) + + payload.AppendSupplier(buf.ReadFullFrom(rand.Reader, 10)) + + nBytes, err := conn.WriteTo(payload.Bytes(), &net.UDPAddr{ + IP: []byte{127, 0, 0, 1}, + Port: int(serverPort), + }) + assert(err, IsNil) + assert(nBytes, Equals, payload.Len()) + + conn.SetReadDeadline(time.Now().Add(time.Second * 10)) + response := make([]byte, 10240) + nBytes, _, err = conn.ReadFrom(response) + assert(err, IsNil) + assert(response[:7], Equals, payload.BytesTo(7)) + assert(response[7:nBytes], Equals, xor(payload.BytesFrom(7))) + + } + + assert(conn.Close(), IsNil) + + CloseAllServers(servers) +} + +func TestShadowsocksChacha20Conformance(t *testing.T) { + assert := With(t) + + tcpServer := tcp.Server{ + MsgProcessor: xor, + } + dest, err := tcpServer.Start() + assert(err, IsNil) + defer tcpServer.Close() + + account := serial.ToTypedMessage(&shadowsocks.Account{ + Password: "ss-password", + CipherType: shadowsocks.CipherType_CHACHA20_IETF, + Ota: shadowsocks.Account_Disabled, + }) + + serverPort := pickPort() + serverConfig := &core.Config{ + App: []*serial.TypedMessage{ + serial.ToTypedMessage(&log.Config{ + ErrorLogLevel: log.LogLevel_Debug, + ErrorLogType: log.LogType_Console, + }), + }, + Inbound: []*proxyman.InboundHandlerConfig{ + { + ReceiverSettings: serial.ToTypedMessage(&proxyman.ReceiverConfig{ + PortRange: net.SinglePortRange(serverPort), + Listen: net.NewIPOrDomain(net.LocalHostIP), + }), + ProxySettings: serial.ToTypedMessage(&shadowsocks.ServerConfig{ + User: &protocol.User{ + Account: account, + Level: 1, + }, + }), + }, + }, + Outbound: []*proxyman.OutboundHandlerConfig{ + { + ProxySettings: serial.ToTypedMessage(&freedom.Config{}), + }, + }, + } + + servers, err := InitializeServerConfigs(serverConfig) + assert(err, IsNil) + + var wg sync.WaitGroup + wg.Add(10) + for i := 0; i < 10; i++ { + go func() { + cipher, err := ss.PickCipher("CHACHA20-IETF", nil, "ss-password") + assert(err, IsNil) + conn, err := ss.Dial("tcp", fmt.Sprintf(":%d", serverPort), cipher) + assert(err, IsNil) + _, err = conn.Write([]byte{1, 127, 0, 0, 1}) + assert(err, IsNil) + _, err = conn.Write(serial.Uint16ToBytes(dest.Port.Value(), nil)) + assert(err, IsNil) + + payload := make([]byte, 10240*1024) + rand.Read(payload) + + nBytes, err := conn.Write([]byte(payload)) + assert(err, IsNil) + assert(nBytes, Equals, len(payload)) + + response := readFrom(conn, time.Second*30, 10240*1024) + assert(response, Equals, xor([]byte(payload))) + assert(conn.Close(), IsNil) wg.Done() }() } diff --git a/testing/scenarios/socks_test.go b/testing/scenarios/socks_test.go index 11f3a1e40..5351ad1c6 100644 --- a/testing/scenarios/socks_test.go +++ b/testing/scenarios/socks_test.go @@ -13,19 +13,19 @@ import ( "v2ray.com/core/proxy/dokodemo" "v2ray.com/core/proxy/freedom" "v2ray.com/core/proxy/socks" - "v2ray.com/core/testing/assert" "v2ray.com/core/testing/servers/tcp" "v2ray.com/core/testing/servers/udp" + . "v2ray.com/ext/assert" ) func TestSocksBridgeTCP(t *testing.T) { - assert := assert.On(t) + assert := With(t) tcpServer := tcp.Server{ MsgProcessor: xor, } dest, err := tcpServer.Start() - assert.Error(err).IsNil() + assert(err, IsNil) defer tcpServer.Close() serverPort := pickPort() @@ -93,36 +93,36 @@ func TestSocksBridgeTCP(t *testing.T) { } servers, err := InitializeServerConfigs(serverConfig, clientConfig) - assert.Error(err).IsNil() + assert(err, IsNil) conn, err := net.DialTCP("tcp", nil, &net.TCPAddr{ IP: []byte{127, 0, 0, 1}, Port: int(clientPort), }) - assert.Error(err).IsNil() + assert(err, IsNil) payload := "test payload" nBytes, err := conn.Write([]byte(payload)) - assert.Error(err).IsNil() - assert.Int(nBytes).Equals(len(payload)) + assert(err, IsNil) + assert(nBytes, Equals, len(payload)) response := make([]byte, 1024) nBytes, err = conn.Read(response) - assert.Error(err).IsNil() - assert.Bytes(response[:nBytes]).Equals(xor([]byte(payload))) - assert.Error(conn.Close()).IsNil() + assert(err, IsNil) + assert(response[:nBytes], Equals, xor([]byte(payload))) + assert(conn.Close(), IsNil) CloseAllServers(servers) } func TestSocksBridageUDP(t *testing.T) { - assert := assert.On(t) + assert := With(t) udpServer := udp.Server{ MsgProcessor: xor, } dest, err := udpServer.Start() - assert.Error(err).IsNil() + assert(err, IsNil) defer udpServer.Close() serverPort := pickPort() @@ -190,36 +190,36 @@ func TestSocksBridageUDP(t *testing.T) { } servers, err := InitializeServerConfigs(serverConfig, clientConfig) - assert.Error(err).IsNil() + assert(err, IsNil) conn, err := net.DialUDP("udp", nil, &net.UDPAddr{ IP: []byte{127, 0, 0, 1}, Port: int(clientPort), }) - assert.Error(err).IsNil() + assert(err, IsNil) payload := "dokodemo request." nBytes, err := conn.Write([]byte(payload)) - assert.Error(err).IsNil() - assert.Int(nBytes).Equals(len(payload)) + assert(err, IsNil) + assert(nBytes, Equals, len(payload)) response := make([]byte, 1024) nBytes, err = conn.Read(response) - assert.Error(err).IsNil() - assert.Bytes(response[:nBytes]).Equals(xor([]byte(payload))) - assert.Error(conn.Close()).IsNil() + assert(err, IsNil) + assert(response[:nBytes], Equals, xor([]byte(payload))) + assert(conn.Close(), IsNil) CloseAllServers(servers) } func TestSocksConformance(t *testing.T) { - assert := assert.On(t) + assert := With(t) tcpServer := tcp.Server{ MsgProcessor: xor, } dest, err := tcpServer.Start() - assert.Error(err).IsNil() + assert(err, IsNil) defer tcpServer.Close() authPort := pickPort() @@ -263,76 +263,76 @@ func TestSocksConformance(t *testing.T) { } servers, err := InitializeServerConfigs(serverConfig) - assert.Error(err).IsNil() + assert(err, IsNil) { noAuthDialer, err := xproxy.SOCKS5("tcp", net.TCPDestination(net.LocalHostIP, noAuthPort).NetAddr(), nil, xproxy.Direct) - assert.Error(err).IsNil() + assert(err, IsNil) conn, err := noAuthDialer.Dial("tcp", dest.NetAddr()) - assert.Error(err).IsNil() + assert(err, IsNil) payload := "test payload" nBytes, err := conn.Write([]byte(payload)) - assert.Error(err).IsNil() - assert.Int(nBytes).Equals(len(payload)) + assert(err, IsNil) + assert(nBytes, Equals, len(payload)) response := make([]byte, 1024) nBytes, err = conn.Read(response) - assert.Error(err).IsNil() - assert.Bytes(response[:nBytes]).Equals(xor([]byte(payload))) - assert.Error(conn.Close()).IsNil() + assert(err, IsNil) + assert(response[:nBytes], Equals, xor([]byte(payload))) + assert(conn.Close(), IsNil) } { authDialer, err := xproxy.SOCKS5("tcp", net.TCPDestination(net.LocalHostIP, authPort).NetAddr(), &xproxy.Auth{User: "Test Account", Password: "Test Password"}, xproxy.Direct) - assert.Error(err).IsNil() + assert(err, IsNil) conn, err := authDialer.Dial("tcp", dest.NetAddr()) - assert.Error(err).IsNil() + assert(err, IsNil) payload := "test payload" nBytes, err := conn.Write([]byte(payload)) - assert.Error(err).IsNil() - assert.Int(nBytes).Equals(len(payload)) + assert(err, IsNil) + assert(nBytes, Equals, len(payload)) response := make([]byte, 1024) nBytes, err = conn.Read(response) - assert.Error(err).IsNil() - assert.Bytes(response[:nBytes]).Equals(xor([]byte(payload))) - assert.Error(conn.Close()).IsNil() + assert(err, IsNil) + assert(response[:nBytes], Equals, xor([]byte(payload))) + assert(conn.Close(), IsNil) } { dialer := socks4.DialSocksProxy(socks4.SOCKS4, net.TCPDestination(net.LocalHostIP, noAuthPort).NetAddr()) conn, err := dialer("tcp", dest.NetAddr()) - assert.Error(err).IsNil() + assert(err, IsNil) payload := "test payload" nBytes, err := conn.Write([]byte(payload)) - assert.Error(err).IsNil() - assert.Int(nBytes).Equals(len(payload)) + assert(err, IsNil) + assert(nBytes, Equals, len(payload)) response := make([]byte, 1024) nBytes, err = conn.Read(response) - assert.Error(err).IsNil() - assert.Bytes(response[:nBytes]).Equals(xor([]byte(payload))) - assert.Error(conn.Close()).IsNil() + assert(err, IsNil) + assert(response[:nBytes], Equals, xor([]byte(payload))) + assert(conn.Close(), IsNil) } { dialer := socks4.DialSocksProxy(socks4.SOCKS4A, net.TCPDestination(net.LocalHostIP, noAuthPort).NetAddr()) conn, err := dialer("tcp", net.TCPDestination(net.LocalHostDomain, tcpServer.Port).NetAddr()) - assert.Error(err).IsNil() + assert(err, IsNil) payload := "test payload" nBytes, err := conn.Write([]byte(payload)) - assert.Error(err).IsNil() - assert.Int(nBytes).Equals(len(payload)) + assert(err, IsNil) + assert(nBytes, Equals, len(payload)) response := make([]byte, 1024) nBytes, err = conn.Read(response) - assert.Error(err).IsNil() - assert.Bytes(response[:nBytes]).Equals(xor([]byte(payload))) - assert.Error(conn.Close()).IsNil() + assert(err, IsNil) + assert(response[:nBytes], Equals, xor([]byte(payload))) + assert(conn.Close(), IsNil) } CloseAllServers(servers) diff --git a/testing/scenarios/tls_test.go b/testing/scenarios/tls_test.go index 8204157e1..76987d7a3 100644 --- a/testing/scenarios/tls_test.go +++ b/testing/scenarios/tls_test.go @@ -16,22 +16,23 @@ import ( "v2ray.com/core/proxy/vmess" "v2ray.com/core/proxy/vmess/inbound" "v2ray.com/core/proxy/vmess/outbound" - "v2ray.com/core/testing/assert" "v2ray.com/core/testing/servers/tcp" + "v2ray.com/core/testing/servers/udp" tlsgen "v2ray.com/core/testing/tls" "v2ray.com/core/transport/internet" "v2ray.com/core/transport/internet/tls" "v2ray.com/core/transport/internet/websocket" + . "v2ray.com/ext/assert" ) func TestSimpleTLSConnection(t *testing.T) { - assert := assert.On(t) + assert := With(t) tcpServer := tcp.Server{ MsgProcessor: xor, } dest, err := tcpServer.Start() - assert.Error(err).IsNil() + assert(err, IsNil) defer tcpServer.Close() userID := protocol.NewID(uuid.New()) @@ -118,38 +119,38 @@ func TestSimpleTLSConnection(t *testing.T) { } servers, err := InitializeServerConfigs(serverConfig, clientConfig) - assert.Error(err).IsNil() + assert(err, IsNil) conn, err := net.DialTCP("tcp", nil, &net.TCPAddr{ IP: []byte{127, 0, 0, 1}, Port: int(clientPort), }) - assert.Error(err).IsNil() + assert(err, IsNil) payload := "dokodemo request." nBytes, err := conn.Write([]byte(payload)) - assert.Error(err).IsNil() - assert.Int(nBytes).Equals(len(payload)) + assert(err, IsNil) + assert(nBytes, Equals, len(payload)) response := readFrom(conn, time.Second*2, len(payload)) - assert.Bytes(response).Equals(xor([]byte(payload))) - assert.Error(conn.Close()).IsNil() + assert(response, Equals, xor([]byte(payload))) + assert(conn.Close(), IsNil) CloseAllServers(servers) } func TestTLSOverKCP(t *testing.T) { - assert := assert.On(t) + assert := With(t) tcpServer := tcp.Server{ MsgProcessor: xor, } dest, err := tcpServer.Start() - assert.Error(err).IsNil() + assert(err, IsNil) defer tcpServer.Close() userID := protocol.NewID(uuid.New()) - serverPort := pickUDPPort() + serverPort := udp.PickPort() serverConfig := &core.Config{ Inbound: []*proxyman.InboundHandlerConfig{ { @@ -234,34 +235,34 @@ func TestTLSOverKCP(t *testing.T) { } servers, err := InitializeServerConfigs(serverConfig, clientConfig) - assert.Error(err).IsNil() + assert(err, IsNil) conn, err := net.DialTCP("tcp", nil, &net.TCPAddr{ IP: []byte{127, 0, 0, 1}, Port: int(clientPort), }) - assert.Error(err).IsNil() + assert(err, IsNil) payload := "dokodemo request." nBytes, err := conn.Write([]byte(payload)) - assert.Error(err).IsNil() - assert.Int(nBytes).Equals(len(payload)) + assert(err, IsNil) + assert(nBytes, Equals, len(payload)) response := readFrom(conn, time.Second*2, len(payload)) - assert.Bytes(response).Equals(xor([]byte(payload))) - assert.Error(conn.Close()).IsNil() + assert(response, Equals, xor([]byte(payload))) + assert(conn.Close(), IsNil) CloseAllServers(servers) } func TestTLSOverWebSocket(t *testing.T) { - assert := assert.On(t) + assert := With(t) tcpServer := tcp.Server{ MsgProcessor: xor, } dest, err := tcpServer.Start() - assert.Error(err).IsNil() + assert(err, IsNil) defer tcpServer.Close() userID := protocol.NewID(uuid.New()) @@ -356,23 +357,23 @@ func TestTLSOverWebSocket(t *testing.T) { } servers, err := InitializeServerConfigs(serverConfig, clientConfig) - assert.Error(err).IsNil() + assert(err, IsNil) conn, err := net.DialTCP("tcp", nil, &net.TCPAddr{ IP: []byte{127, 0, 0, 1}, Port: int(clientPort), }) - assert.Error(err).IsNil() + assert(err, IsNil) payload := make([]byte, 10240*1024) rand.Read(payload) nBytes, err := conn.Write([]byte(payload)) - assert.Error(err).IsNil() - assert.Int(nBytes).Equals(len(payload)) + assert(err, IsNil) + assert(nBytes, Equals, len(payload)) response := readFrom(conn, time.Second*20, len(payload)) - assert.Bytes(response).Equals(xor([]byte(payload))) - assert.Error(conn.Close()).IsNil() + assert(response, Equals, xor([]byte(payload))) + assert(conn.Close(), IsNil) CloseAllServers(servers) } diff --git a/testing/scenarios/transport_test.go b/testing/scenarios/transport_test.go index e2052e01d..a657366e8 100644 --- a/testing/scenarios/transport_test.go +++ b/testing/scenarios/transport_test.go @@ -15,21 +15,21 @@ import ( "v2ray.com/core/proxy/vmess" "v2ray.com/core/proxy/vmess/inbound" "v2ray.com/core/proxy/vmess/outbound" - "v2ray.com/core/testing/assert" "v2ray.com/core/testing/servers/tcp" "v2ray.com/core/transport/internet" "v2ray.com/core/transport/internet/headers/http" tcptransport "v2ray.com/core/transport/internet/tcp" + . "v2ray.com/ext/assert" ) func TestHttpConnectionHeader(t *testing.T) { - assert := assert.On(t) + assert := With(t) tcpServer := tcp.Server{ MsgProcessor: xor, } dest, err := tcpServer.Start() - assert.Error(err).IsNil() + assert(err, IsNil) defer tcpServer.Close() userID := protocol.NewID(uuid.New()) @@ -120,22 +120,22 @@ func TestHttpConnectionHeader(t *testing.T) { } servers, err := InitializeServerConfigs(serverConfig, clientConfig) - assert.Error(err).IsNil() + assert(err, IsNil) conn, err := net.DialTCP("tcp", nil, &net.TCPAddr{ IP: []byte{127, 0, 0, 1}, Port: int(clientPort), }) - assert.Error(err).IsNil() + assert(err, IsNil) payload := "dokodemo request." nBytes, err := conn.Write([]byte(payload)) - assert.Error(err).IsNil() - assert.Int(nBytes).Equals(len(payload)) + assert(err, IsNil) + assert(nBytes, Equals, len(payload)) response := readFrom(conn, time.Second*2, len(payload)) - assert.Bytes(response).Equals(xor([]byte(payload))) - assert.Error(conn.Close()).IsNil() + assert(response, Equals, xor([]byte(payload))) + assert(conn.Close(), IsNil) CloseAllServers(servers) } diff --git a/testing/scenarios/vmess_test.go b/testing/scenarios/vmess_test.go index 1334ce2bb..4d6984e66 100644 --- a/testing/scenarios/vmess_test.go +++ b/testing/scenarios/vmess_test.go @@ -18,25 +18,31 @@ import ( "v2ray.com/core/proxy/vmess" "v2ray.com/core/proxy/vmess/inbound" "v2ray.com/core/proxy/vmess/outbound" - "v2ray.com/core/testing/assert" "v2ray.com/core/testing/servers/tcp" "v2ray.com/core/testing/servers/udp" "v2ray.com/core/transport/internet" + . "v2ray.com/ext/assert" ) func TestVMessDynamicPort(t *testing.T) { - assert := assert.On(t) + assert := With(t) tcpServer := tcp.Server{ MsgProcessor: xor, } dest, err := tcpServer.Start() - assert.Error(err).IsNil() + assert(err, IsNil) defer tcpServer.Close() userID := protocol.NewID(uuid.New()) serverPort := pickPort() serverConfig := &core.Config{ + App: []*serial.TypedMessage{ + serial.ToTypedMessage(&log.Config{ + ErrorLogLevel: log.LogLevel_Debug, + ErrorLogType: log.LogType_Console, + }), + }, Inbound: []*proxyman.InboundHandlerConfig{ { ReceiverSettings: serial.ToTypedMessage(&proxyman.ReceiverConfig{ @@ -82,16 +88,16 @@ func TestVMessDynamicPort(t *testing.T) { ProxySettings: serial.ToTypedMessage(&freedom.Config{}), }, }, + } + + clientPort := pickPort() + clientConfig := &core.Config{ App: []*serial.TypedMessage{ serial.ToTypedMessage(&log.Config{ ErrorLogLevel: log.LogLevel_Debug, ErrorLogType: log.LogType_Console, }), }, - } - - clientPort := pickPort() - clientConfig := &core.Config{ Inbound: []*proxyman.InboundHandlerConfig{ { ReceiverSettings: serial.ToTypedMessage(&proxyman.ReceiverConfig{ @@ -126,52 +132,52 @@ func TestVMessDynamicPort(t *testing.T) { }), }, }, - App: []*serial.TypedMessage{ - serial.ToTypedMessage(&log.Config{ - ErrorLogLevel: log.LogLevel_Debug, - ErrorLogType: log.LogType_Console, - }), - }, } servers, err := InitializeServerConfigs(serverConfig, clientConfig) - assert.Error(err).IsNil() + assert(err, IsNil) for i := 0; i < 10; i++ { conn, err := net.DialTCP("tcp", nil, &net.TCPAddr{ IP: []byte{127, 0, 0, 1}, Port: int(clientPort), }) - assert.Error(err).IsNil() + assert(err, IsNil) payload := "dokodemo request." nBytes, err := conn.Write([]byte(payload)) - assert.Error(err).IsNil() - assert.Int(nBytes).Equals(len(payload)) + assert(err, IsNil) + assert(nBytes, Equals, len(payload)) response := make([]byte, 1024) nBytes, err = conn.Read(response) - assert.Error(err).IsNil() - assert.Bytes(response[:nBytes]).Equals(xor([]byte(payload))) - assert.Error(conn.Close()).IsNil() + assert(err, IsNil) + assert(response[:nBytes], Equals, xor([]byte(payload))) + assert(conn.Close(), IsNil) } CloseAllServers(servers) } func TestVMessGCM(t *testing.T) { - assert := assert.On(t) + assert := With(t) tcpServer := tcp.Server{ MsgProcessor: xor, } dest, err := tcpServer.Start() - assert.Error(err).IsNil() + assert(err, IsNil) defer tcpServer.Close() userID := protocol.NewID(uuid.New()) serverPort := pickPort() serverConfig := &core.Config{ + App: []*serial.TypedMessage{ + serial.ToTypedMessage(&log.Config{ + ErrorLogLevel: log.LogLevel_Debug, + ErrorLogType: log.LogType_Console, + }), + }, Inbound: []*proxyman.InboundHandlerConfig{ { ReceiverSettings: serial.ToTypedMessage(&proxyman.ReceiverConfig{ @@ -195,16 +201,16 @@ func TestVMessGCM(t *testing.T) { ProxySettings: serial.ToTypedMessage(&freedom.Config{}), }, }, + } + + clientPort := pickPort() + clientConfig := &core.Config{ App: []*serial.TypedMessage{ serial.ToTypedMessage(&log.Config{ ErrorLogLevel: log.LogLevel_Debug, ErrorLogType: log.LogType_Console, }), }, - } - - clientPort := pickPort() - clientConfig := &core.Config{ Inbound: []*proxyman.InboundHandlerConfig{ { ReceiverSettings: serial.ToTypedMessage(&proxyman.ReceiverConfig{ @@ -243,16 +249,10 @@ func TestVMessGCM(t *testing.T) { }), }, }, - App: []*serial.TypedMessage{ - serial.ToTypedMessage(&log.Config{ - ErrorLogLevel: log.LogLevel_Debug, - ErrorLogType: log.LogType_Console, - }), - }, } servers, err := InitializeServerConfigs(serverConfig, clientConfig) - assert.Error(err).IsNil() + assert(err, IsNil) var wg sync.WaitGroup wg.Add(10) @@ -262,18 +262,18 @@ func TestVMessGCM(t *testing.T) { IP: []byte{127, 0, 0, 1}, Port: int(clientPort), }) - assert.Error(err).IsNil() + assert(err, IsNil) payload := make([]byte, 10240*1024) rand.Read(payload) nBytes, err := conn.Write([]byte(payload)) - assert.Error(err).IsNil() - assert.Int(nBytes).Equals(len(payload)) + assert(err, IsNil) + assert(nBytes, Equals, len(payload)) response := readFrom(conn, time.Second*20, 10240*1024) - assert.Bytes(response).Equals(xor([]byte(payload))) - assert.Error(conn.Close()).IsNil() + assert(response, Equals, xor([]byte(payload))) + assert(conn.Close(), IsNil) wg.Done() }() } @@ -283,18 +283,24 @@ func TestVMessGCM(t *testing.T) { } func TestVMessGCMUDP(t *testing.T) { - assert := assert.On(t) + assert := With(t) udpServer := udp.Server{ MsgProcessor: xor, } dest, err := udpServer.Start() - assert.Error(err).IsNil() + assert(err, IsNil) defer udpServer.Close() userID := protocol.NewID(uuid.New()) serverPort := pickPort() serverConfig := &core.Config{ + App: []*serial.TypedMessage{ + serial.ToTypedMessage(&log.Config{ + ErrorLogLevel: log.LogLevel_Debug, + ErrorLogType: log.LogType_Console, + }), + }, Inbound: []*proxyman.InboundHandlerConfig{ { ReceiverSettings: serial.ToTypedMessage(&proxyman.ReceiverConfig{ @@ -318,16 +324,16 @@ func TestVMessGCMUDP(t *testing.T) { ProxySettings: serial.ToTypedMessage(&freedom.Config{}), }, }, + } + + clientPort := pickPort() + clientConfig := &core.Config{ App: []*serial.TypedMessage{ serial.ToTypedMessage(&log.Config{ ErrorLogLevel: log.LogLevel_Debug, ErrorLogType: log.LogType_Console, }), }, - } - - clientPort := pickPort() - clientConfig := &core.Config{ Inbound: []*proxyman.InboundHandlerConfig{ { ReceiverSettings: serial.ToTypedMessage(&proxyman.ReceiverConfig{ @@ -366,16 +372,10 @@ func TestVMessGCMUDP(t *testing.T) { }), }, }, - App: []*serial.TypedMessage{ - serial.ToTypedMessage(&log.Config{ - ErrorLogLevel: log.LogLevel_Debug, - ErrorLogType: log.LogType_Console, - }), - }, } servers, err := InitializeServerConfigs(serverConfig, clientConfig) - assert.Error(err).IsNil() + assert(err, IsNil) var wg sync.WaitGroup wg.Add(10) @@ -385,28 +385,28 @@ func TestVMessGCMUDP(t *testing.T) { IP: []byte{127, 0, 0, 1}, Port: int(clientPort), }) - assert.Error(err).IsNil() + assert(err, IsNil) payload := make([]byte, 1024) rand.Read(payload) nBytes, err := conn.Write([]byte(payload)) - assert.Error(err).IsNil() - assert.Int(nBytes).Equals(len(payload)) + assert(err, IsNil) + assert(nBytes, Equals, len(payload)) payload1 := make([]byte, 1024) rand.Read(payload1) nBytes, err = conn.Write([]byte(payload1)) - assert.Error(err).IsNil() - assert.Int(nBytes).Equals(len(payload1)) + assert(err, IsNil) + assert(nBytes, Equals, len(payload1)) response := readFrom(conn, time.Second*5, 1024) - assert.Bytes(response).Equals(xor([]byte(payload))) + assert(response, Equals, xor([]byte(payload))) response = readFrom(conn, time.Second*5, 1024) - assert.Bytes(response).Equals(xor([]byte(payload1))) + assert(response, Equals, xor([]byte(payload1))) - assert.Error(conn.Close()).IsNil() + assert(conn.Close(), IsNil) wg.Done() }() } @@ -416,18 +416,24 @@ func TestVMessGCMUDP(t *testing.T) { } func TestVMessChacha20(t *testing.T) { - assert := assert.On(t) + assert := With(t) tcpServer := tcp.Server{ MsgProcessor: xor, } dest, err := tcpServer.Start() - assert.Error(err).IsNil() + assert(err, IsNil) defer tcpServer.Close() userID := protocol.NewID(uuid.New()) serverPort := pickPort() serverConfig := &core.Config{ + App: []*serial.TypedMessage{ + serial.ToTypedMessage(&log.Config{ + ErrorLogLevel: log.LogLevel_Debug, + ErrorLogType: log.LogType_Console, + }), + }, Inbound: []*proxyman.InboundHandlerConfig{ { ReceiverSettings: serial.ToTypedMessage(&proxyman.ReceiverConfig{ @@ -451,16 +457,16 @@ func TestVMessChacha20(t *testing.T) { ProxySettings: serial.ToTypedMessage(&freedom.Config{}), }, }, + } + + clientPort := pickPort() + clientConfig := &core.Config{ App: []*serial.TypedMessage{ serial.ToTypedMessage(&log.Config{ ErrorLogLevel: log.LogLevel_Debug, ErrorLogType: log.LogType_Console, }), }, - } - - clientPort := pickPort() - clientConfig := &core.Config{ Inbound: []*proxyman.InboundHandlerConfig{ { ReceiverSettings: serial.ToTypedMessage(&proxyman.ReceiverConfig{ @@ -499,16 +505,10 @@ func TestVMessChacha20(t *testing.T) { }), }, }, - App: []*serial.TypedMessage{ - serial.ToTypedMessage(&log.Config{ - ErrorLogLevel: log.LogLevel_Debug, - ErrorLogType: log.LogType_Console, - }), - }, } servers, err := InitializeServerConfigs(serverConfig, clientConfig) - assert.Error(err).IsNil() + assert(err, IsNil) var wg sync.WaitGroup wg.Add(10) @@ -518,18 +518,18 @@ func TestVMessChacha20(t *testing.T) { IP: []byte{127, 0, 0, 1}, Port: int(clientPort), }) - assert.Error(err).IsNil() + assert(err, IsNil) payload := make([]byte, 10240*1024) rand.Read(payload) nBytes, err := conn.Write([]byte(payload)) - assert.Error(err).IsNil() - assert.Int(nBytes).Equals(len(payload)) + assert(err, IsNil) + assert(nBytes, Equals, len(payload)) response := readFrom(conn, time.Second*20, 10240*1024) - assert.Bytes(response).Equals(xor([]byte(payload))) - assert.Error(conn.Close()).IsNil() + assert(response, Equals, xor([]byte(payload))) + assert(conn.Close(), IsNil) wg.Done() }() } @@ -539,18 +539,24 @@ func TestVMessChacha20(t *testing.T) { } func TestVMessNone(t *testing.T) { - assert := assert.On(t) + assert := With(t) tcpServer := tcp.Server{ MsgProcessor: xor, } dest, err := tcpServer.Start() - assert.Error(err).IsNil() + assert(err, IsNil) defer tcpServer.Close() userID := protocol.NewID(uuid.New()) serverPort := pickPort() serverConfig := &core.Config{ + App: []*serial.TypedMessage{ + serial.ToTypedMessage(&log.Config{ + ErrorLogLevel: log.LogLevel_Debug, + ErrorLogType: log.LogType_Console, + }), + }, Inbound: []*proxyman.InboundHandlerConfig{ { ReceiverSettings: serial.ToTypedMessage(&proxyman.ReceiverConfig{ @@ -574,16 +580,16 @@ func TestVMessNone(t *testing.T) { ProxySettings: serial.ToTypedMessage(&freedom.Config{}), }, }, + } + + clientPort := pickPort() + clientConfig := &core.Config{ App: []*serial.TypedMessage{ serial.ToTypedMessage(&log.Config{ ErrorLogLevel: log.LogLevel_Debug, ErrorLogType: log.LogType_Console, }), }, - } - - clientPort := pickPort() - clientConfig := &core.Config{ Inbound: []*proxyman.InboundHandlerConfig{ { ReceiverSettings: serial.ToTypedMessage(&proxyman.ReceiverConfig{ @@ -622,38 +628,34 @@ func TestVMessNone(t *testing.T) { }), }, }, - App: []*serial.TypedMessage{ - serial.ToTypedMessage(&log.Config{ - ErrorLogLevel: log.LogLevel_Debug, - ErrorLogType: log.LogType_Console, - }), - }, } servers, err := InitializeServerConfigs(serverConfig, clientConfig) - assert.Error(err).IsNil() + assert(err, IsNil) var wg sync.WaitGroup wg.Add(10) for i := 0; i < 10; i++ { go func() { + defer wg.Done() + conn, err := net.DialTCP("tcp", nil, &net.TCPAddr{ IP: []byte{127, 0, 0, 1}, Port: int(clientPort), }) - assert.Error(err).IsNil() + assert(err, IsNil) payload := make([]byte, 1024*1024) rand.Read(payload) nBytes, err := conn.Write(payload) - assert.Error(err).IsNil() - assert.Int(nBytes).Equals(len(payload)) + assert(err, IsNil) + assert(nBytes, Equals, len(payload)) - response := readFrom(conn, time.Second*20, 1024*1024) - assert.Bytes(response).Equals(xor(payload)) - assert.Error(conn.Close()).IsNil() - wg.Done() + response := readFrom(conn, time.Second*30, 1024*1024) + + assert(response, Equals, xor(payload)) + assert(conn.Close(), IsNil) }() } wg.Wait() @@ -662,18 +664,24 @@ func TestVMessNone(t *testing.T) { } func TestVMessKCP(t *testing.T) { - assert := assert.On(t) + assert := With(t) tcpServer := tcp.Server{ MsgProcessor: xor, } dest, err := tcpServer.Start() - assert.Error(err).IsNil() + assert(err, IsNil) defer tcpServer.Close() userID := protocol.NewID(uuid.New()) - serverPort := pickUDPPort() + serverPort := udp.PickPort() serverConfig := &core.Config{ + App: []*serial.TypedMessage{ + serial.ToTypedMessage(&log.Config{ + ErrorLogLevel: log.LogLevel_Debug, + ErrorLogType: log.LogType_Console, + }), + }, Inbound: []*proxyman.InboundHandlerConfig{ { ReceiverSettings: serial.ToTypedMessage(&proxyman.ReceiverConfig{ @@ -700,16 +708,16 @@ func TestVMessKCP(t *testing.T) { ProxySettings: serial.ToTypedMessage(&freedom.Config{}), }, }, + } + + clientPort := pickPort() + clientConfig := &core.Config{ App: []*serial.TypedMessage{ serial.ToTypedMessage(&log.Config{ ErrorLogLevel: log.LogLevel_Debug, ErrorLogType: log.LogType_Console, }), }, - } - - clientPort := pickPort() - clientConfig := &core.Config{ Inbound: []*proxyman.InboundHandlerConfig{ { ReceiverSettings: serial.ToTypedMessage(&proxyman.ReceiverConfig{ @@ -753,16 +761,10 @@ func TestVMessKCP(t *testing.T) { }), }, }, - App: []*serial.TypedMessage{ - serial.ToTypedMessage(&log.Config{ - ErrorLogLevel: log.LogLevel_Debug, - ErrorLogType: log.LogType_Console, - }), - }, } servers, err := InitializeServerConfigs(serverConfig, clientConfig) - assert.Error(err).IsNil() + assert(err, IsNil) var wg sync.WaitGroup for i := 0; i < 10; i++ { @@ -772,18 +774,18 @@ func TestVMessKCP(t *testing.T) { IP: []byte{127, 0, 0, 1}, Port: int(clientPort), }) - assert.Error(err).IsNil() + assert(err, IsNil) payload := make([]byte, 10240*1024) rand.Read(payload) nBytes, err := conn.Write(payload) - assert.Error(err).IsNil() - assert.Int(nBytes).Equals(len(payload)) + assert(err, IsNil) + assert(nBytes, Equals, len(payload)) response := readFrom(conn, time.Minute, 10240*1024) - assert.Bytes(response).Equals(xor(payload)) - assert.Error(conn.Close()).IsNil() + assert(response, Equals, xor(payload)) + assert(conn.Close(), IsNil) wg.Done() }() } @@ -794,19 +796,25 @@ func TestVMessKCP(t *testing.T) { func TestVMessIPv6(t *testing.T) { t.SkipNow() // No IPv6 on travis-ci. - assert := assert.On(t) + assert := With(t) tcpServer := tcp.Server{ MsgProcessor: xor, Listen: net.LocalHostIPv6, } dest, err := tcpServer.Start() - assert.Error(err).IsNil() + assert(err, IsNil) defer tcpServer.Close() userID := protocol.NewID(uuid.New()) serverPort := pickPort() serverConfig := &core.Config{ + App: []*serial.TypedMessage{ + serial.ToTypedMessage(&log.Config{ + ErrorLogLevel: log.LogLevel_Debug, + ErrorLogType: log.LogType_Console, + }), + }, Inbound: []*proxyman.InboundHandlerConfig{ { ReceiverSettings: serial.ToTypedMessage(&proxyman.ReceiverConfig{ @@ -830,16 +838,16 @@ func TestVMessIPv6(t *testing.T) { ProxySettings: serial.ToTypedMessage(&freedom.Config{}), }, }, + } + + clientPort := pickPort() + clientConfig := &core.Config{ App: []*serial.TypedMessage{ serial.ToTypedMessage(&log.Config{ ErrorLogLevel: log.LogLevel_Debug, ErrorLogType: log.LogType_Console, }), }, - } - - clientPort := pickPort() - clientConfig := &core.Config{ Inbound: []*proxyman.InboundHandlerConfig{ { ReceiverSettings: serial.ToTypedMessage(&proxyman.ReceiverConfig{ @@ -878,50 +886,50 @@ func TestVMessIPv6(t *testing.T) { }), }, }, + } + + servers, err := InitializeServerConfigs(serverConfig, clientConfig) + assert(err, IsNil) + + conn, err := net.DialTCP("tcp", nil, &net.TCPAddr{ + IP: net.LocalHostIPv6.IP(), + Port: int(clientPort), + }) + assert(err, IsNil) + + payload := make([]byte, 1024) + rand.Read(payload) + + nBytes, err := conn.Write(payload) + assert(err, IsNil) + assert(nBytes, Equals, len(payload)) + + response := readFrom(conn, time.Second*20, 1024) + assert(response, Equals, xor(payload)) + assert(conn.Close(), IsNil) + + CloseAllServers(servers) +} + +func TestVMessGCMMux(t *testing.T) { + assert := With(t) + + tcpServer := tcp.Server{ + MsgProcessor: xor, + } + dest, err := tcpServer.Start() + assert(err, IsNil) + defer tcpServer.Close() + + userID := protocol.NewID(uuid.New()) + serverPort := pickPort() + serverConfig := &core.Config{ App: []*serial.TypedMessage{ serial.ToTypedMessage(&log.Config{ ErrorLogLevel: log.LogLevel_Debug, ErrorLogType: log.LogType_Console, }), }, - } - - servers, err := InitializeServerConfigs(serverConfig, clientConfig) - assert.Error(err).IsNil() - - conn, err := net.DialTCP("tcp", nil, &net.TCPAddr{ - IP: net.LocalHostIPv6.IP(), - Port: int(clientPort), - }) - assert.Error(err).IsNil() - - payload := make([]byte, 1024) - rand.Read(payload) - - nBytes, err := conn.Write(payload) - assert.Error(err).IsNil() - assert.Int(nBytes).Equals(len(payload)) - - response := readFrom(conn, time.Second*20, 1024) - assert.Bytes(response).Equals(xor(payload)) - assert.Error(conn.Close()).IsNil() - - CloseAllServers(servers) -} - -func TestVMessGCMMux(t *testing.T) { - assert := assert.On(t) - - tcpServer := tcp.Server{ - MsgProcessor: xor, - } - dest, err := tcpServer.Start() - assert.Error(err).IsNil() - defer tcpServer.Close() - - userID := protocol.NewID(uuid.New()) - serverPort := pickPort() - serverConfig := &core.Config{ Inbound: []*proxyman.InboundHandlerConfig{ { ReceiverSettings: serial.ToTypedMessage(&proxyman.ReceiverConfig{ @@ -945,16 +953,16 @@ func TestVMessGCMMux(t *testing.T) { ProxySettings: serial.ToTypedMessage(&freedom.Config{}), }, }, + } + + clientPort := pickPort() + clientConfig := &core.Config{ App: []*serial.TypedMessage{ serial.ToTypedMessage(&log.Config{ ErrorLogLevel: log.LogLevel_Debug, ErrorLogType: log.LogType_Console, }), }, - } - - clientPort := pickPort() - clientConfig := &core.Config{ Inbound: []*proxyman.InboundHandlerConfig{ { ReceiverSettings: serial.ToTypedMessage(&proxyman.ReceiverConfig{ @@ -999,16 +1007,10 @@ func TestVMessGCMMux(t *testing.T) { }), }, }, - App: []*serial.TypedMessage{ - serial.ToTypedMessage(&log.Config{ - ErrorLogLevel: log.LogLevel_Debug, - ErrorLogType: log.LogType_Console, - }), - }, } servers, err := InitializeServerConfigs(serverConfig, clientConfig) - assert.Error(err).IsNil() + assert(err, IsNil) for range "abcd" { var wg sync.WaitGroup @@ -1020,7 +1022,7 @@ func TestVMessGCMMux(t *testing.T) { IP: []byte{127, 0, 0, 1}, Port: int(clientPort), }) - assert.Error(err).IsNil() + assert(err, IsNil) payload := make([]byte, 10240) rand.Read(payload) @@ -1028,12 +1030,12 @@ func TestVMessGCMMux(t *testing.T) { xorpayload := xor(payload) nBytes, err := conn.Write(payload) - assert.Error(err).IsNil() - assert.Int(nBytes).Equals(len(payload)) + assert(err, IsNil) + assert(nBytes, Equals, len(payload)) response := readFrom(conn, time.Second*20, 10240) - assert.Bytes(response).Equals(xorpayload) - assert.Error(conn.Close()).IsNil() + assert(response, Equals, xorpayload) + assert(conn.Close(), IsNil) wg.Done() }() } @@ -1045,25 +1047,31 @@ func TestVMessGCMMux(t *testing.T) { } func TestVMessGCMMuxUDP(t *testing.T) { - assert := assert.On(t) + assert := With(t) tcpServer := tcp.Server{ MsgProcessor: xor, } dest, err := tcpServer.Start() - assert.Error(err).IsNil() + assert(err, IsNil) defer tcpServer.Close() udpServer := udp.Server{ MsgProcessor: xor, } udpDest, err := udpServer.Start() - assert.Error(err).IsNil() + assert(err, IsNil) defer udpServer.Close() userID := protocol.NewID(uuid.New()) serverPort := pickPort() serverConfig := &core.Config{ + App: []*serial.TypedMessage{ + serial.ToTypedMessage(&log.Config{ + ErrorLogLevel: log.LogLevel_Debug, + ErrorLogType: log.LogType_Console, + }), + }, Inbound: []*proxyman.InboundHandlerConfig{ { ReceiverSettings: serial.ToTypedMessage(&proxyman.ReceiverConfig{ @@ -1087,17 +1095,17 @@ func TestVMessGCMMuxUDP(t *testing.T) { ProxySettings: serial.ToTypedMessage(&freedom.Config{}), }, }, + } + + clientPort := pickPort() + clientUDPPort := udp.PickPort() + clientConfig := &core.Config{ App: []*serial.TypedMessage{ serial.ToTypedMessage(&log.Config{ ErrorLogLevel: log.LogLevel_Debug, ErrorLogType: log.LogType_Console, }), }, - } - - clientPort := pickPort() - clientUDPPort := pickUDPPort() - clientConfig := &core.Config{ Inbound: []*proxyman.InboundHandlerConfig{ { ReceiverSettings: serial.ToTypedMessage(&proxyman.ReceiverConfig{ @@ -1155,16 +1163,10 @@ func TestVMessGCMMuxUDP(t *testing.T) { }), }, }, - App: []*serial.TypedMessage{ - serial.ToTypedMessage(&log.Config{ - ErrorLogLevel: log.LogLevel_Debug, - ErrorLogType: log.LogType_Console, - }), - }, } servers, err := InitializeServerConfigs(serverConfig, clientConfig) - assert.Error(err).IsNil() + assert(err, IsNil) for range "abcd" { var wg sync.WaitGroup @@ -1176,7 +1178,7 @@ func TestVMessGCMMuxUDP(t *testing.T) { IP: []byte{127, 0, 0, 1}, Port: int(clientPort), }) - assert.Error(err).IsNil() + assert(err, IsNil) payload := make([]byte, 10240) rand.Read(payload) @@ -1184,12 +1186,12 @@ func TestVMessGCMMuxUDP(t *testing.T) { xorpayload := xor(payload) nBytes, err := conn.Write(payload) - assert.Error(err).IsNil() - assert.Int(nBytes).Equals(len(payload)) + assert(err, IsNil) + assert(nBytes, Equals, len(payload)) response := readFrom(conn, time.Second*20, 10240) - assert.Bytes(response).Equals(xorpayload) - assert.Error(conn.Close()).IsNil() + assert(response, Equals, xorpayload) + assert(conn.Close(), IsNil) wg.Done() }() } @@ -1199,7 +1201,7 @@ func TestVMessGCMMuxUDP(t *testing.T) { IP: []byte{127, 0, 0, 1}, Port: int(clientUDPPort), }) - assert.Error(err).IsNil() + assert(err, IsNil) conn.SetDeadline(time.Now().Add(time.Second * 10)) @@ -1210,20 +1212,20 @@ func TestVMessGCMMuxUDP(t *testing.T) { for j := 0; j < 2; j++ { nBytes, _, err := conn.WriteMsgUDP(payload, nil, nil) - assert.Error(err).IsNil() - assert.Int(nBytes).Equals(len(payload)) + assert(err, IsNil) + assert(nBytes, Equals, len(payload)) } response := make([]byte, 1024) oob := make([]byte, 16) for j := 0; j < 2; j++ { nBytes, _, _, _, err := conn.ReadMsgUDP(response, oob) - assert.Error(err).IsNil() - assert.Int(nBytes).Equals(1024) - assert.Bytes(response).Equals(xorpayload) + assert(err, IsNil) + assert(nBytes, Equals, 1024) + assert(response, Equals, xorpayload) } - assert.Error(conn.Close()).IsNil() + assert(conn.Close(), IsNil) wg.Done() }() } diff --git a/testing/servers/http/http.go b/testing/servers/http/http.go index 47ecca114..230e973ce 100644 --- a/testing/servers/http/http.go +++ b/testing/servers/http/http.go @@ -10,9 +10,10 @@ type Server struct { Port net.Port PathHandler map[string]http.HandlerFunc accepting bool + server *http.Server } -func (server *Server) ServeHTTP(resp http.ResponseWriter, req *http.Request) { +func (s *Server) ServeHTTP(resp http.ResponseWriter, req *http.Request) { if req.URL.Path == "/" { resp.Header().Set("Content-Type", "text/plain; charset=utf-8") resp.WriteHeader(http.StatusOK) @@ -20,17 +21,21 @@ func (server *Server) ServeHTTP(resp http.ResponseWriter, req *http.Request) { return } - handler, found := server.PathHandler[req.URL.Path] + handler, found := s.PathHandler[req.URL.Path] if found { handler(resp, req) } } -func (server *Server) Start() (net.Destination, error) { - go http.ListenAndServe("127.0.0.1:"+server.Port.String(), server) - return net.TCPDestination(net.LocalHostIP, net.Port(server.Port)), nil +func (s *Server) Start() (net.Destination, error) { + s.server = &http.Server{ + Addr: "127.0.0.1:" + s.Port.String(), + Handler: s, + } + go s.server.ListenAndServe() + return net.TCPDestination(net.LocalHostIP, net.Port(s.Port)), nil } -func (v *Server) Close() { - v.accepting = false +func (s *Server) Close() { + s.server.Close() } diff --git a/testing/servers/tcp/tcp.go b/testing/servers/tcp/tcp.go index 8117318db..48c819c00 100644 --- a/testing/servers/tcp/tcp.go +++ b/testing/servers/tcp/tcp.go @@ -12,7 +12,6 @@ type Server struct { MsgProcessor func(msg []byte) []byte SendFirst []byte Listen net.Address - accepting bool listener *net.TCPListener } @@ -37,12 +36,11 @@ func (server *Server) Start() (net.Destination, error) { } func (server *Server) acceptConnections(listener *net.TCPListener) { - server.accepting = true - for server.accepting { + for { conn, err := listener.Accept() if err != nil { fmt.Printf("Failed accept TCP connection: %v\n", err) - continue + return } go server.handleConnection(conn) @@ -71,7 +69,6 @@ func (server *Server) handleConnection(conn net.Conn) { conn.Close() } -func (v *Server) Close() { - v.accepting = false - v.listener.Close() +func (server *Server) Close() { + server.listener.Close() } diff --git a/testing/servers/udp/port.go b/testing/servers/udp/port.go new file mode 100644 index 000000000..0c77c4cff --- /dev/null +++ b/testing/servers/udp/port.go @@ -0,0 +1,18 @@ +package udp + +import ( + "v2ray.com/core/common" + "v2ray.com/core/common/net" +) + +func PickPort() net.Port { + conn, err := net.ListenUDP("udp4", &net.UDPAddr{ + IP: net.LocalHostIP.IP(), + Port: 0, + }) + common.Must(err) + defer conn.Close() + + addr := conn.LocalAddr().(*net.UDPAddr) + return net.Port(addr.Port) +} diff --git a/tools/conf/conf.go b/tools/conf/conf.go deleted file mode 100644 index 9e1693d56..000000000 --- a/tools/conf/conf.go +++ /dev/null @@ -1,16 +0,0 @@ -package conf - -import ( - "io" - - "v2ray.com/core" - jsonconf "v2ray.com/ext/tools/conf/serial" -) - -//go:generate go run $GOPATH/src/v2ray.com/core/tools/generrorgen/main.go -pkg conf -path Tools,Conf - -func init() { - core.RegisterConfigLoader(core.ConfigFormat_JSON, func(input io.Reader) (*core.Config, error) { - return jsonconf.LoadJSONConfig(input) - }) -} diff --git a/tools/conf/errors.generated.go b/tools/conf/errors.generated.go deleted file mode 100644 index 5051189c5..000000000 --- a/tools/conf/errors.generated.go +++ /dev/null @@ -1,5 +0,0 @@ -package conf - -import "v2ray.com/core/common/errors" - -func newError(values ...interface{}) *errors.Error { return errors.New(values...).Path("Tools", "Conf") } diff --git a/tools/geoip/geoip.generated.go b/tools/geoip/geoip.generated.go deleted file mode 100644 index 689a9291d..000000000 --- a/tools/geoip/geoip.generated.go +++ /dev/null @@ -1,3 +0,0 @@ -package geoip - -var ChinaIPs = []byte{10, 8, 10, 4, 1, 0, 1, 0, 16, 24, 10, 8, 10, 4, 1, 0, 2, 0, 16, 23, 10, 8, 10, 4, 1, 0, 8, 0, 16, 21, 10, 8, 10, 4, 1, 0, 32, 0, 16, 19, 10, 8, 10, 4, 1, 1, 0, 0, 16, 24, 10, 8, 10, 4, 1, 1, 2, 0, 16, 23, 10, 8, 10, 4, 1, 1, 4, 0, 16, 22, 10, 8, 10, 4, 1, 1, 8, 0, 16, 24, 10, 8, 10, 4, 1, 1, 9, 0, 16, 24, 10, 8, 10, 4, 1, 1, 10, 0, 16, 23, 10, 8, 10, 4, 1, 1, 12, 0, 16, 22, 10, 8, 10, 4, 1, 1, 16, 0, 16, 20, 10, 8, 10, 4, 1, 1, 32, 0, 16, 19, 10, 8, 10, 4, 1, 2, 0, 0, 16, 23, 10, 8, 10, 4, 1, 2, 2, 0, 16, 24, 10, 8, 10, 4, 1, 2, 4, 0, 16, 24, 10, 8, 10, 4, 1, 2, 5, 0, 16, 24, 10, 8, 10, 4, 1, 2, 6, 0, 16, 23, 10, 8, 10, 4, 1, 2, 8, 0, 16, 24, 10, 8, 10, 4, 1, 2, 9, 0, 16, 24, 10, 8, 10, 4, 1, 2, 10, 0, 16, 23, 10, 8, 10, 4, 1, 2, 12, 0, 16, 22, 10, 8, 10, 4, 1, 2, 16, 0, 16, 20, 10, 8, 10, 4, 1, 2, 32, 0, 16, 19, 10, 8, 10, 4, 1, 2, 64, 0, 16, 18, 10, 8, 10, 4, 1, 3, 0, 0, 16, 16, 10, 8, 10, 4, 1, 4, 1, 0, 16, 24, 10, 8, 10, 4, 1, 4, 2, 0, 16, 23, 10, 8, 10, 4, 1, 4, 4, 0, 16, 24, 10, 8, 10, 4, 1, 4, 5, 0, 16, 24, 10, 8, 10, 4, 1, 4, 6, 0, 16, 23, 10, 8, 10, 4, 1, 4, 8, 0, 16, 21, 10, 8, 10, 4, 1, 4, 16, 0, 16, 20, 10, 8, 10, 4, 1, 4, 32, 0, 16, 19, 10, 8, 10, 4, 1, 4, 64, 0, 16, 18, 10, 8, 10, 4, 1, 8, 0, 0, 16, 16, 10, 8, 10, 4, 1, 10, 0, 0, 16, 21, 10, 8, 10, 4, 1, 10, 8, 0, 16, 23, 10, 8, 10, 4, 1, 10, 11, 0, 16, 24, 10, 8, 10, 4, 1, 10, 12, 0, 16, 22, 10, 8, 10, 4, 1, 10, 16, 0, 16, 20, 10, 8, 10, 4, 1, 10, 32, 0, 16, 19, 10, 8, 10, 4, 1, 10, 64, 0, 16, 18, 10, 8, 10, 4, 1, 12, 0, 0, 16, 14, 10, 8, 10, 4, 1, 24, 0, 0, 16, 13, 10, 8, 10, 4, 1, 45, 0, 0, 16, 16, 10, 8, 10, 4, 1, 48, 0, 0, 16, 15, 10, 8, 10, 4, 1, 50, 0, 0, 16, 16, 10, 8, 10, 4, 1, 51, 0, 0, 16, 16, 10, 8, 10, 4, 1, 56, 0, 0, 16, 13, 10, 8, 10, 4, 1, 68, 0, 0, 16, 14, 10, 8, 10, 4, 1, 80, 0, 0, 16, 13, 10, 8, 10, 4, 1, 88, 0, 0, 16, 14, 10, 8, 10, 4, 1, 92, 0, 0, 16, 15, 10, 8, 10, 4, 1, 94, 0, 0, 16, 15, 10, 8, 10, 4, 1, 116, 0, 0, 16, 15, 10, 8, 10, 4, 1, 118, 0, 0, 16, 16, 10, 8, 10, 4, 1, 119, 0, 0, 16, 17, 10, 8, 10, 4, 1, 119, 128, 0, 16, 17, 10, 8, 10, 4, 1, 180, 0, 0, 16, 14, 10, 8, 10, 4, 1, 184, 0, 0, 16, 15, 10, 8, 10, 4, 1, 188, 0, 0, 16, 14, 10, 8, 10, 4, 1, 192, 0, 0, 16, 13, 10, 8, 10, 4, 1, 202, 0, 0, 16, 15, 10, 8, 10, 4, 1, 204, 0, 0, 16, 14, 10, 8, 10, 4, 14, 0, 0, 0, 16, 21, 10, 8, 10, 4, 14, 0, 12, 0, 16, 22, 10, 8, 10, 4, 14, 1, 0, 0, 16, 22, 10, 8, 10, 4, 14, 1, 24, 0, 16, 22, 10, 8, 10, 4, 14, 1, 96, 0, 16, 22, 10, 8, 10, 4, 14, 1, 108, 0, 16, 22, 10, 8, 10, 4, 14, 16, 0, 0, 16, 12, 10, 8, 10, 4, 14, 102, 128, 0, 16, 22, 10, 8, 10, 4, 14, 102, 156, 0, 16, 22, 10, 8, 10, 4, 14, 102, 180, 0, 16, 22, 10, 8, 10, 4, 14, 103, 0, 0, 16, 16, 10, 8, 10, 4, 14, 104, 0, 0, 16, 13, 10, 8, 10, 4, 14, 112, 0, 0, 16, 12, 10, 8, 10, 4, 14, 130, 0, 0, 16, 15, 10, 8, 10, 4, 14, 134, 0, 0, 16, 15, 10, 8, 10, 4, 14, 144, 0, 0, 16, 12, 10, 8, 10, 4, 14, 192, 4, 0, 16, 22, 10, 8, 10, 4, 14, 192, 60, 0, 16, 22, 10, 8, 10, 4, 14, 192, 76, 0, 16, 22, 10, 8, 10, 4, 14, 196, 0, 0, 16, 15, 10, 8, 10, 4, 14, 204, 0, 0, 16, 15, 10, 8, 10, 4, 14, 208, 0, 0, 16, 12, 10, 8, 10, 4, 27, 0, 128, 0, 16, 22, 10, 8, 10, 4, 27, 0, 132, 0, 16, 22, 10, 8, 10, 4, 27, 0, 160, 0, 16, 22, 10, 8, 10, 4, 27, 0, 164, 0, 16, 22, 10, 8, 10, 4, 27, 0, 188, 0, 16, 22, 10, 8, 10, 4, 27, 0, 204, 0, 16, 22, 10, 8, 10, 4, 27, 0, 208, 0, 16, 22, 10, 8, 10, 4, 27, 0, 212, 0, 16, 22, 10, 8, 10, 4, 27, 8, 0, 0, 16, 13, 10, 8, 10, 4, 27, 16, 0, 0, 16, 12, 10, 8, 10, 4, 27, 34, 232, 0, 16, 21, 10, 8, 10, 4, 27, 36, 0, 0, 16, 14, 10, 8, 10, 4, 27, 40, 0, 0, 16, 13, 10, 8, 10, 4, 27, 50, 40, 0, 16, 21, 10, 8, 10, 4, 27, 50, 128, 0, 16, 17, 10, 8, 10, 4, 27, 54, 72, 0, 16, 21, 10, 8, 10, 4, 27, 54, 152, 0, 16, 21, 10, 8, 10, 4, 27, 54, 192, 0, 16, 18, 10, 8, 10, 4, 27, 98, 208, 0, 16, 20, 10, 8, 10, 4, 27, 98, 224, 0, 16, 19, 10, 8, 10, 4, 27, 99, 128, 0, 16, 17, 10, 8, 10, 4, 27, 103, 0, 0, 16, 16, 10, 8, 10, 4, 27, 106, 128, 0, 16, 18, 10, 8, 10, 4, 27, 106, 204, 0, 16, 22, 10, 8, 10, 4, 27, 109, 32, 0, 16, 19, 10, 8, 10, 4, 27, 109, 124, 0, 16, 22, 10, 8, 10, 4, 27, 112, 0, 0, 16, 18, 10, 8, 10, 4, 27, 112, 80, 0, 16, 20, 10, 8, 10, 4, 27, 112, 112, 0, 16, 22, 10, 8, 10, 4, 27, 112, 116, 0, 16, 22, 10, 8, 10, 4, 27, 113, 128, 0, 16, 18, 10, 8, 10, 4, 27, 115, 0, 0, 16, 17, 10, 8, 10, 4, 27, 116, 44, 0, 16, 22, 10, 8, 10, 4, 27, 121, 72, 0, 16, 21, 10, 8, 10, 4, 27, 121, 120, 0, 16, 21, 10, 8, 10, 4, 27, 123, 232, 0, 16, 22, 10, 8, 10, 4, 27, 128, 0, 0, 16, 15, 10, 8, 10, 4, 27, 131, 220, 0, 16, 22, 10, 8, 10, 4, 27, 144, 0, 0, 16, 16, 10, 8, 10, 4, 27, 148, 0, 0, 16, 14, 10, 8, 10, 4, 27, 152, 0, 0, 16, 13, 10, 8, 10, 4, 27, 184, 0, 0, 16, 13, 10, 8, 10, 4, 27, 192, 0, 0, 16, 11, 10, 8, 10, 4, 27, 224, 0, 0, 16, 14, 10, 8, 10, 4, 36, 0, 0, 0, 16, 22, 10, 8, 10, 4, 36, 0, 8, 0, 16, 21, 10, 8, 10, 4, 36, 0, 16, 0, 16, 20, 10, 8, 10, 4, 36, 0, 32, 0, 16, 19, 10, 8, 10, 4, 36, 0, 64, 0, 16, 18, 10, 8, 10, 4, 36, 0, 128, 0, 16, 17, 10, 8, 10, 4, 36, 1, 0, 0, 16, 16, 10, 8, 10, 4, 36, 4, 0, 0, 16, 14, 10, 8, 10, 4, 36, 16, 0, 0, 16, 12, 10, 8, 10, 4, 36, 32, 0, 0, 16, 14, 10, 8, 10, 4, 36, 36, 0, 0, 16, 16, 10, 8, 10, 4, 36, 37, 0, 0, 16, 19, 10, 8, 10, 4, 36, 37, 36, 0, 16, 23, 10, 8, 10, 4, 36, 37, 39, 0, 16, 24, 10, 8, 10, 4, 36, 37, 40, 0, 16, 21, 10, 8, 10, 4, 36, 37, 48, 0, 16, 20, 10, 8, 10, 4, 36, 40, 0, 0, 16, 13, 10, 8, 10, 4, 36, 48, 0, 0, 16, 15, 10, 8, 10, 4, 36, 51, 0, 0, 16, 16, 10, 8, 10, 4, 36, 56, 0, 0, 16, 13, 10, 8, 10, 4, 36, 96, 0, 0, 16, 11, 10, 8, 10, 4, 36, 128, 0, 0, 16, 10, 10, 8, 10, 4, 36, 192, 0, 0, 16, 11, 10, 8, 10, 4, 36, 248, 0, 0, 16, 14, 10, 8, 10, 4, 36, 254, 0, 0, 16, 16, 10, 8, 10, 4, 36, 255, 116, 0, 16, 22, 10, 8, 10, 4, 36, 255, 128, 0, 16, 22, 10, 8, 10, 4, 36, 255, 164, 0, 16, 22, 10, 8, 10, 4, 36, 255, 172, 0, 16, 22, 10, 8, 10, 4, 36, 255, 176, 0, 16, 22, 10, 8, 10, 4, 36, 255, 220, 0, 16, 22, 10, 8, 10, 4, 39, 0, 0, 0, 16, 24, 10, 8, 10, 4, 39, 0, 2, 0, 16, 23, 10, 8, 10, 4, 39, 0, 4, 0, 16, 22, 10, 8, 10, 4, 39, 0, 8, 0, 16, 21, 10, 8, 10, 4, 39, 0, 16, 0, 16, 20, 10, 8, 10, 4, 39, 0, 32, 0, 16, 19, 10, 8, 10, 4, 39, 0, 64, 0, 16, 18, 10, 8, 10, 4, 39, 0, 128, 0, 16, 17, 10, 8, 10, 4, 39, 64, 0, 0, 16, 11, 10, 8, 10, 4, 39, 96, 0, 0, 16, 13, 10, 8, 10, 4, 39, 104, 0, 0, 16, 14, 10, 8, 10, 4, 39, 108, 0, 0, 16, 16, 10, 8, 10, 4, 39, 128, 0, 0, 16, 10, 10, 8, 10, 4, 40, 72, 0, 0, 16, 15, 10, 8, 10, 4, 40, 125, 128, 0, 16, 17, 10, 8, 10, 4, 40, 126, 64, 0, 16, 18, 10, 8, 10, 4, 42, 0, 0, 0, 16, 22, 10, 8, 10, 4, 42, 0, 8, 0, 16, 21, 10, 8, 10, 4, 42, 0, 16, 0, 16, 21, 10, 8, 10, 4, 42, 0, 24, 0, 16, 22, 10, 8, 10, 4, 42, 0, 32, 0, 16, 19, 10, 8, 10, 4, 42, 0, 128, 0, 16, 17, 10, 8, 10, 4, 42, 1, 0, 0, 16, 19, 10, 8, 10, 4, 42, 1, 32, 0, 16, 20, 10, 8, 10, 4, 42, 1, 48, 0, 16, 21, 10, 8, 10, 4, 42, 1, 56, 0, 16, 22, 10, 8, 10, 4, 42, 1, 128, 0, 16, 17, 10, 8, 10, 4, 42, 4, 0, 0, 16, 14, 10, 8, 10, 4, 42, 48, 0, 0, 16, 15, 10, 8, 10, 4, 42, 50, 0, 0, 16, 16, 10, 8, 10, 4, 42, 51, 0, 0, 16, 16, 10, 8, 10, 4, 42, 52, 0, 0, 16, 14, 10, 8, 10, 4, 42, 56, 0, 0, 16, 14, 10, 8, 10, 4, 42, 62, 0, 0, 16, 17, 10, 8, 10, 4, 42, 62, 128, 0, 16, 19, 10, 8, 10, 4, 42, 62, 160, 0, 16, 20, 10, 8, 10, 4, 42, 62, 180, 0, 16, 22, 10, 8, 10, 4, 42, 62, 184, 0, 16, 21, 10, 8, 10, 4, 42, 63, 0, 0, 16, 16, 10, 8, 10, 4, 42, 80, 0, 0, 16, 15, 10, 8, 10, 4, 42, 83, 64, 0, 16, 20, 10, 8, 10, 4, 42, 83, 80, 0, 16, 22, 10, 8, 10, 4, 42, 83, 88, 0, 16, 21, 10, 8, 10, 4, 42, 83, 96, 0, 16, 19, 10, 8, 10, 4, 42, 83, 128, 0, 16, 17, 10, 8, 10, 4, 42, 84, 0, 0, 16, 14, 10, 8, 10, 4, 42, 88, 0, 0, 16, 13, 10, 8, 10, 4, 42, 96, 64, 0, 16, 19, 10, 8, 10, 4, 42, 96, 96, 0, 16, 21, 10, 8, 10, 4, 42, 96, 108, 0, 16, 22, 10, 8, 10, 4, 42, 96, 112, 0, 16, 20, 10, 8, 10, 4, 42, 96, 128, 0, 16, 17, 10, 8, 10, 4, 42, 97, 0, 0, 16, 16, 10, 8, 10, 4, 42, 99, 0, 0, 16, 18, 10, 8, 10, 4, 42, 99, 64, 0, 16, 19, 10, 8, 10, 4, 42, 99, 96, 0, 16, 20, 10, 8, 10, 4, 42, 99, 112, 0, 16, 22, 10, 8, 10, 4, 42, 99, 120, 0, 16, 21, 10, 8, 10, 4, 42, 100, 0, 0, 16, 14, 10, 8, 10, 4, 42, 120, 0, 0, 16, 15, 10, 8, 10, 4, 42, 122, 0, 0, 16, 16, 10, 8, 10, 4, 42, 123, 0, 0, 16, 19, 10, 8, 10, 4, 42, 123, 36, 0, 16, 22, 10, 8, 10, 4, 42, 123, 40, 0, 16, 21, 10, 8, 10, 4, 42, 123, 48, 0, 16, 20, 10, 8, 10, 4, 42, 123, 64, 0, 16, 18, 10, 8, 10, 4, 42, 123, 128, 0, 16, 17, 10, 8, 10, 4, 42, 128, 0, 0, 16, 12, 10, 8, 10, 4, 42, 156, 0, 0, 16, 19, 10, 8, 10, 4, 42, 156, 36, 0, 16, 22, 10, 8, 10, 4, 42, 156, 40, 0, 16, 21, 10, 8, 10, 4, 42, 156, 48, 0, 16, 20, 10, 8, 10, 4, 42, 156, 64, 0, 16, 18, 10, 8, 10, 4, 42, 156, 128, 0, 16, 17, 10, 8, 10, 4, 42, 157, 0, 0, 16, 16, 10, 8, 10, 4, 42, 158, 0, 0, 16, 15, 10, 8, 10, 4, 42, 160, 0, 0, 16, 12, 10, 8, 10, 4, 42, 176, 0, 0, 16, 13, 10, 8, 10, 4, 42, 184, 0, 0, 16, 15, 10, 8, 10, 4, 42, 186, 0, 0, 16, 16, 10, 8, 10, 4, 42, 187, 0, 0, 16, 18, 10, 8, 10, 4, 42, 187, 64, 0, 16, 19, 10, 8, 10, 4, 42, 187, 96, 0, 16, 20, 10, 8, 10, 4, 42, 187, 112, 0, 16, 21, 10, 8, 10, 4, 42, 187, 120, 0, 16, 22, 10, 8, 10, 4, 42, 187, 128, 0, 16, 17, 10, 8, 10, 4, 42, 192, 0, 0, 16, 15, 10, 8, 10, 4, 42, 194, 0, 0, 16, 21, 10, 8, 10, 4, 42, 194, 8, 0, 16, 22, 10, 8, 10, 4, 42, 194, 12, 0, 16, 22, 10, 8, 10, 4, 42, 194, 16, 0, 16, 20, 10, 8, 10, 4, 42, 194, 32, 0, 16, 19, 10, 8, 10, 4, 42, 194, 64, 0, 16, 18, 10, 8, 10, 4, 42, 194, 128, 0, 16, 17, 10, 8, 10, 4, 42, 195, 0, 0, 16, 16, 10, 8, 10, 4, 42, 196, 0, 0, 16, 14, 10, 8, 10, 4, 42, 201, 0, 0, 16, 17, 10, 8, 10, 4, 42, 202, 0, 0, 16, 15, 10, 8, 10, 4, 42, 204, 0, 0, 16, 14, 10, 8, 10, 4, 42, 208, 0, 0, 16, 12, 10, 8, 10, 4, 42, 224, 0, 0, 16, 12, 10, 8, 10, 4, 42, 240, 0, 0, 16, 17, 10, 8, 10, 4, 42, 240, 128, 0, 16, 17, 10, 8, 10, 4, 42, 242, 0, 0, 16, 15, 10, 8, 10, 4, 42, 244, 0, 0, 16, 14, 10, 8, 10, 4, 42, 248, 0, 0, 16, 13, 10, 8, 10, 4, 43, 224, 12, 0, 16, 22, 10, 8, 10, 4, 43, 224, 24, 0, 16, 22, 10, 8, 10, 4, 43, 224, 44, 0, 16, 22, 10, 8, 10, 4, 43, 224, 52, 0, 16, 22, 10, 8, 10, 4, 43, 224, 56, 0, 16, 22, 10, 8, 10, 4, 43, 224, 64, 0, 16, 22, 10, 8, 10, 4, 43, 224, 68, 0, 16, 22, 10, 8, 10, 4, 43, 224, 72, 0, 16, 22, 10, 8, 10, 4, 43, 224, 80, 0, 16, 22, 10, 8, 10, 4, 43, 224, 100, 0, 16, 22, 10, 8, 10, 4, 43, 224, 144, 0, 16, 22, 10, 8, 10, 4, 43, 224, 160, 0, 16, 22, 10, 8, 10, 4, 43, 224, 176, 0, 16, 22, 10, 8, 10, 4, 43, 224, 184, 0, 16, 22, 10, 8, 10, 4, 43, 224, 200, 0, 16, 22, 10, 8, 10, 4, 43, 224, 204, 0, 16, 22, 10, 8, 10, 4, 43, 224, 208, 0, 16, 22, 10, 8, 10, 4, 43, 224, 212, 0, 16, 22, 10, 8, 10, 4, 43, 224, 216, 0, 16, 22, 10, 8, 10, 4, 43, 224, 224, 0, 16, 22, 10, 8, 10, 4, 43, 224, 240, 0, 16, 22, 10, 8, 10, 4, 43, 225, 76, 0, 16, 22, 10, 8, 10, 4, 43, 225, 84, 0, 16, 22, 10, 8, 10, 4, 43, 225, 120, 0, 16, 22, 10, 8, 10, 4, 43, 225, 124, 0, 16, 22, 10, 8, 10, 4, 43, 225, 140, 0, 16, 22, 10, 8, 10, 4, 43, 225, 172, 0, 16, 22, 10, 8, 10, 4, 43, 225, 180, 0, 16, 22, 10, 8, 10, 4, 43, 225, 208, 0, 16, 22, 10, 8, 10, 4, 43, 225, 216, 0, 16, 22, 10, 8, 10, 4, 43, 225, 220, 0, 16, 22, 10, 8, 10, 4, 43, 225, 224, 0, 16, 22, 10, 8, 10, 4, 43, 225, 228, 0, 16, 22, 10, 8, 10, 4, 43, 225, 232, 0, 16, 22, 10, 8, 10, 4, 43, 225, 236, 0, 16, 22, 10, 8, 10, 4, 43, 225, 240, 0, 16, 22, 10, 8, 10, 4, 43, 225, 244, 0, 16, 22, 10, 8, 10, 4, 43, 225, 252, 0, 16, 22, 10, 8, 10, 4, 43, 226, 32, 0, 16, 22, 10, 8, 10, 4, 43, 226, 36, 0, 16, 22, 10, 8, 10, 4, 43, 226, 40, 0, 16, 22, 10, 8, 10, 4, 43, 226, 44, 0, 16, 22, 10, 8, 10, 4, 43, 226, 48, 0, 16, 22, 10, 8, 10, 4, 43, 226, 52, 0, 16, 22, 10, 8, 10, 4, 43, 226, 56, 0, 16, 22, 10, 8, 10, 4, 43, 226, 60, 0, 16, 22, 10, 8, 10, 4, 43, 226, 64, 0, 16, 22, 10, 8, 10, 4, 43, 226, 68, 0, 16, 22, 10, 8, 10, 4, 43, 226, 72, 0, 16, 22, 10, 8, 10, 4, 43, 226, 76, 0, 16, 22, 10, 8, 10, 4, 43, 226, 80, 0, 16, 22, 10, 8, 10, 4, 43, 226, 84, 0, 16, 22, 10, 8, 10, 4, 43, 226, 88, 0, 16, 22, 10, 8, 10, 4, 43, 226, 92, 0, 16, 22, 10, 8, 10, 4, 43, 226, 96, 0, 16, 22, 10, 8, 10, 4, 43, 226, 100, 0, 16, 22, 10, 8, 10, 4, 43, 226, 104, 0, 16, 22, 10, 8, 10, 4, 43, 226, 108, 0, 16, 22, 10, 8, 10, 4, 43, 226, 112, 0, 16, 22, 10, 8, 10, 4, 43, 226, 116, 0, 16, 22, 10, 8, 10, 4, 43, 226, 120, 0, 16, 22, 10, 8, 10, 4, 43, 226, 128, 0, 16, 22, 10, 8, 10, 4, 43, 226, 132, 0, 16, 22, 10, 8, 10, 4, 43, 226, 136, 0, 16, 22, 10, 8, 10, 4, 43, 226, 140, 0, 16, 22, 10, 8, 10, 4, 43, 226, 144, 0, 16, 22, 10, 8, 10, 4, 43, 226, 148, 0, 16, 22, 10, 8, 10, 4, 43, 226, 152, 0, 16, 22, 10, 8, 10, 4, 43, 226, 156, 0, 16, 22, 10, 8, 10, 4, 43, 226, 160, 0, 16, 22, 10, 8, 10, 4, 43, 226, 164, 0, 16, 22, 10, 8, 10, 4, 43, 226, 168, 0, 16, 22, 10, 8, 10, 4, 43, 226, 172, 0, 16, 22, 10, 8, 10, 4, 43, 226, 176, 0, 16, 22, 10, 8, 10, 4, 43, 226, 180, 0, 16, 22, 10, 8, 10, 4, 43, 226, 184, 0, 16, 22, 10, 8, 10, 4, 43, 226, 188, 0, 16, 22, 10, 8, 10, 4, 43, 226, 192, 0, 16, 22, 10, 8, 10, 4, 43, 226, 196, 0, 16, 22, 10, 8, 10, 4, 43, 226, 200, 0, 16, 22, 10, 8, 10, 4, 43, 226, 204, 0, 16, 22, 10, 8, 10, 4, 43, 226, 208, 0, 16, 22, 10, 8, 10, 4, 43, 226, 212, 0, 16, 22, 10, 8, 10, 4, 43, 226, 236, 0, 16, 22, 10, 8, 10, 4, 43, 226, 240, 0, 16, 22, 10, 8, 10, 4, 43, 226, 244, 0, 16, 22, 10, 8, 10, 4, 43, 226, 248, 0, 16, 22, 10, 8, 10, 4, 43, 226, 252, 0, 16, 22, 10, 8, 10, 4, 43, 227, 0, 0, 16, 22, 10, 8, 10, 4, 43, 227, 4, 0, 16, 22, 10, 8, 10, 4, 43, 227, 8, 0, 16, 22, 10, 8, 10, 4, 43, 227, 32, 0, 16, 22, 10, 8, 10, 4, 43, 227, 36, 0, 16, 22, 10, 8, 10, 4, 43, 227, 40, 0, 16, 22, 10, 8, 10, 4, 43, 227, 44, 0, 16, 22, 10, 8, 10, 4, 43, 227, 48, 0, 16, 22, 10, 8, 10, 4, 43, 227, 52, 0, 16, 22, 10, 8, 10, 4, 43, 227, 56, 0, 16, 22, 10, 8, 10, 4, 43, 227, 60, 0, 16, 22, 10, 8, 10, 4, 43, 227, 64, 0, 16, 22, 10, 8, 10, 4, 43, 227, 68, 0, 16, 22, 10, 8, 10, 4, 43, 227, 72, 0, 16, 22, 10, 8, 10, 4, 43, 227, 76, 0, 16, 22, 10, 8, 10, 4, 43, 227, 80, 0, 16, 22, 10, 8, 10, 4, 43, 227, 84, 0, 16, 22, 10, 8, 10, 4, 43, 227, 88, 0, 16, 22, 10, 8, 10, 4, 43, 227, 92, 0, 16, 22, 10, 8, 10, 4, 43, 227, 96, 0, 16, 22, 10, 8, 10, 4, 43, 227, 100, 0, 16, 22, 10, 8, 10, 4, 43, 227, 104, 0, 16, 22, 10, 8, 10, 4, 43, 227, 136, 0, 16, 22, 10, 8, 10, 4, 43, 227, 140, 0, 16, 22, 10, 8, 10, 4, 43, 227, 144, 0, 16, 22, 10, 8, 10, 4, 43, 227, 152, 0, 16, 22, 10, 8, 10, 4, 43, 227, 156, 0, 16, 22, 10, 8, 10, 4, 43, 227, 160, 0, 16, 22, 10, 8, 10, 4, 43, 227, 164, 0, 16, 22, 10, 8, 10, 4, 43, 227, 168, 0, 16, 22, 10, 8, 10, 4, 43, 227, 172, 0, 16, 22, 10, 8, 10, 4, 43, 227, 176, 0, 16, 22, 10, 8, 10, 4, 43, 227, 180, 0, 16, 22, 10, 8, 10, 4, 43, 227, 188, 0, 16, 22, 10, 8, 10, 4, 43, 227, 192, 0, 16, 22, 10, 8, 10, 4, 43, 227, 196, 0, 16, 22, 10, 8, 10, 4, 43, 227, 200, 0, 16, 22, 10, 8, 10, 4, 43, 227, 204, 0, 16, 22, 10, 8, 10, 4, 43, 227, 208, 0, 16, 22, 10, 8, 10, 4, 43, 227, 212, 0, 16, 22, 10, 8, 10, 4, 43, 227, 216, 0, 16, 22, 10, 8, 10, 4, 43, 227, 220, 0, 16, 22, 10, 8, 10, 4, 43, 227, 232, 0, 16, 22, 10, 8, 10, 4, 43, 227, 248, 0, 16, 22, 10, 8, 10, 4, 43, 227, 252, 0, 16, 22, 10, 8, 10, 4, 43, 228, 0, 0, 16, 22, 10, 8, 10, 4, 43, 228, 4, 0, 16, 22, 10, 8, 10, 4, 43, 228, 8, 0, 16, 22, 10, 8, 10, 4, 43, 228, 12, 0, 16, 22, 10, 8, 10, 4, 43, 228, 16, 0, 16, 22, 10, 8, 10, 4, 43, 228, 20, 0, 16, 22, 10, 8, 10, 4, 43, 228, 24, 0, 16, 22, 10, 8, 10, 4, 43, 228, 28, 0, 16, 22, 10, 8, 10, 4, 43, 228, 32, 0, 16, 22, 10, 8, 10, 4, 43, 228, 36, 0, 16, 22, 10, 8, 10, 4, 43, 228, 40, 0, 16, 22, 10, 8, 10, 4, 43, 228, 44, 0, 16, 22, 10, 8, 10, 4, 43, 228, 48, 0, 16, 22, 10, 8, 10, 4, 43, 228, 52, 0, 16, 22, 10, 8, 10, 4, 43, 228, 56, 0, 16, 22, 10, 8, 10, 4, 43, 228, 60, 0, 16, 22, 10, 8, 10, 4, 43, 228, 64, 0, 16, 22, 10, 8, 10, 4, 43, 228, 68, 0, 16, 22, 10, 8, 10, 4, 43, 228, 76, 0, 16, 22, 10, 8, 10, 4, 43, 228, 100, 0, 16, 22, 10, 8, 10, 4, 43, 228, 116, 0, 16, 22, 10, 8, 10, 4, 43, 228, 120, 0, 16, 22, 10, 8, 10, 4, 43, 228, 132, 0, 16, 22, 10, 8, 10, 4, 43, 228, 136, 0, 16, 22, 10, 8, 10, 4, 43, 228, 148, 0, 16, 22, 10, 8, 10, 4, 43, 228, 152, 0, 16, 22, 10, 8, 10, 4, 43, 228, 188, 0, 16, 22, 10, 8, 10, 4, 43, 229, 16, 0, 16, 22, 10, 8, 10, 4, 43, 229, 40, 0, 16, 22, 10, 8, 10, 4, 43, 229, 48, 0, 16, 22, 10, 8, 10, 4, 43, 229, 56, 0, 16, 22, 10, 8, 10, 4, 43, 229, 96, 0, 16, 22, 10, 8, 10, 4, 43, 229, 120, 0, 16, 22, 10, 8, 10, 4, 43, 229, 136, 0, 16, 22, 10, 8, 10, 4, 43, 229, 140, 0, 16, 22, 10, 8, 10, 4, 43, 229, 144, 0, 16, 22, 10, 8, 10, 4, 43, 229, 168, 0, 16, 22, 10, 8, 10, 4, 43, 229, 172, 0, 16, 22, 10, 8, 10, 4, 43, 229, 176, 0, 16, 22, 10, 8, 10, 4, 43, 229, 180, 0, 16, 22, 10, 8, 10, 4, 43, 229, 184, 0, 16, 22, 10, 8, 10, 4, 43, 229, 188, 0, 16, 22, 10, 8, 10, 4, 43, 229, 192, 0, 16, 22, 10, 8, 10, 4, 43, 229, 196, 0, 16, 22, 10, 8, 10, 4, 43, 229, 216, 0, 16, 22, 10, 8, 10, 4, 43, 229, 220, 0, 16, 22, 10, 8, 10, 4, 43, 229, 232, 0, 16, 22, 10, 8, 10, 4, 43, 229, 236, 0, 16, 22, 10, 8, 10, 4, 43, 230, 20, 0, 16, 22, 10, 8, 10, 4, 43, 230, 32, 0, 16, 22, 10, 8, 10, 4, 43, 230, 68, 0, 16, 22, 10, 8, 10, 4, 43, 230, 72, 0, 16, 22, 10, 8, 10, 4, 43, 230, 84, 0, 16, 22, 10, 8, 10, 4, 43, 230, 124, 0, 16, 22, 10, 8, 10, 4, 43, 230, 136, 0, 16, 22, 10, 8, 10, 4, 43, 230, 168, 0, 16, 22, 10, 8, 10, 4, 43, 230, 220, 0, 16, 22, 10, 8, 10, 4, 43, 230, 224, 0, 16, 22, 10, 8, 10, 4, 43, 230, 228, 0, 16, 22, 10, 8, 10, 4, 43, 230, 232, 0, 16, 22, 10, 8, 10, 4, 43, 230, 236, 0, 16, 22, 10, 8, 10, 4, 43, 230, 240, 0, 16, 22, 10, 8, 10, 4, 43, 230, 244, 0, 16, 22, 10, 8, 10, 4, 43, 230, 248, 0, 16, 22, 10, 8, 10, 4, 43, 230, 252, 0, 16, 22, 10, 8, 10, 4, 43, 231, 32, 0, 16, 22, 10, 8, 10, 4, 43, 231, 36, 0, 16, 22, 10, 8, 10, 4, 43, 231, 40, 0, 16, 22, 10, 8, 10, 4, 43, 231, 44, 0, 16, 22, 10, 8, 10, 4, 43, 231, 80, 0, 16, 22, 10, 8, 10, 4, 43, 231, 84, 0, 16, 22, 10, 8, 10, 4, 43, 231, 88, 0, 16, 22, 10, 8, 10, 4, 43, 231, 92, 0, 16, 22, 10, 8, 10, 4, 43, 231, 96, 0, 16, 22, 10, 8, 10, 4, 43, 231, 100, 0, 16, 22, 10, 8, 10, 4, 43, 231, 104, 0, 16, 22, 10, 8, 10, 4, 43, 231, 108, 0, 16, 22, 10, 8, 10, 4, 43, 231, 136, 0, 16, 22, 10, 8, 10, 4, 43, 231, 140, 0, 16, 22, 10, 8, 10, 4, 43, 231, 144, 0, 16, 22, 10, 8, 10, 4, 43, 231, 148, 0, 16, 22, 10, 8, 10, 4, 43, 231, 152, 0, 16, 22, 10, 8, 10, 4, 43, 231, 156, 0, 16, 22, 10, 8, 10, 4, 43, 231, 160, 0, 16, 22, 10, 8, 10, 4, 43, 231, 164, 0, 16, 22, 10, 8, 10, 4, 43, 231, 168, 0, 16, 22, 10, 8, 10, 4, 43, 231, 172, 0, 16, 22, 10, 8, 10, 4, 43, 231, 176, 0, 16, 22, 10, 8, 10, 4, 43, 231, 180, 0, 16, 22, 10, 8, 10, 4, 43, 236, 0, 0, 16, 22, 10, 8, 10, 4, 43, 236, 4, 0, 16, 22, 10, 8, 10, 4, 43, 236, 8, 0, 16, 22, 10, 8, 10, 4, 43, 236, 12, 0, 16, 22, 10, 8, 10, 4, 43, 236, 16, 0, 16, 22, 10, 8, 10, 4, 43, 236, 20, 0, 16, 22, 10, 8, 10, 4, 43, 236, 24, 0, 16, 22, 10, 8, 10, 4, 43, 236, 28, 0, 16, 22, 10, 8, 10, 4, 43, 236, 32, 0, 16, 22, 10, 8, 10, 4, 43, 236, 36, 0, 16, 22, 10, 8, 10, 4, 43, 236, 40, 0, 16, 22, 10, 8, 10, 4, 43, 236, 44, 0, 16, 22, 10, 8, 10, 4, 43, 236, 48, 0, 16, 22, 10, 8, 10, 4, 43, 236, 52, 0, 16, 22, 10, 8, 10, 4, 43, 236, 56, 0, 16, 22, 10, 8, 10, 4, 43, 236, 60, 0, 16, 22, 10, 8, 10, 4, 43, 236, 64, 0, 16, 22, 10, 8, 10, 4, 43, 236, 68, 0, 16, 22, 10, 8, 10, 4, 43, 236, 72, 0, 16, 22, 10, 8, 10, 4, 43, 236, 76, 0, 16, 22, 10, 8, 10, 4, 43, 236, 80, 0, 16, 22, 10, 8, 10, 4, 43, 236, 84, 0, 16, 22, 10, 8, 10, 4, 43, 236, 88, 0, 16, 22, 10, 8, 10, 4, 43, 236, 92, 0, 16, 22, 10, 8, 10, 4, 43, 236, 96, 0, 16, 22, 10, 8, 10, 4, 43, 236, 100, 0, 16, 22, 10, 8, 10, 4, 43, 236, 104, 0, 16, 22, 10, 8, 10, 4, 43, 236, 108, 0, 16, 22, 10, 8, 10, 4, 43, 236, 112, 0, 16, 22, 10, 8, 10, 4, 43, 236, 116, 0, 16, 22, 10, 8, 10, 4, 43, 236, 120, 0, 16, 22, 10, 8, 10, 4, 43, 236, 124, 0, 16, 22, 10, 8, 10, 4, 43, 236, 128, 0, 16, 22, 10, 8, 10, 4, 43, 236, 132, 0, 16, 22, 10, 8, 10, 4, 43, 236, 136, 0, 16, 22, 10, 8, 10, 4, 43, 236, 140, 0, 16, 22, 10, 8, 10, 4, 43, 236, 144, 0, 16, 22, 10, 8, 10, 4, 43, 236, 148, 0, 16, 22, 10, 8, 10, 4, 43, 236, 152, 0, 16, 22, 10, 8, 10, 4, 43, 236, 156, 0, 16, 22, 10, 8, 10, 4, 43, 236, 160, 0, 16, 22, 10, 8, 10, 4, 43, 236, 164, 0, 16, 22, 10, 8, 10, 4, 43, 236, 168, 0, 16, 22, 10, 8, 10, 4, 43, 236, 172, 0, 16, 22, 10, 8, 10, 4, 43, 236, 176, 0, 16, 22, 10, 8, 10, 4, 43, 236, 180, 0, 16, 22, 10, 8, 10, 4, 43, 236, 184, 0, 16, 22, 10, 8, 10, 4, 43, 236, 188, 0, 16, 22, 10, 8, 10, 4, 43, 236, 192, 0, 16, 22, 10, 8, 10, 4, 43, 236, 196, 0, 16, 22, 10, 8, 10, 4, 43, 236, 200, 0, 16, 22, 10, 8, 10, 4, 43, 236, 204, 0, 16, 22, 10, 8, 10, 4, 43, 236, 208, 0, 16, 22, 10, 8, 10, 4, 43, 236, 212, 0, 16, 22, 10, 8, 10, 4, 43, 236, 216, 0, 16, 22, 10, 8, 10, 4, 43, 236, 220, 0, 16, 22, 10, 8, 10, 4, 43, 236, 224, 0, 16, 22, 10, 8, 10, 4, 43, 236, 228, 0, 16, 22, 10, 8, 10, 4, 43, 236, 232, 0, 16, 22, 10, 8, 10, 4, 43, 236, 236, 0, 16, 22, 10, 8, 10, 4, 43, 236, 240, 0, 16, 22, 10, 8, 10, 4, 43, 236, 244, 0, 16, 22, 10, 8, 10, 4, 43, 236, 248, 0, 16, 22, 10, 8, 10, 4, 43, 236, 252, 0, 16, 22, 10, 8, 10, 4, 43, 237, 0, 0, 16, 22, 10, 8, 10, 4, 43, 237, 4, 0, 16, 22, 10, 8, 10, 4, 43, 237, 8, 0, 16, 22, 10, 8, 10, 4, 43, 237, 12, 0, 16, 22, 10, 8, 10, 4, 43, 237, 16, 0, 16, 22, 10, 8, 10, 4, 43, 237, 20, 0, 16, 22, 10, 8, 10, 4, 43, 237, 24, 0, 16, 22, 10, 8, 10, 4, 43, 237, 28, 0, 16, 22, 10, 8, 10, 4, 43, 237, 32, 0, 16, 22, 10, 8, 10, 4, 43, 237, 36, 0, 16, 22, 10, 8, 10, 4, 43, 237, 40, 0, 16, 22, 10, 8, 10, 4, 43, 237, 44, 0, 16, 22, 10, 8, 10, 4, 43, 237, 48, 0, 16, 22, 10, 8, 10, 4, 43, 237, 52, 0, 16, 22, 10, 8, 10, 4, 43, 237, 56, 0, 16, 22, 10, 8, 10, 4, 43, 237, 60, 0, 16, 22, 10, 8, 10, 4, 43, 237, 64, 0, 16, 22, 10, 8, 10, 4, 43, 237, 68, 0, 16, 22, 10, 8, 10, 4, 43, 237, 72, 0, 16, 22, 10, 8, 10, 4, 43, 237, 76, 0, 16, 22, 10, 8, 10, 4, 43, 237, 80, 0, 16, 22, 10, 8, 10, 4, 43, 237, 84, 0, 16, 22, 10, 8, 10, 4, 43, 237, 88, 0, 16, 22, 10, 8, 10, 4, 43, 237, 92, 0, 16, 22, 10, 8, 10, 4, 43, 237, 96, 0, 16, 22, 10, 8, 10, 4, 43, 237, 100, 0, 16, 22, 10, 8, 10, 4, 43, 237, 104, 0, 16, 22, 10, 8, 10, 4, 43, 237, 108, 0, 16, 22, 10, 8, 10, 4, 43, 237, 112, 0, 16, 22, 10, 8, 10, 4, 43, 237, 116, 0, 16, 22, 10, 8, 10, 4, 43, 237, 120, 0, 16, 22, 10, 8, 10, 4, 43, 237, 124, 0, 16, 22, 10, 8, 10, 4, 43, 237, 128, 0, 16, 22, 10, 8, 10, 4, 43, 237, 132, 0, 16, 22, 10, 8, 10, 4, 43, 237, 136, 0, 16, 22, 10, 8, 10, 4, 43, 237, 140, 0, 16, 22, 10, 8, 10, 4, 43, 237, 144, 0, 16, 22, 10, 8, 10, 4, 43, 237, 148, 0, 16, 22, 10, 8, 10, 4, 43, 237, 152, 0, 16, 22, 10, 8, 10, 4, 43, 237, 156, 0, 16, 22, 10, 8, 10, 4, 43, 237, 160, 0, 16, 22, 10, 8, 10, 4, 43, 237, 164, 0, 16, 22, 10, 8, 10, 4, 43, 237, 168, 0, 16, 22, 10, 8, 10, 4, 43, 237, 172, 0, 16, 22, 10, 8, 10, 4, 43, 237, 176, 0, 16, 22, 10, 8, 10, 4, 43, 237, 180, 0, 16, 22, 10, 8, 10, 4, 43, 237, 184, 0, 16, 22, 10, 8, 10, 4, 43, 237, 188, 0, 16, 22, 10, 8, 10, 4, 43, 237, 192, 0, 16, 22, 10, 8, 10, 4, 43, 237, 196, 0, 16, 22, 10, 8, 10, 4, 43, 237, 200, 0, 16, 22, 10, 8, 10, 4, 43, 237, 204, 0, 16, 22, 10, 8, 10, 4, 43, 237, 208, 0, 16, 22, 10, 8, 10, 4, 43, 237, 212, 0, 16, 22, 10, 8, 10, 4, 43, 237, 216, 0, 16, 22, 10, 8, 10, 4, 43, 237, 220, 0, 16, 22, 10, 8, 10, 4, 43, 237, 224, 0, 16, 22, 10, 8, 10, 4, 43, 237, 228, 0, 16, 22, 10, 8, 10, 4, 43, 237, 232, 0, 16, 22, 10, 8, 10, 4, 43, 237, 236, 0, 16, 22, 10, 8, 10, 4, 43, 237, 240, 0, 16, 22, 10, 8, 10, 4, 43, 237, 244, 0, 16, 22, 10, 8, 10, 4, 43, 237, 248, 0, 16, 22, 10, 8, 10, 4, 43, 237, 252, 0, 16, 22, 10, 8, 10, 4, 43, 238, 0, 0, 16, 22, 10, 8, 10, 4, 43, 238, 4, 0, 16, 22, 10, 8, 10, 4, 43, 238, 8, 0, 16, 22, 10, 8, 10, 4, 43, 238, 12, 0, 16, 22, 10, 8, 10, 4, 43, 238, 16, 0, 16, 22, 10, 8, 10, 4, 43, 238, 20, 0, 16, 22, 10, 8, 10, 4, 43, 238, 24, 0, 16, 22, 10, 8, 10, 4, 43, 238, 28, 0, 16, 22, 10, 8, 10, 4, 43, 238, 32, 0, 16, 22, 10, 8, 10, 4, 43, 238, 36, 0, 16, 22, 10, 8, 10, 4, 43, 238, 40, 0, 16, 22, 10, 8, 10, 4, 43, 238, 44, 0, 16, 22, 10, 8, 10, 4, 43, 238, 48, 0, 16, 22, 10, 8, 10, 4, 43, 238, 52, 0, 16, 22, 10, 8, 10, 4, 43, 238, 56, 0, 16, 22, 10, 8, 10, 4, 43, 238, 60, 0, 16, 22, 10, 8, 10, 4, 43, 238, 64, 0, 16, 22, 10, 8, 10, 4, 43, 238, 68, 0, 16, 22, 10, 8, 10, 4, 43, 238, 72, 0, 16, 22, 10, 8, 10, 4, 43, 238, 76, 0, 16, 22, 10, 8, 10, 4, 43, 238, 80, 0, 16, 22, 10, 8, 10, 4, 43, 238, 84, 0, 16, 22, 10, 8, 10, 4, 43, 238, 88, 0, 16, 22, 10, 8, 10, 4, 43, 238, 92, 0, 16, 22, 10, 8, 10, 4, 43, 238, 96, 0, 16, 22, 10, 8, 10, 4, 43, 238, 100, 0, 16, 22, 10, 8, 10, 4, 43, 238, 104, 0, 16, 22, 10, 8, 10, 4, 43, 238, 108, 0, 16, 22, 10, 8, 10, 4, 43, 238, 112, 0, 16, 22, 10, 8, 10, 4, 43, 238, 116, 0, 16, 22, 10, 8, 10, 4, 43, 238, 120, 0, 16, 22, 10, 8, 10, 4, 43, 238, 124, 0, 16, 22, 10, 8, 10, 4, 43, 238, 128, 0, 16, 22, 10, 8, 10, 4, 43, 238, 132, 0, 16, 22, 10, 8, 10, 4, 43, 238, 136, 0, 16, 22, 10, 8, 10, 4, 43, 238, 140, 0, 16, 22, 10, 8, 10, 4, 43, 238, 144, 0, 16, 22, 10, 8, 10, 4, 43, 238, 148, 0, 16, 22, 10, 8, 10, 4, 43, 238, 152, 0, 16, 22, 10, 8, 10, 4, 43, 238, 156, 0, 16, 22, 10, 8, 10, 4, 43, 238, 160, 0, 16, 22, 10, 8, 10, 4, 43, 238, 164, 0, 16, 22, 10, 8, 10, 4, 43, 238, 168, 0, 16, 22, 10, 8, 10, 4, 43, 238, 172, 0, 16, 22, 10, 8, 10, 4, 43, 238, 176, 0, 16, 22, 10, 8, 10, 4, 43, 238, 180, 0, 16, 22, 10, 8, 10, 4, 43, 238, 184, 0, 16, 22, 10, 8, 10, 4, 43, 238, 188, 0, 16, 22, 10, 8, 10, 4, 43, 238, 192, 0, 16, 22, 10, 8, 10, 4, 43, 238, 196, 0, 16, 22, 10, 8, 10, 4, 43, 238, 200, 0, 16, 22, 10, 8, 10, 4, 43, 238, 204, 0, 16, 22, 10, 8, 10, 4, 43, 238, 208, 0, 16, 22, 10, 8, 10, 4, 43, 238, 212, 0, 16, 22, 10, 8, 10, 4, 43, 238, 216, 0, 16, 22, 10, 8, 10, 4, 43, 238, 220, 0, 16, 22, 10, 8, 10, 4, 43, 238, 224, 0, 16, 22, 10, 8, 10, 4, 43, 238, 228, 0, 16, 22, 10, 8, 10, 4, 43, 238, 232, 0, 16, 22, 10, 8, 10, 4, 43, 238, 236, 0, 16, 22, 10, 8, 10, 4, 43, 238, 240, 0, 16, 22, 10, 8, 10, 4, 43, 238, 244, 0, 16, 22, 10, 8, 10, 4, 43, 238, 248, 0, 16, 22, 10, 8, 10, 4, 43, 238, 252, 0, 16, 22, 10, 8, 10, 4, 43, 239, 0, 0, 16, 22, 10, 8, 10, 4, 43, 239, 4, 0, 16, 22, 10, 8, 10, 4, 43, 239, 8, 0, 16, 21, 10, 8, 10, 4, 43, 239, 16, 0, 16, 22, 10, 8, 10, 4, 43, 239, 20, 0, 16, 22, 10, 8, 10, 4, 43, 239, 24, 0, 16, 22, 10, 8, 10, 4, 43, 239, 28, 0, 16, 22, 10, 8, 10, 4, 43, 239, 32, 0, 16, 22, 10, 8, 10, 4, 43, 239, 36, 0, 16, 22, 10, 8, 10, 4, 43, 239, 40, 0, 16, 22, 10, 8, 10, 4, 43, 239, 44, 0, 16, 22, 10, 8, 10, 4, 43, 239, 48, 0, 16, 22, 10, 8, 10, 4, 43, 239, 116, 0, 16, 22, 10, 8, 10, 4, 43, 239, 120, 0, 16, 22, 10, 8, 10, 4, 43, 239, 172, 0, 16, 22, 10, 8, 10, 4, 43, 239, 176, 0, 16, 22, 10, 8, 10, 4, 43, 240, 0, 0, 16, 22, 10, 8, 10, 4, 43, 240, 48, 0, 16, 22, 10, 8, 10, 4, 43, 240, 56, 0, 16, 22, 10, 8, 10, 4, 43, 240, 60, 0, 16, 22, 10, 8, 10, 4, 43, 240, 68, 0, 16, 22, 10, 8, 10, 4, 43, 240, 72, 0, 16, 22, 10, 8, 10, 4, 43, 240, 76, 0, 16, 22, 10, 8, 10, 4, 43, 240, 84, 0, 16, 22, 10, 8, 10, 4, 43, 240, 124, 0, 16, 22, 10, 8, 10, 4, 43, 240, 128, 0, 16, 22, 10, 8, 10, 4, 43, 240, 132, 0, 16, 22, 10, 8, 10, 4, 43, 240, 136, 0, 16, 22, 10, 8, 10, 4, 43, 240, 156, 0, 16, 22, 10, 8, 10, 4, 43, 240, 160, 0, 16, 22, 10, 8, 10, 4, 43, 240, 164, 0, 16, 22, 10, 8, 10, 4, 43, 240, 168, 0, 16, 22, 10, 8, 10, 4, 43, 240, 172, 0, 16, 22, 10, 8, 10, 4, 43, 240, 176, 0, 16, 22, 10, 8, 10, 4, 43, 240, 180, 0, 16, 22, 10, 8, 10, 4, 43, 240, 184, 0, 16, 22, 10, 8, 10, 4, 43, 240, 188, 0, 16, 22, 10, 8, 10, 4, 43, 240, 192, 0, 16, 22, 10, 8, 10, 4, 43, 240, 196, 0, 16, 22, 10, 8, 10, 4, 43, 240, 200, 0, 16, 22, 10, 8, 10, 4, 43, 240, 204, 0, 16, 22, 10, 8, 10, 4, 43, 240, 208, 0, 16, 22, 10, 8, 10, 4, 43, 240, 212, 0, 16, 22, 10, 8, 10, 4, 43, 240, 216, 0, 16, 22, 10, 8, 10, 4, 43, 240, 220, 0, 16, 22, 10, 8, 10, 4, 43, 240, 236, 0, 16, 22, 10, 8, 10, 4, 43, 240, 240, 0, 16, 22, 10, 8, 10, 4, 43, 240, 244, 0, 16, 22, 10, 8, 10, 4, 43, 240, 248, 0, 16, 22, 10, 8, 10, 4, 43, 240, 252, 0, 16, 22, 10, 8, 10, 4, 43, 241, 0, 0, 16, 22, 10, 8, 10, 4, 43, 241, 4, 0, 16, 22, 10, 8, 10, 4, 43, 241, 8, 0, 16, 22, 10, 8, 10, 4, 43, 241, 12, 0, 16, 22, 10, 8, 10, 4, 43, 241, 16, 0, 16, 22, 10, 8, 10, 4, 43, 241, 20, 0, 16, 22, 10, 8, 10, 4, 43, 241, 48, 0, 16, 22, 10, 8, 10, 4, 43, 241, 76, 0, 16, 22, 10, 8, 10, 4, 43, 241, 80, 0, 16, 22, 10, 8, 10, 4, 43, 241, 84, 0, 16, 22, 10, 8, 10, 4, 43, 241, 88, 0, 16, 22, 10, 8, 10, 4, 43, 241, 92, 0, 16, 22, 10, 8, 10, 4, 43, 241, 112, 0, 16, 22, 10, 8, 10, 4, 43, 241, 168, 0, 16, 22, 10, 8, 10, 4, 43, 241, 172, 0, 16, 22, 10, 8, 10, 4, 43, 241, 176, 0, 16, 22, 10, 8, 10, 4, 43, 241, 180, 0, 16, 22, 10, 8, 10, 4, 43, 241, 184, 0, 16, 22, 10, 8, 10, 4, 43, 241, 196, 0, 16, 22, 10, 8, 10, 4, 43, 241, 208, 0, 16, 22, 10, 8, 10, 4, 43, 241, 212, 0, 16, 22, 10, 8, 10, 4, 43, 241, 216, 0, 16, 22, 10, 8, 10, 4, 43, 241, 220, 0, 16, 22, 10, 8, 10, 4, 43, 241, 224, 0, 16, 22, 10, 8, 10, 4, 43, 241, 228, 0, 16, 22, 10, 8, 10, 4, 43, 241, 232, 0, 16, 22, 10, 8, 10, 4, 43, 241, 236, 0, 16, 22, 10, 8, 10, 4, 43, 241, 240, 0, 16, 22, 10, 8, 10, 4, 43, 241, 248, 0, 16, 22, 10, 8, 10, 4, 43, 241, 252, 0, 16, 22, 10, 8, 10, 4, 43, 242, 8, 0, 16, 22, 10, 8, 10, 4, 43, 242, 12, 0, 16, 22, 10, 8, 10, 4, 43, 242, 16, 0, 16, 22, 10, 8, 10, 4, 43, 242, 20, 0, 16, 22, 10, 8, 10, 4, 43, 242, 24, 0, 16, 22, 10, 8, 10, 4, 43, 242, 28, 0, 16, 22, 10, 8, 10, 4, 43, 242, 44, 0, 16, 22, 10, 8, 10, 4, 43, 242, 48, 0, 16, 22, 10, 8, 10, 4, 43, 242, 52, 0, 16, 22, 10, 8, 10, 4, 43, 242, 56, 0, 16, 22, 10, 8, 10, 4, 43, 242, 60, 0, 16, 22, 10, 8, 10, 4, 43, 242, 64, 0, 16, 22, 10, 8, 10, 4, 43, 242, 72, 0, 16, 22, 10, 8, 10, 4, 43, 242, 76, 0, 16, 22, 10, 8, 10, 4, 43, 242, 80, 0, 16, 22, 10, 8, 10, 4, 43, 242, 84, 0, 16, 22, 10, 8, 10, 4, 43, 242, 88, 0, 16, 22, 10, 8, 10, 4, 43, 242, 92, 0, 16, 22, 10, 8, 10, 4, 43, 242, 96, 0, 16, 22, 10, 8, 10, 4, 43, 242, 144, 0, 16, 22, 10, 8, 10, 4, 43, 242, 148, 0, 16, 22, 10, 8, 10, 4, 43, 242, 152, 0, 16, 22, 10, 8, 10, 4, 43, 242, 156, 0, 16, 22, 10, 8, 10, 4, 43, 242, 160, 0, 16, 22, 10, 8, 10, 4, 43, 242, 164, 0, 16, 22, 10, 8, 10, 4, 43, 242, 168, 0, 16, 22, 10, 8, 10, 4, 43, 242, 180, 0, 16, 22, 10, 8, 10, 4, 43, 242, 188, 0, 16, 22, 10, 8, 10, 4, 43, 242, 192, 0, 16, 22, 10, 8, 10, 4, 43, 242, 196, 0, 16, 22, 10, 8, 10, 4, 43, 242, 204, 0, 16, 22, 10, 8, 10, 4, 43, 242, 216, 0, 16, 22, 10, 8, 10, 4, 43, 242, 220, 0, 16, 22, 10, 8, 10, 4, 43, 242, 252, 0, 16, 22, 10, 8, 10, 4, 43, 243, 4, 0, 16, 22, 10, 8, 10, 4, 43, 243, 8, 0, 16, 22, 10, 8, 10, 4, 43, 243, 12, 0, 16, 22, 10, 8, 10, 4, 43, 243, 16, 0, 16, 22, 10, 8, 10, 4, 43, 243, 24, 0, 16, 22, 10, 8, 10, 4, 43, 243, 88, 0, 16, 22, 10, 8, 10, 4, 43, 243, 128, 0, 16, 22, 10, 8, 10, 4, 43, 243, 136, 0, 16, 22, 10, 8, 10, 4, 43, 243, 144, 0, 16, 22, 10, 8, 10, 4, 43, 243, 148, 0, 16, 22, 10, 8, 10, 4, 43, 243, 156, 0, 16, 22, 10, 8, 10, 4, 43, 243, 168, 0, 16, 22, 10, 8, 10, 4, 43, 243, 180, 0, 16, 22, 10, 8, 10, 4, 43, 243, 188, 0, 16, 22, 10, 8, 10, 4, 43, 243, 228, 0, 16, 22, 10, 8, 10, 4, 43, 243, 232, 0, 16, 22, 10, 8, 10, 4, 43, 243, 244, 0, 16, 22, 10, 8, 10, 4, 43, 246, 0, 0, 16, 22, 10, 8, 10, 4, 43, 246, 4, 0, 16, 22, 10, 8, 10, 4, 43, 246, 8, 0, 16, 22, 10, 8, 10, 4, 43, 246, 12, 0, 16, 22, 10, 8, 10, 4, 43, 246, 16, 0, 16, 22, 10, 8, 10, 4, 43, 246, 20, 0, 16, 22, 10, 8, 10, 4, 43, 246, 24, 0, 16, 22, 10, 8, 10, 4, 43, 246, 28, 0, 16, 22, 10, 8, 10, 4, 43, 246, 32, 0, 16, 22, 10, 8, 10, 4, 43, 246, 36, 0, 16, 22, 10, 8, 10, 4, 43, 246, 40, 0, 16, 22, 10, 8, 10, 4, 43, 246, 44, 0, 16, 22, 10, 8, 10, 4, 43, 246, 48, 0, 16, 22, 10, 8, 10, 4, 43, 246, 52, 0, 16, 22, 10, 8, 10, 4, 43, 246, 56, 0, 16, 22, 10, 8, 10, 4, 43, 246, 60, 0, 16, 22, 10, 8, 10, 4, 43, 246, 64, 0, 16, 22, 10, 8, 10, 4, 43, 246, 68, 0, 16, 22, 10, 8, 10, 4, 43, 246, 72, 0, 16, 22, 10, 8, 10, 4, 43, 246, 76, 0, 16, 22, 10, 8, 10, 4, 43, 246, 80, 0, 16, 22, 10, 8, 10, 4, 43, 246, 84, 0, 16, 22, 10, 8, 10, 4, 43, 246, 88, 0, 16, 22, 10, 8, 10, 4, 43, 246, 92, 0, 16, 22, 10, 8, 10, 4, 43, 246, 96, 0, 16, 22, 10, 8, 10, 4, 43, 246, 112, 0, 16, 22, 10, 8, 10, 4, 43, 246, 212, 0, 16, 22, 10, 8, 10, 4, 43, 246, 228, 0, 16, 22, 10, 8, 10, 4, 43, 247, 4, 0, 16, 22, 10, 8, 10, 4, 43, 247, 8, 0, 16, 22, 10, 8, 10, 4, 43, 247, 44, 0, 16, 22, 10, 8, 10, 4, 43, 247, 48, 0, 16, 22, 10, 8, 10, 4, 43, 247, 68, 0, 16, 22, 10, 8, 10, 4, 43, 247, 76, 0, 16, 22, 10, 8, 10, 4, 43, 247, 84, 0, 16, 22, 10, 8, 10, 4, 43, 247, 88, 0, 16, 22, 10, 8, 10, 4, 43, 247, 92, 0, 16, 22, 10, 8, 10, 4, 43, 247, 96, 0, 16, 22, 10, 8, 10, 4, 43, 247, 100, 0, 16, 22, 10, 8, 10, 4, 43, 247, 108, 0, 16, 22, 10, 8, 10, 4, 43, 247, 112, 0, 16, 22, 10, 8, 10, 4, 43, 247, 148, 0, 16, 22, 10, 8, 10, 4, 43, 247, 152, 0, 16, 22, 10, 8, 10, 4, 43, 247, 176, 0, 16, 22, 10, 8, 10, 4, 43, 247, 180, 0, 16, 22, 10, 8, 10, 4, 43, 247, 184, 0, 16, 22, 10, 8, 10, 4, 43, 247, 188, 0, 16, 22, 10, 8, 10, 4, 43, 247, 196, 0, 16, 22, 10, 8, 10, 4, 43, 247, 200, 0, 16, 22, 10, 8, 10, 4, 43, 247, 204, 0, 16, 22, 10, 8, 10, 4, 43, 247, 208, 0, 16, 22, 10, 8, 10, 4, 43, 247, 212, 0, 16, 22, 10, 8, 10, 4, 43, 247, 216, 0, 16, 22, 10, 8, 10, 4, 43, 247, 220, 0, 16, 22, 10, 8, 10, 4, 43, 247, 224, 0, 16, 22, 10, 8, 10, 4, 43, 247, 228, 0, 16, 22, 10, 8, 10, 4, 43, 247, 232, 0, 16, 22, 10, 8, 10, 4, 43, 247, 236, 0, 16, 22, 10, 8, 10, 4, 43, 247, 240, 0, 16, 22, 10, 8, 10, 4, 43, 247, 244, 0, 16, 22, 10, 8, 10, 4, 43, 247, 248, 0, 16, 22, 10, 8, 10, 4, 43, 247, 252, 0, 16, 22, 10, 8, 10, 4, 43, 248, 0, 0, 16, 22, 10, 8, 10, 4, 43, 248, 4, 0, 16, 22, 10, 8, 10, 4, 43, 248, 20, 0, 16, 22, 10, 8, 10, 4, 43, 248, 28, 0, 16, 22, 10, 8, 10, 4, 43, 248, 48, 0, 16, 22, 10, 8, 10, 4, 43, 248, 76, 0, 16, 22, 10, 8, 10, 4, 43, 248, 80, 0, 16, 22, 10, 8, 10, 4, 43, 248, 84, 0, 16, 22, 10, 8, 10, 4, 43, 248, 88, 0, 16, 22, 10, 8, 10, 4, 43, 248, 92, 0, 16, 22, 10, 8, 10, 4, 43, 248, 96, 0, 16, 22, 10, 8, 10, 4, 43, 248, 100, 0, 16, 22, 10, 8, 10, 4, 43, 248, 104, 0, 16, 22, 10, 8, 10, 4, 43, 248, 108, 0, 16, 22, 10, 8, 10, 4, 43, 248, 112, 0, 16, 22, 10, 8, 10, 4, 43, 248, 116, 0, 16, 22, 10, 8, 10, 4, 43, 248, 120, 0, 16, 22, 10, 8, 10, 4, 43, 248, 124, 0, 16, 22, 10, 8, 10, 4, 43, 248, 128, 0, 16, 22, 10, 8, 10, 4, 43, 248, 132, 0, 16, 22, 10, 8, 10, 4, 43, 248, 136, 0, 16, 22, 10, 8, 10, 4, 43, 248, 140, 0, 16, 22, 10, 8, 10, 4, 43, 248, 144, 0, 16, 22, 10, 8, 10, 4, 43, 248, 148, 0, 16, 22, 10, 8, 10, 4, 43, 248, 176, 0, 16, 22, 10, 8, 10, 4, 43, 248, 180, 0, 16, 22, 10, 8, 10, 4, 43, 248, 184, 0, 16, 22, 10, 8, 10, 4, 43, 248, 188, 0, 16, 22, 10, 8, 10, 4, 43, 248, 192, 0, 16, 22, 10, 8, 10, 4, 43, 248, 196, 0, 16, 22, 10, 8, 10, 4, 43, 248, 200, 0, 16, 22, 10, 8, 10, 4, 43, 248, 204, 0, 16, 22, 10, 8, 10, 4, 43, 248, 208, 0, 16, 22, 10, 8, 10, 4, 43, 248, 228, 0, 16, 22, 10, 8, 10, 4, 43, 248, 232, 0, 16, 22, 10, 8, 10, 4, 43, 248, 244, 0, 16, 22, 10, 8, 10, 4, 43, 249, 0, 0, 16, 22, 10, 8, 10, 4, 43, 249, 4, 0, 16, 22, 10, 8, 10, 4, 43, 249, 8, 0, 16, 22, 10, 8, 10, 4, 43, 249, 24, 0, 16, 22, 10, 8, 10, 4, 43, 249, 120, 0, 16, 22, 10, 8, 10, 4, 43, 249, 132, 0, 16, 22, 10, 8, 10, 4, 43, 249, 136, 0, 16, 22, 10, 8, 10, 4, 43, 249, 144, 0, 16, 22, 10, 8, 10, 4, 43, 249, 148, 0, 16, 22, 10, 8, 10, 4, 43, 249, 152, 0, 16, 22, 10, 8, 10, 4, 43, 249, 156, 0, 16, 22, 10, 8, 10, 4, 43, 249, 160, 0, 16, 22, 10, 8, 10, 4, 43, 249, 164, 0, 16, 22, 10, 8, 10, 4, 43, 249, 168, 0, 16, 22, 10, 8, 10, 4, 43, 249, 192, 0, 16, 22, 10, 8, 10, 4, 43, 249, 236, 0, 16, 22, 10, 8, 10, 4, 43, 250, 4, 0, 16, 22, 10, 8, 10, 4, 43, 250, 12, 0, 16, 22, 10, 8, 10, 4, 43, 250, 16, 0, 16, 22, 10, 8, 10, 4, 43, 250, 20, 0, 16, 22, 10, 8, 10, 4, 43, 250, 28, 0, 16, 22, 10, 8, 10, 4, 43, 250, 32, 0, 16, 22, 10, 8, 10, 4, 43, 250, 36, 0, 16, 22, 10, 8, 10, 4, 43, 250, 72, 0, 16, 22, 10, 8, 10, 4, 43, 250, 96, 0, 16, 22, 10, 8, 10, 4, 43, 250, 100, 0, 16, 22, 10, 8, 10, 4, 43, 250, 104, 0, 16, 22, 10, 8, 10, 4, 43, 250, 108, 0, 16, 22, 10, 8, 10, 4, 43, 250, 112, 0, 16, 22, 10, 8, 10, 4, 43, 250, 116, 0, 16, 22, 10, 8, 10, 4, 43, 250, 128, 0, 16, 22, 10, 8, 10, 4, 43, 250, 144, 0, 16, 22, 10, 8, 10, 4, 43, 250, 148, 0, 16, 22, 10, 8, 10, 4, 43, 250, 160, 0, 16, 22, 10, 8, 10, 4, 43, 250, 168, 0, 16, 22, 10, 8, 10, 4, 43, 250, 172, 0, 16, 22, 10, 8, 10, 4, 43, 250, 176, 0, 16, 22, 10, 8, 10, 4, 43, 250, 200, 0, 16, 22, 10, 8, 10, 4, 43, 250, 212, 0, 16, 22, 10, 8, 10, 4, 43, 250, 216, 0, 16, 22, 10, 8, 10, 4, 43, 250, 220, 0, 16, 22, 10, 8, 10, 4, 43, 250, 236, 0, 16, 22, 10, 8, 10, 4, 43, 250, 244, 0, 16, 22, 10, 8, 10, 4, 43, 251, 4, 0, 16, 22, 10, 8, 10, 4, 43, 251, 8, 0, 16, 22, 10, 8, 10, 4, 43, 251, 12, 0, 16, 22, 10, 8, 10, 4, 43, 251, 36, 0, 16, 22, 10, 8, 10, 4, 43, 251, 116, 0, 16, 22, 10, 8, 10, 4, 43, 251, 192, 0, 16, 22, 10, 8, 10, 4, 43, 251, 232, 0, 16, 22, 10, 8, 10, 4, 43, 251, 236, 0, 16, 22, 10, 8, 10, 4, 43, 251, 244, 0, 16, 22, 10, 8, 10, 4, 43, 252, 40, 0, 16, 22, 10, 8, 10, 4, 43, 252, 48, 0, 16, 22, 10, 8, 10, 4, 43, 252, 56, 0, 16, 22, 10, 8, 10, 4, 43, 252, 224, 0, 16, 22, 10, 8, 10, 4, 43, 254, 0, 0, 16, 22, 10, 8, 10, 4, 43, 254, 4, 0, 16, 22, 10, 8, 10, 4, 43, 254, 8, 0, 16, 22, 10, 8, 10, 4, 43, 254, 24, 0, 16, 22, 10, 8, 10, 4, 43, 254, 36, 0, 16, 22, 10, 8, 10, 4, 43, 254, 44, 0, 16, 22, 10, 8, 10, 4, 43, 254, 52, 0, 16, 22, 10, 8, 10, 4, 43, 254, 64, 0, 16, 22, 10, 8, 10, 4, 43, 254, 72, 0, 16, 22, 10, 8, 10, 4, 43, 254, 84, 0, 16, 22, 10, 8, 10, 4, 43, 254, 88, 0, 16, 22, 10, 8, 10, 4, 43, 254, 92, 0, 16, 22, 10, 8, 10, 4, 43, 254, 100, 0, 16, 22, 10, 8, 10, 4, 43, 254, 104, 0, 16, 22, 10, 8, 10, 4, 43, 254, 112, 0, 16, 22, 10, 8, 10, 4, 43, 254, 116, 0, 16, 22, 10, 8, 10, 4, 43, 254, 128, 0, 16, 22, 10, 8, 10, 4, 43, 254, 136, 0, 16, 22, 10, 8, 10, 4, 43, 254, 140, 0, 16, 22, 10, 8, 10, 4, 43, 254, 144, 0, 16, 22, 10, 8, 10, 4, 43, 254, 148, 0, 16, 22, 10, 8, 10, 4, 43, 254, 152, 0, 16, 22, 10, 8, 10, 4, 43, 254, 156, 0, 16, 22, 10, 8, 10, 4, 43, 254, 168, 0, 16, 22, 10, 8, 10, 4, 43, 254, 172, 0, 16, 22, 10, 8, 10, 4, 43, 254, 180, 0, 16, 22, 10, 8, 10, 4, 43, 254, 184, 0, 16, 22, 10, 8, 10, 4, 43, 254, 188, 0, 16, 22, 10, 8, 10, 4, 43, 254, 192, 0, 16, 22, 10, 8, 10, 4, 43, 254, 196, 0, 16, 22, 10, 8, 10, 4, 43, 254, 200, 0, 16, 22, 10, 8, 10, 4, 43, 254, 208, 0, 16, 22, 10, 8, 10, 4, 43, 254, 220, 0, 16, 22, 10, 8, 10, 4, 43, 254, 224, 0, 16, 22, 10, 8, 10, 4, 43, 254, 228, 0, 16, 22, 10, 8, 10, 4, 43, 254, 232, 0, 16, 22, 10, 8, 10, 4, 43, 254, 236, 0, 16, 22, 10, 8, 10, 4, 43, 254, 240, 0, 16, 22, 10, 8, 10, 4, 43, 254, 248, 0, 16, 22, 10, 8, 10, 4, 43, 254, 252, 0, 16, 22, 10, 8, 10, 4, 43, 255, 0, 0, 16, 22, 10, 8, 10, 4, 43, 255, 4, 0, 16, 22, 10, 8, 10, 4, 43, 255, 8, 0, 16, 22, 10, 8, 10, 4, 43, 255, 16, 0, 16, 22, 10, 8, 10, 4, 43, 255, 48, 0, 16, 22, 10, 8, 10, 4, 43, 255, 64, 0, 16, 22, 10, 8, 10, 4, 43, 255, 68, 0, 16, 22, 10, 8, 10, 4, 43, 255, 72, 0, 16, 22, 10, 8, 10, 4, 43, 255, 76, 0, 16, 22, 10, 8, 10, 4, 43, 255, 84, 0, 16, 22, 10, 8, 10, 4, 43, 255, 96, 0, 16, 22, 10, 8, 10, 4, 43, 255, 108, 0, 16, 22, 10, 8, 10, 4, 43, 255, 144, 0, 16, 22, 10, 8, 10, 4, 43, 255, 168, 0, 16, 22, 10, 8, 10, 4, 43, 255, 176, 0, 16, 22, 10, 8, 10, 4, 43, 255, 184, 0, 16, 22, 10, 8, 10, 4, 43, 255, 192, 0, 16, 22, 10, 8, 10, 4, 43, 255, 200, 0, 16, 22, 10, 8, 10, 4, 43, 255, 204, 0, 16, 22, 10, 8, 10, 4, 43, 255, 208, 0, 16, 22, 10, 8, 10, 4, 43, 255, 212, 0, 16, 22, 10, 8, 10, 4, 43, 255, 224, 0, 16, 22, 10, 8, 10, 4, 43, 255, 228, 0, 16, 22, 10, 8, 10, 4, 43, 255, 232, 0, 16, 22, 10, 8, 10, 4, 43, 255, 244, 0, 16, 22, 10, 8, 10, 4, 45, 40, 192, 0, 16, 18, 10, 8, 10, 4, 45, 65, 16, 0, 16, 22, 10, 8, 10, 4, 45, 65, 20, 0, 16, 22, 10, 8, 10, 4, 45, 65, 24, 0, 16, 22, 10, 8, 10, 4, 45, 65, 28, 0, 16, 22, 10, 8, 10, 4, 45, 112, 132, 0, 16, 22, 10, 8, 10, 4, 45, 112, 188, 0, 16, 22, 10, 8, 10, 4, 45, 112, 208, 0, 16, 22, 10, 8, 10, 4, 45, 112, 212, 0, 16, 22, 10, 8, 10, 4, 45, 112, 216, 0, 16, 22, 10, 8, 10, 4, 45, 112, 220, 0, 16, 22, 10, 8, 10, 4, 45, 112, 228, 0, 16, 22, 10, 8, 10, 4, 45, 112, 232, 0, 16, 22, 10, 8, 10, 4, 45, 112, 236, 0, 16, 22, 10, 8, 10, 4, 45, 113, 12, 0, 16, 22, 10, 8, 10, 4, 45, 113, 16, 0, 16, 22, 10, 8, 10, 4, 45, 113, 20, 0, 16, 22, 10, 8, 10, 4, 45, 113, 24, 0, 16, 22, 10, 8, 10, 4, 45, 113, 28, 0, 16, 22, 10, 8, 10, 4, 45, 113, 40, 0, 16, 22, 10, 8, 10, 4, 45, 113, 52, 0, 16, 22, 10, 8, 10, 4, 45, 113, 56, 0, 16, 22, 10, 8, 10, 4, 45, 113, 72, 0, 16, 22, 10, 8, 10, 4, 45, 113, 108, 0, 16, 22, 10, 8, 10, 4, 45, 113, 144, 0, 16, 22, 10, 8, 10, 4, 45, 113, 148, 0, 16, 22, 10, 8, 10, 4, 45, 113, 168, 0, 16, 22, 10, 8, 10, 4, 45, 113, 176, 0, 16, 22, 10, 8, 10, 4, 45, 113, 184, 0, 16, 22, 10, 8, 10, 4, 45, 113, 200, 0, 16, 22, 10, 8, 10, 4, 45, 113, 204, 0, 16, 22, 10, 8, 10, 4, 45, 113, 208, 0, 16, 22, 10, 8, 10, 4, 45, 113, 212, 0, 16, 22, 10, 8, 10, 4, 45, 113, 216, 0, 16, 22, 10, 8, 10, 4, 45, 113, 220, 0, 16, 22, 10, 8, 10, 4, 45, 113, 228, 0, 16, 22, 10, 8, 10, 4, 45, 113, 240, 0, 16, 22, 10, 8, 10, 4, 45, 113, 252, 0, 16, 22, 10, 8, 10, 4, 45, 114, 0, 0, 16, 22, 10, 8, 10, 4, 45, 114, 12, 0, 16, 22, 10, 8, 10, 4, 45, 114, 32, 0, 16, 22, 10, 8, 10, 4, 45, 114, 40, 0, 16, 22, 10, 8, 10, 4, 45, 114, 52, 0, 16, 22, 10, 8, 10, 4, 45, 114, 96, 0, 16, 22, 10, 8, 10, 4, 45, 114, 104, 0, 16, 22, 10, 8, 10, 4, 45, 114, 108, 0, 16, 22, 10, 8, 10, 4, 45, 114, 124, 0, 16, 22, 10, 8, 10, 4, 45, 114, 136, 0, 16, 22, 10, 8, 10, 4, 45, 114, 196, 0, 16, 22, 10, 8, 10, 4, 45, 114, 200, 0, 16, 22, 10, 8, 10, 4, 45, 114, 228, 0, 16, 22, 10, 8, 10, 4, 45, 114, 236, 0, 16, 22, 10, 8, 10, 4, 45, 114, 252, 0, 16, 22, 10, 8, 10, 4, 45, 115, 44, 0, 16, 22, 10, 8, 10, 4, 45, 115, 100, 0, 16, 22, 10, 8, 10, 4, 45, 115, 120, 0, 16, 22, 10, 8, 10, 4, 45, 115, 132, 0, 16, 22, 10, 8, 10, 4, 45, 115, 144, 0, 16, 22, 10, 8, 10, 4, 45, 115, 156, 0, 16, 22, 10, 8, 10, 4, 45, 115, 164, 0, 16, 22, 10, 8, 10, 4, 45, 115, 200, 0, 16, 22, 10, 8, 10, 4, 45, 115, 212, 0, 16, 22, 10, 8, 10, 4, 45, 115, 216, 0, 16, 22, 10, 8, 10, 4, 45, 115, 228, 0, 16, 22, 10, 8, 10, 4, 45, 115, 236, 0, 16, 22, 10, 8, 10, 4, 45, 115, 244, 0, 16, 22, 10, 8, 10, 4, 45, 115, 248, 0, 16, 22, 10, 8, 10, 4, 45, 116, 12, 0, 16, 22, 10, 8, 10, 4, 45, 116, 16, 0, 16, 22, 10, 8, 10, 4, 45, 116, 20, 0, 16, 22, 10, 8, 10, 4, 45, 116, 24, 0, 16, 22, 10, 8, 10, 4, 45, 116, 32, 0, 16, 22, 10, 8, 10, 4, 45, 116, 36, 0, 16, 22, 10, 8, 10, 4, 45, 116, 52, 0, 16, 22, 10, 8, 10, 4, 45, 116, 96, 0, 16, 22, 10, 8, 10, 4, 45, 116, 100, 0, 16, 22, 10, 8, 10, 4, 45, 116, 140, 0, 16, 22, 10, 8, 10, 4, 45, 116, 152, 0, 16, 22, 10, 8, 10, 4, 45, 116, 208, 0, 16, 22, 10, 8, 10, 4, 45, 117, 8, 0, 16, 22, 10, 8, 10, 4, 45, 117, 20, 0, 16, 22, 10, 8, 10, 4, 45, 117, 68, 0, 16, 22, 10, 8, 10, 4, 45, 117, 124, 0, 16, 22, 10, 8, 10, 4, 45, 117, 252, 0, 16, 22, 10, 8, 10, 4, 45, 119, 52, 0, 16, 22, 10, 8, 10, 4, 45, 119, 60, 0, 16, 22, 10, 8, 10, 4, 45, 119, 64, 0, 16, 22, 10, 8, 10, 4, 45, 119, 68, 0, 16, 22, 10, 8, 10, 4, 45, 119, 72, 0, 16, 22, 10, 8, 10, 4, 45, 119, 104, 0, 16, 22, 10, 8, 10, 4, 45, 119, 116, 0, 16, 22, 10, 8, 10, 4, 45, 119, 232, 0, 16, 22, 10, 8, 10, 4, 45, 120, 100, 0, 16, 22, 10, 8, 10, 4, 45, 120, 140, 0, 16, 22, 10, 8, 10, 4, 45, 120, 164, 0, 16, 22, 10, 8, 10, 4, 45, 120, 220, 0, 16, 22, 10, 8, 10, 4, 45, 120, 240, 0, 16, 22, 10, 8, 10, 4, 45, 121, 20, 0, 16, 22, 10, 8, 10, 4, 45, 121, 52, 0, 16, 22, 10, 8, 10, 4, 45, 121, 64, 0, 16, 22, 10, 8, 10, 4, 45, 121, 68, 0, 16, 22, 10, 8, 10, 4, 45, 121, 72, 0, 16, 22, 10, 8, 10, 4, 45, 121, 92, 0, 16, 22, 10, 8, 10, 4, 45, 121, 96, 0, 16, 22, 10, 8, 10, 4, 45, 121, 104, 0, 16, 22, 10, 8, 10, 4, 45, 121, 172, 0, 16, 22, 10, 8, 10, 4, 45, 121, 176, 0, 16, 22, 10, 8, 10, 4, 45, 121, 212, 0, 16, 22, 10, 8, 10, 4, 45, 121, 240, 0, 16, 22, 10, 8, 10, 4, 45, 121, 244, 0, 16, 22, 10, 8, 10, 4, 45, 121, 248, 0, 16, 22, 10, 8, 10, 4, 45, 121, 252, 0, 16, 22, 10, 8, 10, 4, 45, 122, 0, 0, 16, 22, 10, 8, 10, 4, 45, 122, 4, 0, 16, 22, 10, 8, 10, 4, 45, 122, 8, 0, 16, 22, 10, 8, 10, 4, 45, 122, 12, 0, 16, 22, 10, 8, 10, 4, 45, 122, 16, 0, 16, 22, 10, 8, 10, 4, 45, 122, 20, 0, 16, 22, 10, 8, 10, 4, 45, 122, 24, 0, 16, 22, 10, 8, 10, 4, 45, 122, 28, 0, 16, 22, 10, 8, 10, 4, 45, 122, 32, 0, 16, 22, 10, 8, 10, 4, 45, 122, 36, 0, 16, 22, 10, 8, 10, 4, 45, 122, 40, 0, 16, 22, 10, 8, 10, 4, 45, 122, 60, 0, 16, 22, 10, 8, 10, 4, 45, 122, 64, 0, 16, 22, 10, 8, 10, 4, 45, 122, 68, 0, 16, 22, 10, 8, 10, 4, 45, 122, 72, 0, 16, 22, 10, 8, 10, 4, 45, 122, 76, 0, 16, 22, 10, 8, 10, 4, 45, 122, 80, 0, 16, 22, 10, 8, 10, 4, 45, 122, 84, 0, 16, 22, 10, 8, 10, 4, 45, 122, 88, 0, 16, 22, 10, 8, 10, 4, 45, 122, 92, 0, 16, 22, 10, 8, 10, 4, 45, 122, 96, 0, 16, 21, 10, 8, 10, 4, 45, 122, 104, 0, 16, 22, 10, 8, 10, 4, 45, 122, 108, 0, 16, 22, 10, 8, 10, 4, 45, 122, 112, 0, 16, 22, 10, 8, 10, 4, 45, 122, 116, 0, 16, 22, 10, 8, 10, 4, 45, 122, 160, 0, 16, 22, 10, 8, 10, 4, 45, 122, 164, 0, 16, 22, 10, 8, 10, 4, 45, 122, 168, 0, 16, 22, 10, 8, 10, 4, 45, 122, 172, 0, 16, 22, 10, 8, 10, 4, 45, 122, 176, 0, 16, 22, 10, 8, 10, 4, 45, 122, 180, 0, 16, 22, 10, 8, 10, 4, 45, 122, 184, 0, 16, 22, 10, 8, 10, 4, 45, 122, 188, 0, 16, 22, 10, 8, 10, 4, 45, 122, 192, 0, 16, 22, 10, 8, 10, 4, 45, 122, 196, 0, 16, 22, 10, 8, 10, 4, 45, 122, 200, 0, 16, 22, 10, 8, 10, 4, 45, 122, 204, 0, 16, 22, 10, 8, 10, 4, 45, 122, 208, 0, 16, 22, 10, 8, 10, 4, 45, 122, 212, 0, 16, 22, 10, 8, 10, 4, 45, 122, 216, 0, 16, 22, 10, 8, 10, 4, 45, 123, 28, 0, 16, 22, 10, 8, 10, 4, 45, 123, 32, 0, 16, 22, 10, 8, 10, 4, 45, 123, 36, 0, 16, 22, 10, 8, 10, 4, 45, 123, 44, 0, 16, 22, 10, 8, 10, 4, 45, 123, 48, 0, 16, 22, 10, 8, 10, 4, 45, 123, 52, 0, 16, 22, 10, 8, 10, 4, 45, 123, 56, 0, 16, 22, 10, 8, 10, 4, 45, 123, 60, 0, 16, 22, 10, 8, 10, 4, 45, 123, 64, 0, 16, 22, 10, 8, 10, 4, 45, 123, 68, 0, 16, 22, 10, 8, 10, 4, 45, 123, 72, 0, 16, 22, 10, 8, 10, 4, 45, 123, 76, 0, 16, 22, 10, 8, 10, 4, 45, 123, 80, 0, 16, 22, 10, 8, 10, 4, 45, 123, 84, 0, 16, 22, 10, 8, 10, 4, 45, 123, 88, 0, 16, 22, 10, 8, 10, 4, 45, 123, 120, 0, 16, 22, 10, 8, 10, 4, 45, 123, 128, 0, 16, 22, 10, 8, 10, 4, 45, 123, 132, 0, 16, 22, 10, 8, 10, 4, 45, 123, 136, 0, 16, 22, 10, 8, 10, 4, 45, 123, 148, 0, 16, 22, 10, 8, 10, 4, 45, 123, 152, 0, 16, 22, 10, 8, 10, 4, 45, 123, 156, 0, 16, 22, 10, 8, 10, 4, 45, 123, 164, 0, 16, 22, 10, 8, 10, 4, 45, 123, 168, 0, 16, 22, 10, 8, 10, 4, 45, 123, 172, 0, 16, 22, 10, 8, 10, 4, 45, 123, 176, 0, 16, 22, 10, 8, 10, 4, 45, 123, 180, 0, 16, 22, 10, 8, 10, 4, 45, 123, 184, 0, 16, 22, 10, 8, 10, 4, 45, 123, 204, 0, 16, 22, 10, 8, 10, 4, 45, 123, 212, 0, 16, 22, 10, 8, 10, 4, 45, 123, 224, 0, 16, 22, 10, 8, 10, 4, 45, 123, 228, 0, 16, 22, 10, 8, 10, 4, 45, 123, 232, 0, 16, 22, 10, 8, 10, 4, 45, 123, 236, 0, 16, 22, 10, 8, 10, 4, 45, 123, 240, 0, 16, 22, 10, 8, 10, 4, 45, 123, 244, 0, 16, 22, 10, 8, 10, 4, 45, 123, 248, 0, 16, 22, 10, 8, 10, 4, 45, 123, 252, 0, 16, 22, 10, 8, 10, 4, 45, 124, 0, 0, 16, 22, 10, 8, 10, 4, 45, 124, 20, 0, 16, 22, 10, 8, 10, 4, 45, 124, 28, 0, 16, 22, 10, 8, 10, 4, 45, 124, 32, 0, 16, 22, 10, 8, 10, 4, 45, 124, 36, 0, 16, 22, 10, 8, 10, 4, 45, 124, 44, 0, 16, 22, 10, 8, 10, 4, 45, 124, 68, 0, 16, 22, 10, 8, 10, 4, 45, 124, 76, 0, 16, 22, 10, 8, 10, 4, 45, 124, 80, 0, 16, 22, 10, 8, 10, 4, 45, 124, 100, 0, 16, 22, 10, 8, 10, 4, 45, 124, 124, 0, 16, 22, 10, 8, 10, 4, 45, 124, 172, 0, 16, 22, 10, 8, 10, 4, 45, 124, 176, 0, 16, 22, 10, 8, 10, 4, 45, 124, 208, 0, 16, 22, 10, 8, 10, 4, 45, 124, 248, 0, 16, 22, 10, 8, 10, 4, 45, 124, 252, 0, 16, 22, 10, 8, 10, 4, 45, 125, 12, 0, 16, 22, 10, 8, 10, 4, 45, 125, 16, 0, 16, 22, 10, 8, 10, 4, 45, 125, 24, 0, 16, 22, 10, 8, 10, 4, 45, 125, 28, 0, 16, 22, 10, 8, 10, 4, 45, 125, 32, 0, 16, 22, 10, 8, 10, 4, 45, 125, 44, 0, 16, 22, 10, 8, 10, 4, 45, 125, 52, 0, 16, 22, 10, 8, 10, 4, 45, 125, 56, 0, 16, 22, 10, 8, 10, 4, 45, 125, 76, 0, 16, 22, 10, 8, 10, 4, 45, 125, 80, 0, 16, 22, 10, 8, 10, 4, 45, 125, 84, 0, 16, 22, 10, 8, 10, 4, 45, 125, 88, 0, 16, 22, 10, 8, 10, 4, 45, 125, 92, 0, 16, 22, 10, 8, 10, 4, 45, 125, 96, 0, 16, 22, 10, 8, 10, 4, 45, 125, 100, 0, 16, 22, 10, 8, 10, 4, 45, 125, 104, 0, 16, 22, 10, 8, 10, 4, 45, 125, 136, 0, 16, 22, 10, 8, 10, 4, 45, 126, 48, 0, 16, 22, 10, 8, 10, 4, 45, 126, 52, 0, 16, 22, 10, 8, 10, 4, 45, 126, 100, 0, 16, 22, 10, 8, 10, 4, 45, 126, 108, 0, 16, 22, 10, 8, 10, 4, 45, 126, 112, 0, 16, 22, 10, 8, 10, 4, 45, 126, 116, 0, 16, 22, 10, 8, 10, 4, 45, 126, 120, 0, 16, 22, 10, 8, 10, 4, 45, 126, 212, 0, 16, 22, 10, 8, 10, 4, 45, 126, 220, 0, 16, 22, 10, 8, 10, 4, 45, 127, 8, 0, 16, 22, 10, 8, 10, 4, 45, 127, 12, 0, 16, 22, 10, 8, 10, 4, 45, 127, 36, 0, 16, 22, 10, 8, 10, 4, 45, 127, 96, 0, 16, 22, 10, 8, 10, 4, 45, 127, 116, 0, 16, 22, 10, 8, 10, 4, 45, 127, 124, 0, 16, 22, 10, 8, 10, 4, 45, 127, 128, 0, 16, 22, 10, 8, 10, 4, 45, 127, 144, 0, 16, 22, 10, 8, 10, 4, 45, 127, 148, 0, 16, 22, 10, 8, 10, 4, 45, 127, 156, 0, 16, 22, 10, 8, 10, 4, 45, 127, 216, 0, 16, 22, 10, 8, 10, 4, 45, 248, 8, 0, 16, 22, 10, 8, 10, 4, 45, 248, 80, 0, 16, 22, 10, 8, 10, 4, 45, 248, 84, 0, 16, 22, 10, 8, 10, 4, 45, 248, 88, 0, 16, 22, 10, 8, 10, 4, 45, 248, 96, 0, 16, 22, 10, 8, 10, 4, 45, 248, 100, 0, 16, 22, 10, 8, 10, 4, 45, 248, 104, 0, 16, 22, 10, 8, 10, 4, 45, 248, 108, 0, 16, 22, 10, 8, 10, 4, 45, 248, 128, 0, 16, 22, 10, 8, 10, 4, 45, 248, 132, 0, 16, 22, 10, 8, 10, 4, 45, 248, 204, 0, 16, 22, 10, 8, 10, 4, 45, 248, 208, 0, 16, 22, 10, 8, 10, 4, 45, 248, 212, 0, 16, 22, 10, 8, 10, 4, 45, 248, 216, 0, 16, 22, 10, 8, 10, 4, 45, 248, 220, 0, 16, 22, 10, 8, 10, 4, 45, 248, 224, 0, 16, 22, 10, 8, 10, 4, 45, 248, 228, 0, 16, 22, 10, 8, 10, 4, 45, 248, 232, 0, 16, 22, 10, 8, 10, 4, 45, 248, 236, 0, 16, 22, 10, 8, 10, 4, 45, 248, 240, 0, 16, 22, 10, 8, 10, 4, 45, 248, 244, 0, 16, 22, 10, 8, 10, 4, 45, 248, 248, 0, 16, 22, 10, 8, 10, 4, 45, 248, 252, 0, 16, 22, 10, 8, 10, 4, 45, 249, 0, 0, 16, 22, 10, 8, 10, 4, 45, 249, 4, 0, 16, 22, 10, 8, 10, 4, 45, 249, 12, 0, 16, 22, 10, 8, 10, 4, 45, 249, 16, 0, 16, 22, 10, 8, 10, 4, 45, 249, 20, 0, 16, 22, 10, 8, 10, 4, 45, 249, 24, 0, 16, 22, 10, 8, 10, 4, 45, 249, 28, 0, 16, 22, 10, 8, 10, 4, 45, 249, 32, 0, 16, 22, 10, 8, 10, 4, 45, 249, 36, 0, 16, 22, 10, 8, 10, 4, 45, 249, 92, 0, 16, 22, 10, 8, 10, 4, 45, 249, 112, 0, 16, 22, 10, 8, 10, 4, 45, 249, 180, 0, 16, 22, 10, 8, 10, 4, 45, 249, 188, 0, 16, 22, 10, 8, 10, 4, 45, 249, 192, 0, 16, 22, 10, 8, 10, 4, 45, 249, 196, 0, 16, 22, 10, 8, 10, 4, 45, 249, 200, 0, 16, 22, 10, 8, 10, 4, 45, 249, 204, 0, 16, 22, 10, 8, 10, 4, 45, 249, 208, 0, 16, 22, 10, 8, 10, 4, 45, 249, 212, 0, 16, 22, 10, 8, 10, 4, 45, 250, 12, 0, 16, 22, 10, 8, 10, 4, 45, 250, 16, 0, 16, 22, 10, 8, 10, 4, 45, 250, 28, 0, 16, 22, 10, 8, 10, 4, 45, 250, 32, 0, 16, 22, 10, 8, 10, 4, 45, 250, 36, 0, 16, 22, 10, 8, 10, 4, 45, 250, 40, 0, 16, 22, 10, 8, 10, 4, 45, 250, 76, 0, 16, 22, 10, 8, 10, 4, 45, 250, 80, 0, 16, 22, 10, 8, 10, 4, 45, 250, 84, 0, 16, 22, 10, 8, 10, 4, 45, 250, 88, 0, 16, 22, 10, 8, 10, 4, 45, 250, 92, 0, 16, 22, 10, 8, 10, 4, 45, 250, 96, 0, 16, 22, 10, 8, 10, 4, 45, 250, 104, 0, 16, 22, 10, 8, 10, 4, 45, 250, 108, 0, 16, 22, 10, 8, 10, 4, 45, 250, 112, 0, 16, 22, 10, 8, 10, 4, 45, 250, 116, 0, 16, 22, 10, 8, 10, 4, 45, 250, 120, 0, 16, 22, 10, 8, 10, 4, 45, 250, 124, 0, 16, 22, 10, 8, 10, 4, 45, 250, 128, 0, 16, 22, 10, 8, 10, 4, 45, 250, 132, 0, 16, 22, 10, 8, 10, 4, 45, 250, 136, 0, 16, 22, 10, 8, 10, 4, 45, 250, 140, 0, 16, 22, 10, 8, 10, 4, 45, 250, 144, 0, 16, 22, 10, 8, 10, 4, 45, 250, 148, 0, 16, 22, 10, 8, 10, 4, 45, 250, 152, 0, 16, 22, 10, 8, 10, 4, 45, 250, 164, 0, 16, 22, 10, 8, 10, 4, 45, 250, 180, 0, 16, 22, 10, 8, 10, 4, 45, 250, 184, 0, 16, 22, 10, 8, 10, 4, 45, 250, 188, 0, 16, 22, 10, 8, 10, 4, 45, 250, 192, 0, 16, 22, 10, 8, 10, 4, 45, 251, 0, 0, 16, 22, 10, 8, 10, 4, 45, 251, 8, 0, 16, 22, 10, 8, 10, 4, 45, 251, 16, 0, 16, 22, 10, 8, 10, 4, 45, 251, 20, 0, 16, 22, 10, 8, 10, 4, 45, 251, 52, 0, 16, 22, 10, 8, 10, 4, 45, 251, 84, 0, 16, 22, 10, 8, 10, 4, 45, 251, 88, 0, 16, 22, 10, 8, 10, 4, 45, 251, 92, 0, 16, 22, 10, 8, 10, 4, 45, 251, 96, 0, 16, 22, 10, 8, 10, 4, 45, 251, 100, 0, 16, 22, 10, 8, 10, 4, 45, 251, 120, 0, 16, 22, 10, 8, 10, 4, 45, 251, 124, 0, 16, 22, 10, 8, 10, 4, 45, 251, 136, 0, 16, 22, 10, 8, 10, 4, 45, 251, 140, 0, 16, 22, 10, 8, 10, 4, 45, 251, 144, 0, 16, 22, 10, 8, 10, 4, 45, 251, 148, 0, 16, 22, 10, 8, 10, 4, 45, 251, 152, 0, 16, 22, 10, 8, 10, 4, 45, 251, 156, 0, 16, 22, 10, 8, 10, 4, 45, 251, 160, 0, 16, 22, 10, 8, 10, 4, 45, 251, 164, 0, 16, 22, 10, 8, 10, 4, 45, 251, 168, 0, 16, 22, 10, 8, 10, 4, 45, 251, 172, 0, 16, 22, 10, 8, 10, 4, 45, 251, 176, 0, 16, 22, 10, 8, 10, 4, 45, 251, 180, 0, 16, 22, 10, 8, 10, 4, 45, 251, 184, 0, 16, 22, 10, 8, 10, 4, 45, 251, 188, 0, 16, 22, 10, 8, 10, 4, 45, 251, 192, 0, 16, 22, 10, 8, 10, 4, 45, 251, 196, 0, 16, 22, 10, 8, 10, 4, 45, 251, 200, 0, 16, 22, 10, 8, 10, 4, 45, 251, 204, 0, 16, 22, 10, 8, 10, 4, 45, 251, 208, 0, 16, 22, 10, 8, 10, 4, 45, 251, 212, 0, 16, 22, 10, 8, 10, 4, 45, 251, 216, 0, 16, 22, 10, 8, 10, 4, 45, 251, 220, 0, 16, 22, 10, 8, 10, 4, 45, 251, 224, 0, 16, 22, 10, 8, 10, 4, 45, 252, 0, 0, 16, 22, 10, 8, 10, 4, 45, 252, 4, 0, 16, 22, 10, 8, 10, 4, 45, 252, 8, 0, 16, 22, 10, 8, 10, 4, 45, 252, 12, 0, 16, 22, 10, 8, 10, 4, 45, 252, 16, 0, 16, 22, 10, 8, 10, 4, 45, 252, 20, 0, 16, 22, 10, 8, 10, 4, 45, 252, 24, 0, 16, 22, 10, 8, 10, 4, 45, 252, 28, 0, 16, 22, 10, 8, 10, 4, 45, 252, 32, 0, 16, 22, 10, 8, 10, 4, 45, 252, 36, 0, 16, 22, 10, 8, 10, 4, 45, 252, 40, 0, 16, 22, 10, 8, 10, 4, 45, 252, 44, 0, 16, 22, 10, 8, 10, 4, 45, 252, 48, 0, 16, 22, 10, 8, 10, 4, 45, 252, 60, 0, 16, 22, 10, 8, 10, 4, 45, 252, 84, 0, 16, 22, 10, 8, 10, 4, 45, 252, 88, 0, 16, 22, 10, 8, 10, 4, 45, 252, 92, 0, 16, 22, 10, 8, 10, 4, 45, 252, 96, 0, 16, 22, 10, 8, 10, 4, 45, 252, 100, 0, 16, 22, 10, 8, 10, 4, 45, 252, 104, 0, 16, 22, 10, 8, 10, 4, 45, 252, 108, 0, 16, 22, 10, 8, 10, 4, 45, 252, 112, 0, 16, 22, 10, 8, 10, 4, 45, 252, 116, 0, 16, 22, 10, 8, 10, 4, 45, 252, 120, 0, 16, 22, 10, 8, 10, 4, 45, 252, 124, 0, 16, 22, 10, 8, 10, 4, 45, 252, 128, 0, 16, 22, 10, 8, 10, 4, 45, 252, 132, 0, 16, 22, 10, 8, 10, 4, 45, 252, 136, 0, 16, 22, 10, 8, 10, 4, 45, 252, 140, 0, 16, 22, 10, 8, 10, 4, 45, 252, 144, 0, 16, 22, 10, 8, 10, 4, 45, 252, 148, 0, 16, 22, 10, 8, 10, 4, 45, 252, 152, 0, 16, 22, 10, 8, 10, 4, 45, 252, 156, 0, 16, 22, 10, 8, 10, 4, 45, 252, 160, 0, 16, 22, 10, 8, 10, 4, 45, 252, 164, 0, 16, 22, 10, 8, 10, 4, 45, 252, 168, 0, 16, 22, 10, 8, 10, 4, 45, 252, 172, 0, 16, 22, 10, 8, 10, 4, 45, 252, 176, 0, 16, 22, 10, 8, 10, 4, 45, 252, 192, 0, 16, 22, 10, 8, 10, 4, 45, 252, 196, 0, 16, 22, 10, 8, 10, 4, 45, 252, 200, 0, 16, 22, 10, 8, 10, 4, 45, 252, 204, 0, 16, 22, 10, 8, 10, 4, 45, 252, 208, 0, 16, 22, 10, 8, 10, 4, 45, 252, 212, 0, 16, 22, 10, 8, 10, 4, 45, 252, 216, 0, 16, 22, 10, 8, 10, 4, 45, 252, 220, 0, 16, 22, 10, 8, 10, 4, 45, 252, 224, 0, 16, 22, 10, 8, 10, 4, 45, 252, 228, 0, 16, 22, 10, 8, 10, 4, 45, 252, 232, 0, 16, 22, 10, 8, 10, 4, 45, 253, 0, 0, 16, 22, 10, 8, 10, 4, 45, 253, 4, 0, 16, 22, 10, 8, 10, 4, 45, 253, 8, 0, 16, 22, 10, 8, 10, 4, 45, 253, 12, 0, 16, 22, 10, 8, 10, 4, 45, 253, 16, 0, 16, 22, 10, 8, 10, 4, 45, 253, 20, 0, 16, 22, 10, 8, 10, 4, 45, 253, 24, 0, 16, 22, 10, 8, 10, 4, 45, 253, 28, 0, 16, 22, 10, 8, 10, 4, 45, 253, 32, 0, 16, 22, 10, 8, 10, 4, 45, 253, 36, 0, 16, 22, 10, 8, 10, 4, 45, 253, 40, 0, 16, 22, 10, 8, 10, 4, 45, 253, 44, 0, 16, 22, 10, 8, 10, 4, 45, 253, 48, 0, 16, 22, 10, 8, 10, 4, 45, 253, 52, 0, 16, 22, 10, 8, 10, 4, 45, 253, 56, 0, 16, 22, 10, 8, 10, 4, 45, 253, 60, 0, 16, 22, 10, 8, 10, 4, 45, 253, 64, 0, 16, 22, 10, 8, 10, 4, 45, 253, 68, 0, 16, 22, 10, 8, 10, 4, 45, 253, 72, 0, 16, 22, 10, 8, 10, 4, 45, 253, 76, 0, 16, 22, 10, 8, 10, 4, 45, 253, 80, 0, 16, 22, 10, 8, 10, 4, 45, 253, 84, 0, 16, 22, 10, 8, 10, 4, 45, 253, 92, 0, 16, 22, 10, 8, 10, 4, 45, 253, 96, 0, 16, 22, 10, 8, 10, 4, 45, 253, 100, 0, 16, 22, 10, 8, 10, 4, 45, 253, 104, 0, 16, 22, 10, 8, 10, 4, 45, 253, 108, 0, 16, 22, 10, 8, 10, 4, 45, 253, 112, 0, 16, 22, 10, 8, 10, 4, 45, 253, 116, 0, 16, 22, 10, 8, 10, 4, 45, 253, 120, 0, 16, 22, 10, 8, 10, 4, 45, 253, 132, 0, 16, 22, 10, 8, 10, 4, 45, 253, 136, 0, 16, 22, 10, 8, 10, 4, 45, 253, 140, 0, 16, 22, 10, 8, 10, 4, 45, 253, 144, 0, 16, 22, 10, 8, 10, 4, 45, 253, 148, 0, 16, 22, 10, 8, 10, 4, 45, 253, 152, 0, 16, 22, 10, 8, 10, 4, 45, 253, 156, 0, 16, 22, 10, 8, 10, 4, 45, 253, 160, 0, 16, 22, 10, 8, 10, 4, 45, 253, 164, 0, 16, 22, 10, 8, 10, 4, 45, 253, 168, 0, 16, 22, 10, 8, 10, 4, 45, 253, 172, 0, 16, 22, 10, 8, 10, 4, 45, 253, 176, 0, 16, 22, 10, 8, 10, 4, 45, 253, 180, 0, 16, 22, 10, 8, 10, 4, 45, 253, 184, 0, 16, 22, 10, 8, 10, 4, 45, 253, 188, 0, 16, 22, 10, 8, 10, 4, 45, 253, 192, 0, 16, 22, 10, 8, 10, 4, 45, 253, 196, 0, 16, 22, 10, 8, 10, 4, 45, 253, 200, 0, 16, 22, 10, 8, 10, 4, 45, 253, 204, 0, 16, 22, 10, 8, 10, 4, 45, 253, 208, 0, 16, 22, 10, 8, 10, 4, 45, 253, 212, 0, 16, 22, 10, 8, 10, 4, 45, 253, 216, 0, 16, 22, 10, 8, 10, 4, 45, 253, 220, 0, 16, 22, 10, 8, 10, 4, 45, 253, 224, 0, 16, 22, 10, 8, 10, 4, 45, 253, 228, 0, 16, 22, 10, 8, 10, 4, 45, 253, 232, 0, 16, 22, 10, 8, 10, 4, 45, 253, 236, 0, 16, 22, 10, 8, 10, 4, 45, 253, 240, 0, 16, 22, 10, 8, 10, 4, 45, 253, 244, 0, 16, 22, 10, 8, 10, 4, 45, 253, 248, 0, 16, 22, 10, 8, 10, 4, 45, 253, 252, 0, 16, 22, 10, 8, 10, 4, 45, 254, 0, 0, 16, 22, 10, 8, 10, 4, 45, 254, 4, 0, 16, 22, 10, 8, 10, 4, 45, 254, 8, 0, 16, 22, 10, 8, 10, 4, 45, 254, 12, 0, 16, 22, 10, 8, 10, 4, 45, 254, 16, 0, 16, 22, 10, 8, 10, 4, 45, 254, 20, 0, 16, 22, 10, 8, 10, 4, 45, 254, 24, 0, 16, 22, 10, 8, 10, 4, 45, 254, 28, 0, 16, 22, 10, 8, 10, 4, 45, 254, 40, 0, 16, 22, 10, 8, 10, 4, 45, 254, 48, 0, 16, 22, 10, 8, 10, 4, 45, 254, 52, 0, 16, 22, 10, 8, 10, 4, 45, 254, 56, 0, 16, 22, 10, 8, 10, 4, 45, 254, 60, 0, 16, 22, 10, 8, 10, 4, 45, 254, 64, 0, 16, 22, 10, 8, 10, 4, 45, 254, 68, 0, 16, 22, 10, 8, 10, 4, 45, 254, 72, 0, 16, 22, 10, 8, 10, 4, 45, 254, 76, 0, 16, 22, 10, 8, 10, 4, 45, 254, 80, 0, 16, 22, 10, 8, 10, 4, 45, 254, 84, 0, 16, 22, 10, 8, 10, 4, 45, 254, 88, 0, 16, 22, 10, 8, 10, 4, 45, 254, 92, 0, 16, 22, 10, 8, 10, 4, 45, 254, 96, 0, 16, 22, 10, 8, 10, 4, 45, 254, 100, 0, 16, 22, 10, 8, 10, 4, 45, 254, 104, 0, 16, 22, 10, 8, 10, 4, 45, 254, 108, 0, 16, 22, 10, 8, 10, 4, 45, 254, 112, 0, 16, 22, 10, 8, 10, 4, 45, 254, 116, 0, 16, 22, 10, 8, 10, 4, 45, 254, 120, 0, 16, 22, 10, 8, 10, 4, 45, 254, 124, 0, 16, 22, 10, 8, 10, 4, 45, 254, 128, 0, 16, 22, 10, 8, 10, 4, 45, 254, 132, 0, 16, 22, 10, 8, 10, 4, 45, 254, 136, 0, 16, 22, 10, 8, 10, 4, 45, 254, 140, 0, 16, 22, 10, 8, 10, 4, 45, 254, 144, 0, 16, 22, 10, 8, 10, 4, 45, 254, 148, 0, 16, 22, 10, 8, 10, 4, 45, 254, 152, 0, 16, 22, 10, 8, 10, 4, 45, 254, 156, 0, 16, 22, 10, 8, 10, 4, 45, 254, 160, 0, 16, 22, 10, 8, 10, 4, 45, 254, 164, 0, 16, 22, 10, 8, 10, 4, 45, 254, 168, 0, 16, 22, 10, 8, 10, 4, 45, 254, 172, 0, 16, 22, 10, 8, 10, 4, 45, 254, 176, 0, 16, 22, 10, 8, 10, 4, 45, 254, 180, 0, 16, 22, 10, 8, 10, 4, 45, 254, 184, 0, 16, 22, 10, 8, 10, 4, 45, 254, 188, 0, 16, 22, 10, 8, 10, 4, 45, 254, 192, 0, 16, 22, 10, 8, 10, 4, 45, 254, 196, 0, 16, 22, 10, 8, 10, 4, 45, 254, 200, 0, 16, 22, 10, 8, 10, 4, 45, 254, 204, 0, 16, 22, 10, 8, 10, 4, 45, 254, 208, 0, 16, 22, 10, 8, 10, 4, 45, 254, 212, 0, 16, 22, 10, 8, 10, 4, 45, 254, 216, 0, 16, 22, 10, 8, 10, 4, 45, 254, 220, 0, 16, 22, 10, 8, 10, 4, 45, 254, 224, 0, 16, 22, 10, 8, 10, 4, 45, 254, 228, 0, 16, 22, 10, 8, 10, 4, 45, 254, 236, 0, 16, 22, 10, 8, 10, 4, 45, 254, 240, 0, 16, 22, 10, 8, 10, 4, 45, 254, 248, 0, 16, 22, 10, 8, 10, 4, 45, 255, 0, 0, 16, 22, 10, 8, 10, 4, 45, 255, 4, 0, 16, 22, 10, 8, 10, 4, 45, 255, 8, 0, 16, 22, 10, 8, 10, 4, 45, 255, 12, 0, 16, 22, 10, 8, 10, 4, 45, 255, 16, 0, 16, 22, 10, 8, 10, 4, 45, 255, 20, 0, 16, 22, 10, 8, 10, 4, 45, 255, 24, 0, 16, 22, 10, 8, 10, 4, 45, 255, 28, 0, 16, 22, 10, 8, 10, 4, 45, 255, 32, 0, 16, 22, 10, 8, 10, 4, 45, 255, 36, 0, 16, 22, 10, 8, 10, 4, 45, 255, 40, 0, 16, 22, 10, 8, 10, 4, 45, 255, 44, 0, 16, 22, 10, 8, 10, 4, 45, 255, 48, 0, 16, 22, 10, 8, 10, 4, 45, 255, 52, 0, 16, 22, 10, 8, 10, 4, 45, 255, 56, 0, 16, 22, 10, 8, 10, 4, 45, 255, 60, 0, 16, 22, 10, 8, 10, 4, 45, 255, 64, 0, 16, 22, 10, 8, 10, 4, 45, 255, 68, 0, 16, 22, 10, 8, 10, 4, 45, 255, 72, 0, 16, 22, 10, 8, 10, 4, 45, 255, 76, 0, 16, 22, 10, 8, 10, 4, 45, 255, 80, 0, 16, 22, 10, 8, 10, 4, 45, 255, 84, 0, 16, 22, 10, 8, 10, 4, 45, 255, 88, 0, 16, 22, 10, 8, 10, 4, 45, 255, 92, 0, 16, 22, 10, 8, 10, 4, 45, 255, 96, 0, 16, 22, 10, 8, 10, 4, 45, 255, 100, 0, 16, 22, 10, 8, 10, 4, 45, 255, 104, 0, 16, 22, 10, 8, 10, 4, 45, 255, 108, 0, 16, 22, 10, 8, 10, 4, 45, 255, 112, 0, 16, 22, 10, 8, 10, 4, 45, 255, 116, 0, 16, 22, 10, 8, 10, 4, 45, 255, 120, 0, 16, 22, 10, 8, 10, 4, 45, 255, 124, 0, 16, 22, 10, 8, 10, 4, 45, 255, 132, 0, 16, 22, 10, 8, 10, 4, 45, 255, 136, 0, 16, 22, 10, 8, 10, 4, 45, 255, 140, 0, 16, 22, 10, 8, 10, 4, 45, 255, 144, 0, 16, 22, 10, 8, 10, 4, 45, 255, 148, 0, 16, 22, 10, 8, 10, 4, 45, 255, 152, 0, 16, 22, 10, 8, 10, 4, 45, 255, 156, 0, 16, 22, 10, 8, 10, 4, 45, 255, 160, 0, 16, 22, 10, 8, 10, 4, 45, 255, 164, 0, 16, 22, 10, 8, 10, 4, 45, 255, 168, 0, 16, 22, 10, 8, 10, 4, 45, 255, 172, 0, 16, 22, 10, 8, 10, 4, 45, 255, 176, 0, 16, 22, 10, 8, 10, 4, 45, 255, 180, 0, 16, 22, 10, 8, 10, 4, 45, 255, 184, 0, 16, 22, 10, 8, 10, 4, 45, 255, 188, 0, 16, 22, 10, 8, 10, 4, 45, 255, 192, 0, 16, 22, 10, 8, 10, 4, 45, 255, 196, 0, 16, 22, 10, 8, 10, 4, 45, 255, 200, 0, 16, 22, 10, 8, 10, 4, 45, 255, 204, 0, 16, 22, 10, 8, 10, 4, 45, 255, 208, 0, 16, 22, 10, 8, 10, 4, 45, 255, 212, 0, 16, 22, 10, 8, 10, 4, 45, 255, 216, 0, 16, 22, 10, 8, 10, 4, 45, 255, 220, 0, 16, 22, 10, 8, 10, 4, 45, 255, 224, 0, 16, 22, 10, 8, 10, 4, 45, 255, 228, 0, 16, 22, 10, 8, 10, 4, 45, 255, 232, 0, 16, 22, 10, 8, 10, 4, 45, 255, 236, 0, 16, 22, 10, 8, 10, 4, 45, 255, 240, 0, 16, 22, 10, 8, 10, 4, 45, 255, 244, 0, 16, 22, 10, 8, 10, 4, 45, 255, 248, 0, 16, 22, 10, 8, 10, 4, 47, 92, 0, 0, 16, 14, 10, 8, 10, 4, 47, 96, 0, 0, 16, 11, 10, 8, 10, 4, 49, 4, 0, 0, 16, 14, 10, 8, 10, 4, 49, 51, 0, 0, 16, 16, 10, 8, 10, 4, 49, 52, 0, 0, 16, 14, 10, 8, 10, 4, 49, 64, 0, 0, 16, 11, 10, 8, 10, 4, 49, 112, 0, 0, 16, 13, 10, 8, 10, 4, 49, 120, 0, 0, 16, 14, 10, 8, 10, 4, 49, 128, 0, 0, 16, 24, 10, 8, 10, 4, 49, 128, 2, 0, 16, 23, 10, 8, 10, 4, 49, 128, 4, 0, 16, 22, 10, 8, 10, 4, 49, 140, 0, 0, 16, 15, 10, 8, 10, 4, 49, 152, 0, 0, 16, 14, 10, 8, 10, 4, 49, 208, 0, 0, 16, 15, 10, 8, 10, 4, 49, 210, 0, 0, 16, 15, 10, 8, 10, 4, 49, 220, 0, 0, 16, 14, 10, 8, 10, 4, 49, 232, 0, 0, 16, 14, 10, 8, 10, 4, 49, 239, 0, 0, 16, 18, 10, 8, 10, 4, 49, 239, 192, 0, 16, 18, 10, 8, 10, 4, 49, 246, 224, 0, 16, 19, 10, 8, 10, 4, 52, 80, 0, 0, 16, 16, 10, 8, 10, 4, 52, 81, 0, 0, 16, 16, 10, 8, 10, 4, 52, 82, 0, 0, 16, 15, 10, 8, 10, 4, 54, 222, 0, 0, 16, 15, 10, 8, 10, 4, 58, 14, 0, 0, 16, 15, 10, 8, 10, 4, 58, 16, 0, 0, 16, 16, 10, 8, 10, 4, 58, 17, 0, 0, 16, 17, 10, 8, 10, 4, 58, 17, 128, 0, 16, 17, 10, 8, 10, 4, 58, 18, 0, 0, 16, 16, 10, 8, 10, 4, 58, 19, 0, 0, 16, 16, 10, 8, 10, 4, 58, 20, 0, 0, 16, 16, 10, 8, 10, 4, 58, 21, 0, 0, 16, 16, 10, 8, 10, 4, 58, 22, 0, 0, 16, 15, 10, 8, 10, 4, 58, 24, 0, 0, 16, 15, 10, 8, 10, 4, 58, 30, 0, 0, 16, 15, 10, 8, 10, 4, 58, 32, 0, 0, 16, 13, 10, 8, 10, 4, 58, 40, 0, 0, 16, 15, 10, 8, 10, 4, 58, 42, 0, 0, 16, 16, 10, 8, 10, 4, 58, 43, 0, 0, 16, 16, 10, 8, 10, 4, 58, 44, 0, 0, 16, 14, 10, 8, 10, 4, 58, 48, 0, 0, 16, 13, 10, 8, 10, 4, 58, 56, 0, 0, 16, 15, 10, 8, 10, 4, 58, 58, 0, 0, 16, 16, 10, 8, 10, 4, 58, 59, 0, 0, 16, 17, 10, 8, 10, 4, 58, 59, 128, 0, 16, 17, 10, 8, 10, 4, 58, 60, 0, 0, 16, 14, 10, 8, 10, 4, 58, 65, 232, 0, 16, 21, 10, 8, 10, 4, 58, 66, 0, 0, 16, 15, 10, 8, 10, 4, 58, 68, 128, 0, 16, 17, 10, 8, 10, 4, 58, 82, 0, 0, 16, 17, 10, 8, 10, 4, 58, 83, 0, 0, 16, 17, 10, 8, 10, 4, 58, 83, 128, 0, 16, 17, 10, 8, 10, 4, 58, 87, 64, 0, 16, 18, 10, 8, 10, 4, 58, 99, 128, 0, 16, 17, 10, 8, 10, 4, 58, 100, 0, 0, 16, 15, 10, 8, 10, 4, 58, 116, 0, 0, 16, 14, 10, 8, 10, 4, 58, 128, 0, 0, 16, 13, 10, 8, 10, 4, 58, 144, 0, 0, 16, 16, 10, 8, 10, 4, 58, 154, 0, 0, 16, 15, 10, 8, 10, 4, 58, 192, 0, 0, 16, 15, 10, 8, 10, 4, 58, 194, 0, 0, 16, 15, 10, 8, 10, 4, 58, 196, 0, 0, 16, 15, 10, 8, 10, 4, 58, 198, 0, 0, 16, 15, 10, 8, 10, 4, 58, 200, 0, 0, 16, 13, 10, 8, 10, 4, 58, 208, 0, 0, 16, 12, 10, 8, 10, 4, 58, 240, 0, 0, 16, 15, 10, 8, 10, 4, 58, 242, 0, 0, 16, 15, 10, 8, 10, 4, 58, 244, 0, 0, 16, 15, 10, 8, 10, 4, 58, 246, 0, 0, 16, 15, 10, 8, 10, 4, 58, 248, 0, 0, 16, 13, 10, 8, 10, 4, 59, 32, 0, 0, 16, 13, 10, 8, 10, 4, 59, 40, 0, 0, 16, 15, 10, 8, 10, 4, 59, 42, 0, 0, 16, 16, 10, 8, 10, 4, 59, 43, 0, 0, 16, 16, 10, 8, 10, 4, 59, 44, 0, 0, 16, 14, 10, 8, 10, 4, 59, 48, 0, 0, 16, 16, 10, 8, 10, 4, 59, 49, 0, 0, 16, 17, 10, 8, 10, 4, 59, 49, 128, 0, 16, 17, 10, 8, 10, 4, 59, 50, 0, 0, 16, 16, 10, 8, 10, 4, 59, 51, 0, 0, 16, 17, 10, 8, 10, 4, 59, 51, 128, 0, 16, 17, 10, 8, 10, 4, 59, 52, 0, 0, 16, 14, 10, 8, 10, 4, 59, 56, 0, 0, 16, 14, 10, 8, 10, 4, 59, 60, 0, 0, 16, 15, 10, 8, 10, 4, 59, 62, 0, 0, 16, 15, 10, 8, 10, 4, 59, 64, 0, 0, 16, 14, 10, 8, 10, 4, 59, 68, 0, 0, 16, 14, 10, 8, 10, 4, 59, 72, 0, 0, 16, 15, 10, 8, 10, 4, 59, 74, 0, 0, 16, 15, 10, 8, 10, 4, 59, 76, 0, 0, 16, 16, 10, 8, 10, 4, 59, 77, 0, 0, 16, 16, 10, 8, 10, 4, 59, 78, 0, 0, 16, 15, 10, 8, 10, 4, 59, 80, 0, 0, 16, 15, 10, 8, 10, 4, 59, 82, 0, 0, 16, 15, 10, 8, 10, 4, 59, 107, 0, 0, 16, 17, 10, 8, 10, 4, 59, 107, 128, 0, 16, 17, 10, 8, 10, 4, 59, 108, 0, 0, 16, 15, 10, 8, 10, 4, 59, 110, 0, 0, 16, 15, 10, 8, 10, 4, 59, 151, 0, 0, 16, 17, 10, 8, 10, 4, 59, 152, 16, 0, 16, 22, 10, 8, 10, 4, 59, 152, 20, 0, 16, 22, 10, 8, 10, 4, 59, 152, 24, 0, 16, 22, 10, 8, 10, 4, 59, 152, 28, 0, 16, 22, 10, 8, 10, 4, 59, 152, 32, 0, 16, 22, 10, 8, 10, 4, 59, 152, 36, 0, 16, 22, 10, 8, 10, 4, 59, 152, 64, 0, 16, 22, 10, 8, 10, 4, 59, 152, 68, 0, 16, 22, 10, 8, 10, 4, 59, 152, 72, 0, 16, 22, 10, 8, 10, 4, 59, 152, 76, 0, 16, 22, 10, 8, 10, 4, 59, 152, 112, 0, 16, 22, 10, 8, 10, 4, 59, 152, 116, 0, 16, 22, 10, 8, 10, 4, 59, 153, 4, 0, 16, 22, 10, 8, 10, 4, 59, 153, 32, 0, 16, 22, 10, 8, 10, 4, 59, 153, 60, 0, 16, 22, 10, 8, 10, 4, 59, 153, 64, 0, 16, 22, 10, 8, 10, 4, 59, 153, 68, 0, 16, 22, 10, 8, 10, 4, 59, 153, 72, 0, 16, 22, 10, 8, 10, 4, 59, 153, 92, 0, 16, 22, 10, 8, 10, 4, 59, 153, 116, 0, 16, 22, 10, 8, 10, 4, 59, 153, 136, 0, 16, 22, 10, 8, 10, 4, 59, 153, 152, 0, 16, 22, 10, 8, 10, 4, 59, 153, 156, 0, 16, 22, 10, 8, 10, 4, 59, 153, 164, 0, 16, 22, 10, 8, 10, 4, 59, 153, 168, 0, 16, 22, 10, 8, 10, 4, 59, 153, 172, 0, 16, 22, 10, 8, 10, 4, 59, 153, 176, 0, 16, 22, 10, 8, 10, 4, 59, 153, 180, 0, 16, 22, 10, 8, 10, 4, 59, 153, 184, 0, 16, 22, 10, 8, 10, 4, 59, 153, 188, 0, 16, 22, 10, 8, 10, 4, 59, 153, 192, 0, 16, 22, 10, 8, 10, 4, 59, 155, 0, 0, 16, 16, 10, 8, 10, 4, 59, 172, 0, 0, 16, 15, 10, 8, 10, 4, 59, 174, 0, 0, 16, 15, 10, 8, 10, 4, 59, 191, 0, 0, 16, 17, 10, 8, 10, 4, 59, 191, 240, 0, 16, 20, 10, 8, 10, 4, 59, 192, 0, 0, 16, 10, 10, 8, 10, 4, 60, 0, 0, 0, 16, 13, 10, 8, 10, 4, 60, 8, 0, 0, 16, 15, 10, 8, 10, 4, 60, 10, 0, 0, 16, 16, 10, 8, 10, 4, 60, 11, 0, 0, 16, 16, 10, 8, 10, 4, 60, 12, 0, 0, 16, 16, 10, 8, 10, 4, 60, 13, 0, 0, 16, 18, 10, 8, 10, 4, 60, 13, 64, 0, 16, 18, 10, 8, 10, 4, 60, 13, 128, 0, 16, 17, 10, 8, 10, 4, 60, 14, 0, 0, 16, 15, 10, 8, 10, 4, 60, 16, 0, 0, 16, 13, 10, 8, 10, 4, 60, 24, 0, 0, 16, 14, 10, 8, 10, 4, 60, 28, 0, 0, 16, 15, 10, 8, 10, 4, 60, 30, 0, 0, 16, 16, 10, 8, 10, 4, 60, 31, 0, 0, 16, 16, 10, 8, 10, 4, 60, 55, 0, 0, 16, 16, 10, 8, 10, 4, 60, 63, 0, 0, 16, 16, 10, 8, 10, 4, 60, 160, 0, 0, 16, 15, 10, 8, 10, 4, 60, 162, 0, 0, 16, 15, 10, 8, 10, 4, 60, 164, 0, 0, 16, 15, 10, 8, 10, 4, 60, 166, 0, 0, 16, 15, 10, 8, 10, 4, 60, 168, 0, 0, 16, 13, 10, 8, 10, 4, 60, 176, 0, 0, 16, 12, 10, 8, 10, 4, 60, 194, 0, 0, 16, 15, 10, 8, 10, 4, 60, 200, 0, 0, 16, 14, 10, 8, 10, 4, 60, 204, 0, 0, 16, 16, 10, 8, 10, 4, 60, 205, 0, 0, 16, 16, 10, 8, 10, 4, 60, 206, 0, 0, 16, 15, 10, 8, 10, 4, 60, 208, 0, 0, 16, 13, 10, 8, 10, 4, 60, 216, 0, 0, 16, 15, 10, 8, 10, 4, 60, 218, 0, 0, 16, 15, 10, 8, 10, 4, 60, 220, 0, 0, 16, 14, 10, 8, 10, 4, 60, 232, 0, 0, 16, 15, 10, 8, 10, 4, 60, 235, 0, 0, 16, 16, 10, 8, 10, 4, 60, 245, 128, 0, 16, 17, 10, 8, 10, 4, 60, 247, 0, 0, 16, 16, 10, 8, 10, 4, 60, 252, 0, 0, 16, 16, 10, 8, 10, 4, 60, 253, 128, 0, 16, 17, 10, 8, 10, 4, 60, 255, 0, 0, 16, 16, 10, 8, 10, 4, 61, 4, 80, 0, 16, 22, 10, 8, 10, 4, 61, 4, 84, 0, 16, 22, 10, 8, 10, 4, 61, 4, 88, 0, 16, 21, 10, 8, 10, 4, 61, 4, 176, 0, 16, 20, 10, 8, 10, 4, 61, 8, 160, 0, 16, 20, 10, 8, 10, 4, 61, 14, 212, 0, 16, 22, 10, 8, 10, 4, 61, 14, 216, 0, 16, 22, 10, 8, 10, 4, 61, 14, 220, 0, 16, 22, 10, 8, 10, 4, 61, 14, 240, 0, 16, 22, 10, 8, 10, 4, 61, 14, 244, 0, 16, 22, 10, 8, 10, 4, 61, 28, 0, 0, 16, 20, 10, 8, 10, 4, 61, 28, 16, 0, 16, 20, 10, 8, 10, 4, 61, 28, 32, 0, 16, 19, 10, 8, 10, 4, 61, 28, 64, 0, 16, 18, 10, 8, 10, 4, 61, 29, 128, 0, 16, 18, 10, 8, 10, 4, 61, 29, 192, 0, 16, 19, 10, 8, 10, 4, 61, 29, 224, 0, 16, 20, 10, 8, 10, 4, 61, 29, 240, 0, 16, 20, 10, 8, 10, 4, 61, 45, 128, 0, 16, 18, 10, 8, 10, 4, 61, 45, 224, 0, 16, 20, 10, 8, 10, 4, 61, 47, 128, 0, 16, 18, 10, 8, 10, 4, 61, 48, 0, 0, 16, 14, 10, 8, 10, 4, 61, 52, 0, 0, 16, 15, 10, 8, 10, 4, 61, 54, 0, 0, 16, 16, 10, 8, 10, 4, 61, 55, 0, 0, 16, 16, 10, 8, 10, 4, 61, 87, 192, 0, 16, 18, 10, 8, 10, 4, 61, 128, 0, 0, 16, 15, 10, 8, 10, 4, 61, 130, 0, 0, 16, 15, 10, 8, 10, 4, 61, 132, 0, 0, 16, 16, 10, 8, 10, 4, 61, 133, 0, 0, 16, 17, 10, 8, 10, 4, 61, 133, 128, 0, 16, 17, 10, 8, 10, 4, 61, 134, 0, 0, 16, 18, 10, 8, 10, 4, 61, 134, 64, 0, 16, 19, 10, 8, 10, 4, 61, 134, 96, 0, 16, 19, 10, 8, 10, 4, 61, 134, 128, 0, 16, 18, 10, 8, 10, 4, 61, 134, 192, 0, 16, 18, 10, 8, 10, 4, 61, 135, 0, 0, 16, 16, 10, 8, 10, 4, 61, 136, 0, 0, 16, 18, 10, 8, 10, 4, 61, 136, 64, 0, 16, 18, 10, 8, 10, 4, 61, 136, 128, 0, 16, 17, 10, 8, 10, 4, 61, 137, 0, 0, 16, 17, 10, 8, 10, 4, 61, 137, 128, 0, 16, 17, 10, 8, 10, 4, 61, 138, 0, 0, 16, 18, 10, 8, 10, 4, 61, 138, 64, 0, 16, 18, 10, 8, 10, 4, 61, 138, 128, 0, 16, 18, 10, 8, 10, 4, 61, 138, 192, 0, 16, 18, 10, 8, 10, 4, 61, 139, 0, 0, 16, 17, 10, 8, 10, 4, 61, 139, 128, 0, 16, 18, 10, 8, 10, 4, 61, 139, 192, 0, 16, 18, 10, 8, 10, 4, 61, 140, 0, 0, 16, 14, 10, 8, 10, 4, 61, 144, 0, 0, 16, 14, 10, 8, 10, 4, 61, 148, 0, 0, 16, 15, 10, 8, 10, 4, 61, 150, 0, 0, 16, 15, 10, 8, 10, 4, 61, 152, 0, 0, 16, 16, 10, 8, 10, 4, 61, 153, 0, 0, 16, 16, 10, 8, 10, 4, 61, 154, 0, 0, 16, 15, 10, 8, 10, 4, 61, 156, 0, 0, 16, 16, 10, 8, 10, 4, 61, 157, 0, 0, 16, 16, 10, 8, 10, 4, 61, 158, 0, 0, 16, 17, 10, 8, 10, 4, 61, 158, 128, 0, 16, 17, 10, 8, 10, 4, 61, 159, 0, 0, 16, 18, 10, 8, 10, 4, 61, 159, 64, 0, 16, 18, 10, 8, 10, 4, 61, 159, 128, 0, 16, 17, 10, 8, 10, 4, 61, 160, 0, 0, 16, 16, 10, 8, 10, 4, 61, 161, 0, 0, 16, 18, 10, 8, 10, 4, 61, 161, 64, 0, 16, 18, 10, 8, 10, 4, 61, 161, 128, 0, 16, 17, 10, 8, 10, 4, 61, 162, 0, 0, 16, 16, 10, 8, 10, 4, 61, 163, 0, 0, 16, 16, 10, 8, 10, 4, 61, 164, 0, 0, 16, 16, 10, 8, 10, 4, 61, 165, 0, 0, 16, 16, 10, 8, 10, 4, 61, 166, 0, 0, 16, 16, 10, 8, 10, 4, 61, 167, 0, 0, 16, 16, 10, 8, 10, 4, 61, 168, 0, 0, 16, 16, 10, 8, 10, 4, 61, 169, 0, 0, 16, 16, 10, 8, 10, 4, 61, 170, 0, 0, 16, 15, 10, 8, 10, 4, 61, 172, 0, 0, 16, 14, 10, 8, 10, 4, 61, 176, 0, 0, 16, 16, 10, 8, 10, 4, 61, 177, 0, 0, 16, 16, 10, 8, 10, 4, 61, 178, 0, 0, 16, 16, 10, 8, 10, 4, 61, 179, 0, 0, 16, 16, 10, 8, 10, 4, 61, 180, 0, 0, 16, 17, 10, 8, 10, 4, 61, 180, 128, 0, 16, 17, 10, 8, 10, 4, 61, 181, 0, 0, 16, 16, 10, 8, 10, 4, 61, 182, 0, 0, 16, 16, 10, 8, 10, 4, 61, 183, 0, 0, 16, 16, 10, 8, 10, 4, 61, 184, 0, 0, 16, 14, 10, 8, 10, 4, 61, 188, 0, 0, 16, 16, 10, 8, 10, 4, 61, 189, 0, 0, 16, 17, 10, 8, 10, 4, 61, 189, 128, 0, 16, 17, 10, 8, 10, 4, 61, 190, 0, 0, 16, 15, 10, 8, 10, 4, 61, 232, 0, 0, 16, 14, 10, 8, 10, 4, 61, 236, 0, 0, 16, 15, 10, 8, 10, 4, 61, 240, 0, 0, 16, 14, 10, 8, 10, 4, 62, 234, 0, 0, 16, 16, 10, 8, 10, 4, 94, 191, 0, 0, 16, 17, 10, 8, 10, 4, 101, 0, 0, 0, 16, 22, 10, 8, 10, 4, 101, 1, 0, 0, 16, 22, 10, 8, 10, 4, 101, 2, 172, 0, 16, 22, 10, 8, 10, 4, 101, 4, 0, 0, 16, 14, 10, 8, 10, 4, 101, 16, 0, 0, 16, 12, 10, 8, 10, 4, 101, 32, 0, 0, 16, 14, 10, 8, 10, 4, 101, 36, 0, 0, 16, 17, 10, 8, 10, 4, 101, 36, 128, 0, 16, 17, 10, 8, 10, 4, 101, 37, 0, 0, 16, 16, 10, 8, 10, 4, 101, 38, 0, 0, 16, 15, 10, 8, 10, 4, 101, 40, 0, 0, 16, 13, 10, 8, 10, 4, 101, 48, 0, 0, 16, 15, 10, 8, 10, 4, 101, 50, 8, 0, 16, 22, 10, 8, 10, 4, 101, 50, 12, 0, 16, 22, 10, 8, 10, 4, 101, 50, 56, 0, 16, 22, 10, 8, 10, 4, 101, 52, 0, 0, 16, 16, 10, 8, 10, 4, 101, 53, 100, 0, 16, 22, 10, 8, 10, 4, 101, 54, 0, 0, 16, 16, 10, 8, 10, 4, 101, 55, 224, 0, 16, 21, 10, 8, 10, 4, 101, 64, 0, 0, 16, 13, 10, 8, 10, 4, 101, 72, 0, 0, 16, 14, 10, 8, 10, 4, 101, 76, 0, 0, 16, 15, 10, 8, 10, 4, 101, 78, 0, 0, 16, 22, 10, 8, 10, 4, 101, 78, 32, 0, 16, 19, 10, 8, 10, 4, 101, 80, 0, 0, 16, 12, 10, 8, 10, 4, 101, 96, 0, 0, 16, 21, 10, 8, 10, 4, 101, 96, 8, 0, 16, 22, 10, 8, 10, 4, 101, 96, 16, 0, 16, 20, 10, 8, 10, 4, 101, 96, 128, 0, 16, 17, 10, 8, 10, 4, 101, 99, 96, 0, 16, 19, 10, 8, 10, 4, 101, 101, 64, 0, 16, 19, 10, 8, 10, 4, 101, 101, 100, 0, 16, 24, 10, 8, 10, 4, 101, 101, 102, 0, 16, 23, 10, 8, 10, 4, 101, 101, 104, 0, 16, 21, 10, 8, 10, 4, 101, 101, 112, 0, 16, 20, 10, 8, 10, 4, 101, 102, 64, 0, 16, 19, 10, 8, 10, 4, 101, 102, 100, 0, 16, 23, 10, 8, 10, 4, 101, 102, 102, 0, 16, 24, 10, 8, 10, 4, 101, 102, 104, 0, 16, 21, 10, 8, 10, 4, 101, 102, 112, 0, 16, 20, 10, 8, 10, 4, 101, 104, 0, 0, 16, 14, 10, 8, 10, 4, 101, 110, 64, 0, 16, 19, 10, 8, 10, 4, 101, 110, 96, 0, 16, 20, 10, 8, 10, 4, 101, 110, 116, 0, 16, 22, 10, 8, 10, 4, 101, 110, 120, 0, 16, 21, 10, 8, 10, 4, 101, 120, 0, 0, 16, 14, 10, 8, 10, 4, 101, 124, 0, 0, 16, 15, 10, 8, 10, 4, 101, 126, 0, 0, 16, 16, 10, 8, 10, 4, 101, 128, 0, 0, 16, 22, 10, 8, 10, 4, 101, 128, 8, 0, 16, 21, 10, 8, 10, 4, 101, 128, 16, 0, 16, 20, 10, 8, 10, 4, 101, 128, 32, 0, 16, 19, 10, 8, 10, 4, 101, 129, 0, 0, 16, 16, 10, 8, 10, 4, 101, 130, 0, 0, 16, 15, 10, 8, 10, 4, 101, 132, 0, 0, 16, 14, 10, 8, 10, 4, 101, 144, 0, 0, 16, 12, 10, 8, 10, 4, 101, 192, 0, 0, 16, 14, 10, 8, 10, 4, 101, 196, 0, 0, 16, 14, 10, 8, 10, 4, 101, 200, 0, 0, 16, 15, 10, 8, 10, 4, 101, 203, 128, 0, 16, 19, 10, 8, 10, 4, 101, 203, 160, 0, 16, 21, 10, 8, 10, 4, 101, 203, 172, 0, 16, 22, 10, 8, 10, 4, 101, 203, 176, 0, 16, 20, 10, 8, 10, 4, 101, 204, 0, 0, 16, 14, 10, 8, 10, 4, 101, 224, 0, 0, 16, 13, 10, 8, 10, 4, 101, 232, 0, 0, 16, 15, 10, 8, 10, 4, 101, 234, 64, 0, 16, 21, 10, 8, 10, 4, 101, 234, 76, 0, 16, 22, 10, 8, 10, 4, 101, 234, 80, 0, 16, 20, 10, 8, 10, 4, 101, 234, 96, 0, 16, 19, 10, 8, 10, 4, 101, 236, 0, 0, 16, 14, 10, 8, 10, 4, 101, 240, 0, 0, 16, 14, 10, 8, 10, 4, 101, 244, 0, 0, 16, 14, 10, 8, 10, 4, 101, 248, 0, 0, 16, 15, 10, 8, 10, 4, 101, 251, 0, 0, 16, 22, 10, 8, 10, 4, 101, 251, 8, 0, 16, 21, 10, 8, 10, 4, 101, 251, 16, 0, 16, 20, 10, 8, 10, 4, 101, 251, 32, 0, 16, 19, 10, 8, 10, 4, 101, 251, 64, 0, 16, 18, 10, 8, 10, 4, 101, 251, 128, 0, 16, 17, 10, 8, 10, 4, 101, 252, 0, 0, 16, 15, 10, 8, 10, 4, 101, 254, 0, 0, 16, 16, 10, 8, 10, 4, 103, 1, 8, 0, 16, 22, 10, 8, 10, 4, 103, 1, 20, 0, 16, 22, 10, 8, 10, 4, 103, 1, 24, 0, 16, 22, 10, 8, 10, 4, 103, 1, 72, 0, 16, 22, 10, 8, 10, 4, 103, 1, 88, 0, 16, 22, 10, 8, 10, 4, 103, 1, 168, 0, 16, 22, 10, 8, 10, 4, 103, 2, 108, 0, 16, 22, 10, 8, 10, 4, 103, 2, 156, 0, 16, 22, 10, 8, 10, 4, 103, 2, 164, 0, 16, 22, 10, 8, 10, 4, 103, 2, 200, 0, 16, 22, 10, 8, 10, 4, 103, 2, 204, 0, 16, 22, 10, 8, 10, 4, 103, 2, 208, 0, 16, 22, 10, 8, 10, 4, 103, 2, 212, 0, 16, 22, 10, 8, 10, 4, 103, 3, 84, 0, 16, 22, 10, 8, 10, 4, 103, 3, 88, 0, 16, 22, 10, 8, 10, 4, 103, 3, 92, 0, 16, 22, 10, 8, 10, 4, 103, 3, 96, 0, 16, 22, 10, 8, 10, 4, 103, 3, 100, 0, 16, 22, 10, 8, 10, 4, 103, 3, 104, 0, 16, 22, 10, 8, 10, 4, 103, 3, 108, 0, 16, 22, 10, 8, 10, 4, 103, 3, 112, 0, 16, 22, 10, 8, 10, 4, 103, 3, 116, 0, 16, 22, 10, 8, 10, 4, 103, 3, 120, 0, 16, 22, 10, 8, 10, 4, 103, 3, 124, 0, 16, 22, 10, 8, 10, 4, 103, 3, 128, 0, 16, 22, 10, 8, 10, 4, 103, 3, 132, 0, 16, 22, 10, 8, 10, 4, 103, 3, 136, 0, 16, 22, 10, 8, 10, 4, 103, 3, 140, 0, 16, 22, 10, 8, 10, 4, 103, 3, 148, 0, 16, 22, 10, 8, 10, 4, 103, 3, 152, 0, 16, 22, 10, 8, 10, 4, 103, 3, 156, 0, 16, 22, 10, 8, 10, 4, 103, 4, 56, 0, 16, 22, 10, 8, 10, 4, 103, 4, 168, 0, 16, 22, 10, 8, 10, 4, 103, 4, 184, 0, 16, 22, 10, 8, 10, 4, 103, 4, 224, 0, 16, 22, 10, 8, 10, 4, 103, 5, 36, 0, 16, 22, 10, 8, 10, 4, 103, 5, 52, 0, 16, 22, 10, 8, 10, 4, 103, 5, 56, 0, 16, 22, 10, 8, 10, 4, 103, 5, 152, 0, 16, 22, 10, 8, 10, 4, 103, 5, 168, 0, 16, 22, 10, 8, 10, 4, 103, 5, 192, 0, 16, 22, 10, 8, 10, 4, 103, 5, 252, 0, 16, 22, 10, 8, 10, 4, 103, 6, 76, 0, 16, 22, 10, 8, 10, 4, 103, 6, 108, 0, 16, 22, 10, 8, 10, 4, 103, 6, 220, 0, 16, 22, 10, 8, 10, 4, 103, 6, 228, 0, 16, 22, 10, 8, 10, 4, 103, 7, 4, 0, 16, 22, 10, 8, 10, 4, 103, 7, 28, 0, 16, 22, 10, 8, 10, 4, 103, 7, 140, 0, 16, 22, 10, 8, 10, 4, 103, 7, 212, 0, 16, 22, 10, 8, 10, 4, 103, 7, 216, 0, 16, 22, 10, 8, 10, 4, 103, 7, 220, 0, 16, 22, 10, 8, 10, 4, 103, 8, 0, 0, 16, 22, 10, 8, 10, 4, 103, 8, 4, 0, 16, 22, 10, 8, 10, 4, 103, 8, 8, 0, 16, 22, 10, 8, 10, 4, 103, 8, 32, 0, 16, 22, 10, 8, 10, 4, 103, 8, 52, 0, 16, 22, 10, 8, 10, 4, 103, 8, 68, 0, 16, 22, 10, 8, 10, 4, 103, 8, 108, 0, 16, 22, 10, 8, 10, 4, 103, 8, 156, 0, 16, 22, 10, 8, 10, 4, 103, 8, 200, 0, 16, 22, 10, 8, 10, 4, 103, 8, 204, 0, 16, 22, 10, 8, 10, 4, 103, 8, 220, 0, 16, 22, 10, 8, 10, 4, 103, 9, 8, 0, 16, 22, 10, 8, 10, 4, 103, 9, 24, 0, 16, 22, 10, 8, 10, 4, 103, 9, 108, 0, 16, 22, 10, 8, 10, 4, 103, 9, 152, 0, 16, 22, 10, 8, 10, 4, 103, 9, 192, 0, 16, 22, 10, 8, 10, 4, 103, 9, 248, 0, 16, 22, 10, 8, 10, 4, 103, 9, 252, 0, 16, 22, 10, 8, 10, 4, 103, 10, 0, 0, 16, 22, 10, 8, 10, 4, 103, 10, 16, 0, 16, 22, 10, 8, 10, 4, 103, 10, 84, 0, 16, 22, 10, 8, 10, 4, 103, 10, 140, 0, 16, 22, 10, 8, 10, 4, 103, 11, 16, 0, 16, 22, 10, 8, 10, 4, 103, 11, 168, 0, 16, 22, 10, 8, 10, 4, 103, 11, 180, 0, 16, 22, 10, 8, 10, 4, 103, 12, 32, 0, 16, 22, 10, 8, 10, 4, 103, 12, 68, 0, 16, 22, 10, 8, 10, 4, 103, 12, 92, 0, 16, 22, 10, 8, 10, 4, 103, 12, 136, 0, 16, 22, 10, 8, 10, 4, 103, 12, 184, 0, 16, 22, 10, 8, 10, 4, 103, 12, 232, 0, 16, 22, 10, 8, 10, 4, 103, 13, 12, 0, 16, 22, 10, 8, 10, 4, 103, 13, 72, 0, 16, 23, 10, 8, 10, 4, 103, 13, 124, 0, 16, 22, 10, 8, 10, 4, 103, 13, 144, 0, 16, 22, 10, 8, 10, 4, 103, 13, 196, 0, 16, 22, 10, 8, 10, 4, 103, 13, 220, 0, 16, 22, 10, 8, 10, 4, 103, 13, 244, 0, 16, 22, 10, 8, 10, 4, 103, 14, 32, 0, 16, 22, 10, 8, 10, 4, 103, 14, 84, 0, 16, 22, 10, 8, 10, 4, 103, 14, 100, 0, 16, 22, 10, 8, 10, 4, 103, 14, 112, 0, 16, 22, 10, 8, 10, 4, 103, 14, 132, 0, 16, 22, 10, 8, 10, 4, 103, 14, 136, 0, 16, 22, 10, 8, 10, 4, 103, 14, 156, 0, 16, 22, 10, 8, 10, 4, 103, 14, 240, 0, 16, 22, 10, 8, 10, 4, 103, 15, 4, 0, 16, 22, 10, 8, 10, 4, 103, 15, 8, 0, 16, 22, 10, 8, 10, 4, 103, 15, 16, 0, 16, 22, 10, 8, 10, 4, 103, 15, 96, 0, 16, 22, 10, 8, 10, 4, 103, 15, 200, 0, 16, 22, 10, 8, 10, 4, 103, 16, 52, 0, 16, 22, 10, 8, 10, 4, 103, 16, 80, 0, 16, 22, 10, 8, 10, 4, 103, 16, 84, 0, 16, 22, 10, 8, 10, 4, 103, 16, 88, 0, 16, 22, 10, 8, 10, 4, 103, 16, 108, 0, 16, 22, 10, 8, 10, 4, 103, 16, 124, 0, 16, 22, 10, 8, 10, 4, 103, 17, 40, 0, 16, 22, 10, 8, 10, 4, 103, 17, 64, 0, 16, 22, 10, 8, 10, 4, 103, 17, 120, 0, 16, 22, 10, 8, 10, 4, 103, 17, 136, 0, 16, 22, 10, 8, 10, 4, 103, 17, 160, 0, 16, 22, 10, 8, 10, 4, 103, 17, 204, 0, 16, 22, 10, 8, 10, 4, 103, 17, 228, 0, 16, 22, 10, 8, 10, 4, 103, 18, 192, 0, 16, 22, 10, 8, 10, 4, 103, 18, 208, 0, 16, 22, 10, 8, 10, 4, 103, 18, 212, 0, 16, 22, 10, 8, 10, 4, 103, 18, 224, 0, 16, 22, 10, 8, 10, 4, 103, 19, 0, 0, 16, 22, 10, 8, 10, 4, 103, 19, 12, 0, 16, 22, 10, 8, 10, 4, 103, 19, 40, 0, 16, 22, 10, 8, 10, 4, 103, 19, 44, 0, 16, 22, 10, 8, 10, 4, 103, 19, 64, 0, 16, 22, 10, 8, 10, 4, 103, 19, 68, 0, 16, 22, 10, 8, 10, 4, 103, 19, 72, 0, 16, 22, 10, 8, 10, 4, 103, 19, 232, 0, 16, 22, 10, 8, 10, 4, 103, 20, 12, 0, 16, 22, 10, 8, 10, 4, 103, 20, 32, 0, 16, 22, 10, 8, 10, 4, 103, 20, 44, 0, 16, 22, 10, 8, 10, 4, 103, 20, 68, 0, 16, 22, 10, 8, 10, 4, 103, 20, 112, 0, 16, 22, 10, 8, 10, 4, 103, 20, 128, 0, 16, 22, 10, 8, 10, 4, 103, 20, 160, 0, 16, 22, 10, 8, 10, 4, 103, 20, 248, 0, 16, 22, 10, 8, 10, 4, 103, 21, 112, 0, 16, 22, 10, 8, 10, 4, 103, 21, 116, 0, 16, 22, 10, 8, 10, 4, 103, 21, 136, 0, 16, 22, 10, 8, 10, 4, 103, 21, 140, 0, 16, 22, 10, 8, 10, 4, 103, 21, 176, 0, 16, 22, 10, 8, 10, 4, 103, 21, 208, 0, 16, 22, 10, 8, 10, 4, 103, 21, 240, 0, 16, 22, 10, 8, 10, 4, 103, 22, 0, 0, 16, 22, 10, 8, 10, 4, 103, 22, 4, 0, 16, 22, 10, 8, 10, 4, 103, 22, 8, 0, 16, 22, 10, 8, 10, 4, 103, 22, 12, 0, 16, 22, 10, 8, 10, 4, 103, 22, 16, 0, 16, 22, 10, 8, 10, 4, 103, 22, 20, 0, 16, 22, 10, 8, 10, 4, 103, 22, 24, 0, 16, 22, 10, 8, 10, 4, 103, 22, 28, 0, 16, 22, 10, 8, 10, 4, 103, 22, 32, 0, 16, 22, 10, 8, 10, 4, 103, 22, 36, 0, 16, 22, 10, 8, 10, 4, 103, 22, 40, 0, 16, 22, 10, 8, 10, 4, 103, 22, 44, 0, 16, 22, 10, 8, 10, 4, 103, 22, 48, 0, 16, 22, 10, 8, 10, 4, 103, 22, 52, 0, 16, 22, 10, 8, 10, 4, 103, 22, 56, 0, 16, 22, 10, 8, 10, 4, 103, 22, 60, 0, 16, 22, 10, 8, 10, 4, 103, 22, 64, 0, 16, 22, 10, 8, 10, 4, 103, 22, 68, 0, 16, 22, 10, 8, 10, 4, 103, 22, 72, 0, 16, 22, 10, 8, 10, 4, 103, 22, 76, 0, 16, 22, 10, 8, 10, 4, 103, 22, 80, 0, 16, 22, 10, 8, 10, 4, 103, 22, 84, 0, 16, 22, 10, 8, 10, 4, 103, 22, 88, 0, 16, 22, 10, 8, 10, 4, 103, 22, 92, 0, 16, 22, 10, 8, 10, 4, 103, 22, 100, 0, 16, 22, 10, 8, 10, 4, 103, 22, 104, 0, 16, 22, 10, 8, 10, 4, 103, 22, 108, 0, 16, 22, 10, 8, 10, 4, 103, 22, 112, 0, 16, 22, 10, 8, 10, 4, 103, 22, 116, 0, 16, 22, 10, 8, 10, 4, 103, 22, 120, 0, 16, 22, 10, 8, 10, 4, 103, 22, 124, 0, 16, 22, 10, 8, 10, 4, 103, 22, 188, 0, 16, 22, 10, 8, 10, 4, 103, 22, 228, 0, 16, 22, 10, 8, 10, 4, 103, 22, 252, 0, 16, 22, 10, 8, 10, 4, 103, 23, 8, 0, 16, 22, 10, 8, 10, 4, 103, 23, 56, 0, 16, 22, 10, 8, 10, 4, 103, 23, 160, 0, 16, 22, 10, 8, 10, 4, 103, 23, 164, 0, 16, 22, 10, 8, 10, 4, 103, 23, 176, 0, 16, 22, 10, 8, 10, 4, 103, 23, 228, 0, 16, 22, 10, 8, 10, 4, 103, 24, 24, 0, 16, 22, 10, 8, 10, 4, 103, 24, 116, 0, 16, 22, 10, 8, 10, 4, 103, 24, 128, 0, 16, 22, 10, 8, 10, 4, 103, 24, 144, 0, 16, 22, 10, 8, 10, 4, 103, 24, 176, 0, 16, 22, 10, 8, 10, 4, 103, 24, 184, 0, 16, 22, 10, 8, 10, 4, 103, 24, 220, 0, 16, 22, 10, 8, 10, 4, 103, 24, 228, 0, 16, 22, 10, 8, 10, 4, 103, 24, 248, 0, 16, 22, 10, 8, 10, 4, 103, 24, 252, 0, 16, 22, 10, 8, 10, 4, 103, 25, 8, 0, 16, 23, 10, 8, 10, 4, 103, 25, 20, 0, 16, 22, 10, 8, 10, 4, 103, 25, 24, 0, 16, 22, 10, 8, 10, 4, 103, 25, 28, 0, 16, 22, 10, 8, 10, 4, 103, 25, 32, 0, 16, 22, 10, 8, 10, 4, 103, 25, 36, 0, 16, 22, 10, 8, 10, 4, 103, 25, 40, 0, 16, 22, 10, 8, 10, 4, 103, 25, 48, 0, 16, 22, 10, 8, 10, 4, 103, 25, 64, 0, 16, 22, 10, 8, 10, 4, 103, 25, 68, 0, 16, 22, 10, 8, 10, 4, 103, 25, 148, 0, 16, 22, 10, 8, 10, 4, 103, 25, 156, 0, 16, 22, 10, 8, 10, 4, 103, 25, 216, 0, 16, 22, 10, 8, 10, 4, 103, 26, 0, 0, 16, 22, 10, 8, 10, 4, 103, 26, 64, 0, 16, 22, 10, 8, 10, 4, 103, 26, 76, 0, 16, 22, 10, 8, 10, 4, 103, 26, 116, 0, 16, 22, 10, 8, 10, 4, 103, 26, 132, 0, 16, 22, 10, 8, 10, 4, 103, 26, 156, 0, 16, 22, 10, 8, 10, 4, 103, 26, 160, 0, 16, 22, 10, 8, 10, 4, 103, 26, 228, 0, 16, 22, 10, 8, 10, 4, 103, 26, 240, 0, 16, 22, 10, 8, 10, 4, 103, 27, 4, 0, 16, 22, 10, 8, 10, 4, 103, 27, 12, 0, 16, 22, 10, 8, 10, 4, 103, 27, 24, 0, 16, 22, 10, 8, 10, 4, 103, 27, 56, 0, 16, 22, 10, 8, 10, 4, 103, 27, 96, 0, 16, 22, 10, 8, 10, 4, 103, 27, 184, 0, 16, 22, 10, 8, 10, 4, 103, 27, 208, 0, 16, 22, 10, 8, 10, 4, 103, 27, 212, 0, 16, 22, 10, 8, 10, 4, 103, 27, 240, 0, 16, 22, 10, 8, 10, 4, 103, 28, 4, 0, 16, 22, 10, 8, 10, 4, 103, 28, 8, 0, 16, 22, 10, 8, 10, 4, 103, 28, 184, 0, 16, 22, 10, 8, 10, 4, 103, 28, 204, 0, 16, 22, 10, 8, 10, 4, 103, 28, 212, 0, 16, 22, 10, 8, 10, 4, 103, 29, 16, 0, 16, 22, 10, 8, 10, 4, 103, 29, 128, 0, 16, 22, 10, 8, 10, 4, 103, 29, 132, 0, 16, 22, 10, 8, 10, 4, 103, 29, 136, 0, 16, 22, 10, 8, 10, 4, 103, 30, 20, 0, 16, 22, 10, 8, 10, 4, 103, 30, 96, 0, 16, 22, 10, 8, 10, 4, 103, 30, 148, 0, 16, 22, 10, 8, 10, 4, 103, 30, 200, 0, 16, 22, 10, 8, 10, 4, 103, 30, 228, 0, 16, 22, 10, 8, 10, 4, 103, 30, 236, 0, 16, 22, 10, 8, 10, 4, 103, 31, 0, 0, 16, 22, 10, 8, 10, 4, 103, 31, 48, 0, 16, 22, 10, 8, 10, 4, 103, 31, 52, 0, 16, 22, 10, 8, 10, 4, 103, 31, 56, 0, 16, 22, 10, 8, 10, 4, 103, 31, 60, 0, 16, 22, 10, 8, 10, 4, 103, 31, 64, 0, 16, 22, 10, 8, 10, 4, 103, 31, 68, 0, 16, 22, 10, 8, 10, 4, 103, 31, 148, 0, 16, 22, 10, 8, 10, 4, 103, 31, 160, 0, 16, 22, 10, 8, 10, 4, 103, 31, 168, 0, 16, 22, 10, 8, 10, 4, 103, 31, 200, 0, 16, 22, 10, 8, 10, 4, 103, 31, 236, 0, 16, 22, 10, 8, 10, 4, 103, 32, 0, 0, 16, 22, 10, 8, 10, 4, 103, 32, 4, 0, 16, 22, 10, 8, 10, 4, 103, 32, 8, 0, 16, 22, 10, 8, 10, 4, 103, 32, 12, 0, 16, 22, 10, 8, 10, 4, 103, 32, 16, 0, 16, 22, 10, 8, 10, 4, 103, 32, 20, 0, 16, 22, 10, 8, 10, 4, 103, 32, 24, 0, 16, 22, 10, 8, 10, 4, 103, 32, 28, 0, 16, 22, 10, 8, 10, 4, 103, 32, 32, 0, 16, 22, 10, 8, 10, 4, 103, 32, 36, 0, 16, 22, 10, 8, 10, 4, 103, 32, 40, 0, 16, 22, 10, 8, 10, 4, 103, 32, 44, 0, 16, 22, 10, 8, 10, 4, 103, 32, 48, 0, 16, 22, 10, 8, 10, 4, 103, 32, 52, 0, 16, 22, 10, 8, 10, 4, 103, 32, 56, 0, 16, 22, 10, 8, 10, 4, 103, 32, 60, 0, 16, 22, 10, 8, 10, 4, 103, 32, 64, 0, 16, 22, 10, 8, 10, 4, 103, 32, 68, 0, 16, 22, 10, 8, 10, 4, 103, 32, 72, 0, 16, 22, 10, 8, 10, 4, 103, 32, 76, 0, 16, 22, 10, 8, 10, 4, 103, 32, 80, 0, 16, 22, 10, 8, 10, 4, 103, 32, 84, 0, 16, 22, 10, 8, 10, 4, 103, 32, 88, 0, 16, 22, 10, 8, 10, 4, 103, 32, 92, 0, 16, 22, 10, 8, 10, 4, 103, 32, 96, 0, 16, 22, 10, 8, 10, 4, 103, 32, 100, 0, 16, 22, 10, 8, 10, 4, 103, 32, 104, 0, 16, 22, 10, 8, 10, 4, 103, 32, 108, 0, 16, 22, 10, 8, 10, 4, 103, 32, 112, 0, 16, 22, 10, 8, 10, 4, 103, 32, 116, 0, 16, 22, 10, 8, 10, 4, 103, 32, 120, 0, 16, 22, 10, 8, 10, 4, 103, 32, 124, 0, 16, 22, 10, 8, 10, 4, 103, 32, 128, 0, 16, 22, 10, 8, 10, 4, 103, 32, 132, 0, 16, 22, 10, 8, 10, 4, 103, 32, 136, 0, 16, 22, 10, 8, 10, 4, 103, 32, 140, 0, 16, 22, 10, 8, 10, 4, 103, 32, 144, 0, 16, 22, 10, 8, 10, 4, 103, 32, 148, 0, 16, 22, 10, 8, 10, 4, 103, 32, 152, 0, 16, 22, 10, 8, 10, 4, 103, 32, 156, 0, 16, 22, 10, 8, 10, 4, 103, 32, 160, 0, 16, 22, 10, 8, 10, 4, 103, 32, 164, 0, 16, 22, 10, 8, 10, 4, 103, 32, 168, 0, 16, 22, 10, 8, 10, 4, 103, 32, 172, 0, 16, 22, 10, 8, 10, 4, 103, 32, 176, 0, 16, 22, 10, 8, 10, 4, 103, 32, 180, 0, 16, 22, 10, 8, 10, 4, 103, 32, 184, 0, 16, 22, 10, 8, 10, 4, 103, 32, 188, 0, 16, 22, 10, 8, 10, 4, 103, 32, 192, 0, 16, 22, 10, 8, 10, 4, 103, 32, 196, 0, 16, 22, 10, 8, 10, 4, 103, 32, 200, 0, 16, 22, 10, 8, 10, 4, 103, 32, 204, 0, 16, 22, 10, 8, 10, 4, 103, 32, 208, 0, 16, 22, 10, 8, 10, 4, 103, 32, 212, 0, 16, 22, 10, 8, 10, 4, 103, 32, 216, 0, 16, 22, 10, 8, 10, 4, 103, 32, 220, 0, 16, 22, 10, 8, 10, 4, 103, 32, 224, 0, 16, 22, 10, 8, 10, 4, 103, 32, 228, 0, 16, 22, 10, 8, 10, 4, 103, 32, 232, 0, 16, 22, 10, 8, 10, 4, 103, 32, 236, 0, 16, 22, 10, 8, 10, 4, 103, 32, 240, 0, 16, 22, 10, 8, 10, 4, 103, 32, 244, 0, 16, 22, 10, 8, 10, 4, 103, 32, 248, 0, 16, 22, 10, 8, 10, 4, 103, 32, 252, 0, 16, 22, 10, 8, 10, 4, 103, 33, 0, 0, 16, 22, 10, 8, 10, 4, 103, 33, 4, 0, 16, 22, 10, 8, 10, 4, 103, 33, 8, 0, 16, 22, 10, 8, 10, 4, 103, 33, 12, 0, 16, 22, 10, 8, 10, 4, 103, 33, 16, 0, 16, 22, 10, 8, 10, 4, 103, 33, 20, 0, 16, 22, 10, 8, 10, 4, 103, 33, 24, 0, 16, 22, 10, 8, 10, 4, 103, 33, 28, 0, 16, 22, 10, 8, 10, 4, 103, 33, 32, 0, 16, 22, 10, 8, 10, 4, 103, 33, 36, 0, 16, 22, 10, 8, 10, 4, 103, 33, 40, 0, 16, 22, 10, 8, 10, 4, 103, 33, 44, 0, 16, 22, 10, 8, 10, 4, 103, 33, 48, 0, 16, 22, 10, 8, 10, 4, 103, 33, 52, 0, 16, 22, 10, 8, 10, 4, 103, 33, 56, 0, 16, 22, 10, 8, 10, 4, 103, 33, 60, 0, 16, 22, 10, 8, 10, 4, 103, 33, 64, 0, 16, 22, 10, 8, 10, 4, 103, 33, 68, 0, 16, 22, 10, 8, 10, 4, 103, 33, 72, 0, 16, 22, 10, 8, 10, 4, 103, 33, 76, 0, 16, 22, 10, 8, 10, 4, 103, 33, 80, 0, 16, 22, 10, 8, 10, 4, 103, 33, 84, 0, 16, 22, 10, 8, 10, 4, 103, 33, 88, 0, 16, 22, 10, 8, 10, 4, 103, 33, 92, 0, 16, 22, 10, 8, 10, 4, 103, 33, 96, 0, 16, 22, 10, 8, 10, 4, 103, 33, 100, 0, 16, 22, 10, 8, 10, 4, 103, 33, 104, 0, 16, 22, 10, 8, 10, 4, 103, 33, 108, 0, 16, 22, 10, 8, 10, 4, 103, 33, 112, 0, 16, 22, 10, 8, 10, 4, 103, 33, 116, 0, 16, 22, 10, 8, 10, 4, 103, 33, 120, 0, 16, 22, 10, 8, 10, 4, 103, 33, 124, 0, 16, 22, 10, 8, 10, 4, 103, 33, 128, 0, 16, 22, 10, 8, 10, 4, 103, 33, 132, 0, 16, 22, 10, 8, 10, 4, 103, 33, 136, 0, 16, 22, 10, 8, 10, 4, 103, 33, 140, 0, 16, 22, 10, 8, 10, 4, 103, 33, 144, 0, 16, 22, 10, 8, 10, 4, 103, 33, 148, 0, 16, 22, 10, 8, 10, 4, 103, 33, 152, 0, 16, 22, 10, 8, 10, 4, 103, 33, 156, 0, 16, 22, 10, 8, 10, 4, 103, 33, 160, 0, 16, 22, 10, 8, 10, 4, 103, 33, 164, 0, 16, 22, 10, 8, 10, 4, 103, 33, 168, 0, 16, 22, 10, 8, 10, 4, 103, 33, 172, 0, 16, 22, 10, 8, 10, 4, 103, 33, 176, 0, 16, 22, 10, 8, 10, 4, 103, 33, 180, 0, 16, 22, 10, 8, 10, 4, 103, 33, 184, 0, 16, 22, 10, 8, 10, 4, 103, 33, 188, 0, 16, 22, 10, 8, 10, 4, 103, 33, 192, 0, 16, 22, 10, 8, 10, 4, 103, 33, 196, 0, 16, 22, 10, 8, 10, 4, 103, 33, 200, 0, 16, 22, 10, 8, 10, 4, 103, 33, 204, 0, 16, 22, 10, 8, 10, 4, 103, 33, 208, 0, 16, 22, 10, 8, 10, 4, 103, 33, 212, 0, 16, 22, 10, 8, 10, 4, 103, 33, 216, 0, 16, 22, 10, 8, 10, 4, 103, 33, 220, 0, 16, 22, 10, 8, 10, 4, 103, 33, 224, 0, 16, 22, 10, 8, 10, 4, 103, 33, 228, 0, 16, 22, 10, 8, 10, 4, 103, 33, 232, 0, 16, 22, 10, 8, 10, 4, 103, 33, 236, 0, 16, 22, 10, 8, 10, 4, 103, 33, 240, 0, 16, 22, 10, 8, 10, 4, 103, 33, 244, 0, 16, 22, 10, 8, 10, 4, 103, 33, 248, 0, 16, 22, 10, 8, 10, 4, 103, 33, 252, 0, 16, 22, 10, 8, 10, 4, 103, 34, 0, 0, 16, 22, 10, 8, 10, 4, 103, 34, 4, 0, 16, 22, 10, 8, 10, 4, 103, 34, 8, 0, 16, 22, 10, 8, 10, 4, 103, 34, 12, 0, 16, 22, 10, 8, 10, 4, 103, 34, 16, 0, 16, 22, 10, 8, 10, 4, 103, 34, 20, 0, 16, 22, 10, 8, 10, 4, 103, 34, 24, 0, 16, 22, 10, 8, 10, 4, 103, 34, 28, 0, 16, 22, 10, 8, 10, 4, 103, 34, 32, 0, 16, 22, 10, 8, 10, 4, 103, 34, 36, 0, 16, 22, 10, 8, 10, 4, 103, 34, 40, 0, 16, 22, 10, 8, 10, 4, 103, 34, 44, 0, 16, 22, 10, 8, 10, 4, 103, 34, 48, 0, 16, 22, 10, 8, 10, 4, 103, 34, 52, 0, 16, 22, 10, 8, 10, 4, 103, 34, 56, 0, 16, 22, 10, 8, 10, 4, 103, 34, 60, 0, 16, 22, 10, 8, 10, 4, 103, 34, 64, 0, 16, 22, 10, 8, 10, 4, 103, 34, 68, 0, 16, 22, 10, 8, 10, 4, 103, 34, 72, 0, 16, 22, 10, 8, 10, 4, 103, 34, 76, 0, 16, 22, 10, 8, 10, 4, 103, 34, 80, 0, 16, 22, 10, 8, 10, 4, 103, 34, 84, 0, 16, 22, 10, 8, 10, 4, 103, 34, 88, 0, 16, 22, 10, 8, 10, 4, 103, 34, 92, 0, 16, 22, 10, 8, 10, 4, 103, 34, 96, 0, 16, 22, 10, 8, 10, 4, 103, 34, 100, 0, 16, 22, 10, 8, 10, 4, 103, 34, 104, 0, 16, 22, 10, 8, 10, 4, 103, 34, 108, 0, 16, 22, 10, 8, 10, 4, 103, 34, 112, 0, 16, 22, 10, 8, 10, 4, 103, 34, 116, 0, 16, 22, 10, 8, 10, 4, 103, 34, 120, 0, 16, 22, 10, 8, 10, 4, 103, 34, 124, 0, 16, 22, 10, 8, 10, 4, 103, 34, 128, 0, 16, 22, 10, 8, 10, 4, 103, 34, 132, 0, 16, 22, 10, 8, 10, 4, 103, 34, 136, 0, 16, 22, 10, 8, 10, 4, 103, 34, 140, 0, 16, 22, 10, 8, 10, 4, 103, 34, 144, 0, 16, 22, 10, 8, 10, 4, 103, 34, 148, 0, 16, 22, 10, 8, 10, 4, 103, 34, 152, 0, 16, 22, 10, 8, 10, 4, 103, 34, 156, 0, 16, 22, 10, 8, 10, 4, 103, 34, 160, 0, 16, 22, 10, 8, 10, 4, 103, 34, 164, 0, 16, 22, 10, 8, 10, 4, 103, 34, 168, 0, 16, 22, 10, 8, 10, 4, 103, 34, 172, 0, 16, 22, 10, 8, 10, 4, 103, 34, 176, 0, 16, 22, 10, 8, 10, 4, 103, 34, 180, 0, 16, 22, 10, 8, 10, 4, 103, 34, 184, 0, 16, 22, 10, 8, 10, 4, 103, 34, 188, 0, 16, 22, 10, 8, 10, 4, 103, 34, 192, 0, 16, 22, 10, 8, 10, 4, 103, 34, 196, 0, 16, 22, 10, 8, 10, 4, 103, 34, 200, 0, 16, 22, 10, 8, 10, 4, 103, 34, 204, 0, 16, 22, 10, 8, 10, 4, 103, 34, 208, 0, 16, 22, 10, 8, 10, 4, 103, 34, 212, 0, 16, 22, 10, 8, 10, 4, 103, 34, 216, 0, 16, 22, 10, 8, 10, 4, 103, 34, 220, 0, 16, 22, 10, 8, 10, 4, 103, 34, 224, 0, 16, 22, 10, 8, 10, 4, 103, 34, 228, 0, 16, 22, 10, 8, 10, 4, 103, 34, 232, 0, 16, 22, 10, 8, 10, 4, 103, 34, 236, 0, 16, 22, 10, 8, 10, 4, 103, 34, 240, 0, 16, 22, 10, 8, 10, 4, 103, 34, 244, 0, 16, 22, 10, 8, 10, 4, 103, 34, 248, 0, 16, 22, 10, 8, 10, 4, 103, 34, 252, 0, 16, 22, 10, 8, 10, 4, 103, 35, 0, 0, 16, 22, 10, 8, 10, 4, 103, 35, 4, 0, 16, 22, 10, 8, 10, 4, 103, 35, 8, 0, 16, 22, 10, 8, 10, 4, 103, 35, 12, 0, 16, 22, 10, 8, 10, 4, 103, 35, 16, 0, 16, 22, 10, 8, 10, 4, 103, 35, 20, 0, 16, 22, 10, 8, 10, 4, 103, 35, 24, 0, 16, 22, 10, 8, 10, 4, 103, 35, 28, 0, 16, 22, 10, 8, 10, 4, 103, 35, 32, 0, 16, 22, 10, 8, 10, 4, 103, 35, 36, 0, 16, 22, 10, 8, 10, 4, 103, 35, 40, 0, 16, 22, 10, 8, 10, 4, 103, 35, 44, 0, 16, 22, 10, 8, 10, 4, 103, 35, 48, 0, 16, 22, 10, 8, 10, 4, 103, 35, 104, 0, 16, 22, 10, 8, 10, 4, 103, 35, 116, 0, 16, 22, 10, 8, 10, 4, 103, 35, 180, 0, 16, 22, 10, 8, 10, 4, 103, 35, 200, 0, 16, 22, 10, 8, 10, 4, 103, 35, 220, 0, 16, 22, 10, 8, 10, 4, 103, 36, 20, 0, 16, 22, 10, 8, 10, 4, 103, 36, 28, 0, 16, 22, 10, 8, 10, 4, 103, 36, 36, 0, 16, 22, 10, 8, 10, 4, 103, 36, 56, 0, 16, 22, 10, 8, 10, 4, 103, 36, 60, 0, 16, 22, 10, 8, 10, 4, 103, 36, 64, 0, 16, 22, 10, 8, 10, 4, 103, 36, 72, 0, 16, 22, 10, 8, 10, 4, 103, 36, 96, 0, 16, 22, 10, 8, 10, 4, 103, 36, 132, 0, 16, 22, 10, 8, 10, 4, 103, 36, 136, 0, 16, 22, 10, 8, 10, 4, 103, 36, 160, 0, 16, 22, 10, 8, 10, 4, 103, 36, 164, 0, 16, 22, 10, 8, 10, 4, 103, 36, 168, 0, 16, 22, 10, 8, 10, 4, 103, 36, 172, 0, 16, 22, 10, 8, 10, 4, 103, 36, 176, 0, 16, 22, 10, 8, 10, 4, 103, 36, 180, 0, 16, 22, 10, 8, 10, 4, 103, 36, 184, 0, 16, 22, 10, 8, 10, 4, 103, 36, 188, 0, 16, 22, 10, 8, 10, 4, 103, 36, 192, 0, 16, 22, 10, 8, 10, 4, 103, 36, 196, 0, 16, 22, 10, 8, 10, 4, 103, 36, 200, 0, 16, 22, 10, 8, 10, 4, 103, 36, 204, 0, 16, 22, 10, 8, 10, 4, 103, 36, 208, 0, 16, 22, 10, 8, 10, 4, 103, 36, 212, 0, 16, 22, 10, 8, 10, 4, 103, 36, 216, 0, 16, 22, 10, 8, 10, 4, 103, 36, 220, 0, 16, 22, 10, 8, 10, 4, 103, 36, 224, 0, 16, 22, 10, 8, 10, 4, 103, 36, 228, 0, 16, 22, 10, 8, 10, 4, 103, 36, 232, 0, 16, 22, 10, 8, 10, 4, 103, 36, 236, 0, 16, 22, 10, 8, 10, 4, 103, 36, 240, 0, 16, 22, 10, 8, 10, 4, 103, 36, 244, 0, 16, 22, 10, 8, 10, 4, 103, 37, 0, 0, 16, 22, 10, 8, 10, 4, 103, 37, 12, 0, 16, 22, 10, 8, 10, 4, 103, 37, 16, 0, 16, 22, 10, 8, 10, 4, 103, 37, 24, 0, 16, 22, 10, 8, 10, 4, 103, 37, 44, 0, 16, 22, 10, 8, 10, 4, 103, 37, 52, 0, 16, 22, 10, 8, 10, 4, 103, 37, 56, 0, 16, 22, 10, 8, 10, 4, 103, 37, 72, 0, 16, 22, 10, 8, 10, 4, 103, 37, 100, 0, 16, 22, 10, 8, 10, 4, 103, 37, 104, 0, 16, 22, 10, 8, 10, 4, 103, 37, 124, 0, 16, 22, 10, 8, 10, 4, 103, 37, 136, 0, 16, 22, 10, 8, 10, 4, 103, 37, 140, 0, 16, 22, 10, 8, 10, 4, 103, 37, 144, 0, 16, 22, 10, 8, 10, 4, 103, 37, 148, 0, 16, 22, 10, 8, 10, 4, 103, 37, 152, 0, 16, 22, 10, 8, 10, 4, 103, 37, 156, 0, 16, 22, 10, 8, 10, 4, 103, 37, 160, 0, 16, 22, 10, 8, 10, 4, 103, 37, 164, 0, 16, 22, 10, 8, 10, 4, 103, 37, 172, 0, 16, 22, 10, 8, 10, 4, 103, 37, 176, 0, 16, 22, 10, 8, 10, 4, 103, 37, 188, 0, 16, 22, 10, 8, 10, 4, 103, 37, 208, 0, 16, 22, 10, 8, 10, 4, 103, 37, 212, 0, 16, 22, 10, 8, 10, 4, 103, 37, 216, 0, 16, 22, 10, 8, 10, 4, 103, 37, 220, 0, 16, 22, 10, 8, 10, 4, 103, 37, 248, 0, 16, 22, 10, 8, 10, 4, 103, 37, 252, 0, 16, 22, 10, 8, 10, 4, 103, 38, 0, 0, 16, 22, 10, 8, 10, 4, 103, 38, 32, 0, 16, 22, 10, 8, 10, 4, 103, 38, 40, 0, 16, 22, 10, 8, 10, 4, 103, 38, 44, 0, 16, 22, 10, 8, 10, 4, 103, 38, 56, 0, 16, 22, 10, 8, 10, 4, 103, 38, 76, 0, 16, 22, 10, 8, 10, 4, 103, 38, 84, 0, 16, 22, 10, 8, 10, 4, 103, 38, 92, 0, 16, 22, 10, 8, 10, 4, 103, 38, 96, 0, 16, 22, 10, 8, 10, 4, 103, 38, 116, 0, 16, 22, 10, 8, 10, 4, 103, 38, 132, 0, 16, 22, 10, 8, 10, 4, 103, 38, 140, 0, 16, 22, 10, 8, 10, 4, 103, 38, 220, 0, 16, 22, 10, 8, 10, 4, 103, 38, 224, 0, 16, 22, 10, 8, 10, 4, 103, 38, 228, 0, 16, 22, 10, 8, 10, 4, 103, 38, 232, 0, 16, 22, 10, 8, 10, 4, 103, 38, 252, 0, 16, 22, 10, 8, 10, 4, 103, 39, 16, 0, 16, 22, 10, 8, 10, 4, 103, 39, 64, 0, 16, 22, 10, 8, 10, 4, 103, 39, 88, 0, 16, 22, 10, 8, 10, 4, 103, 39, 100, 0, 16, 22, 10, 8, 10, 4, 103, 39, 104, 0, 16, 22, 10, 8, 10, 4, 103, 39, 108, 0, 16, 22, 10, 8, 10, 4, 103, 39, 160, 0, 16, 22, 10, 8, 10, 4, 103, 39, 164, 0, 16, 22, 10, 8, 10, 4, 103, 39, 168, 0, 16, 22, 10, 8, 10, 4, 103, 39, 172, 0, 16, 22, 10, 8, 10, 4, 103, 39, 176, 0, 16, 22, 10, 8, 10, 4, 103, 39, 180, 0, 16, 22, 10, 8, 10, 4, 103, 39, 184, 0, 16, 22, 10, 8, 10, 4, 103, 39, 188, 0, 16, 22, 10, 8, 10, 4, 103, 39, 200, 0, 16, 22, 10, 8, 10, 4, 103, 39, 204, 0, 16, 22, 10, 8, 10, 4, 103, 39, 208, 0, 16, 22, 10, 8, 10, 4, 103, 39, 212, 0, 16, 22, 10, 8, 10, 4, 103, 39, 216, 0, 16, 22, 10, 8, 10, 4, 103, 39, 220, 0, 16, 22, 10, 8, 10, 4, 103, 39, 224, 0, 16, 22, 10, 8, 10, 4, 103, 39, 228, 0, 16, 22, 10, 8, 10, 4, 103, 39, 232, 0, 16, 22, 10, 8, 10, 4, 103, 40, 12, 0, 16, 22, 10, 8, 10, 4, 103, 40, 16, 0, 16, 22, 10, 8, 10, 4, 103, 40, 20, 0, 16, 22, 10, 8, 10, 4, 103, 40, 24, 0, 16, 22, 10, 8, 10, 4, 103, 40, 28, 0, 16, 22, 10, 8, 10, 4, 103, 40, 32, 0, 16, 22, 10, 8, 10, 4, 103, 40, 36, 0, 16, 22, 10, 8, 10, 4, 103, 40, 40, 0, 16, 22, 10, 8, 10, 4, 103, 40, 44, 0, 16, 22, 10, 8, 10, 4, 103, 40, 88, 0, 16, 22, 10, 8, 10, 4, 103, 40, 100, 0, 16, 22, 10, 8, 10, 4, 103, 40, 112, 0, 16, 22, 10, 8, 10, 4, 103, 40, 192, 0, 16, 22, 10, 8, 10, 4, 103, 40, 212, 0, 16, 22, 10, 8, 10, 4, 103, 40, 220, 0, 16, 22, 10, 8, 10, 4, 103, 40, 228, 0, 16, 22, 10, 8, 10, 4, 103, 40, 232, 0, 16, 22, 10, 8, 10, 4, 103, 40, 236, 0, 16, 22, 10, 8, 10, 4, 103, 40, 240, 0, 16, 22, 10, 8, 10, 4, 103, 40, 244, 0, 16, 22, 10, 8, 10, 4, 103, 40, 248, 0, 16, 22, 10, 8, 10, 4, 103, 40, 252, 0, 16, 22, 10, 8, 10, 4, 103, 41, 0, 0, 16, 22, 10, 8, 10, 4, 103, 41, 16, 0, 16, 22, 10, 8, 10, 4, 103, 41, 52, 0, 16, 22, 10, 8, 10, 4, 103, 41, 140, 0, 16, 22, 10, 8, 10, 4, 103, 41, 148, 0, 16, 22, 10, 8, 10, 4, 103, 41, 152, 0, 16, 22, 10, 8, 10, 4, 103, 41, 160, 0, 16, 22, 10, 8, 10, 4, 103, 41, 164, 0, 16, 22, 10, 8, 10, 4, 103, 41, 220, 0, 16, 22, 10, 8, 10, 4, 103, 41, 224, 0, 16, 22, 10, 8, 10, 4, 103, 41, 228, 0, 16, 22, 10, 8, 10, 4, 103, 41, 232, 0, 16, 22, 10, 8, 10, 4, 103, 42, 8, 0, 16, 22, 10, 8, 10, 4, 103, 42, 24, 0, 16, 22, 10, 8, 10, 4, 103, 42, 28, 0, 16, 22, 10, 8, 10, 4, 103, 42, 32, 0, 16, 22, 10, 8, 10, 4, 103, 42, 64, 0, 16, 22, 10, 8, 10, 4, 103, 42, 68, 0, 16, 22, 10, 8, 10, 4, 103, 42, 76, 0, 16, 22, 10, 8, 10, 4, 103, 42, 104, 0, 16, 22, 10, 8, 10, 4, 103, 42, 180, 0, 16, 22, 10, 8, 10, 4, 103, 42, 232, 0, 16, 22, 10, 8, 10, 4, 103, 43, 16, 0, 16, 22, 10, 8, 10, 4, 103, 43, 84, 0, 16, 22, 10, 8, 10, 4, 103, 43, 96, 0, 16, 22, 10, 8, 10, 4, 103, 43, 100, 0, 16, 22, 10, 8, 10, 4, 103, 43, 104, 0, 16, 22, 10, 8, 10, 4, 103, 43, 124, 0, 16, 22, 10, 8, 10, 4, 103, 43, 184, 0, 16, 22, 10, 8, 10, 4, 103, 43, 192, 0, 16, 22, 10, 8, 10, 4, 103, 43, 196, 0, 16, 22, 10, 8, 10, 4, 103, 43, 208, 0, 16, 22, 10, 8, 10, 4, 103, 43, 220, 0, 16, 22, 10, 8, 10, 4, 103, 43, 224, 0, 16, 22, 10, 8, 10, 4, 103, 43, 232, 0, 16, 22, 10, 8, 10, 4, 103, 43, 240, 0, 16, 22, 10, 8, 10, 4, 103, 44, 56, 0, 16, 22, 10, 8, 10, 4, 103, 44, 80, 0, 16, 22, 10, 8, 10, 4, 103, 44, 88, 0, 16, 22, 10, 8, 10, 4, 103, 44, 120, 0, 16, 22, 10, 8, 10, 4, 103, 44, 124, 0, 16, 22, 10, 8, 10, 4, 103, 44, 132, 0, 16, 22, 10, 8, 10, 4, 103, 44, 144, 0, 16, 22, 10, 8, 10, 4, 103, 44, 168, 0, 16, 22, 10, 8, 10, 4, 103, 44, 176, 0, 16, 22, 10, 8, 10, 4, 103, 44, 180, 0, 16, 22, 10, 8, 10, 4, 103, 44, 184, 0, 16, 22, 10, 8, 10, 4, 103, 44, 188, 0, 16, 22, 10, 8, 10, 4, 103, 44, 192, 0, 16, 22, 10, 8, 10, 4, 103, 44, 196, 0, 16, 22, 10, 8, 10, 4, 103, 44, 200, 0, 16, 22, 10, 8, 10, 4, 103, 44, 204, 0, 16, 22, 10, 8, 10, 4, 103, 44, 224, 0, 16, 22, 10, 8, 10, 4, 103, 44, 236, 0, 16, 22, 10, 8, 10, 4, 103, 44, 240, 0, 16, 22, 10, 8, 10, 4, 103, 44, 244, 0, 16, 22, 10, 8, 10, 4, 103, 44, 248, 0, 16, 22, 10, 8, 10, 4, 103, 44, 252, 0, 16, 22, 10, 8, 10, 4, 103, 45, 0, 0, 16, 22, 10, 8, 10, 4, 103, 45, 4, 0, 16, 22, 10, 8, 10, 4, 103, 45, 8, 0, 16, 22, 10, 8, 10, 4, 103, 45, 12, 0, 16, 22, 10, 8, 10, 4, 103, 45, 16, 0, 16, 22, 10, 8, 10, 4, 103, 45, 20, 0, 16, 22, 10, 8, 10, 4, 103, 45, 24, 0, 16, 22, 10, 8, 10, 4, 103, 45, 28, 0, 16, 22, 10, 8, 10, 4, 103, 45, 32, 0, 16, 22, 10, 8, 10, 4, 103, 45, 36, 0, 16, 22, 10, 8, 10, 4, 103, 45, 40, 0, 16, 22, 10, 8, 10, 4, 103, 45, 44, 0, 16, 22, 10, 8, 10, 4, 103, 45, 48, 0, 16, 22, 10, 8, 10, 4, 103, 45, 52, 0, 16, 22, 10, 8, 10, 4, 103, 45, 56, 0, 16, 22, 10, 8, 10, 4, 103, 45, 60, 0, 16, 22, 10, 8, 10, 4, 103, 45, 72, 0, 16, 22, 10, 8, 10, 4, 103, 45, 76, 0, 16, 22, 10, 8, 10, 4, 103, 45, 80, 0, 16, 22, 10, 8, 10, 4, 103, 45, 84, 0, 16, 22, 10, 8, 10, 4, 103, 45, 88, 0, 16, 22, 10, 8, 10, 4, 103, 45, 92, 0, 16, 22, 10, 8, 10, 4, 103, 45, 96, 0, 16, 22, 10, 8, 10, 4, 103, 45, 100, 0, 16, 22, 10, 8, 10, 4, 103, 45, 104, 0, 16, 22, 10, 8, 10, 4, 103, 45, 108, 0, 16, 22, 10, 8, 10, 4, 103, 45, 112, 0, 16, 22, 10, 8, 10, 4, 103, 45, 116, 0, 16, 22, 10, 8, 10, 4, 103, 45, 120, 0, 16, 22, 10, 8, 10, 4, 103, 45, 124, 0, 16, 22, 10, 8, 10, 4, 103, 45, 128, 0, 16, 22, 10, 8, 10, 4, 103, 45, 132, 0, 16, 22, 10, 8, 10, 4, 103, 45, 136, 0, 16, 22, 10, 8, 10, 4, 103, 45, 140, 0, 16, 22, 10, 8, 10, 4, 103, 45, 144, 0, 16, 22, 10, 8, 10, 4, 103, 45, 148, 0, 16, 22, 10, 8, 10, 4, 103, 45, 152, 0, 16, 22, 10, 8, 10, 4, 103, 45, 156, 0, 16, 22, 10, 8, 10, 4, 103, 45, 160, 0, 16, 22, 10, 8, 10, 4, 103, 45, 164, 0, 16, 22, 10, 8, 10, 4, 103, 45, 168, 0, 16, 22, 10, 8, 10, 4, 103, 45, 172, 0, 16, 22, 10, 8, 10, 4, 103, 45, 176, 0, 16, 22, 10, 8, 10, 4, 103, 45, 180, 0, 16, 22, 10, 8, 10, 4, 103, 45, 184, 0, 16, 22, 10, 8, 10, 4, 103, 45, 188, 0, 16, 22, 10, 8, 10, 4, 103, 45, 192, 0, 16, 22, 10, 8, 10, 4, 103, 45, 196, 0, 16, 22, 10, 8, 10, 4, 103, 45, 200, 0, 16, 22, 10, 8, 10, 4, 103, 45, 204, 0, 16, 22, 10, 8, 10, 4, 103, 45, 208, 0, 16, 22, 10, 8, 10, 4, 103, 45, 212, 0, 16, 22, 10, 8, 10, 4, 103, 45, 216, 0, 16, 22, 10, 8, 10, 4, 103, 45, 220, 0, 16, 22, 10, 8, 10, 4, 103, 45, 224, 0, 16, 22, 10, 8, 10, 4, 103, 45, 248, 0, 16, 22, 10, 8, 10, 4, 103, 46, 0, 0, 16, 22, 10, 8, 10, 4, 103, 46, 12, 0, 16, 22, 10, 8, 10, 4, 103, 46, 16, 0, 16, 22, 10, 8, 10, 4, 103, 46, 20, 0, 16, 22, 10, 8, 10, 4, 103, 46, 24, 0, 16, 22, 10, 8, 10, 4, 103, 46, 28, 0, 16, 22, 10, 8, 10, 4, 103, 46, 32, 0, 16, 22, 10, 8, 10, 4, 103, 46, 36, 0, 16, 22, 10, 8, 10, 4, 103, 46, 40, 0, 16, 22, 10, 8, 10, 4, 103, 46, 44, 0, 16, 22, 10, 8, 10, 4, 103, 46, 48, 0, 16, 22, 10, 8, 10, 4, 103, 46, 52, 0, 16, 22, 10, 8, 10, 4, 103, 46, 56, 0, 16, 22, 10, 8, 10, 4, 103, 46, 60, 0, 16, 22, 10, 8, 10, 4, 103, 46, 64, 0, 16, 22, 10, 8, 10, 4, 103, 46, 68, 0, 16, 22, 10, 8, 10, 4, 103, 46, 72, 0, 16, 22, 10, 8, 10, 4, 103, 46, 76, 0, 16, 22, 10, 8, 10, 4, 103, 46, 80, 0, 16, 22, 10, 8, 10, 4, 103, 46, 84, 0, 16, 22, 10, 8, 10, 4, 103, 46, 88, 0, 16, 22, 10, 8, 10, 4, 103, 46, 92, 0, 16, 22, 10, 8, 10, 4, 103, 46, 96, 0, 16, 22, 10, 8, 10, 4, 103, 46, 100, 0, 16, 22, 10, 8, 10, 4, 103, 46, 104, 0, 16, 22, 10, 8, 10, 4, 103, 46, 108, 0, 16, 22, 10, 8, 10, 4, 103, 46, 112, 0, 16, 22, 10, 8, 10, 4, 103, 46, 116, 0, 16, 22, 10, 8, 10, 4, 103, 46, 120, 0, 16, 22, 10, 8, 10, 4, 103, 46, 124, 0, 16, 22, 10, 8, 10, 4, 103, 46, 128, 0, 16, 22, 10, 8, 10, 4, 103, 46, 132, 0, 16, 22, 10, 8, 10, 4, 103, 46, 136, 0, 16, 22, 10, 8, 10, 4, 103, 46, 152, 0, 16, 22, 10, 8, 10, 4, 103, 46, 156, 0, 16, 22, 10, 8, 10, 4, 103, 46, 160, 0, 16, 22, 10, 8, 10, 4, 103, 46, 164, 0, 16, 22, 10, 8, 10, 4, 103, 46, 168, 0, 16, 22, 10, 8, 10, 4, 103, 46, 172, 0, 16, 22, 10, 8, 10, 4, 103, 46, 176, 0, 16, 22, 10, 8, 10, 4, 103, 46, 180, 0, 16, 22, 10, 8, 10, 4, 103, 46, 244, 0, 16, 22, 10, 8, 10, 4, 103, 46, 248, 0, 16, 22, 10, 8, 10, 4, 103, 47, 4, 0, 16, 22, 10, 8, 10, 4, 103, 47, 20, 0, 16, 22, 10, 8, 10, 4, 103, 47, 36, 0, 16, 22, 10, 8, 10, 4, 103, 47, 40, 0, 16, 22, 10, 8, 10, 4, 103, 47, 48, 0, 16, 22, 10, 8, 10, 4, 103, 47, 80, 0, 16, 22, 10, 8, 10, 4, 103, 47, 96, 0, 16, 22, 10, 8, 10, 4, 103, 47, 108, 0, 16, 22, 10, 8, 10, 4, 103, 47, 116, 0, 16, 22, 10, 8, 10, 4, 103, 47, 120, 0, 16, 22, 10, 8, 10, 4, 103, 47, 136, 0, 16, 22, 10, 8, 10, 4, 103, 47, 140, 0, 16, 22, 10, 8, 10, 4, 103, 47, 212, 0, 16, 22, 10, 8, 10, 4, 103, 48, 20, 0, 16, 22, 10, 8, 10, 4, 103, 48, 52, 0, 16, 22, 10, 8, 10, 4, 103, 48, 92, 0, 16, 22, 10, 8, 10, 4, 103, 48, 144, 0, 16, 22, 10, 8, 10, 4, 103, 48, 148, 0, 16, 22, 10, 8, 10, 4, 103, 48, 152, 0, 16, 22, 10, 8, 10, 4, 103, 48, 156, 0, 16, 22, 10, 8, 10, 4, 103, 48, 202, 0, 16, 23, 10, 8, 10, 4, 103, 48, 216, 0, 16, 22, 10, 8, 10, 4, 103, 48, 220, 0, 16, 22, 10, 8, 10, 4, 103, 48, 224, 0, 16, 22, 10, 8, 10, 4, 103, 48, 228, 0, 16, 22, 10, 8, 10, 4, 103, 48, 232, 0, 16, 22, 10, 8, 10, 4, 103, 48, 236, 0, 16, 22, 10, 8, 10, 4, 103, 48, 240, 0, 16, 22, 10, 8, 10, 4, 103, 48, 244, 0, 16, 22, 10, 8, 10, 4, 103, 49, 12, 0, 16, 22, 10, 8, 10, 4, 103, 49, 20, 0, 16, 22, 10, 8, 10, 4, 103, 49, 72, 0, 16, 22, 10, 8, 10, 4, 103, 49, 76, 0, 16, 22, 10, 8, 10, 4, 103, 49, 92, 0, 16, 22, 10, 8, 10, 4, 103, 49, 96, 0, 16, 22, 10, 8, 10, 4, 103, 49, 108, 0, 16, 22, 10, 8, 10, 4, 103, 49, 128, 0, 16, 22, 10, 8, 10, 4, 103, 49, 176, 0, 16, 22, 10, 8, 10, 4, 103, 49, 180, 0, 16, 22, 10, 8, 10, 4, 103, 49, 196, 0, 16, 22, 10, 8, 10, 4, 103, 49, 248, 0, 16, 22, 10, 8, 10, 4, 103, 50, 36, 0, 16, 22, 10, 8, 10, 4, 103, 50, 44, 0, 16, 22, 10, 8, 10, 4, 103, 50, 48, 0, 16, 22, 10, 8, 10, 4, 103, 50, 52, 0, 16, 22, 10, 8, 10, 4, 103, 50, 56, 0, 16, 22, 10, 8, 10, 4, 103, 50, 60, 0, 16, 22, 10, 8, 10, 4, 103, 50, 64, 0, 16, 22, 10, 8, 10, 4, 103, 50, 68, 0, 16, 22, 10, 8, 10, 4, 103, 50, 72, 0, 16, 22, 10, 8, 10, 4, 103, 50, 108, 0, 16, 22, 10, 8, 10, 4, 103, 50, 112, 0, 16, 22, 10, 8, 10, 4, 103, 50, 116, 0, 16, 22, 10, 8, 10, 4, 103, 50, 120, 0, 16, 22, 10, 8, 10, 4, 103, 50, 124, 0, 16, 22, 10, 8, 10, 4, 103, 50, 132, 0, 16, 22, 10, 8, 10, 4, 103, 50, 136, 0, 16, 22, 10, 8, 10, 4, 103, 50, 140, 0, 16, 22, 10, 8, 10, 4, 103, 50, 172, 0, 16, 22, 10, 8, 10, 4, 103, 50, 176, 0, 16, 22, 10, 8, 10, 4, 103, 50, 180, 0, 16, 22, 10, 8, 10, 4, 103, 50, 184, 0, 16, 22, 10, 8, 10, 4, 103, 50, 188, 0, 16, 22, 10, 8, 10, 4, 103, 50, 192, 0, 16, 22, 10, 8, 10, 4, 103, 50, 196, 0, 16, 22, 10, 8, 10, 4, 103, 50, 200, 0, 16, 22, 10, 8, 10, 4, 103, 50, 220, 0, 16, 22, 10, 8, 10, 4, 103, 50, 224, 0, 16, 22, 10, 8, 10, 4, 103, 50, 228, 0, 16, 22, 10, 8, 10, 4, 103, 50, 232, 0, 16, 22, 10, 8, 10, 4, 103, 50, 236, 0, 16, 22, 10, 8, 10, 4, 103, 50, 240, 0, 16, 22, 10, 8, 10, 4, 103, 50, 244, 0, 16, 22, 10, 8, 10, 4, 103, 50, 248, 0, 16, 22, 10, 8, 10, 4, 103, 52, 40, 0, 16, 22, 10, 8, 10, 4, 103, 52, 72, 0, 16, 22, 10, 8, 10, 4, 103, 52, 76, 0, 16, 22, 10, 8, 10, 4, 103, 52, 80, 0, 16, 22, 10, 8, 10, 4, 103, 52, 84, 0, 16, 22, 10, 8, 10, 4, 103, 52, 96, 0, 16, 22, 10, 8, 10, 4, 103, 52, 100, 0, 16, 22, 10, 8, 10, 4, 103, 52, 104, 0, 16, 22, 10, 8, 10, 4, 103, 52, 160, 0, 16, 22, 10, 8, 10, 4, 103, 52, 164, 0, 16, 22, 10, 8, 10, 4, 103, 52, 172, 0, 16, 22, 10, 8, 10, 4, 103, 52, 176, 0, 16, 22, 10, 8, 10, 4, 103, 52, 184, 0, 16, 22, 10, 8, 10, 4, 103, 52, 196, 0, 16, 22, 10, 8, 10, 4, 103, 53, 4, 0, 16, 22, 10, 8, 10, 4, 103, 53, 64, 0, 16, 22, 10, 8, 10, 4, 103, 53, 68, 0, 16, 22, 10, 8, 10, 4, 103, 53, 92, 0, 16, 22, 10, 8, 10, 4, 103, 53, 100, 0, 16, 22, 10, 8, 10, 4, 103, 53, 124, 0, 16, 22, 10, 8, 10, 4, 103, 53, 128, 0, 16, 22, 10, 8, 10, 4, 103, 53, 132, 0, 16, 22, 10, 8, 10, 4, 103, 53, 136, 0, 16, 22, 10, 8, 10, 4, 103, 53, 140, 0, 16, 22, 10, 8, 10, 4, 103, 53, 144, 0, 16, 22, 10, 8, 10, 4, 103, 53, 160, 0, 16, 22, 10, 8, 10, 4, 103, 53, 180, 0, 16, 22, 10, 8, 10, 4, 103, 53, 204, 0, 16, 22, 10, 8, 10, 4, 103, 53, 208, 0, 16, 22, 10, 8, 10, 4, 103, 53, 212, 0, 16, 22, 10, 8, 10, 4, 103, 53, 216, 0, 16, 22, 10, 8, 10, 4, 103, 53, 236, 0, 16, 22, 10, 8, 10, 4, 103, 53, 248, 0, 16, 22, 10, 8, 10, 4, 103, 54, 8, 0, 16, 22, 10, 8, 10, 4, 103, 54, 48, 0, 16, 22, 10, 8, 10, 4, 103, 54, 60, 0, 16, 22, 10, 8, 10, 4, 103, 54, 160, 0, 16, 22, 10, 8, 10, 4, 103, 54, 164, 0, 16, 22, 10, 8, 10, 4, 103, 54, 212, 0, 16, 22, 10, 8, 10, 4, 103, 54, 228, 0, 16, 22, 10, 8, 10, 4, 103, 54, 240, 0, 16, 22, 10, 8, 10, 4, 103, 55, 24, 0, 16, 22, 10, 8, 10, 4, 103, 55, 80, 0, 16, 22, 10, 8, 10, 4, 103, 55, 120, 0, 16, 22, 10, 8, 10, 4, 103, 55, 152, 0, 16, 22, 10, 8, 10, 4, 103, 55, 172, 0, 16, 22, 10, 8, 10, 4, 103, 55, 204, 0, 16, 22, 10, 8, 10, 4, 103, 55, 208, 0, 16, 22, 10, 8, 10, 4, 103, 55, 228, 0, 16, 22, 10, 8, 10, 4, 103, 55, 236, 0, 16, 22, 10, 8, 10, 4, 103, 55, 240, 0, 16, 22, 10, 8, 10, 4, 103, 56, 8, 0, 16, 22, 10, 8, 10, 4, 103, 56, 16, 0, 16, 22, 10, 8, 10, 4, 103, 56, 20, 0, 16, 22, 10, 8, 10, 4, 103, 56, 32, 0, 16, 22, 10, 8, 10, 4, 103, 56, 52, 0, 16, 22, 10, 8, 10, 4, 103, 56, 56, 0, 16, 22, 10, 8, 10, 4, 103, 56, 60, 0, 16, 22, 10, 8, 10, 4, 103, 56, 72, 0, 16, 22, 10, 8, 10, 4, 103, 56, 76, 0, 16, 22, 10, 8, 10, 4, 103, 56, 140, 0, 16, 22, 10, 8, 10, 4, 103, 56, 152, 0, 16, 22, 10, 8, 10, 4, 103, 56, 184, 0, 16, 22, 10, 8, 10, 4, 103, 56, 200, 0, 16, 22, 10, 8, 10, 4, 103, 57, 12, 0, 16, 22, 10, 8, 10, 4, 103, 57, 52, 0, 16, 22, 10, 8, 10, 4, 103, 57, 56, 0, 16, 22, 10, 8, 10, 4, 103, 57, 76, 0, 16, 22, 10, 8, 10, 4, 103, 57, 136, 0, 16, 22, 10, 8, 10, 4, 103, 57, 196, 0, 16, 22, 10, 8, 10, 4, 103, 58, 24, 0, 16, 22, 10, 8, 10, 4, 103, 58, 182, 0, 16, 23, 10, 8, 10, 4, 103, 59, 76, 0, 16, 22, 10, 8, 10, 4, 103, 59, 100, 0, 16, 22, 10, 8, 10, 4, 103, 59, 112, 0, 16, 22, 10, 8, 10, 4, 103, 59, 116, 0, 16, 22, 10, 8, 10, 4, 103, 59, 120, 0, 16, 22, 10, 8, 10, 4, 103, 59, 124, 0, 16, 22, 10, 8, 10, 4, 103, 59, 128, 0, 16, 22, 10, 8, 10, 4, 103, 59, 148, 0, 16, 22, 10, 8, 10, 4, 103, 59, 164, 0, 16, 22, 10, 8, 10, 4, 103, 60, 32, 0, 16, 22, 10, 8, 10, 4, 103, 60, 44, 0, 16, 22, 10, 8, 10, 4, 103, 60, 164, 0, 16, 22, 10, 8, 10, 4, 103, 60, 228, 0, 16, 22, 10, 8, 10, 4, 103, 60, 236, 0, 16, 22, 10, 8, 10, 4, 103, 61, 60, 0, 16, 22, 10, 8, 10, 4, 103, 61, 104, 0, 16, 22, 10, 8, 10, 4, 103, 61, 140, 0, 16, 22, 10, 8, 10, 4, 103, 61, 152, 0, 16, 22, 10, 8, 10, 4, 103, 61, 156, 0, 16, 22, 10, 8, 10, 4, 103, 61, 160, 0, 16, 22, 10, 8, 10, 4, 103, 61, 172, 0, 16, 22, 10, 8, 10, 4, 103, 61, 176, 0, 16, 22, 10, 8, 10, 4, 103, 61, 184, 0, 16, 22, 10, 8, 10, 4, 103, 61, 188, 0, 16, 22, 10, 8, 10, 4, 103, 62, 24, 0, 16, 22, 10, 8, 10, 4, 103, 62, 52, 0, 16, 22, 10, 8, 10, 4, 103, 62, 72, 0, 16, 22, 10, 8, 10, 4, 103, 62, 76, 0, 16, 22, 10, 8, 10, 4, 103, 62, 80, 0, 16, 22, 10, 8, 10, 4, 103, 62, 84, 0, 16, 22, 10, 8, 10, 4, 103, 62, 88, 0, 16, 22, 10, 8, 10, 4, 103, 62, 96, 0, 16, 22, 10, 8, 10, 4, 103, 62, 100, 0, 16, 22, 10, 8, 10, 4, 103, 62, 104, 0, 16, 22, 10, 8, 10, 4, 103, 62, 108, 0, 16, 22, 10, 8, 10, 4, 103, 62, 112, 0, 16, 22, 10, 8, 10, 4, 103, 62, 116, 0, 16, 22, 10, 8, 10, 4, 103, 62, 120, 0, 16, 22, 10, 8, 10, 4, 103, 62, 124, 0, 16, 22, 10, 8, 10, 4, 103, 62, 128, 0, 16, 22, 10, 8, 10, 4, 103, 62, 132, 0, 16, 22, 10, 8, 10, 4, 103, 62, 156, 0, 16, 22, 10, 8, 10, 4, 103, 62, 160, 0, 16, 22, 10, 8, 10, 4, 103, 62, 164, 0, 16, 22, 10, 8, 10, 4, 103, 62, 168, 0, 16, 22, 10, 8, 10, 4, 103, 62, 172, 0, 16, 22, 10, 8, 10, 4, 103, 62, 176, 0, 16, 22, 10, 8, 10, 4, 103, 62, 180, 0, 16, 22, 10, 8, 10, 4, 103, 62, 184, 0, 16, 22, 10, 8, 10, 4, 103, 62, 188, 0, 16, 22, 10, 8, 10, 4, 103, 62, 192, 0, 16, 22, 10, 8, 10, 4, 103, 62, 204, 0, 16, 22, 10, 8, 10, 4, 103, 62, 208, 0, 16, 22, 10, 8, 10, 4, 103, 62, 212, 0, 16, 22, 10, 8, 10, 4, 103, 62, 216, 0, 16, 22, 10, 8, 10, 4, 103, 62, 220, 0, 16, 22, 10, 8, 10, 4, 103, 62, 224, 0, 16, 22, 10, 8, 10, 4, 103, 63, 32, 0, 16, 22, 10, 8, 10, 4, 103, 63, 36, 0, 16, 22, 10, 8, 10, 4, 103, 63, 40, 0, 16, 22, 10, 8, 10, 4, 103, 63, 44, 0, 16, 22, 10, 8, 10, 4, 103, 63, 48, 0, 16, 22, 10, 8, 10, 4, 103, 63, 52, 0, 16, 22, 10, 8, 10, 4, 103, 63, 56, 0, 16, 22, 10, 8, 10, 4, 103, 63, 60, 0, 16, 22, 10, 8, 10, 4, 103, 63, 64, 0, 16, 22, 10, 8, 10, 4, 103, 63, 68, 0, 16, 22, 10, 8, 10, 4, 103, 63, 72, 0, 16, 22, 10, 8, 10, 4, 103, 63, 76, 0, 16, 22, 10, 8, 10, 4, 103, 63, 80, 0, 16, 22, 10, 8, 10, 4, 103, 63, 84, 0, 16, 22, 10, 8, 10, 4, 103, 63, 88, 0, 16, 22, 10, 8, 10, 4, 103, 63, 140, 0, 16, 22, 10, 8, 10, 4, 103, 63, 144, 0, 16, 22, 10, 8, 10, 4, 103, 63, 152, 0, 16, 22, 10, 8, 10, 4, 103, 63, 160, 0, 16, 22, 10, 8, 10, 4, 103, 63, 164, 0, 16, 22, 10, 8, 10, 4, 103, 63, 168, 0, 16, 22, 10, 8, 10, 4, 103, 63, 172, 0, 16, 22, 10, 8, 10, 4, 103, 63, 176, 0, 16, 22, 10, 8, 10, 4, 103, 63, 180, 0, 16, 22, 10, 8, 10, 4, 103, 63, 184, 0, 16, 22, 10, 8, 10, 4, 103, 63, 192, 0, 16, 22, 10, 8, 10, 4, 103, 63, 196, 0, 16, 22, 10, 8, 10, 4, 103, 63, 200, 0, 16, 22, 10, 8, 10, 4, 103, 63, 204, 0, 16, 22, 10, 8, 10, 4, 103, 63, 208, 0, 16, 22, 10, 8, 10, 4, 103, 63, 240, 0, 16, 22, 10, 8, 10, 4, 103, 63, 244, 0, 16, 22, 10, 8, 10, 4, 103, 63, 248, 0, 16, 22, 10, 8, 10, 4, 103, 63, 252, 0, 16, 22, 10, 8, 10, 4, 103, 64, 0, 0, 16, 22, 10, 8, 10, 4, 103, 64, 4, 0, 16, 22, 10, 8, 10, 4, 103, 64, 24, 0, 16, 22, 10, 8, 10, 4, 103, 64, 28, 0, 16, 22, 10, 8, 10, 4, 103, 64, 32, 0, 16, 22, 10, 8, 10, 4, 103, 64, 36, 0, 16, 22, 10, 8, 10, 4, 103, 64, 40, 0, 16, 22, 10, 8, 10, 4, 103, 64, 44, 0, 16, 22, 10, 8, 10, 4, 103, 64, 48, 0, 16, 22, 10, 8, 10, 4, 103, 64, 52, 0, 16, 22, 10, 8, 10, 4, 103, 64, 56, 0, 16, 22, 10, 8, 10, 4, 103, 64, 60, 0, 16, 22, 10, 8, 10, 4, 103, 64, 64, 0, 16, 22, 10, 8, 10, 4, 103, 64, 68, 0, 16, 22, 10, 8, 10, 4, 103, 64, 72, 0, 16, 22, 10, 8, 10, 4, 103, 64, 76, 0, 16, 22, 10, 8, 10, 4, 103, 64, 80, 0, 16, 22, 10, 8, 10, 4, 103, 64, 84, 0, 16, 22, 10, 8, 10, 4, 103, 64, 88, 0, 16, 22, 10, 8, 10, 4, 103, 64, 92, 0, 16, 22, 10, 8, 10, 4, 103, 64, 96, 0, 16, 22, 10, 8, 10, 4, 103, 64, 100, 0, 16, 22, 10, 8, 10, 4, 103, 64, 104, 0, 16, 22, 10, 8, 10, 4, 103, 64, 108, 0, 16, 22, 10, 8, 10, 4, 103, 64, 112, 0, 16, 22, 10, 8, 10, 4, 103, 64, 116, 0, 16, 22, 10, 8, 10, 4, 103, 64, 120, 0, 16, 22, 10, 8, 10, 4, 103, 64, 124, 0, 16, 22, 10, 8, 10, 4, 103, 64, 140, 0, 16, 22, 10, 8, 10, 4, 103, 64, 144, 0, 16, 22, 10, 8, 10, 4, 103, 64, 152, 0, 16, 22, 10, 8, 10, 4, 103, 64, 156, 0, 16, 22, 10, 8, 10, 4, 103, 64, 160, 0, 16, 22, 10, 8, 10, 4, 103, 64, 164, 0, 16, 22, 10, 8, 10, 4, 103, 64, 168, 0, 16, 22, 10, 8, 10, 4, 103, 64, 172, 0, 16, 22, 10, 8, 10, 4, 103, 64, 176, 0, 16, 22, 10, 8, 10, 4, 103, 64, 180, 0, 16, 22, 10, 8, 10, 4, 103, 64, 184, 0, 16, 22, 10, 8, 10, 4, 103, 64, 188, 0, 16, 22, 10, 8, 10, 4, 103, 64, 192, 0, 16, 22, 10, 8, 10, 4, 103, 64, 196, 0, 16, 22, 10, 8, 10, 4, 103, 64, 200, 0, 16, 22, 10, 8, 10, 4, 103, 64, 204, 0, 16, 22, 10, 8, 10, 4, 103, 64, 208, 0, 16, 22, 10, 8, 10, 4, 103, 64, 212, 0, 16, 22, 10, 8, 10, 4, 103, 64, 216, 0, 16, 22, 10, 8, 10, 4, 103, 64, 220, 0, 16, 22, 10, 8, 10, 4, 103, 64, 224, 0, 16, 22, 10, 8, 10, 4, 103, 64, 228, 0, 16, 22, 10, 8, 10, 4, 103, 64, 232, 0, 16, 22, 10, 8, 10, 4, 103, 64, 236, 0, 16, 22, 10, 8, 10, 4, 103, 64, 240, 0, 16, 22, 10, 8, 10, 4, 103, 64, 244, 0, 16, 22, 10, 8, 10, 4, 103, 64, 248, 0, 16, 22, 10, 8, 10, 4, 103, 64, 252, 0, 16, 22, 10, 8, 10, 4, 103, 65, 0, 0, 16, 22, 10, 8, 10, 4, 103, 65, 4, 0, 16, 22, 10, 8, 10, 4, 103, 65, 8, 0, 16, 22, 10, 8, 10, 4, 103, 65, 12, 0, 16, 22, 10, 8, 10, 4, 103, 65, 16, 0, 16, 22, 10, 8, 10, 4, 103, 65, 36, 0, 16, 22, 10, 8, 10, 4, 103, 65, 40, 0, 16, 22, 10, 8, 10, 4, 103, 65, 48, 0, 16, 22, 10, 8, 10, 4, 103, 65, 52, 0, 16, 22, 10, 8, 10, 4, 103, 65, 56, 0, 16, 22, 10, 8, 10, 4, 103, 65, 60, 0, 16, 22, 10, 8, 10, 4, 103, 65, 64, 0, 16, 22, 10, 8, 10, 4, 103, 65, 68, 0, 16, 22, 10, 8, 10, 4, 103, 65, 72, 0, 16, 22, 10, 8, 10, 4, 103, 65, 76, 0, 16, 22, 10, 8, 10, 4, 103, 65, 80, 0, 16, 22, 10, 8, 10, 4, 103, 65, 84, 0, 16, 22, 10, 8, 10, 4, 103, 65, 88, 0, 16, 22, 10, 8, 10, 4, 103, 65, 92, 0, 16, 22, 10, 8, 10, 4, 103, 65, 100, 0, 16, 22, 10, 8, 10, 4, 103, 65, 104, 0, 16, 22, 10, 8, 10, 4, 103, 65, 108, 0, 16, 22, 10, 8, 10, 4, 103, 65, 112, 0, 16, 22, 10, 8, 10, 4, 103, 65, 144, 0, 16, 22, 10, 8, 10, 4, 103, 65, 148, 0, 16, 22, 10, 8, 10, 4, 103, 65, 152, 0, 16, 22, 10, 8, 10, 4, 103, 65, 156, 0, 16, 22, 10, 8, 10, 4, 103, 65, 160, 0, 16, 22, 10, 8, 10, 4, 103, 65, 164, 0, 16, 22, 10, 8, 10, 4, 103, 65, 168, 0, 16, 22, 10, 8, 10, 4, 103, 65, 172, 0, 16, 22, 10, 8, 10, 4, 103, 66, 32, 0, 16, 22, 10, 8, 10, 4, 103, 66, 40, 0, 16, 22, 10, 8, 10, 4, 103, 66, 92, 0, 16, 22, 10, 8, 10, 4, 103, 66, 108, 0, 16, 22, 10, 8, 10, 4, 103, 66, 200, 0, 16, 22, 10, 8, 10, 4, 103, 66, 216, 0, 16, 22, 10, 8, 10, 4, 103, 66, 240, 0, 16, 22, 10, 8, 10, 4, 103, 66, 244, 0, 16, 22, 10, 8, 10, 4, 103, 66, 248, 0, 16, 22, 10, 8, 10, 4, 103, 66, 252, 0, 16, 22, 10, 8, 10, 4, 103, 67, 0, 0, 16, 22, 10, 8, 10, 4, 103, 67, 4, 0, 16, 22, 10, 8, 10, 4, 103, 67, 8, 0, 16, 22, 10, 8, 10, 4, 103, 67, 100, 0, 16, 22, 10, 8, 10, 4, 103, 67, 104, 0, 16, 22, 10, 8, 10, 4, 103, 67, 108, 0, 16, 22, 10, 8, 10, 4, 103, 67, 112, 0, 16, 22, 10, 8, 10, 4, 103, 67, 116, 0, 16, 22, 10, 8, 10, 4, 103, 67, 120, 0, 16, 22, 10, 8, 10, 4, 103, 67, 124, 0, 16, 22, 10, 8, 10, 4, 103, 67, 128, 0, 16, 22, 10, 8, 10, 4, 103, 67, 132, 0, 16, 22, 10, 8, 10, 4, 103, 67, 136, 0, 16, 22, 10, 8, 10, 4, 103, 67, 140, 0, 16, 22, 10, 8, 10, 4, 103, 67, 144, 0, 16, 22, 10, 8, 10, 4, 103, 67, 148, 0, 16, 22, 10, 8, 10, 4, 103, 67, 172, 0, 16, 22, 10, 8, 10, 4, 103, 67, 192, 0, 16, 22, 10, 8, 10, 4, 103, 67, 212, 0, 16, 22, 10, 8, 10, 4, 103, 67, 252, 0, 16, 22, 10, 8, 10, 4, 103, 68, 64, 0, 16, 22, 10, 8, 10, 4, 103, 68, 88, 0, 16, 22, 10, 8, 10, 4, 103, 68, 100, 0, 16, 22, 10, 8, 10, 4, 103, 68, 128, 0, 16, 22, 10, 8, 10, 4, 103, 68, 192, 0, 16, 22, 10, 8, 10, 4, 103, 69, 16, 0, 16, 22, 10, 8, 10, 4, 103, 69, 116, 0, 16, 22, 10, 8, 10, 4, 103, 69, 132, 0, 16, 22, 10, 8, 10, 4, 103, 69, 152, 0, 16, 22, 10, 8, 10, 4, 103, 69, 212, 0, 16, 22, 10, 8, 10, 4, 103, 70, 8, 0, 16, 22, 10, 8, 10, 4, 103, 70, 148, 0, 16, 22, 10, 8, 10, 4, 103, 70, 184, 0, 16, 22, 10, 8, 10, 4, 103, 70, 220, 0, 16, 22, 10, 8, 10, 4, 103, 70, 224, 0, 16, 22, 10, 8, 10, 4, 103, 70, 236, 0, 16, 22, 10, 8, 10, 4, 103, 70, 252, 0, 16, 22, 10, 8, 10, 4, 103, 71, 0, 0, 16, 22, 10, 8, 10, 4, 103, 71, 32, 0, 16, 22, 10, 8, 10, 4, 103, 71, 48, 0, 16, 22, 10, 8, 10, 4, 103, 71, 68, 0, 16, 22, 10, 8, 10, 4, 103, 71, 72, 0, 16, 22, 10, 8, 10, 4, 103, 71, 80, 0, 16, 22, 10, 8, 10, 4, 103, 71, 84, 0, 16, 22, 10, 8, 10, 4, 103, 71, 88, 0, 16, 22, 10, 8, 10, 4, 103, 71, 120, 0, 16, 22, 10, 8, 10, 4, 103, 71, 124, 0, 16, 22, 10, 8, 10, 4, 103, 71, 128, 0, 16, 22, 10, 8, 10, 4, 103, 71, 144, 0, 16, 22, 10, 8, 10, 4, 103, 71, 196, 0, 16, 22, 10, 8, 10, 4, 103, 71, 200, 0, 16, 22, 10, 8, 10, 4, 103, 71, 232, 0, 16, 22, 10, 8, 10, 4, 103, 72, 12, 0, 16, 22, 10, 8, 10, 4, 103, 72, 16, 0, 16, 22, 10, 8, 10, 4, 103, 72, 20, 0, 16, 22, 10, 8, 10, 4, 103, 72, 24, 0, 16, 22, 10, 8, 10, 4, 103, 72, 28, 0, 16, 22, 10, 8, 10, 4, 103, 72, 32, 0, 16, 22, 10, 8, 10, 4, 103, 72, 36, 0, 16, 22, 10, 8, 10, 4, 103, 72, 40, 0, 16, 22, 10, 8, 10, 4, 103, 72, 44, 0, 16, 22, 10, 8, 10, 4, 103, 72, 48, 0, 16, 22, 10, 8, 10, 4, 103, 72, 52, 0, 16, 22, 10, 8, 10, 4, 103, 72, 112, 0, 16, 22, 10, 8, 10, 4, 103, 72, 116, 0, 16, 22, 10, 8, 10, 4, 103, 72, 120, 0, 16, 22, 10, 8, 10, 4, 103, 72, 124, 0, 16, 22, 10, 8, 10, 4, 103, 72, 128, 0, 16, 22, 10, 8, 10, 4, 103, 72, 132, 0, 16, 22, 10, 8, 10, 4, 103, 72, 144, 0, 16, 22, 10, 8, 10, 4, 103, 72, 148, 0, 16, 22, 10, 8, 10, 4, 103, 72, 164, 0, 16, 22, 10, 8, 10, 4, 103, 72, 172, 0, 16, 22, 10, 8, 10, 4, 103, 72, 180, 0, 16, 22, 10, 8, 10, 4, 103, 72, 224, 0, 16, 22, 10, 8, 10, 4, 103, 72, 228, 0, 16, 22, 10, 8, 10, 4, 103, 72, 232, 0, 16, 22, 10, 8, 10, 4, 103, 72, 236, 0, 16, 22, 10, 8, 10, 4, 103, 72, 240, 0, 16, 22, 10, 8, 10, 4, 103, 72, 244, 0, 16, 22, 10, 8, 10, 4, 103, 72, 248, 0, 16, 22, 10, 8, 10, 4, 103, 72, 252, 0, 16, 22, 10, 8, 10, 4, 103, 73, 0, 0, 16, 22, 10, 8, 10, 4, 103, 73, 4, 0, 16, 22, 10, 8, 10, 4, 103, 73, 8, 0, 16, 22, 10, 8, 10, 4, 103, 73, 12, 0, 16, 22, 10, 8, 10, 4, 103, 73, 16, 0, 16, 22, 10, 8, 10, 4, 103, 73, 20, 0, 16, 22, 10, 8, 10, 4, 103, 73, 24, 0, 16, 22, 10, 8, 10, 4, 103, 73, 28, 0, 16, 22, 10, 8, 10, 4, 103, 73, 48, 0, 16, 22, 10, 8, 10, 4, 103, 73, 88, 0, 16, 22, 10, 8, 10, 4, 103, 73, 96, 0, 16, 22, 10, 8, 10, 4, 103, 73, 116, 0, 16, 22, 10, 8, 10, 4, 103, 73, 120, 0, 16, 22, 10, 8, 10, 4, 103, 73, 128, 0, 16, 22, 10, 8, 10, 4, 103, 73, 132, 0, 16, 22, 10, 8, 10, 4, 103, 73, 136, 0, 16, 22, 10, 8, 10, 4, 103, 73, 140, 0, 16, 22, 10, 8, 10, 4, 103, 73, 144, 0, 16, 22, 10, 8, 10, 4, 103, 73, 168, 0, 16, 22, 10, 8, 10, 4, 103, 73, 176, 0, 16, 22, 10, 8, 10, 4, 103, 73, 204, 0, 16, 22, 10, 8, 10, 4, 103, 73, 208, 0, 16, 22, 10, 8, 10, 4, 103, 73, 240, 0, 16, 22, 10, 8, 10, 4, 103, 73, 244, 0, 16, 22, 10, 8, 10, 4, 103, 73, 248, 0, 16, 22, 10, 8, 10, 4, 103, 74, 24, 0, 16, 22, 10, 8, 10, 4, 103, 74, 28, 0, 16, 22, 10, 8, 10, 4, 103, 74, 32, 0, 16, 22, 10, 8, 10, 4, 103, 74, 36, 0, 16, 22, 10, 8, 10, 4, 103, 74, 40, 0, 16, 22, 10, 8, 10, 4, 103, 74, 44, 0, 16, 22, 10, 8, 10, 4, 103, 74, 48, 0, 16, 22, 10, 8, 10, 4, 103, 74, 56, 0, 16, 22, 10, 8, 10, 4, 103, 74, 60, 0, 16, 22, 10, 8, 10, 4, 103, 74, 80, 0, 16, 22, 10, 8, 10, 4, 103, 74, 124, 0, 16, 22, 10, 8, 10, 4, 103, 74, 148, 0, 16, 22, 10, 8, 10, 4, 103, 74, 152, 0, 16, 22, 10, 8, 10, 4, 103, 74, 156, 0, 16, 22, 10, 8, 10, 4, 103, 74, 204, 0, 16, 22, 10, 8, 10, 4, 103, 74, 232, 0, 16, 22, 10, 8, 10, 4, 103, 75, 16, 0, 16, 22, 10, 8, 10, 4, 103, 75, 84, 0, 16, 22, 10, 8, 10, 4, 103, 75, 88, 0, 16, 22, 10, 8, 10, 4, 103, 75, 92, 0, 16, 22, 10, 8, 10, 4, 103, 75, 104, 0, 16, 22, 10, 8, 10, 4, 103, 75, 108, 0, 16, 22, 10, 8, 10, 4, 103, 75, 112, 0, 16, 22, 10, 8, 10, 4, 103, 75, 120, 0, 16, 22, 10, 8, 10, 4, 103, 75, 128, 0, 16, 22, 10, 8, 10, 4, 103, 75, 144, 0, 16, 22, 10, 8, 10, 4, 103, 75, 152, 0, 16, 22, 10, 8, 10, 4, 103, 75, 236, 0, 16, 24, 10, 8, 10, 4, 103, 76, 60, 0, 16, 22, 10, 8, 10, 4, 103, 76, 64, 0, 16, 22, 10, 8, 10, 4, 103, 76, 68, 0, 16, 22, 10, 8, 10, 4, 103, 76, 72, 0, 16, 22, 10, 8, 10, 4, 103, 76, 84, 0, 16, 22, 10, 8, 10, 4, 103, 76, 92, 0, 16, 22, 10, 8, 10, 4, 103, 76, 104, 0, 16, 22, 10, 8, 10, 4, 103, 76, 216, 0, 16, 22, 10, 8, 10, 4, 103, 76, 220, 0, 16, 22, 10, 8, 10, 4, 103, 76, 224, 0, 16, 22, 10, 8, 10, 4, 103, 77, 28, 0, 16, 22, 10, 8, 10, 4, 103, 77, 52, 0, 16, 22, 10, 8, 10, 4, 103, 77, 56, 0, 16, 22, 10, 8, 10, 4, 103, 77, 72, 0, 16, 22, 10, 8, 10, 4, 103, 77, 88, 0, 16, 22, 10, 8, 10, 4, 103, 77, 92, 0, 16, 22, 10, 8, 10, 4, 103, 77, 132, 0, 16, 22, 10, 8, 10, 4, 103, 77, 148, 0, 16, 22, 10, 8, 10, 4, 103, 77, 220, 0, 16, 22, 10, 8, 10, 4, 103, 78, 56, 0, 16, 22, 10, 8, 10, 4, 103, 78, 60, 0, 16, 22, 10, 8, 10, 4, 103, 78, 64, 0, 16, 22, 10, 8, 10, 4, 103, 78, 68, 0, 16, 22, 10, 8, 10, 4, 103, 78, 124, 0, 16, 22, 10, 8, 10, 4, 103, 78, 172, 0, 16, 22, 10, 8, 10, 4, 103, 78, 176, 0, 16, 22, 10, 8, 10, 4, 103, 78, 196, 0, 16, 22, 10, 8, 10, 4, 103, 78, 228, 0, 16, 22, 10, 8, 10, 4, 103, 79, 24, 0, 16, 22, 10, 8, 10, 4, 103, 79, 28, 0, 16, 22, 10, 8, 10, 4, 103, 79, 36, 0, 16, 22, 10, 8, 10, 4, 103, 79, 40, 0, 16, 22, 10, 8, 10, 4, 103, 79, 44, 0, 16, 22, 10, 8, 10, 4, 103, 79, 52, 0, 16, 22, 10, 8, 10, 4, 103, 79, 56, 0, 16, 22, 10, 8, 10, 4, 103, 79, 60, 0, 16, 22, 10, 8, 10, 4, 103, 79, 64, 0, 16, 22, 10, 8, 10, 4, 103, 79, 68, 0, 16, 22, 10, 8, 10, 4, 103, 79, 80, 0, 16, 22, 10, 8, 10, 4, 103, 79, 84, 0, 16, 22, 10, 8, 10, 4, 103, 79, 120, 0, 16, 22, 10, 8, 10, 4, 103, 79, 136, 0, 16, 22, 10, 8, 10, 4, 103, 79, 188, 0, 16, 22, 10, 8, 10, 4, 103, 79, 192, 0, 16, 22, 10, 8, 10, 4, 103, 79, 196, 0, 16, 22, 10, 8, 10, 4, 103, 79, 200, 0, 16, 22, 10, 8, 10, 4, 103, 79, 204, 0, 16, 22, 10, 8, 10, 4, 103, 79, 208, 0, 16, 22, 10, 8, 10, 4, 103, 79, 212, 0, 16, 22, 10, 8, 10, 4, 103, 79, 240, 0, 16, 22, 10, 8, 10, 4, 103, 80, 24, 0, 16, 22, 10, 8, 10, 4, 103, 80, 28, 0, 16, 22, 10, 8, 10, 4, 103, 80, 44, 0, 16, 22, 10, 8, 10, 4, 103, 80, 72, 0, 16, 22, 10, 8, 10, 4, 103, 80, 176, 0, 16, 22, 10, 8, 10, 4, 103, 80, 180, 0, 16, 22, 10, 8, 10, 4, 103, 80, 184, 0, 16, 22, 10, 8, 10, 4, 103, 80, 192, 0, 16, 22, 10, 8, 10, 4, 103, 80, 200, 0, 16, 22, 10, 8, 10, 4, 103, 80, 212, 0, 16, 22, 10, 8, 10, 4, 103, 80, 232, 0, 16, 22, 10, 8, 10, 4, 103, 81, 4, 0, 16, 22, 10, 8, 10, 4, 103, 81, 8, 0, 16, 22, 10, 8, 10, 4, 103, 81, 16, 0, 16, 22, 10, 8, 10, 4, 103, 81, 20, 0, 16, 22, 10, 8, 10, 4, 103, 81, 44, 0, 16, 22, 10, 8, 10, 4, 103, 81, 48, 0, 16, 22, 10, 8, 10, 4, 103, 81, 96, 0, 16, 22, 10, 8, 10, 4, 103, 81, 120, 0, 16, 22, 10, 8, 10, 4, 103, 81, 148, 0, 16, 22, 10, 8, 10, 4, 103, 81, 164, 0, 16, 22, 10, 8, 10, 4, 103, 81, 168, 0, 16, 22, 10, 8, 10, 4, 103, 81, 183, 0, 16, 24, 10, 8, 10, 4, 103, 81, 184, 0, 16, 22, 10, 8, 10, 4, 103, 81, 200, 0, 16, 22, 10, 8, 10, 4, 103, 81, 232, 0, 16, 22, 10, 8, 10, 4, 103, 82, 52, 0, 16, 22, 10, 8, 10, 4, 103, 82, 60, 0, 16, 22, 10, 8, 10, 4, 103, 82, 68, 0, 16, 22, 10, 8, 10, 4, 103, 82, 84, 0, 16, 22, 10, 8, 10, 4, 103, 82, 104, 0, 16, 22, 10, 8, 10, 4, 103, 82, 224, 0, 16, 22, 10, 8, 10, 4, 103, 82, 236, 0, 16, 22, 10, 8, 10, 4, 103, 83, 44, 0, 16, 22, 10, 8, 10, 4, 103, 83, 52, 0, 16, 22, 10, 8, 10, 4, 103, 83, 60, 0, 16, 22, 10, 8, 10, 4, 103, 83, 64, 0, 16, 22, 10, 8, 10, 4, 103, 83, 72, 0, 16, 22, 10, 8, 10, 4, 103, 83, 112, 0, 16, 22, 10, 8, 10, 4, 103, 83, 120, 0, 16, 22, 10, 8, 10, 4, 103, 83, 180, 0, 16, 22, 10, 8, 10, 4, 103, 84, 0, 0, 16, 22, 10, 8, 10, 4, 103, 84, 12, 0, 16, 22, 10, 8, 10, 4, 103, 84, 16, 0, 16, 22, 10, 8, 10, 4, 103, 84, 20, 0, 16, 22, 10, 8, 10, 4, 103, 84, 24, 0, 16, 22, 10, 8, 10, 4, 103, 84, 28, 0, 16, 22, 10, 8, 10, 4, 103, 84, 48, 0, 16, 22, 10, 8, 10, 4, 103, 84, 56, 0, 16, 22, 10, 8, 10, 4, 103, 84, 64, 0, 16, 22, 10, 8, 10, 4, 103, 84, 72, 0, 16, 22, 10, 8, 10, 4, 103, 84, 92, 0, 16, 22, 10, 8, 10, 4, 103, 84, 108, 0, 16, 22, 10, 8, 10, 4, 103, 84, 136, 0, 16, 22, 10, 8, 10, 4, 103, 85, 20, 0, 16, 22, 10, 8, 10, 4, 103, 85, 24, 0, 16, 22, 10, 8, 10, 4, 103, 85, 44, 0, 16, 22, 10, 8, 10, 4, 103, 85, 48, 0, 16, 22, 10, 8, 10, 4, 103, 85, 52, 0, 16, 22, 10, 8, 10, 4, 103, 85, 56, 0, 16, 22, 10, 8, 10, 4, 103, 85, 84, 0, 16, 22, 10, 8, 10, 4, 103, 85, 136, 0, 16, 22, 10, 8, 10, 4, 103, 85, 144, 0, 16, 22, 10, 8, 10, 4, 103, 85, 164, 0, 16, 22, 10, 8, 10, 4, 103, 85, 168, 0, 16, 22, 10, 8, 10, 4, 103, 85, 172, 0, 16, 22, 10, 8, 10, 4, 103, 85, 176, 0, 16, 22, 10, 8, 10, 4, 103, 85, 224, 0, 16, 22, 10, 8, 10, 4, 103, 86, 28, 0, 16, 22, 10, 8, 10, 4, 103, 86, 32, 0, 16, 22, 10, 8, 10, 4, 103, 86, 44, 0, 16, 22, 10, 8, 10, 4, 103, 86, 60, 0, 16, 22, 10, 8, 10, 4, 103, 86, 68, 0, 16, 22, 10, 8, 10, 4, 103, 86, 80, 0, 16, 22, 10, 8, 10, 4, 103, 86, 84, 0, 16, 22, 10, 8, 10, 4, 103, 86, 88, 0, 16, 22, 10, 8, 10, 4, 103, 86, 129, 0, 16, 24, 10, 8, 10, 4, 103, 86, 204, 0, 16, 22, 10, 8, 10, 4, 103, 86, 208, 0, 16, 22, 10, 8, 10, 4, 103, 86, 212, 0, 16, 22, 10, 8, 10, 4, 103, 86, 216, 0, 16, 22, 10, 8, 10, 4, 103, 86, 220, 0, 16, 22, 10, 8, 10, 4, 103, 86, 224, 0, 16, 22, 10, 8, 10, 4, 103, 86, 228, 0, 16, 22, 10, 8, 10, 4, 103, 86, 232, 0, 16, 22, 10, 8, 10, 4, 103, 86, 236, 0, 16, 22, 10, 8, 10, 4, 103, 86, 240, 0, 16, 22, 10, 8, 10, 4, 103, 86, 244, 0, 16, 22, 10, 8, 10, 4, 103, 86, 248, 0, 16, 22, 10, 8, 10, 4, 103, 86, 252, 0, 16, 22, 10, 8, 10, 4, 103, 87, 0, 0, 16, 22, 10, 8, 10, 4, 103, 87, 4, 0, 16, 22, 10, 8, 10, 4, 103, 87, 20, 0, 16, 22, 10, 8, 10, 4, 103, 87, 32, 0, 16, 22, 10, 8, 10, 4, 103, 87, 72, 0, 16, 22, 10, 8, 10, 4, 103, 87, 96, 0, 16, 22, 10, 8, 10, 4, 103, 87, 132, 0, 16, 22, 10, 8, 10, 4, 103, 87, 180, 0, 16, 22, 10, 8, 10, 4, 103, 87, 224, 0, 16, 22, 10, 8, 10, 4, 103, 88, 4, 0, 16, 22, 10, 8, 10, 4, 103, 88, 8, 0, 16, 22, 10, 8, 10, 4, 103, 88, 12, 0, 16, 22, 10, 8, 10, 4, 103, 88, 16, 0, 16, 22, 10, 8, 10, 4, 103, 88, 20, 0, 16, 22, 10, 8, 10, 4, 103, 88, 32, 0, 16, 22, 10, 8, 10, 4, 103, 88, 36, 0, 16, 22, 10, 8, 10, 4, 103, 88, 60, 0, 16, 22, 10, 8, 10, 4, 103, 88, 64, 0, 16, 22, 10, 8, 10, 4, 103, 88, 72, 0, 16, 22, 10, 8, 10, 4, 103, 88, 96, 0, 16, 22, 10, 8, 10, 4, 103, 88, 100, 0, 16, 22, 10, 8, 10, 4, 103, 88, 139, 0, 16, 24, 10, 8, 10, 4, 103, 88, 152, 0, 16, 23, 10, 8, 10, 4, 103, 88, 164, 0, 16, 22, 10, 8, 10, 4, 103, 88, 176, 0, 16, 22, 10, 8, 10, 4, 103, 88, 184, 0, 16, 22, 10, 8, 10, 4, 103, 88, 188, 0, 16, 22, 10, 8, 10, 4, 103, 88, 212, 0, 16, 22, 10, 8, 10, 4, 103, 89, 28, 0, 16, 22, 10, 8, 10, 4, 103, 89, 96, 0, 16, 22, 10, 8, 10, 4, 103, 89, 100, 0, 16, 22, 10, 8, 10, 4, 103, 89, 104, 0, 16, 22, 10, 8, 10, 4, 103, 89, 108, 0, 16, 22, 10, 8, 10, 4, 103, 89, 112, 0, 16, 22, 10, 8, 10, 4, 103, 89, 116, 0, 16, 22, 10, 8, 10, 4, 103, 89, 148, 0, 16, 22, 10, 8, 10, 4, 103, 89, 172, 0, 16, 22, 10, 8, 10, 4, 103, 89, 184, 0, 16, 22, 10, 8, 10, 4, 103, 89, 188, 0, 16, 22, 10, 8, 10, 4, 103, 89, 192, 0, 16, 22, 10, 8, 10, 4, 103, 89, 196, 0, 16, 22, 10, 8, 10, 4, 103, 89, 200, 0, 16, 22, 10, 8, 10, 4, 103, 89, 204, 0, 16, 22, 10, 8, 10, 4, 103, 89, 208, 0, 16, 22, 10, 8, 10, 4, 103, 89, 212, 0, 16, 22, 10, 8, 10, 4, 103, 89, 216, 0, 16, 22, 10, 8, 10, 4, 103, 89, 220, 0, 16, 22, 10, 8, 10, 4, 103, 89, 224, 0, 16, 22, 10, 8, 10, 4, 103, 89, 228, 0, 16, 22, 10, 8, 10, 4, 103, 90, 52, 0, 16, 22, 10, 8, 10, 4, 103, 90, 92, 0, 16, 22, 10, 8, 10, 4, 103, 90, 100, 0, 16, 22, 10, 8, 10, 4, 103, 90, 104, 0, 16, 22, 10, 8, 10, 4, 103, 90, 108, 0, 16, 22, 10, 8, 10, 4, 103, 90, 112, 0, 16, 22, 10, 8, 10, 4, 103, 90, 116, 0, 16, 22, 10, 8, 10, 4, 103, 90, 120, 0, 16, 22, 10, 8, 10, 4, 103, 90, 124, 0, 16, 22, 10, 8, 10, 4, 103, 90, 128, 0, 16, 22, 10, 8, 10, 4, 103, 90, 132, 0, 16, 22, 10, 8, 10, 4, 103, 90, 152, 0, 16, 22, 10, 8, 10, 4, 103, 90, 168, 0, 16, 22, 10, 8, 10, 4, 103, 90, 173, 0, 16, 24, 10, 8, 10, 4, 103, 90, 176, 0, 16, 22, 10, 8, 10, 4, 103, 90, 188, 0, 16, 22, 10, 8, 10, 4, 103, 90, 192, 0, 16, 22, 10, 8, 10, 4, 103, 91, 36, 0, 16, 22, 10, 8, 10, 4, 103, 91, 40, 0, 16, 22, 10, 8, 10, 4, 103, 91, 108, 0, 16, 22, 10, 8, 10, 4, 103, 91, 152, 0, 16, 22, 10, 8, 10, 4, 103, 91, 176, 0, 16, 22, 10, 8, 10, 4, 103, 91, 200, 0, 16, 22, 10, 8, 10, 4, 103, 91, 208, 0, 16, 22, 10, 8, 10, 4, 103, 91, 212, 0, 16, 22, 10, 8, 10, 4, 103, 91, 219, 0, 16, 24, 10, 8, 10, 4, 103, 91, 236, 0, 16, 22, 10, 8, 10, 4, 103, 91, 252, 0, 16, 22, 10, 8, 10, 4, 103, 92, 0, 0, 16, 22, 10, 8, 10, 4, 103, 92, 4, 0, 16, 22, 10, 8, 10, 4, 103, 92, 8, 0, 16, 22, 10, 8, 10, 4, 103, 92, 12, 0, 16, 22, 10, 8, 10, 4, 103, 92, 48, 0, 16, 22, 10, 8, 10, 4, 103, 92, 52, 0, 16, 22, 10, 8, 10, 4, 103, 92, 56, 0, 16, 22, 10, 8, 10, 4, 103, 92, 60, 0, 16, 22, 10, 8, 10, 4, 103, 92, 64, 0, 16, 22, 10, 8, 10, 4, 103, 92, 68, 0, 16, 22, 10, 8, 10, 4, 103, 92, 72, 0, 16, 22, 10, 8, 10, 4, 103, 92, 76, 0, 16, 22, 10, 8, 10, 4, 103, 92, 80, 0, 16, 22, 10, 8, 10, 4, 103, 92, 86, 0, 16, 24, 10, 8, 10, 4, 103, 92, 88, 0, 16, 22, 10, 8, 10, 4, 103, 92, 108, 0, 16, 22, 10, 8, 10, 4, 103, 92, 124, 0, 16, 22, 10, 8, 10, 4, 103, 92, 128, 0, 16, 24, 10, 8, 10, 4, 103, 92, 132, 0, 16, 22, 10, 8, 10, 4, 103, 92, 156, 0, 16, 22, 10, 8, 10, 4, 103, 92, 164, 0, 16, 22, 10, 8, 10, 4, 103, 92, 168, 0, 16, 22, 10, 8, 10, 4, 103, 92, 172, 0, 16, 22, 10, 8, 10, 4, 103, 92, 176, 0, 16, 22, 10, 8, 10, 4, 103, 92, 180, 0, 16, 22, 10, 8, 10, 4, 103, 92, 184, 0, 16, 22, 10, 8, 10, 4, 103, 92, 188, 0, 16, 22, 10, 8, 10, 4, 103, 92, 192, 0, 16, 22, 10, 8, 10, 4, 103, 92, 236, 0, 16, 22, 10, 8, 10, 4, 103, 92, 240, 0, 16, 22, 10, 8, 10, 4, 103, 92, 244, 0, 16, 22, 10, 8, 10, 4, 103, 92, 248, 0, 16, 22, 10, 8, 10, 4, 103, 92, 252, 0, 16, 22, 10, 8, 10, 4, 103, 93, 0, 0, 16, 22, 10, 8, 10, 4, 103, 93, 4, 0, 16, 22, 10, 8, 10, 4, 103, 93, 28, 0, 16, 22, 10, 8, 10, 4, 103, 93, 76, 0, 16, 22, 10, 8, 10, 4, 103, 93, 84, 0, 16, 22, 10, 8, 10, 4, 103, 93, 121, 0, 16, 24, 10, 8, 10, 4, 103, 93, 152, 0, 16, 22, 10, 8, 10, 4, 103, 93, 180, 0, 16, 22, 10, 8, 10, 4, 103, 93, 204, 0, 16, 22, 10, 8, 10, 4, 103, 94, 12, 0, 16, 22, 10, 8, 10, 4, 103, 94, 20, 0, 16, 22, 10, 8, 10, 4, 103, 94, 28, 0, 16, 22, 10, 8, 10, 4, 103, 94, 32, 0, 16, 22, 10, 8, 10, 4, 103, 94, 36, 0, 16, 22, 10, 8, 10, 4, 103, 94, 40, 0, 16, 22, 10, 8, 10, 4, 103, 94, 44, 0, 16, 22, 10, 8, 10, 4, 103, 94, 72, 0, 16, 22, 10, 8, 10, 4, 103, 94, 88, 0, 16, 22, 10, 8, 10, 4, 103, 94, 116, 0, 16, 22, 10, 8, 10, 4, 103, 94, 160, 0, 16, 22, 10, 8, 10, 4, 103, 94, 180, 0, 16, 22, 10, 8, 10, 4, 103, 94, 200, 0, 16, 22, 10, 8, 10, 4, 103, 95, 28, 0, 16, 22, 10, 8, 10, 4, 103, 95, 52, 0, 16, 22, 10, 8, 10, 4, 103, 95, 64, 0, 16, 22, 10, 8, 10, 4, 103, 95, 68, 0, 16, 22, 10, 8, 10, 4, 103, 95, 88, 0, 16, 22, 10, 8, 10, 4, 103, 95, 92, 0, 16, 22, 10, 8, 10, 4, 103, 95, 116, 0, 16, 22, 10, 8, 10, 4, 103, 95, 128, 0, 16, 22, 10, 8, 10, 4, 103, 95, 136, 0, 16, 22, 10, 8, 10, 4, 103, 95, 140, 0, 16, 22, 10, 8, 10, 4, 103, 95, 144, 0, 16, 22, 10, 8, 10, 4, 103, 95, 152, 0, 16, 22, 10, 8, 10, 4, 103, 95, 207, 0, 16, 24, 10, 8, 10, 4, 103, 95, 216, 0, 16, 22, 10, 8, 10, 4, 103, 95, 220, 0, 16, 22, 10, 8, 10, 4, 103, 95, 224, 0, 16, 22, 10, 8, 10, 4, 103, 95, 236, 0, 16, 22, 10, 8, 10, 4, 103, 95, 240, 0, 16, 22, 10, 8, 10, 4, 103, 95, 244, 0, 16, 22, 10, 8, 10, 4, 103, 95, 248, 0, 16, 22, 10, 8, 10, 4, 103, 95, 252, 0, 16, 22, 10, 8, 10, 4, 103, 96, 0, 0, 16, 22, 10, 8, 10, 4, 103, 96, 8, 0, 16, 22, 10, 8, 10, 4, 103, 96, 80, 0, 16, 22, 10, 8, 10, 4, 103, 96, 124, 0, 16, 22, 10, 8, 10, 4, 103, 96, 136, 0, 16, 22, 10, 8, 10, 4, 103, 96, 140, 0, 16, 24, 10, 8, 10, 4, 103, 96, 148, 0, 16, 22, 10, 8, 10, 4, 103, 96, 152, 0, 16, 22, 10, 8, 10, 4, 103, 96, 156, 0, 16, 22, 10, 8, 10, 4, 103, 96, 160, 0, 16, 22, 10, 8, 10, 4, 103, 96, 164, 0, 16, 22, 10, 8, 10, 4, 103, 96, 168, 0, 16, 22, 10, 8, 10, 4, 103, 96, 172, 0, 16, 22, 10, 8, 10, 4, 103, 96, 176, 0, 16, 22, 10, 8, 10, 4, 103, 96, 180, 0, 16, 22, 10, 8, 10, 4, 103, 96, 184, 0, 16, 22, 10, 8, 10, 4, 103, 96, 188, 0, 16, 22, 10, 8, 10, 4, 103, 96, 192, 0, 16, 22, 10, 8, 10, 4, 103, 96, 196, 0, 16, 22, 10, 8, 10, 4, 103, 96, 200, 0, 16, 22, 10, 8, 10, 4, 103, 96, 204, 0, 16, 22, 10, 8, 10, 4, 103, 96, 208, 0, 16, 22, 10, 8, 10, 4, 103, 96, 212, 0, 16, 22, 10, 8, 10, 4, 103, 96, 216, 0, 16, 22, 10, 8, 10, 4, 103, 97, 8, 0, 16, 22, 10, 8, 10, 4, 103, 97, 12, 0, 16, 22, 10, 8, 10, 4, 103, 97, 16, 0, 16, 22, 10, 8, 10, 4, 103, 97, 20, 0, 16, 22, 10, 8, 10, 4, 103, 97, 24, 0, 16, 22, 10, 8, 10, 4, 103, 97, 28, 0, 16, 22, 10, 8, 10, 4, 103, 97, 32, 0, 16, 22, 10, 8, 10, 4, 103, 97, 36, 0, 16, 22, 10, 8, 10, 4, 103, 97, 40, 0, 16, 22, 10, 8, 10, 4, 103, 97, 56, 0, 16, 22, 10, 8, 10, 4, 103, 97, 60, 0, 16, 22, 10, 8, 10, 4, 103, 97, 64, 0, 16, 22, 10, 8, 10, 4, 103, 97, 68, 0, 16, 22, 10, 8, 10, 4, 103, 97, 72, 0, 16, 22, 10, 8, 10, 4, 103, 97, 80, 0, 16, 22, 10, 8, 10, 4, 103, 97, 112, 0, 16, 22, 10, 8, 10, 4, 103, 97, 116, 0, 16, 22, 10, 8, 10, 4, 103, 97, 128, 0, 16, 22, 10, 8, 10, 4, 103, 97, 144, 0, 16, 22, 10, 8, 10, 4, 103, 97, 148, 0, 16, 22, 10, 8, 10, 4, 103, 97, 188, 0, 16, 22, 10, 8, 10, 4, 103, 97, 192, 0, 16, 22, 10, 8, 10, 4, 103, 97, 224, 0, 16, 22, 10, 8, 10, 4, 103, 97, 228, 0, 16, 23, 10, 8, 10, 4, 103, 98, 28, 0, 16, 23, 10, 8, 10, 4, 103, 98, 40, 0, 16, 22, 10, 8, 10, 4, 103, 98, 44, 0, 16, 22, 10, 8, 10, 4, 103, 98, 48, 0, 16, 22, 10, 8, 10, 4, 103, 98, 56, 0, 16, 22, 10, 8, 10, 4, 103, 98, 80, 0, 16, 22, 10, 8, 10, 4, 103, 98, 88, 0, 16, 22, 10, 8, 10, 4, 103, 98, 92, 0, 16, 22, 10, 8, 10, 4, 103, 98, 96, 0, 16, 22, 10, 8, 10, 4, 103, 98, 100, 0, 16, 22, 10, 8, 10, 4, 103, 98, 124, 0, 16, 22, 10, 8, 10, 4, 103, 98, 136, 0, 16, 22, 10, 8, 10, 4, 103, 98, 140, 0, 16, 22, 10, 8, 10, 4, 103, 98, 144, 0, 16, 22, 10, 8, 10, 4, 103, 98, 164, 0, 16, 22, 10, 8, 10, 4, 103, 98, 168, 0, 16, 22, 10, 8, 10, 4, 103, 98, 180, 0, 16, 22, 10, 8, 10, 4, 103, 98, 196, 0, 16, 22, 10, 8, 10, 4, 103, 98, 216, 0, 16, 22, 10, 8, 10, 4, 103, 98, 220, 0, 16, 22, 10, 8, 10, 4, 103, 98, 224, 0, 16, 22, 10, 8, 10, 4, 103, 98, 228, 0, 16, 22, 10, 8, 10, 4, 103, 98, 232, 0, 16, 22, 10, 8, 10, 4, 103, 98, 240, 0, 16, 22, 10, 8, 10, 4, 103, 98, 244, 0, 16, 22, 10, 8, 10, 4, 103, 98, 248, 0, 16, 22, 10, 8, 10, 4, 103, 98, 252, 0, 16, 22, 10, 8, 10, 4, 103, 99, 40, 0, 16, 23, 10, 8, 10, 4, 103, 99, 52, 0, 16, 22, 10, 8, 10, 4, 103, 99, 56, 0, 16, 22, 10, 8, 10, 4, 103, 99, 60, 0, 16, 22, 10, 8, 10, 4, 103, 99, 76, 0, 16, 22, 10, 8, 10, 4, 103, 99, 104, 0, 16, 22, 10, 8, 10, 4, 103, 99, 116, 0, 16, 22, 10, 8, 10, 4, 103, 99, 120, 0, 16, 22, 10, 8, 10, 4, 103, 99, 132, 0, 16, 22, 10, 8, 10, 4, 103, 99, 136, 0, 16, 22, 10, 8, 10, 4, 103, 99, 140, 0, 16, 22, 10, 8, 10, 4, 103, 99, 144, 0, 16, 22, 10, 8, 10, 4, 103, 99, 152, 0, 16, 22, 10, 8, 10, 4, 103, 99, 220, 0, 16, 22, 10, 8, 10, 4, 103, 99, 232, 0, 16, 22, 10, 8, 10, 4, 103, 99, 236, 0, 16, 22, 10, 8, 10, 4, 103, 100, 0, 0, 16, 22, 10, 8, 10, 4, 103, 100, 32, 0, 16, 22, 10, 8, 10, 4, 103, 100, 40, 0, 16, 22, 10, 8, 10, 4, 103, 100, 48, 0, 16, 22, 10, 8, 10, 4, 103, 100, 52, 0, 16, 22, 10, 8, 10, 4, 103, 100, 56, 0, 16, 22, 10, 8, 10, 4, 103, 100, 60, 0, 16, 22, 10, 8, 10, 4, 103, 100, 64, 0, 16, 22, 10, 8, 10, 4, 103, 100, 68, 0, 16, 22, 10, 8, 10, 4, 103, 100, 88, 0, 16, 22, 10, 8, 10, 4, 103, 100, 116, 0, 16, 22, 10, 8, 10, 4, 103, 100, 140, 0, 16, 22, 10, 8, 10, 4, 103, 100, 144, 0, 16, 22, 10, 8, 10, 4, 103, 100, 236, 0, 16, 22, 10, 8, 10, 4, 103, 100, 240, 0, 16, 22, 10, 8, 10, 4, 103, 100, 248, 0, 16, 22, 10, 8, 10, 4, 103, 100, 252, 0, 16, 22, 10, 8, 10, 4, 103, 101, 4, 0, 16, 22, 10, 8, 10, 4, 103, 101, 8, 0, 16, 22, 10, 8, 10, 4, 103, 101, 12, 0, 16, 22, 10, 8, 10, 4, 103, 101, 28, 0, 16, 22, 10, 8, 10, 4, 103, 101, 60, 0, 16, 22, 10, 8, 10, 4, 103, 101, 120, 0, 16, 22, 10, 8, 10, 4, 103, 101, 124, 0, 16, 22, 10, 8, 10, 4, 103, 192, 0, 0, 16, 22, 10, 8, 10, 4, 103, 192, 4, 0, 16, 22, 10, 8, 10, 4, 103, 192, 8, 0, 16, 22, 10, 8, 10, 4, 103, 192, 12, 0, 16, 22, 10, 8, 10, 4, 103, 192, 16, 0, 16, 22, 10, 8, 10, 4, 103, 192, 20, 0, 16, 22, 10, 8, 10, 4, 103, 192, 24, 0, 16, 22, 10, 8, 10, 4, 103, 192, 28, 0, 16, 22, 10, 8, 10, 4, 103, 192, 48, 0, 16, 22, 10, 8, 10, 4, 103, 192, 52, 0, 16, 22, 10, 8, 10, 4, 103, 192, 56, 0, 16, 22, 10, 8, 10, 4, 103, 192, 84, 0, 16, 22, 10, 8, 10, 4, 103, 192, 88, 0, 16, 22, 10, 8, 10, 4, 103, 192, 92, 0, 16, 22, 10, 8, 10, 4, 103, 192, 96, 0, 16, 22, 10, 8, 10, 4, 103, 192, 100, 0, 16, 22, 10, 8, 10, 4, 103, 192, 104, 0, 16, 22, 10, 8, 10, 4, 103, 192, 108, 0, 16, 22, 10, 8, 10, 4, 103, 192, 112, 0, 16, 22, 10, 8, 10, 4, 103, 192, 128, 0, 16, 22, 10, 8, 10, 4, 103, 192, 132, 0, 16, 22, 10, 8, 10, 4, 103, 192, 136, 0, 16, 22, 10, 8, 10, 4, 103, 192, 140, 0, 16, 22, 10, 8, 10, 4, 103, 192, 144, 0, 16, 22, 10, 8, 10, 4, 103, 192, 164, 0, 16, 22, 10, 8, 10, 4, 103, 192, 188, 0, 16, 22, 10, 8, 10, 4, 103, 192, 208, 0, 16, 22, 10, 8, 10, 4, 103, 192, 212, 0, 16, 22, 10, 8, 10, 4, 103, 192, 216, 0, 16, 22, 10, 8, 10, 4, 103, 192, 252, 0, 16, 22, 10, 8, 10, 4, 103, 193, 40, 0, 16, 22, 10, 8, 10, 4, 103, 193, 44, 0, 16, 22, 10, 8, 10, 4, 103, 193, 120, 0, 16, 22, 10, 8, 10, 4, 103, 193, 124, 0, 16, 22, 10, 8, 10, 4, 103, 193, 140, 0, 16, 22, 10, 8, 10, 4, 103, 193, 144, 0, 16, 22, 10, 8, 10, 4, 103, 193, 148, 0, 16, 22, 10, 8, 10, 4, 103, 193, 160, 0, 16, 22, 10, 8, 10, 4, 103, 193, 188, 0, 16, 22, 10, 8, 10, 4, 103, 193, 192, 0, 16, 22, 10, 8, 10, 4, 103, 193, 212, 0, 16, 22, 10, 8, 10, 4, 103, 193, 216, 0, 16, 22, 10, 8, 10, 4, 103, 193, 220, 0, 16, 22, 10, 8, 10, 4, 103, 193, 224, 0, 16, 22, 10, 8, 10, 4, 103, 193, 228, 0, 16, 22, 10, 8, 10, 4, 103, 193, 232, 0, 16, 22, 10, 8, 10, 4, 103, 193, 236, 0, 16, 22, 10, 8, 10, 4, 103, 193, 240, 0, 16, 22, 10, 8, 10, 4, 103, 194, 16, 0, 16, 22, 10, 8, 10, 4, 103, 195, 104, 0, 16, 22, 10, 8, 10, 4, 103, 195, 112, 0, 16, 22, 10, 8, 10, 4, 103, 195, 136, 0, 16, 22, 10, 8, 10, 4, 103, 195, 148, 0, 16, 22, 10, 8, 10, 4, 103, 195, 152, 0, 16, 22, 10, 8, 10, 4, 103, 195, 160, 0, 16, 22, 10, 8, 10, 4, 103, 195, 192, 0, 16, 22, 10, 8, 10, 4, 103, 196, 60, 0, 16, 22, 10, 8, 10, 4, 103, 196, 64, 0, 16, 22, 10, 8, 10, 4, 103, 196, 72, 0, 16, 22, 10, 8, 10, 4, 103, 196, 88, 0, 16, 22, 10, 8, 10, 4, 103, 196, 92, 0, 16, 22, 10, 8, 10, 4, 103, 196, 96, 0, 16, 22, 10, 8, 10, 4, 103, 196, 168, 0, 16, 22, 10, 8, 10, 4, 103, 196, 204, 0, 16, 22, 10, 8, 10, 4, 103, 197, 180, 0, 16, 22, 10, 8, 10, 4, 103, 197, 228, 0, 16, 22, 10, 8, 10, 4, 103, 198, 20, 0, 16, 22, 10, 8, 10, 4, 103, 198, 60, 0, 16, 22, 10, 8, 10, 4, 103, 198, 64, 0, 16, 22, 10, 8, 10, 4, 103, 198, 72, 0, 16, 22, 10, 8, 10, 4, 103, 198, 124, 0, 16, 22, 10, 8, 10, 4, 103, 198, 156, 0, 16, 22, 10, 8, 10, 4, 103, 198, 180, 0, 16, 22, 10, 8, 10, 4, 103, 198, 196, 0, 16, 22, 10, 8, 10, 4, 103, 198, 200, 0, 16, 22, 10, 8, 10, 4, 103, 198, 216, 0, 16, 22, 10, 8, 10, 4, 103, 198, 220, 0, 16, 22, 10, 8, 10, 4, 103, 198, 224, 0, 16, 22, 10, 8, 10, 4, 103, 198, 228, 0, 16, 22, 10, 8, 10, 4, 103, 198, 232, 0, 16, 22, 10, 8, 10, 4, 103, 198, 236, 0, 16, 22, 10, 8, 10, 4, 103, 198, 240, 0, 16, 22, 10, 8, 10, 4, 103, 198, 244, 0, 16, 22, 10, 8, 10, 4, 103, 199, 164, 0, 16, 22, 10, 8, 10, 4, 103, 199, 196, 0, 16, 22, 10, 8, 10, 4, 103, 199, 228, 0, 16, 22, 10, 8, 10, 4, 103, 199, 248, 0, 16, 22, 10, 8, 10, 4, 103, 199, 252, 0, 16, 22, 10, 8, 10, 4, 103, 200, 28, 0, 16, 22, 10, 8, 10, 4, 103, 200, 32, 0, 16, 22, 10, 8, 10, 4, 103, 200, 52, 0, 16, 22, 10, 8, 10, 4, 103, 200, 64, 0, 16, 22, 10, 8, 10, 4, 103, 200, 68, 0, 16, 22, 10, 8, 10, 4, 103, 200, 136, 0, 16, 22, 10, 8, 10, 4, 103, 200, 140, 0, 16, 22, 10, 8, 10, 4, 103, 200, 144, 0, 16, 22, 10, 8, 10, 4, 103, 200, 148, 0, 16, 22, 10, 8, 10, 4, 103, 200, 152, 0, 16, 22, 10, 8, 10, 4, 103, 200, 156, 0, 16, 22, 10, 8, 10, 4, 103, 200, 160, 0, 16, 22, 10, 8, 10, 4, 103, 200, 164, 0, 16, 22, 10, 8, 10, 4, 103, 200, 168, 0, 16, 22, 10, 8, 10, 4, 103, 200, 172, 0, 16, 22, 10, 8, 10, 4, 103, 200, 176, 0, 16, 22, 10, 8, 10, 4, 103, 200, 180, 0, 16, 22, 10, 8, 10, 4, 103, 200, 184, 0, 16, 22, 10, 8, 10, 4, 103, 200, 188, 0, 16, 22, 10, 8, 10, 4, 103, 200, 192, 0, 16, 22, 10, 8, 10, 4, 103, 200, 220, 0, 16, 22, 10, 8, 10, 4, 103, 200, 224, 0, 16, 22, 10, 8, 10, 4, 103, 200, 228, 0, 16, 22, 10, 8, 10, 4, 103, 200, 232, 0, 16, 22, 10, 8, 10, 4, 103, 200, 236, 0, 16, 22, 10, 8, 10, 4, 103, 200, 240, 0, 16, 22, 10, 8, 10, 4, 103, 200, 244, 0, 16, 22, 10, 8, 10, 4, 103, 200, 248, 0, 16, 22, 10, 8, 10, 4, 103, 200, 252, 0, 16, 22, 10, 8, 10, 4, 103, 201, 0, 0, 16, 22, 10, 8, 10, 4, 103, 201, 4, 0, 16, 22, 10, 8, 10, 4, 103, 201, 8, 0, 16, 22, 10, 8, 10, 4, 103, 201, 12, 0, 16, 22, 10, 8, 10, 4, 103, 201, 16, 0, 16, 22, 10, 8, 10, 4, 103, 201, 20, 0, 16, 22, 10, 8, 10, 4, 103, 201, 28, 0, 16, 22, 10, 8, 10, 4, 103, 201, 32, 0, 16, 22, 10, 8, 10, 4, 103, 201, 36, 0, 16, 22, 10, 8, 10, 4, 103, 201, 40, 0, 16, 22, 10, 8, 10, 4, 103, 201, 44, 0, 16, 22, 10, 8, 10, 4, 103, 201, 48, 0, 16, 22, 10, 8, 10, 4, 103, 201, 52, 0, 16, 22, 10, 8, 10, 4, 103, 201, 56, 0, 16, 22, 10, 8, 10, 4, 103, 201, 60, 0, 16, 22, 10, 8, 10, 4, 103, 201, 64, 0, 16, 22, 10, 8, 10, 4, 103, 201, 76, 0, 16, 22, 10, 8, 10, 4, 103, 201, 80, 0, 16, 22, 10, 8, 10, 4, 103, 201, 84, 0, 16, 22, 10, 8, 10, 4, 103, 201, 88, 0, 16, 22, 10, 8, 10, 4, 103, 201, 92, 0, 16, 22, 10, 8, 10, 4, 103, 201, 96, 0, 16, 22, 10, 8, 10, 4, 103, 201, 100, 0, 16, 22, 10, 8, 10, 4, 103, 201, 104, 0, 16, 22, 10, 8, 10, 4, 103, 201, 108, 0, 16, 22, 10, 8, 10, 4, 103, 201, 112, 0, 16, 22, 10, 8, 10, 4, 103, 201, 116, 0, 16, 22, 10, 8, 10, 4, 103, 201, 120, 0, 16, 22, 10, 8, 10, 4, 103, 201, 152, 0, 16, 22, 10, 8, 10, 4, 103, 201, 156, 0, 16, 22, 10, 8, 10, 4, 103, 201, 160, 0, 16, 22, 10, 8, 10, 4, 103, 201, 164, 0, 16, 22, 10, 8, 10, 4, 103, 201, 168, 0, 16, 22, 10, 8, 10, 4, 103, 201, 172, 0, 16, 22, 10, 8, 10, 4, 103, 201, 176, 0, 16, 22, 10, 8, 10, 4, 103, 201, 180, 0, 16, 22, 10, 8, 10, 4, 103, 201, 184, 0, 16, 22, 10, 8, 10, 4, 103, 201, 188, 0, 16, 22, 10, 8, 10, 4, 103, 201, 192, 0, 16, 22, 10, 8, 10, 4, 103, 201, 196, 0, 16, 22, 10, 8, 10, 4, 103, 201, 200, 0, 16, 22, 10, 8, 10, 4, 103, 201, 204, 0, 16, 22, 10, 8, 10, 4, 103, 201, 208, 0, 16, 22, 10, 8, 10, 4, 103, 201, 212, 0, 16, 22, 10, 8, 10, 4, 103, 201, 216, 0, 16, 22, 10, 8, 10, 4, 103, 201, 220, 0, 16, 22, 10, 8, 10, 4, 103, 201, 224, 0, 16, 22, 10, 8, 10, 4, 103, 201, 228, 0, 16, 22, 10, 8, 10, 4, 103, 201, 232, 0, 16, 22, 10, 8, 10, 4, 103, 201, 236, 0, 16, 22, 10, 8, 10, 4, 103, 201, 240, 0, 16, 22, 10, 8, 10, 4, 103, 201, 244, 0, 16, 22, 10, 8, 10, 4, 103, 201, 248, 0, 16, 22, 10, 8, 10, 4, 103, 201, 252, 0, 16, 22, 10, 8, 10, 4, 103, 202, 0, 0, 16, 22, 10, 8, 10, 4, 103, 202, 4, 0, 16, 22, 10, 8, 10, 4, 103, 202, 8, 0, 16, 22, 10, 8, 10, 4, 103, 202, 12, 0, 16, 22, 10, 8, 10, 4, 103, 202, 16, 0, 16, 22, 10, 8, 10, 4, 103, 202, 20, 0, 16, 22, 10, 8, 10, 4, 103, 202, 24, 0, 16, 22, 10, 8, 10, 4, 103, 202, 28, 0, 16, 22, 10, 8, 10, 4, 103, 202, 32, 0, 16, 22, 10, 8, 10, 4, 103, 202, 36, 0, 16, 22, 10, 8, 10, 4, 103, 202, 40, 0, 16, 22, 10, 8, 10, 4, 103, 202, 44, 0, 16, 22, 10, 8, 10, 4, 103, 202, 56, 0, 16, 22, 10, 8, 10, 4, 103, 202, 60, 0, 16, 22, 10, 8, 10, 4, 103, 202, 64, 0, 16, 22, 10, 8, 10, 4, 103, 202, 68, 0, 16, 22, 10, 8, 10, 4, 103, 202, 72, 0, 16, 22, 10, 8, 10, 4, 103, 202, 76, 0, 16, 22, 10, 8, 10, 4, 103, 202, 80, 0, 16, 22, 10, 8, 10, 4, 103, 202, 84, 0, 16, 22, 10, 8, 10, 4, 103, 202, 88, 0, 16, 22, 10, 8, 10, 4, 103, 202, 92, 0, 16, 22, 10, 8, 10, 4, 103, 202, 96, 0, 16, 22, 10, 8, 10, 4, 103, 202, 100, 0, 16, 22, 10, 8, 10, 4, 103, 202, 104, 0, 16, 22, 10, 8, 10, 4, 103, 202, 108, 0, 16, 22, 10, 8, 10, 4, 103, 202, 112, 0, 16, 22, 10, 8, 10, 4, 103, 202, 116, 0, 16, 22, 10, 8, 10, 4, 103, 202, 120, 0, 16, 22, 10, 8, 10, 4, 103, 202, 124, 0, 16, 22, 10, 8, 10, 4, 103, 202, 128, 0, 16, 22, 10, 8, 10, 4, 103, 202, 132, 0, 16, 22, 10, 8, 10, 4, 103, 202, 136, 0, 16, 22, 10, 8, 10, 4, 103, 202, 140, 0, 16, 22, 10, 8, 10, 4, 103, 202, 144, 0, 16, 22, 10, 8, 10, 4, 103, 202, 152, 0, 16, 22, 10, 8, 10, 4, 103, 202, 156, 0, 16, 22, 10, 8, 10, 4, 103, 202, 160, 0, 16, 22, 10, 8, 10, 4, 103, 202, 164, 0, 16, 22, 10, 8, 10, 4, 103, 202, 168, 0, 16, 22, 10, 8, 10, 4, 103, 202, 172, 0, 16, 22, 10, 8, 10, 4, 103, 202, 176, 0, 16, 22, 10, 8, 10, 4, 103, 202, 180, 0, 16, 22, 10, 8, 10, 4, 103, 202, 184, 0, 16, 22, 10, 8, 10, 4, 103, 202, 188, 0, 16, 22, 10, 8, 10, 4, 103, 202, 192, 0, 16, 22, 10, 8, 10, 4, 103, 202, 196, 0, 16, 22, 10, 8, 10, 4, 103, 202, 200, 0, 16, 21, 10, 8, 10, 4, 103, 202, 212, 0, 16, 22, 10, 8, 10, 4, 103, 202, 228, 0, 16, 22, 10, 8, 10, 4, 103, 202, 236, 0, 16, 22, 10, 8, 10, 4, 103, 202, 240, 0, 16, 22, 10, 8, 10, 4, 103, 202, 244, 0, 16, 22, 10, 8, 10, 4, 103, 202, 248, 0, 16, 22, 10, 8, 10, 4, 103, 202, 252, 0, 16, 22, 10, 8, 10, 4, 103, 203, 0, 0, 16, 22, 10, 8, 10, 4, 103, 203, 4, 0, 16, 22, 10, 8, 10, 4, 103, 203, 8, 0, 16, 22, 10, 8, 10, 4, 103, 203, 12, 0, 16, 22, 10, 8, 10, 4, 103, 203, 16, 0, 16, 22, 10, 8, 10, 4, 103, 203, 20, 0, 16, 22, 10, 8, 10, 4, 103, 203, 24, 0, 16, 22, 10, 8, 10, 4, 103, 203, 28, 0, 16, 22, 10, 8, 10, 4, 103, 203, 32, 0, 16, 22, 10, 8, 10, 4, 103, 203, 52, 0, 16, 22, 10, 8, 10, 4, 103, 203, 56, 0, 16, 22, 10, 8, 10, 4, 103, 203, 96, 0, 16, 22, 10, 8, 10, 4, 103, 203, 100, 0, 16, 22, 10, 8, 10, 4, 103, 203, 104, 0, 16, 22, 10, 8, 10, 4, 103, 203, 108, 0, 16, 22, 10, 8, 10, 4, 103, 203, 112, 0, 16, 22, 10, 8, 10, 4, 103, 203, 116, 0, 16, 22, 10, 8, 10, 4, 103, 203, 120, 0, 16, 22, 10, 8, 10, 4, 103, 203, 124, 0, 16, 22, 10, 8, 10, 4, 103, 203, 128, 0, 16, 22, 10, 8, 10, 4, 103, 203, 140, 0, 16, 22, 10, 8, 10, 4, 103, 203, 164, 0, 16, 22, 10, 8, 10, 4, 103, 203, 168, 0, 16, 22, 10, 8, 10, 4, 103, 203, 192, 0, 16, 22, 10, 8, 10, 4, 103, 203, 200, 0, 16, 22, 10, 8, 10, 4, 103, 203, 212, 0, 16, 22, 10, 8, 10, 4, 103, 203, 216, 0, 16, 22, 10, 8, 10, 4, 103, 204, 24, 0, 16, 22, 10, 8, 10, 4, 103, 204, 72, 0, 16, 22, 10, 8, 10, 4, 103, 204, 88, 0, 16, 22, 10, 8, 10, 4, 103, 204, 112, 0, 16, 22, 10, 8, 10, 4, 103, 204, 136, 0, 16, 22, 10, 8, 10, 4, 103, 204, 140, 0, 16, 22, 10, 8, 10, 4, 103, 204, 144, 0, 16, 22, 10, 8, 10, 4, 103, 204, 148, 0, 16, 22, 10, 8, 10, 4, 103, 204, 152, 0, 16, 22, 10, 8, 10, 4, 103, 204, 196, 0, 16, 22, 10, 8, 10, 4, 103, 204, 232, 0, 16, 22, 10, 8, 10, 4, 103, 204, 236, 0, 16, 22, 10, 8, 10, 4, 103, 205, 4, 0, 16, 22, 10, 8, 10, 4, 103, 205, 8, 0, 16, 22, 10, 8, 10, 4, 103, 205, 40, 0, 16, 22, 10, 8, 10, 4, 103, 205, 44, 0, 16, 22, 10, 8, 10, 4, 103, 205, 52, 0, 16, 22, 10, 8, 10, 4, 103, 205, 108, 0, 16, 22, 10, 8, 10, 4, 103, 205, 116, 0, 16, 22, 10, 8, 10, 4, 103, 205, 120, 0, 16, 22, 10, 8, 10, 4, 103, 205, 136, 0, 16, 22, 10, 8, 10, 4, 103, 205, 162, 0, 16, 24, 10, 8, 10, 4, 103, 205, 188, 0, 16, 22, 10, 8, 10, 4, 103, 205, 192, 0, 16, 22, 10, 8, 10, 4, 103, 205, 196, 0, 16, 22, 10, 8, 10, 4, 103, 205, 200, 0, 16, 22, 10, 8, 10, 4, 103, 205, 236, 0, 16, 22, 10, 8, 10, 4, 103, 205, 248, 0, 16, 22, 10, 8, 10, 4, 103, 205, 252, 0, 16, 22, 10, 8, 10, 4, 103, 206, 0, 0, 16, 22, 10, 8, 10, 4, 103, 206, 44, 0, 16, 22, 10, 8, 10, 4, 103, 206, 108, 0, 16, 22, 10, 8, 10, 4, 103, 206, 148, 0, 16, 22, 10, 8, 10, 4, 103, 207, 48, 0, 16, 22, 10, 8, 10, 4, 103, 207, 104, 0, 16, 22, 10, 8, 10, 4, 103, 207, 164, 0, 16, 22, 10, 8, 10, 4, 103, 207, 184, 0, 16, 22, 10, 8, 10, 4, 103, 207, 188, 0, 16, 22, 10, 8, 10, 4, 103, 207, 192, 0, 16, 22, 10, 8, 10, 4, 103, 207, 196, 0, 16, 22, 10, 8, 10, 4, 103, 207, 200, 0, 16, 22, 10, 8, 10, 4, 103, 207, 204, 0, 16, 22, 10, 8, 10, 4, 103, 207, 208, 0, 16, 22, 10, 8, 10, 4, 103, 207, 212, 0, 16, 22, 10, 8, 10, 4, 103, 207, 220, 0, 16, 22, 10, 8, 10, 4, 103, 207, 228, 0, 16, 22, 10, 8, 10, 4, 103, 207, 232, 0, 16, 22, 10, 8, 10, 4, 103, 208, 12, 0, 16, 22, 10, 8, 10, 4, 103, 208, 16, 0, 16, 22, 10, 8, 10, 4, 103, 208, 28, 0, 16, 22, 10, 8, 10, 4, 103, 208, 40, 0, 16, 22, 10, 8, 10, 4, 103, 208, 44, 0, 16, 22, 10, 8, 10, 4, 103, 208, 48, 0, 16, 22, 10, 8, 10, 4, 103, 208, 148, 0, 16, 22, 10, 8, 10, 4, 103, 209, 112, 0, 16, 22, 10, 8, 10, 4, 103, 209, 136, 0, 16, 22, 10, 8, 10, 4, 103, 209, 200, 0, 16, 22, 10, 8, 10, 4, 103, 209, 208, 0, 16, 22, 10, 8, 10, 4, 103, 209, 216, 0, 16, 22, 10, 8, 10, 4, 103, 210, 0, 0, 16, 22, 10, 8, 10, 4, 103, 210, 20, 0, 16, 22, 10, 8, 10, 4, 103, 210, 96, 0, 16, 22, 10, 8, 10, 4, 103, 210, 156, 0, 16, 22, 10, 8, 10, 4, 103, 210, 160, 0, 16, 22, 10, 8, 10, 4, 103, 210, 164, 0, 16, 22, 10, 8, 10, 4, 103, 210, 168, 0, 16, 22, 10, 8, 10, 4, 103, 210, 172, 0, 16, 22, 10, 8, 10, 4, 103, 210, 176, 0, 16, 22, 10, 8, 10, 4, 103, 210, 180, 0, 16, 22, 10, 8, 10, 4, 103, 210, 184, 0, 16, 22, 10, 8, 10, 4, 103, 210, 188, 0, 16, 22, 10, 8, 10, 4, 103, 210, 216, 0, 16, 22, 10, 8, 10, 4, 103, 211, 44, 0, 16, 22, 10, 8, 10, 4, 103, 211, 96, 0, 16, 22, 10, 8, 10, 4, 103, 211, 100, 0, 16, 22, 10, 8, 10, 4, 103, 211, 156, 0, 16, 22, 10, 8, 10, 4, 103, 211, 164, 0, 16, 22, 10, 8, 10, 4, 103, 211, 168, 0, 16, 22, 10, 8, 10, 4, 103, 211, 192, 0, 16, 22, 10, 8, 10, 4, 103, 211, 220, 0, 16, 22, 10, 8, 10, 4, 103, 211, 224, 0, 16, 22, 10, 8, 10, 4, 103, 211, 228, 0, 16, 22, 10, 8, 10, 4, 103, 211, 248, 0, 16, 22, 10, 8, 10, 4, 103, 212, 0, 0, 16, 22, 10, 8, 10, 4, 103, 212, 4, 0, 16, 22, 10, 8, 10, 4, 103, 212, 8, 0, 16, 22, 10, 8, 10, 4, 103, 212, 12, 0, 16, 22, 10, 8, 10, 4, 103, 212, 32, 0, 16, 22, 10, 8, 10, 4, 103, 212, 44, 0, 16, 22, 10, 8, 10, 4, 103, 212, 48, 0, 16, 22, 10, 8, 10, 4, 103, 212, 84, 0, 16, 22, 10, 8, 10, 4, 103, 212, 100, 0, 16, 22, 10, 8, 10, 4, 103, 212, 104, 0, 16, 22, 10, 8, 10, 4, 103, 212, 108, 0, 16, 22, 10, 8, 10, 4, 103, 212, 148, 0, 16, 22, 10, 8, 10, 4, 103, 212, 164, 0, 16, 22, 10, 8, 10, 4, 103, 212, 196, 0, 16, 22, 10, 8, 10, 4, 103, 212, 200, 0, 16, 22, 10, 8, 10, 4, 103, 212, 228, 0, 16, 22, 10, 8, 10, 4, 103, 212, 252, 0, 16, 22, 10, 8, 10, 4, 103, 213, 40, 0, 16, 22, 10, 8, 10, 4, 103, 213, 44, 0, 16, 22, 10, 8, 10, 4, 103, 213, 48, 0, 16, 22, 10, 8, 10, 4, 103, 213, 52, 0, 16, 22, 10, 8, 10, 4, 103, 213, 56, 0, 16, 22, 10, 8, 10, 4, 103, 213, 60, 0, 16, 22, 10, 8, 10, 4, 103, 213, 64, 0, 16, 22, 10, 8, 10, 4, 103, 213, 68, 0, 16, 22, 10, 8, 10, 4, 103, 213, 72, 0, 16, 22, 10, 8, 10, 4, 103, 213, 76, 0, 16, 22, 10, 8, 10, 4, 103, 213, 80, 0, 16, 22, 10, 8, 10, 4, 103, 213, 84, 0, 16, 22, 10, 8, 10, 4, 103, 213, 88, 0, 16, 22, 10, 8, 10, 4, 103, 213, 92, 0, 16, 22, 10, 8, 10, 4, 103, 213, 96, 0, 16, 22, 10, 8, 10, 4, 103, 213, 132, 0, 16, 22, 10, 8, 10, 4, 103, 213, 136, 0, 16, 22, 10, 8, 10, 4, 103, 213, 140, 0, 16, 22, 10, 8, 10, 4, 103, 213, 144, 0, 16, 22, 10, 8, 10, 4, 103, 213, 148, 0, 16, 22, 10, 8, 10, 4, 103, 213, 152, 0, 16, 22, 10, 8, 10, 4, 103, 213, 156, 0, 16, 22, 10, 8, 10, 4, 103, 213, 160, 0, 16, 22, 10, 8, 10, 4, 103, 213, 164, 0, 16, 22, 10, 8, 10, 4, 103, 213, 168, 0, 16, 22, 10, 8, 10, 4, 103, 213, 172, 0, 16, 22, 10, 8, 10, 4, 103, 213, 176, 0, 16, 22, 10, 8, 10, 4, 103, 213, 180, 0, 16, 22, 10, 8, 10, 4, 103, 213, 184, 0, 16, 22, 10, 8, 10, 4, 103, 213, 188, 0, 16, 22, 10, 8, 10, 4, 103, 213, 248, 0, 16, 22, 10, 8, 10, 4, 103, 213, 252, 0, 16, 22, 10, 8, 10, 4, 103, 214, 32, 0, 16, 22, 10, 8, 10, 4, 103, 214, 48, 0, 16, 22, 10, 8, 10, 4, 103, 214, 84, 0, 16, 22, 10, 8, 10, 4, 103, 214, 168, 0, 16, 22, 10, 8, 10, 4, 103, 214, 212, 0, 16, 22, 10, 8, 10, 4, 103, 214, 224, 0, 16, 22, 10, 8, 10, 4, 103, 214, 240, 0, 16, 22, 10, 8, 10, 4, 103, 214, 244, 0, 16, 22, 10, 8, 10, 4, 103, 215, 28, 0, 16, 22, 10, 8, 10, 4, 103, 215, 32, 0, 16, 22, 10, 8, 10, 4, 103, 215, 36, 0, 16, 22, 10, 8, 10, 4, 103, 215, 44, 0, 16, 22, 10, 8, 10, 4, 103, 215, 48, 0, 16, 22, 10, 8, 10, 4, 103, 215, 100, 0, 16, 22, 10, 8, 10, 4, 103, 215, 104, 0, 16, 22, 10, 8, 10, 4, 103, 215, 108, 0, 16, 22, 10, 8, 10, 4, 103, 215, 116, 0, 16, 22, 10, 8, 10, 4, 103, 215, 120, 0, 16, 22, 10, 8, 10, 4, 103, 215, 140, 0, 16, 22, 10, 8, 10, 4, 103, 215, 184, 0, 16, 22, 10, 8, 10, 4, 103, 215, 228, 0, 16, 22, 10, 8, 10, 4, 103, 216, 4, 0, 16, 22, 10, 8, 10, 4, 103, 216, 8, 0, 16, 22, 10, 8, 10, 4, 103, 216, 12, 0, 16, 22, 10, 8, 10, 4, 103, 216, 16, 0, 16, 22, 10, 8, 10, 4, 103, 216, 20, 0, 16, 22, 10, 8, 10, 4, 103, 216, 24, 0, 16, 22, 10, 8, 10, 4, 103, 216, 28, 0, 16, 22, 10, 8, 10, 4, 103, 216, 32, 0, 16, 22, 10, 8, 10, 4, 103, 216, 36, 0, 16, 22, 10, 8, 10, 4, 103, 216, 40, 0, 16, 22, 10, 8, 10, 4, 103, 216, 44, 0, 16, 22, 10, 8, 10, 4, 103, 216, 64, 0, 16, 22, 10, 8, 10, 4, 103, 216, 108, 0, 16, 22, 10, 8, 10, 4, 103, 216, 136, 0, 16, 22, 10, 8, 10, 4, 103, 216, 152, 0, 16, 22, 10, 8, 10, 4, 103, 216, 224, 0, 16, 22, 10, 8, 10, 4, 103, 216, 228, 0, 16, 22, 10, 8, 10, 4, 103, 216, 240, 0, 16, 22, 10, 8, 10, 4, 103, 216, 244, 0, 16, 22, 10, 8, 10, 4, 103, 216, 248, 0, 16, 22, 10, 8, 10, 4, 103, 216, 252, 0, 16, 22, 10, 8, 10, 4, 103, 217, 0, 0, 16, 22, 10, 8, 10, 4, 103, 217, 4, 0, 16, 22, 10, 8, 10, 4, 103, 217, 8, 0, 16, 22, 10, 8, 10, 4, 103, 217, 12, 0, 16, 22, 10, 8, 10, 4, 103, 217, 16, 0, 16, 22, 10, 8, 10, 4, 103, 217, 20, 0, 16, 22, 10, 8, 10, 4, 103, 217, 24, 0, 16, 22, 10, 8, 10, 4, 103, 217, 28, 0, 16, 22, 10, 8, 10, 4, 103, 217, 32, 0, 16, 22, 10, 8, 10, 4, 103, 217, 36, 0, 16, 22, 10, 8, 10, 4, 103, 217, 40, 0, 16, 22, 10, 8, 10, 4, 103, 217, 44, 0, 16, 22, 10, 8, 10, 4, 103, 217, 48, 0, 16, 22, 10, 8, 10, 4, 103, 217, 52, 0, 16, 22, 10, 8, 10, 4, 103, 217, 56, 0, 16, 22, 10, 8, 10, 4, 103, 217, 60, 0, 16, 22, 10, 8, 10, 4, 103, 217, 168, 0, 16, 22, 10, 8, 10, 4, 103, 217, 180, 0, 16, 22, 10, 8, 10, 4, 103, 217, 184, 0, 16, 22, 10, 8, 10, 4, 103, 217, 188, 0, 16, 22, 10, 8, 10, 4, 103, 217, 192, 0, 16, 22, 10, 8, 10, 4, 103, 217, 196, 0, 16, 22, 10, 8, 10, 4, 103, 217, 200, 0, 16, 22, 10, 8, 10, 4, 103, 217, 204, 0, 16, 22, 10, 8, 10, 4, 103, 218, 0, 0, 16, 22, 10, 8, 10, 4, 103, 218, 8, 0, 16, 22, 10, 8, 10, 4, 103, 218, 12, 0, 16, 22, 10, 8, 10, 4, 103, 218, 16, 0, 16, 22, 10, 8, 10, 4, 103, 218, 20, 0, 16, 22, 10, 8, 10, 4, 103, 218, 28, 0, 16, 22, 10, 8, 10, 4, 103, 218, 32, 0, 16, 22, 10, 8, 10, 4, 103, 218, 36, 0, 16, 22, 10, 8, 10, 4, 103, 218, 40, 0, 16, 22, 10, 8, 10, 4, 103, 218, 44, 0, 16, 22, 10, 8, 10, 4, 103, 218, 48, 0, 16, 22, 10, 8, 10, 4, 103, 218, 52, 0, 16, 22, 10, 8, 10, 4, 103, 218, 56, 0, 16, 22, 10, 8, 10, 4, 103, 218, 60, 0, 16, 22, 10, 8, 10, 4, 103, 218, 64, 0, 16, 22, 10, 8, 10, 4, 103, 218, 68, 0, 16, 22, 10, 8, 10, 4, 103, 218, 72, 0, 16, 22, 10, 8, 10, 4, 103, 218, 76, 0, 16, 22, 10, 8, 10, 4, 103, 218, 80, 0, 16, 22, 10, 8, 10, 4, 103, 218, 84, 0, 16, 22, 10, 8, 10, 4, 103, 218, 88, 0, 16, 22, 10, 8, 10, 4, 103, 218, 92, 0, 16, 22, 10, 8, 10, 4, 103, 218, 184, 0, 16, 22, 10, 8, 10, 4, 103, 218, 192, 0, 16, 22, 10, 8, 10, 4, 103, 218, 196, 0, 16, 22, 10, 8, 10, 4, 103, 218, 200, 0, 16, 22, 10, 8, 10, 4, 103, 218, 204, 0, 16, 22, 10, 8, 10, 4, 103, 218, 208, 0, 16, 22, 10, 8, 10, 4, 103, 218, 212, 0, 16, 22, 10, 8, 10, 4, 103, 218, 216, 0, 16, 22, 10, 8, 10, 4, 103, 219, 24, 0, 16, 22, 10, 8, 10, 4, 103, 219, 28, 0, 16, 22, 10, 8, 10, 4, 103, 219, 32, 0, 16, 22, 10, 8, 10, 4, 103, 219, 36, 0, 16, 22, 10, 8, 10, 4, 103, 219, 64, 0, 16, 22, 10, 8, 10, 4, 103, 219, 84, 0, 16, 22, 10, 8, 10, 4, 103, 219, 88, 0, 16, 22, 10, 8, 10, 4, 103, 219, 92, 0, 16, 22, 10, 8, 10, 4, 103, 219, 96, 0, 16, 22, 10, 8, 10, 4, 103, 219, 100, 0, 16, 22, 10, 8, 10, 4, 103, 219, 176, 0, 16, 22, 10, 8, 10, 4, 103, 219, 184, 0, 16, 22, 10, 8, 10, 4, 103, 220, 48, 0, 16, 22, 10, 8, 10, 4, 103, 220, 52, 0, 16, 22, 10, 8, 10, 4, 103, 220, 56, 0, 16, 22, 10, 8, 10, 4, 103, 220, 60, 0, 16, 22, 10, 8, 10, 4, 103, 220, 64, 0, 16, 22, 10, 8, 10, 4, 103, 220, 92, 0, 16, 22, 10, 8, 10, 4, 103, 220, 96, 0, 16, 22, 10, 8, 10, 4, 103, 220, 100, 0, 16, 22, 10, 8, 10, 4, 103, 220, 104, 0, 16, 22, 10, 8, 10, 4, 103, 220, 108, 0, 16, 22, 10, 8, 10, 4, 103, 220, 116, 0, 16, 22, 10, 8, 10, 4, 103, 220, 120, 0, 16, 22, 10, 8, 10, 4, 103, 220, 124, 0, 16, 22, 10, 8, 10, 4, 103, 220, 128, 0, 16, 22, 10, 8, 10, 4, 103, 220, 132, 0, 16, 22, 10, 8, 10, 4, 103, 220, 136, 0, 16, 22, 10, 8, 10, 4, 103, 220, 140, 0, 16, 22, 10, 8, 10, 4, 103, 220, 144, 0, 16, 22, 10, 8, 10, 4, 103, 220, 148, 0, 16, 22, 10, 8, 10, 4, 103, 220, 152, 0, 16, 22, 10, 8, 10, 4, 103, 220, 160, 0, 16, 22, 10, 8, 10, 4, 103, 220, 164, 0, 16, 22, 10, 8, 10, 4, 103, 220, 168, 0, 16, 22, 10, 8, 10, 4, 103, 220, 172, 0, 16, 22, 10, 8, 10, 4, 103, 220, 176, 0, 16, 22, 10, 8, 10, 4, 103, 220, 180, 0, 16, 22, 10, 8, 10, 4, 103, 220, 184, 0, 16, 22, 10, 8, 10, 4, 103, 220, 188, 0, 16, 22, 10, 8, 10, 4, 103, 220, 192, 0, 16, 22, 10, 8, 10, 4, 103, 220, 196, 0, 16, 22, 10, 8, 10, 4, 103, 220, 200, 0, 16, 22, 10, 8, 10, 4, 103, 220, 240, 0, 16, 22, 10, 8, 10, 4, 103, 220, 244, 0, 16, 22, 10, 8, 10, 4, 103, 220, 248, 0, 16, 22, 10, 8, 10, 4, 103, 220, 252, 0, 16, 22, 10, 8, 10, 4, 103, 221, 0, 0, 16, 22, 10, 8, 10, 4, 103, 221, 4, 0, 16, 22, 10, 8, 10, 4, 103, 221, 8, 0, 16, 22, 10, 8, 10, 4, 103, 221, 12, 0, 16, 22, 10, 8, 10, 4, 103, 221, 16, 0, 16, 22, 10, 8, 10, 4, 103, 221, 20, 0, 16, 22, 10, 8, 10, 4, 103, 221, 24, 0, 16, 22, 10, 8, 10, 4, 103, 221, 28, 0, 16, 22, 10, 8, 10, 4, 103, 221, 32, 0, 16, 22, 10, 8, 10, 4, 103, 221, 36, 0, 16, 22, 10, 8, 10, 4, 103, 221, 40, 0, 16, 22, 10, 8, 10, 4, 103, 221, 44, 0, 16, 22, 10, 8, 10, 4, 103, 221, 48, 0, 16, 22, 10, 8, 10, 4, 103, 221, 88, 0, 16, 22, 10, 8, 10, 4, 103, 221, 92, 0, 16, 22, 10, 8, 10, 4, 103, 221, 96, 0, 16, 22, 10, 8, 10, 4, 103, 221, 100, 0, 16, 22, 10, 8, 10, 4, 103, 221, 104, 0, 16, 22, 10, 8, 10, 4, 103, 221, 108, 0, 16, 22, 10, 8, 10, 4, 103, 221, 112, 0, 16, 22, 10, 8, 10, 4, 103, 221, 116, 0, 16, 22, 10, 8, 10, 4, 103, 221, 120, 0, 16, 22, 10, 8, 10, 4, 103, 221, 124, 0, 16, 22, 10, 8, 10, 4, 103, 221, 128, 0, 16, 22, 10, 8, 10, 4, 103, 221, 132, 0, 16, 22, 10, 8, 10, 4, 103, 221, 136, 0, 16, 22, 10, 8, 10, 4, 103, 221, 140, 0, 16, 22, 10, 8, 10, 4, 103, 221, 144, 0, 16, 22, 10, 8, 10, 4, 103, 221, 148, 0, 16, 22, 10, 8, 10, 4, 103, 221, 152, 0, 16, 22, 10, 8, 10, 4, 103, 221, 156, 0, 16, 22, 10, 8, 10, 4, 103, 221, 160, 0, 16, 22, 10, 8, 10, 4, 103, 221, 164, 0, 16, 22, 10, 8, 10, 4, 103, 221, 168, 0, 16, 22, 10, 8, 10, 4, 103, 221, 172, 0, 16, 22, 10, 8, 10, 4, 103, 221, 176, 0, 16, 22, 10, 8, 10, 4, 103, 221, 180, 0, 16, 22, 10, 8, 10, 4, 103, 221, 184, 0, 16, 22, 10, 8, 10, 4, 103, 221, 188, 0, 16, 22, 10, 8, 10, 4, 103, 221, 192, 0, 16, 22, 10, 8, 10, 4, 103, 221, 196, 0, 16, 22, 10, 8, 10, 4, 103, 221, 200, 0, 16, 22, 10, 8, 10, 4, 103, 221, 204, 0, 16, 22, 10, 8, 10, 4, 103, 222, 0, 0, 16, 22, 10, 8, 10, 4, 103, 222, 4, 0, 16, 22, 10, 8, 10, 4, 103, 222, 8, 0, 16, 22, 10, 8, 10, 4, 103, 222, 12, 0, 16, 22, 10, 8, 10, 4, 103, 222, 16, 0, 16, 22, 10, 8, 10, 4, 103, 222, 24, 0, 16, 22, 10, 8, 10, 4, 103, 222, 28, 0, 16, 22, 10, 8, 10, 4, 103, 222, 32, 0, 16, 22, 10, 8, 10, 4, 103, 222, 36, 0, 16, 22, 10, 8, 10, 4, 103, 222, 40, 0, 16, 22, 10, 8, 10, 4, 103, 222, 44, 0, 16, 22, 10, 8, 10, 4, 103, 222, 48, 0, 16, 22, 10, 8, 10, 4, 103, 222, 52, 0, 16, 22, 10, 8, 10, 4, 103, 222, 56, 0, 16, 22, 10, 8, 10, 4, 103, 222, 60, 0, 16, 22, 10, 8, 10, 4, 103, 222, 64, 0, 16, 22, 10, 8, 10, 4, 103, 222, 68, 0, 16, 22, 10, 8, 10, 4, 103, 222, 72, 0, 16, 22, 10, 8, 10, 4, 103, 222, 76, 0, 16, 22, 10, 8, 10, 4, 103, 222, 80, 0, 16, 22, 10, 8, 10, 4, 103, 222, 84, 0, 16, 22, 10, 8, 10, 4, 103, 222, 88, 0, 16, 22, 10, 8, 10, 4, 103, 222, 92, 0, 16, 22, 10, 8, 10, 4, 103, 222, 96, 0, 16, 22, 10, 8, 10, 4, 103, 222, 100, 0, 16, 22, 10, 8, 10, 4, 103, 222, 104, 0, 16, 22, 10, 8, 10, 4, 103, 222, 108, 0, 16, 22, 10, 8, 10, 4, 103, 222, 112, 0, 16, 22, 10, 8, 10, 4, 103, 222, 116, 0, 16, 22, 10, 8, 10, 4, 103, 222, 120, 0, 16, 22, 10, 8, 10, 4, 103, 222, 124, 0, 16, 22, 10, 8, 10, 4, 103, 222, 128, 0, 16, 22, 10, 8, 10, 4, 103, 222, 132, 0, 16, 22, 10, 8, 10, 4, 103, 222, 136, 0, 16, 22, 10, 8, 10, 4, 103, 222, 140, 0, 16, 22, 10, 8, 10, 4, 103, 222, 144, 0, 16, 22, 10, 8, 10, 4, 103, 222, 148, 0, 16, 22, 10, 8, 10, 4, 103, 222, 152, 0, 16, 22, 10, 8, 10, 4, 103, 222, 156, 0, 16, 22, 10, 8, 10, 4, 103, 222, 160, 0, 16, 22, 10, 8, 10, 4, 103, 222, 164, 0, 16, 22, 10, 8, 10, 4, 103, 222, 168, 0, 16, 22, 10, 8, 10, 4, 103, 222, 172, 0, 16, 22, 10, 8, 10, 4, 103, 222, 176, 0, 16, 22, 10, 8, 10, 4, 103, 222, 180, 0, 16, 22, 10, 8, 10, 4, 103, 222, 184, 0, 16, 22, 10, 8, 10, 4, 103, 222, 188, 0, 16, 22, 10, 8, 10, 4, 103, 222, 192, 0, 16, 22, 10, 8, 10, 4, 103, 222, 196, 0, 16, 22, 10, 8, 10, 4, 103, 222, 200, 0, 16, 22, 10, 8, 10, 4, 103, 222, 204, 0, 16, 22, 10, 8, 10, 4, 103, 222, 208, 0, 16, 22, 10, 8, 10, 4, 103, 222, 212, 0, 16, 22, 10, 8, 10, 4, 103, 222, 216, 0, 16, 22, 10, 8, 10, 4, 103, 222, 220, 0, 16, 22, 10, 8, 10, 4, 103, 222, 224, 0, 16, 22, 10, 8, 10, 4, 103, 222, 228, 0, 16, 22, 10, 8, 10, 4, 103, 222, 232, 0, 16, 22, 10, 8, 10, 4, 103, 222, 240, 0, 16, 22, 10, 8, 10, 4, 103, 222, 244, 0, 16, 22, 10, 8, 10, 4, 103, 223, 16, 0, 16, 22, 10, 8, 10, 4, 103, 223, 20, 0, 16, 22, 10, 8, 10, 4, 103, 223, 24, 0, 16, 22, 10, 8, 10, 4, 103, 223, 28, 0, 16, 22, 10, 8, 10, 4, 103, 223, 32, 0, 16, 22, 10, 8, 10, 4, 103, 223, 36, 0, 16, 22, 10, 8, 10, 4, 103, 223, 40, 0, 16, 22, 10, 8, 10, 4, 103, 223, 44, 0, 16, 22, 10, 8, 10, 4, 103, 223, 48, 0, 16, 22, 10, 8, 10, 4, 103, 223, 52, 0, 16, 22, 10, 8, 10, 4, 103, 223, 56, 0, 16, 22, 10, 8, 10, 4, 103, 223, 60, 0, 16, 22, 10, 8, 10, 4, 103, 223, 64, 0, 16, 22, 10, 8, 10, 4, 103, 223, 68, 0, 16, 22, 10, 8, 10, 4, 103, 223, 72, 0, 16, 22, 10, 8, 10, 4, 103, 223, 76, 0, 16, 22, 10, 8, 10, 4, 103, 223, 80, 0, 16, 22, 10, 8, 10, 4, 103, 223, 84, 0, 16, 22, 10, 8, 10, 4, 103, 223, 88, 0, 16, 22, 10, 8, 10, 4, 103, 223, 92, 0, 16, 22, 10, 8, 10, 4, 103, 223, 96, 0, 16, 22, 10, 8, 10, 4, 103, 223, 100, 0, 16, 22, 10, 8, 10, 4, 103, 223, 104, 0, 16, 22, 10, 8, 10, 4, 103, 223, 108, 0, 16, 22, 10, 8, 10, 4, 103, 223, 112, 0, 16, 22, 10, 8, 10, 4, 103, 223, 116, 0, 16, 22, 10, 8, 10, 4, 103, 223, 120, 0, 16, 22, 10, 8, 10, 4, 103, 223, 124, 0, 16, 22, 10, 8, 10, 4, 103, 223, 128, 0, 16, 22, 10, 8, 10, 4, 103, 223, 132, 0, 16, 22, 10, 8, 10, 4, 103, 223, 140, 0, 16, 22, 10, 8, 10, 4, 103, 223, 144, 0, 16, 22, 10, 8, 10, 4, 103, 223, 148, 0, 16, 22, 10, 8, 10, 4, 103, 223, 152, 0, 16, 22, 10, 8, 10, 4, 103, 223, 156, 0, 16, 22, 10, 8, 10, 4, 103, 223, 160, 0, 16, 22, 10, 8, 10, 4, 103, 223, 164, 0, 16, 22, 10, 8, 10, 4, 103, 223, 168, 0, 16, 22, 10, 8, 10, 4, 103, 223, 172, 0, 16, 22, 10, 8, 10, 4, 103, 223, 176, 0, 16, 22, 10, 8, 10, 4, 103, 223, 180, 0, 16, 22, 10, 8, 10, 4, 103, 223, 188, 0, 16, 22, 10, 8, 10, 4, 103, 223, 192, 0, 16, 22, 10, 8, 10, 4, 103, 223, 196, 0, 16, 22, 10, 8, 10, 4, 103, 223, 200, 0, 16, 22, 10, 8, 10, 4, 103, 223, 204, 0, 16, 22, 10, 8, 10, 4, 103, 223, 208, 0, 16, 22, 10, 8, 10, 4, 103, 223, 212, 0, 16, 22, 10, 8, 10, 4, 103, 223, 216, 0, 16, 22, 10, 8, 10, 4, 103, 223, 220, 0, 16, 22, 10, 8, 10, 4, 103, 223, 224, 0, 16, 22, 10, 8, 10, 4, 103, 223, 228, 0, 16, 22, 10, 8, 10, 4, 103, 223, 232, 0, 16, 22, 10, 8, 10, 4, 103, 223, 236, 0, 16, 22, 10, 8, 10, 4, 103, 223, 240, 0, 16, 22, 10, 8, 10, 4, 103, 223, 244, 0, 16, 22, 10, 8, 10, 4, 103, 223, 248, 0, 16, 22, 10, 8, 10, 4, 103, 223, 252, 0, 16, 22, 10, 8, 10, 4, 103, 224, 0, 0, 16, 22, 10, 8, 10, 4, 103, 224, 16, 0, 16, 22, 10, 8, 10, 4, 103, 224, 40, 0, 16, 22, 10, 8, 10, 4, 103, 224, 44, 0, 16, 22, 10, 8, 10, 4, 103, 224, 60, 0, 16, 22, 10, 8, 10, 4, 103, 224, 80, 0, 16, 22, 10, 8, 10, 4, 103, 224, 220, 0, 16, 22, 10, 8, 10, 4, 103, 224, 224, 0, 16, 22, 10, 8, 10, 4, 103, 224, 228, 0, 16, 22, 10, 8, 10, 4, 103, 224, 232, 0, 16, 22, 10, 8, 10, 4, 103, 225, 84, 0, 16, 22, 10, 8, 10, 4, 103, 226, 16, 0, 16, 22, 10, 8, 10, 4, 103, 226, 40, 0, 16, 22, 10, 8, 10, 4, 103, 226, 56, 0, 16, 22, 10, 8, 10, 4, 103, 226, 60, 0, 16, 22, 10, 8, 10, 4, 103, 226, 80, 0, 16, 22, 10, 8, 10, 4, 103, 226, 116, 0, 16, 22, 10, 8, 10, 4, 103, 226, 132, 0, 16, 22, 10, 8, 10, 4, 103, 226, 156, 0, 16, 22, 10, 8, 10, 4, 103, 226, 180, 0, 16, 22, 10, 8, 10, 4, 103, 226, 196, 0, 16, 22, 10, 8, 10, 4, 103, 227, 48, 0, 16, 22, 10, 8, 10, 4, 103, 227, 72, 0, 16, 22, 10, 8, 10, 4, 103, 227, 76, 0, 16, 22, 10, 8, 10, 4, 103, 227, 80, 0, 16, 22, 10, 8, 10, 4, 103, 227, 100, 0, 16, 22, 10, 8, 10, 4, 103, 227, 120, 0, 16, 22, 10, 8, 10, 4, 103, 227, 132, 0, 16, 22, 10, 8, 10, 4, 103, 227, 136, 0, 16, 22, 10, 8, 10, 4, 103, 227, 196, 0, 16, 22, 10, 8, 10, 4, 103, 227, 204, 0, 16, 22, 10, 8, 10, 4, 103, 227, 212, 0, 16, 22, 10, 8, 10, 4, 103, 227, 228, 0, 16, 22, 10, 8, 10, 4, 103, 228, 12, 0, 16, 22, 10, 8, 10, 4, 103, 228, 28, 0, 16, 22, 10, 8, 10, 4, 103, 228, 68, 0, 16, 22, 10, 8, 10, 4, 103, 228, 88, 0, 16, 22, 10, 8, 10, 4, 103, 228, 128, 0, 16, 22, 10, 8, 10, 4, 103, 228, 136, 0, 16, 22, 10, 8, 10, 4, 103, 228, 160, 0, 16, 22, 10, 8, 10, 4, 103, 228, 176, 0, 16, 22, 10, 8, 10, 4, 103, 228, 204, 0, 16, 22, 10, 8, 10, 4, 103, 228, 208, 0, 16, 22, 10, 8, 10, 4, 103, 228, 228, 0, 16, 22, 10, 8, 10, 4, 103, 228, 232, 0, 16, 22, 10, 8, 10, 4, 103, 229, 20, 0, 16, 22, 10, 8, 10, 4, 103, 229, 60, 0, 16, 22, 10, 8, 10, 4, 103, 229, 136, 0, 16, 22, 10, 8, 10, 4, 103, 229, 148, 0, 16, 22, 10, 8, 10, 4, 103, 229, 172, 0, 16, 22, 10, 8, 10, 4, 103, 229, 212, 0, 16, 22, 10, 8, 10, 4, 103, 229, 216, 0, 16, 22, 10, 8, 10, 4, 103, 229, 220, 0, 16, 22, 10, 8, 10, 4, 103, 229, 228, 0, 16, 22, 10, 8, 10, 4, 103, 229, 236, 0, 16, 22, 10, 8, 10, 4, 103, 229, 240, 0, 16, 22, 10, 8, 10, 4, 103, 230, 0, 0, 16, 22, 10, 8, 10, 4, 103, 230, 28, 0, 16, 22, 10, 8, 10, 4, 103, 230, 40, 0, 16, 22, 10, 8, 10, 4, 103, 230, 44, 0, 16, 22, 10, 8, 10, 4, 103, 230, 96, 0, 16, 22, 10, 8, 10, 4, 103, 230, 196, 0, 16, 22, 10, 8, 10, 4, 103, 230, 200, 0, 16, 22, 10, 8, 10, 4, 103, 230, 204, 0, 16, 22, 10, 8, 10, 4, 103, 230, 212, 0, 16, 22, 10, 8, 10, 4, 103, 230, 236, 0, 16, 22, 10, 8, 10, 4, 103, 231, 16, 0, 16, 22, 10, 8, 10, 4, 103, 231, 20, 0, 16, 22, 10, 8, 10, 4, 103, 231, 64, 0, 16, 22, 10, 8, 10, 4, 103, 231, 68, 0, 16, 22, 10, 8, 10, 4, 103, 231, 144, 0, 16, 22, 10, 8, 10, 4, 103, 231, 180, 0, 16, 22, 10, 8, 10, 4, 103, 231, 184, 0, 16, 22, 10, 8, 10, 4, 103, 231, 244, 0, 16, 22, 10, 8, 10, 4, 103, 232, 4, 0, 16, 22, 10, 8, 10, 4, 103, 232, 144, 0, 16, 22, 10, 8, 10, 4, 103, 232, 188, 0, 16, 22, 10, 8, 10, 4, 103, 232, 212, 0, 16, 22, 10, 8, 10, 4, 103, 233, 4, 0, 16, 22, 10, 8, 10, 4, 103, 233, 44, 0, 16, 22, 10, 8, 10, 4, 103, 233, 52, 0, 16, 22, 10, 8, 10, 4, 103, 233, 104, 0, 16, 22, 10, 8, 10, 4, 103, 233, 128, 0, 16, 22, 10, 8, 10, 4, 103, 233, 136, 0, 16, 22, 10, 8, 10, 4, 103, 233, 228, 0, 16, 22, 10, 8, 10, 4, 103, 234, 0, 0, 16, 22, 10, 8, 10, 4, 103, 234, 20, 0, 16, 22, 10, 8, 10, 4, 103, 234, 56, 0, 16, 22, 10, 8, 10, 4, 103, 234, 124, 0, 16, 22, 10, 8, 10, 4, 103, 234, 128, 0, 16, 22, 10, 8, 10, 4, 103, 234, 172, 0, 16, 22, 10, 8, 10, 4, 103, 234, 180, 0, 16, 22, 10, 8, 10, 4, 103, 234, 244, 0, 16, 22, 10, 8, 10, 4, 103, 235, 16, 0, 16, 22, 10, 8, 10, 4, 103, 235, 48, 0, 16, 22, 10, 8, 10, 4, 103, 235, 56, 0, 16, 22, 10, 8, 10, 4, 103, 235, 60, 0, 16, 22, 10, 8, 10, 4, 103, 235, 80, 0, 16, 22, 10, 8, 10, 4, 103, 235, 84, 0, 16, 22, 10, 8, 10, 4, 103, 235, 128, 0, 16, 22, 10, 8, 10, 4, 103, 235, 132, 0, 16, 22, 10, 8, 10, 4, 103, 235, 136, 0, 16, 22, 10, 8, 10, 4, 103, 235, 140, 0, 16, 22, 10, 8, 10, 4, 103, 235, 144, 0, 16, 22, 10, 8, 10, 4, 103, 235, 148, 0, 16, 22, 10, 8, 10, 4, 103, 235, 184, 0, 16, 22, 10, 8, 10, 4, 103, 235, 192, 0, 16, 22, 10, 8, 10, 4, 103, 235, 200, 0, 16, 22, 10, 8, 10, 4, 103, 235, 220, 0, 16, 22, 10, 8, 10, 4, 103, 235, 224, 0, 16, 22, 10, 8, 10, 4, 103, 235, 228, 0, 16, 22, 10, 8, 10, 4, 103, 235, 232, 0, 16, 22, 10, 8, 10, 4, 103, 235, 236, 0, 16, 22, 10, 8, 10, 4, 103, 235, 240, 0, 16, 22, 10, 8, 10, 4, 103, 235, 244, 0, 16, 22, 10, 8, 10, 4, 103, 235, 248, 0, 16, 22, 10, 8, 10, 4, 103, 235, 252, 0, 16, 22, 10, 8, 10, 4, 103, 236, 0, 0, 16, 22, 10, 8, 10, 4, 103, 236, 4, 0, 16, 22, 10, 8, 10, 4, 103, 236, 8, 0, 16, 22, 10, 8, 10, 4, 103, 236, 12, 0, 16, 22, 10, 8, 10, 4, 103, 236, 16, 0, 16, 22, 10, 8, 10, 4, 103, 236, 20, 0, 16, 22, 10, 8, 10, 4, 103, 236, 24, 0, 16, 22, 10, 8, 10, 4, 103, 236, 28, 0, 16, 22, 10, 8, 10, 4, 103, 236, 32, 0, 16, 22, 10, 8, 10, 4, 103, 236, 36, 0, 16, 22, 10, 8, 10, 4, 103, 236, 40, 0, 16, 22, 10, 8, 10, 4, 103, 236, 44, 0, 16, 22, 10, 8, 10, 4, 103, 236, 48, 0, 16, 22, 10, 8, 10, 4, 103, 236, 52, 0, 16, 22, 10, 8, 10, 4, 103, 236, 56, 0, 16, 22, 10, 8, 10, 4, 103, 236, 60, 0, 16, 22, 10, 8, 10, 4, 103, 236, 64, 0, 16, 22, 10, 8, 10, 4, 103, 236, 68, 0, 16, 22, 10, 8, 10, 4, 103, 236, 72, 0, 16, 22, 10, 8, 10, 4, 103, 236, 76, 0, 16, 22, 10, 8, 10, 4, 103, 236, 80, 0, 16, 22, 10, 8, 10, 4, 103, 236, 84, 0, 16, 22, 10, 8, 10, 4, 103, 236, 88, 0, 16, 22, 10, 8, 10, 4, 103, 236, 92, 0, 16, 22, 10, 8, 10, 4, 103, 236, 96, 0, 16, 22, 10, 8, 10, 4, 103, 236, 120, 0, 16, 22, 10, 8, 10, 4, 103, 236, 184, 0, 16, 22, 10, 8, 10, 4, 103, 236, 220, 0, 16, 22, 10, 8, 10, 4, 103, 236, 232, 0, 16, 22, 10, 8, 10, 4, 103, 236, 240, 0, 16, 22, 10, 8, 10, 4, 103, 236, 244, 0, 16, 22, 10, 8, 10, 4, 103, 236, 248, 0, 16, 22, 10, 8, 10, 4, 103, 236, 252, 0, 16, 22, 10, 8, 10, 4, 103, 237, 0, 0, 16, 22, 10, 8, 10, 4, 103, 237, 4, 0, 16, 22, 10, 8, 10, 4, 103, 237, 8, 0, 16, 22, 10, 8, 10, 4, 103, 237, 12, 0, 16, 22, 10, 8, 10, 4, 103, 237, 24, 0, 16, 22, 10, 8, 10, 4, 103, 237, 28, 0, 16, 22, 10, 8, 10, 4, 103, 237, 68, 0, 16, 22, 10, 8, 10, 4, 103, 237, 88, 0, 16, 22, 10, 8, 10, 4, 103, 237, 152, 0, 16, 22, 10, 8, 10, 4, 103, 237, 176, 0, 16, 22, 10, 8, 10, 4, 103, 237, 180, 0, 16, 22, 10, 8, 10, 4, 103, 237, 184, 0, 16, 22, 10, 8, 10, 4, 103, 237, 188, 0, 16, 22, 10, 8, 10, 4, 103, 237, 192, 0, 16, 22, 10, 8, 10, 4, 103, 237, 196, 0, 16, 22, 10, 8, 10, 4, 103, 237, 200, 0, 16, 22, 10, 8, 10, 4, 103, 237, 204, 0, 16, 22, 10, 8, 10, 4, 103, 237, 208, 0, 16, 22, 10, 8, 10, 4, 103, 237, 212, 0, 16, 22, 10, 8, 10, 4, 103, 237, 216, 0, 16, 22, 10, 8, 10, 4, 103, 237, 220, 0, 16, 22, 10, 8, 10, 4, 103, 237, 224, 0, 16, 22, 10, 8, 10, 4, 103, 237, 228, 0, 16, 22, 10, 8, 10, 4, 103, 237, 232, 0, 16, 22, 10, 8, 10, 4, 103, 237, 236, 0, 16, 22, 10, 8, 10, 4, 103, 237, 240, 0, 16, 22, 10, 8, 10, 4, 103, 237, 244, 0, 16, 22, 10, 8, 10, 4, 103, 237, 248, 0, 16, 22, 10, 8, 10, 4, 103, 237, 252, 0, 16, 22, 10, 8, 10, 4, 103, 238, 0, 0, 16, 22, 10, 8, 10, 4, 103, 238, 4, 0, 16, 22, 10, 8, 10, 4, 103, 238, 16, 0, 16, 22, 10, 8, 10, 4, 103, 238, 20, 0, 16, 22, 10, 8, 10, 4, 103, 238, 24, 0, 16, 22, 10, 8, 10, 4, 103, 238, 28, 0, 16, 22, 10, 8, 10, 4, 103, 238, 32, 0, 16, 22, 10, 8, 10, 4, 103, 238, 36, 0, 16, 22, 10, 8, 10, 4, 103, 238, 40, 0, 16, 22, 10, 8, 10, 4, 103, 238, 44, 0, 16, 22, 10, 8, 10, 4, 103, 238, 48, 0, 16, 22, 10, 8, 10, 4, 103, 238, 52, 0, 16, 22, 10, 8, 10, 4, 103, 238, 56, 0, 16, 22, 10, 8, 10, 4, 103, 238, 88, 0, 16, 22, 10, 8, 10, 4, 103, 238, 92, 0, 16, 22, 10, 8, 10, 4, 103, 238, 96, 0, 16, 22, 10, 8, 10, 4, 103, 238, 132, 0, 16, 22, 10, 8, 10, 4, 103, 238, 140, 0, 16, 22, 10, 8, 10, 4, 103, 238, 144, 0, 16, 22, 10, 8, 10, 4, 103, 238, 160, 0, 16, 22, 10, 8, 10, 4, 103, 238, 164, 0, 16, 22, 10, 8, 10, 4, 103, 238, 168, 0, 16, 22, 10, 8, 10, 4, 103, 238, 172, 0, 16, 22, 10, 8, 10, 4, 103, 238, 176, 0, 16, 22, 10, 8, 10, 4, 103, 238, 180, 0, 16, 22, 10, 8, 10, 4, 103, 238, 184, 0, 16, 22, 10, 8, 10, 4, 103, 238, 188, 0, 16, 22, 10, 8, 10, 4, 103, 238, 196, 0, 16, 22, 10, 8, 10, 4, 103, 238, 204, 0, 16, 22, 10, 8, 10, 4, 103, 238, 252, 0, 16, 22, 10, 8, 10, 4, 103, 239, 0, 0, 16, 22, 10, 8, 10, 4, 103, 239, 44, 0, 16, 22, 10, 8, 10, 4, 103, 239, 68, 0, 16, 22, 10, 8, 10, 4, 103, 239, 96, 0, 16, 22, 10, 8, 10, 4, 103, 239, 152, 0, 16, 22, 10, 8, 10, 4, 103, 239, 156, 0, 16, 22, 10, 8, 10, 4, 103, 239, 176, 0, 16, 22, 10, 8, 10, 4, 103, 239, 180, 0, 16, 22, 10, 8, 10, 4, 103, 239, 184, 0, 16, 22, 10, 8, 10, 4, 103, 239, 192, 0, 16, 22, 10, 8, 10, 4, 103, 239, 196, 0, 16, 22, 10, 8, 10, 4, 103, 239, 204, 0, 16, 22, 10, 8, 10, 4, 103, 239, 208, 0, 16, 22, 10, 8, 10, 4, 103, 239, 224, 0, 16, 22, 10, 8, 10, 4, 103, 239, 244, 0, 16, 22, 10, 8, 10, 4, 103, 240, 16, 0, 16, 22, 10, 8, 10, 4, 103, 240, 36, 0, 16, 22, 10, 8, 10, 4, 103, 240, 72, 0, 16, 22, 10, 8, 10, 4, 103, 240, 84, 0, 16, 22, 10, 8, 10, 4, 103, 240, 124, 0, 16, 22, 10, 8, 10, 4, 103, 240, 156, 0, 16, 22, 10, 8, 10, 4, 103, 240, 172, 0, 16, 22, 10, 8, 10, 4, 103, 240, 188, 0, 16, 22, 10, 8, 10, 4, 103, 240, 244, 0, 16, 22, 10, 8, 10, 4, 103, 241, 12, 0, 16, 22, 10, 8, 10, 4, 103, 241, 72, 0, 16, 22, 10, 8, 10, 4, 103, 241, 92, 0, 16, 22, 10, 8, 10, 4, 103, 241, 96, 0, 16, 22, 10, 8, 10, 4, 103, 241, 160, 0, 16, 22, 10, 8, 10, 4, 103, 241, 184, 0, 16, 22, 10, 8, 10, 4, 103, 241, 188, 0, 16, 22, 10, 8, 10, 4, 103, 241, 220, 0, 16, 22, 10, 8, 10, 4, 103, 242, 8, 0, 16, 22, 10, 8, 10, 4, 103, 242, 64, 0, 16, 22, 10, 8, 10, 4, 103, 242, 128, 0, 16, 22, 10, 8, 10, 4, 103, 242, 132, 0, 16, 22, 10, 8, 10, 4, 103, 242, 160, 0, 16, 22, 10, 8, 10, 4, 103, 242, 168, 0, 16, 22, 10, 8, 10, 4, 103, 242, 172, 0, 16, 22, 10, 8, 10, 4, 103, 242, 176, 0, 16, 22, 10, 8, 10, 4, 103, 242, 200, 0, 16, 22, 10, 8, 10, 4, 103, 242, 212, 0, 16, 22, 10, 8, 10, 4, 103, 242, 220, 0, 16, 22, 10, 8, 10, 4, 103, 242, 240, 0, 16, 22, 10, 8, 10, 4, 103, 243, 136, 0, 16, 22, 10, 8, 10, 4, 103, 243, 252, 0, 16, 22, 10, 8, 10, 4, 103, 244, 16, 0, 16, 22, 10, 8, 10, 4, 103, 244, 58, 0, 16, 23, 10, 8, 10, 4, 103, 244, 60, 0, 16, 22, 10, 8, 10, 4, 103, 244, 64, 0, 16, 22, 10, 8, 10, 4, 103, 244, 68, 0, 16, 22, 10, 8, 10, 4, 103, 244, 72, 0, 16, 22, 10, 8, 10, 4, 103, 244, 76, 0, 16, 22, 10, 8, 10, 4, 103, 244, 80, 0, 16, 22, 10, 8, 10, 4, 103, 244, 84, 0, 16, 22, 10, 8, 10, 4, 103, 244, 116, 0, 16, 22, 10, 8, 10, 4, 103, 244, 164, 0, 16, 22, 10, 8, 10, 4, 103, 244, 232, 0, 16, 22, 10, 8, 10, 4, 103, 244, 252, 0, 16, 22, 10, 8, 10, 4, 103, 245, 23, 0, 16, 24, 10, 8, 10, 4, 103, 245, 52, 0, 16, 22, 10, 8, 10, 4, 103, 245, 60, 0, 16, 22, 10, 8, 10, 4, 103, 245, 80, 0, 16, 22, 10, 8, 10, 4, 103, 245, 124, 0, 16, 22, 10, 8, 10, 4, 103, 245, 128, 0, 16, 22, 10, 8, 10, 4, 103, 246, 8, 0, 16, 22, 10, 8, 10, 4, 103, 246, 12, 0, 16, 22, 10, 8, 10, 4, 103, 246, 120, 0, 16, 22, 10, 8, 10, 4, 103, 246, 124, 0, 16, 22, 10, 8, 10, 4, 103, 246, 132, 0, 16, 22, 10, 8, 10, 4, 103, 246, 152, 0, 16, 22, 10, 8, 10, 4, 103, 246, 156, 0, 16, 22, 10, 8, 10, 4, 103, 247, 168, 0, 16, 22, 10, 8, 10, 4, 103, 247, 172, 0, 16, 22, 10, 8, 10, 4, 103, 247, 176, 0, 16, 22, 10, 8, 10, 4, 103, 247, 200, 0, 16, 22, 10, 8, 10, 4, 103, 247, 212, 0, 16, 22, 10, 8, 10, 4, 103, 248, 0, 0, 16, 23, 10, 8, 10, 4, 103, 248, 64, 0, 16, 22, 10, 8, 10, 4, 103, 248, 100, 0, 16, 22, 10, 8, 10, 4, 103, 248, 124, 0, 16, 22, 10, 8, 10, 4, 103, 248, 152, 0, 16, 22, 10, 8, 10, 4, 103, 248, 168, 0, 16, 22, 10, 8, 10, 4, 103, 248, 192, 0, 16, 22, 10, 8, 10, 4, 103, 248, 212, 0, 16, 22, 10, 8, 10, 4, 103, 248, 220, 0, 16, 22, 10, 8, 10, 4, 103, 248, 224, 0, 16, 22, 10, 8, 10, 4, 103, 248, 228, 0, 16, 22, 10, 8, 10, 4, 103, 249, 8, 0, 16, 22, 10, 8, 10, 4, 103, 249, 12, 0, 16, 22, 10, 8, 10, 4, 103, 249, 52, 0, 16, 22, 10, 8, 10, 4, 103, 249, 104, 0, 16, 22, 10, 8, 10, 4, 103, 249, 128, 0, 16, 22, 10, 8, 10, 4, 103, 249, 136, 0, 16, 22, 10, 8, 10, 4, 103, 249, 144, 0, 16, 22, 10, 8, 10, 4, 103, 249, 164, 0, 16, 22, 10, 8, 10, 4, 103, 249, 168, 0, 16, 22, 10, 8, 10, 4, 103, 249, 172, 0, 16, 22, 10, 8, 10, 4, 103, 249, 176, 0, 16, 22, 10, 8, 10, 4, 103, 249, 188, 0, 16, 22, 10, 8, 10, 4, 103, 249, 192, 0, 16, 22, 10, 8, 10, 4, 103, 249, 244, 0, 16, 22, 10, 8, 10, 4, 103, 249, 252, 0, 16, 22, 10, 8, 10, 4, 103, 250, 32, 0, 16, 22, 10, 8, 10, 4, 103, 250, 104, 0, 16, 22, 10, 8, 10, 4, 103, 250, 124, 0, 16, 22, 10, 8, 10, 4, 103, 250, 180, 0, 16, 22, 10, 8, 10, 4, 103, 250, 192, 0, 16, 22, 10, 8, 10, 4, 103, 250, 216, 0, 16, 22, 10, 8, 10, 4, 103, 250, 224, 0, 16, 22, 10, 8, 10, 4, 103, 250, 236, 0, 16, 22, 10, 8, 10, 4, 103, 250, 248, 0, 16, 22, 10, 8, 10, 4, 103, 250, 252, 0, 16, 22, 10, 8, 10, 4, 103, 251, 32, 0, 16, 22, 10, 8, 10, 4, 103, 251, 36, 0, 16, 22, 10, 8, 10, 4, 103, 251, 84, 0, 16, 22, 10, 8, 10, 4, 103, 251, 96, 0, 16, 22, 10, 8, 10, 4, 103, 251, 124, 0, 16, 22, 10, 8, 10, 4, 103, 251, 128, 0, 16, 22, 10, 8, 10, 4, 103, 251, 160, 0, 16, 22, 10, 8, 10, 4, 103, 251, 192, 0, 16, 22, 10, 8, 10, 4, 103, 251, 204, 0, 16, 22, 10, 8, 10, 4, 103, 251, 236, 0, 16, 22, 10, 8, 10, 4, 103, 251, 240, 0, 16, 22, 10, 8, 10, 4, 103, 252, 28, 0, 16, 22, 10, 8, 10, 4, 103, 252, 36, 0, 16, 22, 10, 8, 10, 4, 103, 252, 64, 0, 16, 22, 10, 8, 10, 4, 103, 252, 96, 0, 16, 22, 10, 8, 10, 4, 103, 252, 104, 0, 16, 22, 10, 8, 10, 4, 103, 252, 172, 0, 16, 22, 10, 8, 10, 4, 103, 252, 204, 0, 16, 22, 10, 8, 10, 4, 103, 252, 208, 0, 16, 22, 10, 8, 10, 4, 103, 252, 232, 0, 16, 22, 10, 8, 10, 4, 103, 252, 248, 0, 16, 22, 10, 8, 10, 4, 103, 253, 4, 0, 16, 22, 10, 8, 10, 4, 103, 253, 60, 0, 16, 22, 10, 8, 10, 4, 103, 253, 204, 0, 16, 22, 10, 8, 10, 4, 103, 253, 220, 0, 16, 22, 10, 8, 10, 4, 103, 253, 224, 0, 16, 22, 10, 8, 10, 4, 103, 253, 232, 0, 16, 22, 10, 8, 10, 4, 103, 254, 8, 0, 16, 22, 10, 8, 10, 4, 103, 254, 20, 0, 16, 22, 10, 8, 10, 4, 103, 254, 64, 0, 16, 22, 10, 8, 10, 4, 103, 254, 68, 0, 16, 22, 10, 8, 10, 4, 103, 254, 72, 0, 16, 22, 10, 8, 10, 4, 103, 254, 76, 0, 16, 22, 10, 8, 10, 4, 103, 254, 112, 0, 16, 22, 10, 8, 10, 4, 103, 254, 176, 0, 16, 22, 10, 8, 10, 4, 103, 254, 188, 0, 16, 22, 10, 8, 10, 4, 103, 254, 196, 0, 16, 24, 10, 8, 10, 4, 103, 254, 220, 0, 16, 22, 10, 8, 10, 4, 103, 255, 56, 0, 16, 22, 10, 8, 10, 4, 103, 255, 68, 0, 16, 22, 10, 8, 10, 4, 103, 255, 88, 0, 16, 22, 10, 8, 10, 4, 103, 255, 92, 0, 16, 22, 10, 8, 10, 4, 103, 255, 136, 0, 16, 22, 10, 8, 10, 4, 103, 255, 140, 0, 16, 22, 10, 8, 10, 4, 103, 255, 184, 0, 16, 22, 10, 8, 10, 4, 103, 255, 200, 0, 16, 22, 10, 8, 10, 4, 103, 255, 212, 0, 16, 22, 10, 8, 10, 4, 103, 255, 228, 0, 16, 22, 10, 8, 10, 4, 106, 0, 0, 0, 16, 24, 10, 8, 10, 4, 106, 0, 2, 0, 16, 23, 10, 8, 10, 4, 106, 0, 4, 0, 16, 22, 10, 8, 10, 4, 106, 0, 8, 0, 16, 21, 10, 8, 10, 4, 106, 0, 16, 0, 16, 20, 10, 8, 10, 4, 106, 0, 44, 0, 16, 22, 10, 8, 10, 4, 106, 0, 64, 0, 16, 18, 10, 8, 10, 4, 106, 2, 0, 0, 16, 15, 10, 8, 10, 4, 106, 4, 0, 0, 16, 14, 10, 8, 10, 4, 106, 8, 0, 0, 16, 15, 10, 8, 10, 4, 106, 11, 0, 0, 16, 16, 10, 8, 10, 4, 106, 12, 0, 0, 16, 14, 10, 8, 10, 4, 106, 16, 0, 0, 16, 12, 10, 8, 10, 4, 106, 32, 0, 0, 16, 12, 10, 8, 10, 4, 106, 48, 0, 0, 16, 15, 10, 8, 10, 4, 106, 50, 0, 0, 16, 16, 10, 8, 10, 4, 106, 52, 0, 0, 16, 14, 10, 8, 10, 4, 106, 56, 0, 0, 16, 13, 10, 8, 10, 4, 106, 74, 0, 0, 16, 16, 10, 8, 10, 4, 106, 75, 0, 0, 16, 16, 10, 8, 10, 4, 106, 80, 0, 0, 16, 12, 10, 8, 10, 4, 106, 108, 0, 0, 16, 14, 10, 8, 10, 4, 106, 112, 0, 0, 16, 13, 10, 8, 10, 4, 106, 120, 0, 0, 16, 13, 10, 8, 10, 4, 106, 224, 0, 0, 16, 12, 10, 8, 10, 4, 109, 244, 0, 0, 16, 16, 10, 8, 10, 4, 110, 6, 0, 0, 16, 15, 10, 8, 10, 4, 110, 16, 0, 0, 16, 14, 10, 8, 10, 4, 110, 34, 40, 0, 16, 22, 10, 8, 10, 4, 110, 34, 44, 0, 16, 22, 10, 8, 10, 4, 110, 40, 0, 0, 16, 14, 10, 8, 10, 4, 110, 44, 12, 0, 16, 22, 10, 8, 10, 4, 110, 44, 144, 0, 16, 20, 10, 8, 10, 4, 110, 48, 0, 0, 16, 16, 10, 8, 10, 4, 110, 51, 0, 0, 16, 16, 10, 8, 10, 4, 110, 52, 0, 0, 16, 15, 10, 8, 10, 4, 110, 56, 0, 0, 16, 13, 10, 8, 10, 4, 110, 64, 0, 0, 16, 15, 10, 8, 10, 4, 110, 72, 0, 0, 16, 15, 10, 8, 10, 4, 110, 75, 0, 0, 16, 17, 10, 8, 10, 4, 110, 75, 128, 0, 16, 19, 10, 8, 10, 4, 110, 75, 160, 0, 16, 19, 10, 8, 10, 4, 110, 75, 192, 0, 16, 18, 10, 8, 10, 4, 110, 76, 0, 0, 16, 19, 10, 8, 10, 4, 110, 76, 32, 0, 16, 19, 10, 8, 10, 4, 110, 76, 132, 0, 16, 22, 10, 8, 10, 4, 110, 76, 156, 0, 16, 22, 10, 8, 10, 4, 110, 76, 184, 0, 16, 22, 10, 8, 10, 4, 110, 76, 192, 0, 16, 18, 10, 8, 10, 4, 110, 77, 0, 0, 16, 17, 10, 8, 10, 4, 110, 80, 0, 0, 16, 13, 10, 8, 10, 4, 110, 88, 0, 0, 16, 14, 10, 8, 10, 4, 110, 92, 68, 0, 16, 22, 10, 8, 10, 4, 110, 93, 32, 0, 16, 19, 10, 8, 10, 4, 110, 94, 0, 0, 16, 15, 10, 8, 10, 4, 110, 96, 0, 0, 16, 11, 10, 8, 10, 4, 110, 152, 0, 0, 16, 14, 10, 8, 10, 4, 110, 156, 0, 0, 16, 15, 10, 8, 10, 4, 110, 165, 32, 0, 16, 19, 10, 8, 10, 4, 110, 166, 0, 0, 16, 15, 10, 8, 10, 4, 110, 172, 192, 0, 16, 18, 10, 8, 10, 4, 110, 173, 0, 0, 16, 19, 10, 8, 10, 4, 110, 173, 32, 0, 16, 20, 10, 8, 10, 4, 110, 173, 64, 0, 16, 19, 10, 8, 10, 4, 110, 173, 96, 0, 16, 19, 10, 8, 10, 4, 110, 173, 192, 0, 16, 19, 10, 8, 10, 4, 110, 176, 0, 0, 16, 13, 10, 8, 10, 4, 110, 184, 0, 0, 16, 13, 10, 8, 10, 4, 110, 192, 0, 0, 16, 11, 10, 8, 10, 4, 110, 228, 0, 0, 16, 14, 10, 8, 10, 4, 110, 232, 32, 0, 16, 19, 10, 8, 10, 4, 110, 236, 0, 0, 16, 15, 10, 8, 10, 4, 110, 240, 0, 0, 16, 12, 10, 8, 10, 4, 111, 0, 0, 0, 16, 10, 10, 8, 10, 4, 111, 66, 0, 0, 16, 16, 10, 8, 10, 4, 111, 67, 192, 0, 16, 20, 10, 8, 10, 4, 111, 68, 64, 0, 16, 19, 10, 8, 10, 4, 111, 72, 0, 0, 16, 13, 10, 8, 10, 4, 111, 85, 0, 0, 16, 16, 10, 8, 10, 4, 111, 91, 192, 0, 16, 19, 10, 8, 10, 4, 111, 92, 248, 0, 16, 22, 10, 8, 10, 4, 111, 92, 252, 0, 16, 22, 10, 8, 10, 4, 111, 112, 0, 0, 16, 15, 10, 8, 10, 4, 111, 114, 0, 0, 16, 15, 10, 8, 10, 4, 111, 116, 0, 0, 16, 15, 10, 8, 10, 4, 111, 118, 200, 0, 16, 21, 10, 8, 10, 4, 111, 119, 64, 0, 16, 18, 10, 8, 10, 4, 111, 119, 128, 0, 16, 19, 10, 8, 10, 4, 111, 120, 0, 0, 16, 14, 10, 8, 10, 4, 111, 124, 0, 0, 16, 16, 10, 8, 10, 4, 111, 126, 0, 0, 16, 15, 10, 8, 10, 4, 111, 128, 0, 0, 16, 11, 10, 8, 10, 4, 111, 160, 0, 0, 16, 13, 10, 8, 10, 4, 111, 170, 0, 0, 16, 16, 10, 8, 10, 4, 111, 172, 0, 0, 16, 14, 10, 8, 10, 4, 111, 176, 0, 0, 16, 13, 10, 8, 10, 4, 111, 186, 0, 0, 16, 15, 10, 8, 10, 4, 111, 192, 0, 0, 16, 12, 10, 8, 10, 4, 111, 208, 0, 0, 16, 14, 10, 8, 10, 4, 111, 212, 0, 0, 16, 14, 10, 8, 10, 4, 111, 221, 28, 0, 16, 24, 10, 8, 10, 4, 111, 221, 128, 0, 16, 17, 10, 8, 10, 4, 111, 222, 0, 0, 16, 16, 10, 8, 10, 4, 111, 223, 4, 0, 16, 22, 10, 8, 10, 4, 111, 223, 8, 0, 16, 22, 10, 8, 10, 4, 111, 223, 12, 0, 16, 22, 10, 8, 10, 4, 111, 223, 16, 0, 16, 22, 10, 8, 10, 4, 111, 223, 240, 0, 16, 22, 10, 8, 10, 4, 111, 223, 248, 0, 16, 22, 10, 8, 10, 4, 111, 224, 0, 0, 16, 14, 10, 8, 10, 4, 111, 228, 0, 0, 16, 14, 10, 8, 10, 4, 111, 235, 96, 0, 16, 19, 10, 8, 10, 4, 111, 235, 156, 0, 16, 22, 10, 8, 10, 4, 111, 235, 160, 0, 16, 19, 10, 8, 10, 4, 112, 0, 0, 0, 16, 10, 10, 8, 10, 4, 112, 64, 0, 0, 16, 15, 10, 8, 10, 4, 112, 66, 0, 0, 16, 15, 10, 8, 10, 4, 112, 73, 0, 0, 16, 16, 10, 8, 10, 4, 112, 74, 0, 0, 16, 15, 10, 8, 10, 4, 112, 80, 0, 0, 16, 13, 10, 8, 10, 4, 112, 88, 0, 0, 16, 13, 10, 8, 10, 4, 112, 96, 0, 0, 16, 15, 10, 8, 10, 4, 112, 98, 0, 0, 16, 15, 10, 8, 10, 4, 112, 100, 0, 0, 16, 14, 10, 8, 10, 4, 112, 109, 128, 0, 16, 17, 10, 8, 10, 4, 112, 111, 0, 0, 16, 16, 10, 8, 10, 4, 112, 112, 0, 0, 16, 14, 10, 8, 10, 4, 112, 116, 0, 0, 16, 15, 10, 8, 10, 4, 112, 122, 0, 0, 16, 15, 10, 8, 10, 4, 112, 124, 0, 0, 16, 14, 10, 8, 10, 4, 112, 128, 0, 0, 16, 14, 10, 8, 10, 4, 112, 132, 0, 0, 16, 16, 10, 8, 10, 4, 112, 137, 48, 0, 16, 21, 10, 8, 10, 4, 112, 192, 0, 0, 16, 14, 10, 8, 10, 4, 112, 224, 0, 0, 16, 11, 10, 8, 10, 4, 113, 0, 0, 0, 16, 13, 10, 8, 10, 4, 113, 8, 0, 0, 16, 15, 10, 8, 10, 4, 113, 11, 192, 0, 16, 19, 10, 8, 10, 4, 113, 12, 0, 0, 16, 14, 10, 8, 10, 4, 113, 16, 0, 0, 16, 15, 10, 8, 10, 4, 113, 18, 0, 0, 16, 16, 10, 8, 10, 4, 113, 21, 232, 0, 16, 22, 10, 8, 10, 4, 113, 21, 236, 0, 16, 22, 10, 8, 10, 4, 113, 24, 0, 0, 16, 14, 10, 8, 10, 4, 113, 31, 0, 0, 16, 16, 10, 8, 10, 4, 113, 44, 0, 0, 16, 14, 10, 8, 10, 4, 113, 48, 0, 0, 16, 14, 10, 8, 10, 4, 113, 52, 160, 0, 16, 19, 10, 8, 10, 4, 113, 52, 228, 0, 16, 22, 10, 8, 10, 4, 113, 54, 0, 0, 16, 15, 10, 8, 10, 4, 113, 56, 0, 0, 16, 15, 10, 8, 10, 4, 113, 58, 0, 0, 16, 16, 10, 8, 10, 4, 113, 59, 0, 0, 16, 17, 10, 8, 10, 4, 113, 59, 224, 0, 16, 22, 10, 8, 10, 4, 113, 62, 0, 0, 16, 15, 10, 8, 10, 4, 113, 64, 0, 0, 16, 11, 10, 8, 10, 4, 113, 96, 0, 0, 16, 12, 10, 8, 10, 4, 113, 112, 0, 0, 16, 13, 10, 8, 10, 4, 113, 120, 0, 0, 16, 13, 10, 8, 10, 4, 113, 128, 0, 0, 16, 15, 10, 8, 10, 4, 113, 130, 96, 0, 16, 20, 10, 8, 10, 4, 113, 130, 112, 0, 16, 21, 10, 8, 10, 4, 113, 132, 0, 0, 16, 14, 10, 8, 10, 4, 113, 136, 0, 0, 16, 13, 10, 8, 10, 4, 113, 194, 0, 0, 16, 15, 10, 8, 10, 4, 113, 197, 100, 0, 16, 22, 10, 8, 10, 4, 113, 200, 0, 0, 16, 15, 10, 8, 10, 4, 113, 202, 0, 0, 16, 16, 10, 8, 10, 4, 113, 204, 0, 0, 16, 14, 10, 8, 10, 4, 113, 208, 96, 0, 16, 19, 10, 8, 10, 4, 113, 208, 128, 0, 16, 17, 10, 8, 10, 4, 113, 209, 0, 0, 16, 16, 10, 8, 10, 4, 113, 212, 0, 0, 16, 18, 10, 8, 10, 4, 113, 212, 100, 0, 16, 22, 10, 8, 10, 4, 113, 212, 184, 0, 16, 21, 10, 8, 10, 4, 113, 213, 0, 0, 16, 17, 10, 8, 10, 4, 113, 214, 0, 0, 16, 15, 10, 8, 10, 4, 113, 218, 0, 0, 16, 15, 10, 8, 10, 4, 113, 220, 0, 0, 16, 14, 10, 8, 10, 4, 113, 224, 0, 0, 16, 12, 10, 8, 10, 4, 113, 240, 0, 0, 16, 13, 10, 8, 10, 4, 113, 248, 0, 0, 16, 14, 10, 8, 10, 4, 114, 28, 0, 0, 16, 16, 10, 8, 10, 4, 114, 31, 64, 0, 16, 22, 10, 8, 10, 4, 114, 31, 68, 0, 16, 22, 10, 8, 10, 4, 114, 54, 0, 0, 16, 15, 10, 8, 10, 4, 114, 60, 0, 0, 16, 14, 10, 8, 10, 4, 114, 64, 0, 0, 16, 14, 10, 8, 10, 4, 114, 68, 0, 0, 16, 16, 10, 8, 10, 4, 114, 79, 64, 0, 16, 18, 10, 8, 10, 4, 114, 80, 0, 0, 16, 12, 10, 8, 10, 4, 114, 96, 0, 0, 16, 13, 10, 8, 10, 4, 114, 104, 0, 0, 16, 14, 10, 8, 10, 4, 114, 110, 0, 0, 16, 20, 10, 8, 10, 4, 114, 110, 64, 0, 16, 18, 10, 8, 10, 4, 114, 111, 0, 0, 16, 19, 10, 8, 10, 4, 114, 111, 160, 0, 16, 19, 10, 8, 10, 4, 114, 112, 0, 0, 16, 14, 10, 8, 10, 4, 114, 116, 0, 0, 16, 16, 10, 8, 10, 4, 114, 117, 0, 0, 16, 16, 10, 8, 10, 4, 114, 118, 0, 0, 16, 16, 10, 8, 10, 4, 114, 119, 0, 0, 16, 17, 10, 8, 10, 4, 114, 119, 128, 0, 16, 18, 10, 8, 10, 4, 114, 119, 192, 0, 16, 21, 10, 8, 10, 4, 114, 119, 200, 0, 16, 22, 10, 8, 10, 4, 114, 119, 204, 0, 16, 22, 10, 8, 10, 4, 114, 119, 208, 0, 16, 20, 10, 8, 10, 4, 114, 119, 224, 0, 16, 19, 10, 8, 10, 4, 114, 132, 0, 0, 16, 16, 10, 8, 10, 4, 114, 135, 0, 0, 16, 16, 10, 8, 10, 4, 114, 138, 0, 0, 16, 15, 10, 8, 10, 4, 114, 141, 64, 0, 16, 21, 10, 8, 10, 4, 114, 141, 80, 0, 16, 22, 10, 8, 10, 4, 114, 141, 84, 0, 16, 22, 10, 8, 10, 4, 114, 141, 128, 0, 16, 18, 10, 8, 10, 4, 114, 196, 0, 0, 16, 15, 10, 8, 10, 4, 114, 198, 248, 0, 16, 21, 10, 8, 10, 4, 114, 208, 0, 0, 16, 14, 10, 8, 10, 4, 114, 212, 0, 0, 16, 15, 10, 8, 10, 4, 114, 214, 0, 0, 16, 16, 10, 8, 10, 4, 114, 215, 0, 0, 16, 16, 10, 8, 10, 4, 114, 216, 0, 0, 16, 13, 10, 8, 10, 4, 114, 224, 0, 0, 16, 12, 10, 8, 10, 4, 114, 240, 0, 0, 16, 12, 10, 8, 10, 4, 115, 24, 0, 0, 16, 14, 10, 8, 10, 4, 115, 28, 0, 0, 16, 15, 10, 8, 10, 4, 115, 31, 64, 0, 16, 22, 10, 8, 10, 4, 115, 31, 68, 0, 16, 22, 10, 8, 10, 4, 115, 31, 72, 0, 16, 22, 10, 8, 10, 4, 115, 31, 76, 0, 16, 22, 10, 8, 10, 4, 115, 32, 0, 0, 16, 14, 10, 8, 10, 4, 115, 42, 56, 0, 16, 22, 10, 8, 10, 4, 115, 44, 0, 0, 16, 15, 10, 8, 10, 4, 115, 46, 0, 0, 16, 16, 10, 8, 10, 4, 115, 47, 0, 0, 16, 16, 10, 8, 10, 4, 115, 48, 0, 0, 16, 12, 10, 8, 10, 4, 115, 69, 64, 0, 16, 20, 10, 8, 10, 4, 115, 84, 0, 0, 16, 18, 10, 8, 10, 4, 115, 84, 192, 0, 16, 19, 10, 8, 10, 4, 115, 85, 192, 0, 16, 18, 10, 8, 10, 4, 115, 100, 0, 0, 16, 14, 10, 8, 10, 4, 115, 104, 0, 0, 16, 14, 10, 8, 10, 4, 115, 120, 0, 0, 16, 14, 10, 8, 10, 4, 115, 124, 16, 0, 16, 20, 10, 8, 10, 4, 115, 148, 0, 0, 16, 14, 10, 8, 10, 4, 115, 152, 0, 0, 16, 15, 10, 8, 10, 4, 115, 154, 0, 0, 16, 15, 10, 8, 10, 4, 115, 156, 0, 0, 16, 15, 10, 8, 10, 4, 115, 158, 0, 0, 16, 16, 10, 8, 10, 4, 115, 159, 0, 0, 16, 16, 10, 8, 10, 4, 115, 166, 64, 0, 16, 19, 10, 8, 10, 4, 115, 168, 0, 0, 16, 14, 10, 8, 10, 4, 115, 172, 0, 0, 16, 14, 10, 8, 10, 4, 115, 180, 0, 0, 16, 14, 10, 8, 10, 4, 115, 187, 0, 0, 16, 22, 10, 8, 10, 4, 115, 187, 4, 0, 16, 22, 10, 8, 10, 4, 115, 187, 8, 0, 16, 22, 10, 8, 10, 4, 115, 187, 12, 0, 16, 22, 10, 8, 10, 4, 115, 190, 0, 0, 16, 15, 10, 8, 10, 4, 115, 192, 0, 0, 16, 11, 10, 8, 10, 4, 115, 224, 0, 0, 16, 12, 10, 8, 10, 4, 116, 0, 8, 0, 16, 21, 10, 8, 10, 4, 116, 0, 24, 0, 16, 21, 10, 8, 10, 4, 116, 1, 0, 0, 16, 16, 10, 8, 10, 4, 116, 2, 0, 0, 16, 15, 10, 8, 10, 4, 116, 4, 0, 0, 16, 14, 10, 8, 10, 4, 116, 8, 0, 0, 16, 14, 10, 8, 10, 4, 116, 13, 0, 0, 16, 16, 10, 8, 10, 4, 116, 16, 0, 0, 16, 12, 10, 8, 10, 4, 116, 50, 0, 0, 16, 20, 10, 8, 10, 4, 116, 52, 0, 0, 16, 14, 10, 8, 10, 4, 116, 56, 0, 0, 16, 15, 10, 8, 10, 4, 116, 58, 128, 0, 16, 20, 10, 8, 10, 4, 116, 58, 208, 0, 16, 20, 10, 8, 10, 4, 116, 60, 0, 0, 16, 14, 10, 8, 10, 4, 116, 66, 0, 0, 16, 17, 10, 8, 10, 4, 116, 66, 176, 0, 16, 22, 10, 8, 10, 4, 116, 68, 136, 0, 16, 22, 10, 8, 10, 4, 116, 68, 140, 0, 16, 22, 10, 8, 10, 4, 116, 68, 176, 0, 16, 22, 10, 8, 10, 4, 116, 68, 180, 0, 16, 22, 10, 8, 10, 4, 116, 69, 0, 0, 16, 16, 10, 8, 10, 4, 116, 70, 0, 0, 16, 17, 10, 8, 10, 4, 116, 76, 0, 0, 16, 15, 10, 8, 10, 4, 116, 78, 0, 0, 16, 15, 10, 8, 10, 4, 116, 85, 0, 0, 16, 16, 10, 8, 10, 4, 116, 89, 144, 0, 16, 20, 10, 8, 10, 4, 116, 89, 240, 0, 16, 22, 10, 8, 10, 4, 116, 90, 80, 0, 16, 20, 10, 8, 10, 4, 116, 90, 184, 0, 16, 21, 10, 8, 10, 4, 116, 95, 0, 0, 16, 16, 10, 8, 10, 4, 116, 112, 0, 0, 16, 14, 10, 8, 10, 4, 116, 116, 0, 0, 16, 15, 10, 8, 10, 4, 116, 128, 0, 0, 16, 10, 10, 8, 10, 4, 116, 192, 0, 0, 16, 16, 10, 8, 10, 4, 116, 193, 16, 0, 16, 20, 10, 8, 10, 4, 116, 193, 32, 0, 16, 19, 10, 8, 10, 4, 116, 193, 152, 0, 16, 22, 10, 8, 10, 4, 116, 193, 164, 0, 16, 22, 10, 8, 10, 4, 116, 193, 176, 0, 16, 21, 10, 8, 10, 4, 116, 194, 0, 0, 16, 15, 10, 8, 10, 4, 116, 196, 0, 0, 16, 16, 10, 8, 10, 4, 116, 197, 160, 0, 16, 22, 10, 8, 10, 4, 116, 197, 164, 0, 16, 22, 10, 8, 10, 4, 116, 198, 0, 0, 16, 16, 10, 8, 10, 4, 116, 199, 0, 0, 16, 17, 10, 8, 10, 4, 116, 199, 128, 0, 16, 19, 10, 8, 10, 4, 116, 204, 0, 0, 16, 17, 10, 8, 10, 4, 116, 205, 0, 0, 16, 16, 10, 8, 10, 4, 116, 206, 92, 0, 16, 22, 10, 8, 10, 4, 116, 206, 100, 0, 16, 22, 10, 8, 10, 4, 116, 206, 176, 0, 16, 22, 10, 8, 10, 4, 116, 207, 0, 0, 16, 16, 10, 8, 10, 4, 116, 208, 0, 0, 16, 14, 10, 8, 10, 4, 116, 212, 160, 0, 16, 20, 10, 8, 10, 4, 116, 213, 40, 0, 16, 22, 10, 8, 10, 4, 116, 213, 44, 0, 16, 22, 10, 8, 10, 4, 116, 213, 64, 0, 16, 18, 10, 8, 10, 4, 116, 213, 128, 0, 16, 17, 10, 8, 10, 4, 116, 214, 32, 0, 16, 19, 10, 8, 10, 4, 116, 214, 64, 0, 16, 20, 10, 8, 10, 4, 116, 214, 128, 0, 16, 17, 10, 8, 10, 4, 116, 215, 0, 0, 16, 16, 10, 8, 10, 4, 116, 216, 0, 0, 16, 14, 10, 8, 10, 4, 116, 224, 0, 0, 16, 12, 10, 8, 10, 4, 116, 242, 0, 0, 16, 15, 10, 8, 10, 4, 116, 244, 0, 0, 16, 15, 10, 8, 10, 4, 116, 246, 0, 0, 16, 15, 10, 8, 10, 4, 116, 248, 0, 0, 16, 15, 10, 8, 10, 4, 116, 251, 64, 0, 16, 18, 10, 8, 10, 4, 116, 252, 0, 0, 16, 15, 10, 8, 10, 4, 116, 254, 104, 0, 16, 22, 10, 8, 10, 4, 116, 254, 108, 0, 16, 22, 10, 8, 10, 4, 116, 254, 128, 0, 16, 17, 10, 8, 10, 4, 116, 255, 128, 0, 16, 17, 10, 8, 10, 4, 117, 8, 0, 0, 16, 13, 10, 8, 10, 4, 117, 21, 0, 0, 16, 16, 10, 8, 10, 4, 117, 22, 0, 0, 16, 15, 10, 8, 10, 4, 117, 24, 0, 0, 16, 13, 10, 8, 10, 4, 117, 32, 0, 0, 16, 13, 10, 8, 10, 4, 117, 40, 0, 0, 16, 14, 10, 8, 10, 4, 117, 44, 0, 0, 16, 15, 10, 8, 10, 4, 117, 48, 0, 0, 16, 14, 10, 8, 10, 4, 117, 53, 48, 0, 16, 20, 10, 8, 10, 4, 117, 53, 176, 0, 16, 20, 10, 8, 10, 4, 117, 57, 0, 0, 16, 16, 10, 8, 10, 4, 117, 58, 0, 0, 16, 17, 10, 8, 10, 4, 117, 59, 0, 0, 16, 16, 10, 8, 10, 4, 117, 60, 0, 0, 16, 14, 10, 8, 10, 4, 117, 64, 0, 0, 16, 13, 10, 8, 10, 4, 117, 72, 0, 0, 16, 15, 10, 8, 10, 4, 117, 74, 64, 0, 16, 20, 10, 8, 10, 4, 117, 74, 80, 0, 16, 20, 10, 8, 10, 4, 117, 74, 128, 0, 16, 17, 10, 8, 10, 4, 117, 75, 0, 0, 16, 16, 10, 8, 10, 4, 117, 76, 0, 0, 16, 14, 10, 8, 10, 4, 117, 80, 0, 0, 16, 12, 10, 8, 10, 4, 117, 100, 0, 0, 16, 15, 10, 8, 10, 4, 117, 103, 16, 0, 16, 20, 10, 8, 10, 4, 117, 103, 40, 0, 16, 21, 10, 8, 10, 4, 117, 103, 72, 0, 16, 21, 10, 8, 10, 4, 117, 103, 128, 0, 16, 20, 10, 8, 10, 4, 117, 104, 168, 0, 16, 21, 10, 8, 10, 4, 117, 106, 0, 0, 16, 15, 10, 8, 10, 4, 117, 112, 0, 0, 16, 13, 10, 8, 10, 4, 117, 120, 64, 0, 16, 18, 10, 8, 10, 4, 117, 120, 128, 0, 16, 17, 10, 8, 10, 4, 117, 121, 0, 0, 16, 17, 10, 8, 10, 4, 117, 121, 128, 0, 16, 18, 10, 8, 10, 4, 117, 121, 192, 0, 16, 21, 10, 8, 10, 4, 117, 122, 128, 0, 16, 17, 10, 8, 10, 4, 117, 124, 0, 0, 16, 14, 10, 8, 10, 4, 117, 128, 0, 0, 16, 10, 10, 8, 10, 4, 118, 24, 0, 0, 16, 15, 10, 8, 10, 4, 118, 26, 0, 0, 16, 16, 10, 8, 10, 4, 118, 28, 0, 0, 16, 15, 10, 8, 10, 4, 118, 30, 0, 0, 16, 16, 10, 8, 10, 4, 118, 31, 0, 0, 16, 16, 10, 8, 10, 4, 118, 64, 0, 0, 16, 15, 10, 8, 10, 4, 118, 66, 0, 0, 16, 16, 10, 8, 10, 4, 118, 67, 112, 0, 16, 20, 10, 8, 10, 4, 118, 72, 0, 0, 16, 13, 10, 8, 10, 4, 118, 80, 0, 0, 16, 15, 10, 8, 10, 4, 118, 84, 0, 0, 16, 15, 10, 8, 10, 4, 118, 88, 32, 0, 16, 19, 10, 8, 10, 4, 118, 88, 64, 0, 16, 18, 10, 8, 10, 4, 118, 88, 128, 0, 16, 17, 10, 8, 10, 4, 118, 89, 0, 0, 16, 16, 10, 8, 10, 4, 118, 91, 240, 0, 16, 20, 10, 8, 10, 4, 118, 102, 16, 0, 16, 20, 10, 8, 10, 4, 118, 102, 32, 0, 16, 21, 10, 8, 10, 4, 118, 103, 164, 0, 16, 22, 10, 8, 10, 4, 118, 103, 168, 0, 16, 22, 10, 8, 10, 4, 118, 103, 172, 0, 16, 22, 10, 8, 10, 4, 118, 103, 176, 0, 16, 22, 10, 8, 10, 4, 118, 107, 180, 0, 16, 22, 10, 8, 10, 4, 118, 112, 0, 0, 16, 13, 10, 8, 10, 4, 118, 120, 0, 0, 16, 14, 10, 8, 10, 4, 118, 124, 0, 0, 16, 15, 10, 8, 10, 4, 118, 126, 0, 0, 16, 16, 10, 8, 10, 4, 118, 127, 128, 0, 16, 19, 10, 8, 10, 4, 118, 132, 0, 0, 16, 14, 10, 8, 10, 4, 118, 144, 0, 0, 16, 14, 10, 8, 10, 4, 118, 178, 0, 0, 16, 16, 10, 8, 10, 4, 118, 180, 0, 0, 16, 14, 10, 8, 10, 4, 118, 184, 0, 0, 16, 17, 10, 8, 10, 4, 118, 184, 128, 0, 16, 17, 10, 8, 10, 4, 118, 186, 0, 0, 16, 15, 10, 8, 10, 4, 118, 188, 0, 0, 16, 16, 10, 8, 10, 4, 118, 190, 0, 0, 16, 16, 10, 8, 10, 4, 118, 191, 0, 0, 16, 16, 10, 8, 10, 4, 118, 192, 0, 0, 16, 16, 10, 8, 10, 4, 118, 193, 0, 0, 16, 20, 10, 8, 10, 4, 118, 193, 32, 0, 16, 19, 10, 8, 10, 4, 118, 193, 64, 0, 16, 20, 10, 8, 10, 4, 118, 193, 96, 0, 16, 19, 10, 8, 10, 4, 118, 193, 128, 0, 16, 17, 10, 8, 10, 4, 118, 194, 0, 0, 16, 17, 10, 8, 10, 4, 118, 194, 128, 0, 16, 17, 10, 8, 10, 4, 118, 195, 0, 0, 16, 17, 10, 8, 10, 4, 118, 195, 128, 0, 16, 17, 10, 8, 10, 4, 118, 196, 0, 0, 16, 14, 10, 8, 10, 4, 118, 202, 0, 0, 16, 15, 10, 8, 10, 4, 118, 204, 0, 0, 16, 14, 10, 8, 10, 4, 118, 212, 0, 0, 16, 16, 10, 8, 10, 4, 118, 213, 0, 0, 16, 16, 10, 8, 10, 4, 118, 215, 192, 0, 16, 18, 10, 8, 10, 4, 118, 224, 0, 0, 16, 14, 10, 8, 10, 4, 118, 228, 0, 0, 16, 15, 10, 8, 10, 4, 118, 230, 0, 0, 16, 16, 10, 8, 10, 4, 118, 239, 0, 0, 16, 16, 10, 8, 10, 4, 118, 242, 0, 0, 16, 16, 10, 8, 10, 4, 118, 244, 0, 0, 16, 14, 10, 8, 10, 4, 118, 248, 0, 0, 16, 13, 10, 8, 10, 4, 119, 0, 0, 0, 16, 15, 10, 8, 10, 4, 119, 2, 0, 0, 16, 19, 10, 8, 10, 4, 119, 2, 128, 0, 16, 17, 10, 8, 10, 4, 119, 3, 0, 0, 16, 16, 10, 8, 10, 4, 119, 4, 0, 0, 16, 14, 10, 8, 10, 4, 119, 8, 0, 0, 16, 16, 10, 8, 10, 4, 119, 10, 0, 0, 16, 17, 10, 8, 10, 4, 119, 15, 136, 0, 16, 21, 10, 8, 10, 4, 119, 16, 0, 0, 16, 16, 10, 8, 10, 4, 119, 18, 192, 0, 16, 20, 10, 8, 10, 4, 119, 18, 208, 0, 16, 21, 10, 8, 10, 4, 119, 18, 224, 0, 16, 20, 10, 8, 10, 4, 119, 18, 240, 0, 16, 20, 10, 8, 10, 4, 119, 19, 0, 0, 16, 16, 10, 8, 10, 4, 119, 20, 0, 0, 16, 14, 10, 8, 10, 4, 119, 27, 64, 0, 16, 18, 10, 8, 10, 4, 119, 27, 128, 0, 16, 19, 10, 8, 10, 4, 119, 27, 160, 0, 16, 19, 10, 8, 10, 4, 119, 27, 192, 0, 16, 18, 10, 8, 10, 4, 119, 28, 0, 0, 16, 15, 10, 8, 10, 4, 119, 30, 48, 0, 16, 20, 10, 8, 10, 4, 119, 31, 192, 0, 16, 19, 10, 8, 10, 4, 119, 32, 0, 0, 16, 14, 10, 8, 10, 4, 119, 36, 0, 0, 16, 16, 10, 8, 10, 4, 119, 37, 0, 0, 16, 17, 10, 8, 10, 4, 119, 37, 128, 0, 16, 18, 10, 8, 10, 4, 119, 37, 192, 0, 16, 18, 10, 8, 10, 4, 119, 38, 0, 0, 16, 17, 10, 8, 10, 4, 119, 38, 128, 0, 16, 18, 10, 8, 10, 4, 119, 38, 192, 0, 16, 20, 10, 8, 10, 4, 119, 38, 208, 0, 16, 20, 10, 8, 10, 4, 119, 38, 224, 0, 16, 19, 10, 8, 10, 4, 119, 39, 0, 0, 16, 16, 10, 8, 10, 4, 119, 40, 0, 0, 16, 18, 10, 8, 10, 4, 119, 40, 64, 0, 16, 20, 10, 8, 10, 4, 119, 40, 128, 0, 16, 17, 10, 8, 10, 4, 119, 41, 0, 0, 16, 16, 10, 8, 10, 4, 119, 42, 0, 0, 16, 19, 10, 8, 10, 4, 119, 42, 52, 0, 16, 22, 10, 8, 10, 4, 119, 42, 128, 0, 16, 21, 10, 8, 10, 4, 119, 42, 136, 0, 16, 21, 10, 8, 10, 4, 119, 42, 224, 0, 16, 19, 10, 8, 10, 4, 119, 44, 0, 0, 16, 15, 10, 8, 10, 4, 119, 48, 0, 0, 16, 13, 10, 8, 10, 4, 119, 57, 0, 0, 16, 16, 10, 8, 10, 4, 119, 58, 0, 0, 16, 16, 10, 8, 10, 4, 119, 59, 128, 0, 16, 17, 10, 8, 10, 4, 119, 60, 0, 0, 16, 16, 10, 8, 10, 4, 119, 61, 0, 0, 16, 16, 10, 8, 10, 4, 119, 62, 0, 0, 16, 16, 10, 8, 10, 4, 119, 63, 32, 0, 16, 19, 10, 8, 10, 4, 119, 75, 208, 0, 16, 20, 10, 8, 10, 4, 119, 78, 0, 0, 16, 15, 10, 8, 10, 4, 119, 80, 0, 0, 16, 16, 10, 8, 10, 4, 119, 82, 208, 0, 16, 20, 10, 8, 10, 4, 119, 84, 0, 0, 16, 14, 10, 8, 10, 4, 119, 88, 0, 0, 16, 14, 10, 8, 10, 4, 119, 96, 0, 0, 16, 13, 10, 8, 10, 4, 119, 108, 0, 0, 16, 15, 10, 8, 10, 4, 119, 112, 0, 0, 16, 13, 10, 8, 10, 4, 119, 120, 0, 0, 16, 13, 10, 8, 10, 4, 119, 128, 0, 0, 16, 12, 10, 8, 10, 4, 119, 144, 0, 0, 16, 14, 10, 8, 10, 4, 119, 148, 160, 0, 16, 20, 10, 8, 10, 4, 119, 148, 176, 0, 16, 20, 10, 8, 10, 4, 119, 151, 192, 0, 16, 18, 10, 8, 10, 4, 119, 160, 200, 0, 16, 21, 10, 8, 10, 4, 119, 161, 120, 0, 16, 22, 10, 8, 10, 4, 119, 161, 124, 0, 16, 22, 10, 8, 10, 4, 119, 161, 128, 0, 16, 17, 10, 8, 10, 4, 119, 162, 0, 0, 16, 15, 10, 8, 10, 4, 119, 164, 0, 0, 16, 14, 10, 8, 10, 4, 119, 176, 0, 0, 16, 12, 10, 8, 10, 4, 119, 232, 0, 0, 16, 15, 10, 8, 10, 4, 119, 235, 128, 0, 16, 18, 10, 8, 10, 4, 119, 248, 0, 0, 16, 14, 10, 8, 10, 4, 119, 252, 96, 0, 16, 21, 10, 8, 10, 4, 119, 252, 240, 0, 16, 20, 10, 8, 10, 4, 119, 253, 0, 0, 16, 16, 10, 8, 10, 4, 119, 254, 0, 0, 16, 15, 10, 8, 10, 4, 120, 0, 0, 0, 16, 12, 10, 8, 10, 4, 120, 24, 0, 0, 16, 14, 10, 8, 10, 4, 120, 30, 0, 0, 16, 16, 10, 8, 10, 4, 120, 31, 0, 0, 16, 16, 10, 8, 10, 4, 120, 32, 0, 0, 16, 13, 10, 8, 10, 4, 120, 40, 0, 0, 16, 14, 10, 8, 10, 4, 120, 44, 0, 0, 16, 14, 10, 8, 10, 4, 120, 48, 0, 0, 16, 15, 10, 8, 10, 4, 120, 52, 0, 0, 16, 16, 10, 8, 10, 4, 120, 53, 0, 0, 16, 16, 10, 8, 10, 4, 120, 54, 0, 0, 16, 15, 10, 8, 10, 4, 120, 64, 0, 0, 16, 14, 10, 8, 10, 4, 120, 68, 0, 0, 16, 14, 10, 8, 10, 4, 120, 72, 32, 0, 16, 19, 10, 8, 10, 4, 120, 72, 128, 0, 16, 17, 10, 8, 10, 4, 120, 76, 0, 0, 16, 14, 10, 8, 10, 4, 120, 80, 0, 0, 16, 13, 10, 8, 10, 4, 120, 88, 8, 0, 16, 21, 10, 8, 10, 4, 120, 90, 0, 0, 16, 15, 10, 8, 10, 4, 120, 92, 0, 0, 16, 16, 10, 8, 10, 4, 120, 94, 0, 0, 16, 16, 10, 8, 10, 4, 120, 95, 0, 0, 16, 16, 10, 8, 10, 4, 120, 128, 0, 0, 16, 14, 10, 8, 10, 4, 120, 132, 0, 0, 16, 17, 10, 8, 10, 4, 120, 132, 128, 0, 16, 17, 10, 8, 10, 4, 120, 133, 0, 0, 16, 16, 10, 8, 10, 4, 120, 134, 0, 0, 16, 15, 10, 8, 10, 4, 120, 136, 16, 0, 16, 22, 10, 8, 10, 4, 120, 136, 20, 0, 16, 22, 10, 8, 10, 4, 120, 136, 128, 0, 16, 18, 10, 8, 10, 4, 120, 137, 0, 0, 16, 17, 10, 8, 10, 4, 120, 143, 128, 0, 16, 19, 10, 8, 10, 4, 120, 192, 0, 0, 16, 10, 10, 8, 10, 4, 121, 0, 8, 0, 16, 21, 10, 8, 10, 4, 121, 0, 16, 0, 16, 20, 10, 8, 10, 4, 121, 4, 0, 0, 16, 15, 10, 8, 10, 4, 121, 8, 0, 0, 16, 13, 10, 8, 10, 4, 121, 16, 0, 0, 16, 13, 10, 8, 10, 4, 121, 24, 0, 0, 16, 14, 10, 8, 10, 4, 121, 28, 0, 0, 16, 15, 10, 8, 10, 4, 121, 30, 0, 0, 16, 16, 10, 8, 10, 4, 121, 31, 0, 0, 16, 16, 10, 8, 10, 4, 121, 32, 0, 0, 16, 14, 10, 8, 10, 4, 121, 36, 0, 0, 16, 16, 10, 8, 10, 4, 121, 37, 0, 0, 16, 16, 10, 8, 10, 4, 121, 38, 0, 0, 16, 15, 10, 8, 10, 4, 121, 40, 0, 0, 16, 14, 10, 8, 10, 4, 121, 46, 0, 0, 16, 18, 10, 8, 10, 4, 121, 46, 76, 0, 16, 22, 10, 8, 10, 4, 121, 46, 128, 0, 16, 17, 10, 8, 10, 4, 121, 47, 0, 0, 16, 16, 10, 8, 10, 4, 121, 48, 0, 0, 16, 15, 10, 8, 10, 4, 121, 50, 8, 0, 16, 21, 10, 8, 10, 4, 121, 51, 0, 0, 16, 16, 10, 8, 10, 4, 121, 52, 160, 0, 16, 19, 10, 8, 10, 4, 121, 52, 208, 0, 16, 20, 10, 8, 10, 4, 121, 52, 224, 0, 16, 19, 10, 8, 10, 4, 121, 54, 176, 0, 16, 21, 10, 8, 10, 4, 121, 54, 188, 0, 16, 22, 10, 8, 10, 4, 121, 55, 0, 0, 16, 18, 10, 8, 10, 4, 121, 56, 0, 0, 16, 15, 10, 8, 10, 4, 121, 58, 0, 0, 16, 17, 10, 8, 10, 4, 121, 58, 136, 0, 16, 21, 10, 8, 10, 4, 121, 58, 144, 0, 16, 20, 10, 8, 10, 4, 121, 58, 160, 0, 16, 21, 10, 8, 10, 4, 121, 59, 0, 0, 16, 16, 10, 8, 10, 4, 121, 60, 0, 0, 16, 14, 10, 8, 10, 4, 121, 68, 0, 0, 16, 14, 10, 8, 10, 4, 121, 76, 0, 0, 16, 15, 10, 8, 10, 4, 121, 79, 128, 0, 16, 18, 10, 8, 10, 4, 121, 89, 0, 0, 16, 16, 10, 8, 10, 4, 121, 100, 128, 0, 16, 17, 10, 8, 10, 4, 121, 101, 0, 0, 16, 18, 10, 8, 10, 4, 121, 101, 208, 0, 16, 20, 10, 8, 10, 4, 121, 192, 0, 0, 16, 16, 10, 8, 10, 4, 121, 193, 0, 0, 16, 16, 10, 8, 10, 4, 121, 194, 0, 0, 16, 15, 10, 8, 10, 4, 121, 196, 0, 0, 16, 14, 10, 8, 10, 4, 121, 200, 192, 0, 16, 21, 10, 8, 10, 4, 121, 201, 0, 0, 16, 16, 10, 8, 10, 4, 121, 204, 0, 0, 16, 14, 10, 8, 10, 4, 121, 224, 0, 0, 16, 12, 10, 8, 10, 4, 121, 248, 0, 0, 16, 14, 10, 8, 10, 4, 121, 255, 0, 0, 16, 16, 10, 8, 10, 4, 122, 0, 64, 0, 16, 18, 10, 8, 10, 4, 122, 0, 128, 0, 16, 17, 10, 8, 10, 4, 122, 4, 0, 0, 16, 14, 10, 8, 10, 4, 122, 8, 0, 0, 16, 16, 10, 8, 10, 4, 122, 9, 0, 0, 16, 16, 10, 8, 10, 4, 122, 10, 0, 0, 16, 17, 10, 8, 10, 4, 122, 10, 128, 0, 16, 22, 10, 8, 10, 4, 122, 10, 132, 0, 16, 23, 10, 8, 10, 4, 122, 10, 134, 0, 16, 23, 10, 8, 10, 4, 122, 10, 136, 0, 16, 23, 10, 8, 10, 4, 122, 10, 138, 0, 16, 23, 10, 8, 10, 4, 122, 10, 140, 0, 16, 22, 10, 8, 10, 4, 122, 10, 144, 0, 16, 20, 10, 8, 10, 4, 122, 10, 160, 0, 16, 19, 10, 8, 10, 4, 122, 10, 192, 0, 16, 18, 10, 8, 10, 4, 122, 11, 0, 0, 16, 17, 10, 8, 10, 4, 122, 12, 0, 0, 16, 16, 10, 8, 10, 4, 122, 13, 0, 0, 16, 16, 10, 8, 10, 4, 122, 14, 0, 0, 16, 17, 10, 8, 10, 4, 122, 14, 128, 0, 16, 18, 10, 8, 10, 4, 122, 14, 192, 0, 16, 18, 10, 8, 10, 4, 122, 48, 0, 0, 16, 16, 10, 8, 10, 4, 122, 49, 0, 0, 16, 18, 10, 8, 10, 4, 122, 51, 0, 0, 16, 16, 10, 8, 10, 4, 122, 64, 0, 0, 16, 11, 10, 8, 10, 4, 122, 96, 0, 0, 16, 15, 10, 8, 10, 4, 122, 102, 0, 0, 16, 20, 10, 8, 10, 4, 122, 102, 64, 0, 16, 20, 10, 8, 10, 4, 122, 102, 80, 0, 16, 20, 10, 8, 10, 4, 122, 112, 0, 0, 16, 14, 10, 8, 10, 4, 122, 119, 0, 0, 16, 16, 10, 8, 10, 4, 122, 128, 100, 0, 16, 22, 10, 8, 10, 4, 122, 128, 120, 0, 16, 21, 10, 8, 10, 4, 122, 136, 0, 0, 16, 13, 10, 8, 10, 4, 122, 144, 128, 0, 16, 17, 10, 8, 10, 4, 122, 152, 192, 0, 16, 18, 10, 8, 10, 4, 122, 156, 0, 0, 16, 14, 10, 8, 10, 4, 122, 188, 0, 0, 16, 14, 10, 8, 10, 4, 122, 192, 0, 0, 16, 14, 10, 8, 10, 4, 122, 198, 0, 0, 16, 16, 10, 8, 10, 4, 122, 200, 40, 0, 16, 22, 10, 8, 10, 4, 122, 200, 44, 0, 16, 22, 10, 8, 10, 4, 122, 200, 64, 0, 16, 18, 10, 8, 10, 4, 122, 201, 48, 0, 16, 20, 10, 8, 10, 4, 122, 204, 0, 0, 16, 14, 10, 8, 10, 4, 122, 224, 0, 0, 16, 12, 10, 8, 10, 4, 122, 240, 0, 0, 16, 13, 10, 8, 10, 4, 122, 248, 24, 0, 16, 21, 10, 8, 10, 4, 122, 248, 48, 0, 16, 20, 10, 8, 10, 4, 122, 255, 64, 0, 16, 21, 10, 8, 10, 4, 123, 0, 128, 0, 16, 18, 10, 8, 10, 4, 123, 4, 0, 0, 16, 14, 10, 8, 10, 4, 123, 8, 0, 0, 16, 13, 10, 8, 10, 4, 123, 49, 128, 0, 16, 17, 10, 8, 10, 4, 123, 50, 160, 0, 16, 19, 10, 8, 10, 4, 123, 52, 0, 0, 16, 14, 10, 8, 10, 4, 123, 56, 0, 0, 16, 15, 10, 8, 10, 4, 123, 58, 0, 0, 16, 20, 10, 8, 10, 4, 123, 58, 16, 0, 16, 20, 10, 8, 10, 4, 123, 58, 32, 0, 16, 19, 10, 8, 10, 4, 123, 58, 64, 0, 16, 19, 10, 8, 10, 4, 123, 58, 96, 0, 16, 19, 10, 8, 10, 4, 123, 58, 128, 0, 16, 18, 10, 8, 10, 4, 123, 58, 192, 0, 16, 19, 10, 8, 10, 4, 123, 58, 224, 0, 16, 20, 10, 8, 10, 4, 123, 58, 240, 0, 16, 20, 10, 8, 10, 4, 123, 59, 0, 0, 16, 16, 10, 8, 10, 4, 123, 60, 0, 0, 16, 16, 10, 8, 10, 4, 123, 61, 0, 0, 16, 16, 10, 8, 10, 4, 123, 62, 0, 0, 16, 16, 10, 8, 10, 4, 123, 64, 0, 0, 16, 11, 10, 8, 10, 4, 123, 96, 0, 0, 16, 15, 10, 8, 10, 4, 123, 98, 0, 0, 16, 17, 10, 8, 10, 4, 123, 99, 128, 0, 16, 17, 10, 8, 10, 4, 123, 100, 0, 0, 16, 19, 10, 8, 10, 4, 123, 101, 0, 0, 16, 16, 10, 8, 10, 4, 123, 103, 0, 0, 16, 17, 10, 8, 10, 4, 123, 108, 128, 0, 16, 20, 10, 8, 10, 4, 123, 108, 208, 0, 16, 20, 10, 8, 10, 4, 123, 112, 0, 0, 16, 12, 10, 8, 10, 4, 123, 128, 0, 0, 16, 13, 10, 8, 10, 4, 123, 136, 80, 0, 16, 20, 10, 8, 10, 4, 123, 137, 0, 0, 16, 16, 10, 8, 10, 4, 123, 138, 0, 0, 16, 15, 10, 8, 10, 4, 123, 144, 0, 0, 16, 14, 10, 8, 10, 4, 123, 148, 0, 0, 16, 16, 10, 8, 10, 4, 123, 149, 0, 0, 16, 16, 10, 8, 10, 4, 123, 150, 0, 0, 16, 15, 10, 8, 10, 4, 123, 152, 0, 0, 16, 13, 10, 8, 10, 4, 123, 160, 0, 0, 16, 14, 10, 8, 10, 4, 123, 164, 0, 0, 16, 14, 10, 8, 10, 4, 123, 168, 0, 0, 16, 14, 10, 8, 10, 4, 123, 172, 0, 0, 16, 15, 10, 8, 10, 4, 123, 174, 0, 0, 16, 15, 10, 8, 10, 4, 123, 176, 60, 0, 16, 22, 10, 8, 10, 4, 123, 176, 80, 0, 16, 20, 10, 8, 10, 4, 123, 177, 0, 0, 16, 16, 10, 8, 10, 4, 123, 178, 0, 0, 16, 15, 10, 8, 10, 4, 123, 180, 0, 0, 16, 14, 10, 8, 10, 4, 123, 184, 0, 0, 16, 14, 10, 8, 10, 4, 123, 188, 0, 0, 16, 14, 10, 8, 10, 4, 123, 196, 0, 0, 16, 15, 10, 8, 10, 4, 123, 199, 128, 0, 16, 17, 10, 8, 10, 4, 123, 206, 0, 0, 16, 15, 10, 8, 10, 4, 123, 232, 0, 0, 16, 14, 10, 8, 10, 4, 123, 242, 0, 0, 16, 17, 10, 8, 10, 4, 123, 242, 192, 0, 16, 22, 10, 8, 10, 4, 123, 242, 196, 0, 16, 22, 10, 8, 10, 4, 123, 244, 0, 0, 16, 14, 10, 8, 10, 4, 123, 249, 0, 0, 16, 16, 10, 8, 10, 4, 123, 254, 96, 0, 16, 22, 10, 8, 10, 4, 123, 254, 100, 0, 16, 22, 10, 8, 10, 4, 124, 6, 64, 0, 16, 18, 10, 8, 10, 4, 124, 14, 0, 0, 16, 15, 10, 8, 10, 4, 124, 16, 0, 0, 16, 15, 10, 8, 10, 4, 124, 20, 0, 0, 16, 16, 10, 8, 10, 4, 124, 21, 0, 0, 16, 20, 10, 8, 10, 4, 124, 21, 16, 0, 16, 20, 10, 8, 10, 4, 124, 21, 32, 0, 16, 19, 10, 8, 10, 4, 124, 21, 64, 0, 16, 18, 10, 8, 10, 4, 124, 21, 128, 0, 16, 17, 10, 8, 10, 4, 124, 22, 0, 0, 16, 15, 10, 8, 10, 4, 124, 28, 192, 0, 16, 18, 10, 8, 10, 4, 124, 29, 0, 0, 16, 17, 10, 8, 10, 4, 124, 31, 0, 0, 16, 16, 10, 8, 10, 4, 124, 40, 112, 0, 16, 20, 10, 8, 10, 4, 124, 40, 128, 0, 16, 18, 10, 8, 10, 4, 124, 40, 192, 0, 16, 19, 10, 8, 10, 4, 124, 40, 240, 0, 16, 22, 10, 8, 10, 4, 124, 42, 0, 0, 16, 17, 10, 8, 10, 4, 124, 42, 128, 0, 16, 17, 10, 8, 10, 4, 124, 47, 0, 0, 16, 18, 10, 8, 10, 4, 124, 64, 0, 0, 16, 15, 10, 8, 10, 4, 124, 66, 0, 0, 16, 17, 10, 8, 10, 4, 124, 67, 0, 0, 16, 16, 10, 8, 10, 4, 124, 68, 0, 0, 16, 14, 10, 8, 10, 4, 124, 72, 0, 0, 16, 16, 10, 8, 10, 4, 124, 73, 0, 0, 16, 16, 10, 8, 10, 4, 124, 74, 0, 0, 16, 15, 10, 8, 10, 4, 124, 76, 0, 0, 16, 14, 10, 8, 10, 4, 124, 88, 0, 0, 16, 16, 10, 8, 10, 4, 124, 89, 0, 0, 16, 17, 10, 8, 10, 4, 124, 89, 128, 0, 16, 17, 10, 8, 10, 4, 124, 90, 0, 0, 16, 15, 10, 8, 10, 4, 124, 92, 0, 0, 16, 14, 10, 8, 10, 4, 124, 108, 8, 0, 16, 21, 10, 8, 10, 4, 124, 108, 40, 0, 16, 21, 10, 8, 10, 4, 124, 109, 96, 0, 16, 21, 10, 8, 10, 4, 124, 112, 0, 0, 16, 15, 10, 8, 10, 4, 124, 114, 0, 0, 16, 15, 10, 8, 10, 4, 124, 116, 0, 0, 16, 16, 10, 8, 10, 4, 124, 117, 0, 0, 16, 16, 10, 8, 10, 4, 124, 118, 0, 0, 16, 15, 10, 8, 10, 4, 124, 126, 0, 0, 16, 15, 10, 8, 10, 4, 124, 128, 0, 0, 16, 13, 10, 8, 10, 4, 124, 147, 128, 0, 16, 17, 10, 8, 10, 4, 124, 150, 137, 0, 16, 24, 10, 8, 10, 4, 124, 151, 0, 0, 16, 16, 10, 8, 10, 4, 124, 152, 0, 0, 16, 16, 10, 8, 10, 4, 124, 156, 0, 0, 16, 16, 10, 8, 10, 4, 124, 160, 0, 0, 16, 16, 10, 8, 10, 4, 124, 161, 0, 0, 16, 16, 10, 8, 10, 4, 124, 162, 0, 0, 16, 16, 10, 8, 10, 4, 124, 163, 0, 0, 16, 16, 10, 8, 10, 4, 124, 164, 0, 0, 16, 14, 10, 8, 10, 4, 124, 172, 0, 0, 16, 15, 10, 8, 10, 4, 124, 174, 0, 0, 16, 15, 10, 8, 10, 4, 124, 192, 0, 0, 16, 15, 10, 8, 10, 4, 124, 196, 0, 0, 16, 16, 10, 8, 10, 4, 124, 200, 0, 0, 16, 13, 10, 8, 10, 4, 124, 220, 0, 0, 16, 14, 10, 8, 10, 4, 124, 224, 0, 0, 16, 16, 10, 8, 10, 4, 124, 225, 0, 0, 16, 16, 10, 8, 10, 4, 124, 226, 0, 0, 16, 15, 10, 8, 10, 4, 124, 228, 0, 0, 16, 14, 10, 8, 10, 4, 124, 232, 0, 0, 16, 15, 10, 8, 10, 4, 124, 234, 0, 0, 16, 15, 10, 8, 10, 4, 124, 236, 0, 0, 16, 14, 10, 8, 10, 4, 124, 240, 0, 0, 16, 17, 10, 8, 10, 4, 124, 240, 128, 0, 16, 18, 10, 8, 10, 4, 124, 242, 0, 0, 16, 16, 10, 8, 10, 4, 124, 243, 192, 0, 16, 18, 10, 8, 10, 4, 124, 248, 0, 0, 16, 17, 10, 8, 10, 4, 124, 249, 0, 0, 16, 16, 10, 8, 10, 4, 124, 250, 0, 0, 16, 15, 10, 8, 10, 4, 124, 254, 0, 0, 16, 18, 10, 8, 10, 4, 125, 31, 192, 0, 16, 18, 10, 8, 10, 4, 125, 32, 0, 0, 16, 16, 10, 8, 10, 4, 125, 33, 0, 0, 16, 16, 10, 8, 10, 4, 125, 34, 0, 0, 16, 16, 10, 8, 10, 4, 125, 35, 0, 0, 16, 17, 10, 8, 10, 4, 125, 35, 128, 0, 16, 17, 10, 8, 10, 4, 125, 36, 0, 0, 16, 14, 10, 8, 10, 4, 125, 40, 0, 0, 16, 13, 10, 8, 10, 4, 125, 58, 128, 0, 16, 17, 10, 8, 10, 4, 125, 61, 128, 0, 16, 17, 10, 8, 10, 4, 125, 62, 0, 0, 16, 18, 10, 8, 10, 4, 125, 64, 0, 0, 16, 13, 10, 8, 10, 4, 125, 72, 0, 0, 16, 16, 10, 8, 10, 4, 125, 73, 0, 0, 16, 16, 10, 8, 10, 4, 125, 74, 0, 0, 16, 15, 10, 8, 10, 4, 125, 76, 0, 0, 16, 17, 10, 8, 10, 4, 125, 76, 128, 0, 16, 17, 10, 8, 10, 4, 125, 77, 0, 0, 16, 16, 10, 8, 10, 4, 125, 78, 0, 0, 16, 15, 10, 8, 10, 4, 125, 80, 0, 0, 16, 13, 10, 8, 10, 4, 125, 88, 0, 0, 16, 13, 10, 8, 10, 4, 125, 96, 0, 0, 16, 15, 10, 8, 10, 4, 125, 98, 0, 0, 16, 16, 10, 8, 10, 4, 125, 104, 0, 0, 16, 13, 10, 8, 10, 4, 125, 112, 0, 0, 16, 12, 10, 8, 10, 4, 125, 169, 0, 0, 16, 16, 10, 8, 10, 4, 125, 171, 0, 0, 16, 16, 10, 8, 10, 4, 125, 208, 0, 0, 16, 18, 10, 8, 10, 4, 125, 210, 0, 0, 16, 16, 10, 8, 10, 4, 125, 211, 0, 0, 16, 16, 10, 8, 10, 4, 125, 213, 0, 0, 16, 17, 10, 8, 10, 4, 125, 214, 96, 0, 16, 19, 10, 8, 10, 4, 125, 215, 0, 0, 16, 18, 10, 8, 10, 4, 125, 216, 0, 0, 16, 15, 10, 8, 10, 4, 125, 218, 0, 0, 16, 16, 10, 8, 10, 4, 125, 219, 0, 0, 16, 16, 10, 8, 10, 4, 125, 220, 0, 0, 16, 15, 10, 8, 10, 4, 125, 222, 0, 0, 16, 15, 10, 8, 10, 4, 125, 254, 128, 0, 16, 18, 10, 8, 10, 4, 125, 254, 192, 0, 16, 18, 10, 8, 10, 4, 129, 28, 0, 0, 16, 16, 10, 8, 10, 4, 137, 59, 59, 0, 16, 24, 10, 8, 10, 4, 137, 59, 88, 0, 16, 22, 10, 8, 10, 4, 139, 5, 56, 0, 16, 22, 10, 8, 10, 4, 139, 5, 60, 0, 16, 22, 10, 8, 10, 4, 139, 5, 80, 0, 16, 22, 10, 8, 10, 4, 139, 5, 92, 0, 16, 22, 10, 8, 10, 4, 139, 5, 108, 0, 16, 22, 10, 8, 10, 4, 139, 5, 128, 0, 16, 22, 10, 8, 10, 4, 139, 5, 160, 0, 16, 22, 10, 8, 10, 4, 139, 5, 192, 0, 16, 22, 10, 8, 10, 4, 139, 5, 204, 0, 16, 22, 10, 8, 10, 4, 139, 5, 208, 0, 16, 22, 10, 8, 10, 4, 139, 5, 212, 0, 16, 22, 10, 8, 10, 4, 139, 5, 244, 0, 16, 22, 10, 8, 10, 4, 139, 9, 0, 0, 16, 16, 10, 8, 10, 4, 139, 129, 0, 0, 16, 16, 10, 8, 10, 4, 139, 148, 0, 0, 16, 16, 10, 8, 10, 4, 139, 155, 0, 0, 16, 16, 10, 8, 10, 4, 139, 159, 0, 0, 16, 16, 10, 8, 10, 4, 139, 170, 0, 0, 16, 16, 10, 8, 10, 4, 139, 176, 0, 0, 16, 16, 10, 8, 10, 4, 139, 183, 0, 0, 16, 16, 10, 8, 10, 4, 139, 186, 0, 0, 16, 16, 10, 8, 10, 4, 139, 189, 0, 0, 16, 16, 10, 8, 10, 4, 139, 196, 0, 0, 16, 14, 10, 8, 10, 4, 139, 200, 0, 0, 16, 13, 10, 8, 10, 4, 139, 208, 0, 0, 16, 13, 10, 8, 10, 4, 139, 217, 0, 0, 16, 16, 10, 8, 10, 4, 139, 219, 0, 0, 16, 16, 10, 8, 10, 4, 139, 220, 0, 0, 16, 15, 10, 8, 10, 4, 139, 224, 0, 0, 16, 16, 10, 8, 10, 4, 139, 226, 0, 0, 16, 15, 10, 8, 10, 4, 140, 75, 0, 0, 16, 16, 10, 8, 10, 4, 140, 143, 0, 0, 16, 16, 10, 8, 10, 4, 140, 205, 0, 0, 16, 16, 10, 8, 10, 4, 140, 206, 0, 0, 16, 15, 10, 8, 10, 4, 140, 210, 0, 0, 16, 16, 10, 8, 10, 4, 140, 224, 0, 0, 16, 16, 10, 8, 10, 4, 140, 237, 0, 0, 16, 16, 10, 8, 10, 4, 140, 240, 0, 0, 16, 16, 10, 8, 10, 4, 140, 243, 0, 0, 16, 16, 10, 8, 10, 4, 140, 246, 0, 0, 16, 16, 10, 8, 10, 4, 140, 249, 0, 0, 16, 16, 10, 8, 10, 4, 140, 250, 0, 0, 16, 16, 10, 8, 10, 4, 140, 255, 0, 0, 16, 16, 10, 8, 10, 4, 144, 0, 0, 0, 16, 16, 10, 8, 10, 4, 144, 7, 0, 0, 16, 16, 10, 8, 10, 4, 144, 12, 0, 0, 16, 16, 10, 8, 10, 4, 144, 48, 8, 0, 16, 22, 10, 8, 10, 4, 144, 48, 12, 0, 16, 22, 10, 8, 10, 4, 144, 48, 56, 0, 16, 22, 10, 8, 10, 4, 144, 48, 64, 0, 16, 22, 10, 8, 10, 4, 144, 48, 88, 0, 16, 22, 10, 8, 10, 4, 144, 48, 156, 0, 16, 22, 10, 8, 10, 4, 144, 48, 172, 0, 16, 22, 10, 8, 10, 4, 144, 48, 180, 0, 16, 22, 10, 8, 10, 4, 144, 48, 184, 0, 16, 22, 10, 8, 10, 4, 144, 48, 204, 0, 16, 22, 10, 8, 10, 4, 144, 48, 208, 0, 16, 22, 10, 8, 10, 4, 144, 48, 212, 0, 16, 22, 10, 8, 10, 4, 144, 48, 220, 0, 16, 22, 10, 8, 10, 4, 144, 48, 252, 0, 16, 22, 10, 8, 10, 4, 144, 52, 0, 0, 16, 16, 10, 8, 10, 4, 144, 123, 0, 0, 16, 16, 10, 8, 10, 4, 144, 255, 0, 0, 16, 16, 10, 8, 10, 4, 146, 196, 56, 0, 16, 22, 10, 8, 10, 4, 146, 196, 68, 0, 16, 22, 10, 8, 10, 4, 146, 196, 72, 0, 16, 22, 10, 8, 10, 4, 146, 196, 76, 0, 16, 22, 10, 8, 10, 4, 146, 196, 92, 0, 16, 22, 10, 8, 10, 4, 146, 196, 112, 0, 16, 22, 10, 8, 10, 4, 146, 196, 116, 0, 16, 22, 10, 8, 10, 4, 146, 196, 124, 0, 16, 22, 10, 8, 10, 4, 150, 0, 0, 0, 16, 16, 10, 8, 10, 4, 150, 115, 0, 0, 16, 16, 10, 8, 10, 4, 150, 121, 0, 0, 16, 16, 10, 8, 10, 4, 150, 122, 0, 0, 16, 16, 10, 8, 10, 4, 150, 129, 136, 0, 16, 22, 10, 8, 10, 4, 150, 129, 152, 0, 16, 22, 10, 8, 10, 4, 150, 129, 192, 0, 16, 22, 10, 8, 10, 4, 150, 129, 216, 0, 16, 22, 10, 8, 10, 4, 150, 129, 252, 0, 16, 22, 10, 8, 10, 4, 150, 138, 0, 0, 16, 15, 10, 8, 10, 4, 150, 223, 0, 0, 16, 16, 10, 8, 10, 4, 150, 242, 0, 0, 16, 22, 10, 8, 10, 4, 150, 242, 4, 0, 16, 22, 10, 8, 10, 4, 150, 242, 8, 0, 16, 22, 10, 8, 10, 4, 150, 242, 28, 0, 16, 22, 10, 8, 10, 4, 150, 242, 44, 0, 16, 22, 10, 8, 10, 4, 150, 242, 48, 0, 16, 22, 10, 8, 10, 4, 150, 242, 52, 0, 16, 22, 10, 8, 10, 4, 150, 242, 56, 0, 16, 22, 10, 8, 10, 4, 150, 242, 76, 0, 16, 22, 10, 8, 10, 4, 150, 242, 80, 0, 16, 22, 10, 8, 10, 4, 150, 242, 92, 0, 16, 22, 10, 8, 10, 4, 150, 242, 96, 0, 16, 22, 10, 8, 10, 4, 150, 242, 112, 0, 16, 22, 10, 8, 10, 4, 150, 242, 116, 0, 16, 22, 10, 8, 10, 4, 150, 242, 120, 0, 16, 22, 10, 8, 10, 4, 150, 242, 152, 0, 16, 22, 10, 8, 10, 4, 150, 242, 156, 0, 16, 22, 10, 8, 10, 4, 150, 242, 160, 0, 16, 22, 10, 8, 10, 4, 150, 242, 164, 0, 16, 22, 10, 8, 10, 4, 150, 242, 168, 0, 16, 22, 10, 8, 10, 4, 150, 242, 184, 0, 16, 22, 10, 8, 10, 4, 150, 242, 188, 0, 16, 22, 10, 8, 10, 4, 150, 242, 192, 0, 16, 22, 10, 8, 10, 4, 150, 242, 212, 0, 16, 22, 10, 8, 10, 4, 150, 242, 224, 0, 16, 22, 10, 8, 10, 4, 150, 242, 228, 0, 16, 22, 10, 8, 10, 4, 150, 242, 232, 0, 16, 22, 10, 8, 10, 4, 150, 242, 236, 0, 16, 22, 10, 8, 10, 4, 150, 242, 240, 0, 16, 22, 10, 8, 10, 4, 150, 242, 244, 0, 16, 22, 10, 8, 10, 4, 150, 242, 248, 0, 16, 22, 10, 8, 10, 4, 150, 255, 0, 0, 16, 16, 10, 8, 10, 4, 152, 104, 128, 0, 16, 17, 10, 8, 10, 4, 153, 0, 0, 0, 16, 16, 10, 8, 10, 4, 153, 3, 0, 0, 16, 16, 10, 8, 10, 4, 153, 34, 0, 0, 16, 15, 10, 8, 10, 4, 153, 36, 0, 0, 16, 15, 10, 8, 10, 4, 153, 99, 0, 0, 16, 16, 10, 8, 10, 4, 153, 101, 0, 0, 16, 16, 10, 8, 10, 4, 153, 118, 0, 0, 16, 15, 10, 8, 10, 4, 154, 8, 128, 0, 16, 17, 10, 8, 10, 4, 157, 0, 0, 0, 16, 16, 10, 8, 10, 4, 157, 18, 0, 0, 16, 16, 10, 8, 10, 4, 157, 61, 0, 0, 16, 16, 10, 8, 10, 4, 157, 119, 0, 0, 16, 22, 10, 8, 10, 4, 157, 119, 8, 0, 16, 22, 10, 8, 10, 4, 157, 119, 12, 0, 16, 22, 10, 8, 10, 4, 157, 119, 16, 0, 16, 22, 10, 8, 10, 4, 157, 119, 28, 0, 16, 22, 10, 8, 10, 4, 157, 119, 68, 0, 16, 22, 10, 8, 10, 4, 157, 119, 112, 0, 16, 22, 10, 8, 10, 4, 157, 119, 132, 0, 16, 22, 10, 8, 10, 4, 157, 119, 136, 0, 16, 22, 10, 8, 10, 4, 157, 119, 140, 0, 16, 22, 10, 8, 10, 4, 157, 119, 144, 0, 16, 22, 10, 8, 10, 4, 157, 119, 148, 0, 16, 22, 10, 8, 10, 4, 157, 119, 152, 0, 16, 22, 10, 8, 10, 4, 157, 119, 156, 0, 16, 22, 10, 8, 10, 4, 157, 119, 160, 0, 16, 22, 10, 8, 10, 4, 157, 119, 164, 0, 16, 22, 10, 8, 10, 4, 157, 119, 172, 0, 16, 22, 10, 8, 10, 4, 157, 119, 192, 0, 16, 22, 10, 8, 10, 4, 157, 119, 196, 0, 16, 22, 10, 8, 10, 4, 157, 119, 240, 0, 16, 22, 10, 8, 10, 4, 157, 119, 252, 0, 16, 22, 10, 8, 10, 4, 157, 122, 0, 0, 16, 16, 10, 8, 10, 4, 157, 148, 0, 0, 16, 16, 10, 8, 10, 4, 157, 156, 0, 0, 16, 16, 10, 8, 10, 4, 157, 255, 0, 0, 16, 16, 10, 8, 10, 4, 159, 226, 0, 0, 16, 16, 10, 8, 10, 4, 160, 19, 48, 0, 16, 22, 10, 8, 10, 4, 160, 19, 208, 0, 16, 22, 10, 8, 10, 4, 160, 19, 212, 0, 16, 22, 10, 8, 10, 4, 160, 19, 216, 0, 16, 22, 10, 8, 10, 4, 160, 20, 48, 0, 16, 22, 10, 8, 10, 4, 160, 202, 60, 0, 16, 22, 10, 8, 10, 4, 160, 202, 148, 0, 16, 22, 10, 8, 10, 4, 160, 202, 152, 0, 16, 22, 10, 8, 10, 4, 160, 202, 168, 0, 16, 22, 10, 8, 10, 4, 160, 202, 212, 0, 16, 22, 10, 8, 10, 4, 160, 202, 216, 0, 16, 22, 10, 8, 10, 4, 160, 202, 220, 0, 16, 22, 10, 8, 10, 4, 160, 202, 224, 0, 16, 22, 10, 8, 10, 4, 160, 202, 228, 0, 16, 22, 10, 8, 10, 4, 160, 202, 232, 0, 16, 22, 10, 8, 10, 4, 160, 202, 236, 0, 16, 22, 10, 8, 10, 4, 160, 202, 240, 0, 16, 22, 10, 8, 10, 4, 160, 202, 244, 0, 16, 22, 10, 8, 10, 4, 160, 202, 248, 0, 16, 22, 10, 8, 10, 4, 160, 202, 252, 0, 16, 22, 10, 8, 10, 4, 160, 238, 64, 0, 16, 22, 10, 8, 10, 4, 161, 207, 0, 0, 16, 16, 10, 8, 10, 4, 162, 105, 0, 0, 16, 16, 10, 8, 10, 4, 163, 0, 0, 0, 16, 16, 10, 8, 10, 4, 163, 47, 4, 0, 16, 22, 10, 8, 10, 4, 163, 53, 0, 0, 16, 22, 10, 8, 10, 4, 163, 53, 4, 0, 16, 22, 10, 8, 10, 4, 163, 53, 8, 0, 16, 22, 10, 8, 10, 4, 163, 53, 12, 0, 16, 22, 10, 8, 10, 4, 163, 53, 36, 0, 16, 22, 10, 8, 10, 4, 163, 53, 40, 0, 16, 22, 10, 8, 10, 4, 163, 53, 44, 0, 16, 22, 10, 8, 10, 4, 163, 53, 48, 0, 16, 22, 10, 8, 10, 4, 163, 53, 52, 0, 16, 22, 10, 8, 10, 4, 163, 53, 56, 0, 16, 22, 10, 8, 10, 4, 163, 53, 60, 0, 16, 22, 10, 8, 10, 4, 163, 53, 64, 0, 16, 22, 10, 8, 10, 4, 163, 53, 88, 0, 16, 22, 10, 8, 10, 4, 163, 53, 92, 0, 16, 22, 10, 8, 10, 4, 163, 53, 96, 0, 16, 22, 10, 8, 10, 4, 163, 53, 100, 0, 16, 22, 10, 8, 10, 4, 163, 53, 104, 0, 16, 22, 10, 8, 10, 4, 163, 53, 108, 0, 16, 22, 10, 8, 10, 4, 163, 53, 112, 0, 16, 22, 10, 8, 10, 4, 163, 53, 116, 0, 16, 22, 10, 8, 10, 4, 163, 53, 120, 0, 16, 22, 10, 8, 10, 4, 163, 53, 124, 0, 16, 22, 10, 8, 10, 4, 163, 53, 128, 0, 16, 22, 10, 8, 10, 4, 163, 53, 132, 0, 16, 22, 10, 8, 10, 4, 163, 53, 136, 0, 16, 22, 10, 8, 10, 4, 163, 53, 160, 0, 16, 22, 10, 8, 10, 4, 163, 53, 164, 0, 16, 22, 10, 8, 10, 4, 163, 53, 168, 0, 16, 22, 10, 8, 10, 4, 163, 53, 172, 0, 16, 22, 10, 8, 10, 4, 163, 53, 188, 0, 16, 22, 10, 8, 10, 4, 163, 53, 220, 0, 16, 22, 10, 8, 10, 4, 163, 53, 236, 0, 16, 22, 10, 8, 10, 4, 163, 53, 240, 0, 16, 22, 10, 8, 10, 4, 163, 125, 0, 0, 16, 16, 10, 8, 10, 4, 163, 142, 0, 0, 16, 16, 10, 8, 10, 4, 163, 177, 0, 0, 16, 16, 10, 8, 10, 4, 163, 179, 0, 0, 16, 16, 10, 8, 10, 4, 163, 204, 0, 0, 16, 16, 10, 8, 10, 4, 164, 52, 0, 0, 16, 17, 10, 8, 10, 4, 166, 111, 0, 0, 16, 16, 10, 8, 10, 4, 167, 139, 0, 0, 16, 16, 10, 8, 10, 4, 167, 189, 0, 0, 16, 16, 10, 8, 10, 4, 167, 220, 244, 0, 16, 22, 10, 8, 10, 4, 168, 160, 0, 0, 16, 16, 10, 8, 10, 4, 170, 179, 0, 0, 16, 16, 10, 8, 10, 4, 171, 8, 0, 0, 16, 13, 10, 8, 10, 4, 171, 34, 0, 0, 16, 15, 10, 8, 10, 4, 171, 36, 0, 0, 16, 14, 10, 8, 10, 4, 171, 40, 0, 0, 16, 13, 10, 8, 10, 4, 171, 80, 0, 0, 16, 14, 10, 8, 10, 4, 171, 84, 0, 0, 16, 14, 10, 8, 10, 4, 171, 88, 0, 0, 16, 13, 10, 8, 10, 4, 171, 104, 0, 0, 16, 13, 10, 8, 10, 4, 171, 112, 0, 0, 16, 14, 10, 8, 10, 4, 171, 116, 0, 0, 16, 14, 10, 8, 10, 4, 171, 120, 0, 0, 16, 13, 10, 8, 10, 4, 171, 208, 0, 0, 16, 12, 10, 8, 10, 4, 172, 81, 192, 0, 16, 18, 10, 8, 10, 4, 175, 0, 0, 0, 16, 12, 10, 8, 10, 4, 175, 16, 0, 0, 16, 13, 10, 8, 10, 4, 175, 24, 0, 0, 16, 14, 10, 8, 10, 4, 175, 30, 0, 0, 16, 15, 10, 8, 10, 4, 175, 42, 0, 0, 16, 15, 10, 8, 10, 4, 175, 44, 0, 0, 16, 16, 10, 8, 10, 4, 175, 46, 0, 0, 16, 15, 10, 8, 10, 4, 175, 48, 0, 0, 16, 12, 10, 8, 10, 4, 175, 64, 0, 0, 16, 11, 10, 8, 10, 4, 175, 102, 0, 0, 16, 16, 10, 8, 10, 4, 175, 106, 128, 0, 16, 17, 10, 8, 10, 4, 175, 111, 108, 0, 16, 22, 10, 8, 10, 4, 175, 111, 144, 0, 16, 22, 10, 8, 10, 4, 175, 111, 148, 0, 16, 22, 10, 8, 10, 4, 175, 111, 152, 0, 16, 22, 10, 8, 10, 4, 175, 111, 156, 0, 16, 22, 10, 8, 10, 4, 175, 111, 160, 0, 16, 22, 10, 8, 10, 4, 175, 111, 164, 0, 16, 22, 10, 8, 10, 4, 175, 111, 168, 0, 16, 22, 10, 8, 10, 4, 175, 111, 172, 0, 16, 22, 10, 8, 10, 4, 175, 111, 184, 0, 16, 22, 10, 8, 10, 4, 175, 146, 0, 0, 16, 15, 10, 8, 10, 4, 175, 148, 0, 0, 16, 14, 10, 8, 10, 4, 175, 152, 0, 0, 16, 14, 10, 8, 10, 4, 175, 158, 96, 0, 16, 22, 10, 8, 10, 4, 175, 160, 0, 0, 16, 12, 10, 8, 10, 4, 175, 176, 156, 0, 16, 22, 10, 8, 10, 4, 175, 176, 176, 0, 16, 22, 10, 8, 10, 4, 175, 176, 188, 0, 16, 22, 10, 8, 10, 4, 175, 178, 0, 0, 16, 16, 10, 8, 10, 4, 175, 184, 128, 0, 16, 18, 10, 8, 10, 4, 175, 185, 0, 0, 16, 16, 10, 8, 10, 4, 175, 186, 0, 0, 16, 15, 10, 8, 10, 4, 175, 188, 0, 0, 16, 14, 10, 8, 10, 4, 180, 76, 0, 0, 16, 16, 10, 8, 10, 4, 180, 77, 0, 0, 16, 16, 10, 8, 10, 4, 180, 78, 0, 0, 16, 15, 10, 8, 10, 4, 180, 84, 0, 0, 16, 15, 10, 8, 10, 4, 180, 86, 0, 0, 16, 16, 10, 8, 10, 4, 180, 88, 0, 0, 16, 14, 10, 8, 10, 4, 180, 94, 56, 0, 16, 21, 10, 8, 10, 4, 180, 94, 96, 0, 16, 20, 10, 8, 10, 4, 180, 94, 120, 0, 16, 22, 10, 8, 10, 4, 180, 94, 124, 0, 16, 22, 10, 8, 10, 4, 180, 95, 128, 0, 16, 17, 10, 8, 10, 4, 180, 96, 0, 0, 16, 11, 10, 8, 10, 4, 180, 129, 128, 0, 16, 17, 10, 8, 10, 4, 180, 130, 0, 0, 16, 16, 10, 8, 10, 4, 180, 136, 0, 0, 16, 13, 10, 8, 10, 4, 180, 148, 16, 0, 16, 21, 10, 8, 10, 4, 180, 148, 152, 0, 16, 21, 10, 8, 10, 4, 180, 148, 216, 0, 16, 21, 10, 8, 10, 4, 180, 148, 224, 0, 16, 19, 10, 8, 10, 4, 180, 149, 128, 0, 16, 19, 10, 8, 10, 4, 180, 149, 236, 0, 16, 22, 10, 8, 10, 4, 180, 150, 160, 0, 16, 19, 10, 8, 10, 4, 180, 152, 0, 0, 16, 13, 10, 8, 10, 4, 180, 160, 0, 0, 16, 12, 10, 8, 10, 4, 180, 178, 112, 0, 16, 22, 10, 8, 10, 4, 180, 178, 116, 0, 16, 22, 10, 8, 10, 4, 180, 178, 192, 0, 16, 18, 10, 8, 10, 4, 180, 184, 0, 0, 16, 14, 10, 8, 10, 4, 180, 188, 0, 0, 16, 17, 10, 8, 10, 4, 180, 189, 148, 0, 16, 22, 10, 8, 10, 4, 180, 200, 252, 0, 16, 22, 10, 8, 10, 4, 180, 201, 0, 0, 16, 16, 10, 8, 10, 4, 180, 202, 0, 0, 16, 15, 10, 8, 10, 4, 180, 208, 0, 0, 16, 15, 10, 8, 10, 4, 180, 210, 212, 0, 16, 22, 10, 8, 10, 4, 180, 210, 224, 0, 16, 19, 10, 8, 10, 4, 180, 212, 0, 0, 16, 15, 10, 8, 10, 4, 180, 222, 224, 0, 16, 19, 10, 8, 10, 4, 180, 223, 0, 0, 16, 16, 10, 8, 10, 4, 180, 233, 0, 0, 16, 18, 10, 8, 10, 4, 180, 233, 64, 0, 16, 19, 10, 8, 10, 4, 180, 233, 144, 0, 16, 22, 10, 8, 10, 4, 180, 235, 64, 0, 16, 19, 10, 8, 10, 4, 180, 235, 112, 0, 16, 22, 10, 8, 10, 4, 180, 235, 136, 0, 16, 22, 10, 8, 10, 4, 182, 16, 144, 0, 16, 22, 10, 8, 10, 4, 182, 16, 148, 0, 16, 22, 10, 8, 10, 4, 182, 16, 192, 0, 16, 19, 10, 8, 10, 4, 182, 18, 0, 0, 16, 17, 10, 8, 10, 4, 182, 23, 184, 0, 16, 21, 10, 8, 10, 4, 182, 23, 200, 0, 16, 21, 10, 8, 10, 4, 182, 32, 0, 0, 16, 12, 10, 8, 10, 4, 182, 48, 96, 0, 16, 19, 10, 8, 10, 4, 182, 49, 0, 0, 16, 16, 10, 8, 10, 4, 182, 50, 0, 0, 16, 20, 10, 8, 10, 4, 182, 50, 112, 0, 16, 20, 10, 8, 10, 4, 182, 51, 0, 0, 16, 16, 10, 8, 10, 4, 182, 54, 0, 0, 16, 17, 10, 8, 10, 4, 182, 54, 244, 0, 16, 22, 10, 8, 10, 4, 182, 61, 0, 0, 16, 16, 10, 8, 10, 4, 182, 80, 0, 0, 16, 14, 10, 8, 10, 4, 182, 84, 0, 0, 16, 14, 10, 8, 10, 4, 182, 88, 0, 0, 16, 14, 10, 8, 10, 4, 182, 92, 0, 0, 16, 16, 10, 8, 10, 4, 182, 96, 0, 0, 16, 12, 10, 8, 10, 4, 182, 112, 0, 0, 16, 12, 10, 8, 10, 4, 182, 128, 0, 0, 16, 12, 10, 8, 10, 4, 182, 144, 0, 0, 16, 13, 10, 8, 10, 4, 182, 157, 0, 0, 16, 16, 10, 8, 10, 4, 182, 160, 64, 0, 16, 19, 10, 8, 10, 4, 182, 174, 0, 0, 16, 15, 10, 8, 10, 4, 182, 200, 0, 0, 16, 13, 10, 8, 10, 4, 182, 236, 128, 0, 16, 17, 10, 8, 10, 4, 182, 237, 24, 0, 16, 22, 10, 8, 10, 4, 182, 237, 28, 0, 16, 22, 10, 8, 10, 4, 182, 238, 0, 0, 16, 16, 10, 8, 10, 4, 182, 239, 0, 0, 16, 19, 10, 8, 10, 4, 182, 240, 0, 0, 16, 13, 10, 8, 10, 4, 182, 254, 0, 0, 16, 16, 10, 8, 10, 4, 182, 255, 36, 0, 16, 22, 10, 8, 10, 4, 182, 255, 60, 0, 16, 22, 10, 8, 10, 4, 183, 0, 0, 0, 16, 10, 10, 8, 10, 4, 183, 64, 0, 0, 16, 13, 10, 8, 10, 4, 183, 78, 160, 0, 16, 22, 10, 8, 10, 4, 183, 78, 164, 0, 16, 22, 10, 8, 10, 4, 183, 78, 180, 0, 16, 22, 10, 8, 10, 4, 183, 81, 172, 0, 16, 22, 10, 8, 10, 4, 183, 81, 180, 0, 16, 22, 10, 8, 10, 4, 183, 84, 0, 0, 16, 15, 10, 8, 10, 4, 183, 91, 128, 0, 16, 22, 10, 8, 10, 4, 183, 91, 136, 0, 16, 21, 10, 8, 10, 4, 183, 91, 144, 0, 16, 20, 10, 8, 10, 4, 183, 92, 0, 0, 16, 14, 10, 8, 10, 4, 183, 128, 0, 0, 16, 11, 10, 8, 10, 4, 183, 160, 0, 0, 16, 13, 10, 8, 10, 4, 183, 168, 0, 0, 16, 15, 10, 8, 10, 4, 183, 170, 0, 0, 16, 16, 10, 8, 10, 4, 183, 172, 0, 0, 16, 14, 10, 8, 10, 4, 183, 182, 0, 0, 16, 19, 10, 8, 10, 4, 183, 184, 0, 0, 16, 13, 10, 8, 10, 4, 183, 192, 0, 0, 16, 10, 10, 8, 10, 4, 188, 131, 128, 0, 16, 17, 10, 8, 10, 4, 192, 124, 154, 0, 16, 24, 10, 8, 10, 4, 192, 140, 128, 0, 16, 22, 10, 8, 10, 4, 192, 140, 132, 0, 16, 22, 10, 8, 10, 4, 192, 140, 136, 0, 16, 22, 10, 8, 10, 4, 192, 140, 156, 0, 16, 22, 10, 8, 10, 4, 192, 140, 160, 0, 16, 22, 10, 8, 10, 4, 192, 140, 164, 0, 16, 22, 10, 8, 10, 4, 192, 140, 168, 0, 16, 22, 10, 8, 10, 4, 192, 140, 172, 0, 16, 22, 10, 8, 10, 4, 192, 140, 176, 0, 16, 22, 10, 8, 10, 4, 192, 140, 180, 0, 16, 22, 10, 8, 10, 4, 192, 140, 184, 0, 16, 22, 10, 8, 10, 4, 192, 140, 188, 0, 16, 22, 10, 8, 10, 4, 192, 140, 192, 0, 16, 22, 10, 8, 10, 4, 192, 140, 196, 0, 16, 22, 10, 8, 10, 4, 192, 140, 200, 0, 16, 22, 10, 8, 10, 4, 192, 140, 204, 0, 16, 22, 10, 8, 10, 4, 192, 140, 208, 0, 16, 22, 10, 8, 10, 4, 192, 140, 212, 0, 16, 22, 10, 8, 10, 4, 192, 144, 128, 0, 16, 17, 10, 8, 10, 4, 193, 112, 0, 0, 16, 16, 10, 8, 10, 4, 202, 0, 100, 0, 16, 23, 10, 8, 10, 4, 202, 0, 122, 0, 16, 23, 10, 8, 10, 4, 202, 0, 176, 0, 16, 22, 10, 8, 10, 4, 202, 3, 128, 0, 16, 23, 10, 8, 10, 4, 202, 4, 128, 0, 16, 19, 10, 8, 10, 4, 202, 4, 252, 0, 16, 22, 10, 8, 10, 4, 202, 5, 208, 0, 16, 22, 10, 8, 10, 4, 202, 5, 212, 0, 16, 22, 10, 8, 10, 4, 202, 5, 216, 0, 16, 22, 10, 8, 10, 4, 202, 6, 6, 0, 16, 23, 10, 8, 10, 4, 202, 6, 66, 0, 16, 23, 10, 8, 10, 4, 202, 6, 72, 0, 16, 23, 10, 8, 10, 4, 202, 6, 87, 0, 16, 24, 10, 8, 10, 4, 202, 6, 88, 0, 16, 23, 10, 8, 10, 4, 202, 6, 92, 0, 16, 23, 10, 8, 10, 4, 202, 6, 103, 0, 16, 24, 10, 8, 10, 4, 202, 6, 108, 0, 16, 24, 10, 8, 10, 4, 202, 6, 110, 0, 16, 23, 10, 8, 10, 4, 202, 6, 114, 0, 16, 24, 10, 8, 10, 4, 202, 6, 176, 0, 16, 20, 10, 8, 10, 4, 202, 8, 0, 0, 16, 24, 10, 8, 10, 4, 202, 8, 2, 0, 16, 23, 10, 8, 10, 4, 202, 8, 4, 0, 16, 23, 10, 8, 10, 4, 202, 8, 12, 0, 16, 24, 10, 8, 10, 4, 202, 8, 24, 0, 16, 24, 10, 8, 10, 4, 202, 8, 77, 0, 16, 24, 10, 8, 10, 4, 202, 8, 128, 0, 16, 19, 10, 8, 10, 4, 202, 8, 192, 0, 16, 20, 10, 8, 10, 4, 202, 9, 32, 0, 16, 24, 10, 8, 10, 4, 202, 9, 34, 0, 16, 23, 10, 8, 10, 4, 202, 9, 48, 0, 16, 23, 10, 8, 10, 4, 202, 9, 51, 0, 16, 24, 10, 8, 10, 4, 202, 9, 52, 0, 16, 23, 10, 8, 10, 4, 202, 9, 54, 0, 16, 24, 10, 8, 10, 4, 202, 9, 57, 0, 16, 24, 10, 8, 10, 4, 202, 9, 58, 0, 16, 23, 10, 8, 10, 4, 202, 10, 64, 0, 16, 20, 10, 8, 10, 4, 202, 10, 112, 0, 16, 22, 10, 8, 10, 4, 202, 10, 116, 0, 16, 22, 10, 8, 10, 4, 202, 10, 120, 0, 16, 22, 10, 8, 10, 4, 202, 10, 124, 0, 16, 22, 10, 8, 10, 4, 202, 12, 1, 0, 16, 24, 10, 8, 10, 4, 202, 12, 2, 0, 16, 24, 10, 8, 10, 4, 202, 12, 17, 0, 16, 24, 10, 8, 10, 4, 202, 12, 18, 0, 16, 24, 10, 8, 10, 4, 202, 12, 19, 0, 16, 24, 10, 8, 10, 4, 202, 12, 72, 0, 16, 24, 10, 8, 10, 4, 202, 12, 84, 0, 16, 23, 10, 8, 10, 4, 202, 12, 96, 0, 16, 24, 10, 8, 10, 4, 202, 12, 98, 0, 16, 23, 10, 8, 10, 4, 202, 12, 106, 0, 16, 24, 10, 8, 10, 4, 202, 12, 111, 0, 16, 24, 10, 8, 10, 4, 202, 12, 116, 0, 16, 24, 10, 8, 10, 4, 202, 14, 64, 0, 16, 23, 10, 8, 10, 4, 202, 14, 69, 0, 16, 24, 10, 8, 10, 4, 202, 14, 73, 0, 16, 24, 10, 8, 10, 4, 202, 14, 74, 0, 16, 23, 10, 8, 10, 4, 202, 14, 76, 0, 16, 24, 10, 8, 10, 4, 202, 14, 78, 0, 16, 23, 10, 8, 10, 4, 202, 14, 88, 0, 16, 24, 10, 8, 10, 4, 202, 14, 97, 0, 16, 24, 10, 8, 10, 4, 202, 14, 104, 0, 16, 23, 10, 8, 10, 4, 202, 14, 108, 0, 16, 23, 10, 8, 10, 4, 202, 14, 111, 0, 16, 24, 10, 8, 10, 4, 202, 14, 114, 0, 16, 23, 10, 8, 10, 4, 202, 14, 118, 0, 16, 23, 10, 8, 10, 4, 202, 14, 124, 0, 16, 23, 10, 8, 10, 4, 202, 14, 127, 0, 16, 24, 10, 8, 10, 4, 202, 14, 129, 0, 16, 24, 10, 8, 10, 4, 202, 14, 135, 0, 16, 24, 10, 8, 10, 4, 202, 14, 136, 0, 16, 24, 10, 8, 10, 4, 202, 14, 149, 0, 16, 24, 10, 8, 10, 4, 202, 14, 151, 0, 16, 24, 10, 8, 10, 4, 202, 14, 157, 0, 16, 24, 10, 8, 10, 4, 202, 14, 158, 0, 16, 23, 10, 8, 10, 4, 202, 14, 169, 0, 16, 24, 10, 8, 10, 4, 202, 14, 170, 0, 16, 23, 10, 8, 10, 4, 202, 14, 172, 0, 16, 22, 10, 8, 10, 4, 202, 14, 176, 0, 16, 24, 10, 8, 10, 4, 202, 14, 184, 0, 16, 23, 10, 8, 10, 4, 202, 14, 208, 0, 16, 23, 10, 8, 10, 4, 202, 14, 213, 0, 16, 24, 10, 8, 10, 4, 202, 14, 219, 0, 16, 24, 10, 8, 10, 4, 202, 14, 220, 0, 16, 24, 10, 8, 10, 4, 202, 14, 222, 0, 16, 23, 10, 8, 10, 4, 202, 14, 225, 0, 16, 24, 10, 8, 10, 4, 202, 14, 226, 0, 16, 23, 10, 8, 10, 4, 202, 14, 231, 0, 16, 24, 10, 8, 10, 4, 202, 14, 235, 0, 16, 24, 10, 8, 10, 4, 202, 14, 236, 0, 16, 23, 10, 8, 10, 4, 202, 14, 238, 0, 16, 24, 10, 8, 10, 4, 202, 14, 239, 0, 16, 24, 10, 8, 10, 4, 202, 14, 246, 0, 16, 24, 10, 8, 10, 4, 202, 14, 251, 0, 16, 24, 10, 8, 10, 4, 202, 20, 66, 0, 16, 24, 10, 8, 10, 4, 202, 20, 79, 0, 16, 24, 10, 8, 10, 4, 202, 20, 87, 0, 16, 24, 10, 8, 10, 4, 202, 20, 88, 0, 16, 23, 10, 8, 10, 4, 202, 20, 90, 0, 16, 24, 10, 8, 10, 4, 202, 20, 94, 0, 16, 23, 10, 8, 10, 4, 202, 20, 114, 0, 16, 24, 10, 8, 10, 4, 202, 20, 117, 0, 16, 24, 10, 8, 10, 4, 202, 20, 120, 0, 16, 24, 10, 8, 10, 4, 202, 20, 125, 0, 16, 24, 10, 8, 10, 4, 202, 20, 126, 0, 16, 24, 10, 8, 10, 4, 202, 20, 127, 0, 16, 24, 10, 8, 10, 4, 202, 21, 48, 0, 16, 22, 10, 8, 10, 4, 202, 21, 52, 0, 16, 22, 10, 8, 10, 4, 202, 21, 56, 0, 16, 22, 10, 8, 10, 4, 202, 21, 60, 0, 16, 22, 10, 8, 10, 4, 202, 21, 131, 0, 16, 24, 10, 8, 10, 4, 202, 21, 132, 0, 16, 24, 10, 8, 10, 4, 202, 21, 141, 0, 16, 24, 10, 8, 10, 4, 202, 21, 142, 0, 16, 24, 10, 8, 10, 4, 202, 21, 147, 0, 16, 24, 10, 8, 10, 4, 202, 21, 148, 0, 16, 24, 10, 8, 10, 4, 202, 21, 150, 0, 16, 23, 10, 8, 10, 4, 202, 21, 152, 0, 16, 23, 10, 8, 10, 4, 202, 21, 154, 0, 16, 24, 10, 8, 10, 4, 202, 21, 156, 0, 16, 24, 10, 8, 10, 4, 202, 22, 248, 0, 16, 22, 10, 8, 10, 4, 202, 22, 252, 0, 16, 22, 10, 8, 10, 4, 202, 27, 12, 0, 16, 24, 10, 8, 10, 4, 202, 27, 14, 0, 16, 24, 10, 8, 10, 4, 202, 27, 136, 0, 16, 23, 10, 8, 10, 4, 202, 36, 226, 0, 16, 24, 10, 8, 10, 4, 202, 38, 0, 0, 16, 23, 10, 8, 10, 4, 202, 38, 2, 0, 16, 23, 10, 8, 10, 4, 202, 38, 8, 0, 16, 21, 10, 8, 10, 4, 202, 38, 48, 0, 16, 20, 10, 8, 10, 4, 202, 38, 64, 0, 16, 19, 10, 8, 10, 4, 202, 38, 96, 0, 16, 19, 10, 8, 10, 4, 202, 38, 128, 0, 16, 23, 10, 8, 10, 4, 202, 38, 130, 0, 16, 23, 10, 8, 10, 4, 202, 38, 132, 0, 16, 23, 10, 8, 10, 4, 202, 38, 134, 0, 16, 24, 10, 8, 10, 4, 202, 38, 135, 0, 16, 24, 10, 8, 10, 4, 202, 38, 136, 0, 16, 23, 10, 8, 10, 4, 202, 38, 138, 0, 16, 24, 10, 8, 10, 4, 202, 38, 140, 0, 16, 23, 10, 8, 10, 4, 202, 38, 142, 0, 16, 23, 10, 8, 10, 4, 202, 38, 146, 0, 16, 23, 10, 8, 10, 4, 202, 38, 149, 0, 16, 24, 10, 8, 10, 4, 202, 38, 150, 0, 16, 23, 10, 8, 10, 4, 202, 38, 152, 0, 16, 23, 10, 8, 10, 4, 202, 38, 154, 0, 16, 23, 10, 8, 10, 4, 202, 38, 156, 0, 16, 24, 10, 8, 10, 4, 202, 38, 158, 0, 16, 23, 10, 8, 10, 4, 202, 38, 160, 0, 16, 23, 10, 8, 10, 4, 202, 38, 164, 0, 16, 22, 10, 8, 10, 4, 202, 38, 168, 0, 16, 23, 10, 8, 10, 4, 202, 38, 170, 0, 16, 24, 10, 8, 10, 4, 202, 38, 171, 0, 16, 24, 10, 8, 10, 4, 202, 38, 176, 0, 16, 23, 10, 8, 10, 4, 202, 38, 184, 0, 16, 21, 10, 8, 10, 4, 202, 38, 192, 0, 16, 18, 10, 8, 10, 4, 202, 40, 4, 0, 16, 23, 10, 8, 10, 4, 202, 40, 7, 0, 16, 24, 10, 8, 10, 4, 202, 40, 15, 0, 16, 24, 10, 8, 10, 4, 202, 40, 135, 0, 16, 24, 10, 8, 10, 4, 202, 40, 136, 0, 16, 24, 10, 8, 10, 4, 202, 40, 140, 0, 16, 24, 10, 8, 10, 4, 202, 40, 143, 0, 16, 24, 10, 8, 10, 4, 202, 40, 144, 0, 16, 23, 10, 8, 10, 4, 202, 40, 150, 0, 16, 24, 10, 8, 10, 4, 202, 40, 155, 0, 16, 24, 10, 8, 10, 4, 202, 40, 156, 0, 16, 24, 10, 8, 10, 4, 202, 40, 158, 0, 16, 23, 10, 8, 10, 4, 202, 40, 162, 0, 16, 24, 10, 8, 10, 4, 202, 41, 8, 0, 16, 23, 10, 8, 10, 4, 202, 41, 11, 0, 16, 24, 10, 8, 10, 4, 202, 41, 12, 0, 16, 23, 10, 8, 10, 4, 202, 41, 128, 0, 16, 24, 10, 8, 10, 4, 202, 41, 130, 0, 16, 23, 10, 8, 10, 4, 202, 41, 152, 0, 16, 21, 10, 8, 10, 4, 202, 41, 192, 0, 16, 24, 10, 8, 10, 4, 202, 41, 196, 0, 16, 22, 10, 8, 10, 4, 202, 41, 200, 0, 16, 22, 10, 8, 10, 4, 202, 41, 240, 0, 16, 20, 10, 8, 10, 4, 202, 43, 76, 0, 16, 22, 10, 8, 10, 4, 202, 43, 144, 0, 16, 20, 10, 8, 10, 4, 202, 44, 16, 0, 16, 20, 10, 8, 10, 4, 202, 44, 48, 0, 16, 22, 10, 8, 10, 4, 202, 44, 67, 0, 16, 24, 10, 8, 10, 4, 202, 44, 74, 0, 16, 24, 10, 8, 10, 4, 202, 44, 97, 0, 16, 24, 10, 8, 10, 4, 202, 44, 129, 0, 16, 24, 10, 8, 10, 4, 202, 44, 132, 0, 16, 23, 10, 8, 10, 4, 202, 44, 146, 0, 16, 23, 10, 8, 10, 4, 202, 45, 0, 0, 16, 23, 10, 8, 10, 4, 202, 45, 2, 0, 16, 24, 10, 8, 10, 4, 202, 45, 15, 0, 16, 24, 10, 8, 10, 4, 202, 45, 16, 0, 16, 20, 10, 8, 10, 4, 202, 46, 16, 0, 16, 23, 10, 8, 10, 4, 202, 46, 18, 0, 16, 24, 10, 8, 10, 4, 202, 46, 20, 0, 16, 23, 10, 8, 10, 4, 202, 46, 32, 0, 16, 19, 10, 8, 10, 4, 202, 46, 128, 0, 16, 24, 10, 8, 10, 4, 202, 46, 224, 0, 16, 20, 10, 8, 10, 4, 202, 47, 82, 0, 16, 23, 10, 8, 10, 4, 202, 47, 96, 0, 16, 22, 10, 8, 10, 4, 202, 47, 100, 0, 16, 22, 10, 8, 10, 4, 202, 47, 104, 0, 16, 22, 10, 8, 10, 4, 202, 47, 108, 0, 16, 22, 10, 8, 10, 4, 202, 47, 126, 0, 16, 24, 10, 8, 10, 4, 202, 47, 128, 0, 16, 24, 10, 8, 10, 4, 202, 47, 130, 0, 16, 23, 10, 8, 10, 4, 202, 52, 33, 0, 16, 24, 10, 8, 10, 4, 202, 52, 34, 0, 16, 24, 10, 8, 10, 4, 202, 52, 47, 0, 16, 24, 10, 8, 10, 4, 202, 52, 143, 0, 16, 24, 10, 8, 10, 4, 202, 53, 140, 0, 16, 24, 10, 8, 10, 4, 202, 53, 143, 0, 16, 24, 10, 8, 10, 4, 202, 57, 192, 0, 16, 22, 10, 8, 10, 4, 202, 57, 196, 0, 16, 22, 10, 8, 10, 4, 202, 57, 200, 0, 16, 22, 10, 8, 10, 4, 202, 57, 204, 0, 16, 22, 10, 8, 10, 4, 202, 57, 212, 0, 16, 22, 10, 8, 10, 4, 202, 57, 216, 0, 16, 22, 10, 8, 10, 4, 202, 57, 240, 0, 16, 20, 10, 8, 10, 4, 202, 58, 0, 0, 16, 24, 10, 8, 10, 4, 202, 58, 104, 0, 16, 22, 10, 8, 10, 4, 202, 58, 112, 0, 16, 22, 10, 8, 10, 4, 202, 59, 0, 0, 16, 24, 10, 8, 10, 4, 202, 59, 1, 0, 16, 24, 10, 8, 10, 4, 202, 59, 212, 0, 16, 22, 10, 8, 10, 4, 202, 59, 236, 0, 16, 24, 10, 8, 10, 4, 202, 59, 240, 0, 16, 24, 10, 8, 10, 4, 202, 60, 48, 0, 16, 21, 10, 8, 10, 4, 202, 60, 96, 0, 16, 21, 10, 8, 10, 4, 202, 60, 112, 0, 16, 20, 10, 8, 10, 4, 202, 60, 132, 0, 16, 22, 10, 8, 10, 4, 202, 60, 136, 0, 16, 21, 10, 8, 10, 4, 202, 60, 144, 0, 16, 20, 10, 8, 10, 4, 202, 61, 68, 0, 16, 22, 10, 8, 10, 4, 202, 61, 76, 0, 16, 22, 10, 8, 10, 4, 202, 61, 88, 0, 16, 22, 10, 8, 10, 4, 202, 61, 123, 0, 16, 24, 10, 8, 10, 4, 202, 61, 127, 0, 16, 24, 10, 8, 10, 4, 202, 62, 112, 0, 16, 22, 10, 8, 10, 4, 202, 62, 248, 0, 16, 22, 10, 8, 10, 4, 202, 62, 252, 0, 16, 24, 10, 8, 10, 4, 202, 62, 255, 0, 16, 24, 10, 8, 10, 4, 202, 63, 80, 0, 16, 24, 10, 8, 10, 4, 202, 63, 81, 0, 16, 24, 10, 8, 10, 4, 202, 63, 82, 0, 16, 23, 10, 8, 10, 4, 202, 63, 84, 0, 16, 22, 10, 8, 10, 4, 202, 63, 88, 0, 16, 21, 10, 8, 10, 4, 202, 63, 160, 0, 16, 19, 10, 8, 10, 4, 202, 63, 248, 0, 16, 22, 10, 8, 10, 4, 202, 63, 253, 0, 16, 24, 10, 8, 10, 4, 202, 65, 0, 0, 16, 21, 10, 8, 10, 4, 202, 65, 8, 0, 16, 23, 10, 8, 10, 4, 202, 65, 96, 0, 16, 22, 10, 8, 10, 4, 202, 65, 100, 0, 16, 22, 10, 8, 10, 4, 202, 65, 104, 0, 16, 22, 10, 8, 10, 4, 202, 65, 108, 0, 16, 22, 10, 8, 10, 4, 202, 66, 168, 0, 16, 22, 10, 8, 10, 4, 202, 67, 0, 0, 16, 22, 10, 8, 10, 4, 202, 69, 4, 0, 16, 22, 10, 8, 10, 4, 202, 69, 16, 0, 16, 20, 10, 8, 10, 4, 202, 70, 0, 0, 16, 19, 10, 8, 10, 4, 202, 70, 96, 0, 16, 20, 10, 8, 10, 4, 202, 70, 192, 0, 16, 20, 10, 8, 10, 4, 202, 71, 32, 0, 16, 22, 10, 8, 10, 4, 202, 71, 36, 0, 16, 22, 10, 8, 10, 4, 202, 71, 40, 0, 16, 22, 10, 8, 10, 4, 202, 71, 44, 0, 16, 22, 10, 8, 10, 4, 202, 72, 40, 0, 16, 21, 10, 8, 10, 4, 202, 72, 80, 0, 16, 20, 10, 8, 10, 4, 202, 72, 112, 0, 16, 22, 10, 8, 10, 4, 202, 72, 116, 0, 16, 22, 10, 8, 10, 4, 202, 72, 120, 0, 16, 22, 10, 8, 10, 4, 202, 72, 124, 0, 16, 22, 10, 8, 10, 4, 202, 73, 128, 0, 16, 22, 10, 8, 10, 4, 202, 73, 240, 0, 16, 22, 10, 8, 10, 4, 202, 73, 244, 0, 16, 22, 10, 8, 10, 4, 202, 73, 248, 0, 16, 22, 10, 8, 10, 4, 202, 73, 252, 0, 16, 22, 10, 8, 10, 4, 202, 74, 8, 0, 16, 21, 10, 8, 10, 4, 202, 74, 36, 0, 16, 24, 10, 8, 10, 4, 202, 74, 42, 0, 16, 24, 10, 8, 10, 4, 202, 74, 52, 0, 16, 24, 10, 8, 10, 4, 202, 74, 80, 0, 16, 20, 10, 8, 10, 4, 202, 74, 232, 0, 16, 22, 10, 8, 10, 4, 202, 74, 254, 0, 16, 23, 10, 8, 10, 4, 202, 75, 208, 0, 16, 20, 10, 8, 10, 4, 202, 75, 252, 0, 16, 22, 10, 8, 10, 4, 202, 76, 252, 0, 16, 22, 10, 8, 10, 4, 202, 77, 80, 0, 16, 21, 10, 8, 10, 4, 202, 77, 92, 0, 16, 22, 10, 8, 10, 4, 202, 78, 8, 0, 16, 21, 10, 8, 10, 4, 202, 79, 224, 0, 16, 21, 10, 8, 10, 4, 202, 79, 248, 0, 16, 22, 10, 8, 10, 4, 202, 80, 192, 0, 16, 21, 10, 8, 10, 4, 202, 80, 200, 0, 16, 21, 10, 8, 10, 4, 202, 81, 0, 0, 16, 22, 10, 8, 10, 4, 202, 81, 176, 0, 16, 22, 10, 8, 10, 4, 202, 81, 180, 0, 16, 22, 10, 8, 10, 4, 202, 81, 184, 0, 16, 22, 10, 8, 10, 4, 202, 81, 188, 0, 16, 22, 10, 8, 10, 4, 202, 83, 252, 0, 16, 22, 10, 8, 10, 4, 202, 84, 0, 0, 16, 22, 10, 8, 10, 4, 202, 84, 4, 0, 16, 22, 10, 8, 10, 4, 202, 84, 8, 0, 16, 21, 10, 8, 10, 4, 202, 84, 16, 0, 16, 23, 10, 8, 10, 4, 202, 84, 22, 0, 16, 24, 10, 8, 10, 4, 202, 84, 24, 0, 16, 21, 10, 8, 10, 4, 202, 85, 208, 0, 16, 20, 10, 8, 10, 4, 202, 86, 249, 0, 16, 24, 10, 8, 10, 4, 202, 86, 252, 0, 16, 22, 10, 8, 10, 4, 202, 87, 80, 0, 16, 20, 10, 8, 10, 4, 202, 88, 32, 0, 16, 22, 10, 8, 10, 4, 202, 89, 8, 0, 16, 21, 10, 8, 10, 4, 202, 89, 96, 0, 16, 22, 10, 8, 10, 4, 202, 89, 108, 0, 16, 22, 10, 8, 10, 4, 202, 89, 119, 0, 16, 24, 10, 8, 10, 4, 202, 89, 232, 0, 16, 21, 10, 8, 10, 4, 202, 90, 0, 0, 16, 22, 10, 8, 10, 4, 202, 90, 16, 0, 16, 22, 10, 8, 10, 4, 202, 90, 20, 0, 16, 22, 10, 8, 10, 4, 202, 90, 24, 0, 16, 22, 10, 8, 10, 4, 202, 90, 28, 0, 16, 22, 10, 8, 10, 4, 202, 90, 37, 0, 16, 24, 10, 8, 10, 4, 202, 90, 96, 0, 16, 22, 10, 8, 10, 4, 202, 90, 100, 0, 16, 22, 10, 8, 10, 4, 202, 90, 104, 0, 16, 22, 10, 8, 10, 4, 202, 90, 108, 0, 16, 22, 10, 8, 10, 4, 202, 90, 112, 0, 16, 20, 10, 8, 10, 4, 202, 90, 193, 0, 16, 24, 10, 8, 10, 4, 202, 90, 196, 0, 16, 24, 10, 8, 10, 4, 202, 90, 205, 0, 16, 24, 10, 8, 10, 4, 202, 90, 224, 0, 16, 20, 10, 8, 10, 4, 202, 91, 0, 0, 16, 22, 10, 8, 10, 4, 202, 91, 36, 0, 16, 22, 10, 8, 10, 4, 202, 91, 96, 0, 16, 20, 10, 8, 10, 4, 202, 91, 128, 0, 16, 22, 10, 8, 10, 4, 202, 91, 176, 0, 16, 20, 10, 8, 10, 4, 202, 91, 224, 0, 16, 19, 10, 8, 10, 4, 202, 92, 0, 0, 16, 22, 10, 8, 10, 4, 202, 92, 8, 0, 16, 21, 10, 8, 10, 4, 202, 92, 48, 0, 16, 20, 10, 8, 10, 4, 202, 92, 252, 0, 16, 22, 10, 8, 10, 4, 202, 93, 0, 0, 16, 22, 10, 8, 10, 4, 202, 93, 252, 0, 16, 22, 10, 8, 10, 4, 202, 94, 74, 0, 16, 24, 10, 8, 10, 4, 202, 94, 81, 0, 16, 24, 10, 8, 10, 4, 202, 94, 92, 0, 16, 22, 10, 8, 10, 4, 202, 95, 0, 0, 16, 22, 10, 8, 10, 4, 202, 95, 4, 0, 16, 22, 10, 8, 10, 4, 202, 95, 8, 0, 16, 21, 10, 8, 10, 4, 202, 95, 16, 0, 16, 20, 10, 8, 10, 4, 202, 95, 240, 0, 16, 21, 10, 8, 10, 4, 202, 95, 252, 0, 16, 22, 10, 8, 10, 4, 202, 96, 0, 0, 16, 18, 10, 8, 10, 4, 202, 96, 64, 0, 16, 21, 10, 8, 10, 4, 202, 96, 72, 0, 16, 21, 10, 8, 10, 4, 202, 96, 80, 0, 16, 20, 10, 8, 10, 4, 202, 96, 96, 0, 16, 21, 10, 8, 10, 4, 202, 96, 104, 0, 16, 21, 10, 8, 10, 4, 202, 96, 112, 0, 16, 20, 10, 8, 10, 4, 202, 96, 128, 0, 16, 21, 10, 8, 10, 4, 202, 96, 136, 0, 16, 21, 10, 8, 10, 4, 202, 96, 144, 0, 16, 20, 10, 8, 10, 4, 202, 96, 160, 0, 16, 21, 10, 8, 10, 4, 202, 96, 168, 0, 16, 21, 10, 8, 10, 4, 202, 96, 176, 0, 16, 20, 10, 8, 10, 4, 202, 96, 192, 0, 16, 21, 10, 8, 10, 4, 202, 96, 200, 0, 16, 21, 10, 8, 10, 4, 202, 96, 208, 0, 16, 20, 10, 8, 10, 4, 202, 96, 224, 0, 16, 21, 10, 8, 10, 4, 202, 96, 232, 0, 16, 21, 10, 8, 10, 4, 202, 96, 240, 0, 16, 20, 10, 8, 10, 4, 202, 97, 0, 0, 16, 21, 10, 8, 10, 4, 202, 97, 8, 0, 16, 21, 10, 8, 10, 4, 202, 97, 16, 0, 16, 20, 10, 8, 10, 4, 202, 97, 32, 0, 16, 19, 10, 8, 10, 4, 202, 97, 64, 0, 16, 19, 10, 8, 10, 4, 202, 97, 96, 0, 16, 20, 10, 8, 10, 4, 202, 97, 112, 0, 16, 20, 10, 8, 10, 4, 202, 97, 128, 0, 16, 18, 10, 8, 10, 4, 202, 97, 192, 0, 16, 19, 10, 8, 10, 4, 202, 97, 224, 0, 16, 21, 10, 8, 10, 4, 202, 97, 232, 0, 16, 21, 10, 8, 10, 4, 202, 97, 240, 0, 16, 20, 10, 8, 10, 4, 202, 98, 0, 0, 16, 21, 10, 8, 10, 4, 202, 98, 8, 0, 16, 21, 10, 8, 10, 4, 202, 98, 16, 0, 16, 20, 10, 8, 10, 4, 202, 98, 32, 0, 16, 21, 10, 8, 10, 4, 202, 98, 40, 0, 16, 21, 10, 8, 10, 4, 202, 98, 48, 0, 16, 20, 10, 8, 10, 4, 202, 98, 64, 0, 16, 19, 10, 8, 10, 4, 202, 98, 96, 0, 16, 21, 10, 8, 10, 4, 202, 98, 104, 0, 16, 21, 10, 8, 10, 4, 202, 98, 112, 0, 16, 20, 10, 8, 10, 4, 202, 98, 128, 0, 16, 19, 10, 8, 10, 4, 202, 98, 160, 0, 16, 21, 10, 8, 10, 4, 202, 98, 168, 0, 16, 21, 10, 8, 10, 4, 202, 98, 176, 0, 16, 20, 10, 8, 10, 4, 202, 98, 192, 0, 16, 21, 10, 8, 10, 4, 202, 98, 200, 0, 16, 21, 10, 8, 10, 4, 202, 98, 208, 0, 16, 20, 10, 8, 10, 4, 202, 98, 224, 0, 16, 21, 10, 8, 10, 4, 202, 98, 232, 0, 16, 21, 10, 8, 10, 4, 202, 98, 240, 0, 16, 20, 10, 8, 10, 4, 202, 99, 0, 0, 16, 18, 10, 8, 10, 4, 202, 99, 64, 0, 16, 19, 10, 8, 10, 4, 202, 99, 96, 0, 16, 21, 10, 8, 10, 4, 202, 99, 104, 0, 16, 21, 10, 8, 10, 4, 202, 99, 112, 0, 16, 20, 10, 8, 10, 4, 202, 99, 128, 0, 16, 19, 10, 8, 10, 4, 202, 99, 160, 0, 16, 21, 10, 8, 10, 4, 202, 99, 168, 0, 16, 21, 10, 8, 10, 4, 202, 99, 176, 0, 16, 20, 10, 8, 10, 4, 202, 99, 192, 0, 16, 21, 10, 8, 10, 4, 202, 99, 200, 0, 16, 21, 10, 8, 10, 4, 202, 99, 208, 0, 16, 20, 10, 8, 10, 4, 202, 99, 224, 0, 16, 21, 10, 8, 10, 4, 202, 99, 232, 0, 16, 21, 10, 8, 10, 4, 202, 99, 240, 0, 16, 20, 10, 8, 10, 4, 202, 100, 0, 0, 16, 21, 10, 8, 10, 4, 202, 100, 8, 0, 16, 21, 10, 8, 10, 4, 202, 100, 16, 0, 16, 20, 10, 8, 10, 4, 202, 100, 32, 0, 16, 19, 10, 8, 10, 4, 202, 100, 64, 0, 16, 21, 10, 8, 10, 4, 202, 100, 72, 0, 16, 21, 10, 8, 10, 4, 202, 100, 80, 0, 16, 20, 10, 8, 10, 4, 202, 100, 96, 0, 16, 21, 10, 8, 10, 4, 202, 100, 104, 0, 16, 21, 10, 8, 10, 4, 202, 100, 112, 0, 16, 20, 10, 8, 10, 4, 202, 100, 128, 0, 16, 21, 10, 8, 10, 4, 202, 100, 136, 0, 16, 21, 10, 8, 10, 4, 202, 100, 144, 0, 16, 20, 10, 8, 10, 4, 202, 100, 160, 0, 16, 21, 10, 8, 10, 4, 202, 100, 168, 0, 16, 21, 10, 8, 10, 4, 202, 100, 176, 0, 16, 20, 10, 8, 10, 4, 202, 100, 192, 0, 16, 21, 10, 8, 10, 4, 202, 100, 200, 0, 16, 21, 10, 8, 10, 4, 202, 100, 208, 0, 16, 20, 10, 8, 10, 4, 202, 100, 224, 0, 16, 19, 10, 8, 10, 4, 202, 101, 0, 0, 16, 18, 10, 8, 10, 4, 202, 101, 64, 0, 16, 19, 10, 8, 10, 4, 202, 101, 96, 0, 16, 19, 10, 8, 10, 4, 202, 101, 128, 0, 16, 18, 10, 8, 10, 4, 202, 101, 192, 0, 16, 19, 10, 8, 10, 4, 202, 101, 224, 0, 16, 21, 10, 8, 10, 4, 202, 101, 232, 0, 16, 21, 10, 8, 10, 4, 202, 101, 240, 0, 16, 20, 10, 8, 10, 4, 202, 102, 0, 0, 16, 19, 10, 8, 10, 4, 202, 102, 32, 0, 16, 19, 10, 8, 10, 4, 202, 102, 64, 0, 16, 18, 10, 8, 10, 4, 202, 102, 128, 0, 16, 21, 10, 8, 10, 4, 202, 102, 136, 0, 16, 21, 10, 8, 10, 4, 202, 102, 144, 0, 16, 20, 10, 8, 10, 4, 202, 102, 160, 0, 16, 19, 10, 8, 10, 4, 202, 102, 192, 0, 16, 21, 10, 8, 10, 4, 202, 102, 200, 0, 16, 21, 10, 8, 10, 4, 202, 102, 208, 0, 16, 20, 10, 8, 10, 4, 202, 102, 224, 0, 16, 21, 10, 8, 10, 4, 202, 102, 232, 0, 16, 21, 10, 8, 10, 4, 202, 102, 240, 0, 16, 20, 10, 8, 10, 4, 202, 103, 0, 0, 16, 21, 10, 8, 10, 4, 202, 103, 8, 0, 16, 21, 10, 8, 10, 4, 202, 103, 16, 0, 16, 20, 10, 8, 10, 4, 202, 103, 32, 0, 16, 19, 10, 8, 10, 4, 202, 103, 64, 0, 16, 19, 10, 8, 10, 4, 202, 103, 96, 0, 16, 21, 10, 8, 10, 4, 202, 103, 104, 0, 16, 21, 10, 8, 10, 4, 202, 103, 112, 0, 16, 20, 10, 8, 10, 4, 202, 103, 128, 0, 16, 18, 10, 8, 10, 4, 202, 103, 192, 0, 16, 19, 10, 8, 10, 4, 202, 103, 224, 0, 16, 21, 10, 8, 10, 4, 202, 103, 232, 0, 16, 21, 10, 8, 10, 4, 202, 103, 240, 0, 16, 20, 10, 8, 10, 4, 202, 104, 0, 0, 16, 15, 10, 8, 10, 4, 202, 106, 0, 0, 16, 16, 10, 8, 10, 4, 202, 107, 0, 0, 16, 17, 10, 8, 10, 4, 202, 107, 128, 0, 16, 17, 10, 8, 10, 4, 202, 108, 0, 0, 16, 16, 10, 8, 10, 4, 202, 109, 0, 0, 16, 16, 10, 8, 10, 4, 202, 110, 0, 0, 16, 18, 10, 8, 10, 4, 202, 110, 64, 0, 16, 18, 10, 8, 10, 4, 202, 110, 128, 0, 16, 18, 10, 8, 10, 4, 202, 110, 192, 0, 16, 18, 10, 8, 10, 4, 202, 111, 0, 0, 16, 17, 10, 8, 10, 4, 202, 111, 128, 0, 16, 19, 10, 8, 10, 4, 202, 111, 160, 0, 16, 19, 10, 8, 10, 4, 202, 111, 192, 0, 16, 18, 10, 8, 10, 4, 202, 112, 0, 0, 16, 16, 10, 8, 10, 4, 202, 113, 0, 0, 16, 20, 10, 8, 10, 4, 202, 113, 16, 0, 16, 20, 10, 8, 10, 4, 202, 113, 32, 0, 16, 19, 10, 8, 10, 4, 202, 113, 64, 0, 16, 18, 10, 8, 10, 4, 202, 113, 128, 0, 16, 18, 10, 8, 10, 4, 202, 113, 192, 0, 16, 19, 10, 8, 10, 4, 202, 113, 224, 0, 16, 20, 10, 8, 10, 4, 202, 113, 240, 0, 16, 20, 10, 8, 10, 4, 202, 114, 0, 0, 16, 19, 10, 8, 10, 4, 202, 114, 32, 0, 16, 19, 10, 8, 10, 4, 202, 114, 64, 0, 16, 18, 10, 8, 10, 4, 202, 114, 128, 0, 16, 17, 10, 8, 10, 4, 202, 115, 0, 0, 16, 19, 10, 8, 10, 4, 202, 115, 32, 0, 16, 19, 10, 8, 10, 4, 202, 115, 64, 0, 16, 18, 10, 8, 10, 4, 202, 115, 128, 0, 16, 17, 10, 8, 10, 4, 202, 116, 0, 0, 16, 19, 10, 8, 10, 4, 202, 116, 32, 0, 16, 20, 10, 8, 10, 4, 202, 116, 48, 0, 16, 20, 10, 8, 10, 4, 202, 116, 64, 0, 16, 19, 10, 8, 10, 4, 202, 116, 96, 0, 16, 19, 10, 8, 10, 4, 202, 116, 128, 0, 16, 17, 10, 8, 10, 4, 202, 117, 0, 0, 16, 18, 10, 8, 10, 4, 202, 117, 64, 0, 16, 18, 10, 8, 10, 4, 202, 117, 128, 0, 16, 17, 10, 8, 10, 4, 202, 118, 0, 0, 16, 19, 10, 8, 10, 4, 202, 118, 32, 0, 16, 19, 10, 8, 10, 4, 202, 118, 64, 0, 16, 18, 10, 8, 10, 4, 202, 118, 128, 0, 16, 17, 10, 8, 10, 4, 202, 119, 0, 0, 16, 19, 10, 8, 10, 4, 202, 119, 32, 0, 16, 19, 10, 8, 10, 4, 202, 119, 64, 0, 16, 20, 10, 8, 10, 4, 202, 119, 80, 0, 16, 20, 10, 8, 10, 4, 202, 119, 96, 0, 16, 19, 10, 8, 10, 4, 202, 119, 128, 0, 16, 17, 10, 8, 10, 4, 202, 120, 0, 0, 16, 18, 10, 8, 10, 4, 202, 120, 64, 0, 16, 18, 10, 8, 10, 4, 202, 120, 128, 0, 16, 17, 10, 8, 10, 4, 202, 121, 0, 0, 16, 16, 10, 8, 10, 4, 202, 122, 0, 0, 16, 21, 10, 8, 10, 4, 202, 122, 32, 0, 16, 21, 10, 8, 10, 4, 202, 122, 64, 0, 16, 19, 10, 8, 10, 4, 202, 122, 112, 0, 16, 21, 10, 8, 10, 4, 202, 122, 120, 0, 16, 21, 10, 8, 10, 4, 202, 122, 128, 0, 16, 24, 10, 8, 10, 4, 202, 122, 132, 0, 16, 24, 10, 8, 10, 4, 202, 123, 96, 0, 16, 20, 10, 8, 10, 4, 202, 123, 116, 0, 16, 22, 10, 8, 10, 4, 202, 123, 120, 0, 16, 22, 10, 8, 10, 4, 202, 124, 16, 0, 16, 21, 10, 8, 10, 4, 202, 124, 24, 0, 16, 22, 10, 8, 10, 4, 202, 125, 107, 0, 16, 24, 10, 8, 10, 4, 202, 125, 109, 0, 16, 24, 10, 8, 10, 4, 202, 125, 112, 0, 16, 20, 10, 8, 10, 4, 202, 125, 176, 0, 16, 20, 10, 8, 10, 4, 202, 127, 0, 0, 16, 23, 10, 8, 10, 4, 202, 127, 2, 0, 16, 24, 10, 8, 10, 4, 202, 127, 3, 0, 16, 24, 10, 8, 10, 4, 202, 127, 4, 0, 16, 24, 10, 8, 10, 4, 202, 127, 5, 0, 16, 24, 10, 8, 10, 4, 202, 127, 6, 0, 16, 23, 10, 8, 10, 4, 202, 127, 12, 0, 16, 22, 10, 8, 10, 4, 202, 127, 16, 0, 16, 20, 10, 8, 10, 4, 202, 127, 40, 0, 16, 21, 10, 8, 10, 4, 202, 127, 48, 0, 16, 20, 10, 8, 10, 4, 202, 127, 112, 0, 16, 20, 10, 8, 10, 4, 202, 127, 128, 0, 16, 20, 10, 8, 10, 4, 202, 127, 144, 0, 16, 20, 10, 8, 10, 4, 202, 127, 160, 0, 16, 21, 10, 8, 10, 4, 202, 127, 192, 0, 16, 23, 10, 8, 10, 4, 202, 127, 194, 0, 16, 23, 10, 8, 10, 4, 202, 127, 196, 0, 16, 22, 10, 8, 10, 4, 202, 127, 200, 0, 16, 21, 10, 8, 10, 4, 202, 127, 208, 0, 16, 24, 10, 8, 10, 4, 202, 127, 209, 0, 16, 24, 10, 8, 10, 4, 202, 127, 212, 0, 16, 22, 10, 8, 10, 4, 202, 127, 216, 0, 16, 21, 10, 8, 10, 4, 202, 127, 224, 0, 16, 19, 10, 8, 10, 4, 202, 129, 208, 0, 16, 24, 10, 8, 10, 4, 202, 130, 0, 0, 16, 19, 10, 8, 10, 4, 202, 130, 39, 0, 16, 24, 10, 8, 10, 4, 202, 130, 224, 0, 16, 19, 10, 8, 10, 4, 202, 131, 16, 0, 16, 21, 10, 8, 10, 4, 202, 131, 48, 0, 16, 20, 10, 8, 10, 4, 202, 131, 208, 0, 16, 20, 10, 8, 10, 4, 202, 133, 32, 0, 16, 20, 10, 8, 10, 4, 202, 134, 58, 0, 16, 24, 10, 8, 10, 4, 202, 134, 128, 0, 16, 20, 10, 8, 10, 4, 202, 134, 208, 0, 16, 22, 10, 8, 10, 4, 202, 134, 212, 0, 16, 22, 10, 8, 10, 4, 202, 134, 216, 0, 16, 22, 10, 8, 10, 4, 202, 134, 220, 0, 16, 22, 10, 8, 10, 4, 202, 136, 48, 0, 16, 20, 10, 8, 10, 4, 202, 136, 208, 0, 16, 20, 10, 8, 10, 4, 202, 136, 224, 0, 16, 20, 10, 8, 10, 4, 202, 136, 248, 0, 16, 22, 10, 8, 10, 4, 202, 137, 231, 0, 16, 24, 10, 8, 10, 4, 202, 140, 140, 0, 16, 22, 10, 8, 10, 4, 202, 140, 144, 0, 16, 22, 10, 8, 10, 4, 202, 140, 148, 0, 16, 22, 10, 8, 10, 4, 202, 140, 152, 0, 16, 22, 10, 8, 10, 4, 202, 140, 156, 0, 16, 22, 10, 8, 10, 4, 202, 141, 160, 0, 16, 19, 10, 8, 10, 4, 202, 142, 16, 0, 16, 20, 10, 8, 10, 4, 202, 143, 4, 0, 16, 22, 10, 8, 10, 4, 202, 143, 16, 0, 16, 20, 10, 8, 10, 4, 202, 143, 32, 0, 16, 20, 10, 8, 10, 4, 202, 143, 56, 0, 16, 21, 10, 8, 10, 4, 202, 143, 100, 0, 16, 22, 10, 8, 10, 4, 202, 143, 104, 0, 16, 22, 10, 8, 10, 4, 202, 144, 196, 0, 16, 22, 10, 8, 10, 4, 202, 146, 160, 0, 16, 20, 10, 8, 10, 4, 202, 146, 186, 0, 16, 24, 10, 8, 10, 4, 202, 146, 188, 0, 16, 22, 10, 8, 10, 4, 202, 146, 196, 0, 16, 22, 10, 8, 10, 4, 202, 146, 200, 0, 16, 21, 10, 8, 10, 4, 202, 147, 144, 0, 16, 20, 10, 8, 10, 4, 202, 148, 32, 0, 16, 20, 10, 8, 10, 4, 202, 148, 64, 0, 16, 19, 10, 8, 10, 4, 202, 148, 96, 0, 16, 19, 10, 8, 10, 4, 202, 149, 32, 0, 16, 19, 10, 8, 10, 4, 202, 149, 160, 0, 16, 19, 10, 8, 10, 4, 202, 149, 224, 0, 16, 19, 10, 8, 10, 4, 202, 150, 16, 0, 16, 20, 10, 8, 10, 4, 202, 150, 32, 0, 16, 20, 10, 8, 10, 4, 202, 150, 56, 0, 16, 22, 10, 8, 10, 4, 202, 150, 192, 0, 16, 20, 10, 8, 10, 4, 202, 150, 224, 0, 16, 19, 10, 8, 10, 4, 202, 151, 0, 0, 16, 22, 10, 8, 10, 4, 202, 151, 33, 0, 16, 24, 10, 8, 10, 4, 202, 151, 128, 0, 16, 19, 10, 8, 10, 4, 202, 152, 176, 0, 16, 20, 10, 8, 10, 4, 202, 153, 0, 0, 16, 22, 10, 8, 10, 4, 202, 153, 7, 0, 16, 24, 10, 8, 10, 4, 202, 153, 48, 0, 16, 20, 10, 8, 10, 4, 202, 157, 192, 0, 16, 19, 10, 8, 10, 4, 202, 158, 160, 0, 16, 19, 10, 8, 10, 4, 202, 158, 242, 0, 16, 24, 10, 8, 10, 4, 202, 160, 140, 0, 16, 22, 10, 8, 10, 4, 202, 160, 156, 0, 16, 22, 10, 8, 10, 4, 202, 160, 176, 0, 16, 20, 10, 8, 10, 4, 202, 162, 67, 0, 16, 24, 10, 8, 10, 4, 202, 162, 75, 0, 16, 24, 10, 8, 10, 4, 202, 164, 0, 0, 16, 20, 10, 8, 10, 4, 202, 164, 96, 0, 16, 19, 10, 8, 10, 4, 202, 165, 96, 0, 16, 20, 10, 8, 10, 4, 202, 165, 176, 0, 16, 20, 10, 8, 10, 4, 202, 165, 208, 0, 16, 20, 10, 8, 10, 4, 202, 165, 239, 0, 16, 24, 10, 8, 10, 4, 202, 165, 240, 0, 16, 23, 10, 8, 10, 4, 202, 165, 243, 0, 16, 24, 10, 8, 10, 4, 202, 165, 245, 0, 16, 24, 10, 8, 10, 4, 202, 165, 251, 0, 16, 24, 10, 8, 10, 4, 202, 165, 252, 0, 16, 22, 10, 8, 10, 4, 202, 166, 224, 0, 16, 19, 10, 8, 10, 4, 202, 168, 80, 0, 16, 22, 10, 8, 10, 4, 202, 168, 128, 0, 16, 22, 10, 8, 10, 4, 202, 168, 132, 0, 16, 22, 10, 8, 10, 4, 202, 168, 136, 0, 16, 22, 10, 8, 10, 4, 202, 168, 140, 0, 16, 22, 10, 8, 10, 4, 202, 168, 160, 0, 16, 20, 10, 8, 10, 4, 202, 168, 176, 0, 16, 20, 10, 8, 10, 4, 202, 170, 128, 0, 16, 19, 10, 8, 10, 4, 202, 170, 216, 0, 16, 21, 10, 8, 10, 4, 202, 170, 224, 0, 16, 19, 10, 8, 10, 4, 202, 171, 216, 0, 16, 21, 10, 8, 10, 4, 202, 171, 232, 0, 16, 24, 10, 8, 10, 4, 202, 171, 235, 0, 16, 24, 10, 8, 10, 4, 202, 172, 0, 0, 16, 22, 10, 8, 10, 4, 202, 172, 7, 0, 16, 24, 10, 8, 10, 4, 202, 173, 0, 0, 16, 22, 10, 8, 10, 4, 202, 173, 6, 0, 16, 24, 10, 8, 10, 4, 202, 173, 8, 0, 16, 21, 10, 8, 10, 4, 202, 173, 112, 0, 16, 22, 10, 8, 10, 4, 202, 173, 224, 0, 16, 19, 10, 8, 10, 4, 202, 174, 64, 0, 16, 20, 10, 8, 10, 4, 202, 174, 124, 0, 16, 22, 10, 8, 10, 4, 202, 176, 224, 0, 16, 19, 10, 8, 10, 4, 202, 179, 160, 0, 16, 22, 10, 8, 10, 4, 202, 179, 164, 0, 16, 22, 10, 8, 10, 4, 202, 179, 168, 0, 16, 22, 10, 8, 10, 4, 202, 179, 172, 0, 16, 22, 10, 8, 10, 4, 202, 179, 240, 0, 16, 20, 10, 8, 10, 4, 202, 180, 128, 0, 16, 19, 10, 8, 10, 4, 202, 180, 208, 0, 16, 21, 10, 8, 10, 4, 202, 181, 8, 0, 16, 22, 10, 8, 10, 4, 202, 181, 28, 0, 16, 22, 10, 8, 10, 4, 202, 181, 112, 0, 16, 20, 10, 8, 10, 4, 202, 182, 32, 0, 16, 20, 10, 8, 10, 4, 202, 182, 192, 0, 16, 19, 10, 8, 10, 4, 202, 189, 0, 0, 16, 18, 10, 8, 10, 4, 202, 189, 80, 0, 16, 20, 10, 8, 10, 4, 202, 189, 184, 0, 16, 21, 10, 8, 10, 4, 202, 191, 0, 0, 16, 24, 10, 8, 10, 4, 202, 191, 68, 0, 16, 22, 10, 8, 10, 4, 202, 191, 72, 0, 16, 21, 10, 8, 10, 4, 202, 191, 80, 0, 16, 20, 10, 8, 10, 4, 202, 192, 0, 0, 16, 13, 10, 8, 10, 4, 202, 200, 0, 0, 16, 14, 10, 8, 10, 4, 202, 204, 0, 0, 16, 14, 10, 8, 10, 4, 203, 0, 4, 0, 16, 22, 10, 8, 10, 4, 203, 0, 10, 0, 16, 23, 10, 8, 10, 4, 203, 0, 18, 0, 16, 24, 10, 8, 10, 4, 203, 0, 24, 0, 16, 24, 10, 8, 10, 4, 203, 0, 42, 0, 16, 23, 10, 8, 10, 4, 203, 0, 45, 0, 16, 24, 10, 8, 10, 4, 203, 0, 46, 0, 16, 23, 10, 8, 10, 4, 203, 0, 81, 0, 16, 24, 10, 8, 10, 4, 203, 0, 82, 0, 16, 23, 10, 8, 10, 4, 203, 0, 90, 0, 16, 23, 10, 8, 10, 4, 203, 0, 96, 0, 16, 23, 10, 8, 10, 4, 203, 0, 104, 0, 16, 21, 10, 8, 10, 4, 203, 0, 114, 0, 16, 23, 10, 8, 10, 4, 203, 0, 122, 0, 16, 24, 10, 8, 10, 4, 203, 0, 128, 0, 16, 24, 10, 8, 10, 4, 203, 0, 130, 0, 16, 23, 10, 8, 10, 4, 203, 0, 132, 0, 16, 22, 10, 8, 10, 4, 203, 0, 137, 0, 16, 24, 10, 8, 10, 4, 203, 0, 142, 0, 16, 24, 10, 8, 10, 4, 203, 0, 144, 0, 16, 24, 10, 8, 10, 4, 203, 0, 146, 0, 16, 24, 10, 8, 10, 4, 203, 0, 148, 0, 16, 24, 10, 8, 10, 4, 203, 0, 150, 0, 16, 23, 10, 8, 10, 4, 203, 0, 152, 0, 16, 24, 10, 8, 10, 4, 203, 0, 177, 0, 16, 24, 10, 8, 10, 4, 203, 0, 224, 0, 16, 24, 10, 8, 10, 4, 203, 1, 4, 0, 16, 22, 10, 8, 10, 4, 203, 1, 18, 0, 16, 24, 10, 8, 10, 4, 203, 1, 26, 0, 16, 23, 10, 8, 10, 4, 203, 1, 65, 0, 16, 24, 10, 8, 10, 4, 203, 1, 66, 0, 16, 23, 10, 8, 10, 4, 203, 1, 70, 0, 16, 23, 10, 8, 10, 4, 203, 1, 76, 0, 16, 23, 10, 8, 10, 4, 203, 1, 90, 0, 16, 24, 10, 8, 10, 4, 203, 1, 97, 0, 16, 24, 10, 8, 10, 4, 203, 1, 98, 0, 16, 23, 10, 8, 10, 4, 203, 1, 100, 0, 16, 22, 10, 8, 10, 4, 203, 1, 108, 0, 16, 24, 10, 8, 10, 4, 203, 1, 253, 0, 16, 24, 10, 8, 10, 4, 203, 1, 254, 0, 16, 24, 10, 8, 10, 4, 203, 2, 64, 0, 16, 21, 10, 8, 10, 4, 203, 2, 73, 0, 16, 24, 10, 8, 10, 4, 203, 2, 112, 0, 16, 21, 10, 8, 10, 4, 203, 2, 126, 0, 16, 23, 10, 8, 10, 4, 203, 2, 140, 0, 16, 24, 10, 8, 10, 4, 203, 2, 150, 0, 16, 24, 10, 8, 10, 4, 203, 2, 152, 0, 16, 22, 10, 8, 10, 4, 203, 2, 156, 0, 16, 23, 10, 8, 10, 4, 203, 2, 160, 0, 16, 21, 10, 8, 10, 4, 203, 2, 180, 0, 16, 23, 10, 8, 10, 4, 203, 2, 196, 0, 16, 23, 10, 8, 10, 4, 203, 2, 209, 0, 16, 24, 10, 8, 10, 4, 203, 2, 214, 0, 16, 23, 10, 8, 10, 4, 203, 2, 226, 0, 16, 23, 10, 8, 10, 4, 203, 2, 229, 0, 16, 24, 10, 8, 10, 4, 203, 2, 236, 0, 16, 23, 10, 8, 10, 4, 203, 3, 68, 0, 16, 24, 10, 8, 10, 4, 203, 3, 72, 0, 16, 23, 10, 8, 10, 4, 203, 3, 75, 0, 16, 24, 10, 8, 10, 4, 203, 3, 80, 0, 16, 21, 10, 8, 10, 4, 203, 3, 96, 0, 16, 22, 10, 8, 10, 4, 203, 3, 105, 0, 16, 24, 10, 8, 10, 4, 203, 3, 112, 0, 16, 21, 10, 8, 10, 4, 203, 3, 120, 0, 16, 24, 10, 8, 10, 4, 203, 3, 123, 0, 16, 24, 10, 8, 10, 4, 203, 3, 135, 0, 16, 24, 10, 8, 10, 4, 203, 3, 139, 0, 16, 24, 10, 8, 10, 4, 203, 3, 143, 0, 16, 24, 10, 8, 10, 4, 203, 4, 132, 0, 16, 23, 10, 8, 10, 4, 203, 4, 134, 0, 16, 24, 10, 8, 10, 4, 203, 4, 151, 0, 16, 24, 10, 8, 10, 4, 203, 4, 152, 0, 16, 22, 10, 8, 10, 4, 203, 4, 174, 0, 16, 23, 10, 8, 10, 4, 203, 4, 180, 0, 16, 24, 10, 8, 10, 4, 203, 4, 186, 0, 16, 24, 10, 8, 10, 4, 203, 4, 205, 0, 16, 24, 10, 8, 10, 4, 203, 4, 208, 0, 16, 22, 10, 8, 10, 4, 203, 4, 227, 0, 16, 24, 10, 8, 10, 4, 203, 4, 230, 0, 16, 23, 10, 8, 10, 4, 203, 5, 4, 0, 16, 23, 10, 8, 10, 4, 203, 5, 7, 0, 16, 24, 10, 8, 10, 4, 203, 5, 8, 0, 16, 23, 10, 8, 10, 4, 203, 5, 11, 0, 16, 24, 10, 8, 10, 4, 203, 5, 21, 0, 16, 24, 10, 8, 10, 4, 203, 5, 22, 0, 16, 24, 10, 8, 10, 4, 203, 5, 44, 0, 16, 24, 10, 8, 10, 4, 203, 5, 46, 0, 16, 23, 10, 8, 10, 4, 203, 5, 52, 0, 16, 22, 10, 8, 10, 4, 203, 5, 56, 0, 16, 23, 10, 8, 10, 4, 203, 5, 60, 0, 16, 23, 10, 8, 10, 4, 203, 5, 114, 0, 16, 23, 10, 8, 10, 4, 203, 5, 118, 0, 16, 24, 10, 8, 10, 4, 203, 5, 120, 0, 16, 24, 10, 8, 10, 4, 203, 5, 172, 0, 16, 24, 10, 8, 10, 4, 203, 5, 180, 0, 16, 23, 10, 8, 10, 4, 203, 5, 182, 0, 16, 24, 10, 8, 10, 4, 203, 5, 185, 0, 16, 24, 10, 8, 10, 4, 203, 5, 186, 0, 16, 24, 10, 8, 10, 4, 203, 5, 188, 0, 16, 23, 10, 8, 10, 4, 203, 5, 190, 0, 16, 24, 10, 8, 10, 4, 203, 5, 195, 0, 16, 24, 10, 8, 10, 4, 203, 5, 214, 0, 16, 23, 10, 8, 10, 4, 203, 5, 218, 0, 16, 23, 10, 8, 10, 4, 203, 6, 131, 0, 16, 24, 10, 8, 10, 4, 203, 6, 136, 0, 16, 24, 10, 8, 10, 4, 203, 6, 138, 0, 16, 23, 10, 8, 10, 4, 203, 6, 142, 0, 16, 24, 10, 8, 10, 4, 203, 6, 150, 0, 16, 23, 10, 8, 10, 4, 203, 6, 157, 0, 16, 24, 10, 8, 10, 4, 203, 6, 159, 0, 16, 24, 10, 8, 10, 4, 203, 6, 224, 0, 16, 20, 10, 8, 10, 4, 203, 6, 248, 0, 16, 23, 10, 8, 10, 4, 203, 7, 129, 0, 16, 24, 10, 8, 10, 4, 203, 7, 138, 0, 16, 23, 10, 8, 10, 4, 203, 7, 147, 0, 16, 24, 10, 8, 10, 4, 203, 7, 150, 0, 16, 23, 10, 8, 10, 4, 203, 7, 158, 0, 16, 24, 10, 8, 10, 4, 203, 7, 192, 0, 16, 23, 10, 8, 10, 4, 203, 7, 200, 0, 16, 24, 10, 8, 10, 4, 203, 8, 0, 0, 16, 24, 10, 8, 10, 4, 203, 8, 8, 0, 16, 24, 10, 8, 10, 4, 203, 8, 23, 0, 16, 24, 10, 8, 10, 4, 203, 8, 24, 0, 16, 21, 10, 8, 10, 4, 203, 8, 70, 0, 16, 24, 10, 8, 10, 4, 203, 8, 82, 0, 16, 24, 10, 8, 10, 4, 203, 8, 86, 0, 16, 23, 10, 8, 10, 4, 203, 8, 91, 0, 16, 24, 10, 8, 10, 4, 203, 8, 110, 0, 16, 23, 10, 8, 10, 4, 203, 8, 115, 0, 16, 24, 10, 8, 10, 4, 203, 8, 166, 0, 16, 23, 10, 8, 10, 4, 203, 8, 169, 0, 16, 24, 10, 8, 10, 4, 203, 8, 173, 0, 16, 24, 10, 8, 10, 4, 203, 8, 184, 0, 16, 24, 10, 8, 10, 4, 203, 8, 186, 0, 16, 23, 10, 8, 10, 4, 203, 8, 190, 0, 16, 23, 10, 8, 10, 4, 203, 8, 192, 0, 16, 24, 10, 8, 10, 4, 203, 8, 197, 0, 16, 24, 10, 8, 10, 4, 203, 8, 198, 0, 16, 23, 10, 8, 10, 4, 203, 8, 203, 0, 16, 24, 10, 8, 10, 4, 203, 8, 209, 0, 16, 24, 10, 8, 10, 4, 203, 8, 210, 0, 16, 23, 10, 8, 10, 4, 203, 8, 212, 0, 16, 22, 10, 8, 10, 4, 203, 8, 217, 0, 16, 24, 10, 8, 10, 4, 203, 8, 220, 0, 16, 24, 10, 8, 10, 4, 203, 9, 32, 0, 16, 24, 10, 8, 10, 4, 203, 9, 36, 0, 16, 23, 10, 8, 10, 4, 203, 9, 57, 0, 16, 24, 10, 8, 10, 4, 203, 9, 63, 0, 16, 24, 10, 8, 10, 4, 203, 9, 65, 0, 16, 24, 10, 8, 10, 4, 203, 9, 70, 0, 16, 23, 10, 8, 10, 4, 203, 9, 72, 0, 16, 24, 10, 8, 10, 4, 203, 9, 75, 0, 16, 24, 10, 8, 10, 4, 203, 9, 76, 0, 16, 23, 10, 8, 10, 4, 203, 9, 96, 0, 16, 22, 10, 8, 10, 4, 203, 9, 100, 0, 16, 23, 10, 8, 10, 4, 203, 9, 108, 0, 16, 24, 10, 8, 10, 4, 203, 9, 158, 0, 16, 24, 10, 8, 10, 4, 203, 10, 34, 0, 16, 24, 10, 8, 10, 4, 203, 10, 56, 0, 16, 24, 10, 8, 10, 4, 203, 10, 74, 0, 16, 23, 10, 8, 10, 4, 203, 10, 84, 0, 16, 22, 10, 8, 10, 4, 203, 10, 88, 0, 16, 24, 10, 8, 10, 4, 203, 10, 95, 0, 16, 24, 10, 8, 10, 4, 203, 10, 125, 0, 16, 24, 10, 8, 10, 4, 203, 11, 70, 0, 16, 24, 10, 8, 10, 4, 203, 11, 76, 0, 16, 22, 10, 8, 10, 4, 203, 11, 82, 0, 16, 24, 10, 8, 10, 4, 203, 11, 84, 0, 16, 22, 10, 8, 10, 4, 203, 11, 100, 0, 16, 22, 10, 8, 10, 4, 203, 11, 109, 0, 16, 24, 10, 8, 10, 4, 203, 11, 117, 0, 16, 24, 10, 8, 10, 4, 203, 11, 122, 0, 16, 24, 10, 8, 10, 4, 203, 11, 126, 0, 16, 24, 10, 8, 10, 4, 203, 11, 136, 0, 16, 22, 10, 8, 10, 4, 203, 11, 141, 0, 16, 24, 10, 8, 10, 4, 203, 11, 142, 0, 16, 23, 10, 8, 10, 4, 203, 11, 180, 0, 16, 22, 10, 8, 10, 4, 203, 11, 208, 0, 16, 22, 10, 8, 10, 4, 203, 12, 16, 0, 16, 24, 10, 8, 10, 4, 203, 12, 19, 0, 16, 24, 10, 8, 10, 4, 203, 12, 24, 0, 16, 24, 10, 8, 10, 4, 203, 12, 57, 0, 16, 24, 10, 8, 10, 4, 203, 12, 65, 0, 16, 24, 10, 8, 10, 4, 203, 12, 66, 0, 16, 24, 10, 8, 10, 4, 203, 12, 70, 0, 16, 23, 10, 8, 10, 4, 203, 12, 87, 0, 16, 24, 10, 8, 10, 4, 203, 12, 88, 0, 16, 21, 10, 8, 10, 4, 203, 12, 100, 0, 16, 23, 10, 8, 10, 4, 203, 12, 103, 0, 16, 24, 10, 8, 10, 4, 203, 12, 114, 0, 16, 24, 10, 8, 10, 4, 203, 12, 118, 0, 16, 24, 10, 8, 10, 4, 203, 12, 130, 0, 16, 24, 10, 8, 10, 4, 203, 12, 137, 0, 16, 24, 10, 8, 10, 4, 203, 12, 196, 0, 16, 22, 10, 8, 10, 4, 203, 12, 200, 0, 16, 21, 10, 8, 10, 4, 203, 12, 211, 0, 16, 24, 10, 8, 10, 4, 203, 12, 219, 0, 16, 24, 10, 8, 10, 4, 203, 12, 226, 0, 16, 24, 10, 8, 10, 4, 203, 12, 240, 0, 16, 22, 10, 8, 10, 4, 203, 13, 18, 0, 16, 24, 10, 8, 10, 4, 203, 13, 24, 0, 16, 24, 10, 8, 10, 4, 203, 13, 44, 0, 16, 23, 10, 8, 10, 4, 203, 13, 80, 0, 16, 21, 10, 8, 10, 4, 203, 13, 88, 0, 16, 23, 10, 8, 10, 4, 203, 13, 92, 0, 16, 22, 10, 8, 10, 4, 203, 13, 173, 0, 16, 24, 10, 8, 10, 4, 203, 13, 224, 0, 16, 23, 10, 8, 10, 4, 203, 13, 227, 0, 16, 24, 10, 8, 10, 4, 203, 13, 233, 0, 16, 24, 10, 8, 10, 4, 203, 14, 24, 0, 16, 22, 10, 8, 10, 4, 203, 14, 33, 0, 16, 24, 10, 8, 10, 4, 203, 14, 56, 0, 16, 24, 10, 8, 10, 4, 203, 14, 61, 0, 16, 24, 10, 8, 10, 4, 203, 14, 62, 0, 16, 24, 10, 8, 10, 4, 203, 14, 104, 0, 16, 24, 10, 8, 10, 4, 203, 14, 114, 0, 16, 23, 10, 8, 10, 4, 203, 14, 118, 0, 16, 24, 10, 8, 10, 4, 203, 14, 162, 0, 16, 24, 10, 8, 10, 4, 203, 14, 184, 0, 16, 21, 10, 8, 10, 4, 203, 14, 192, 0, 16, 24, 10, 8, 10, 4, 203, 14, 194, 0, 16, 23, 10, 8, 10, 4, 203, 14, 214, 0, 16, 24, 10, 8, 10, 4, 203, 14, 231, 0, 16, 24, 10, 8, 10, 4, 203, 14, 246, 0, 16, 24, 10, 8, 10, 4, 203, 15, 0, 0, 16, 20, 10, 8, 10, 4, 203, 15, 20, 0, 16, 23, 10, 8, 10, 4, 203, 15, 22, 0, 16, 24, 10, 8, 10, 4, 203, 15, 87, 0, 16, 24, 10, 8, 10, 4, 203, 15, 88, 0, 16, 23, 10, 8, 10, 4, 203, 15, 105, 0, 16, 24, 10, 8, 10, 4, 203, 15, 112, 0, 16, 21, 10, 8, 10, 4, 203, 15, 130, 0, 16, 23, 10, 8, 10, 4, 203, 15, 149, 0, 16, 24, 10, 8, 10, 4, 203, 15, 151, 0, 16, 24, 10, 8, 10, 4, 203, 15, 156, 0, 16, 22, 10, 8, 10, 4, 203, 15, 174, 0, 16, 24, 10, 8, 10, 4, 203, 15, 227, 0, 16, 24, 10, 8, 10, 4, 203, 15, 232, 0, 16, 21, 10, 8, 10, 4, 203, 15, 240, 0, 16, 23, 10, 8, 10, 4, 203, 15, 246, 0, 16, 24, 10, 8, 10, 4, 203, 16, 10, 0, 16, 24, 10, 8, 10, 4, 203, 16, 12, 0, 16, 23, 10, 8, 10, 4, 203, 16, 16, 0, 16, 21, 10, 8, 10, 4, 203, 16, 27, 0, 16, 24, 10, 8, 10, 4, 203, 16, 38, 0, 16, 24, 10, 8, 10, 4, 203, 16, 49, 0, 16, 24, 10, 8, 10, 4, 203, 16, 50, 0, 16, 23, 10, 8, 10, 4, 203, 16, 58, 0, 16, 24, 10, 8, 10, 4, 203, 16, 63, 0, 16, 24, 10, 8, 10, 4, 203, 16, 133, 0, 16, 24, 10, 8, 10, 4, 203, 16, 161, 0, 16, 24, 10, 8, 10, 4, 203, 16, 162, 0, 16, 24, 10, 8, 10, 4, 203, 16, 186, 0, 16, 23, 10, 8, 10, 4, 203, 16, 228, 0, 16, 24, 10, 8, 10, 4, 203, 16, 238, 0, 16, 24, 10, 8, 10, 4, 203, 16, 240, 0, 16, 24, 10, 8, 10, 4, 203, 16, 245, 0, 16, 24, 10, 8, 10, 4, 203, 17, 2, 0, 16, 24, 10, 8, 10, 4, 203, 17, 18, 0, 16, 24, 10, 8, 10, 4, 203, 17, 28, 0, 16, 24, 10, 8, 10, 4, 203, 17, 39, 0, 16, 24, 10, 8, 10, 4, 203, 17, 56, 0, 16, 24, 10, 8, 10, 4, 203, 17, 74, 0, 16, 23, 10, 8, 10, 4, 203, 17, 88, 0, 16, 23, 10, 8, 10, 4, 203, 17, 136, 0, 16, 24, 10, 8, 10, 4, 203, 17, 164, 0, 16, 24, 10, 8, 10, 4, 203, 17, 187, 0, 16, 24, 10, 8, 10, 4, 203, 17, 190, 0, 16, 23, 10, 8, 10, 4, 203, 17, 231, 0, 16, 24, 10, 8, 10, 4, 203, 17, 233, 0, 16, 24, 10, 8, 10, 4, 203, 17, 248, 0, 16, 24, 10, 8, 10, 4, 203, 17, 249, 0, 16, 24, 10, 8, 10, 4, 203, 17, 255, 0, 16, 24, 10, 8, 10, 4, 203, 18, 2, 0, 16, 23, 10, 8, 10, 4, 203, 18, 4, 0, 16, 24, 10, 8, 10, 4, 203, 18, 7, 0, 16, 24, 10, 8, 10, 4, 203, 18, 31, 0, 16, 24, 10, 8, 10, 4, 203, 18, 37, 0, 16, 24, 10, 8, 10, 4, 203, 18, 48, 0, 16, 23, 10, 8, 10, 4, 203, 18, 52, 0, 16, 24, 10, 8, 10, 4, 203, 18, 72, 0, 16, 22, 10, 8, 10, 4, 203, 18, 80, 0, 16, 23, 10, 8, 10, 4, 203, 18, 87, 0, 16, 24, 10, 8, 10, 4, 203, 18, 100, 0, 16, 23, 10, 8, 10, 4, 203, 18, 105, 0, 16, 24, 10, 8, 10, 4, 203, 18, 107, 0, 16, 24, 10, 8, 10, 4, 203, 18, 110, 0, 16, 24, 10, 8, 10, 4, 203, 18, 129, 0, 16, 24, 10, 8, 10, 4, 203, 18, 131, 0, 16, 24, 10, 8, 10, 4, 203, 18, 132, 0, 16, 23, 10, 8, 10, 4, 203, 18, 144, 0, 16, 24, 10, 8, 10, 4, 203, 18, 153, 0, 16, 24, 10, 8, 10, 4, 203, 18, 199, 0, 16, 24, 10, 8, 10, 4, 203, 18, 208, 0, 16, 24, 10, 8, 10, 4, 203, 18, 211, 0, 16, 24, 10, 8, 10, 4, 203, 18, 215, 0, 16, 24, 10, 8, 10, 4, 203, 19, 1, 0, 16, 24, 10, 8, 10, 4, 203, 19, 18, 0, 16, 24, 10, 8, 10, 4, 203, 19, 24, 0, 16, 24, 10, 8, 10, 4, 203, 19, 30, 0, 16, 24, 10, 8, 10, 4, 203, 19, 32, 0, 16, 21, 10, 8, 10, 4, 203, 19, 41, 0, 16, 24, 10, 8, 10, 4, 203, 19, 44, 0, 16, 23, 10, 8, 10, 4, 203, 19, 46, 0, 16, 24, 10, 8, 10, 4, 203, 19, 58, 0, 16, 24, 10, 8, 10, 4, 203, 19, 60, 0, 16, 23, 10, 8, 10, 4, 203, 19, 64, 0, 16, 24, 10, 8, 10, 4, 203, 19, 68, 0, 16, 24, 10, 8, 10, 4, 203, 19, 72, 0, 16, 24, 10, 8, 10, 4, 203, 19, 101, 0, 16, 24, 10, 8, 10, 4, 203, 19, 111, 0, 16, 24, 10, 8, 10, 4, 203, 19, 131, 0, 16, 24, 10, 8, 10, 4, 203, 19, 133, 0, 16, 24, 10, 8, 10, 4, 203, 19, 144, 0, 16, 24, 10, 8, 10, 4, 203, 19, 147, 0, 16, 24, 10, 8, 10, 4, 203, 19, 149, 0, 16, 24, 10, 8, 10, 4, 203, 19, 156, 0, 16, 24, 10, 8, 10, 4, 203, 19, 176, 0, 16, 24, 10, 8, 10, 4, 203, 19, 178, 0, 16, 23, 10, 8, 10, 4, 203, 19, 208, 0, 16, 24, 10, 8, 10, 4, 203, 19, 228, 0, 16, 22, 10, 8, 10, 4, 203, 19, 233, 0, 16, 24, 10, 8, 10, 4, 203, 19, 242, 0, 16, 24, 10, 8, 10, 4, 203, 19, 248, 0, 16, 23, 10, 8, 10, 4, 203, 19, 255, 0, 16, 24, 10, 8, 10, 4, 203, 20, 17, 0, 16, 24, 10, 8, 10, 4, 203, 20, 40, 0, 16, 23, 10, 8, 10, 4, 203, 20, 44, 0, 16, 24, 10, 8, 10, 4, 203, 20, 48, 0, 16, 24, 10, 8, 10, 4, 203, 20, 61, 0, 16, 24, 10, 8, 10, 4, 203, 20, 65, 0, 16, 24, 10, 8, 10, 4, 203, 20, 84, 0, 16, 23, 10, 8, 10, 4, 203, 20, 89, 0, 16, 24, 10, 8, 10, 4, 203, 20, 106, 0, 16, 23, 10, 8, 10, 4, 203, 20, 115, 0, 16, 24, 10, 8, 10, 4, 203, 20, 117, 0, 16, 24, 10, 8, 10, 4, 203, 20, 118, 0, 16, 23, 10, 8, 10, 4, 203, 20, 122, 0, 16, 24, 10, 8, 10, 4, 203, 20, 126, 0, 16, 23, 10, 8, 10, 4, 203, 20, 135, 0, 16, 24, 10, 8, 10, 4, 203, 20, 136, 0, 16, 21, 10, 8, 10, 4, 203, 20, 150, 0, 16, 24, 10, 8, 10, 4, 203, 20, 230, 0, 16, 24, 10, 8, 10, 4, 203, 20, 232, 0, 16, 24, 10, 8, 10, 4, 203, 20, 236, 0, 16, 24, 10, 8, 10, 4, 203, 21, 0, 0, 16, 23, 10, 8, 10, 4, 203, 21, 2, 0, 16, 24, 10, 8, 10, 4, 203, 21, 8, 0, 16, 24, 10, 8, 10, 4, 203, 21, 10, 0, 16, 24, 10, 8, 10, 4, 203, 21, 18, 0, 16, 24, 10, 8, 10, 4, 203, 21, 33, 0, 16, 24, 10, 8, 10, 4, 203, 21, 34, 0, 16, 24, 10, 8, 10, 4, 203, 21, 41, 0, 16, 24, 10, 8, 10, 4, 203, 21, 44, 0, 16, 24, 10, 8, 10, 4, 203, 21, 68, 0, 16, 24, 10, 8, 10, 4, 203, 21, 82, 0, 16, 24, 10, 8, 10, 4, 203, 21, 96, 0, 16, 22, 10, 8, 10, 4, 203, 21, 124, 0, 16, 24, 10, 8, 10, 4, 203, 21, 136, 0, 16, 23, 10, 8, 10, 4, 203, 21, 145, 0, 16, 24, 10, 8, 10, 4, 203, 21, 206, 0, 16, 24, 10, 8, 10, 4, 203, 22, 24, 0, 16, 24, 10, 8, 10, 4, 203, 22, 28, 0, 16, 23, 10, 8, 10, 4, 203, 22, 31, 0, 16, 24, 10, 8, 10, 4, 203, 22, 68, 0, 16, 24, 10, 8, 10, 4, 203, 22, 76, 0, 16, 24, 10, 8, 10, 4, 203, 22, 78, 0, 16, 24, 10, 8, 10, 4, 203, 22, 84, 0, 16, 24, 10, 8, 10, 4, 203, 22, 87, 0, 16, 24, 10, 8, 10, 4, 203, 22, 92, 0, 16, 22, 10, 8, 10, 4, 203, 22, 99, 0, 16, 24, 10, 8, 10, 4, 203, 22, 106, 0, 16, 24, 10, 8, 10, 4, 203, 22, 122, 0, 16, 23, 10, 8, 10, 4, 203, 22, 131, 0, 16, 24, 10, 8, 10, 4, 203, 22, 163, 0, 16, 24, 10, 8, 10, 4, 203, 22, 166, 0, 16, 24, 10, 8, 10, 4, 203, 22, 170, 0, 16, 24, 10, 8, 10, 4, 203, 22, 176, 0, 16, 21, 10, 8, 10, 4, 203, 22, 194, 0, 16, 24, 10, 8, 10, 4, 203, 22, 242, 0, 16, 23, 10, 8, 10, 4, 203, 22, 245, 0, 16, 24, 10, 8, 10, 4, 203, 22, 246, 0, 16, 24, 10, 8, 10, 4, 203, 22, 252, 0, 16, 23, 10, 8, 10, 4, 203, 23, 0, 0, 16, 24, 10, 8, 10, 4, 203, 23, 47, 0, 16, 24, 10, 8, 10, 4, 203, 23, 61, 0, 16, 24, 10, 8, 10, 4, 203, 23, 62, 0, 16, 23, 10, 8, 10, 4, 203, 23, 73, 0, 16, 24, 10, 8, 10, 4, 203, 23, 85, 0, 16, 24, 10, 8, 10, 4, 203, 23, 92, 0, 16, 22, 10, 8, 10, 4, 203, 23, 98, 0, 16, 24, 10, 8, 10, 4, 203, 23, 107, 0, 16, 24, 10, 8, 10, 4, 203, 23, 112, 0, 16, 24, 10, 8, 10, 4, 203, 23, 130, 0, 16, 24, 10, 8, 10, 4, 203, 23, 140, 0, 16, 23, 10, 8, 10, 4, 203, 23, 172, 0, 16, 24, 10, 8, 10, 4, 203, 23, 182, 0, 16, 24, 10, 8, 10, 4, 203, 23, 186, 0, 16, 23, 10, 8, 10, 4, 203, 23, 192, 0, 16, 24, 10, 8, 10, 4, 203, 23, 197, 0, 16, 24, 10, 8, 10, 4, 203, 23, 198, 0, 16, 24, 10, 8, 10, 4, 203, 23, 204, 0, 16, 22, 10, 8, 10, 4, 203, 23, 224, 0, 16, 24, 10, 8, 10, 4, 203, 23, 226, 0, 16, 23, 10, 8, 10, 4, 203, 23, 228, 0, 16, 22, 10, 8, 10, 4, 203, 23, 249, 0, 16, 24, 10, 8, 10, 4, 203, 23, 251, 0, 16, 24, 10, 8, 10, 4, 203, 24, 13, 0, 16, 24, 10, 8, 10, 4, 203, 24, 18, 0, 16, 24, 10, 8, 10, 4, 203, 24, 27, 0, 16, 24, 10, 8, 10, 4, 203, 24, 43, 0, 16, 24, 10, 8, 10, 4, 203, 24, 56, 0, 16, 24, 10, 8, 10, 4, 203, 24, 58, 0, 16, 24, 10, 8, 10, 4, 203, 24, 67, 0, 16, 24, 10, 8, 10, 4, 203, 24, 74, 0, 16, 24, 10, 8, 10, 4, 203, 24, 79, 0, 16, 24, 10, 8, 10, 4, 203, 24, 80, 0, 16, 23, 10, 8, 10, 4, 203, 24, 84, 0, 16, 23, 10, 8, 10, 4, 203, 24, 86, 0, 16, 24, 10, 8, 10, 4, 203, 24, 90, 0, 16, 24, 10, 8, 10, 4, 203, 24, 111, 0, 16, 24, 10, 8, 10, 4, 203, 24, 112, 0, 16, 24, 10, 8, 10, 4, 203, 24, 116, 0, 16, 24, 10, 8, 10, 4, 203, 24, 122, 0, 16, 23, 10, 8, 10, 4, 203, 24, 145, 0, 16, 24, 10, 8, 10, 4, 203, 24, 152, 0, 16, 23, 10, 8, 10, 4, 203, 24, 157, 0, 16, 24, 10, 8, 10, 4, 203, 24, 161, 0, 16, 24, 10, 8, 10, 4, 203, 24, 167, 0, 16, 24, 10, 8, 10, 4, 203, 24, 186, 0, 16, 23, 10, 8, 10, 4, 203, 24, 199, 0, 16, 24, 10, 8, 10, 4, 203, 24, 202, 0, 16, 24, 10, 8, 10, 4, 203, 24, 212, 0, 16, 23, 10, 8, 10, 4, 203, 24, 217, 0, 16, 24, 10, 8, 10, 4, 203, 24, 219, 0, 16, 24, 10, 8, 10, 4, 203, 24, 244, 0, 16, 24, 10, 8, 10, 4, 203, 25, 19, 0, 16, 24, 10, 8, 10, 4, 203, 25, 20, 0, 16, 23, 10, 8, 10, 4, 203, 25, 46, 0, 16, 24, 10, 8, 10, 4, 203, 25, 48, 0, 16, 21, 10, 8, 10, 4, 203, 25, 64, 0, 16, 23, 10, 8, 10, 4, 203, 25, 91, 0, 16, 24, 10, 8, 10, 4, 203, 25, 99, 0, 16, 24, 10, 8, 10, 4, 203, 25, 100, 0, 16, 24, 10, 8, 10, 4, 203, 25, 106, 0, 16, 24, 10, 8, 10, 4, 203, 25, 131, 0, 16, 24, 10, 8, 10, 4, 203, 25, 135, 0, 16, 24, 10, 8, 10, 4, 203, 25, 138, 0, 16, 24, 10, 8, 10, 4, 203, 25, 147, 0, 16, 24, 10, 8, 10, 4, 203, 25, 153, 0, 16, 24, 10, 8, 10, 4, 203, 25, 154, 0, 16, 23, 10, 8, 10, 4, 203, 25, 164, 0, 16, 24, 10, 8, 10, 4, 203, 25, 166, 0, 16, 24, 10, 8, 10, 4, 203, 25, 174, 0, 16, 23, 10, 8, 10, 4, 203, 25, 180, 0, 16, 24, 10, 8, 10, 4, 203, 25, 182, 0, 16, 24, 10, 8, 10, 4, 203, 25, 191, 0, 16, 24, 10, 8, 10, 4, 203, 25, 199, 0, 16, 24, 10, 8, 10, 4, 203, 25, 200, 0, 16, 24, 10, 8, 10, 4, 203, 25, 202, 0, 16, 23, 10, 8, 10, 4, 203, 25, 208, 0, 16, 20, 10, 8, 10, 4, 203, 25, 229, 0, 16, 24, 10, 8, 10, 4, 203, 25, 235, 0, 16, 24, 10, 8, 10, 4, 203, 25, 236, 0, 16, 24, 10, 8, 10, 4, 203, 25, 242, 0, 16, 24, 10, 8, 10, 4, 203, 26, 12, 0, 16, 24, 10, 8, 10, 4, 203, 26, 34, 0, 16, 24, 10, 8, 10, 4, 203, 26, 49, 0, 16, 24, 10, 8, 10, 4, 203, 26, 50, 0, 16, 24, 10, 8, 10, 4, 203, 26, 55, 0, 16, 24, 10, 8, 10, 4, 203, 26, 56, 0, 16, 23, 10, 8, 10, 4, 203, 26, 60, 0, 16, 24, 10, 8, 10, 4, 203, 26, 65, 0, 16, 24, 10, 8, 10, 4, 203, 26, 68, 0, 16, 24, 10, 8, 10, 4, 203, 26, 76, 0, 16, 24, 10, 8, 10, 4, 203, 26, 80, 0, 16, 24, 10, 8, 10, 4, 203, 26, 84, 0, 16, 24, 10, 8, 10, 4, 203, 26, 97, 0, 16, 24, 10, 8, 10, 4, 203, 26, 102, 0, 16, 23, 10, 8, 10, 4, 203, 26, 115, 0, 16, 24, 10, 8, 10, 4, 203, 26, 116, 0, 16, 24, 10, 8, 10, 4, 203, 26, 129, 0, 16, 24, 10, 8, 10, 4, 203, 26, 143, 0, 16, 24, 10, 8, 10, 4, 203, 26, 144, 0, 16, 24, 10, 8, 10, 4, 203, 26, 148, 0, 16, 23, 10, 8, 10, 4, 203, 26, 154, 0, 16, 24, 10, 8, 10, 4, 203, 26, 158, 0, 16, 23, 10, 8, 10, 4, 203, 26, 170, 0, 16, 24, 10, 8, 10, 4, 203, 26, 173, 0, 16, 24, 10, 8, 10, 4, 203, 26, 176, 0, 16, 24, 10, 8, 10, 4, 203, 26, 185, 0, 16, 24, 10, 8, 10, 4, 203, 26, 202, 0, 16, 23, 10, 8, 10, 4, 203, 26, 210, 0, 16, 24, 10, 8, 10, 4, 203, 26, 214, 0, 16, 24, 10, 8, 10, 4, 203, 26, 222, 0, 16, 24, 10, 8, 10, 4, 203, 26, 224, 0, 16, 24, 10, 8, 10, 4, 203, 26, 228, 0, 16, 24, 10, 8, 10, 4, 203, 26, 232, 0, 16, 24, 10, 8, 10, 4, 203, 27, 0, 0, 16, 24, 10, 8, 10, 4, 203, 27, 10, 0, 16, 24, 10, 8, 10, 4, 203, 27, 15, 0, 16, 24, 10, 8, 10, 4, 203, 27, 16, 0, 16, 24, 10, 8, 10, 4, 203, 27, 20, 0, 16, 24, 10, 8, 10, 4, 203, 27, 22, 0, 16, 23, 10, 8, 10, 4, 203, 27, 40, 0, 16, 24, 10, 8, 10, 4, 203, 27, 45, 0, 16, 24, 10, 8, 10, 4, 203, 27, 53, 0, 16, 24, 10, 8, 10, 4, 203, 27, 65, 0, 16, 24, 10, 8, 10, 4, 203, 27, 66, 0, 16, 24, 10, 8, 10, 4, 203, 27, 81, 0, 16, 24, 10, 8, 10, 4, 203, 27, 88, 0, 16, 24, 10, 8, 10, 4, 203, 27, 102, 0, 16, 24, 10, 8, 10, 4, 203, 27, 109, 0, 16, 24, 10, 8, 10, 4, 203, 27, 117, 0, 16, 24, 10, 8, 10, 4, 203, 27, 121, 0, 16, 24, 10, 8, 10, 4, 203, 27, 122, 0, 16, 23, 10, 8, 10, 4, 203, 27, 125, 0, 16, 24, 10, 8, 10, 4, 203, 27, 200, 0, 16, 24, 10, 8, 10, 4, 203, 27, 202, 0, 16, 24, 10, 8, 10, 4, 203, 27, 233, 0, 16, 24, 10, 8, 10, 4, 203, 27, 241, 0, 16, 24, 10, 8, 10, 4, 203, 27, 250, 0, 16, 24, 10, 8, 10, 4, 203, 28, 10, 0, 16, 24, 10, 8, 10, 4, 203, 28, 12, 0, 16, 24, 10, 8, 10, 4, 203, 28, 33, 0, 16, 24, 10, 8, 10, 4, 203, 28, 34, 0, 16, 23, 10, 8, 10, 4, 203, 28, 43, 0, 16, 24, 10, 8, 10, 4, 203, 28, 44, 0, 16, 24, 10, 8, 10, 4, 203, 28, 54, 0, 16, 24, 10, 8, 10, 4, 203, 28, 56, 0, 16, 24, 10, 8, 10, 4, 203, 28, 73, 0, 16, 24, 10, 8, 10, 4, 203, 28, 74, 0, 16, 24, 10, 8, 10, 4, 203, 28, 76, 0, 16, 24, 10, 8, 10, 4, 203, 28, 86, 0, 16, 24, 10, 8, 10, 4, 203, 28, 88, 0, 16, 24, 10, 8, 10, 4, 203, 28, 112, 0, 16, 24, 10, 8, 10, 4, 203, 28, 131, 0, 16, 24, 10, 8, 10, 4, 203, 28, 136, 0, 16, 24, 10, 8, 10, 4, 203, 28, 140, 0, 16, 24, 10, 8, 10, 4, 203, 28, 145, 0, 16, 24, 10, 8, 10, 4, 203, 28, 165, 0, 16, 24, 10, 8, 10, 4, 203, 28, 169, 0, 16, 24, 10, 8, 10, 4, 203, 28, 170, 0, 16, 24, 10, 8, 10, 4, 203, 28, 178, 0, 16, 23, 10, 8, 10, 4, 203, 28, 185, 0, 16, 24, 10, 8, 10, 4, 203, 28, 187, 0, 16, 24, 10, 8, 10, 4, 203, 28, 196, 0, 16, 24, 10, 8, 10, 4, 203, 28, 226, 0, 16, 23, 10, 8, 10, 4, 203, 28, 239, 0, 16, 24, 10, 8, 10, 4, 203, 29, 2, 0, 16, 24, 10, 8, 10, 4, 203, 29, 8, 0, 16, 23, 10, 8, 10, 4, 203, 29, 13, 0, 16, 24, 10, 8, 10, 4, 203, 29, 14, 0, 16, 24, 10, 8, 10, 4, 203, 29, 28, 0, 16, 24, 10, 8, 10, 4, 203, 29, 46, 0, 16, 24, 10, 8, 10, 4, 203, 29, 57, 0, 16, 24, 10, 8, 10, 4, 203, 29, 61, 0, 16, 24, 10, 8, 10, 4, 203, 29, 63, 0, 16, 24, 10, 8, 10, 4, 203, 29, 69, 0, 16, 24, 10, 8, 10, 4, 203, 29, 73, 0, 16, 24, 10, 8, 10, 4, 203, 29, 81, 0, 16, 24, 10, 8, 10, 4, 203, 29, 90, 0, 16, 24, 10, 8, 10, 4, 203, 29, 95, 0, 16, 24, 10, 8, 10, 4, 203, 29, 100, 0, 16, 24, 10, 8, 10, 4, 203, 29, 103, 0, 16, 24, 10, 8, 10, 4, 203, 29, 112, 0, 16, 24, 10, 8, 10, 4, 203, 29, 120, 0, 16, 22, 10, 8, 10, 4, 203, 29, 182, 0, 16, 23, 10, 8, 10, 4, 203, 29, 187, 0, 16, 24, 10, 8, 10, 4, 203, 29, 189, 0, 16, 24, 10, 8, 10, 4, 203, 29, 190, 0, 16, 24, 10, 8, 10, 4, 203, 29, 205, 0, 16, 24, 10, 8, 10, 4, 203, 29, 210, 0, 16, 24, 10, 8, 10, 4, 203, 29, 217, 0, 16, 24, 10, 8, 10, 4, 203, 29, 227, 0, 16, 24, 10, 8, 10, 4, 203, 29, 231, 0, 16, 24, 10, 8, 10, 4, 203, 29, 233, 0, 16, 24, 10, 8, 10, 4, 203, 29, 234, 0, 16, 24, 10, 8, 10, 4, 203, 29, 248, 0, 16, 24, 10, 8, 10, 4, 203, 29, 254, 0, 16, 23, 10, 8, 10, 4, 203, 30, 16, 0, 16, 23, 10, 8, 10, 4, 203, 30, 25, 0, 16, 24, 10, 8, 10, 4, 203, 30, 27, 0, 16, 24, 10, 8, 10, 4, 203, 30, 29, 0, 16, 24, 10, 8, 10, 4, 203, 30, 66, 0, 16, 24, 10, 8, 10, 4, 203, 30, 81, 0, 16, 24, 10, 8, 10, 4, 203, 30, 87, 0, 16, 24, 10, 8, 10, 4, 203, 30, 111, 0, 16, 24, 10, 8, 10, 4, 203, 30, 121, 0, 16, 24, 10, 8, 10, 4, 203, 30, 123, 0, 16, 24, 10, 8, 10, 4, 203, 30, 152, 0, 16, 24, 10, 8, 10, 4, 203, 30, 156, 0, 16, 24, 10, 8, 10, 4, 203, 30, 162, 0, 16, 24, 10, 8, 10, 4, 203, 30, 173, 0, 16, 24, 10, 8, 10, 4, 203, 30, 175, 0, 16, 24, 10, 8, 10, 4, 203, 30, 187, 0, 16, 24, 10, 8, 10, 4, 203, 30, 194, 0, 16, 24, 10, 8, 10, 4, 203, 30, 217, 0, 16, 24, 10, 8, 10, 4, 203, 30, 220, 0, 16, 24, 10, 8, 10, 4, 203, 30, 222, 0, 16, 24, 10, 8, 10, 4, 203, 30, 232, 0, 16, 23, 10, 8, 10, 4, 203, 30, 235, 0, 16, 24, 10, 8, 10, 4, 203, 30, 240, 0, 16, 23, 10, 8, 10, 4, 203, 30, 246, 0, 16, 24, 10, 8, 10, 4, 203, 30, 250, 0, 16, 23, 10, 8, 10, 4, 203, 31, 45, 0, 16, 24, 10, 8, 10, 4, 203, 31, 46, 0, 16, 24, 10, 8, 10, 4, 203, 31, 49, 0, 16, 24, 10, 8, 10, 4, 203, 31, 51, 0, 16, 24, 10, 8, 10, 4, 203, 31, 54, 0, 16, 23, 10, 8, 10, 4, 203, 31, 69, 0, 16, 24, 10, 8, 10, 4, 203, 31, 72, 0, 16, 24, 10, 8, 10, 4, 203, 31, 80, 0, 16, 24, 10, 8, 10, 4, 203, 31, 85, 0, 16, 24, 10, 8, 10, 4, 203, 31, 97, 0, 16, 24, 10, 8, 10, 4, 203, 31, 105, 0, 16, 24, 10, 8, 10, 4, 203, 31, 106, 0, 16, 24, 10, 8, 10, 4, 203, 31, 108, 0, 16, 23, 10, 8, 10, 4, 203, 31, 124, 0, 16, 24, 10, 8, 10, 4, 203, 31, 162, 0, 16, 24, 10, 8, 10, 4, 203, 31, 174, 0, 16, 24, 10, 8, 10, 4, 203, 31, 177, 0, 16, 24, 10, 8, 10, 4, 203, 31, 181, 0, 16, 24, 10, 8, 10, 4, 203, 31, 187, 0, 16, 24, 10, 8, 10, 4, 203, 31, 189, 0, 16, 24, 10, 8, 10, 4, 203, 31, 204, 0, 16, 24, 10, 8, 10, 4, 203, 31, 220, 0, 16, 24, 10, 8, 10, 4, 203, 31, 222, 0, 16, 23, 10, 8, 10, 4, 203, 31, 225, 0, 16, 24, 10, 8, 10, 4, 203, 31, 229, 0, 16, 24, 10, 8, 10, 4, 203, 31, 248, 0, 16, 23, 10, 8, 10, 4, 203, 31, 253, 0, 16, 24, 10, 8, 10, 4, 203, 32, 20, 0, 16, 24, 10, 8, 10, 4, 203, 32, 48, 0, 16, 23, 10, 8, 10, 4, 203, 32, 56, 0, 16, 24, 10, 8, 10, 4, 203, 32, 60, 0, 16, 24, 10, 8, 10, 4, 203, 32, 62, 0, 16, 24, 10, 8, 10, 4, 203, 32, 68, 0, 16, 23, 10, 8, 10, 4, 203, 32, 76, 0, 16, 24, 10, 8, 10, 4, 203, 32, 81, 0, 16, 24, 10, 8, 10, 4, 203, 32, 84, 0, 16, 23, 10, 8, 10, 4, 203, 32, 95, 0, 16, 24, 10, 8, 10, 4, 203, 32, 102, 0, 16, 24, 10, 8, 10, 4, 203, 32, 105, 0, 16, 24, 10, 8, 10, 4, 203, 32, 130, 0, 16, 24, 10, 8, 10, 4, 203, 32, 133, 0, 16, 24, 10, 8, 10, 4, 203, 32, 140, 0, 16, 24, 10, 8, 10, 4, 203, 32, 152, 0, 16, 24, 10, 8, 10, 4, 203, 32, 186, 0, 16, 23, 10, 8, 10, 4, 203, 32, 192, 0, 16, 24, 10, 8, 10, 4, 203, 32, 196, 0, 16, 24, 10, 8, 10, 4, 203, 32, 203, 0, 16, 24, 10, 8, 10, 4, 203, 32, 204, 0, 16, 23, 10, 8, 10, 4, 203, 32, 212, 0, 16, 24, 10, 8, 10, 4, 203, 33, 4, 0, 16, 24, 10, 8, 10, 4, 203, 33, 7, 0, 16, 24, 10, 8, 10, 4, 203, 33, 8, 0, 16, 21, 10, 8, 10, 4, 203, 33, 21, 0, 16, 24, 10, 8, 10, 4, 203, 33, 26, 0, 16, 24, 10, 8, 10, 4, 203, 33, 32, 0, 16, 24, 10, 8, 10, 4, 203, 33, 63, 0, 16, 24, 10, 8, 10, 4, 203, 33, 64, 0, 16, 24, 10, 8, 10, 4, 203, 33, 67, 0, 16, 24, 10, 8, 10, 4, 203, 33, 68, 0, 16, 24, 10, 8, 10, 4, 203, 33, 73, 0, 16, 24, 10, 8, 10, 4, 203, 33, 79, 0, 16, 24, 10, 8, 10, 4, 203, 33, 100, 0, 16, 24, 10, 8, 10, 4, 203, 33, 122, 0, 16, 24, 10, 8, 10, 4, 203, 33, 129, 0, 16, 24, 10, 8, 10, 4, 203, 33, 131, 0, 16, 24, 10, 8, 10, 4, 203, 33, 145, 0, 16, 24, 10, 8, 10, 4, 203, 33, 156, 0, 16, 24, 10, 8, 10, 4, 203, 33, 158, 0, 16, 23, 10, 8, 10, 4, 203, 33, 174, 0, 16, 24, 10, 8, 10, 4, 203, 33, 185, 0, 16, 24, 10, 8, 10, 4, 203, 33, 200, 0, 16, 24, 10, 8, 10, 4, 203, 33, 202, 0, 16, 23, 10, 8, 10, 4, 203, 33, 204, 0, 16, 24, 10, 8, 10, 4, 203, 33, 206, 0, 16, 23, 10, 8, 10, 4, 203, 33, 214, 0, 16, 23, 10, 8, 10, 4, 203, 33, 224, 0, 16, 23, 10, 8, 10, 4, 203, 33, 226, 0, 16, 24, 10, 8, 10, 4, 203, 33, 233, 0, 16, 24, 10, 8, 10, 4, 203, 33, 243, 0, 16, 24, 10, 8, 10, 4, 203, 33, 250, 0, 16, 24, 10, 8, 10, 4, 203, 34, 4, 0, 16, 24, 10, 8, 10, 4, 203, 34, 21, 0, 16, 24, 10, 8, 10, 4, 203, 34, 27, 0, 16, 24, 10, 8, 10, 4, 203, 34, 39, 0, 16, 24, 10, 8, 10, 4, 203, 34, 48, 0, 16, 23, 10, 8, 10, 4, 203, 34, 54, 0, 16, 24, 10, 8, 10, 4, 203, 34, 56, 0, 16, 23, 10, 8, 10, 4, 203, 34, 67, 0, 16, 24, 10, 8, 10, 4, 203, 34, 69, 0, 16, 24, 10, 8, 10, 4, 203, 34, 76, 0, 16, 24, 10, 8, 10, 4, 203, 34, 92, 0, 16, 24, 10, 8, 10, 4, 203, 34, 106, 0, 16, 24, 10, 8, 10, 4, 203, 34, 113, 0, 16, 24, 10, 8, 10, 4, 203, 34, 147, 0, 16, 24, 10, 8, 10, 4, 203, 34, 150, 0, 16, 24, 10, 8, 10, 4, 203, 34, 152, 0, 16, 23, 10, 8, 10, 4, 203, 34, 161, 0, 16, 24, 10, 8, 10, 4, 203, 34, 162, 0, 16, 24, 10, 8, 10, 4, 203, 34, 187, 0, 16, 24, 10, 8, 10, 4, 203, 34, 192, 0, 16, 21, 10, 8, 10, 4, 203, 34, 204, 0, 16, 22, 10, 8, 10, 4, 203, 34, 232, 0, 16, 24, 10, 8, 10, 4, 203, 34, 240, 0, 16, 24, 10, 8, 10, 4, 203, 34, 242, 0, 16, 24, 10, 8, 10, 4, 203, 34, 245, 0, 16, 24, 10, 8, 10, 4, 203, 34, 251, 0, 16, 24, 10, 8, 10, 4, 203, 55, 2, 0, 16, 23, 10, 8, 10, 4, 203, 55, 4, 0, 16, 24, 10, 8, 10, 4, 203, 55, 10, 0, 16, 24, 10, 8, 10, 4, 203, 55, 13, 0, 16, 24, 10, 8, 10, 4, 203, 55, 22, 0, 16, 24, 10, 8, 10, 4, 203, 55, 30, 0, 16, 24, 10, 8, 10, 4, 203, 55, 93, 0, 16, 24, 10, 8, 10, 4, 203, 55, 101, 0, 16, 24, 10, 8, 10, 4, 203, 55, 109, 0, 16, 24, 10, 8, 10, 4, 203, 55, 110, 0, 16, 24, 10, 8, 10, 4, 203, 55, 116, 0, 16, 23, 10, 8, 10, 4, 203, 55, 119, 0, 16, 24, 10, 8, 10, 4, 203, 55, 128, 0, 16, 23, 10, 8, 10, 4, 203, 55, 146, 0, 16, 23, 10, 8, 10, 4, 203, 55, 192, 0, 16, 24, 10, 8, 10, 4, 203, 55, 196, 0, 16, 24, 10, 8, 10, 4, 203, 55, 218, 0, 16, 23, 10, 8, 10, 4, 203, 55, 221, 0, 16, 24, 10, 8, 10, 4, 203, 55, 224, 0, 16, 24, 10, 8, 10, 4, 203, 56, 1, 0, 16, 24, 10, 8, 10, 4, 203, 56, 4, 0, 16, 24, 10, 8, 10, 4, 203, 56, 12, 0, 16, 24, 10, 8, 10, 4, 203, 56, 24, 0, 16, 24, 10, 8, 10, 4, 203, 56, 38, 0, 16, 24, 10, 8, 10, 4, 203, 56, 40, 0, 16, 24, 10, 8, 10, 4, 203, 56, 46, 0, 16, 24, 10, 8, 10, 4, 203, 56, 48, 0, 16, 21, 10, 8, 10, 4, 203, 56, 68, 0, 16, 23, 10, 8, 10, 4, 203, 56, 82, 0, 16, 23, 10, 8, 10, 4, 203, 56, 84, 0, 16, 23, 10, 8, 10, 4, 203, 56, 95, 0, 16, 24, 10, 8, 10, 4, 203, 56, 110, 0, 16, 24, 10, 8, 10, 4, 203, 56, 121, 0, 16, 24, 10, 8, 10, 4, 203, 56, 161, 0, 16, 24, 10, 8, 10, 4, 203, 56, 169, 0, 16, 24, 10, 8, 10, 4, 203, 56, 172, 0, 16, 23, 10, 8, 10, 4, 203, 56, 175, 0, 16, 24, 10, 8, 10, 4, 203, 56, 183, 0, 16, 24, 10, 8, 10, 4, 203, 56, 185, 0, 16, 24, 10, 8, 10, 4, 203, 56, 187, 0, 16, 24, 10, 8, 10, 4, 203, 56, 192, 0, 16, 24, 10, 8, 10, 4, 203, 56, 198, 0, 16, 24, 10, 8, 10, 4, 203, 56, 201, 0, 16, 24, 10, 8, 10, 4, 203, 56, 208, 0, 16, 23, 10, 8, 10, 4, 203, 56, 210, 0, 16, 24, 10, 8, 10, 4, 203, 56, 214, 0, 16, 24, 10, 8, 10, 4, 203, 56, 216, 0, 16, 24, 10, 8, 10, 4, 203, 56, 227, 0, 16, 24, 10, 8, 10, 4, 203, 56, 228, 0, 16, 24, 10, 8, 10, 4, 203, 56, 231, 0, 16, 24, 10, 8, 10, 4, 203, 56, 232, 0, 16, 24, 10, 8, 10, 4, 203, 56, 240, 0, 16, 24, 10, 8, 10, 4, 203, 56, 252, 0, 16, 24, 10, 8, 10, 4, 203, 56, 254, 0, 16, 24, 10, 8, 10, 4, 203, 57, 5, 0, 16, 24, 10, 8, 10, 4, 203, 57, 6, 0, 16, 24, 10, 8, 10, 4, 203, 57, 12, 0, 16, 23, 10, 8, 10, 4, 203, 57, 28, 0, 16, 24, 10, 8, 10, 4, 203, 57, 39, 0, 16, 24, 10, 8, 10, 4, 203, 57, 46, 0, 16, 24, 10, 8, 10, 4, 203, 57, 58, 0, 16, 24, 10, 8, 10, 4, 203, 57, 61, 0, 16, 24, 10, 8, 10, 4, 203, 57, 66, 0, 16, 24, 10, 8, 10, 4, 203, 57, 69, 0, 16, 24, 10, 8, 10, 4, 203, 57, 70, 0, 16, 23, 10, 8, 10, 4, 203, 57, 73, 0, 16, 24, 10, 8, 10, 4, 203, 57, 90, 0, 16, 24, 10, 8, 10, 4, 203, 57, 101, 0, 16, 24, 10, 8, 10, 4, 203, 57, 109, 0, 16, 24, 10, 8, 10, 4, 203, 57, 123, 0, 16, 24, 10, 8, 10, 4, 203, 57, 157, 0, 16, 24, 10, 8, 10, 4, 203, 57, 200, 0, 16, 24, 10, 8, 10, 4, 203, 57, 202, 0, 16, 24, 10, 8, 10, 4, 203, 57, 206, 0, 16, 24, 10, 8, 10, 4, 203, 57, 222, 0, 16, 24, 10, 8, 10, 4, 203, 57, 224, 0, 16, 20, 10, 8, 10, 4, 203, 57, 246, 0, 16, 23, 10, 8, 10, 4, 203, 57, 249, 0, 16, 24, 10, 8, 10, 4, 203, 57, 253, 0, 16, 24, 10, 8, 10, 4, 203, 57, 254, 0, 16, 23, 10, 8, 10, 4, 203, 62, 2, 0, 16, 24, 10, 8, 10, 4, 203, 62, 131, 0, 16, 24, 10, 8, 10, 4, 203, 62, 139, 0, 16, 24, 10, 8, 10, 4, 203, 62, 161, 0, 16, 24, 10, 8, 10, 4, 203, 62, 197, 0, 16, 24, 10, 8, 10, 4, 203, 62, 228, 0, 16, 22, 10, 8, 10, 4, 203, 62, 234, 0, 16, 24, 10, 8, 10, 4, 203, 62, 246, 0, 16, 24, 10, 8, 10, 4, 203, 76, 160, 0, 16, 22, 10, 8, 10, 4, 203, 76, 168, 0, 16, 22, 10, 8, 10, 4, 203, 76, 208, 0, 16, 22, 10, 8, 10, 4, 203, 76, 212, 0, 16, 22, 10, 8, 10, 4, 203, 76, 216, 0, 16, 22, 10, 8, 10, 4, 203, 76, 240, 0, 16, 22, 10, 8, 10, 4, 203, 76, 244, 0, 16, 22, 10, 8, 10, 4, 203, 77, 180, 0, 16, 22, 10, 8, 10, 4, 203, 78, 48, 0, 16, 20, 10, 8, 10, 4, 203, 78, 156, 0, 16, 22, 10, 8, 10, 4, 203, 79, 0, 0, 16, 20, 10, 8, 10, 4, 203, 79, 32, 0, 16, 20, 10, 8, 10, 4, 203, 80, 4, 0, 16, 23, 10, 8, 10, 4, 203, 80, 32, 0, 16, 20, 10, 8, 10, 4, 203, 80, 57, 0, 16, 24, 10, 8, 10, 4, 203, 80, 129, 0, 16, 24, 10, 8, 10, 4, 203, 80, 132, 0, 16, 22, 10, 8, 10, 4, 203, 80, 136, 0, 16, 21, 10, 8, 10, 4, 203, 80, 144, 0, 16, 20, 10, 8, 10, 4, 203, 81, 0, 0, 16, 21, 10, 8, 10, 4, 203, 81, 16, 0, 16, 20, 10, 8, 10, 4, 203, 81, 244, 0, 16, 22, 10, 8, 10, 4, 203, 82, 0, 0, 16, 23, 10, 8, 10, 4, 203, 82, 16, 0, 16, 21, 10, 8, 10, 4, 203, 82, 112, 0, 16, 22, 10, 8, 10, 4, 203, 82, 116, 0, 16, 22, 10, 8, 10, 4, 203, 82, 120, 0, 16, 22, 10, 8, 10, 4, 203, 82, 124, 0, 16, 22, 10, 8, 10, 4, 203, 82, 224, 0, 16, 22, 10, 8, 10, 4, 203, 82, 228, 0, 16, 22, 10, 8, 10, 4, 203, 82, 232, 0, 16, 22, 10, 8, 10, 4, 203, 82, 236, 0, 16, 22, 10, 8, 10, 4, 203, 83, 0, 0, 16, 22, 10, 8, 10, 4, 203, 83, 8, 0, 16, 22, 10, 8, 10, 4, 203, 83, 12, 0, 16, 22, 10, 8, 10, 4, 203, 83, 56, 0, 16, 21, 10, 8, 10, 4, 203, 83, 224, 0, 16, 20, 10, 8, 10, 4, 203, 86, 0, 0, 16, 19, 10, 8, 10, 4, 203, 86, 32, 0, 16, 19, 10, 8, 10, 4, 203, 86, 64, 0, 16, 20, 10, 8, 10, 4, 203, 86, 80, 0, 16, 20, 10, 8, 10, 4, 203, 86, 96, 0, 16, 19, 10, 8, 10, 4, 203, 86, 250, 0, 16, 24, 10, 8, 10, 4, 203, 86, 254, 0, 16, 23, 10, 8, 10, 4, 203, 88, 32, 0, 16, 19, 10, 8, 10, 4, 203, 88, 192, 0, 16, 19, 10, 8, 10, 4, 203, 89, 0, 0, 16, 22, 10, 8, 10, 4, 203, 89, 8, 0, 16, 21, 10, 8, 10, 4, 203, 89, 133, 0, 16, 24, 10, 8, 10, 4, 203, 89, 136, 0, 16, 22, 10, 8, 10, 4, 203, 89, 144, 0, 16, 24, 10, 8, 10, 4, 203, 90, 0, 0, 16, 22, 10, 8, 10, 4, 203, 90, 8, 0, 16, 22, 10, 8, 10, 4, 203, 90, 12, 0, 16, 22, 10, 8, 10, 4, 203, 90, 128, 0, 16, 19, 10, 8, 10, 4, 203, 90, 160, 0, 16, 19, 10, 8, 10, 4, 203, 90, 192, 0, 16, 19, 10, 8, 10, 4, 203, 91, 32, 0, 16, 19, 10, 8, 10, 4, 203, 91, 96, 0, 16, 20, 10, 8, 10, 4, 203, 91, 120, 0, 16, 21, 10, 8, 10, 4, 203, 92, 0, 0, 16, 22, 10, 8, 10, 4, 203, 92, 6, 0, 16, 24, 10, 8, 10, 4, 203, 92, 160, 0, 16, 19, 10, 8, 10, 4, 203, 93, 0, 0, 16, 22, 10, 8, 10, 4, 203, 93, 4, 0, 16, 22, 10, 8, 10, 4, 203, 93, 8, 0, 16, 24, 10, 8, 10, 4, 203, 93, 9, 0, 16, 24, 10, 8, 10, 4, 203, 93, 10, 0, 16, 23, 10, 8, 10, 4, 203, 93, 12, 0, 16, 22, 10, 8, 10, 4, 203, 93, 16, 0, 16, 20, 10, 8, 10, 4, 203, 93, 32, 0, 16, 19, 10, 8, 10, 4, 203, 93, 64, 0, 16, 18, 10, 8, 10, 4, 203, 93, 128, 0, 16, 21, 10, 8, 10, 4, 203, 93, 136, 0, 16, 22, 10, 8, 10, 4, 203, 93, 140, 0, 16, 24, 10, 8, 10, 4, 203, 93, 141, 0, 16, 24, 10, 8, 10, 4, 203, 93, 142, 0, 16, 23, 10, 8, 10, 4, 203, 93, 144, 0, 16, 20, 10, 8, 10, 4, 203, 93, 160, 0, 16, 19, 10, 8, 10, 4, 203, 93, 192, 0, 16, 18, 10, 8, 10, 4, 203, 94, 0, 0, 16, 22, 10, 8, 10, 4, 203, 94, 4, 0, 16, 22, 10, 8, 10, 4, 203, 94, 8, 0, 16, 21, 10, 8, 10, 4, 203, 94, 16, 0, 16, 20, 10, 8, 10, 4, 203, 95, 0, 0, 16, 21, 10, 8, 10, 4, 203, 95, 96, 0, 16, 20, 10, 8, 10, 4, 203, 95, 112, 0, 16, 20, 10, 8, 10, 4, 203, 95, 128, 0, 16, 18, 10, 8, 10, 4, 203, 95, 200, 0, 16, 22, 10, 8, 10, 4, 203, 95, 204, 0, 16, 22, 10, 8, 10, 4, 203, 95, 208, 0, 16, 22, 10, 8, 10, 4, 203, 95, 224, 0, 16, 19, 10, 8, 10, 4, 203, 99, 8, 0, 16, 21, 10, 8, 10, 4, 203, 99, 16, 0, 16, 20, 10, 8, 10, 4, 203, 99, 80, 0, 16, 20, 10, 8, 10, 4, 203, 100, 32, 0, 16, 20, 10, 8, 10, 4, 203, 100, 48, 0, 16, 21, 10, 8, 10, 4, 203, 100, 58, 0, 16, 24, 10, 8, 10, 4, 203, 100, 60, 0, 16, 24, 10, 8, 10, 4, 203, 100, 63, 0, 16, 24, 10, 8, 10, 4, 203, 100, 80, 0, 16, 20, 10, 8, 10, 4, 203, 100, 96, 0, 16, 19, 10, 8, 10, 4, 203, 100, 192, 0, 16, 20, 10, 8, 10, 4, 203, 104, 32, 0, 16, 20, 10, 8, 10, 4, 203, 105, 96, 0, 16, 19, 10, 8, 10, 4, 203, 105, 128, 0, 16, 19, 10, 8, 10, 4, 203, 107, 0, 0, 16, 17, 10, 8, 10, 4, 203, 110, 160, 0, 16, 19, 10, 8, 10, 4, 203, 110, 208, 0, 16, 20, 10, 8, 10, 4, 203, 110, 232, 0, 16, 23, 10, 8, 10, 4, 203, 110, 234, 0, 16, 24, 10, 8, 10, 4, 203, 114, 80, 0, 16, 22, 10, 8, 10, 4, 203, 114, 84, 0, 16, 22, 10, 8, 10, 4, 203, 114, 88, 0, 16, 22, 10, 8, 10, 4, 203, 114, 92, 0, 16, 22, 10, 8, 10, 4, 203, 114, 244, 0, 16, 22, 10, 8, 10, 4, 203, 118, 192, 0, 16, 19, 10, 8, 10, 4, 203, 118, 241, 0, 16, 24, 10, 8, 10, 4, 203, 118, 248, 0, 16, 22, 10, 8, 10, 4, 203, 119, 24, 0, 16, 21, 10, 8, 10, 4, 203, 119, 32, 0, 16, 22, 10, 8, 10, 4, 203, 119, 80, 0, 16, 22, 10, 8, 10, 4, 203, 119, 85, 0, 16, 24, 10, 8, 10, 4, 203, 119, 113, 0, 16, 24, 10, 8, 10, 4, 203, 119, 114, 0, 16, 23, 10, 8, 10, 4, 203, 119, 116, 0, 16, 22, 10, 8, 10, 4, 203, 119, 120, 0, 16, 21, 10, 8, 10, 4, 203, 119, 128, 0, 16, 17, 10, 8, 10, 4, 203, 123, 58, 0, 16, 24, 10, 8, 10, 4, 203, 128, 32, 0, 16, 19, 10, 8, 10, 4, 203, 128, 96, 0, 16, 19, 10, 8, 10, 4, 203, 128, 224, 0, 16, 21, 10, 8, 10, 4, 203, 129, 8, 0, 16, 21, 10, 8, 10, 4, 203, 130, 32, 0, 16, 19, 10, 8, 10, 4, 203, 132, 32, 0, 16, 19, 10, 8, 10, 4, 203, 134, 240, 0, 16, 21, 10, 8, 10, 4, 203, 135, 96, 0, 16, 20, 10, 8, 10, 4, 203, 135, 112, 0, 16, 20, 10, 8, 10, 4, 203, 135, 160, 0, 16, 20, 10, 8, 10, 4, 203, 142, 219, 0, 16, 24, 10, 8, 10, 4, 203, 142, 224, 0, 16, 19, 10, 8, 10, 4, 203, 144, 96, 0, 16, 19, 10, 8, 10, 4, 203, 145, 0, 0, 16, 19, 10, 8, 10, 4, 203, 148, 0, 0, 16, 18, 10, 8, 10, 4, 203, 148, 64, 0, 16, 20, 10, 8, 10, 4, 203, 148, 80, 0, 16, 22, 10, 8, 10, 4, 203, 148, 86, 0, 16, 23, 10, 8, 10, 4, 203, 149, 92, 0, 16, 22, 10, 8, 10, 4, 203, 152, 64, 0, 16, 19, 10, 8, 10, 4, 203, 152, 128, 0, 16, 19, 10, 8, 10, 4, 203, 153, 0, 0, 16, 22, 10, 8, 10, 4, 203, 156, 192, 0, 16, 18, 10, 8, 10, 4, 203, 158, 16, 0, 16, 21, 10, 8, 10, 4, 203, 160, 52, 0, 16, 22, 10, 8, 10, 4, 203, 160, 104, 0, 16, 21, 10, 8, 10, 4, 203, 160, 129, 0, 16, 24, 10, 8, 10, 4, 203, 160, 192, 0, 16, 19, 10, 8, 10, 4, 203, 161, 0, 0, 16, 22, 10, 8, 10, 4, 203, 161, 180, 0, 16, 24, 10, 8, 10, 4, 203, 161, 183, 0, 16, 24, 10, 8, 10, 4, 203, 161, 192, 0, 16, 19, 10, 8, 10, 4, 203, 166, 160, 0, 16, 19, 10, 8, 10, 4, 203, 167, 28, 0, 16, 22, 10, 8, 10, 4, 203, 168, 0, 0, 16, 19, 10, 8, 10, 4, 203, 170, 58, 0, 16, 23, 10, 8, 10, 4, 203, 171, 0, 0, 16, 22, 10, 8, 10, 4, 203, 171, 208, 0, 16, 24, 10, 8, 10, 4, 203, 171, 224, 0, 16, 20, 10, 8, 10, 4, 203, 174, 4, 0, 16, 24, 10, 8, 10, 4, 203, 174, 6, 0, 16, 24, 10, 8, 10, 4, 203, 174, 7, 0, 16, 24, 10, 8, 10, 4, 203, 174, 96, 0, 16, 19, 10, 8, 10, 4, 203, 175, 128, 0, 16, 19, 10, 8, 10, 4, 203, 175, 192, 0, 16, 18, 10, 8, 10, 4, 203, 176, 0, 0, 16, 18, 10, 8, 10, 4, 203, 176, 64, 0, 16, 19, 10, 8, 10, 4, 203, 176, 168, 0, 16, 21, 10, 8, 10, 4, 203, 184, 80, 0, 16, 20, 10, 8, 10, 4, 203, 185, 189, 0, 16, 24, 10, 8, 10, 4, 203, 187, 160, 0, 16, 19, 10, 8, 10, 4, 203, 189, 0, 0, 16, 23, 10, 8, 10, 4, 203, 189, 6, 0, 16, 23, 10, 8, 10, 4, 203, 189, 112, 0, 16, 22, 10, 8, 10, 4, 203, 189, 192, 0, 16, 19, 10, 8, 10, 4, 203, 189, 232, 0, 16, 22, 10, 8, 10, 4, 203, 189, 236, 0, 16, 22, 10, 8, 10, 4, 203, 189, 240, 0, 16, 22, 10, 8, 10, 4, 203, 190, 96, 0, 16, 20, 10, 8, 10, 4, 203, 190, 249, 0, 16, 24, 10, 8, 10, 4, 203, 191, 0, 0, 16, 23, 10, 8, 10, 4, 203, 191, 2, 0, 16, 24, 10, 8, 10, 4, 203, 191, 5, 0, 16, 24, 10, 8, 10, 4, 203, 191, 7, 0, 16, 24, 10, 8, 10, 4, 203, 191, 16, 0, 16, 20, 10, 8, 10, 4, 203, 191, 64, 0, 16, 18, 10, 8, 10, 4, 203, 191, 133, 0, 16, 24, 10, 8, 10, 4, 203, 191, 144, 0, 16, 21, 10, 8, 10, 4, 203, 191, 152, 0, 16, 21, 10, 8, 10, 4, 203, 192, 0, 0, 16, 19, 10, 8, 10, 4, 203, 193, 224, 0, 16, 19, 10, 8, 10, 4, 203, 194, 120, 0, 16, 21, 10, 8, 10, 4, 203, 195, 64, 0, 16, 19, 10, 8, 10, 4, 203, 195, 112, 0, 16, 21, 10, 8, 10, 4, 203, 195, 128, 0, 16, 17, 10, 8, 10, 4, 203, 196, 0, 0, 16, 21, 10, 8, 10, 4, 203, 196, 8, 0, 16, 21, 10, 8, 10, 4, 203, 196, 28, 0, 16, 22, 10, 8, 10, 4, 203, 201, 181, 0, 16, 24, 10, 8, 10, 4, 203, 201, 182, 0, 16, 24, 10, 8, 10, 4, 203, 202, 236, 0, 16, 22, 10, 8, 10, 4, 203, 205, 64, 0, 16, 19, 10, 8, 10, 4, 203, 205, 128, 0, 16, 17, 10, 8, 10, 4, 203, 207, 64, 0, 16, 20, 10, 8, 10, 4, 203, 207, 80, 0, 16, 21, 10, 8, 10, 4, 203, 207, 88, 0, 16, 22, 10, 8, 10, 4, 203, 207, 92, 0, 16, 22, 10, 8, 10, 4, 203, 207, 96, 0, 16, 20, 10, 8, 10, 4, 203, 207, 112, 0, 16, 20, 10, 8, 10, 4, 203, 207, 128, 0, 16, 18, 10, 8, 10, 4, 203, 207, 192, 0, 16, 21, 10, 8, 10, 4, 203, 207, 200, 0, 16, 21, 10, 8, 10, 4, 203, 207, 208, 0, 16, 20, 10, 8, 10, 4, 203, 207, 224, 0, 16, 19, 10, 8, 10, 4, 203, 208, 0, 0, 16, 20, 10, 8, 10, 4, 203, 208, 16, 0, 16, 22, 10, 8, 10, 4, 203, 208, 32, 0, 16, 19, 10, 8, 10, 4, 203, 209, 224, 0, 16, 19, 10, 8, 10, 4, 203, 212, 0, 0, 16, 20, 10, 8, 10, 4, 203, 212, 80, 0, 16, 20, 10, 8, 10, 4, 203, 215, 232, 0, 16, 21, 10, 8, 10, 4, 203, 217, 164, 0, 16, 22, 10, 8, 10, 4, 203, 222, 192, 0, 16, 20, 10, 8, 10, 4, 203, 223, 0, 0, 16, 20, 10, 8, 10, 4, 203, 223, 16, 0, 16, 21, 10, 8, 10, 4, 210, 2, 0, 0, 16, 20, 10, 8, 10, 4, 210, 2, 16, 0, 16, 20, 10, 8, 10, 4, 210, 5, 0, 0, 16, 19, 10, 8, 10, 4, 210, 5, 56, 0, 16, 21, 10, 8, 10, 4, 210, 5, 128, 0, 16, 20, 10, 8, 10, 4, 210, 5, 144, 0, 16, 20, 10, 8, 10, 4, 210, 7, 56, 0, 16, 22, 10, 8, 10, 4, 210, 7, 60, 0, 16, 22, 10, 8, 10, 4, 210, 12, 0, 0, 16, 18, 10, 8, 10, 4, 210, 12, 64, 0, 16, 18, 10, 8, 10, 4, 210, 12, 128, 0, 16, 18, 10, 8, 10, 4, 210, 12, 192, 0, 16, 18, 10, 8, 10, 4, 210, 13, 0, 0, 16, 18, 10, 8, 10, 4, 210, 13, 64, 0, 16, 18, 10, 8, 10, 4, 210, 13, 128, 0, 16, 17, 10, 8, 10, 4, 210, 14, 64, 0, 16, 19, 10, 8, 10, 4, 210, 14, 112, 0, 16, 20, 10, 8, 10, 4, 210, 14, 128, 0, 16, 19, 10, 8, 10, 4, 210, 14, 160, 0, 16, 19, 10, 8, 10, 4, 210, 14, 192, 0, 16, 19, 10, 8, 10, 4, 210, 14, 224, 0, 16, 19, 10, 8, 10, 4, 210, 15, 0, 0, 16, 19, 10, 8, 10, 4, 210, 15, 32, 0, 16, 19, 10, 8, 10, 4, 210, 15, 64, 0, 16, 19, 10, 8, 10, 4, 210, 15, 96, 0, 16, 19, 10, 8, 10, 4, 210, 15, 128, 0, 16, 18, 10, 8, 10, 4, 210, 16, 104, 0, 16, 22, 10, 8, 10, 4, 210, 16, 128, 0, 16, 18, 10, 8, 10, 4, 210, 21, 0, 0, 16, 17, 10, 8, 10, 4, 210, 21, 128, 0, 16, 17, 10, 8, 10, 4, 210, 22, 0, 0, 16, 16, 10, 8, 10, 4, 210, 23, 32, 0, 16, 19, 10, 8, 10, 4, 210, 25, 0, 0, 16, 16, 10, 8, 10, 4, 210, 26, 0, 0, 16, 15, 10, 8, 10, 4, 210, 28, 0, 0, 16, 14, 10, 8, 10, 4, 210, 32, 0, 0, 16, 14, 10, 8, 10, 4, 210, 36, 0, 0, 16, 14, 10, 8, 10, 4, 210, 40, 0, 0, 16, 13, 10, 8, 10, 4, 210, 51, 0, 0, 16, 16, 10, 8, 10, 4, 210, 52, 0, 0, 16, 18, 10, 8, 10, 4, 210, 52, 64, 0, 16, 18, 10, 8, 10, 4, 210, 52, 128, 0, 16, 17, 10, 8, 10, 4, 210, 53, 0, 0, 16, 17, 10, 8, 10, 4, 210, 53, 128, 0, 16, 17, 10, 8, 10, 4, 210, 56, 192, 0, 16, 19, 10, 8, 10, 4, 210, 72, 0, 0, 16, 17, 10, 8, 10, 4, 210, 72, 128, 0, 16, 19, 10, 8, 10, 4, 210, 72, 160, 0, 16, 19, 10, 8, 10, 4, 210, 72, 192, 0, 16, 18, 10, 8, 10, 4, 210, 73, 0, 0, 16, 19, 10, 8, 10, 4, 210, 73, 32, 0, 16, 19, 10, 8, 10, 4, 210, 73, 64, 0, 16, 18, 10, 8, 10, 4, 210, 73, 128, 0, 16, 17, 10, 8, 10, 4, 210, 74, 0, 0, 16, 19, 10, 8, 10, 4, 210, 74, 32, 0, 16, 19, 10, 8, 10, 4, 210, 74, 64, 0, 16, 19, 10, 8, 10, 4, 210, 74, 96, 0, 16, 19, 10, 8, 10, 4, 210, 74, 128, 0, 16, 19, 10, 8, 10, 4, 210, 74, 160, 0, 16, 19, 10, 8, 10, 4, 210, 74, 192, 0, 16, 18, 10, 8, 10, 4, 210, 75, 0, 0, 16, 16, 10, 8, 10, 4, 210, 76, 0, 0, 16, 19, 10, 8, 10, 4, 210, 76, 32, 0, 16, 19, 10, 8, 10, 4, 210, 76, 64, 0, 16, 18, 10, 8, 10, 4, 210, 76, 128, 0, 16, 17, 10, 8, 10, 4, 210, 77, 0, 0, 16, 16, 10, 8, 10, 4, 210, 78, 0, 0, 16, 19, 10, 8, 10, 4, 210, 78, 32, 0, 16, 19, 10, 8, 10, 4, 210, 78, 64, 0, 16, 18, 10, 8, 10, 4, 210, 78, 128, 0, 16, 19, 10, 8, 10, 4, 210, 78, 160, 0, 16, 19, 10, 8, 10, 4, 210, 78, 192, 0, 16, 18, 10, 8, 10, 4, 210, 79, 64, 0, 16, 18, 10, 8, 10, 4, 210, 79, 224, 0, 16, 19, 10, 8, 10, 4, 210, 82, 0, 0, 16, 15, 10, 8, 10, 4, 210, 87, 128, 0, 16, 20, 10, 8, 10, 4, 210, 87, 144, 0, 16, 20, 10, 8, 10, 4, 210, 87, 160, 0, 16, 19, 10, 8, 10, 4, 210, 185, 192, 0, 16, 18, 10, 8, 10, 4, 210, 192, 96, 0, 16, 19, 10, 8, 10, 4, 211, 64, 0, 0, 16, 14, 10, 8, 10, 4, 211, 68, 0, 0, 16, 15, 10, 8, 10, 4, 211, 70, 0, 0, 16, 15, 10, 8, 10, 4, 211, 80, 0, 0, 16, 16, 10, 8, 10, 4, 211, 81, 0, 0, 16, 16, 10, 8, 10, 4, 211, 82, 0, 0, 16, 16, 10, 8, 10, 4, 211, 83, 0, 0, 16, 16, 10, 8, 10, 4, 211, 84, 0, 0, 16, 15, 10, 8, 10, 4, 211, 86, 0, 0, 16, 15, 10, 8, 10, 4, 211, 88, 0, 0, 16, 16, 10, 8, 10, 4, 211, 89, 0, 0, 16, 16, 10, 8, 10, 4, 211, 90, 0, 0, 16, 15, 10, 8, 10, 4, 211, 92, 0, 0, 16, 15, 10, 8, 10, 4, 211, 94, 0, 0, 16, 15, 10, 8, 10, 4, 211, 96, 0, 0, 16, 15, 10, 8, 10, 4, 211, 98, 0, 0, 16, 16, 10, 8, 10, 4, 211, 99, 0, 0, 16, 18, 10, 8, 10, 4, 211, 99, 64, 0, 16, 19, 10, 8, 10, 4, 211, 99, 96, 0, 16, 19, 10, 8, 10, 4, 211, 99, 128, 0, 16, 17, 10, 8, 10, 4, 211, 100, 0, 0, 16, 16, 10, 8, 10, 4, 211, 101, 0, 0, 16, 18, 10, 8, 10, 4, 211, 101, 64, 0, 16, 18, 10, 8, 10, 4, 211, 101, 128, 0, 16, 17, 10, 8, 10, 4, 211, 102, 0, 0, 16, 16, 10, 8, 10, 4, 211, 103, 0, 0, 16, 17, 10, 8, 10, 4, 211, 103, 128, 0, 16, 17, 10, 8, 10, 4, 211, 136, 0, 0, 16, 14, 10, 8, 10, 4, 211, 140, 0, 0, 16, 15, 10, 8, 10, 4, 211, 142, 0, 0, 16, 17, 10, 8, 10, 4, 211, 142, 128, 0, 16, 17, 10, 8, 10, 4, 211, 143, 0, 0, 16, 16, 10, 8, 10, 4, 211, 144, 0, 0, 16, 15, 10, 8, 10, 4, 211, 146, 0, 0, 16, 16, 10, 8, 10, 4, 211, 147, 0, 0, 16, 16, 10, 8, 10, 4, 211, 148, 0, 0, 16, 14, 10, 8, 10, 4, 211, 152, 0, 0, 16, 15, 10, 8, 10, 4, 211, 154, 0, 0, 16, 16, 10, 8, 10, 4, 211, 155, 0, 0, 16, 18, 10, 8, 10, 4, 211, 155, 64, 0, 16, 19, 10, 8, 10, 4, 211, 155, 96, 0, 16, 19, 10, 8, 10, 4, 211, 155, 128, 0, 16, 17, 10, 8, 10, 4, 211, 156, 0, 0, 16, 14, 10, 8, 10, 4, 211, 160, 0, 0, 16, 14, 10, 8, 10, 4, 211, 164, 0, 0, 16, 14, 10, 8, 10, 4, 212, 64, 0, 0, 16, 17, 10, 8, 10, 4, 212, 129, 128, 0, 16, 17, 10, 8, 10, 4, 216, 250, 108, 0, 16, 22, 10, 8, 10, 4, 218, 0, 0, 0, 16, 16, 10, 8, 10, 4, 218, 1, 0, 0, 16, 16, 10, 8, 10, 4, 218, 2, 0, 0, 16, 15, 10, 8, 10, 4, 218, 4, 0, 0, 16, 15, 10, 8, 10, 4, 218, 6, 0, 0, 16, 16, 10, 8, 10, 4, 218, 7, 0, 0, 16, 16, 10, 8, 10, 4, 218, 8, 0, 0, 16, 15, 10, 8, 10, 4, 218, 10, 0, 0, 16, 16, 10, 8, 10, 4, 218, 11, 0, 0, 16, 16, 10, 8, 10, 4, 218, 12, 0, 0, 16, 16, 10, 8, 10, 4, 218, 13, 0, 0, 16, 16, 10, 8, 10, 4, 218, 14, 0, 0, 16, 15, 10, 8, 10, 4, 218, 16, 0, 0, 16, 14, 10, 8, 10, 4, 218, 20, 0, 0, 16, 16, 10, 8, 10, 4, 218, 21, 0, 0, 16, 17, 10, 8, 10, 4, 218, 21, 128, 0, 16, 17, 10, 8, 10, 4, 218, 22, 0, 0, 16, 15, 10, 8, 10, 4, 218, 24, 0, 0, 16, 15, 10, 8, 10, 4, 218, 26, 0, 0, 16, 16, 10, 8, 10, 4, 218, 27, 0, 0, 16, 16, 10, 8, 10, 4, 218, 28, 0, 0, 16, 15, 10, 8, 10, 4, 218, 30, 0, 0, 16, 15, 10, 8, 10, 4, 218, 56, 0, 0, 16, 14, 10, 8, 10, 4, 218, 60, 0, 0, 16, 15, 10, 8, 10, 4, 218, 62, 0, 0, 16, 17, 10, 8, 10, 4, 218, 62, 128, 0, 16, 17, 10, 8, 10, 4, 218, 63, 0, 0, 16, 16, 10, 8, 10, 4, 218, 64, 0, 0, 16, 15, 10, 8, 10, 4, 218, 66, 0, 0, 16, 16, 10, 8, 10, 4, 218, 67, 0, 0, 16, 17, 10, 8, 10, 4, 218, 67, 128, 0, 16, 17, 10, 8, 10, 4, 218, 68, 0, 0, 16, 15, 10, 8, 10, 4, 218, 70, 0, 0, 16, 15, 10, 8, 10, 4, 218, 72, 0, 0, 16, 14, 10, 8, 10, 4, 218, 76, 0, 0, 16, 15, 10, 8, 10, 4, 218, 78, 0, 0, 16, 15, 10, 8, 10, 4, 218, 80, 0, 0, 16, 14, 10, 8, 10, 4, 218, 84, 0, 0, 16, 14, 10, 8, 10, 4, 218, 88, 0, 0, 16, 13, 10, 8, 10, 4, 218, 96, 0, 0, 16, 15, 10, 8, 10, 4, 218, 98, 0, 0, 16, 17, 10, 8, 10, 4, 218, 98, 128, 0, 16, 18, 10, 8, 10, 4, 218, 98, 192, 0, 16, 19, 10, 8, 10, 4, 218, 98, 224, 0, 16, 19, 10, 8, 10, 4, 218, 99, 0, 0, 16, 16, 10, 8, 10, 4, 218, 100, 88, 0, 16, 21, 10, 8, 10, 4, 218, 100, 96, 0, 16, 19, 10, 8, 10, 4, 218, 100, 128, 0, 16, 17, 10, 8, 10, 4, 218, 104, 0, 0, 16, 17, 10, 8, 10, 4, 218, 104, 128, 0, 16, 19, 10, 8, 10, 4, 218, 104, 160, 0, 16, 19, 10, 8, 10, 4, 218, 104, 192, 0, 16, 21, 10, 8, 10, 4, 218, 104, 200, 0, 16, 21, 10, 8, 10, 4, 218, 104, 208, 0, 16, 20, 10, 8, 10, 4, 218, 104, 224, 0, 16, 19, 10, 8, 10, 4, 218, 105, 0, 0, 16, 16, 10, 8, 10, 4, 218, 106, 0, 0, 16, 15, 10, 8, 10, 4, 218, 108, 0, 0, 16, 16, 10, 8, 10, 4, 218, 109, 0, 0, 16, 16, 10, 8, 10, 4, 218, 185, 192, 0, 16, 19, 10, 8, 10, 4, 218, 185, 240, 0, 16, 21, 10, 8, 10, 4, 218, 192, 0, 0, 16, 16, 10, 8, 10, 4, 218, 193, 0, 0, 16, 16, 10, 8, 10, 4, 218, 194, 0, 0, 16, 16, 10, 8, 10, 4, 218, 195, 0, 0, 16, 16, 10, 8, 10, 4, 218, 196, 0, 0, 16, 14, 10, 8, 10, 4, 218, 200, 0, 0, 16, 14, 10, 8, 10, 4, 218, 204, 0, 0, 16, 15, 10, 8, 10, 4, 218, 206, 0, 0, 16, 15, 10, 8, 10, 4, 218, 240, 0, 0, 16, 14, 10, 8, 10, 4, 218, 244, 0, 0, 16, 15, 10, 8, 10, 4, 218, 246, 0, 0, 16, 15, 10, 8, 10, 4, 218, 249, 0, 0, 16, 16, 10, 8, 10, 4, 219, 72, 0, 0, 16, 16, 10, 8, 10, 4, 219, 82, 0, 0, 16, 16, 10, 8, 10, 4, 219, 83, 128, 0, 16, 17, 10, 8, 10, 4, 219, 90, 68, 0, 16, 22, 10, 8, 10, 4, 219, 90, 72, 0, 16, 22, 10, 8, 10, 4, 219, 90, 76, 0, 16, 22, 10, 8, 10, 4, 219, 128, 0, 0, 16, 12, 10, 8, 10, 4, 219, 144, 0, 0, 16, 14, 10, 8, 10, 4, 219, 148, 0, 0, 16, 16, 10, 8, 10, 4, 219, 149, 0, 0, 16, 17, 10, 8, 10, 4, 219, 149, 128, 0, 16, 18, 10, 8, 10, 4, 219, 149, 192, 0, 16, 18, 10, 8, 10, 4, 219, 150, 0, 0, 16, 19, 10, 8, 10, 4, 219, 150, 32, 0, 16, 19, 10, 8, 10, 4, 219, 150, 64, 0, 16, 19, 10, 8, 10, 4, 219, 150, 96, 0, 16, 20, 10, 8, 10, 4, 219, 150, 112, 0, 16, 20, 10, 8, 10, 4, 219, 150, 128, 0, 16, 17, 10, 8, 10, 4, 219, 151, 0, 0, 16, 19, 10, 8, 10, 4, 219, 151, 32, 0, 16, 19, 10, 8, 10, 4, 219, 151, 64, 0, 16, 18, 10, 8, 10, 4, 219, 151, 128, 0, 16, 17, 10, 8, 10, 4, 219, 152, 0, 0, 16, 15, 10, 8, 10, 4, 219, 154, 0, 0, 16, 15, 10, 8, 10, 4, 219, 156, 0, 0, 16, 15, 10, 8, 10, 4, 219, 158, 0, 0, 16, 17, 10, 8, 10, 4, 219, 158, 128, 0, 16, 17, 10, 8, 10, 4, 219, 159, 0, 0, 16, 18, 10, 8, 10, 4, 219, 159, 64, 0, 16, 18, 10, 8, 10, 4, 219, 159, 128, 0, 16, 17, 10, 8, 10, 4, 219, 216, 0, 0, 16, 15, 10, 8, 10, 4, 219, 218, 0, 0, 16, 15, 10, 8, 10, 4, 219, 220, 0, 0, 16, 16, 10, 8, 10, 4, 219, 221, 0, 0, 16, 16, 10, 8, 10, 4, 219, 222, 0, 0, 16, 15, 10, 8, 10, 4, 219, 224, 0, 0, 16, 15, 10, 8, 10, 4, 219, 226, 0, 0, 16, 16, 10, 8, 10, 4, 219, 227, 0, 0, 16, 16, 10, 8, 10, 4, 219, 228, 0, 0, 16, 15, 10, 8, 10, 4, 219, 230, 0, 0, 16, 15, 10, 8, 10, 4, 219, 232, 0, 0, 16, 14, 10, 8, 10, 4, 219, 236, 0, 0, 16, 15, 10, 8, 10, 4, 219, 238, 0, 0, 16, 15, 10, 8, 10, 4, 219, 242, 0, 0, 16, 15, 10, 8, 10, 4, 219, 244, 0, 0, 16, 14, 10, 8, 10, 4, 220, 101, 192, 0, 16, 18, 10, 8, 10, 4, 220, 112, 0, 0, 16, 14, 10, 8, 10, 4, 220, 152, 128, 0, 16, 17, 10, 8, 10, 4, 220, 154, 0, 0, 16, 15, 10, 8, 10, 4, 220, 158, 240, 0, 16, 22, 10, 8, 10, 4, 220, 160, 0, 0, 16, 11, 10, 8, 10, 4, 220, 192, 0, 0, 16, 15, 10, 8, 10, 4, 220, 194, 0, 0, 16, 15, 10, 8, 10, 4, 220, 196, 0, 0, 16, 14, 10, 8, 10, 4, 220, 200, 0, 0, 16, 13, 10, 8, 10, 4, 220, 231, 0, 0, 16, 18, 10, 8, 10, 4, 220, 231, 128, 0, 16, 17, 10, 8, 10, 4, 220, 232, 64, 0, 16, 18, 10, 8, 10, 4, 220, 234, 0, 0, 16, 16, 10, 8, 10, 4, 220, 242, 0, 0, 16, 15, 10, 8, 10, 4, 220, 247, 136, 0, 16, 21, 10, 8, 10, 4, 220, 248, 0, 0, 16, 14, 10, 8, 10, 4, 220, 252, 0, 0, 16, 16, 10, 8, 10, 4, 221, 0, 0, 0, 16, 15, 10, 8, 10, 4, 221, 2, 0, 0, 16, 16, 10, 8, 10, 4, 221, 3, 0, 0, 16, 17, 10, 8, 10, 4, 221, 3, 128, 0, 16, 17, 10, 8, 10, 4, 221, 4, 0, 0, 16, 16, 10, 8, 10, 4, 221, 5, 0, 0, 16, 17, 10, 8, 10, 4, 221, 5, 128, 0, 16, 17, 10, 8, 10, 4, 221, 6, 0, 0, 16, 16, 10, 8, 10, 4, 221, 7, 0, 0, 16, 19, 10, 8, 10, 4, 221, 7, 32, 0, 16, 19, 10, 8, 10, 4, 221, 7, 64, 0, 16, 19, 10, 8, 10, 4, 221, 7, 96, 0, 16, 19, 10, 8, 10, 4, 221, 7, 128, 0, 16, 17, 10, 8, 10, 4, 221, 8, 0, 0, 16, 15, 10, 8, 10, 4, 221, 10, 0, 0, 16, 16, 10, 8, 10, 4, 221, 11, 0, 0, 16, 17, 10, 8, 10, 4, 221, 11, 128, 0, 16, 18, 10, 8, 10, 4, 221, 11, 192, 0, 16, 19, 10, 8, 10, 4, 221, 11, 224, 0, 16, 19, 10, 8, 10, 4, 221, 12, 0, 0, 16, 17, 10, 8, 10, 4, 221, 12, 128, 0, 16, 18, 10, 8, 10, 4, 221, 13, 0, 0, 16, 18, 10, 8, 10, 4, 221, 13, 64, 0, 16, 19, 10, 8, 10, 4, 221, 13, 96, 0, 16, 19, 10, 8, 10, 4, 221, 13, 128, 0, 16, 17, 10, 8, 10, 4, 221, 14, 0, 0, 16, 15, 10, 8, 10, 4, 221, 122, 0, 0, 16, 15, 10, 8, 10, 4, 221, 128, 128, 0, 16, 17, 10, 8, 10, 4, 221, 129, 0, 0, 16, 16, 10, 8, 10, 4, 221, 130, 0, 0, 16, 15, 10, 8, 10, 4, 221, 133, 224, 0, 16, 19, 10, 8, 10, 4, 221, 136, 0, 0, 16, 16, 10, 8, 10, 4, 221, 137, 0, 0, 16, 16, 10, 8, 10, 4, 221, 172, 0, 0, 16, 14, 10, 8, 10, 4, 221, 176, 0, 0, 16, 13, 10, 8, 10, 4, 221, 192, 0, 0, 16, 15, 10, 8, 10, 4, 221, 194, 0, 0, 16, 16, 10, 8, 10, 4, 221, 195, 0, 0, 16, 16, 10, 8, 10, 4, 221, 196, 0, 0, 16, 15, 10, 8, 10, 4, 221, 198, 0, 0, 16, 16, 10, 8, 10, 4, 221, 199, 0, 0, 16, 19, 10, 8, 10, 4, 221, 199, 32, 0, 16, 20, 10, 8, 10, 4, 221, 199, 48, 0, 16, 20, 10, 8, 10, 4, 221, 199, 64, 0, 16, 18, 10, 8, 10, 4, 221, 199, 128, 0, 16, 18, 10, 8, 10, 4, 221, 199, 192, 0, 16, 20, 10, 8, 10, 4, 221, 199, 224, 0, 16, 19, 10, 8, 10, 4, 221, 200, 0, 0, 16, 14, 10, 8, 10, 4, 221, 204, 0, 0, 16, 15, 10, 8, 10, 4, 221, 206, 0, 0, 16, 16, 10, 8, 10, 4, 221, 207, 0, 0, 16, 18, 10, 8, 10, 4, 221, 207, 64, 0, 16, 18, 10, 8, 10, 4, 221, 207, 128, 0, 16, 17, 10, 8, 10, 4, 221, 208, 0, 0, 16, 14, 10, 8, 10, 4, 221, 212, 0, 0, 16, 16, 10, 8, 10, 4, 221, 213, 0, 0, 16, 16, 10, 8, 10, 4, 221, 214, 0, 0, 16, 15, 10, 8, 10, 4, 221, 216, 0, 0, 16, 13, 10, 8, 10, 4, 221, 224, 0, 0, 16, 13, 10, 8, 10, 4, 221, 232, 0, 0, 16, 14, 10, 8, 10, 4, 221, 236, 0, 0, 16, 15, 10, 8, 10, 4, 221, 238, 0, 0, 16, 16, 10, 8, 10, 4, 221, 239, 0, 0, 16, 17, 10, 8, 10, 4, 221, 239, 128, 0, 16, 17, 10, 8, 10, 4, 222, 16, 0, 0, 16, 15, 10, 8, 10, 4, 222, 18, 0, 0, 16, 15, 10, 8, 10, 4, 222, 20, 0, 0, 16, 15, 10, 8, 10, 4, 222, 22, 0, 0, 16, 16, 10, 8, 10, 4, 222, 23, 0, 0, 16, 16, 10, 8, 10, 4, 222, 24, 0, 0, 16, 15, 10, 8, 10, 4, 222, 26, 0, 0, 16, 15, 10, 8, 10, 4, 222, 28, 0, 0, 16, 14, 10, 8, 10, 4, 222, 32, 0, 0, 16, 11, 10, 8, 10, 4, 222, 64, 0, 0, 16, 13, 10, 8, 10, 4, 222, 72, 0, 0, 16, 15, 10, 8, 10, 4, 222, 74, 0, 0, 16, 16, 10, 8, 10, 4, 222, 75, 0, 0, 16, 16, 10, 8, 10, 4, 222, 76, 0, 0, 16, 14, 10, 8, 10, 4, 222, 80, 0, 0, 16, 15, 10, 8, 10, 4, 222, 82, 0, 0, 16, 16, 10, 8, 10, 4, 222, 83, 0, 0, 16, 17, 10, 8, 10, 4, 222, 83, 128, 0, 16, 17, 10, 8, 10, 4, 222, 84, 0, 0, 16, 16, 10, 8, 10, 4, 222, 85, 0, 0, 16, 17, 10, 8, 10, 4, 222, 85, 128, 0, 16, 17, 10, 8, 10, 4, 222, 86, 0, 0, 16, 15, 10, 8, 10, 4, 222, 88, 0, 0, 16, 15, 10, 8, 10, 4, 222, 90, 0, 0, 16, 15, 10, 8, 10, 4, 222, 92, 0, 0, 16, 14, 10, 8, 10, 4, 222, 125, 0, 0, 16, 16, 10, 8, 10, 4, 222, 126, 128, 0, 16, 17, 10, 8, 10, 4, 222, 128, 0, 0, 16, 14, 10, 8, 10, 4, 222, 132, 0, 0, 16, 14, 10, 8, 10, 4, 222, 136, 0, 0, 16, 13, 10, 8, 10, 4, 222, 160, 0, 0, 16, 15, 10, 8, 10, 4, 222, 162, 0, 0, 16, 16, 10, 8, 10, 4, 222, 163, 0, 0, 16, 19, 10, 8, 10, 4, 222, 163, 32, 0, 16, 19, 10, 8, 10, 4, 222, 163, 64, 0, 16, 18, 10, 8, 10, 4, 222, 163, 128, 0, 16, 17, 10, 8, 10, 4, 222, 168, 0, 0, 16, 15, 10, 8, 10, 4, 222, 170, 0, 0, 16, 15, 10, 8, 10, 4, 222, 172, 0, 0, 16, 17, 10, 8, 10, 4, 222, 172, 128, 0, 16, 17, 10, 8, 10, 4, 222, 173, 0, 0, 16, 16, 10, 8, 10, 4, 222, 174, 0, 0, 16, 15, 10, 8, 10, 4, 222, 176, 0, 0, 16, 13, 10, 8, 10, 4, 222, 184, 0, 0, 16, 13, 10, 8, 10, 4, 222, 192, 0, 0, 16, 14, 10, 8, 10, 4, 222, 196, 0, 0, 16, 15, 10, 8, 10, 4, 222, 198, 0, 0, 16, 16, 10, 8, 10, 4, 222, 199, 0, 0, 16, 16, 10, 8, 10, 4, 222, 200, 0, 0, 16, 14, 10, 8, 10, 4, 222, 204, 0, 0, 16, 15, 10, 8, 10, 4, 222, 206, 0, 0, 16, 15, 10, 8, 10, 4, 222, 208, 0, 0, 16, 13, 10, 8, 10, 4, 222, 216, 0, 0, 16, 15, 10, 8, 10, 4, 222, 218, 0, 0, 16, 16, 10, 8, 10, 4, 222, 219, 0, 0, 16, 16, 10, 8, 10, 4, 222, 220, 0, 0, 16, 15, 10, 8, 10, 4, 222, 222, 0, 0, 16, 15, 10, 8, 10, 4, 222, 240, 0, 0, 16, 13, 10, 8, 10, 4, 222, 248, 0, 0, 16, 16, 10, 8, 10, 4, 222, 249, 0, 0, 16, 17, 10, 8, 10, 4, 222, 249, 128, 0, 16, 19, 10, 8, 10, 4, 222, 249, 160, 0, 16, 20, 10, 8, 10, 4, 222, 249, 176, 0, 16, 20, 10, 8, 10, 4, 222, 249, 192, 0, 16, 18, 10, 8, 10, 4, 223, 0, 0, 0, 16, 15, 10, 8, 10, 4, 223, 2, 0, 0, 16, 15, 10, 8, 10, 4, 223, 4, 0, 0, 16, 14, 10, 8, 10, 4, 223, 8, 0, 0, 16, 13, 10, 8, 10, 4, 223, 20, 0, 0, 16, 15, 10, 8, 10, 4, 223, 27, 184, 0, 16, 22, 10, 8, 10, 4, 223, 29, 208, 0, 16, 22, 10, 8, 10, 4, 223, 29, 252, 0, 16, 22, 10, 8, 10, 4, 223, 64, 0, 0, 16, 11, 10, 8, 10, 4, 223, 96, 0, 0, 16, 12, 10, 8, 10, 4, 223, 112, 0, 0, 16, 14, 10, 8, 10, 4, 223, 116, 0, 0, 16, 15, 10, 8, 10, 4, 223, 120, 0, 0, 16, 13, 10, 8, 10, 4, 223, 128, 0, 0, 16, 15, 10, 8, 10, 4, 223, 130, 8, 0, 16, 22, 10, 8, 10, 4, 223, 144, 0, 0, 16, 12, 10, 8, 10, 4, 223, 160, 0, 0, 16, 14, 10, 8, 10, 4, 223, 166, 0, 0, 16, 15, 10, 8, 10, 4, 223, 192, 0, 0, 16, 15, 10, 8, 10, 4, 223, 198, 0, 0, 16, 15, 10, 8, 10, 4, 223, 201, 0, 0, 16, 16, 10, 8, 10, 4, 223, 202, 0, 0, 16, 15, 10, 8, 10, 4, 223, 208, 0, 0, 16, 14, 10, 8, 10, 4, 223, 212, 0, 0, 16, 15, 10, 8, 10, 4, 223, 214, 0, 0, 16, 15, 10, 8, 10, 4, 223, 220, 0, 0, 16, 15, 10, 8, 10, 4, 223, 223, 176, 0, 16, 20, 10, 8, 10, 4, 223, 223, 192, 0, 16, 20, 10, 8, 10, 4, 223, 240, 0, 0, 16, 13, 10, 8, 10, 4, 223, 248, 0, 0, 16, 14, 10, 8, 10, 4, 223, 252, 128, 0, 16, 17, 10, 8, 10, 4, 223, 254, 0, 0, 16, 16, 10, 8, 10, 4, 223, 255, 0, 0, 16, 17, 10, 8, 10, 4, 223, 255, 236, 0, 16, 22, 10, 8, 10, 4, 223, 255, 252, 0, 16, 23} diff --git a/tools/geoip/geoip.go b/tools/geoip/geoip.go deleted file mode 100644 index 4276ecc60..000000000 --- a/tools/geoip/geoip.go +++ /dev/null @@ -1,3 +0,0 @@ -package geoip - -//go:generate go run geoip_gen.go diff --git a/tools/geoip/geoip.pb.go b/tools/geoip/geoip.pb.go deleted file mode 100644 index 945d6c480..000000000 --- a/tools/geoip/geoip.pb.go +++ /dev/null @@ -1,55 +0,0 @@ -package geoip - -import proto "github.com/golang/protobuf/proto" -import fmt "fmt" -import math "math" -import v2ray_core_app_router "v2ray.com/core/app/router" - -// Reference imports to suppress errors if they are not otherwise used. -var _ = proto.Marshal -var _ = fmt.Errorf -var _ = math.Inf - -// This is a compile-time assertion to ensure that this generated file -// is compatible with the proto package it is being compiled against. -// A compilation error at this line likely means your copy of the -// proto package needs to be updated. -const _ = proto.ProtoPackageIsVersion2 // please upgrade the proto package - -type CountryIPRange struct { - Ips []*v2ray_core_app_router.CIDR `protobuf:"bytes,1,rep,name=ips" json:"ips,omitempty"` -} - -func (m *CountryIPRange) Reset() { *m = CountryIPRange{} } -func (m *CountryIPRange) String() string { return proto.CompactTextString(m) } -func (*CountryIPRange) ProtoMessage() {} -func (*CountryIPRange) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{0} } - -func (m *CountryIPRange) GetIps() []*v2ray_core_app_router.CIDR { - if m != nil { - return m.Ips - } - return nil -} - -func init() { - proto.RegisterType((*CountryIPRange)(nil), "v2ray.core.tools.geoip.CountryIPRange") -} - -func init() { proto.RegisterFile("v2ray.com/core/tools/geoip/geoip.proto", fileDescriptor0) } - -var fileDescriptor0 = []byte{ - // 184 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0x52, 0x2b, 0x33, 0x2a, 0x4a, - 0xac, 0xd4, 0x4b, 0xce, 0xcf, 0xd5, 0x4f, 0xce, 0x2f, 0x4a, 0xd5, 0x2f, 0xc9, 0xcf, 0xcf, 0x29, - 0xd6, 0x4f, 0x4f, 0xcd, 0xcf, 0x2c, 0x80, 0x90, 0x7a, 0x05, 0x45, 0xf9, 0x25, 0xf9, 0x42, 0x62, - 0x30, 0x75, 0x45, 0xa9, 0x7a, 0x60, 0x35, 0x7a, 0x60, 0x59, 0x29, 0x74, 0xfd, 0x89, 0x05, 0x05, - 0xfa, 0x45, 0xf9, 0xa5, 0x25, 0xa9, 0x45, 0xfa, 0xc9, 0xf9, 0x79, 0x69, 0x99, 0xe9, 0x10, 0xfd, - 0x4a, 0xf6, 0x5c, 0x7c, 0xce, 0xf9, 0xa5, 0x79, 0x25, 0x45, 0x95, 0x9e, 0x01, 0x41, 0x89, 0x79, - 0xe9, 0xa9, 0x42, 0xba, 0x5c, 0xcc, 0x99, 0x05, 0xc5, 0x12, 0x8c, 0x0a, 0xcc, 0x1a, 0xdc, 0x46, - 0xd2, 0x7a, 0x48, 0xe6, 0x27, 0x16, 0x14, 0xe8, 0x41, 0xcc, 0xd0, 0x73, 0xf6, 0x74, 0x09, 0x0a, - 0x02, 0xa9, 0x73, 0xb2, 0xe3, 0x92, 0x4a, 0xce, 0xcf, 0xd5, 0xc3, 0xee, 0x8c, 0x00, 0xc6, 0x28, - 0x56, 0x30, 0x63, 0x15, 0x93, 0x58, 0x98, 0x51, 0x50, 0x62, 0xa5, 0x9e, 0x33, 0x48, 0x45, 0x08, - 0x58, 0x85, 0x3b, 0x48, 0x22, 0x89, 0x0d, 0xec, 0x0e, 0x63, 0x40, 0x00, 0x00, 0x00, 0xff, 0xff, - 0xe5, 0xf7, 0xf0, 0xf6, 0xf1, 0x00, 0x00, 0x00, -} diff --git a/tools/geoip/geoip.proto b/tools/geoip/geoip.proto deleted file mode 100644 index 10691bc69..000000000 --- a/tools/geoip/geoip.proto +++ /dev/null @@ -1,13 +0,0 @@ -syntax = "proto3"; - -package v2ray.core.tools.geoip; -option csharp_namespace = "V2Ray.Core.Tools.Geoip"; -option go_package = "geoip"; -option java_package = "com.v2ray.core.tools.geoip"; -option java_multiple_files = true; - -import "v2ray.com/core/app/router/config.proto"; - -message CountryIPRange { - repeated v2ray.core.app.router.CIDR ips = 1; -} \ No newline at end of file diff --git a/tools/geoip/geoip_gen.go b/tools/geoip/geoip_gen.go deleted file mode 100644 index 0c56ddda5..000000000 --- a/tools/geoip/geoip_gen.go +++ /dev/null @@ -1,92 +0,0 @@ -// +build generate - -package main - -import ( - "bufio" - "fmt" - "log" - "math" - "net" - "net/http" - "os" - "strconv" - "strings" - - "v2ray.com/core/app/router" - "v2ray.com/core/common" - "v2ray.com/core/common/errors" - "v2ray.com/core/tools/geoip" - - "github.com/golang/protobuf/proto" -) - -const ( - apnicFile = "http://ftp.apnic.net/apnic/stats/apnic/delegated-apnic-latest" -) - -func main() { - resp, err := http.Get(apnicFile) - common.Must(err) - if resp.StatusCode != 200 { - panic(errors.New("unexpected status ", resp.StatusCode)) - } - defer resp.Body.Close() - scanner := bufio.NewScanner(resp.Body) - - ips := &geoip.CountryIPRange{ - Ips: make([]*router.CIDR, 0, 8192), - } - for scanner.Scan() { - line := scanner.Text() - line = strings.TrimSpace(line) - parts := strings.Split(line, "|") - if len(parts) < 5 { - continue - } - if strings.ToLower(parts[1]) != "cn" || strings.ToLower(parts[2]) != "ipv4" { - continue - } - ip := parts[3] - count, err := strconv.Atoi(parts[4]) - if err != nil { - continue - } - mask := uint32(math.Floor(math.Log2(float64(count)) + 0.5)) - ipBytes := net.ParseIP(ip) - if len(ipBytes) == 0 { - panic("Invalid IP " + ip) - } - ips.Ips = append(ips.Ips, &router.CIDR{ - Ip: []byte(ipBytes)[12:16], - Prefix: 32 - mask, - }) - } - - ipbytes, err := proto.Marshal(ips) - if err != nil { - log.Fatalf("Failed to marshal country IPs: %v", err) - } - - file, err := os.OpenFile("geoip.generated.go", os.O_WRONLY|os.O_TRUNC|os.O_CREATE, 0644) - if err != nil { - log.Fatalf("Failed to generate geoip_data.go: %v", err) - } - defer file.Close() - - fmt.Fprintln(file, "package geoip") - - fmt.Fprintln(file, "var ChinaIPs = "+formatArray(ipbytes)) -} - -func formatArray(a []byte) string { - r := "[]byte{" - for idx, val := range a { - if idx > 0 { - r += "," - } - r += fmt.Sprintf("%d", val) - } - r += "}" - return r -} diff --git a/tools/release/config/geoip.dat b/tools/release/config/geoip.dat new file mode 100755 index 000000000..b83c93765 Binary files /dev/null and b/tools/release/config/geoip.dat differ diff --git a/tools/release/config/geosite.dat b/tools/release/config/geosite.dat new file mode 100755 index 000000000..b66d6212b --- /dev/null +++ b/tools/release/config/geosite.dat @@ -0,0 +1,113 @@ + +; +CNcn +xn--fiqs8s  10010.com 100offer.com 115.com 123juzi.com 123juzi.net 123u.com 126.com 126.net 127.net 163.com  17173.com  17cdn.com 188.com 1905.com 21cn.com 2288.org 2345.com 263.net 2cto.com 3322.org +35.com +360doc.com +360buy.com 360buyimg.com 360safe.com 36kr.com +39.net 3dmgame.com 3conline.com 4399.com 500d.me +50bang.org 51.la 51credit.com  51cto.com51jingying.com  51job.com 51jobcdn.com 51wendang.com +55.com  51yes.com  55bbs.com +58.com +6rooms.com 71.am 7k7k.com +900.la 9718.com 9xu.com abchina.com acfun.tv acgvideo.com agrantsem.com  aicdn.com aixifan.com alibaba.com +alicdn.comaliimg.com.com +alipay.comalipayobjects.com +aliyun.com aliyuncdn.com aliyuncs.com +allyes.com amap.com +anjuke.com +anquan.org +appinn.com babytree.combabytreeimg.com  baidu.combaiducontent.com baidupcs.combaidustatic.combaifendian.com baifubao.com  baihe.com  baike.com baixing.com baixing.net bankcomm.combankofchina.com bcy.net  bdimg.com bdstatic.com bilibili.com cn.bing.com bitauto.combitautoimg.com bobo.com bootcss.com btcfans.com caiyunapp.com ccb.com cctv.com cctvpic.com  cdn20.com cebbank.com +ch.com chashebao.com +che168.com  china.comchinacache.comchinacache.net chinahr.comchinamobile.com chinapay.comchinatranslation.net +chinaz.com chiphell.com +chouti.com chuangxin.com chuansong.me clouddn.com cloudxns.com cmbchina.com +cnbeta.com cnbetacdn.com cnblogs.com +cnepub.com cnzz.com +coding.net coolapk.com  cqvip.com  csbew.com csdn.net +ctfile.com  ctrip.com +cubead.com  dajie.com dajieimg.com dangdang.com daocloud.io daovoice.io  dbank.com dedecms.com  dgtle.com diandian.com dianping.com +diopic.net  docin.com dockerone.com +dockone.io +donews.com +douban.com  douban.fm doubanio.com +dpfile.com +duomai.com duoshuo.com +duowan.com dxpmedia.com eastday.com +ecitic.com emarbox.comeoeandroid.com etao.com excelhome.net  fanli.com feng.com fengniao.com +fhldns.com foxmail.com geekpark.net geetest.com geilicdn.com  getui.comgoogle-analytics.com growingio.com  gtags.net +gwdang.com +hao123.com hao123img.com +haosou.com  hdslb.com  henha.com henkuai.com  hexun.com hichina.com huanqiu.com hunantv.comhuochepiao.com hupu.com hupucdn.com  huxiu.com iask.com  iciba.com idqqimg.com  ifanr.comifanrusercontent.com +ifanrx.com  ifeng.com ifengimg.com ijinshan.com +ikafan.com +imedao.com imgo.tv  imooc.com  infoq.cominfoqstatic.com  ip138.com ipinyou.com ipip.net +ip-cdn.com  iqiyi.com  irs01.com  it165.net  it168.com  it610.com  iteye.com +ithome.com +itjuzi.com +jandan.net +jd.com jb51.com jia.com jianshu.com +jianshu.io jiasuhui.com jiathis.com jiayuan.comjikexueyuan.com jisuanke.com jmstatic.com jsdelivr.net jstv.com  jumei.com  jyimg.com kaixin001.com +kanimg.com kankanews.com  kejet.net kf5.com +kimiss.com +kouclo.com +koudai.com koudai8.com ku6.com +ku6cdn.com +ku6img.com  kuqin.com lady8844.com  lagou.com +le.com leanote.com leiphone.com leju.com leturich.org letv.com letvcdn.com letvimg.com  liantu.meliaoxuefeng.com liba.com libaclub.com +liepin.com +lietou.com lightonus.com linkvans.com linuxidc.com liuxiaoer.com +lofter.com +lu.com  lufax.com lufaxcdn.com +lvmama.com  lxdns.com  lxway.com +ly.com +mayihr.com mechina.org +mediav.com +meiqia.com meika360.com meilishuo.com meishij.net meituan.com  meizu.com mgtv.com +mi.com miaopai.com miaozhen.com miui.com +mmbang.com mmbang.info +mmstat.com mogucdn.com mogujie.com mop.com +mscbsc.com mukewang.com mydrivers.com myshow360.net mzstatic.com netease.comnewbandeng.com ngacn.cc ntalker.com nvsheng.com  oeeee.com +ol-img.com +oneapm.comonlinedown.netonlinesjtu.com oschina.net +paipai.com +pcbeta.com +pchome.net +pingan.compingplusplus.com +pps.tv psbc.com +pubyun.com qbox.me +qcloud.com  qhimg.com  qhres.comqiaobutang.com +qidian.com qihucdn.com qingcloud.comqingsongchou.com  qiniu.com qiniucdn.com qiniudn.com qiniudns.com qiyi.com qiyipic.com +qtmojo.com +qq.com +qqmail.com  qunar.com qunarzz.com  qzone.com +renren.com +runoob.com ruanmei.comruby-china.org +sandai.net sanguosha.com +sanwen.netsegmentfault.comsf-express.com sharejs.com shmetro.com +shutcm.com +simei8.com sina.com sinaapp.com sinaedge.com sinaimg.com +sinajs.com szzfgjj.com  smzdm.com sohu.com  sogou.com sogoucdn.com soso.com  sspai.com starbaby.cc starbaby.comstaticfile.org stockstar.com +suning.com szfw.org t1y5.com tanx.com +tao123.com +taobao.com taobaocdn.com tbcache.com tencent.com +tenpay.com tenxcloud.com tiebaimg.com tietuku.com +tiexue.net  tmall.com  tmcdn.net topthink.com  tudou.com tudouui.com tuicool.com  tuniu.com tutuapp.com u17.com  useso.com unionpay.comunionpaysecure.com  upyun.com upaiyun.com v2ex.com  v5875.com vamaker.com  vancl.com  vcimg.com vip.comwallstreetcn.com wandoujia.com +wdjimg.com  weand.com webterren.com  weibo.com weicaifu.com weidian.com weiphone.com weiphone.net weixing.com +weiyun.com wonnder.com worktile.com +wooyun.org wrating.com +wscdns.com  wumii.comxiachufang.com  xiami.com xiaokaxiu.com +xiaomi.com xitu.com xinhuanet.com xinshipu.com xiu8.com  xnpic.com +xueqiu.com +xunlei.com xywy.com +yaolan.com  yccdn.com +yeepay.com  yesky.com  yigao.com yihaodian.comyihaodianimg.comyingjiesheng.com yinxiang.com yinyuetai.com yixi.tv  yjbys.com yhd.com +youboy.com  youku.com yunba.io yundaex.com yunshipei.com  yupoo.com  yuzua.com +yy.com +yytcdn.com +zampda.net zastatic.com +zbjimg.com +zdfans.com +zdmimg.com +zhenai.com  zhanqi.tv zhaopin.com  zhihu.com  zhimg.com zhiziyun.com  zjstv.com zhubajie.com +zrblog.net  zuche.com zuchecdn.com \ No newline at end of file diff --git a/tools/release/config/vpoint_socks_vmess.json b/tools/release/config/vpoint_socks_vmess.json index 27f7834c6..d8a09ae6b 100644 --- a/tools/release/config/vpoint_socks_vmess.json +++ b/tools/release/config/vpoint_socks_vmess.json @@ -18,7 +18,7 @@ "vnext": [ { "address": "v2ray.cool", - "port": 10086, + "port": 443, "users": [ { "id": "a3482e88-686a-4a58-8126-99c9df64b7bf", @@ -31,6 +31,17 @@ }, "mux": { "enabled": true + }, + "streamSettings": { + "network": "ws", + "security": "tls", + "tlsSettings": { + "serverName": "v2ray.cool", + "allowInsecure": true + }, + "wsSettings": { + "path": "/v2ray.cool/" + } } }, "outboundDetour": [ @@ -73,7 +84,8 @@ "outboundTag": "direct" }, { - "type": "chinasites", + "type": "field", + "domain": ["geosite:cn"], "outboundTag": "direct" }, { @@ -93,13 +105,10 @@ "203.0.113.0/24", "::1/128", "fc00::/7", - "fe80::/10" + "fe80::/10", + "geoip:cn" ], "outboundTag": "direct" - }, - { - "type": "chinaip", - "outboundTag": "direct" } ] } diff --git a/tools/release/make-release.sh b/tools/release/make-release.sh index df1ea1efd..387e1bdcf 100755 --- a/tools/release/make-release.sh +++ b/tools/release/make-release.sh @@ -41,4 +41,6 @@ gcloud compute instances create "v2raycore-${RAND}" \ --metadata=release_tag=v${VER},prerelease=${PRE} \ --metadata-from-file=startup-script=${DIR}/release-ci.sh \ --zone=us-central1-c \ - --project ${PROJECT} + --project ${PROJECT} \ + --scopes "https://www.googleapis.com/auth/compute,https://www.googleapis.com/auth/devstorage.read_write" \ + diff --git a/tools/release/release-ci.sh b/tools/release/release-ci.sh index bf3e71adc..e74e77a1c 100755 --- a/tools/release/release-ci.sh +++ b/tools/release/release-ci.sh @@ -3,7 +3,7 @@ set -x apt-get update -apt-get -y install jq git file +apt-get -y install jq git file p7zip-full dbus function getattr() { curl -s -H "Metadata-Flavor: Google" http://metadata.google.internal/computeMetadata/v1/$2/attributes/$1 @@ -25,7 +25,7 @@ echo ${SIGN_KEY_PASS} | gpg --passphrase-fd 0 --batch --import /v2ray/build/sign curl -L -o /v2ray/build/releases https://api.github.com/repos/v2ray/v2ray-core/releases GO_INSTALL=golang.tar.gz -curl -L -o ${GO_INSTALL} https://storage.googleapis.com/golang/go1.9.linux-amd64.tar.gz +curl -L -o ${GO_INSTALL} https://storage.googleapis.com/golang/go1.9.2.linux-amd64.tar.gz tar -C /usr/local -xzf ${GO_INSTALL} export PATH=$PATH:/usr/local/go/bin @@ -45,23 +45,26 @@ export TRAVIS_TAG=${RELEASE_TAG} export GPG_SIGN_PASS=${SIGN_KEY_PASS} export V_USER=${VUSER} -$GOPATH/bin/vbuild --os=windows --arch=x86 --zip --sign -$GOPATH/bin/vbuild --os=windows --arch=x64 --zip --sign -$GOPATH/bin/vbuild --os=macos --arch=x64 --zip --sign -$GOPATH/bin/vbuild --os=linux --arch=x86 --zip --sign -$GOPATH/bin/vbuild --os=linux --arch=x64 --zip --sign -$GOPATH/bin/vbuild --os=linux --arch=arm --zip --sign -$GOPATH/bin/vbuild --os=linux --arch=arm64 --zip --sign -$GOPATH/bin/vbuild --os=linux --arch=mips64 --zip --sign -$GOPATH/bin/vbuild --os=linux --arch=mips64le --zip --sign -$GOPATH/bin/vbuild --os=linux --arch=mips --zip --sign -$GOPATH/bin/vbuild --os=linux --arch=mipsle --zip --sign -$GOPATH/bin/vbuild --os=freebsd --arch=x86 --zip --sign -$GOPATH/bin/vbuild --os=freebsd --arch=amd64 --zip --sign -$GOPATH/bin/vbuild --os=openbsd --arch=x86 --zip --sign -$GOPATH/bin/vbuild --os=openbsd --arch=amd64 --zip --sign +$GOPATH/bin/vbuild --os=windows --arch=x86 --zip --sign #--encrypt +$GOPATH/bin/vbuild --os=windows --arch=x64 --zip --sign #--encrypt +$GOPATH/bin/vbuild --os=macos --arch=x64 --zip --sign #--encrypt +$GOPATH/bin/vbuild --os=linux --arch=x86 --zip --sign #--encrypt +$GOPATH/bin/vbuild --os=linux --arch=x64 --zip --sign #--encrypt +$GOPATH/bin/vbuild --os=linux --arch=arm --zip --sign #--encrypt +$GOPATH/bin/vbuild --os=linux --arch=arm64 --zip --sign #--encrypt +$GOPATH/bin/vbuild --os=linux --arch=mips64 --zip --sign #--encrypt +$GOPATH/bin/vbuild --os=linux --arch=mips64le --zip --sign #--encrypt +$GOPATH/bin/vbuild --os=linux --arch=mips --zip --sign #--encrypt +$GOPATH/bin/vbuild --os=linux --arch=mipsle --zip --sign #--encrypt +$GOPATH/bin/vbuild --os=freebsd --arch=x86 --zip --sign #--encrypt +$GOPATH/bin/vbuild --os=freebsd --arch=amd64 --zip --sign #--encrypt +$GOPATH/bin/vbuild --os=openbsd --arch=x86 --zip --sign #--encrypt +$GOPATH/bin/vbuild --os=openbsd --arch=amd64 --zip --sign #--encrypt -JSON_DATA=$(printf '{"tag_name": "%s", "prerelease": %s}' ${RELEASE_TAG} ${PRERELEASE}) +#RELBODY=$(cat $GOPATH/bin/metadata.txt | jq -R -s -c .) +JSON_DATA=$(echo "{}" | jq -c ".tag_name=\"${RELEASE_TAG}\"") +JSON_DATA=$(echo ${JSON_DATA} | jq -c ".prerelease=${PRERELEASE}") +#JSON_DATA=$(echo ${JSON_DATA} | jq -c ".body=${RELBODY}") RELEASE_ID=$(curl --data "${JSON_DATA}" -H "Authorization: token ${GITHUB_TOKEN}" -X POST https://api.github.com/repos/v2ray/v2ray-core/releases | jq ".id") function upload() { @@ -89,25 +92,10 @@ upload $GOPATH/bin/metadata.txt if [[ "${PRERELEASE}" == "false" ]]; then -INSTALL_DIR=/v2ray/src/github.com/v2ray/install - -git clone "https://github.com/v2ray/install.git" ${INSTALL_DIR} - -#RELEASE_DIR=${INSTALL_DIR}/releases/${RELEASE_TAG} -#mkdir -p ${RELEASE_DIR}/ -#cp $GOPATH/bin/metadata.txt ${RELEASE_DIR}/ -#cp $GOPATH/bin/v2ray-*.zip ${RELEASE_DIR}/ -#echo ${RELEASE_TAG} > ${INSTALL_DIR}/releases/latest.txt - -cp $GOPATH/bin/v2ray-${RELEASE_TAG}-linux-64/v2ray ${INSTALL_DIR}/docker/official/ - -pushd ${INSTALL_DIR} -git config user.name "V2Ray Auto Build" -git config user.email "admin@v2ray.com" -git add -A -git commit -m "Update for ${RELEASE_TAG}" -git push "https://${GITHUB_TOKEN}@github.com/v2ray/install.git" master -popd +gsutil cp $GOPATH/bin/v2ray-${RELEASE_TAG}-linux-64/v2ray gs://v2ray-docker/ +gsutil cp $GOPATH/bin/v2ray-${RELEASE_TAG}-linux-64/v2ctl gs://v2ray-docker/ +gsutil cp $GOPATH/bin/v2ray-${RELEASE_TAG}-linux-64/geoip.dat gs://v2ray-docker/ +gsutil cp $GOPATH/bin/v2ray-${RELEASE_TAG}-linux-64/geosite.dat gs://v2ray-docker/ DOCKER_HUB_API=https://registry.hub.docker.com/u/v2ray/official/trigger/${DOCKER_HUB_KEY}/ curl -H "Content-Type: application/json" --data '{"build": true}' -X POST "${DOCKER_HUB_API}" diff --git a/transport/internet/config.go b/transport/internet/config.go index 55a11e08d..72d20f8e1 100644 --- a/transport/internet/config.go +++ b/transport/internet/config.go @@ -23,22 +23,22 @@ func CreateTransportConfig(protocol TransportProtocol) (interface{}, error) { return creator(), nil } -func (v *TransportConfig) GetTypedSettings() (interface{}, error) { - return v.Settings.GetInstance() +func (c *TransportConfig) GetTypedSettings() (interface{}, error) { + return c.Settings.GetInstance() } -func (v *StreamConfig) GetEffectiveProtocol() TransportProtocol { - if v == nil { +func (c *StreamConfig) GetEffectiveProtocol() TransportProtocol { + if c == nil { return TransportProtocol_TCP } - return v.Protocol + return c.Protocol } -func (v *StreamConfig) GetEffectiveTransportSettings() (interface{}, error) { - protocol := v.GetEffectiveProtocol() +func (c *StreamConfig) GetEffectiveTransportSettings() (interface{}, error) { + protocol := c.GetEffectiveProtocol() - if v != nil { - for _, settings := range v.TransportSettings { + if c != nil { + for _, settings := range c.TransportSettings { if settings.Protocol == protocol { return settings.GetTypedSettings() } @@ -71,17 +71,17 @@ func (c *StreamConfig) GetTransportSettingsFor(protocol TransportProtocol) (inte return CreateTransportConfig(protocol) } -func (v *StreamConfig) GetEffectiveSecuritySettings() (interface{}, error) { - for _, settings := range v.SecuritySettings { - if settings.Type == v.SecurityType { +func (c *StreamConfig) GetEffectiveSecuritySettings() (interface{}, error) { + for _, settings := range c.SecuritySettings { + if settings.Type == c.SecurityType { return settings.GetInstance() } } - return serial.GetInstance(v.SecurityType) + return serial.GetInstance(c.SecurityType) } -func (v *StreamConfig) HasSecuritySettings() bool { - return len(v.SecurityType) > 0 +func (c *StreamConfig) HasSecuritySettings() bool { + return len(c.SecurityType) > 0 } func ApplyGlobalTransportSettings(settings []*TransportConfig) error { @@ -89,6 +89,6 @@ func ApplyGlobalTransportSettings(settings []*TransportConfig) error { return nil } -func (v *ProxyConfig) HasTag() bool { - return v != nil && len(v.Tag) > 0 +func (c *ProxyConfig) HasTag() bool { + return c != nil && len(c.Tag) > 0 } diff --git a/transport/internet/connection.go b/transport/internet/connection.go index b526f7469..2405ce1b3 100644 --- a/transport/internet/connection.go +++ b/transport/internet/connection.go @@ -4,12 +4,6 @@ import ( "net" ) -type ConnectionHandler func(Connection) - type Connection interface { net.Conn } - -type SysFd interface { - SysFd() (int, error) -} diff --git a/transport/internet/dialer_test.go b/transport/internet/dialer_test.go index deabfbbdc..dbc9e587c 100644 --- a/transport/internet/dialer_test.go +++ b/transport/internet/dialer_test.go @@ -5,21 +5,21 @@ import ( "testing" "v2ray.com/core/common/net" - "v2ray.com/core/testing/assert" "v2ray.com/core/testing/servers/tcp" . "v2ray.com/core/transport/internet" + . "v2ray.com/ext/assert" ) func TestDialWithLocalAddr(t *testing.T) { - assert := assert.On(t) + assert := With(t) server := &tcp.Server{} dest, err := server.Start() - assert.Error(err).IsNil() + assert(err, IsNil) defer server.Close() conn, err := DialSystem(context.Background(), net.LocalHostIP, net.TCPDestination(net.LocalHostIP, dest.Port)) - assert.Error(err).IsNil() - assert.String(conn.RemoteAddr().String()).Equals("127.0.0.1:" + dest.Port.String()) + assert(err, IsNil) + assert(conn.RemoteAddr().String(), Equals, "127.0.0.1:"+dest.Port.String()) conn.Close() } diff --git a/transport/internet/header_test.go b/transport/internet/header_test.go index d4a13e4e2..65a7afa19 100644 --- a/transport/internet/header_test.go +++ b/transport/internet/header_test.go @@ -3,25 +3,25 @@ package internet_test import ( "testing" - "v2ray.com/core/testing/assert" . "v2ray.com/core/transport/internet" "v2ray.com/core/transport/internet/headers/noop" "v2ray.com/core/transport/internet/headers/srtp" "v2ray.com/core/transport/internet/headers/utp" + . "v2ray.com/ext/assert" ) func TestAllHeadersLoadable(t *testing.T) { - assert := assert.On(t) + assert := With(t) noopAuth, err := CreatePacketHeader((*noop.Config)(nil)) - assert.Error(err).IsNil() - assert.Int(noopAuth.Size()).Equals(0) + assert(err, IsNil) + assert(noopAuth.Size(), Equals, 0) srtp, err := CreatePacketHeader((*srtp.Config)(nil)) - assert.Error(err).IsNil() - assert.Int(srtp.Size()).Equals(4) + assert(err, IsNil) + assert(srtp.Size(), Equals, 4) utp, err := CreatePacketHeader((*utp.Config)(nil)) - assert.Error(err).IsNil() - assert.Int(utp.Size()).Equals(4) + assert(err, IsNil) + assert(utp.Size(), Equals, 4) } diff --git a/transport/internet/headers/http/http_test.go b/transport/internet/headers/http/http_test.go index 6b805e12a..26ff5fb0f 100644 --- a/transport/internet/headers/http/http_test.go +++ b/transport/internet/headers/http/http_test.go @@ -8,31 +8,31 @@ import ( "v2ray.com/core/common/buf" "v2ray.com/core/common/net" "v2ray.com/core/common/serial" - "v2ray.com/core/testing/assert" . "v2ray.com/core/transport/internet/headers/http" + . "v2ray.com/ext/assert" ) func TestReaderWriter(t *testing.T) { - assert := assert.On(t) + assert := With(t) cache := buf.New() b := buf.NewLocal(256) b.AppendSupplier(serial.WriteString("abcd" + ENDING)) writer := NewHeaderWriter(b) err := writer.Write(cache) - assert.Error(err).IsNil() - assert.Int(cache.Len()).Equals(8) + assert(err, IsNil) + assert(cache.Len(), Equals, 8) _, err = cache.Write([]byte{'e', 'f', 'g'}) - assert.Error(err).IsNil() + assert(err, IsNil) reader := &HeaderReader{} buffer, err := reader.Read(cache) - assert.Error(err).IsNil() - assert.Bytes(buffer.Bytes()).Equals([]byte{'e', 'f', 'g'}) + assert(err, IsNil) + assert(buffer.Bytes(), Equals, []byte{'e', 'f', 'g'}) } func TestRequestHeader(t *testing.T) { - assert := assert.On(t) + assert := With(t) auth, err := NewHttpAuthenticator(context.Background(), &Config{ Request: &RequestConfig{ @@ -45,39 +45,39 @@ func TestRequestHeader(t *testing.T) { }, }, }) - assert.Error(err).IsNil() + assert(err, IsNil) cache := buf.New() err = auth.GetClientWriter().Write(cache) - assert.Error(err).IsNil() + assert(err, IsNil) - assert.String(cache.String()).Equals("GET / HTTP/1.1\r\nTest: Value\r\n\r\n") + assert(cache.String(), Equals, "GET / HTTP/1.1\r\nTest: Value\r\n\r\n") } func TestConnection(t *testing.T) { - assert := assert.On(t) + assert := With(t) auth, err := NewHttpAuthenticator(context.Background(), new(Config)) - assert.Error(err).IsNil() + assert(err, IsNil) listener, err := net.Listen("tcp", "127.0.0.1:0") - assert.Error(err).IsNil() + assert(err, IsNil) go func() { conn, err := listener.Accept() - assert.Error(err).IsNil() + assert(err, IsNil) authConn := auth.Server(conn) b := make([]byte, 256) for { n, err := authConn.Read(b) - assert.Error(err).IsNil() + assert(err, IsNil) _, err = authConn.Write(b[:n]) - assert.Error(err).IsNil() + assert(err, IsNil) } }() conn, err := net.DialTCP("tcp", nil, listener.Addr().(*net.TCPAddr)) - assert.Error(err).IsNil() + assert(err, IsNil) authConn := auth.Client(conn) authConn.Write([]byte("Test payload")) @@ -89,12 +89,12 @@ func TestConnection(t *testing.T) { totalBytes := 0 for { n, err := authConn.Read(actualResponse[totalBytes:]) - assert.Error(err).IsNil() + assert(err, IsNil) totalBytes += n if totalBytes >= len(expectedResponse) || time.Now().After(deadline) { break } } - assert.String(string(actualResponse[:totalBytes])).Equals(expectedResponse) + assert(string(actualResponse[:totalBytes]), Equals, expectedResponse) } diff --git a/transport/internet/headers/srtp/srtp_test.go b/transport/internet/headers/srtp/srtp_test.go index f0e0be2ba..db138fa52 100644 --- a/transport/internet/headers/srtp/srtp_test.go +++ b/transport/internet/headers/srtp/srtp_test.go @@ -4,12 +4,12 @@ import ( "testing" "v2ray.com/core/common/buf" - "v2ray.com/core/testing/assert" . "v2ray.com/core/transport/internet/headers/srtp" + . "v2ray.com/ext/assert" ) func TestSRTPWrite(t *testing.T) { - assert := assert.On(t) + assert := With(t) content := []byte{'a', 'b', 'c', 'd', 'e', 'f', 'g'} srtp := SRTP{} @@ -18,5 +18,5 @@ func TestSRTPWrite(t *testing.T) { payload.AppendSupplier(srtp.Write) payload.Append(content) - assert.Int(payload.Len()).Equals(len(content) + srtp.Size()) + assert(payload.Len(), Equals, len(content)+srtp.Size()) } diff --git a/transport/internet/headers/utp/utp_test.go b/transport/internet/headers/utp/utp_test.go index 3faa3bbcd..eaffb70c6 100644 --- a/transport/internet/headers/utp/utp_test.go +++ b/transport/internet/headers/utp/utp_test.go @@ -4,12 +4,12 @@ import ( "testing" "v2ray.com/core/common/buf" - "v2ray.com/core/testing/assert" . "v2ray.com/core/transport/internet/headers/utp" + . "v2ray.com/ext/assert" ) func TestUTPWrite(t *testing.T) { - assert := assert.On(t) + assert := With(t) content := []byte{'a', 'b', 'c', 'd', 'e', 'f', 'g'} utp := UTP{} @@ -18,5 +18,5 @@ func TestUTPWrite(t *testing.T) { payload.AppendSupplier(utp.Write) payload.Append(content) - assert.Int(payload.Len()).Equals(len(content) + utp.Size()) + assert(payload.Len(), Equals, len(content)+utp.Size()) } diff --git a/transport/internet/headers/wechat/wechat_test.go b/transport/internet/headers/wechat/wechat_test.go index 5bdaa04fc..9a26ffa49 100644 --- a/transport/internet/headers/wechat/wechat_test.go +++ b/transport/internet/headers/wechat/wechat_test.go @@ -4,17 +4,17 @@ import ( "testing" "v2ray.com/core/common/buf" - "v2ray.com/core/testing/assert" . "v2ray.com/core/transport/internet/headers/wechat" + . "v2ray.com/ext/assert" ) func TestUTPWrite(t *testing.T) { - assert := assert.On(t) + assert := With(t) video := VideoChat{} payload := buf.NewLocal(2048) payload.AppendSupplier(video.Write) - assert.Int(payload.Len()).Equals(video.Size()) + assert(payload.Len(), Equals, video.Size()) } diff --git a/transport/internet/kcp/connection.go b/transport/internet/kcp/connection.go index f20ab562e..5551fab6e 100644 --- a/transport/internet/kcp/connection.go +++ b/transport/internet/kcp/connection.go @@ -169,8 +169,7 @@ type SystemConnection interface { } var ( - _ buf.MultiBufferReader = (*Connection)(nil) - _ buf.MultiBufferWriter = (*Connection)(nil) + _ buf.Reader = (*Connection)(nil) ) // Connection is a KCP connection over UDP. @@ -265,7 +264,7 @@ func (v *Connection) OnDataOutput() { } } -// ReadMultiBuffer implements buf.MultiBufferReader. +// ReadMultiBuffer implements buf.Reader. func (v *Connection) ReadMultiBuffer() (buf.MultiBuffer, error) { if v == nil { return nil, io.EOF @@ -375,13 +374,6 @@ func (v *Connection) Write(b []byte) (int, error) { } } -func (c *Connection) WriteMultiBuffer(mb buf.MultiBuffer) error { - if c.mergingWriter == nil { - c.mergingWriter = buf.NewMergingWriterSize(c, c.mss) - } - return c.mergingWriter.Write(mb) -} - func (v *Connection) SetState(state State) { current := v.Elapsed() atomic.StoreInt32((*int32)(&v.state), int32(state)) diff --git a/transport/internet/kcp/connection_test.go b/transport/internet/kcp/connection_test.go index 231f6e325..f397a34f9 100644 --- a/transport/internet/kcp/connection_test.go +++ b/transport/internet/kcp/connection_test.go @@ -5,8 +5,8 @@ import ( "testing" "time" - "v2ray.com/core/testing/assert" . "v2ray.com/core/transport/internet/kcp" + . "v2ray.com/ext/assert" ) type NoOpConn struct{} @@ -51,15 +51,15 @@ func (o *NoOpConn) SetWriteDeadline(time.Time) error { func (o *NoOpConn) Reset(input func([]Segment)) {} func TestConnectionReadTimeout(t *testing.T) { - assert := assert.On(t) + assert := With(t) conn := NewConnection(1, &NoOpConn{}, &Config{}) conn.SetReadDeadline(time.Now().Add(time.Second)) b := make([]byte, 1024) nBytes, err := conn.Read(b) - assert.Int(nBytes).Equals(0) - assert.Error(err).IsNotNil() + assert(nBytes, Equals, 0) + assert(err, IsNotNil) conn.Terminate() } diff --git a/transport/internet/kcp/crypt_test.go b/transport/internet/kcp/crypt_test.go index 47ddc7b52..b3db18b8a 100644 --- a/transport/internet/kcp/crypt_test.go +++ b/transport/internet/kcp/crypt_test.go @@ -3,12 +3,12 @@ package kcp_test import ( "testing" - "v2ray.com/core/testing/assert" . "v2ray.com/core/transport/internet/kcp" + . "v2ray.com/ext/assert" ) func TestSimpleAuthenticator(t *testing.T) { - assert := assert.On(t) + assert := With(t) cache := make([]byte, 512) @@ -17,12 +17,12 @@ func TestSimpleAuthenticator(t *testing.T) { auth := NewSimpleAuthenticator() b := auth.Seal(cache[:0], nil, payload, nil) c, err := auth.Open(cache[:0], nil, b, nil) - assert.Error(err).IsNil() - assert.Bytes(c).Equals(payload) + assert(err, IsNil) + assert(c, Equals, payload) } func TestSimpleAuthenticator2(t *testing.T) { - assert := assert.On(t) + assert := With(t) cache := make([]byte, 512) @@ -31,6 +31,6 @@ func TestSimpleAuthenticator2(t *testing.T) { auth := NewSimpleAuthenticator() b := auth.Seal(cache[:0], nil, payload, nil) c, err := auth.Open(cache[:0], nil, b, nil) - assert.Error(err).IsNil() - assert.Bytes(c).Equals(payload) + assert(err, IsNil) + assert(c, Equals, payload) } diff --git a/transport/internet/kcp/dialer.go b/transport/internet/kcp/dialer.go index 1c63e5cc0..73d9a90c1 100644 --- a/transport/internet/kcp/dialer.go +++ b/transport/internet/kcp/dialer.go @@ -129,16 +129,15 @@ func DialKCP(ctx context.Context, dest net.Destination) (internet.Connection, er conv := uint16(atomic.AddUint32(&globalConv, 1)) session := NewConnection(conv, conn, kcpSettings) - var iConn internet.Connection - iConn = session + var iConn internet.Connection = session if securitySettings := internet.SecuritySettingsFromContext(ctx); securitySettings != nil { switch securitySettings := securitySettings.(type) { case *v2tls.Config: - config := securitySettings.GetTLSConfig() if dest.Address.Family().IsDomain() { - config.ServerName = dest.Address.Domain() + securitySettings.OverrideServerNameIfEmpty(dest.Address.Domain()) } + config := securitySettings.GetTLSConfig() tlsConn := tls.Client(iConn, config) iConn = tlsConn } diff --git a/transport/internet/kcp/kcp_test.go b/transport/internet/kcp/kcp_test.go index 6658d2606..d7625b3b4 100644 --- a/transport/internet/kcp/kcp_test.go +++ b/transport/internet/kcp/kcp_test.go @@ -9,13 +9,13 @@ import ( "time" "v2ray.com/core/common/net" - "v2ray.com/core/testing/assert" "v2ray.com/core/transport/internet" . "v2ray.com/core/transport/internet/kcp" + . "v2ray.com/ext/assert" ) func TestDialAndListen(t *testing.T) { - assert := assert.On(t) + assert := With(t) listerner, err := NewListener(internet.ContextWithTransportSettings(context.Background(), &Config{}), net.LocalHostIP, net.Port(0), func(ctx context.Context, conn internet.Connection) bool { go func(c internet.Connection) { @@ -34,14 +34,14 @@ func TestDialAndListen(t *testing.T) { }(conn) return true }) - assert.Error(err).IsNil() + assert(err, IsNil) port := net.Port(listerner.Addr().(*net.UDPAddr).Port) ctx := internet.ContextWithTransportSettings(context.Background(), &Config{}) wg := new(sync.WaitGroup) for i := 0; i < 10; i++ { clientConn, err := DialKCP(ctx, net.UDPDestination(net.LocalHostIP, port)) - assert.Error(err).IsNil() + assert(err, IsNil) wg.Add(1) go func() { @@ -51,14 +51,14 @@ func TestDialAndListen(t *testing.T) { clientReceived := make([]byte, 1024*1024) nBytes, _ := io.ReadFull(clientConn, clientReceived) - assert.Int(nBytes).Equals(len(clientReceived)) + assert(nBytes, Equals, len(clientReceived)) clientConn.Close() clientExpected := make([]byte, 1024*1024) for idx, b := range clientSend { clientExpected[idx] = b ^ 'c' } - assert.Bytes(clientReceived).Equals(clientExpected) + assert(clientReceived, Equals, clientExpected) wg.Done() }() @@ -68,7 +68,7 @@ func TestDialAndListen(t *testing.T) { for i := 0; i < 60 && listerner.ActiveConnections() > 0; i++ { time.Sleep(500 * time.Millisecond) } - assert.Int(listerner.ActiveConnections()).Equals(0) + assert(listerner.ActiveConnections(), Equals, 0) listerner.Close() } diff --git a/transport/internet/kcp/receiving.go b/transport/internet/kcp/receiving.go index 7c10dad57..8c281bb93 100644 --- a/transport/internet/kcp/receiving.go +++ b/transport/internet/kcp/receiving.go @@ -203,7 +203,7 @@ func (v *ReceivingWorker) ReadMultiBuffer() buf.MultiBuffer { return mb } - mb := buf.NewMultiBuffer() + mb := buf.NewMultiBufferCap(32) v.Lock() defer v.Unlock() @@ -256,7 +256,7 @@ func (v *ReceivingWorker) Write(seg Segment) error { ackSeg.Conv = v.conn.conv ackSeg.ReceivingNext = v.nextNumber ackSeg.ReceivingWindow = v.nextNumber + v.windowSize - if v.conn.state == StateReadyToClose { + if v.conn.State() == StateReadyToClose { ackSeg.Option = SegmentOptionClose } return v.conn.output.Write(ackSeg) diff --git a/transport/internet/kcp/receiving_test.go b/transport/internet/kcp/receiving_test.go index ca12143b2..21cf2c8f0 100644 --- a/transport/internet/kcp/receiving_test.go +++ b/transport/internet/kcp/receiving_test.go @@ -3,12 +3,12 @@ package kcp_test import ( "testing" - "v2ray.com/core/testing/assert" . "v2ray.com/core/transport/internet/kcp" + . "v2ray.com/ext/assert" ) func TestRecivingWindow(t *testing.T) { - assert := assert.On(t) + assert := With(t) window := NewReceivingWindow(3) @@ -17,20 +17,18 @@ func TestRecivingWindow(t *testing.T) { seg2 := &DataSegment{} seg3 := &DataSegment{} - assert.Bool(window.Set(0, seg0)).IsTrue() - assert.Pointer(window.RemoveFirst()).Equals(seg0) + assert(window.Set(0, seg0), IsTrue) + assert(window.RemoveFirst(), Equals, seg0) e := window.RemoveFirst() - if e != nil { - assert.Fail("Expecting nil.") - } + assert(e, IsNil) - assert.Bool(window.Set(1, seg1)).IsTrue() - assert.Bool(window.Set(2, seg2)).IsTrue() + assert(window.Set(1, seg1), IsTrue) + assert(window.Set(2, seg2), IsTrue) window.Advance() - assert.Bool(window.Set(2, seg3)).IsTrue() + assert(window.Set(2, seg3), IsTrue) - assert.Pointer(window.RemoveFirst()).Equals(seg1) - assert.Pointer(window.Remove(1)).Equals(seg2) - assert.Pointer(window.Remove(2)).Equals(seg3) + assert(window.RemoveFirst(), Equals, seg1) + assert(window.Remove(1), Equals, seg2) + assert(window.Remove(2), Equals, seg3) } diff --git a/transport/internet/kcp/segment_test.go b/transport/internet/kcp/segment_test.go index c573c1596..e13f89fcc 100644 --- a/transport/internet/kcp/segment_test.go +++ b/transport/internet/kcp/segment_test.go @@ -4,20 +4,20 @@ import ( "testing" "v2ray.com/core/common/buf" - "v2ray.com/core/testing/assert" . "v2ray.com/core/transport/internet/kcp" + . "v2ray.com/ext/assert" ) func TestBadSegment(t *testing.T) { - assert := assert.On(t) + assert := With(t) seg, buf := ReadSegment(nil) - assert.Pointer(seg).IsNil() - assert.Int(len(buf)).Equals(0) + assert(seg, IsNil) + assert(len(buf), Equals, 0) } func TestDataSegment(t *testing.T) { - assert := assert.On(t) + assert := With(t) b := buf.NewLocal(512) b.Append([]byte{'a', 'b', 'c', 'd'}) @@ -33,19 +33,19 @@ func TestDataSegment(t *testing.T) { bytes := make([]byte, nBytes) seg.Bytes()(bytes) - assert.Int(len(bytes)).Equals(nBytes) + assert(len(bytes), Equals, nBytes) iseg, _ := ReadSegment(bytes) seg2 := iseg.(*DataSegment) - assert.Uint16(seg2.Conv).Equals(seg.Conv) - assert.Uint32(seg2.Timestamp).Equals(seg.Timestamp) - assert.Uint32(seg2.SendingNext).Equals(seg.SendingNext) - assert.Uint32(seg2.Number).Equals(seg.Number) - assert.Bytes(seg2.Data.Bytes()).Equals(seg.Data.Bytes()) + assert(seg2.Conv, Equals, seg.Conv) + assert(seg2.Timestamp, Equals, seg.Timestamp) + assert(seg2.SendingNext, Equals, seg.SendingNext) + assert(seg2.Number, Equals, seg.Number) + assert(seg2.Data.Bytes(), Equals, seg.Data.Bytes()) } func Test1ByteDataSegment(t *testing.T) { - assert := assert.On(t) + assert := With(t) b := buf.NewLocal(512) b.AppendBytes('a') @@ -61,19 +61,19 @@ func Test1ByteDataSegment(t *testing.T) { bytes := make([]byte, nBytes) seg.Bytes()(bytes) - assert.Int(len(bytes)).Equals(nBytes) + assert(len(bytes), Equals, nBytes) iseg, _ := ReadSegment(bytes) seg2 := iseg.(*DataSegment) - assert.Uint16(seg2.Conv).Equals(seg.Conv) - assert.Uint32(seg2.Timestamp).Equals(seg.Timestamp) - assert.Uint32(seg2.SendingNext).Equals(seg.SendingNext) - assert.Uint32(seg2.Number).Equals(seg.Number) - assert.Bytes(seg2.Data.Bytes()).Equals(seg.Data.Bytes()) + assert(seg2.Conv, Equals, seg.Conv) + assert(seg2.Timestamp, Equals, seg.Timestamp) + assert(seg2.SendingNext, Equals, seg.SendingNext) + assert(seg2.Number, Equals, seg.Number) + assert(seg2.Data.Bytes(), Equals, seg.Data.Bytes()) } func TestACKSegment(t *testing.T) { - assert := assert.On(t) + assert := With(t) seg := &AckSegment{ Conv: 1, @@ -87,22 +87,22 @@ func TestACKSegment(t *testing.T) { bytes := make([]byte, nBytes) seg.Bytes()(bytes) - assert.Int(len(bytes)).Equals(nBytes) + assert(len(bytes), Equals, nBytes) iseg, _ := ReadSegment(bytes) seg2 := iseg.(*AckSegment) - assert.Uint16(seg2.Conv).Equals(seg.Conv) - assert.Uint32(seg2.ReceivingWindow).Equals(seg.ReceivingWindow) - assert.Uint32(seg2.ReceivingNext).Equals(seg.ReceivingNext) - assert.Int(len(seg2.NumberList)).Equals(len(seg.NumberList)) - assert.Uint32(seg2.Timestamp).Equals(seg.Timestamp) + assert(seg2.Conv, Equals, seg.Conv) + assert(seg2.ReceivingWindow, Equals, seg.ReceivingWindow) + assert(seg2.ReceivingNext, Equals, seg.ReceivingNext) + assert(len(seg2.NumberList), Equals, len(seg.NumberList)) + assert(seg2.Timestamp, Equals, seg.Timestamp) for i, number := range seg2.NumberList { - assert.Uint32(number).Equals(seg.NumberList[i]) + assert(number, Equals, seg.NumberList[i]) } } func TestCmdSegment(t *testing.T) { - assert := assert.On(t) + assert := With(t) seg := &CmdOnlySegment{ Conv: 1, @@ -117,14 +117,14 @@ func TestCmdSegment(t *testing.T) { bytes := make([]byte, nBytes) seg.Bytes()(bytes) - assert.Int(len(bytes)).Equals(nBytes) + assert(len(bytes), Equals, nBytes) iseg, _ := ReadSegment(bytes) seg2 := iseg.(*CmdOnlySegment) - assert.Uint16(seg2.Conv).Equals(seg.Conv) - assert.Byte(byte(seg2.Command())).Equals(byte(seg.Command())) - assert.Byte(byte(seg2.Option)).Equals(byte(seg.Option)) - assert.Uint32(seg2.SendingNext).Equals(seg.SendingNext) - assert.Uint32(seg2.ReceivinNext).Equals(seg.ReceivinNext) - assert.Uint32(seg2.PeerRTO).Equals(seg.PeerRTO) + assert(seg2.Conv, Equals, seg.Conv) + assert(byte(seg2.Command()), Equals, byte(seg.Command())) + assert(byte(seg2.Option), Equals, byte(seg.Option)) + assert(seg2.SendingNext, Equals, seg.SendingNext) + assert(seg2.ReceivinNext, Equals, seg.ReceivinNext) + assert(seg2.PeerRTO, Equals, seg.PeerRTO) } diff --git a/transport/internet/kcp/sending_test.go b/transport/internet/kcp/sending_test.go index dfdb99693..d8f689980 100644 --- a/transport/internet/kcp/sending_test.go +++ b/transport/internet/kcp/sending_test.go @@ -3,40 +3,40 @@ package kcp_test import ( "testing" - "v2ray.com/core/testing/assert" . "v2ray.com/core/transport/internet/kcp" + . "v2ray.com/ext/assert" ) func TestSendingWindow(t *testing.T) { - assert := assert.On(t) + assert := With(t) window := NewSendingWindow(5, nil, nil) window.Push(0, []byte{}) window.Push(1, []byte{}) window.Push(2, []byte{}) - assert.Int(window.Len()).Equals(3) + assert(window.Len(), Equals, 3) window.Remove(1) - assert.Int(window.Len()).Equals(3) - assert.Uint32(window.FirstNumber()).Equals(0) + assert(window.Len(), Equals, 3) + assert(window.FirstNumber(), Equals, uint32(0)) window.Remove(0) - assert.Int(window.Len()).Equals(1) - assert.Uint32(window.FirstNumber()).Equals(2) + assert(window.Len(), Equals, 1) + assert(window.FirstNumber(), Equals, uint32(2)) window.Remove(0) - assert.Int(window.Len()).Equals(0) + assert(window.Len(), Equals, 0) window.Push(4, []byte{}) - assert.Int(window.Len()).Equals(1) - assert.Uint32(window.FirstNumber()).Equals(4) + assert(window.Len(), Equals, 1) + assert(window.FirstNumber(), Equals, uint32(4)) window.Push(5, []byte{}) - assert.Int(window.Len()).Equals(2) + assert(window.Len(), Equals, 2) window.Remove(1) - assert.Int(window.Len()).Equals(2) + assert(window.Len(), Equals, 2) window.Remove(0) - assert.Int(window.Len()).Equals(0) + assert(window.Len(), Equals, 0) } diff --git a/transport/internet/tcp/dialer.go b/transport/internet/tcp/dialer.go index 17beeb90d..37921d9d3 100644 --- a/transport/internet/tcp/dialer.go +++ b/transport/internet/tcp/dialer.go @@ -29,10 +29,10 @@ func Dial(ctx context.Context, dest net.Destination) (internet.Connection, error if securitySettings := internet.SecuritySettingsFromContext(ctx); securitySettings != nil { tlsConfig, ok := securitySettings.(*tls.Config) if ok { - config := tlsConfig.GetTLSConfig() if dest.Address.Family().IsDomain() { - config.ServerName = dest.Address.Domain() + tlsConfig.OverrideServerNameIfEmpty(dest.Address.Domain()) } + config := tlsConfig.GetTLSConfig() conn = tls.Client(conn, config) } } diff --git a/transport/internet/tcp/hub.go b/transport/internet/tcp/hub.go index 56a8cf7ae..22a6cfb20 100644 --- a/transport/internet/tcp/hub.go +++ b/transport/internet/tcp/hub.go @@ -13,7 +13,6 @@ import ( ) type TCPListener struct { - ctx context.Context listener *net.TCPListener tlsConfig *gotls.Config authConfig internet.ConnectionAuthenticator @@ -34,7 +33,6 @@ func ListenTCP(ctx context.Context, address net.Address, port net.Port, addConn tcpSettings := networkSettings.(*Config) l := &TCPListener{ - ctx: ctx, listener: listener, config: tcpSettings, addConn: addConn, @@ -56,14 +54,14 @@ func ListenTCP(ctx context.Context, address net.Address, port net.Port, addConn } l.authConfig = auth } - go l.KeepAccepting() + go l.KeepAccepting(ctx) return l, nil } -func (v *TCPListener) KeepAccepting() { +func (v *TCPListener) KeepAccepting(ctx context.Context) { for { select { - case <-v.ctx.Done(): + case <-ctx.Done(): return default: } diff --git a/transport/internet/tcp/sockopt_linux_test.go b/transport/internet/tcp/sockopt_linux_test.go index 34e430d8d..23e4906aa 100644 --- a/transport/internet/tcp/sockopt_linux_test.go +++ b/transport/internet/tcp/sockopt_linux_test.go @@ -7,23 +7,23 @@ import ( "strings" "testing" - "v2ray.com/core/testing/assert" "v2ray.com/core/testing/servers/tcp" . "v2ray.com/core/transport/internet/tcp" + . "v2ray.com/ext/assert" ) func TestGetOriginalDestination(t *testing.T) { - assert := assert.On(t) + assert := With(t) tcpServer := tcp.Server{} dest, err := tcpServer.Start() - assert.Error(err).IsNil() + assert(err, IsNil) defer tcpServer.Close() conn, err := Dial(context.Background(), dest) - assert.Error(err).IsNil() + assert(err, IsNil) defer conn.Close() originalDest, err := GetOriginalDestination(conn) - assert.Bool(dest == originalDest || strings.Contains(err.Error(), "failed to call getsockopt")) + assert(dest == originalDest || strings.Contains(err.Error(), "failed to call getsockopt"), IsTrue) } diff --git a/transport/internet/tls/config.go b/transport/internet/tls/config.go index 468e62732..919a91a37 100644 --- a/transport/internet/tls/config.go +++ b/transport/internet/tls/config.go @@ -10,9 +10,9 @@ var ( globalSessionCache = tls.NewLRUClientSessionCache(128) ) -func (v *Config) BuildCertificates() []tls.Certificate { - certs := make([]tls.Certificate, 0, len(v.Certificate)) - for _, entry := range v.Certificate { +func (c *Config) BuildCertificates() []tls.Certificate { + certs := make([]tls.Certificate, 0, len(c.Certificate)) + for _, entry := range c.Certificate { keyPair, err := tls.X509KeyPair(entry.Certificate, entry.Key) if err != nil { log.Trace(newError("ignoring invalid X509 key pair").Base(err).AtWarning()) @@ -23,21 +23,27 @@ func (v *Config) BuildCertificates() []tls.Certificate { return certs } -func (v *Config) GetTLSConfig() *tls.Config { +func (c *Config) GetTLSConfig() *tls.Config { config := &tls.Config{ ClientSessionCache: globalSessionCache, NextProtos: []string{"http/1.1"}, } - if v == nil { + if c == nil { return config } - config.InsecureSkipVerify = v.AllowInsecure - config.Certificates = v.BuildCertificates() + config.InsecureSkipVerify = c.AllowInsecure + config.Certificates = c.BuildCertificates() config.BuildNameToCertificate() - if len(v.ServerName) > 0 { - config.ServerName = v.ServerName + if len(c.ServerName) > 0 { + config.ServerName = c.ServerName } return config } + +func (c *Config) OverrideServerNameIfEmpty(serverName string) { + if len(c.ServerName) == 0 { + c.ServerName = serverName + } +} diff --git a/transport/internet/tls/tls.go b/transport/internet/tls/tls.go index 12f5a155a..c9b6e6f4d 100644 --- a/transport/internet/tls/tls.go +++ b/transport/internet/tls/tls.go @@ -10,29 +10,23 @@ import ( //go:generate go run $GOPATH/src/v2ray.com/core/tools/generrorgen/main.go -pkg tls -path Transport,Internet,TLS var ( - _ buf.MultiBufferReader = (*conn)(nil) - _ buf.MultiBufferWriter = (*conn)(nil) + _ buf.Writer = (*conn)(nil) ) type conn struct { net.Conn - mergingReader buf.Reader - mergingWriter buf.Writer -} - -func (c *conn) ReadMultiBuffer() (buf.MultiBuffer, error) { - if c.mergingReader == nil { - c.mergingReader = buf.NewMergingReaderSize(c.Conn, 16*1024) - } - return c.mergingReader.Read() + mergingWriter *buf.BufferedWriter } func (c *conn) WriteMultiBuffer(mb buf.MultiBuffer) error { if c.mergingWriter == nil { - c.mergingWriter = buf.NewMergingWriter(c.Conn) + c.mergingWriter = buf.NewBufferedWriter(buf.NewWriter(c.Conn)) } - return c.mergingWriter.Write(mb) + if err := c.mergingWriter.WriteMultiBuffer(mb); err != nil { + return err + } + return c.mergingWriter.Flush() } func Client(c net.Conn, config *tls.Config) net.Conn { diff --git a/transport/internet/udp/dispatcher.go b/transport/internet/udp/dispatcher.go index ab9e8b006..d2c155a17 100644 --- a/transport/internet/udp/dispatcher.go +++ b/transport/internet/udp/dispatcher.go @@ -3,25 +3,33 @@ package udp import ( "context" "sync" + "time" "v2ray.com/core/app/dispatcher" "v2ray.com/core/app/log" "v2ray.com/core/common/buf" "v2ray.com/core/common/net" + "v2ray.com/core/common/signal" "v2ray.com/core/transport/ray" ) type ResponseCallback func(payload *buf.Buffer) +type connEntry struct { + inbound ray.InboundRay + timer signal.ActivityUpdater + cancel context.CancelFunc +} + type Dispatcher struct { sync.RWMutex - conns map[net.Destination]ray.InboundRay + conns map[net.Destination]*connEntry dispatcher dispatcher.Interface } func NewDispatcher(dispatcher dispatcher.Interface) *Dispatcher { return &Dispatcher{ - conns: make(map[net.Destination]ray.InboundRay), + conns: make(map[net.Destination]*connEntry), dispatcher: dispatcher, } } @@ -30,51 +38,72 @@ func (v *Dispatcher) RemoveRay(dest net.Destination) { v.Lock() defer v.Unlock() if conn, found := v.conns[dest]; found { - conn.InboundInput().Close() - conn.InboundOutput().Close() + conn.inbound.InboundInput().Close() + conn.inbound.InboundOutput().Close() delete(v.conns, dest) } } -func (v *Dispatcher) getInboundRay(ctx context.Context, dest net.Destination) (ray.InboundRay, bool) { +func (v *Dispatcher) getInboundRay(dest net.Destination, callback ResponseCallback) *connEntry { v.Lock() defer v.Unlock() if entry, found := v.conns[dest]; found { - return entry, true + return entry } log.Trace(newError("establishing new connection for ", dest)) + + ctx, cancel := context.WithCancel(context.Background()) + removeRay := func() { + cancel() + v.RemoveRay(dest) + } + timer := signal.CancelAfterInactivity(ctx, removeRay, time.Second*4) inboundRay, _ := v.dispatcher.Dispatch(ctx, dest) - v.conns[dest] = inboundRay - return inboundRay, false + entry := &connEntry{ + inbound: inboundRay, + timer: timer, + cancel: removeRay, + } + v.conns[dest] = entry + go handleInput(ctx, entry, callback) + return entry } func (v *Dispatcher) Dispatch(ctx context.Context, destination net.Destination, payload *buf.Buffer, callback ResponseCallback) { // TODO: Add user to destString log.Trace(newError("dispatch request to: ", destination).AtDebug()) - inboundRay, existing := v.getInboundRay(ctx, destination) - outputStream := inboundRay.InboundInput() + conn := v.getInboundRay(destination, callback) + outputStream := conn.inbound.InboundInput() if outputStream != nil { - if err := outputStream.Write(buf.NewMultiBufferValue(payload)); err != nil { - v.RemoveRay(destination) + if err := outputStream.WriteMultiBuffer(buf.NewMultiBufferValue(payload)); err != nil { + log.Trace(newError("failed to write first UDP payload").Base(err)) + conn.cancel() + return } } - if !existing { - go func() { - handleInput(inboundRay.InboundOutput(), callback) - v.RemoveRay(destination) - }() - } } -func handleInput(input ray.InputStream, callback ResponseCallback) { +func handleInput(ctx context.Context, conn *connEntry, callback ResponseCallback) { + input := conn.inbound.InboundOutput() + timer := conn.timer + for { - mb, err := input.Read() - if err != nil { - break + select { + case <-ctx.Done(): + return + default: } + + mb, err := input.ReadMultiBuffer() + if err != nil { + log.Trace(newError("failed to handle UDP input").Base(err)) + conn.cancel() + return + } + timer.Update() for _, b := range mb { callback(b) } diff --git a/transport/internet/udp/dispatcher_test.go b/transport/internet/udp/dispatcher_test.go index 5f44b53e7..76a939e77 100644 --- a/transport/internet/udp/dispatcher_test.go +++ b/transport/internet/udp/dispatcher_test.go @@ -8,9 +8,9 @@ import ( "v2ray.com/core/common/buf" "v2ray.com/core/common/net" - "v2ray.com/core/testing/assert" . "v2ray.com/core/transport/internet/udp" "v2ray.com/core/transport/ray" + . "v2ray.com/ext/assert" ) type TestDispatcher struct { @@ -22,18 +22,18 @@ func (d *TestDispatcher) Dispatch(ctx context.Context, dest net.Destination) (ra } func TestSameDestinationDispatching(t *testing.T) { - assert := assert.On(t) + assert := With(t) ctx, cancel := context.WithCancel(context.Background()) link := ray.NewRay(ctx) go func() { for { - data, err := link.OutboundInput().Read() + data, err := link.OutboundInput().ReadMultiBuffer() if err != nil { break } - err = link.OutboundOutput().Write(data) - assert.Error(err).IsNil() + err = link.OutboundOutput().WriteMultiBuffer(data) + assert(err, IsNil) } }() @@ -60,6 +60,6 @@ func TestSameDestinationDispatching(t *testing.T) { time.Sleep(time.Second) cancel() - assert.Uint32(count).Equals(1) - assert.Uint32(msgCount).Equals(6) + assert(count, Equals, uint32(1)) + assert(msgCount, Equals, uint32(6)) } diff --git a/transport/internet/udp/hub.go b/transport/internet/udp/hub.go index f54c5e709..d5382c15d 100644 --- a/transport/internet/udp/hub.go +++ b/transport/internet/udp/hub.go @@ -38,15 +38,16 @@ func NewPayloadQueue(option ListenOption) *PayloadQueue { return queue } -func (v *PayloadQueue) Enqueue(payload Payload) { - size := len(v.queue) +// Enqueue adds the payload to the end of this queue. +func (q *PayloadQueue) Enqueue(payload Payload) { + size := len(q.queue) idx := 0 if size > 1 { idx = dice.Roll(size) } for i := 0; i < size; i++ { select { - case v.queue[idx%size] <- payload: + case q.queue[idx%size] <- payload: return default: idx++ @@ -54,14 +55,14 @@ func (v *PayloadQueue) Enqueue(payload Payload) { } } -func (v *PayloadQueue) Dequeue(queue <-chan Payload) { +func (q *PayloadQueue) Dequeue(queue <-chan Payload) { for payload := range queue { - v.callback(payload.payload, payload.source, payload.originalDest) + q.callback(payload.payload, payload.source, payload.originalDest) } } -func (v *PayloadQueue) Close() { - for _, queue := range v.queue { +func (q *PayloadQueue) Close() { + for _, queue := range q.queue { close(queue) } } @@ -116,19 +117,19 @@ func ListenUDP(address net.Address, port net.Port, option ListenOption) (*Hub, e return hub, nil } -func (v *Hub) Close() { - v.cancel() - v.conn.Close() +func (h *Hub) Close() { + h.cancel() + h.conn.Close() } -func (v *Hub) WriteTo(payload []byte, dest net.Destination) (int, error) { - return v.conn.WriteToUDP(payload, &net.UDPAddr{ +func (h *Hub) WriteTo(payload []byte, dest net.Destination) (int, error) { + return h.conn.WriteToUDP(payload, &net.UDPAddr{ IP: dest.Address.IP(), Port: int(dest.Port), }) } -func (v *Hub) start(ctx context.Context) { +func (h *Hub) start(ctx context.Context) { oobBytes := make([]byte, 256) L: for { @@ -142,7 +143,7 @@ L: var noob int var addr *net.UDPAddr err := buffer.AppendSupplier(func(b []byte) (int, error) { - n, nb, _, a, e := ReadUDPMsg(v.conn, b, oobBytes) + n, nb, _, a, e := ReadUDPMsg(h.conn, b, oobBytes) noob = nb addr = a return n, e @@ -158,20 +159,14 @@ L: payload: buffer, } payload.source = net.UDPDestination(net.IPAddress(addr.IP), net.Port(addr.Port)) - if v.option.ReceiveOriginalDest && noob > 0 { + if h.option.ReceiveOriginalDest && noob > 0 { payload.originalDest = RetrieveOriginalDest(oobBytes[:noob]) } - v.queue.Enqueue(payload) + h.queue.Enqueue(payload) } - v.queue.Close() + h.queue.Close() } -// Connection returns the net.Conn underneath this hub. -// Private: Visible for testing only -func (v *Hub) Connection() net.Conn { - return v.conn -} - -func (v *Hub) Addr() net.Addr { - return v.conn.LocalAddr() +func (h *Hub) Addr() net.Addr { + return h.conn.LocalAddr() } diff --git a/transport/internet/udp/source_forging.go b/transport/internet/udp/source_forging.go new file mode 100644 index 000000000..caa935343 --- /dev/null +++ b/transport/internet/udp/source_forging.go @@ -0,0 +1,11 @@ +// +build !linux + +package udp + +import ( + "net" +) + +func TransmitSocket(src net.Addr, dst net.Addr) (net.Conn, error) { + return nil, newError("forging source address is not supported on non-Linux platform.").AtWarning() +} diff --git a/transport/internet/udp/source_forging_linux.go b/transport/internet/udp/source_forging_linux.go new file mode 100644 index 000000000..238519b37 --- /dev/null +++ b/transport/internet/udp/source_forging_linux.go @@ -0,0 +1,55 @@ +// +build linux + +package udp + +import ( + "net" + "os" + "syscall" +) + +//Currently, Only IPv4 Forge is supported +func TransmitSocket(src net.Addr, dst net.Addr) (net.Conn, error) { + var fd int + var err error + fd, err = syscall.Socket(syscall.AF_INET, syscall.SOCK_DGRAM, 0) + if err != nil { + return nil, newError("failed to create fd").Base(err).AtWarning() + } + err = syscall.SetsockoptInt(fd, syscall.SOL_SOCKET, syscall.SO_REUSEADDR, 1) + if err != nil { + return nil, newError("failed to set resuse_addr").Base(err).AtWarning() + } + + err = syscall.SetsockoptInt(fd, syscall.SOL_IP, syscall.IP_TRANSPARENT, 1) + if err != nil { + return nil, newError("failed to set transparent").Base(err).AtWarning() + } + + ip := src.(*net.UDPAddr).IP.To4() + var ip2 [4]byte + copy(ip2[:], ip) + srcaddr := syscall.SockaddrInet4{} + srcaddr.Addr = ip2 + srcaddr.Port = src.(*net.UDPAddr).Port + err = syscall.Bind(fd, &srcaddr) + if err != nil { + return nil, newError("failed to bind source address").Base(err).AtWarning() + } + ipd := dst.(*net.UDPAddr).IP.To4() + var ip2d [4]byte + copy(ip2d[:], ipd) + dstaddr := syscall.SockaddrInet4{} + dstaddr.Addr = ip2d + dstaddr.Port = dst.(*net.UDPAddr).Port + err = syscall.Connect(fd, &dstaddr) + if err != nil { + return nil, newError("failed to connect to source address").Base(err).AtWarning() + } + fdf := os.NewFile(uintptr(fd), "/dev/udp/") + c, err := net.FileConn(fdf) + if err != nil { + return nil, newError("failed to create file conn").Base(err).AtWarning() + } + return c, nil +} diff --git a/transport/internet/websocket/config.go b/transport/internet/websocket/config.go index 4082f4fde..4469a83a1 100644 --- a/transport/internet/websocket/config.go +++ b/transport/internet/websocket/config.go @@ -1,6 +1,8 @@ package websocket import ( + "net/http" + "v2ray.com/core/common" "v2ray.com/core/transport/internet" ) @@ -16,6 +18,14 @@ func (c *Config) GetNormailzedPath() string { return path } +func (c *Config) GetRequestHeader() http.Header { + header := http.Header{} + for _, h := range c.Header { + header.Add(h.Key, h.Value) + } + return header +} + func init() { common.Must(internet.RegisterProtocolConfigCreator(internet.TransportProtocol_WebSocket, func() interface{} { return new(Config) diff --git a/transport/internet/websocket/config.pb.go b/transport/internet/websocket/config.pb.go index c2a6abaf1..3ca9eba7e 100644 --- a/transport/internet/websocket/config.pb.go +++ b/transport/internet/websocket/config.pb.go @@ -15,25 +15,34 @@ var _ = math.Inf // proto package needs to be updated. const _ = proto.ProtoPackageIsVersion2 // please upgrade the proto package -type ConnectionReuse struct { - Enable bool `protobuf:"varint,1,opt,name=enable" json:"enable,omitempty"` +type Header struct { + Key string `protobuf:"bytes,1,opt,name=key" json:"key,omitempty"` + Value string `protobuf:"bytes,2,opt,name=value" json:"value,omitempty"` } -func (m *ConnectionReuse) Reset() { *m = ConnectionReuse{} } -func (m *ConnectionReuse) String() string { return proto.CompactTextString(m) } -func (*ConnectionReuse) ProtoMessage() {} -func (*ConnectionReuse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{0} } +func (m *Header) Reset() { *m = Header{} } +func (m *Header) String() string { return proto.CompactTextString(m) } +func (*Header) ProtoMessage() {} +func (*Header) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{0} } -func (m *ConnectionReuse) GetEnable() bool { +func (m *Header) GetKey() string { if m != nil { - return m.Enable + return m.Key } - return false + return "" +} + +func (m *Header) GetValue() string { + if m != nil { + return m.Value + } + return "" } type Config struct { // URL path to the WebSocket service. Empty value means root(/). - Path string `protobuf:"bytes,2,opt,name=path" json:"path,omitempty"` + Path string `protobuf:"bytes,2,opt,name=path" json:"path,omitempty"` + Header []*Header `protobuf:"bytes,3,rep,name=header" json:"header,omitempty"` } func (m *Config) Reset() { *m = Config{} } @@ -48,8 +57,15 @@ func (m *Config) GetPath() string { return "" } +func (m *Config) GetHeader() []*Header { + if m != nil { + return m.Header + } + return nil +} + func init() { - proto.RegisterType((*ConnectionReuse)(nil), "v2ray.core.transport.internet.websocket.ConnectionReuse") + proto.RegisterType((*Header)(nil), "v2ray.core.transport.internet.websocket.Header") proto.RegisterType((*Config)(nil), "v2ray.core.transport.internet.websocket.Config") } @@ -58,18 +74,20 @@ func init() { } var fileDescriptor0 = []byte{ - // 204 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x8c, 0xcf, 0x31, 0x4b, 0xc7, 0x30, - 0x10, 0x05, 0x70, 0x52, 0xfe, 0x94, 0x36, 0x8b, 0x92, 0x41, 0x3a, 0x96, 0x2e, 0xad, 0x08, 0x09, - 0xd4, 0xc5, 0xd9, 0x4e, 0x3a, 0x49, 0x10, 0x05, 0xb7, 0x34, 0x9e, 0x5a, 0xb4, 0x77, 0x25, 0x3d, - 0x95, 0x7e, 0x25, 0x3f, 0xa5, 0x58, 0x4c, 0xe6, 0xff, 0x76, 0x0f, 0xee, 0xc7, 0xe3, 0xc9, 0xab, - 0xaf, 0x3e, 0xb8, 0x4d, 0x7b, 0x9a, 0x8d, 0xa7, 0x00, 0x86, 0x83, 0xc3, 0x75, 0xa1, 0xc0, 0x66, - 0x42, 0x86, 0x80, 0xc0, 0xe6, 0x1b, 0xc6, 0x95, 0xfc, 0x3b, 0xb0, 0xf1, 0x84, 0x2f, 0xd3, 0xab, - 0x5e, 0x02, 0x31, 0xa9, 0x36, 0xca, 0x00, 0x3a, 0x29, 0x1d, 0x95, 0x4e, 0xaa, 0x39, 0x97, 0x27, - 0x03, 0x21, 0x82, 0xe7, 0x89, 0xd0, 0xc2, 0xe7, 0x0a, 0xea, 0x4c, 0xe6, 0x80, 0x6e, 0xfc, 0x80, - 0x4a, 0xd4, 0xa2, 0x2b, 0xec, 0x7f, 0x6a, 0x1a, 0x99, 0x0f, 0x7b, 0x87, 0x52, 0xf2, 0xb0, 0x38, - 0x7e, 0xab, 0xb2, 0x5a, 0x74, 0xa5, 0xdd, 0xef, 0xdb, 0x43, 0x21, 0x4e, 0xb3, 0xeb, 0x67, 0x79, - 0xe1, 0x69, 0xd6, 0x47, 0xb6, 0xdf, 0x89, 0xa7, 0x32, 0x85, 0x9f, 0xac, 0x7d, 0xe8, 0xad, 0xdb, - 0xf4, 0xf0, 0xc7, 0xee, 0x13, 0xbb, 0x89, 0xec, 0x31, 0x7e, 0x8e, 0xf9, 0x3e, 0xf2, 0xf2, 0x37, - 0x00, 0x00, 0xff, 0xff, 0x7a, 0xf3, 0x2b, 0x77, 0x20, 0x01, 0x00, 0x00, + // 229 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0xb2, 0x28, 0x33, 0x2a, 0x4a, + 0xac, 0xd4, 0x4b, 0xce, 0xcf, 0xd5, 0x4f, 0xce, 0x2f, 0x4a, 0xd5, 0x2f, 0x29, 0x4a, 0xcc, 0x2b, + 0x2e, 0xc8, 0x2f, 0x2a, 0xd1, 0xcf, 0xcc, 0x2b, 0x49, 0x2d, 0xca, 0x4b, 0x2d, 0xd1, 0x2f, 0x4f, + 0x4d, 0x2a, 0xce, 0x4f, 0xce, 0x4e, 0x2d, 0xd1, 0x4f, 0xce, 0xcf, 0x4b, 0xcb, 0x4c, 0xd7, 0x2b, + 0x28, 0xca, 0x2f, 0xc9, 0x17, 0x52, 0x87, 0xe9, 0x2c, 0x4a, 0xd5, 0x83, 0xeb, 0xd2, 0x83, 0xe9, + 0xd2, 0x83, 0xeb, 0x52, 0x32, 0xe0, 0x62, 0xf3, 0x48, 0x4d, 0x4c, 0x49, 0x2d, 0x12, 0x12, 0xe0, + 0x62, 0xce, 0x4e, 0xad, 0x94, 0x60, 0x54, 0x60, 0xd4, 0xe0, 0x0c, 0x02, 0x31, 0x85, 0x44, 0xb8, + 0x58, 0xcb, 0x12, 0x73, 0x4a, 0x53, 0x25, 0x98, 0xc0, 0x62, 0x10, 0x8e, 0x52, 0x36, 0x17, 0x9b, + 0x33, 0xd8, 0x2a, 0x21, 0x21, 0x2e, 0x96, 0x82, 0xc4, 0x92, 0x0c, 0xa8, 0x34, 0x98, 0x2d, 0xe4, + 0xce, 0xc5, 0x96, 0x01, 0x36, 0x4f, 0x82, 0x59, 0x81, 0x59, 0x83, 0xdb, 0x48, 0x5f, 0x8f, 0x48, + 0x97, 0xe8, 0x41, 0x9c, 0x11, 0x04, 0xd5, 0xee, 0xc5, 0xc2, 0xc1, 0x28, 0xc0, 0xe4, 0x94, 0xc2, + 0xa5, 0x9d, 0x9c, 0x9f, 0x4b, 0xac, 0x19, 0x01, 0x8c, 0x51, 0x9c, 0x70, 0xce, 0x2a, 0x26, 0xf5, + 0x30, 0xa3, 0xa0, 0xc4, 0x4a, 0x3d, 0x67, 0x90, 0xb6, 0x10, 0xb8, 0x36, 0x4f, 0x98, 0xb6, 0x70, + 0x98, 0xca, 0x24, 0x36, 0x70, 0xa0, 0x19, 0x03, 0x02, 0x00, 0x00, 0xff, 0xff, 0xf5, 0x7e, 0x60, + 0xf9, 0x70, 0x01, 0x00, 0x00, } diff --git a/transport/internet/websocket/config.proto b/transport/internet/websocket/config.proto index ebf47dbf4..6e36467d1 100644 --- a/transport/internet/websocket/config.proto +++ b/transport/internet/websocket/config.proto @@ -6,8 +6,9 @@ option go_package = "websocket"; option java_package = "com.v2ray.core.transport.internet.websocket"; option java_multiple_files = true; -message ConnectionReuse { - bool enable = 1; +message Header { + string key = 1; + string value = 2; } message Config { @@ -15,4 +16,6 @@ message Config { // URL path to the WebSocket service. Empty value means root(/). string path = 2; + + repeated Header header = 3; } \ No newline at end of file diff --git a/transport/internet/websocket/connection.go b/transport/internet/websocket/connection.go index 5b7db36d3..d4e774326 100644 --- a/transport/internet/websocket/connection.go +++ b/transport/internet/websocket/connection.go @@ -11,17 +11,21 @@ import ( ) var ( - _ buf.MultiBufferReader = (*connection)(nil) - _ buf.MultiBufferWriter = (*connection)(nil) + _ buf.Writer = (*connection)(nil) ) // connection is a wrapper for net.Conn over WebSocket connection. type connection struct { - wsc *websocket.Conn + conn *websocket.Conn reader io.Reader - mergingReader buf.Reader - mergingWriter buf.Writer + mergingWriter *buf.BufferedWriter +} + +func newConnection(conn *websocket.Conn) *connection { + return &connection{ + conn: conn, + } } // Read implements net.Conn.Read() @@ -41,19 +45,12 @@ func (c *connection) Read(b []byte) (int, error) { } } -func (c *connection) ReadMultiBuffer() (buf.MultiBuffer, error) { - if c.mergingReader == nil { - c.mergingReader = buf.NewMergingReader(c) - } - return c.mergingReader.Read() -} - func (c *connection) getReader() (io.Reader, error) { if c.reader != nil { return c.reader, nil } - _, reader, err := c.wsc.NextReader() + _, reader, err := c.conn.NextReader() if err != nil { return nil, err } @@ -63,7 +60,7 @@ func (c *connection) getReader() (io.Reader, error) { // Write implements io.Writer. func (c *connection) Write(b []byte) (int, error) { - if err := c.wsc.WriteMessage(websocket.BinaryMessage, b); err != nil { + if err := c.conn.WriteMessage(websocket.BinaryMessage, b); err != nil { return 0, err } return len(b), nil @@ -71,22 +68,25 @@ func (c *connection) Write(b []byte) (int, error) { func (c *connection) WriteMultiBuffer(mb buf.MultiBuffer) error { if c.mergingWriter == nil { - c.mergingWriter = buf.NewMergingWriter(c) + c.mergingWriter = buf.NewBufferedWriter(buf.NewBufferToBytesWriter(c)) } - return c.mergingWriter.Write(mb) + if err := c.mergingWriter.WriteMultiBuffer(mb); err != nil { + return err + } + return c.mergingWriter.Flush() } func (c *connection) Close() error { - c.wsc.WriteControl(websocket.CloseMessage, websocket.FormatCloseMessage(websocket.CloseNormalClosure, ""), time.Now().Add(time.Second*5)) - return c.wsc.Close() + c.conn.WriteControl(websocket.CloseMessage, websocket.FormatCloseMessage(websocket.CloseNormalClosure, ""), time.Now().Add(time.Second*5)) + return c.conn.Close() } func (c *connection) LocalAddr() net.Addr { - return c.wsc.LocalAddr() + return c.conn.LocalAddr() } func (c *connection) RemoteAddr() net.Addr { - return c.wsc.RemoteAddr() + return c.conn.RemoteAddr() } func (c *connection) SetDeadline(t time.Time) error { @@ -97,9 +97,9 @@ func (c *connection) SetDeadline(t time.Time) error { } func (c *connection) SetReadDeadline(t time.Time) error { - return c.wsc.SetReadDeadline(t) + return c.conn.SetReadDeadline(t) } func (c *connection) SetWriteDeadline(t time.Time) error { - return c.wsc.SetWriteDeadline(t) + return c.conn.SetWriteDeadline(t) } diff --git a/transport/internet/websocket/dialer.go b/transport/internet/websocket/dialer.go index b3cf98248..bd49b228f 100644 --- a/transport/internet/websocket/dialer.go +++ b/transport/internet/websocket/dialer.go @@ -2,6 +2,7 @@ package websocket import ( "context" + "time" "github.com/gorilla/websocket" "v2ray.com/core/app/log" @@ -30,14 +31,13 @@ func dialWebsocket(ctx context.Context, dest net.Destination) (net.Conn, error) src := internet.DialerSourceFromContext(ctx) wsSettings := internet.TransportSettingsFromContext(ctx).(*Config) - commonDial := func(network, addr string) (net.Conn, error) { - return internet.DialSystem(ctx, src, dest) - } - - dialer := websocket.Dialer{ - NetDial: commonDial, - ReadBufferSize: 32 * 1024, - WriteBufferSize: 32 * 1024, + dialer := &websocket.Dialer{ + NetDial: func(network, addr string) (net.Conn, error) { + return internet.DialSystem(ctx, src, dest) + }, + ReadBufferSize: 8 * 1024, + WriteBufferSize: 8 * 1024, + HandshakeTimeout: time.Second * 8, } protocol := "ws" @@ -46,10 +46,10 @@ func dialWebsocket(ctx context.Context, dest net.Destination) (net.Conn, error) tlsConfig, ok := securitySettings.(*tls.Config) if ok { protocol = "wss" - dialer.TLSClientConfig = tlsConfig.GetTLSConfig() if dest.Address.Family().IsDomain() { - dialer.TLSClientConfig.ServerName = dest.Address.Domain() + tlsConfig.OverrideServerNameIfEmpty(dest.Address.Domain()) } + dialer.TLSClientConfig = tlsConfig.GetTLSConfig() } } @@ -59,7 +59,7 @@ func dialWebsocket(ctx context.Context, dest net.Destination) (net.Conn, error) } uri := protocol + "://" + host + wsSettings.GetNormailzedPath() - conn, resp, err := dialer.Dial(uri, nil) + conn, resp, err := dialer.Dial(uri, wsSettings.GetRequestHeader()) if err != nil { var reason string if resp != nil { @@ -68,7 +68,5 @@ func dialWebsocket(ctx context.Context, dest net.Destination) (net.Conn, error) return nil, newError("failed to dial to (", uri, "): ", reason).Base(err) } - return &connection{ - wsc: conn, - }, nil + return newConnection(conn), nil } diff --git a/transport/internet/websocket/hub.go b/transport/internet/websocket/hub.go index b67257e3b..196624b22 100644 --- a/transport/internet/websocket/hub.go +++ b/transport/internet/websocket/hub.go @@ -6,6 +6,7 @@ import ( "net/http" "strconv" "sync" + "time" "github.com/gorilla/websocket" "v2ray.com/core/app/log" @@ -20,18 +21,24 @@ type requestHandler struct { ln *Listener } +var upgrader = &websocket.Upgrader{ + ReadBufferSize: 8 * 1024, + WriteBufferSize: 8 * 1024, + HandshakeTimeout: time.Second * 8, +} + func (h *requestHandler) ServeHTTP(writer http.ResponseWriter, request *http.Request) { if request.URL.Path != h.path { writer.WriteHeader(http.StatusNotFound) return } - conn, err := converttovws(writer, request) + conn, err := upgrader.Upgrade(writer, request, nil) if err != nil { log.Trace(newError("failed to convert to WebSocket connection").Base(err)) return } - h.ln.addConn(h.ln.ctx, internet.Connection(conn)) + h.ln.addConn(h.ln.ctx, newConnection(conn)) } type Listener struct { @@ -83,33 +90,24 @@ func (ln *Listener) listenws(address net.Address, port net.Port) error { ln.listener = listener go func() { - http.Serve(listener, &requestHandler{ + err := http.Serve(listener, &requestHandler{ path: ln.config.GetNormailzedPath(), ln: ln, }) + if err != nil { + log.Trace(newError("failed to serve http for WebSocket").Base(err).AtWarning()) + } }() return nil } -func converttovws(w http.ResponseWriter, r *http.Request) (*connection, error) { - var upgrader = websocket.Upgrader{ - ReadBufferSize: 32 * 1024, - WriteBufferSize: 32 * 1024, - } - conn, err := upgrader.Upgrade(w, r, nil) - - if err != nil { - return nil, err - } - - return &connection{wsc: conn}, nil -} - +// Addr implements net.Listener.Addr(). func (ln *Listener) Addr() net.Addr { return ln.listener.Addr() } +// Close implements net.Listener.Close(). func (ln *Listener) Close() error { return ln.listener.Close() } diff --git a/transport/internet/websocket/ws_test.go b/transport/internet/websocket/ws_test.go index 2501f5ad0..ac97fbf89 100644 --- a/transport/internet/websocket/ws_test.go +++ b/transport/internet/websocket/ws_test.go @@ -7,15 +7,15 @@ import ( "time" "v2ray.com/core/common/net" - "v2ray.com/core/testing/assert" tlsgen "v2ray.com/core/testing/tls" "v2ray.com/core/transport/internet" v2tls "v2ray.com/core/transport/internet/tls" . "v2ray.com/core/transport/internet/websocket" + . "v2ray.com/ext/assert" ) func Test_listenWSAndDial(t *testing.T) { - assert := assert.On(t) + assert := With(t) listen, err := ListenWS(internet.ContextWithTransportSettings(context.Background(), &Config{ Path: "ws", }), net.DomainAddress("localhost"), 13146, func(ctx context.Context, conn internet.Connection) bool { @@ -24,60 +24,58 @@ func Test_listenWSAndDial(t *testing.T) { var b [1024]byte n, err := c.Read(b[:]) - //assert.Error(err).IsNil() + //assert(err, IsNil) if err != nil { return } - assert.Bool(bytes.HasPrefix(b[:n], []byte("Test connection"))).IsTrue() + assert(bytes.HasPrefix(b[:n], []byte("Test connection")), IsTrue) _, err = c.Write([]byte("Response")) - assert.Error(err).IsNil() + assert(err, IsNil) }(conn) return true }) - assert.Error(err).IsNil() + assert(err, IsNil) ctx := internet.ContextWithTransportSettings(context.Background(), &Config{Path: "ws"}) conn, err := Dial(ctx, net.TCPDestination(net.DomainAddress("localhost"), 13146)) - assert.Error(err).IsNil() + assert(err, IsNil) _, err = conn.Write([]byte("Test connection 1")) - assert.Error(err).IsNil() + assert(err, IsNil) var b [1024]byte n, err := conn.Read(b[:]) - assert.Error(err).IsNil() - assert.String(string(b[:n])).Equals("Response") + assert(err, IsNil) + assert(string(b[:n]), Equals, "Response") - assert.Error(conn.Close()).IsNil() + assert(conn.Close(), IsNil) <-time.After(time.Second * 5) conn, err = Dial(ctx, net.TCPDestination(net.DomainAddress("localhost"), 13146)) - assert.Error(err).IsNil() + assert(err, IsNil) _, err = conn.Write([]byte("Test connection 2")) - assert.Error(err).IsNil() + assert(err, IsNil) n, err = conn.Read(b[:]) - assert.Error(err).IsNil() - assert.String(string(b[:n])).Equals("Response") - assert.Error(conn.Close()).IsNil() + assert(err, IsNil) + assert(string(b[:n]), Equals, "Response") + assert(conn.Close(), IsNil) <-time.After(time.Second * 15) conn, err = Dial(ctx, net.TCPDestination(net.DomainAddress("localhost"), 13146)) - assert.Error(err).IsNil() + assert(err, IsNil) _, err = conn.Write([]byte("Test connection 3")) - assert.Error(err).IsNil() + assert(err, IsNil) n, err = conn.Read(b[:]) - assert.Error(err).IsNil() - assert.String(string(b[:n])).Equals("Response") - assert.Error(conn.Close()).IsNil() + assert(err, IsNil) + assert(string(b[:n]), Equals, "Response") + assert(conn.Close(), IsNil) - assert.Error(listen.Close()).IsNil() + assert(listen.Close(), IsNil) } func Test_listenWSAndDial_TLS(t *testing.T) { - assert := assert.On(t) - go func() { - <-time.After(time.Second * 5) - assert.Fail("Too slow") - }() + assert := With(t) + + start := time.Now() ctx := internet.ContextWithTransportSettings(context.Background(), &Config{ Path: "wss", @@ -88,14 +86,17 @@ func Test_listenWSAndDial_TLS(t *testing.T) { }) listen, err := ListenWS(ctx, net.DomainAddress("localhost"), 13143, func(ctx context.Context, conn internet.Connection) bool { go func() { - conn.Close() + _ = conn.Close() }() return true }) - assert.Error(err).IsNil() + assert(err, IsNil) defer listen.Close() conn, err := Dial(ctx, net.TCPDestination(net.DomainAddress("localhost"), 13143)) - assert.Error(err).IsNil() - conn.Close() + assert(err, IsNil) + _ = conn.Close() + + end := time.Now() + assert(end.Before(start.Add(time.Second*5)), IsTrue) } diff --git a/transport/ray/direct.go b/transport/ray/direct.go index 3fcea2c84..2df368b49 100644 --- a/transport/ray/direct.go +++ b/transport/ray/direct.go @@ -6,6 +6,7 @@ import ( "sync" "time" + "v2ray.com/core/common" "v2ray.com/core/common/buf" "v2ray.com/core/common/platform" ) @@ -50,6 +51,7 @@ func init() { streamSizeLimit = uint64(size) * 1024 * 1024 } +// Stream is a sequential container for data in bytes. type Stream struct { access sync.RWMutex data buf.MultiBuffer @@ -61,6 +63,7 @@ type Stream struct { err bool } +// NewStream creates a new Stream. func NewStream(ctx context.Context) *Stream { return &Stream{ ctx: ctx, @@ -92,16 +95,18 @@ func (s *Stream) getData() (buf.MultiBuffer, error) { return nil, nil } +// Peek fills in the given buffer with data from head of the Stream. func (s *Stream) Peek(b *buf.Buffer) { s.access.RLock() defer s.access.RUnlock() - b.Reset(func(data []byte) (int, error) { + common.Must(b.Reset(func(data []byte) (int, error) { return s.data.Copy(data), nil - }) + })) } -func (s *Stream) Read() (buf.MultiBuffer, error) { +// Read reads data from the Stream. +func (s *Stream) ReadMultiBuffer() (buf.MultiBuffer, error) { for { mb, err := s.getData() if err != nil { @@ -121,6 +126,7 @@ func (s *Stream) Read() (buf.MultiBuffer, error) { } } +// ReadTimeout reads from the Stream with a specified timeout. func (s *Stream) ReadTimeout(timeout time.Duration) (buf.MultiBuffer, error) { for { mb, err := s.getData() @@ -143,26 +149,45 @@ func (s *Stream) ReadTimeout(timeout time.Duration) (buf.MultiBuffer, error) { } } -func (s *Stream) Write(data buf.MultiBuffer) error { - if data.IsEmpty() { +// Size returns the number of bytes hold in the Stream. +func (s *Stream) Size() uint64 { + s.access.RLock() + defer s.access.RUnlock() + + return s.size +} + +// waitForStreamSize waits until the Stream has room for more data, or any error happens. +func (s *Stream) waitForStreamSize() error { + if streamSizeLimit == 0 { return nil } - for streamSizeLimit > 0 && s.size >= streamSizeLimit { + for s.Size() >= streamSizeLimit { select { case <-s.ctx.Done(): return io.ErrClosedPipe case <-s.readSignal: - s.access.RLock() if s.err || s.close { - data.Release() - s.access.RUnlock() return io.ErrClosedPipe } - s.access.RUnlock() } } + return nil +} + +// Write writes more data into the Stream. +func (s *Stream) WriteMultiBuffer(data buf.MultiBuffer) error { + if data.IsEmpty() { + return nil + } + + if err := s.waitForStreamSize(); err != nil { + data.Release() + return err + } + s.access.Lock() defer s.access.Unlock() @@ -172,10 +197,10 @@ func (s *Stream) Write(data buf.MultiBuffer) error { } if s.data == nil { - s.data = data - } else { - s.data.AppendMulti(data) + s.data = buf.NewMultiBufferCap(128) } + + s.data.AppendMulti(data) s.size += uint64(data.Len()) s.notifyWrite() @@ -196,6 +221,7 @@ func (s *Stream) notifyWrite() { } } +// Close closes the stream for writing. Read() still works until EOF. func (s *Stream) Close() { s.access.Lock() s.close = true @@ -204,6 +230,7 @@ func (s *Stream) Close() { s.access.Unlock() } +// CloseError closes the Stream with error. Read() will return an error afterwards. func (s *Stream) CloseError() { s.access.Lock() s.err = true diff --git a/transport/ray/direct_test.go b/transport/ray/direct_test.go index 20d0d443f..64c0ab1d0 100644 --- a/transport/ray/direct_test.go +++ b/transport/ray/direct_test.go @@ -6,44 +6,44 @@ import ( "testing" "v2ray.com/core/common/buf" - "v2ray.com/core/testing/assert" . "v2ray.com/core/transport/ray" + . "v2ray.com/ext/assert" ) func TestStreamIO(t *testing.T) { - assert := assert.On(t) + assert := With(t) stream := NewStream(context.Background()) b1 := buf.New() b1.AppendBytes('a') - assert.Error(stream.Write(buf.NewMultiBufferValue(b1))).IsNil() + assert(stream.WriteMultiBuffer(buf.NewMultiBufferValue(b1)), IsNil) - _, err := stream.Read() - assert.Error(err).IsNil() + _, err := stream.ReadMultiBuffer() + assert(err, IsNil) stream.Close() - _, err = stream.Read() - assert.Error(err).Equals(io.EOF) + _, err = stream.ReadMultiBuffer() + assert(err, Equals, io.EOF) b2 := buf.New() b2.AppendBytes('b') - err = stream.Write(buf.NewMultiBufferValue(b2)) - assert.Error(err).Equals(io.ErrClosedPipe) + err = stream.WriteMultiBuffer(buf.NewMultiBufferValue(b2)) + assert(err, Equals, io.ErrClosedPipe) } func TestStreamClose(t *testing.T) { - assert := assert.On(t) + assert := With(t) stream := NewStream(context.Background()) b1 := buf.New() b1.AppendBytes('a') - assert.Error(stream.Write(buf.NewMultiBufferValue(b1))).IsNil() + assert(stream.WriteMultiBuffer(buf.NewMultiBufferValue(b1)), IsNil) stream.Close() - _, err := stream.Read() - assert.Error(err).IsNil() + _, err := stream.ReadMultiBuffer() + assert(err, IsNil) - _, err = stream.Read() - assert.Error(err).Equals(io.EOF) + _, err = stream.ReadMultiBuffer() + assert(err, Equals, io.EOF) } diff --git a/v2ray.go b/v2ray.go index ffbb0a566..687ca8edb 100644 --- a/v2ray.go +++ b/v2ray.go @@ -7,6 +7,7 @@ import ( "v2ray.com/core/app/dispatcher" "v2ray.com/core/app/dns" "v2ray.com/core/app/log" + "v2ray.com/core/app/policy" "v2ray.com/core/app/proxyman" "v2ray.com/core/common" "v2ray.com/core/common/net" @@ -109,14 +110,30 @@ func newSimpleServer(config *Config) (*simpleServer, error) { common.Must(space.AddApplication(d)) } - disp := dispatcher.FromSpace(space) - if disp == nil { + if disp := dispatcher.FromSpace(space); disp == nil { d, err := app.CreateAppFromConfig(ctx, new(dispatcher.Config)) if err != nil { return nil, err } common.Must(space.AddApplication(d)) - disp = d.(dispatcher.Interface) + } + + if p := policy.FromSpace(space); p == nil { + p, err := app.CreateAppFromConfig(ctx, &policy.Config{ + Level: map[uint32]*policy.Policy{ + 1: &policy.Policy{ + Timeout: &policy.Policy_Timeout{ + ConnectionIdle: &policy.Second{ + Value: 600, + }, + }, + }, + }, + }) + if err != nil { + return nil, err + } + common.Must(space.AddApplication(p)) } for _, inbound := range config.Inbound { diff --git a/v2ray_test.go b/v2ray_test.go index a78bd6d53..4374340c3 100644 --- a/v2ray_test.go +++ b/v2ray_test.go @@ -14,11 +14,11 @@ import ( "v2ray.com/core/proxy/dokodemo" "v2ray.com/core/proxy/vmess" "v2ray.com/core/proxy/vmess/outbound" - "v2ray.com/core/testing/assert" + . "v2ray.com/ext/assert" ) func TestV2RayClose(t *testing.T) { - assert := assert.On(t) + assert := With(t) port := net.Port(dice.RollUint16()) config := &Config{ @@ -59,7 +59,7 @@ func TestV2RayClose(t *testing.T) { } server, err := New(config) - assert.Error(err).IsNil() + assert(err, IsNil) server.Close() } diff --git a/vendor/github.com/Yawning/chacha20 b/vendor/github.com/Yawning/chacha20 new file mode 160000 index 000000000..e3b1f968f --- /dev/null +++ b/vendor/github.com/Yawning/chacha20 @@ -0,0 +1 @@ +Subproject commit e3b1f968fc6397b51d963fee8ec8711a47bc0ce8 diff --git a/vendor/github.com/shadowsocks/go-shadowsocks2 b/vendor/github.com/shadowsocks/go-shadowsocks2 new file mode 160000 index 000000000..87b55c90a --- /dev/null +++ b/vendor/github.com/shadowsocks/go-shadowsocks2 @@ -0,0 +1 @@ +Subproject commit 87b55c90ac57968b4979adaef9a51c98582f76a9