diff options
Diffstat (limited to 'vendor/golang.org/x/net')
56 files changed, 22317 insertions, 703 deletions
diff --git a/vendor/golang.org/x/net/AUTHORS b/vendor/golang.org/x/net/AUTHORS new file mode 100644 index 0000000..15167cd --- /dev/null +++ b/vendor/golang.org/x/net/AUTHORS | |||
@@ -0,0 +1,3 @@ | |||
1 | # This source code refers to The Go Authors for copyright purposes. | ||
2 | # The master list of authors is in the main Go distribution, | ||
3 | # visible at http://tip.golang.org/AUTHORS. | ||
diff --git a/vendor/golang.org/x/net/CONTRIBUTORS b/vendor/golang.org/x/net/CONTRIBUTORS new file mode 100644 index 0000000..1c4577e --- /dev/null +++ b/vendor/golang.org/x/net/CONTRIBUTORS | |||
@@ -0,0 +1,3 @@ | |||
1 | # This source code was written by the Go contributors. | ||
2 | # The master list of contributors is in the main Go distribution, | ||
3 | # visible at http://tip.golang.org/CONTRIBUTORS. | ||
diff --git a/vendor/golang.org/x/net/context/context.go b/vendor/golang.org/x/net/context/context.go new file mode 100644 index 0000000..d3681ab --- /dev/null +++ b/vendor/golang.org/x/net/context/context.go | |||
@@ -0,0 +1,54 @@ | |||
1 | // Copyright 2014 The Go Authors. All rights reserved. | ||
2 | // Use of this source code is governed by a BSD-style | ||
3 | // license that can be found in the LICENSE file. | ||
4 | |||
5 | // Package context defines the Context type, which carries deadlines, | ||
6 | // cancelation signals, and other request-scoped values across API boundaries | ||
7 | // and between processes. | ||
8 | // | ||
9 | // Incoming requests to a server should create a Context, and outgoing calls to | ||
10 | // servers should accept a Context. The chain of function calls between must | ||
11 | // propagate the Context, optionally replacing it with a modified copy created | ||
12 | // using WithDeadline, WithTimeout, WithCancel, or WithValue. | ||
13 | // | ||
14 | // Programs that use Contexts should follow these rules to keep interfaces | ||
15 | // consistent across packages and enable static analysis tools to check context | ||
16 | // propagation: | ||
17 | // | ||
18 | // Do not store Contexts inside a struct type; instead, pass a Context | ||
19 | // explicitly to each function that needs it. The Context should be the first | ||
20 | // parameter, typically named ctx: | ||
21 | // | ||
22 | // func DoSomething(ctx context.Context, arg Arg) error { | ||
23 | // // ... use ctx ... | ||
24 | // } | ||
25 | // | ||
26 | // Do not pass a nil Context, even if a function permits it. Pass context.TODO | ||
27 | // if you are unsure about which Context to use. | ||
28 | // | ||
29 | // Use context Values only for request-scoped data that transits processes and | ||
30 | // APIs, not for passing optional parameters to functions. | ||
31 | // | ||
32 | // The same Context may be passed to functions running in different goroutines; | ||
33 | // Contexts are safe for simultaneous use by multiple goroutines. | ||
34 | // | ||
35 | // See http://blog.golang.org/context for example code for a server that uses | ||
36 | // Contexts. | ||
37 | package context // import "golang.org/x/net/context" | ||
38 | |||
39 | // Background returns a non-nil, empty Context. It is never canceled, has no | ||
40 | // values, and has no deadline. It is typically used by the main function, | ||
41 | // initialization, and tests, and as the top-level Context for incoming | ||
42 | // requests. | ||
43 | func Background() Context { | ||
44 | return background | ||
45 | } | ||
46 | |||
47 | // TODO returns a non-nil, empty Context. Code should use context.TODO when | ||
48 | // it's unclear which Context to use or it is not yet available (because the | ||
49 | // surrounding function has not yet been extended to accept a Context | ||
50 | // parameter). TODO is recognized by static analysis tools that determine | ||
51 | // whether Contexts are propagated correctly in a program. | ||
52 | func TODO() Context { | ||
53 | return todo | ||
54 | } | ||
diff --git a/vendor/golang.org/x/net/context/go17.go b/vendor/golang.org/x/net/context/go17.go new file mode 100644 index 0000000..d20f52b --- /dev/null +++ b/vendor/golang.org/x/net/context/go17.go | |||
@@ -0,0 +1,72 @@ | |||
1 | // Copyright 2016 The Go Authors. All rights reserved. | ||
2 | // Use of this source code is governed by a BSD-style | ||
3 | // license that can be found in the LICENSE file. | ||
4 | |||
5 | // +build go1.7 | ||
6 | |||
7 | package context | ||
8 | |||
9 | import ( | ||
10 | "context" // standard library's context, as of Go 1.7 | ||
11 | "time" | ||
12 | ) | ||
13 | |||
14 | var ( | ||
15 | todo = context.TODO() | ||
16 | background = context.Background() | ||
17 | ) | ||
18 | |||
19 | // Canceled is the error returned by Context.Err when the context is canceled. | ||
20 | var Canceled = context.Canceled | ||
21 | |||
22 | // DeadlineExceeded is the error returned by Context.Err when the context's | ||
23 | // deadline passes. | ||
24 | var DeadlineExceeded = context.DeadlineExceeded | ||
25 | |||
26 | // WithCancel returns a copy of parent with a new Done channel. The returned | ||
27 | // context's Done channel is closed when the returned cancel function is called | ||
28 | // or when the parent context's Done channel is closed, whichever happens first. | ||
29 | // | ||
30 | // Canceling this context releases resources associated with it, so code should | ||
31 | // call cancel as soon as the operations running in this Context complete. | ||
32 | func WithCancel(parent Context) (ctx Context, cancel CancelFunc) { | ||
33 | ctx, f := context.WithCancel(parent) | ||
34 | return ctx, CancelFunc(f) | ||
35 | } | ||
36 | |||
37 | // WithDeadline returns a copy of the parent context with the deadline adjusted | ||
38 | // to be no later than d. If the parent's deadline is already earlier than d, | ||
39 | // WithDeadline(parent, d) is semantically equivalent to parent. The returned | ||
40 | // context's Done channel is closed when the deadline expires, when the returned | ||
41 | // cancel function is called, or when the parent context's Done channel is | ||
42 | // closed, whichever happens first. | ||
43 | // | ||
44 | // Canceling this context releases resources associated with it, so code should | ||
45 | // call cancel as soon as the operations running in this Context complete. | ||
46 | func WithDeadline(parent Context, deadline time.Time) (Context, CancelFunc) { | ||
47 | ctx, f := context.WithDeadline(parent, deadline) | ||
48 | return ctx, CancelFunc(f) | ||
49 | } | ||
50 | |||
51 | // WithTimeout returns WithDeadline(parent, time.Now().Add(timeout)). | ||
52 | // | ||
53 | // Canceling this context releases resources associated with it, so code should | ||
54 | // call cancel as soon as the operations running in this Context complete: | ||
55 | // | ||
56 | // func slowOperationWithTimeout(ctx context.Context) (Result, error) { | ||
57 | // ctx, cancel := context.WithTimeout(ctx, 100*time.Millisecond) | ||
58 | // defer cancel() // releases resources if slowOperation completes before timeout elapses | ||
59 | // return slowOperation(ctx) | ||
60 | // } | ||
61 | func WithTimeout(parent Context, timeout time.Duration) (Context, CancelFunc) { | ||
62 | return WithDeadline(parent, time.Now().Add(timeout)) | ||
63 | } | ||
64 | |||
65 | // WithValue returns a copy of parent in which the value associated with key is | ||
66 | // val. | ||
67 | // | ||
68 | // Use context Values only for request-scoped data that transits processes and | ||
69 | // APIs, not for passing optional parameters to functions. | ||
70 | func WithValue(parent Context, key interface{}, val interface{}) Context { | ||
71 | return context.WithValue(parent, key, val) | ||
72 | } | ||
diff --git a/vendor/golang.org/x/net/context/go19.go b/vendor/golang.org/x/net/context/go19.go new file mode 100644 index 0000000..d88bd1d --- /dev/null +++ b/vendor/golang.org/x/net/context/go19.go | |||
@@ -0,0 +1,20 @@ | |||
1 | // Copyright 2017 The Go Authors. All rights reserved. | ||
2 | // Use of this source code is governed by a BSD-style | ||
3 | // license that can be found in the LICENSE file. | ||
4 | |||
5 | // +build go1.9 | ||
6 | |||
7 | package context | ||
8 | |||
9 | import "context" // standard library's context, as of Go 1.7 | ||
10 | |||
11 | // A Context carries a deadline, a cancelation signal, and other values across | ||
12 | // API boundaries. | ||
13 | // | ||
14 | // Context's methods may be called by multiple goroutines simultaneously. | ||
15 | type Context = context.Context | ||
16 | |||
17 | // A CancelFunc tells an operation to abandon its work. | ||
18 | // A CancelFunc does not wait for the work to stop. | ||
19 | // After the first call, subsequent calls to a CancelFunc do nothing. | ||
20 | type CancelFunc = context.CancelFunc | ||
diff --git a/vendor/golang.org/x/net/context/pre_go17.go b/vendor/golang.org/x/net/context/pre_go17.go new file mode 100644 index 0000000..0f35592 --- /dev/null +++ b/vendor/golang.org/x/net/context/pre_go17.go | |||
@@ -0,0 +1,300 @@ | |||
1 | // Copyright 2014 The Go Authors. All rights reserved. | ||
2 | // Use of this source code is governed by a BSD-style | ||
3 | // license that can be found in the LICENSE file. | ||
4 | |||
5 | // +build !go1.7 | ||
6 | |||
7 | package context | ||
8 | |||
9 | import ( | ||
10 | "errors" | ||
11 | "fmt" | ||
12 | "sync" | ||
13 | "time" | ||
14 | ) | ||
15 | |||
16 | // An emptyCtx is never canceled, has no values, and has no deadline. It is not | ||
17 | // struct{}, since vars of this type must have distinct addresses. | ||
18 | type emptyCtx int | ||
19 | |||
20 | func (*emptyCtx) Deadline() (deadline time.Time, ok bool) { | ||
21 | return | ||
22 | } | ||
23 | |||
24 | func (*emptyCtx) Done() <-chan struct{} { | ||
25 | return nil | ||
26 | } | ||
27 | |||
28 | func (*emptyCtx) Err() error { | ||
29 | return nil | ||
30 | } | ||
31 | |||
32 | func (*emptyCtx) Value(key interface{}) interface{} { | ||
33 | return nil | ||
34 | } | ||
35 | |||
36 | func (e *emptyCtx) String() string { | ||
37 | switch e { | ||
38 | case background: | ||
39 | return "context.Background" | ||
40 | case todo: | ||
41 | return "context.TODO" | ||
42 | } | ||
43 | return "unknown empty Context" | ||
44 | } | ||
45 | |||
46 | var ( | ||
47 | background = new(emptyCtx) | ||
48 | todo = new(emptyCtx) | ||
49 | ) | ||
50 | |||
51 | // Canceled is the error returned by Context.Err when the context is canceled. | ||
52 | var Canceled = errors.New("context canceled") | ||
53 | |||
54 | // DeadlineExceeded is the error returned by Context.Err when the context's | ||
55 | // deadline passes. | ||
56 | var DeadlineExceeded = errors.New("context deadline exceeded") | ||
57 | |||
58 | // WithCancel returns a copy of parent with a new Done channel. The returned | ||
59 | // context's Done channel is closed when the returned cancel function is called | ||
60 | // or when the parent context's Done channel is closed, whichever happens first. | ||
61 | // | ||
62 | // Canceling this context releases resources associated with it, so code should | ||
63 | // call cancel as soon as the operations running in this Context complete. | ||
64 | func WithCancel(parent Context) (ctx Context, cancel CancelFunc) { | ||
65 | c := newCancelCtx(parent) | ||
66 | propagateCancel(parent, c) | ||
67 | return c, func() { c.cancel(true, Canceled) } | ||
68 | } | ||
69 | |||
70 | // newCancelCtx returns an initialized cancelCtx. | ||
71 | func newCancelCtx(parent Context) *cancelCtx { | ||
72 | return &cancelCtx{ | ||
73 | Context: parent, | ||
74 | done: make(chan struct{}), | ||
75 | } | ||
76 | } | ||
77 | |||
78 | // propagateCancel arranges for child to be canceled when parent is. | ||
79 | func propagateCancel(parent Context, child canceler) { | ||
80 | if parent.Done() == nil { | ||
81 | return // parent is never canceled | ||
82 | } | ||
83 | if p, ok := parentCancelCtx(parent); ok { | ||
84 | p.mu.Lock() | ||
85 | if p.err != nil { | ||
86 | // parent has already been canceled | ||
87 | child.cancel(false, p.err) | ||
88 | } else { | ||
89 | if p.children == nil { | ||
90 | p.children = make(map[canceler]bool) | ||
91 | } | ||
92 | p.children[child] = true | ||
93 | } | ||
94 | p.mu.Unlock() | ||
95 | } else { | ||
96 | go func() { | ||
97 | select { | ||
98 | case <-parent.Done(): | ||
99 | child.cancel(false, parent.Err()) | ||
100 | case <-child.Done(): | ||
101 | } | ||
102 | }() | ||
103 | } | ||
104 | } | ||
105 | |||
106 | // parentCancelCtx follows a chain of parent references until it finds a | ||
107 | // *cancelCtx. This function understands how each of the concrete types in this | ||
108 | // package represents its parent. | ||
109 | func parentCancelCtx(parent Context) (*cancelCtx, bool) { | ||
110 | for { | ||
111 | switch c := parent.(type) { | ||
112 | case *cancelCtx: | ||
113 | return c, true | ||
114 | case *timerCtx: | ||
115 | return c.cancelCtx, true | ||
116 | case *valueCtx: | ||
117 | parent = c.Context | ||
118 | default: | ||
119 | return nil, false | ||
120 | } | ||
121 | } | ||
122 | } | ||
123 | |||
124 | // removeChild removes a context from its parent. | ||
125 | func removeChild(parent Context, child canceler) { | ||
126 | p, ok := parentCancelCtx(parent) | ||
127 | if !ok { | ||
128 | return | ||
129 | } | ||
130 | p.mu.Lock() | ||
131 | if p.children != nil { | ||
132 | delete(p.children, child) | ||
133 | } | ||
134 | p.mu.Unlock() | ||
135 | } | ||
136 | |||
137 | // A canceler is a context type that can be canceled directly. The | ||
138 | // implementations are *cancelCtx and *timerCtx. | ||
139 | type canceler interface { | ||
140 | cancel(removeFromParent bool, err error) | ||
141 | Done() <-chan struct{} | ||
142 | } | ||
143 | |||
144 | // A cancelCtx can be canceled. When canceled, it also cancels any children | ||
145 | // that implement canceler. | ||
146 | type cancelCtx struct { | ||
147 | Context | ||
148 | |||
149 | done chan struct{} // closed by the first cancel call. | ||
150 | |||
151 | mu sync.Mutex | ||
152 | children map[canceler]bool // set to nil by the first cancel call | ||
153 | err error // set to non-nil by the first cancel call | ||
154 | } | ||
155 | |||
156 | func (c *cancelCtx) Done() <-chan struct{} { | ||
157 | return c.done | ||
158 | } | ||
159 | |||
160 | func (c *cancelCtx) Err() error { | ||
161 | c.mu.Lock() | ||
162 | defer c.mu.Unlock() | ||
163 | return c.err | ||
164 | } | ||
165 | |||
166 | func (c *cancelCtx) String() string { | ||
167 | return fmt.Sprintf("%v.WithCancel", c.Context) | ||
168 | } | ||
169 | |||
170 | // cancel closes c.done, cancels each of c's children, and, if | ||
171 | // removeFromParent is true, removes c from its parent's children. | ||
172 | func (c *cancelCtx) cancel(removeFromParent bool, err error) { | ||
173 | if err == nil { | ||
174 | panic("context: internal error: missing cancel error") | ||
175 | } | ||
176 | c.mu.Lock() | ||
177 | if c.err != nil { | ||
178 | c.mu.Unlock() | ||
179 | return // already canceled | ||
180 | } | ||
181 | c.err = err | ||
182 | close(c.done) | ||
183 | for child := range c.children { | ||
184 | // NOTE: acquiring the child's lock while holding parent's lock. | ||
185 | child.cancel(false, err) | ||
186 | } | ||
187 | c.children = nil | ||
188 | c.mu.Unlock() | ||
189 | |||
190 | if removeFromParent { | ||
191 | removeChild(c.Context, c) | ||
192 | } | ||
193 | } | ||
194 | |||
195 | // WithDeadline returns a copy of the parent context with the deadline adjusted | ||
196 | // to be no later than d. If the parent's deadline is already earlier than d, | ||
197 | // WithDeadline(parent, d) is semantically equivalent to parent. The returned | ||
198 | // context's Done channel is closed when the deadline expires, when the returned | ||
199 | // cancel function is called, or when the parent context's Done channel is | ||
200 | // closed, whichever happens first. | ||
201 | // | ||
202 | // Canceling this context releases resources associated with it, so code should | ||
203 | // call cancel as soon as the operations running in this Context complete. | ||
204 | func WithDeadline(parent Context, deadline time.Time) (Context, CancelFunc) { | ||
205 | if cur, ok := parent.Deadline(); ok && cur.Before(deadline) { | ||
206 | // The current deadline is already sooner than the new one. | ||
207 | return WithCancel(parent) | ||
208 | } | ||
209 | c := &timerCtx{ | ||
210 | cancelCtx: newCancelCtx(parent), | ||
211 | deadline: deadline, | ||
212 | } | ||
213 | propagateCancel(parent, c) | ||
214 | d := deadline.Sub(time.Now()) | ||
215 | if d <= 0 { | ||
216 | c.cancel(true, DeadlineExceeded) // deadline has already passed | ||
217 | return c, func() { c.cancel(true, Canceled) } | ||
218 | } | ||
219 | c.mu.Lock() | ||
220 | defer c.mu.Unlock() | ||
221 | if c.err == nil { | ||
222 | c.timer = time.AfterFunc(d, func() { | ||
223 | c.cancel(true, DeadlineExceeded) | ||
224 | }) | ||
225 | } | ||
226 | return c, func() { c.cancel(true, Canceled) } | ||
227 | } | ||
228 | |||
229 | // A timerCtx carries a timer and a deadline. It embeds a cancelCtx to | ||
230 | // implement Done and Err. It implements cancel by stopping its timer then | ||
231 | // delegating to cancelCtx.cancel. | ||
232 | type timerCtx struct { | ||
233 | *cancelCtx | ||
234 | timer *time.Timer // Under cancelCtx.mu. | ||
235 | |||
236 | deadline time.Time | ||
237 | } | ||
238 | |||
239 | func (c *timerCtx) Deadline() (deadline time.Time, ok bool) { | ||
240 | return c.deadline, true | ||
241 | } | ||
242 | |||
243 | func (c *timerCtx) String() string { | ||
244 | return fmt.Sprintf("%v.WithDeadline(%s [%s])", c.cancelCtx.Context, c.deadline, c.deadline.Sub(time.Now())) | ||
245 | } | ||
246 | |||
247 | func (c *timerCtx) cancel(removeFromParent bool, err error) { | ||
248 | c.cancelCtx.cancel(false, err) | ||
249 | if removeFromParent { | ||
250 | // Remove this timerCtx from its parent cancelCtx's children. | ||
251 | removeChild(c.cancelCtx.Context, c) | ||
252 | } | ||
253 | c.mu.Lock() | ||
254 | if c.timer != nil { | ||
255 | c.timer.Stop() | ||
256 | c.timer = nil | ||
257 | } | ||
258 | c.mu.Unlock() | ||
259 | } | ||
260 | |||
261 | // WithTimeout returns WithDeadline(parent, time.Now().Add(timeout)). | ||
262 | // | ||
263 | // Canceling this context releases resources associated with it, so code should | ||
264 | // call cancel as soon as the operations running in this Context complete: | ||
265 | // | ||
266 | // func slowOperationWithTimeout(ctx context.Context) (Result, error) { | ||
267 | // ctx, cancel := context.WithTimeout(ctx, 100*time.Millisecond) | ||
268 | // defer cancel() // releases resources if slowOperation completes before timeout elapses | ||
269 | // return slowOperation(ctx) | ||
270 | // } | ||
271 | func WithTimeout(parent Context, timeout time.Duration) (Context, CancelFunc) { | ||
272 | return WithDeadline(parent, time.Now().Add(timeout)) | ||
273 | } | ||
274 | |||
275 | // WithValue returns a copy of parent in which the value associated with key is | ||
276 | // val. | ||
277 | // | ||
278 | // Use context Values only for request-scoped data that transits processes and | ||
279 | // APIs, not for passing optional parameters to functions. | ||
280 | func WithValue(parent Context, key interface{}, val interface{}) Context { | ||
281 | return &valueCtx{parent, key, val} | ||
282 | } | ||
283 | |||
284 | // A valueCtx carries a key-value pair. It implements Value for that key and | ||
285 | // delegates all other calls to the embedded Context. | ||
286 | type valueCtx struct { | ||
287 | Context | ||
288 | key, val interface{} | ||
289 | } | ||
290 | |||
291 | func (c *valueCtx) String() string { | ||
292 | return fmt.Sprintf("%v.WithValue(%#v, %#v)", c.Context, c.key, c.val) | ||
293 | } | ||
294 | |||
295 | func (c *valueCtx) Value(key interface{}) interface{} { | ||
296 | if c.key == key { | ||
297 | return c.val | ||
298 | } | ||
299 | return c.Context.Value(key) | ||
300 | } | ||
diff --git a/vendor/golang.org/x/net/context/pre_go19.go b/vendor/golang.org/x/net/context/pre_go19.go new file mode 100644 index 0000000..b105f80 --- /dev/null +++ b/vendor/golang.org/x/net/context/pre_go19.go | |||
@@ -0,0 +1,109 @@ | |||
1 | // Copyright 2014 The Go Authors. All rights reserved. | ||
2 | // Use of this source code is governed by a BSD-style | ||
3 | // license that can be found in the LICENSE file. | ||
4 | |||
5 | // +build !go1.9 | ||
6 | |||
7 | package context | ||
8 | |||
9 | import "time" | ||
10 | |||
11 | // A Context carries a deadline, a cancelation signal, and other values across | ||
12 | // API boundaries. | ||
13 | // | ||
14 | // Context's methods may be called by multiple goroutines simultaneously. | ||
15 | type Context interface { | ||
16 | // Deadline returns the time when work done on behalf of this context | ||
17 | // should be canceled. Deadline returns ok==false when no deadline is | ||
18 | // set. Successive calls to Deadline return the same results. | ||
19 | Deadline() (deadline time.Time, ok bool) | ||
20 | |||
21 | // Done returns a channel that's closed when work done on behalf of this | ||
22 | // context should be canceled. Done may return nil if this context can | ||
23 | // never be canceled. Successive calls to Done return the same value. | ||
24 | // | ||
25 | // WithCancel arranges for Done to be closed when cancel is called; | ||
26 | // WithDeadline arranges for Done to be closed when the deadline | ||
27 | // expires; WithTimeout arranges for Done to be closed when the timeout | ||
28 | // elapses. | ||
29 | // | ||
30 | // Done is provided for use in select statements: | ||
31 | // | ||
32 | // // Stream generates values with DoSomething and sends them to out | ||
33 | // // until DoSomething returns an error or ctx.Done is closed. | ||
34 | // func Stream(ctx context.Context, out chan<- Value) error { | ||
35 | // for { | ||
36 | // v, err := DoSomething(ctx) | ||
37 | // if err != nil { | ||
38 | // return err | ||
39 | // } | ||
40 | // select { | ||
41 | // case <-ctx.Done(): | ||
42 | // return ctx.Err() | ||
43 | // case out <- v: | ||
44 | // } | ||
45 | // } | ||
46 | // } | ||
47 | // | ||
48 | // See http://blog.golang.org/pipelines for more examples of how to use | ||
49 | // a Done channel for cancelation. | ||
50 | Done() <-chan struct{} | ||
51 | |||
52 | // Err returns a non-nil error value after Done is closed. Err returns | ||
53 | // Canceled if the context was canceled or DeadlineExceeded if the | ||
54 | // context's deadline passed. No other values for Err are defined. | ||
55 | // After Done is closed, successive calls to Err return the same value. | ||
56 | Err() error | ||
57 | |||
58 | // Value returns the value associated with this context for key, or nil | ||
59 | // if no value is associated with key. Successive calls to Value with | ||
60 | // the same key returns the same result. | ||
61 | // | ||
62 | // Use context values only for request-scoped data that transits | ||
63 | // processes and API boundaries, not for passing optional parameters to | ||
64 | // functions. | ||
65 | // | ||
66 | // A key identifies a specific value in a Context. Functions that wish | ||
67 | // to store values in Context typically allocate a key in a global | ||
68 | // variable then use that key as the argument to context.WithValue and | ||
69 | // Context.Value. A key can be any type that supports equality; | ||
70 | // packages should define keys as an unexported type to avoid | ||
71 | // collisions. | ||
72 | // | ||
73 | // Packages that define a Context key should provide type-safe accessors | ||
74 | // for the values stores using that key: | ||
75 | // | ||
76 | // // Package user defines a User type that's stored in Contexts. | ||
77 | // package user | ||
78 | // | ||
79 | // import "golang.org/x/net/context" | ||
80 | // | ||
81 | // // User is the type of value stored in the Contexts. | ||
82 | // type User struct {...} | ||
83 | // | ||
84 | // // key is an unexported type for keys defined in this package. | ||
85 | // // This prevents collisions with keys defined in other packages. | ||
86 | // type key int | ||
87 | // | ||
88 | // // userKey is the key for user.User values in Contexts. It is | ||
89 | // // unexported; clients use user.NewContext and user.FromContext | ||
90 | // // instead of using this key directly. | ||
91 | // var userKey key = 0 | ||
92 | // | ||
93 | // // NewContext returns a new Context that carries value u. | ||
94 | // func NewContext(ctx context.Context, u *User) context.Context { | ||
95 | // return context.WithValue(ctx, userKey, u) | ||
96 | // } | ||
97 | // | ||
98 | // // FromContext returns the User value stored in ctx, if any. | ||
99 | // func FromContext(ctx context.Context) (*User, bool) { | ||
100 | // u, ok := ctx.Value(userKey).(*User) | ||
101 | // return u, ok | ||
102 | // } | ||
103 | Value(key interface{}) interface{} | ||
104 | } | ||
105 | |||
106 | // A CancelFunc tells an operation to abandon its work. | ||
107 | // A CancelFunc does not wait for the work to stop. | ||
108 | // After the first call, subsequent calls to a CancelFunc do nothing. | ||
109 | type CancelFunc func() | ||
diff --git a/vendor/golang.org/x/net/html/atom/gen.go b/vendor/golang.org/x/net/html/atom/gen.go new file mode 100644 index 0000000..cc5dc5d --- /dev/null +++ b/vendor/golang.org/x/net/html/atom/gen.go | |||
@@ -0,0 +1,709 @@ | |||
1 | // Copyright 2012 The Go Authors. All rights reserved. | ||
2 | // Use of this source code is governed by a BSD-style | ||
3 | // license that can be found in the LICENSE file. | ||
4 | |||
5 | // +build ignore | ||
6 | |||
7 | //go:generate go run gen.go | ||
8 | //go:generate go run gen.go -test | ||
9 | |||
10 | package main | ||
11 | |||
12 | import ( | ||
13 | "bytes" | ||
14 | "flag" | ||
15 | "fmt" | ||
16 | "go/format" | ||
17 | "io/ioutil" | ||
18 | "math/rand" | ||
19 | "os" | ||
20 | "sort" | ||
21 | "strings" | ||
22 | ) | ||
23 | |||
24 | // identifier converts s to a Go exported identifier. | ||
25 | // It converts "div" to "Div" and "accept-charset" to "AcceptCharset". | ||
26 | func identifier(s string) string { | ||
27 | b := make([]byte, 0, len(s)) | ||
28 | cap := true | ||
29 | for _, c := range s { | ||
30 | if c == '-' { | ||
31 | cap = true | ||
32 | continue | ||
33 | } | ||
34 | if cap && 'a' <= c && c <= 'z' { | ||
35 | c -= 'a' - 'A' | ||
36 | } | ||
37 | cap = false | ||
38 | b = append(b, byte(c)) | ||
39 | } | ||
40 | return string(b) | ||
41 | } | ||
42 | |||
43 | var test = flag.Bool("test", false, "generate table_test.go") | ||
44 | |||
45 | func genFile(name string, buf *bytes.Buffer) { | ||
46 | b, err := format.Source(buf.Bytes()) | ||
47 | if err != nil { | ||
48 | fmt.Fprintln(os.Stderr, err) | ||
49 | os.Exit(1) | ||
50 | } | ||
51 | if err := ioutil.WriteFile(name, b, 0644); err != nil { | ||
52 | fmt.Fprintln(os.Stderr, err) | ||
53 | os.Exit(1) | ||
54 | } | ||
55 | } | ||
56 | |||
57 | func main() { | ||
58 | flag.Parse() | ||
59 | |||
60 | var all []string | ||
61 | all = append(all, elements...) | ||
62 | all = append(all, attributes...) | ||
63 | all = append(all, eventHandlers...) | ||
64 | all = append(all, extra...) | ||
65 | sort.Strings(all) | ||
66 | |||
67 | // uniq - lists have dups | ||
68 | w := 0 | ||
69 | for _, s := range all { | ||
70 | if w == 0 || all[w-1] != s { | ||
71 | all[w] = s | ||
72 | w++ | ||
73 | } | ||
74 | } | ||
75 | all = all[:w] | ||
76 | |||
77 | if *test { | ||
78 | var buf bytes.Buffer | ||
79 | fmt.Fprintln(&buf, "// Code generated by go generate gen.go; DO NOT EDIT.\n") | ||
80 | fmt.Fprintln(&buf, "//go:generate go run gen.go -test\n") | ||
81 | fmt.Fprintln(&buf, "package atom\n") | ||
82 | fmt.Fprintln(&buf, "var testAtomList = []string{") | ||
83 | for _, s := range all { | ||
84 | fmt.Fprintf(&buf, "\t%q,\n", s) | ||
85 | } | ||
86 | fmt.Fprintln(&buf, "}") | ||
87 | |||
88 | genFile("table_test.go", &buf) | ||
89 | return | ||
90 | } | ||
91 | |||
92 | // Find hash that minimizes table size. | ||
93 | var best *table | ||
94 | for i := 0; i < 1000000; i++ { | ||
95 | if best != nil && 1<<(best.k-1) < len(all) { | ||
96 | break | ||
97 | } | ||
98 | h := rand.Uint32() | ||
99 | for k := uint(0); k <= 16; k++ { | ||
100 | if best != nil && k >= best.k { | ||
101 | break | ||
102 | } | ||
103 | var t table | ||
104 | if t.init(h, k, all) { | ||
105 | best = &t | ||
106 | break | ||
107 | } | ||
108 | } | ||
109 | } | ||
110 | if best == nil { | ||
111 | fmt.Fprintf(os.Stderr, "failed to construct string table\n") | ||
112 | os.Exit(1) | ||
113 | } | ||
114 | |||
115 | // Lay out strings, using overlaps when possible. | ||
116 | layout := append([]string{}, all...) | ||
117 | |||
118 | // Remove strings that are substrings of other strings | ||
119 | for changed := true; changed; { | ||
120 | changed = false | ||
121 | for i, s := range layout { | ||
122 | if s == "" { | ||
123 | continue | ||
124 | } | ||
125 | for j, t := range layout { | ||
126 | if i != j && t != "" && strings.Contains(s, t) { | ||
127 | changed = true | ||
128 | layout[j] = "" | ||
129 | } | ||
130 | } | ||
131 | } | ||
132 | } | ||
133 | |||
134 | // Join strings where one suffix matches another prefix. | ||
135 | for { | ||
136 | // Find best i, j, k such that layout[i][len-k:] == layout[j][:k], | ||
137 | // maximizing overlap length k. | ||
138 | besti := -1 | ||
139 | bestj := -1 | ||
140 | bestk := 0 | ||
141 | for i, s := range layout { | ||
142 | if s == "" { | ||
143 | continue | ||
144 | } | ||
145 | for j, t := range layout { | ||
146 | if i == j { | ||
147 | continue | ||
148 | } | ||
149 | for k := bestk + 1; k <= len(s) && k <= len(t); k++ { | ||
150 | if s[len(s)-k:] == t[:k] { | ||
151 | besti = i | ||
152 | bestj = j | ||
153 | bestk = k | ||
154 | } | ||
155 | } | ||
156 | } | ||
157 | } | ||
158 | if bestk > 0 { | ||
159 | layout[besti] += layout[bestj][bestk:] | ||
160 | layout[bestj] = "" | ||
161 | continue | ||
162 | } | ||
163 | break | ||
164 | } | ||
165 | |||
166 | text := strings.Join(layout, "") | ||
167 | |||
168 | atom := map[string]uint32{} | ||
169 | for _, s := range all { | ||
170 | off := strings.Index(text, s) | ||
171 | if off < 0 { | ||
172 | panic("lost string " + s) | ||
173 | } | ||
174 | atom[s] = uint32(off<<8 | len(s)) | ||
175 | } | ||
176 | |||
177 | var buf bytes.Buffer | ||
178 | // Generate the Go code. | ||
179 | fmt.Fprintln(&buf, "// Code generated by go generate gen.go; DO NOT EDIT.\n") | ||
180 | fmt.Fprintln(&buf, "//go:generate go run gen.go\n") | ||
181 | fmt.Fprintln(&buf, "package atom\n\nconst (") | ||
182 | |||
183 | // compute max len | ||
184 | maxLen := 0 | ||
185 | for _, s := range all { | ||
186 | if maxLen < len(s) { | ||
187 | maxLen = len(s) | ||
188 | } | ||
189 | fmt.Fprintf(&buf, "\t%s Atom = %#x\n", identifier(s), atom[s]) | ||
190 | } | ||
191 | fmt.Fprintln(&buf, ")\n") | ||
192 | |||
193 | fmt.Fprintf(&buf, "const hash0 = %#x\n\n", best.h0) | ||
194 | fmt.Fprintf(&buf, "const maxAtomLen = %d\n\n", maxLen) | ||
195 | |||
196 | fmt.Fprintf(&buf, "var table = [1<<%d]Atom{\n", best.k) | ||
197 | for i, s := range best.tab { | ||
198 | if s == "" { | ||
199 | continue | ||
200 | } | ||
201 | fmt.Fprintf(&buf, "\t%#x: %#x, // %s\n", i, atom[s], s) | ||
202 | } | ||
203 | fmt.Fprintf(&buf, "}\n") | ||
204 | datasize := (1 << best.k) * 4 | ||
205 | |||
206 | fmt.Fprintln(&buf, "const atomText =") | ||
207 | textsize := len(text) | ||
208 | for len(text) > 60 { | ||
209 | fmt.Fprintf(&buf, "\t%q +\n", text[:60]) | ||
210 | text = text[60:] | ||
211 | } | ||
212 | fmt.Fprintf(&buf, "\t%q\n\n", text) | ||
213 | |||
214 | genFile("table.go", &buf) | ||
215 | |||
216 | fmt.Fprintf(os.Stdout, "%d atoms; %d string bytes + %d tables = %d total data\n", len(all), textsize, datasize, textsize+datasize) | ||
217 | } | ||
218 | |||
219 | type byLen []string | ||
220 | |||
221 | func (x byLen) Less(i, j int) bool { return len(x[i]) > len(x[j]) } | ||
222 | func (x byLen) Swap(i, j int) { x[i], x[j] = x[j], x[i] } | ||
223 | func (x byLen) Len() int { return len(x) } | ||
224 | |||
225 | // fnv computes the FNV hash with an arbitrary starting value h. | ||
226 | func fnv(h uint32, s string) uint32 { | ||
227 | for i := 0; i < len(s); i++ { | ||
228 | h ^= uint32(s[i]) | ||
229 | h *= 16777619 | ||
230 | } | ||
231 | return h | ||
232 | } | ||
233 | |||
234 | // A table represents an attempt at constructing the lookup table. | ||
235 | // The lookup table uses cuckoo hashing, meaning that each string | ||
236 | // can be found in one of two positions. | ||
237 | type table struct { | ||
238 | h0 uint32 | ||
239 | k uint | ||
240 | mask uint32 | ||
241 | tab []string | ||
242 | } | ||
243 | |||
244 | // hash returns the two hashes for s. | ||
245 | func (t *table) hash(s string) (h1, h2 uint32) { | ||
246 | h := fnv(t.h0, s) | ||
247 | h1 = h & t.mask | ||
248 | h2 = (h >> 16) & t.mask | ||
249 | return | ||
250 | } | ||
251 | |||
252 | // init initializes the table with the given parameters. | ||
253 | // h0 is the initial hash value, | ||
254 | // k is the number of bits of hash value to use, and | ||
255 | // x is the list of strings to store in the table. | ||
256 | // init returns false if the table cannot be constructed. | ||
257 | func (t *table) init(h0 uint32, k uint, x []string) bool { | ||
258 | t.h0 = h0 | ||
259 | t.k = k | ||
260 | t.tab = make([]string, 1<<k) | ||
261 | t.mask = 1<<k - 1 | ||
262 | for _, s := range x { | ||
263 | if !t.insert(s) { | ||
264 | return false | ||
265 | } | ||
266 | } | ||
267 | return true | ||
268 | } | ||
269 | |||
270 | // insert inserts s in the table. | ||
271 | func (t *table) insert(s string) bool { | ||
272 | h1, h2 := t.hash(s) | ||
273 | if t.tab[h1] == "" { | ||
274 | t.tab[h1] = s | ||
275 | return true | ||
276 | } | ||
277 | if t.tab[h2] == "" { | ||
278 | t.tab[h2] = s | ||
279 | return true | ||
280 | } | ||
281 | if t.push(h1, 0) { | ||
282 | t.tab[h1] = s | ||
283 | return true | ||
284 | } | ||
285 | if t.push(h2, 0) { | ||
286 | t.tab[h2] = s | ||
287 | return true | ||
288 | } | ||
289 | return false | ||
290 | } | ||
291 | |||
292 | // push attempts to push aside the entry in slot i. | ||
293 | func (t *table) push(i uint32, depth int) bool { | ||
294 | if depth > len(t.tab) { | ||
295 | return false | ||
296 | } | ||
297 | s := t.tab[i] | ||
298 | h1, h2 := t.hash(s) | ||
299 | j := h1 + h2 - i | ||
300 | if t.tab[j] != "" && !t.push(j, depth+1) { | ||
301 | return false | ||
302 | } | ||
303 | t.tab[j] = s | ||
304 | return true | ||
305 | } | ||
306 | |||
307 | // The lists of element names and attribute keys were taken from | ||
308 | // https://html.spec.whatwg.org/multipage/indices.html#index | ||
309 | // as of the "HTML Living Standard - Last Updated 18 September 2017" version. | ||
310 | |||
311 | // "command", "keygen" and "menuitem" have been removed from the spec, | ||
312 | // but are kept here for backwards compatibility. | ||
313 | var elements = []string{ | ||
314 | "a", | ||
315 | "abbr", | ||
316 | "address", | ||
317 | "area", | ||
318 | "article", | ||
319 | "aside", | ||
320 | "audio", | ||
321 | "b", | ||
322 | "base", | ||
323 | "bdi", | ||
324 | "bdo", | ||
325 | "blockquote", | ||
326 | "body", | ||
327 | "br", | ||
328 | "button", | ||
329 | "canvas", | ||
330 | "caption", | ||
331 | "cite", | ||
332 | "code", | ||
333 | "col", | ||
334 | "colgroup", | ||
335 | "command", | ||
336 | "data", | ||
337 | "datalist", | ||
338 | "dd", | ||
339 | "del", | ||
340 | "details", | ||
341 | "dfn", | ||
342 | "dialog", | ||
343 | "div", | ||
344 | "dl", | ||
345 | "dt", | ||
346 | "em", | ||
347 | "embed", | ||
348 | "fieldset", | ||
349 | "figcaption", | ||
350 | "figure", | ||
351 | "footer", | ||
352 | "form", | ||
353 | "h1", | ||
354 | "h2", | ||
355 | "h3", | ||
356 | "h4", | ||
357 | "h5", | ||
358 | "h6", | ||
359 | "head", | ||
360 | "header", | ||
361 | "hgroup", | ||
362 | "hr", | ||
363 | "html", | ||
364 | "i", | ||
365 | "iframe", | ||
366 | "img", | ||
367 | "input", | ||
368 | "ins", | ||
369 | "kbd", | ||
370 | "keygen", | ||
371 | "label", | ||
372 | "legend", | ||
373 | "li", | ||
374 | "link", | ||
375 | "main", | ||
376 | "map", | ||
377 | "mark", | ||
378 | "menu", | ||
379 | "menuitem", | ||
380 | "meta", | ||
381 | "meter", | ||
382 | "nav", | ||
383 | "noscript", | ||
384 | "object", | ||
385 | "ol", | ||
386 | "optgroup", | ||
387 | "option", | ||
388 | "output", | ||
389 | "p", | ||
390 | "param", | ||
391 | "picture", | ||
392 | "pre", | ||
393 | "progress", | ||
394 | "q", | ||
395 | "rp", | ||
396 | "rt", | ||
397 | "ruby", | ||
398 | "s", | ||
399 | "samp", | ||
400 | "script", | ||
401 | "section", | ||
402 | "select", | ||
403 | "slot", | ||
404 | "small", | ||
405 | "source", | ||
406 | "span", | ||
407 | "strong", | ||
408 | "style", | ||
409 | "sub", | ||
410 | "summary", | ||
411 | "sup", | ||
412 | "table", | ||
413 | "tbody", | ||
414 | "td", | ||
415 | "template", | ||
416 | "textarea", | ||
417 | "tfoot", | ||
418 | "th", | ||
419 | "thead", | ||
420 | "time", | ||
421 | "title", | ||
422 | "tr", | ||
423 | "track", | ||
424 | "u", | ||
425 | "ul", | ||
426 | "var", | ||
427 | "video", | ||
428 | "wbr", | ||
429 | } | ||
430 | |||
431 | // https://html.spec.whatwg.org/multipage/indices.html#attributes-3 | ||
432 | // | ||
433 | // "challenge", "command", "contextmenu", "dropzone", "icon", "keytype", "mediagroup", | ||
434 | // "radiogroup", "spellcheck", "scoped", "seamless", "sortable" and "sorted" have been removed from the spec, | ||
435 | // but are kept here for backwards compatibility. | ||
436 | var attributes = []string{ | ||
437 | "abbr", | ||
438 | "accept", | ||
439 | "accept-charset", | ||
440 | "accesskey", | ||
441 | "action", | ||
442 | "allowfullscreen", | ||
443 | "allowpaymentrequest", | ||
444 | "allowusermedia", | ||
445 | "alt", | ||
446 | "as", | ||
447 | "async", | ||
448 | "autocomplete", | ||
449 | "autofocus", | ||
450 | "autoplay", | ||
451 | "challenge", | ||
452 | "charset", | ||
453 | "checked", | ||
454 | "cite", | ||
455 | "class", | ||
456 | "color", | ||
457 | "cols", | ||
458 | "colspan", | ||
459 | "command", | ||
460 | "content", | ||
461 | "contenteditable", | ||
462 | "contextmenu", | ||
463 | "controls", | ||
464 | "coords", | ||
465 | "crossorigin", | ||
466 | "data", | ||
467 | "datetime", | ||
468 | "default", | ||
469 | "defer", | ||
470 | "dir", | ||
471 | "dirname", | ||
472 | "disabled", | ||
473 | "download", | ||
474 | "draggable", | ||
475 | "dropzone", | ||
476 | "enctype", | ||
477 | "for", | ||
478 | "form", | ||
479 | "formaction", | ||
480 | "formenctype", | ||
481 | "formmethod", | ||
482 | "formnovalidate", | ||
483 | "formtarget", | ||
484 | "headers", | ||
485 | "height", | ||
486 | "hidden", | ||
487 | "high", | ||
488 | "href", | ||
489 | "hreflang", | ||
490 | "http-equiv", | ||
491 | "icon", | ||
492 | "id", | ||
493 | "inputmode", | ||
494 | "integrity", | ||
495 | "is", | ||
496 | "ismap", | ||
497 | "itemid", | ||
498 | "itemprop", | ||
499 | "itemref", | ||
500 | "itemscope", | ||
501 | "itemtype", | ||
502 | "keytype", | ||
503 | "kind", | ||
504 | "label", | ||
505 | "lang", | ||
506 | "list", | ||
507 | "loop", | ||
508 | "low", | ||
509 | "manifest", | ||
510 | "max", | ||
511 | "maxlength", | ||
512 | "media", | ||
513 | "mediagroup", | ||
514 | "method", | ||
515 | "min", | ||
516 | "minlength", | ||
517 | "multiple", | ||
518 | "muted", | ||
519 | "name", | ||
520 | "nomodule", | ||
521 | "nonce", | ||
522 | "novalidate", | ||
523 | "open", | ||
524 | "optimum", | ||
525 | "pattern", | ||
526 | "ping", | ||
527 | "placeholder", | ||
528 | "playsinline", | ||
529 | "poster", | ||
530 | "preload", | ||
531 | "radiogroup", | ||
532 | "readonly", | ||
533 | "referrerpolicy", | ||
534 | "rel", | ||
535 | "required", | ||
536 | "reversed", | ||
537 | "rows", | ||
538 | "rowspan", | ||
539 | "sandbox", | ||
540 | "spellcheck", | ||
541 | "scope", | ||
542 | "scoped", | ||
543 | "seamless", | ||
544 | "selected", | ||
545 | "shape", | ||
546 | "size", | ||
547 | "sizes", | ||
548 | "sortable", | ||
549 | "sorted", | ||
550 | "slot", | ||
551 | "span", | ||
552 | "spellcheck", | ||
553 | "src", | ||
554 | "srcdoc", | ||
555 | "srclang", | ||
556 | "srcset", | ||
557 | "start", | ||
558 | "step", | ||
559 | "style", | ||
560 | "tabindex", | ||
561 | "target", | ||
562 | "title", | ||
563 | "translate", | ||
564 | "type", | ||
565 | "typemustmatch", | ||
566 | "updateviacache", | ||
567 | "usemap", | ||
568 | "value", | ||
569 | "width", | ||
570 | "workertype", | ||
571 | "wrap", | ||
572 | } | ||
573 | |||
574 | // "onautocomplete", "onautocompleteerror", "onmousewheel", | ||
575 | // "onshow" and "onsort" have been removed from the spec, | ||
576 | // but are kept here for backwards compatibility. | ||
577 | var eventHandlers = []string{ | ||
578 | "onabort", | ||
579 | "onautocomplete", | ||
580 | "onautocompleteerror", | ||
581 | "onauxclick", | ||
582 | "onafterprint", | ||
583 | "onbeforeprint", | ||
584 | "onbeforeunload", | ||
585 | "onblur", | ||
586 | "oncancel", | ||
587 | "oncanplay", | ||
588 | "oncanplaythrough", | ||
589 | "onchange", | ||
590 | "onclick", | ||
591 | "onclose", | ||
592 | "oncontextmenu", | ||
593 | "oncopy", | ||
594 | "oncuechange", | ||
595 | "oncut", | ||
596 | "ondblclick", | ||
597 | "ondrag", | ||
598 | "ondragend", | ||
599 | "ondragenter", | ||
600 | "ondragexit", | ||
601 | "ondragleave", | ||
602 | "ondragover", | ||
603 | "ondragstart", | ||
604 | "ondrop", | ||
605 | "ondurationchange", | ||
606 | "onemptied", | ||
607 | "onended", | ||
608 | "onerror", | ||
609 | "onfocus", | ||
610 | "onhashchange", | ||
611 | "oninput", | ||
612 | "oninvalid", | ||
613 | "onkeydown", | ||
614 | "onkeypress", | ||
615 | "onkeyup", | ||
616 | "onlanguagechange", | ||
617 | "onload", | ||
618 | "onloadeddata", | ||
619 | "onloadedmetadata", | ||
620 | "onloadend", | ||
621 | "onloadstart", | ||
622 | "onmessage", | ||
623 | "onmessageerror", | ||
624 | "onmousedown", | ||
625 | "onmouseenter", | ||
626 | "onmouseleave", | ||
627 | "onmousemove", | ||
628 | "onmouseout", | ||
629 | "onmouseover", | ||
630 | "onmouseup", | ||
631 | "onmousewheel", | ||
632 | "onwheel", | ||
633 | "onoffline", | ||
634 | "ononline", | ||
635 | "onpagehide", | ||
636 | "onpageshow", | ||
637 | "onpaste", | ||
638 | "onpause", | ||
639 | "onplay", | ||
640 | "onplaying", | ||
641 | "onpopstate", | ||
642 | "onprogress", | ||
643 | "onratechange", | ||
644 | "onreset", | ||
645 | "onresize", | ||
646 | "onrejectionhandled", | ||
647 | "onscroll", | ||
648 | "onsecuritypolicyviolation", | ||
649 | "onseeked", | ||
650 | "onseeking", | ||
651 | "onselect", | ||
652 | "onshow", | ||
653 | "onsort", | ||
654 | "onstalled", | ||
655 | "onstorage", | ||
656 | "onsubmit", | ||
657 | "onsuspend", | ||
658 | "ontimeupdate", | ||
659 | "ontoggle", | ||
660 | "onunhandledrejection", | ||
661 | "onunload", | ||
662 | "onvolumechange", | ||
663 | "onwaiting", | ||
664 | } | ||
665 | |||
666 | // extra are ad-hoc values not covered by any of the lists above. | ||
667 | var extra = []string{ | ||
668 | "align", | ||
669 | "annotation", | ||
670 | "annotation-xml", | ||
671 | "applet", | ||
672 | "basefont", | ||
673 | "bgsound", | ||
674 | "big", | ||
675 | "blink", | ||
676 | "center", | ||
677 | "color", | ||
678 | "desc", | ||
679 | "face", | ||
680 | "font", | ||
681 | "foreignObject", // HTML is case-insensitive, but SVG-embedded-in-HTML is case-sensitive. | ||
682 | "foreignobject", | ||
683 | "frame", | ||
684 | "frameset", | ||
685 | "image", | ||
686 | "isindex", | ||
687 | "listing", | ||
688 | "malignmark", | ||
689 | "marquee", | ||
690 | "math", | ||
691 | "mglyph", | ||
692 | "mi", | ||
693 | "mn", | ||
694 | "mo", | ||
695 | "ms", | ||
696 | "mtext", | ||
697 | "nobr", | ||
698 | "noembed", | ||
699 | "noframes", | ||
700 | "plaintext", | ||
701 | "prompt", | ||
702 | "public", | ||
703 | "spacer", | ||
704 | "strike", | ||
705 | "svg", | ||
706 | "system", | ||
707 | "tt", | ||
708 | "xmp", | ||
709 | } | ||
diff --git a/vendor/golang.org/x/net/html/atom/table.go b/vendor/golang.org/x/net/html/atom/table.go index 2605ba3..f74018e 100644 --- a/vendor/golang.org/x/net/html/atom/table.go +++ b/vendor/golang.org/x/net/html/atom/table.go | |||
@@ -1,713 +1,777 @@ | |||
1 | // generated by go run gen.go; DO NOT EDIT | 1 | // Code generated by go generate gen.go; DO NOT EDIT. |
2 | |||
3 | //go:generate go run gen.go | ||
2 | 4 | ||
3 | package atom | 5 | package atom |
4 | 6 | ||
5 | const ( | 7 | const ( |
6 | A Atom = 0x1 | 8 | A Atom = 0x1 |
7 | Abbr Atom = 0x4 | 9 | Abbr Atom = 0x4 |
8 | Accept Atom = 0x2106 | 10 | Accept Atom = 0x1a06 |
9 | AcceptCharset Atom = 0x210e | 11 | AcceptCharset Atom = 0x1a0e |
10 | Accesskey Atom = 0x3309 | 12 | Accesskey Atom = 0x2c09 |
11 | Action Atom = 0x1f606 | 13 | Action Atom = 0x25a06 |
12 | Address Atom = 0x4f307 | 14 | Address Atom = 0x6ed07 |
13 | Align Atom = 0x1105 | 15 | Align Atom = 0x6d405 |
14 | Alt Atom = 0x4503 | 16 | Allowfullscreen Atom = 0x1f00f |
15 | Annotation Atom = 0x1670a | 17 | Allowpaymentrequest Atom = 0x6913 |
16 | AnnotationXml Atom = 0x1670e | 18 | Allowusermedia Atom = 0x850e |
17 | Applet Atom = 0x2b306 | 19 | Alt Atom = 0xb003 |
18 | Area Atom = 0x2fa04 | 20 | Annotation Atom = 0x1b90a |
19 | Article Atom = 0x38807 | 21 | AnnotationXml Atom = 0x1b90e |
20 | Aside Atom = 0x8305 | 22 | Applet Atom = 0x30106 |
21 | Async Atom = 0x7b05 | 23 | Area Atom = 0x34a04 |
22 | Audio Atom = 0xa605 | 24 | Article Atom = 0x3f007 |
23 | Autocomplete Atom = 0x1fc0c | 25 | As Atom = 0xb902 |
24 | Autofocus Atom = 0xb309 | 26 | Aside Atom = 0xc105 |
25 | Autoplay Atom = 0xce08 | 27 | Async Atom = 0xb905 |
26 | B Atom = 0x101 | 28 | Audio Atom = 0xcf05 |
27 | Base Atom = 0xd604 | 29 | Autocomplete Atom = 0x2600c |
28 | Basefont Atom = 0xd608 | 30 | Autofocus Atom = 0xeb09 |
29 | Bdi Atom = 0x1a03 | 31 | Autoplay Atom = 0x10608 |
30 | Bdo Atom = 0xe703 | 32 | B Atom = 0x101 |
31 | Bgsound Atom = 0x11807 | 33 | Base Atom = 0x11504 |
32 | Big Atom = 0x12403 | 34 | Basefont Atom = 0x11508 |
33 | Blink Atom = 0x12705 | 35 | Bdi Atom = 0x16103 |
34 | Blockquote Atom = 0x12c0a | 36 | Bdo Atom = 0x13403 |
35 | Body Atom = 0x2f04 | 37 | Bgsound Atom = 0x14707 |
36 | Br Atom = 0x202 | 38 | Big Atom = 0x15903 |
37 | Button Atom = 0x13606 | 39 | Blink Atom = 0x15c05 |
38 | Canvas Atom = 0x7f06 | 40 | Blockquote Atom = 0x1680a |
39 | Caption Atom = 0x1bb07 | 41 | Body Atom = 0x2804 |
40 | Center Atom = 0x5b506 | 42 | Br Atom = 0x202 |
41 | Challenge Atom = 0x21f09 | 43 | Button Atom = 0x17206 |
42 | Charset Atom = 0x2807 | 44 | Canvas Atom = 0xbd06 |
43 | Checked Atom = 0x32807 | 45 | Caption Atom = 0x21907 |
44 | Cite Atom = 0x3c804 | 46 | Center Atom = 0x20806 |
45 | Class Atom = 0x4de05 | 47 | Challenge Atom = 0x28309 |
46 | Code Atom = 0x14904 | 48 | Charset Atom = 0x2107 |
47 | Col Atom = 0x15003 | 49 | Checked Atom = 0x46d07 |
48 | Colgroup Atom = 0x15008 | 50 | Cite Atom = 0x55804 |
49 | Color Atom = 0x15d05 | 51 | Class Atom = 0x5b905 |
50 | Cols Atom = 0x16204 | 52 | Code Atom = 0x19004 |
51 | Colspan Atom = 0x16207 | 53 | Col Atom = 0x19703 |
52 | Command Atom = 0x17507 | 54 | Colgroup Atom = 0x19708 |
53 | Content Atom = 0x42307 | 55 | Color Atom = 0x1af05 |
54 | Contenteditable Atom = 0x4230f | 56 | Cols Atom = 0x1b404 |
55 | Contextmenu Atom = 0x3310b | 57 | Colspan Atom = 0x1b407 |
56 | Controls Atom = 0x18808 | 58 | Command Atom = 0x1c707 |
57 | Coords Atom = 0x19406 | 59 | Content Atom = 0x57f07 |
58 | Crossorigin Atom = 0x19f0b | 60 | Contenteditable Atom = 0x57f0f |
59 | Data Atom = 0x44a04 | 61 | Contextmenu Atom = 0x3740b |
60 | Datalist Atom = 0x44a08 | 62 | Controls Atom = 0x1ce08 |
61 | Datetime Atom = 0x23c08 | 63 | Coords Atom = 0x1da06 |
62 | Dd Atom = 0x26702 | 64 | Crossorigin Atom = 0x1e30b |
63 | Default Atom = 0x8607 | 65 | Data Atom = 0x49904 |
64 | Defer Atom = 0x14b05 | 66 | Datalist Atom = 0x49908 |
65 | Del Atom = 0x3ef03 | 67 | Datetime Atom = 0x2a008 |
66 | Desc Atom = 0x4db04 | 68 | Dd Atom = 0x2bf02 |
67 | Details Atom = 0x4807 | 69 | Default Atom = 0xc407 |
68 | Dfn Atom = 0x6103 | 70 | Defer Atom = 0x19205 |
69 | Dialog Atom = 0x1b06 | 71 | Del Atom = 0x44603 |
70 | Dir Atom = 0x6903 | 72 | Desc Atom = 0x55504 |
71 | Dirname Atom = 0x6907 | 73 | Details Atom = 0x4607 |
72 | Disabled Atom = 0x10c08 | 74 | Dfn Atom = 0x5f03 |
73 | Div Atom = 0x11303 | 75 | Dialog Atom = 0x16206 |
74 | Dl Atom = 0x11e02 | 76 | Dir Atom = 0xa303 |
75 | Download Atom = 0x40008 | 77 | Dirname Atom = 0xa307 |
76 | Draggable Atom = 0x17b09 | 78 | Disabled Atom = 0x14d08 |
77 | Dropzone Atom = 0x39108 | 79 | Div Atom = 0x15403 |
78 | Dt Atom = 0x50902 | 80 | Dl Atom = 0x5e202 |
79 | Em Atom = 0x6502 | 81 | Download Atom = 0x45708 |
80 | Embed Atom = 0x6505 | 82 | Draggable Atom = 0x18309 |
81 | Enctype Atom = 0x21107 | 83 | Dropzone Atom = 0x3f908 |
82 | Face Atom = 0x5b304 | 84 | Dt Atom = 0x64702 |
83 | Fieldset Atom = 0x1b008 | 85 | Em Atom = 0x4202 |
84 | Figcaption Atom = 0x1b80a | 86 | Embed Atom = 0x4205 |
85 | Figure Atom = 0x1cc06 | 87 | Enctype Atom = 0x27507 |
86 | Font Atom = 0xda04 | 88 | Face Atom = 0x20604 |
87 | Footer Atom = 0x8d06 | 89 | Fieldset Atom = 0x20e08 |
88 | For Atom = 0x1d803 | 90 | Figcaption Atom = 0x2160a |
89 | ForeignObject Atom = 0x1d80d | 91 | Figure Atom = 0x23006 |
90 | Foreignobject Atom = 0x1e50d | 92 | Font Atom = 0x11904 |
91 | Form Atom = 0x1f204 | 93 | Footer Atom = 0xb306 |
92 | Formaction Atom = 0x1f20a | 94 | For Atom = 0x23c03 |
93 | Formenctype Atom = 0x20d0b | 95 | ForeignObject Atom = 0x23c0d |
94 | Formmethod Atom = 0x2280a | 96 | Foreignobject Atom = 0x2490d |
95 | Formnovalidate Atom = 0x2320e | 97 | Form Atom = 0x25604 |
96 | Formtarget Atom = 0x2470a | 98 | Formaction Atom = 0x2560a |
97 | Frame Atom = 0x9a05 | 99 | Formenctype Atom = 0x2710b |
98 | Frameset Atom = 0x9a08 | 100 | Formmethod Atom = 0x28c0a |
99 | H1 Atom = 0x26e02 | 101 | Formnovalidate Atom = 0x2960e |
100 | H2 Atom = 0x29402 | 102 | Formtarget Atom = 0x2a80a |
101 | H3 Atom = 0x2a702 | 103 | Frame Atom = 0x5705 |
102 | H4 Atom = 0x2e902 | 104 | Frameset Atom = 0x5708 |
103 | H5 Atom = 0x2f302 | 105 | H1 Atom = 0x14502 |
104 | H6 Atom = 0x50b02 | 106 | H2 Atom = 0x2c602 |
105 | Head Atom = 0x2d504 | 107 | H3 Atom = 0x2f502 |
106 | Header Atom = 0x2d506 | 108 | H4 Atom = 0x33902 |
107 | Headers Atom = 0x2d507 | 109 | H5 Atom = 0x34302 |
108 | Height Atom = 0x25106 | 110 | H6 Atom = 0x64902 |
109 | Hgroup Atom = 0x25906 | 111 | Head Atom = 0x32504 |
110 | Hidden Atom = 0x26506 | 112 | Header Atom = 0x32506 |
111 | High Atom = 0x26b04 | 113 | Headers Atom = 0x32507 |
112 | Hr Atom = 0x27002 | 114 | Height Atom = 0x12c06 |
113 | Href Atom = 0x27004 | 115 | Hgroup Atom = 0x2b206 |
114 | Hreflang Atom = 0x27008 | 116 | Hidden Atom = 0x2bd06 |
115 | Html Atom = 0x25504 | 117 | High Atom = 0x2c304 |
116 | HttpEquiv Atom = 0x2780a | 118 | Hr Atom = 0x14002 |
117 | I Atom = 0x601 | 119 | Href Atom = 0x2c804 |
118 | Icon Atom = 0x42204 | 120 | Hreflang Atom = 0x2c808 |
119 | Id Atom = 0x8502 | 121 | Html Atom = 0x13004 |
120 | Iframe Atom = 0x29606 | 122 | HttpEquiv Atom = 0x2d00a |
121 | Image Atom = 0x29c05 | 123 | I Atom = 0x601 |
122 | Img Atom = 0x2a103 | 124 | Icon Atom = 0x57e04 |
123 | Input Atom = 0x3e805 | 125 | Id Atom = 0xc302 |
124 | Inputmode Atom = 0x3e809 | 126 | Iframe Atom = 0x2e406 |
125 | Ins Atom = 0x1a803 | 127 | Image Atom = 0x2ea05 |
126 | Isindex Atom = 0x2a907 | 128 | Img Atom = 0x2ef03 |
127 | Ismap Atom = 0x2b005 | 129 | Input Atom = 0x43f05 |
128 | Itemid Atom = 0x33c06 | 130 | Inputmode Atom = 0x43f09 |
129 | Itemprop Atom = 0x3c908 | 131 | Ins Atom = 0x1ec03 |
130 | Itemref Atom = 0x5ad07 | 132 | Integrity Atom = 0x22709 |
131 | Itemscope Atom = 0x2b909 | 133 | Is Atom = 0x14e02 |
132 | Itemtype Atom = 0x2c308 | 134 | Isindex Atom = 0x2f707 |
133 | Kbd Atom = 0x1903 | 135 | Ismap Atom = 0x2fe05 |
134 | Keygen Atom = 0x3906 | 136 | Itemid Atom = 0x37f06 |
135 | Keytype Atom = 0x53707 | 137 | Itemprop Atom = 0x55908 |
136 | Kind Atom = 0x10904 | 138 | Itemref Atom = 0x3c107 |
137 | Label Atom = 0xf005 | 139 | Itemscope Atom = 0x66d09 |
138 | Lang Atom = 0x27404 | 140 | Itemtype Atom = 0x30708 |
139 | Legend Atom = 0x18206 | 141 | Kbd Atom = 0x16003 |
140 | Li Atom = 0x1202 | 142 | Keygen Atom = 0x3206 |
141 | Link Atom = 0x12804 | 143 | Keytype Atom = 0x7e07 |
142 | List Atom = 0x44e04 | 144 | Kind Atom = 0x18004 |
143 | Listing Atom = 0x44e07 | 145 | Label Atom = 0xda05 |
144 | Loop Atom = 0xf404 | 146 | Lang Atom = 0x2cc04 |
145 | Low Atom = 0x11f03 | 147 | Legend Atom = 0x18a06 |
146 | Malignmark Atom = 0x100a | 148 | Li Atom = 0x11102 |
147 | Manifest Atom = 0x5f108 | 149 | Link Atom = 0x15d04 |
148 | Map Atom = 0x2b203 | 150 | List Atom = 0x49d04 |
149 | Mark Atom = 0x1604 | 151 | Listing Atom = 0x49d07 |
150 | Marquee Atom = 0x2cb07 | 152 | Loop Atom = 0xde04 |
151 | Math Atom = 0x2d204 | 153 | Low Atom = 0x6b03 |
152 | Max Atom = 0x2e103 | 154 | Main Atom = 0x1004 |
153 | Maxlength Atom = 0x2e109 | 155 | Malignmark Atom = 0x6d30a |
154 | Media Atom = 0x6e05 | 156 | Manifest Atom = 0x30f08 |
155 | Mediagroup Atom = 0x6e0a | 157 | Map Atom = 0x30003 |
156 | Menu Atom = 0x33804 | 158 | Mark Atom = 0x6d904 |
157 | Menuitem Atom = 0x33808 | 159 | Marquee Atom = 0x31b07 |
158 | Meta Atom = 0x45d04 | 160 | Math Atom = 0x32204 |
159 | Meter Atom = 0x24205 | 161 | Max Atom = 0x33103 |
160 | Method Atom = 0x22c06 | 162 | Maxlength Atom = 0x33109 |
161 | Mglyph Atom = 0x2a206 | 163 | Media Atom = 0x8e05 |
162 | Mi Atom = 0x2eb02 | 164 | Mediagroup Atom = 0x8e0a |
163 | Min Atom = 0x2eb03 | 165 | Menu Atom = 0x37b04 |
164 | Minlength Atom = 0x2eb09 | 166 | Menuitem Atom = 0x37b08 |
165 | Mn Atom = 0x23502 | 167 | Meta Atom = 0x4ac04 |
166 | Mo Atom = 0x3ed02 | 168 | Meter Atom = 0xa805 |
167 | Ms Atom = 0x2bc02 | 169 | Method Atom = 0x29006 |
168 | Mtext Atom = 0x2f505 | 170 | Mglyph Atom = 0x2f006 |
169 | Multiple Atom = 0x30308 | 171 | Mi Atom = 0x33b02 |
170 | Muted Atom = 0x30b05 | 172 | Min Atom = 0x33b03 |
171 | Name Atom = 0x6c04 | 173 | Minlength Atom = 0x33b09 |
172 | Nav Atom = 0x3e03 | 174 | Mn Atom = 0x29902 |
173 | Nobr Atom = 0x5704 | 175 | Mo Atom = 0x6302 |
174 | Noembed Atom = 0x6307 | 176 | Ms Atom = 0x67002 |
175 | Noframes Atom = 0x9808 | 177 | Mtext Atom = 0x34505 |
176 | Noscript Atom = 0x3d208 | 178 | Multiple Atom = 0x35308 |
177 | Novalidate Atom = 0x2360a | 179 | Muted Atom = 0x35b05 |
178 | Object Atom = 0x1ec06 | 180 | Name Atom = 0xa604 |
179 | Ol Atom = 0xc902 | 181 | Nav Atom = 0x1303 |
180 | Onabort Atom = 0x13a07 | 182 | Nobr Atom = 0x3704 |
181 | Onafterprint Atom = 0x1c00c | 183 | Noembed Atom = 0x4007 |
182 | Onautocomplete Atom = 0x1fa0e | 184 | Noframes Atom = 0x5508 |
183 | Onautocompleteerror Atom = 0x1fa13 | 185 | Nomodule Atom = 0x6108 |
184 | Onbeforeprint Atom = 0x6040d | 186 | Nonce Atom = 0x56205 |
185 | Onbeforeunload Atom = 0x4e70e | 187 | Noscript Atom = 0x1fe08 |
186 | Onblur Atom = 0xaa06 | 188 | Novalidate Atom = 0x29a0a |
187 | Oncancel Atom = 0xe908 | 189 | Object Atom = 0x25006 |
188 | Oncanplay Atom = 0x28509 | 190 | Ol Atom = 0x10102 |
189 | Oncanplaythrough Atom = 0x28510 | 191 | Onabort Atom = 0x17607 |
190 | Onchange Atom = 0x3a708 | 192 | Onafterprint Atom = 0x21e0c |
191 | Onclick Atom = 0x31007 | 193 | Onautocomplete Atom = 0x25e0e |
192 | Onclose Atom = 0x31707 | 194 | Onautocompleteerror Atom = 0x25e13 |
193 | Oncontextmenu Atom = 0x32f0d | 195 | Onauxclick Atom = 0x61b0a |
194 | Oncuechange Atom = 0x3420b | 196 | Onbeforeprint Atom = 0x69a0d |
195 | Ondblclick Atom = 0x34d0a | 197 | Onbeforeunload Atom = 0x6e10e |
196 | Ondrag Atom = 0x35706 | 198 | Onblur Atom = 0x5c206 |
197 | Ondragend Atom = 0x35709 | 199 | Oncancel Atom = 0xd308 |
198 | Ondragenter Atom = 0x3600b | 200 | Oncanplay Atom = 0x13609 |
199 | Ondragleave Atom = 0x36b0b | 201 | Oncanplaythrough Atom = 0x13610 |
200 | Ondragover Atom = 0x3760a | 202 | Onchange Atom = 0x40f08 |
201 | Ondragstart Atom = 0x3800b | 203 | Onclick Atom = 0x2dd07 |
202 | Ondrop Atom = 0x38f06 | 204 | Onclose Atom = 0x36007 |
203 | Ondurationchange Atom = 0x39f10 | 205 | Oncontextmenu Atom = 0x3720d |
204 | Onemptied Atom = 0x39609 | 206 | Oncopy Atom = 0x38506 |
205 | Onended Atom = 0x3af07 | 207 | Oncuechange Atom = 0x38b0b |
206 | Onerror Atom = 0x3b607 | 208 | Oncut Atom = 0x39605 |
207 | Onfocus Atom = 0x3bd07 | 209 | Ondblclick Atom = 0x39b0a |
208 | Onhashchange Atom = 0x3da0c | 210 | Ondrag Atom = 0x3a506 |
209 | Oninput Atom = 0x3e607 | 211 | Ondragend Atom = 0x3a509 |
210 | Oninvalid Atom = 0x3f209 | 212 | Ondragenter Atom = 0x3ae0b |
211 | Onkeydown Atom = 0x3fb09 | 213 | Ondragexit Atom = 0x3b90a |
212 | Onkeypress Atom = 0x4080a | 214 | Ondragleave Atom = 0x3d30b |
213 | Onkeyup Atom = 0x41807 | 215 | Ondragover Atom = 0x3de0a |
214 | Onlanguagechange Atom = 0x43210 | 216 | Ondragstart Atom = 0x3e80b |
215 | Onload Atom = 0x44206 | 217 | Ondrop Atom = 0x3f706 |
216 | Onloadeddata Atom = 0x4420c | 218 | Ondurationchange Atom = 0x40710 |
217 | Onloadedmetadata Atom = 0x45510 | 219 | Onemptied Atom = 0x3fe09 |
218 | Onloadstart Atom = 0x46b0b | 220 | Onended Atom = 0x41707 |
219 | Onmessage Atom = 0x47609 | 221 | Onerror Atom = 0x41e07 |
220 | Onmousedown Atom = 0x47f0b | 222 | Onfocus Atom = 0x42507 |
221 | Onmousemove Atom = 0x48a0b | 223 | Onhashchange Atom = 0x4310c |
222 | Onmouseout Atom = 0x4950a | 224 | Oninput Atom = 0x43d07 |
223 | Onmouseover Atom = 0x4a20b | 225 | Oninvalid Atom = 0x44909 |
224 | Onmouseup Atom = 0x4ad09 | 226 | Onkeydown Atom = 0x45209 |
225 | Onmousewheel Atom = 0x4b60c | 227 | Onkeypress Atom = 0x45f0a |
226 | Onoffline Atom = 0x4c209 | 228 | Onkeyup Atom = 0x47407 |
227 | Ononline Atom = 0x4cb08 | 229 | Onlanguagechange Atom = 0x48110 |
228 | Onpagehide Atom = 0x4d30a | 230 | Onload Atom = 0x49106 |
229 | Onpageshow Atom = 0x4fe0a | 231 | Onloadeddata Atom = 0x4910c |
230 | Onpause Atom = 0x50d07 | 232 | Onloadedmetadata Atom = 0x4a410 |
231 | Onplay Atom = 0x51706 | 233 | Onloadend Atom = 0x4ba09 |
232 | Onplaying Atom = 0x51709 | 234 | Onloadstart Atom = 0x4c30b |
233 | Onpopstate Atom = 0x5200a | 235 | Onmessage Atom = 0x4ce09 |
234 | Onprogress Atom = 0x52a0a | 236 | Onmessageerror Atom = 0x4ce0e |
235 | Onratechange Atom = 0x53e0c | 237 | Onmousedown Atom = 0x4dc0b |
236 | Onreset Atom = 0x54a07 | 238 | Onmouseenter Atom = 0x4e70c |
237 | Onresize Atom = 0x55108 | 239 | Onmouseleave Atom = 0x4f30c |
238 | Onscroll Atom = 0x55f08 | 240 | Onmousemove Atom = 0x4ff0b |
239 | Onseeked Atom = 0x56708 | 241 | Onmouseout Atom = 0x50a0a |
240 | Onseeking Atom = 0x56f09 | 242 | Onmouseover Atom = 0x5170b |
241 | Onselect Atom = 0x57808 | 243 | Onmouseup Atom = 0x52209 |
242 | Onshow Atom = 0x58206 | 244 | Onmousewheel Atom = 0x5300c |
243 | Onsort Atom = 0x58b06 | 245 | Onoffline Atom = 0x53c09 |
244 | Onstalled Atom = 0x59509 | 246 | Ononline Atom = 0x54508 |
245 | Onstorage Atom = 0x59e09 | 247 | Onpagehide Atom = 0x54d0a |
246 | Onsubmit Atom = 0x5a708 | 248 | Onpageshow Atom = 0x5670a |
247 | Onsuspend Atom = 0x5bb09 | 249 | Onpaste Atom = 0x57307 |
248 | Ontimeupdate Atom = 0xdb0c | 250 | Onpause Atom = 0x58e07 |
249 | Ontoggle Atom = 0x5c408 | 251 | Onplay Atom = 0x59806 |
250 | Onunload Atom = 0x5cc08 | 252 | Onplaying Atom = 0x59809 |
251 | Onvolumechange Atom = 0x5d40e | 253 | Onpopstate Atom = 0x5a10a |
252 | Onwaiting Atom = 0x5e209 | 254 | Onprogress Atom = 0x5ab0a |
253 | Open Atom = 0x3cf04 | 255 | Onratechange Atom = 0x5c80c |
254 | Optgroup Atom = 0xf608 | 256 | Onrejectionhandled Atom = 0x5d412 |
255 | Optimum Atom = 0x5eb07 | 257 | Onreset Atom = 0x5e607 |
256 | Option Atom = 0x60006 | 258 | Onresize Atom = 0x5ed08 |
257 | Output Atom = 0x49c06 | 259 | Onscroll Atom = 0x5fc08 |
258 | P Atom = 0xc01 | 260 | Onsecuritypolicyviolation Atom = 0x60419 |
259 | Param Atom = 0xc05 | 261 | Onseeked Atom = 0x62508 |
260 | Pattern Atom = 0x5107 | 262 | Onseeking Atom = 0x62d09 |
261 | Ping Atom = 0x7704 | 263 | Onselect Atom = 0x63608 |
262 | Placeholder Atom = 0xc30b | 264 | Onshow Atom = 0x64006 |
263 | Plaintext Atom = 0xfd09 | 265 | Onsort Atom = 0x64b06 |
264 | Poster Atom = 0x15706 | 266 | Onstalled Atom = 0x65509 |
265 | Pre Atom = 0x25e03 | 267 | Onstorage Atom = 0x65e09 |
266 | Preload Atom = 0x25e07 | 268 | Onsubmit Atom = 0x66708 |
267 | Progress Atom = 0x52c08 | 269 | Onsuspend Atom = 0x67709 |
268 | Prompt Atom = 0x5fa06 | 270 | Ontimeupdate Atom = 0x11a0c |
269 | Public Atom = 0x41e06 | 271 | Ontoggle Atom = 0x68008 |
270 | Q Atom = 0x13101 | 272 | Onunhandledrejection Atom = 0x68814 |
271 | Radiogroup Atom = 0x30a | 273 | Onunload Atom = 0x6a708 |
272 | Readonly Atom = 0x2fb08 | 274 | Onvolumechange Atom = 0x6af0e |
273 | Rel Atom = 0x25f03 | 275 | Onwaiting Atom = 0x6bd09 |
274 | Required Atom = 0x1d008 | 276 | Onwheel Atom = 0x6c607 |
275 | Reversed Atom = 0x5a08 | 277 | Open Atom = 0x55f04 |
276 | Rows Atom = 0x9204 | 278 | Optgroup Atom = 0xe008 |
277 | Rowspan Atom = 0x9207 | 279 | Optimum Atom = 0x6cd07 |
278 | Rp Atom = 0x1c602 | 280 | Option Atom = 0x6dd06 |
279 | Rt Atom = 0x13f02 | 281 | Output Atom = 0x51106 |
280 | Ruby Atom = 0xaf04 | 282 | P Atom = 0xc01 |
281 | S Atom = 0x2c01 | 283 | Param Atom = 0xc05 |
282 | Samp Atom = 0x4e04 | 284 | Pattern Atom = 0x4f07 |
283 | Sandbox Atom = 0xbb07 | 285 | Picture Atom = 0x9707 |
284 | Scope Atom = 0x2bd05 | 286 | Ping Atom = 0xe704 |
285 | Scoped Atom = 0x2bd06 | 287 | Placeholder Atom = 0xfb0b |
286 | Script Atom = 0x3d406 | 288 | Plaintext Atom = 0x19e09 |
287 | Seamless Atom = 0x31c08 | 289 | Playsinline Atom = 0x10a0b |
288 | Section Atom = 0x4e207 | 290 | Poster Atom = 0x2b706 |
289 | Select Atom = 0x57a06 | 291 | Pre Atom = 0x46403 |
290 | Selected Atom = 0x57a08 | 292 | Preload Atom = 0x47a07 |
291 | Shape Atom = 0x4f905 | 293 | Progress Atom = 0x5ad08 |
292 | Size Atom = 0x55504 | 294 | Prompt Atom = 0x52a06 |
293 | Sizes Atom = 0x55505 | 295 | Public Atom = 0x57a06 |
294 | Small Atom = 0x18f05 | 296 | Q Atom = 0x7701 |
295 | Sortable Atom = 0x58d08 | 297 | Radiogroup Atom = 0x30a |
296 | Sorted Atom = 0x19906 | 298 | Readonly Atom = 0x34b08 |
297 | Source Atom = 0x1aa06 | 299 | Referrerpolicy Atom = 0x3c50e |
298 | Spacer Atom = 0x2db06 | 300 | Rel Atom = 0x47b03 |
299 | Span Atom = 0x9504 | 301 | Required Atom = 0x23408 |
300 | Spellcheck Atom = 0x3230a | 302 | Reversed Atom = 0x9c08 |
301 | Src Atom = 0x3c303 | 303 | Rows Atom = 0x3a04 |
302 | Srcdoc Atom = 0x3c306 | 304 | Rowspan Atom = 0x3a07 |
303 | Srclang Atom = 0x41107 | 305 | Rp Atom = 0x22402 |
304 | Start Atom = 0x38605 | 306 | Rt Atom = 0x17b02 |
305 | Step Atom = 0x5f704 | 307 | Ruby Atom = 0xac04 |
306 | Strike Atom = 0x53306 | 308 | S Atom = 0x2501 |
307 | Strong Atom = 0x55906 | 309 | Samp Atom = 0x4c04 |
308 | Style Atom = 0x61105 | 310 | Sandbox Atom = 0xf307 |
309 | Sub Atom = 0x5a903 | 311 | Scope Atom = 0x67105 |
310 | Summary Atom = 0x61607 | 312 | Scoped Atom = 0x67106 |
311 | Sup Atom = 0x61d03 | 313 | Script Atom = 0x20006 |
312 | Svg Atom = 0x62003 | 314 | Seamless Atom = 0x36508 |
313 | System Atom = 0x62306 | 315 | Section Atom = 0x5bd07 |
314 | Tabindex Atom = 0x46308 | 316 | Select Atom = 0x63806 |
315 | Table Atom = 0x42d05 | 317 | Selected Atom = 0x63808 |
316 | Target Atom = 0x24b06 | 318 | Shape Atom = 0x1d505 |
317 | Tbody Atom = 0x2e05 | 319 | Size Atom = 0x5f104 |
318 | Td Atom = 0x4702 | 320 | Sizes Atom = 0x5f105 |
319 | Template Atom = 0x62608 | 321 | Slot Atom = 0x1df04 |
320 | Textarea Atom = 0x2f608 | 322 | Small Atom = 0x1ee05 |
321 | Tfoot Atom = 0x8c05 | 323 | Sortable Atom = 0x64d08 |
322 | Th Atom = 0x22e02 | 324 | Sorted Atom = 0x32b06 |
323 | Thead Atom = 0x2d405 | 325 | Source Atom = 0x36c06 |
324 | Time Atom = 0xdd04 | 326 | Spacer Atom = 0x42b06 |
325 | Title Atom = 0xa105 | 327 | Span Atom = 0x3d04 |
326 | Tr Atom = 0x10502 | 328 | Spellcheck Atom = 0x4680a |
327 | Track Atom = 0x10505 | 329 | Src Atom = 0x5b403 |
328 | Translate Atom = 0x14009 | 330 | Srcdoc Atom = 0x5b406 |
329 | Tt Atom = 0x5302 | 331 | Srclang Atom = 0x5f507 |
330 | Type Atom = 0x21404 | 332 | Srcset Atom = 0x6f306 |
331 | Typemustmatch Atom = 0x2140d | 333 | Start Atom = 0x3ee05 |
332 | U Atom = 0xb01 | 334 | Step Atom = 0x57704 |
333 | Ul Atom = 0x8a02 | 335 | Strike Atom = 0x7a06 |
334 | Usemap Atom = 0x51106 | 336 | Strong Atom = 0x31506 |
335 | Value Atom = 0x4005 | 337 | Style Atom = 0x6f905 |
336 | Var Atom = 0x11503 | 338 | Sub Atom = 0x66903 |
337 | Video Atom = 0x28105 | 339 | Summary Atom = 0x6fe07 |
338 | Wbr Atom = 0x12103 | 340 | Sup Atom = 0x70503 |
339 | Width Atom = 0x50705 | 341 | Svg Atom = 0x70803 |
340 | Wrap Atom = 0x58704 | 342 | System Atom = 0x70b06 |
341 | Xmp Atom = 0xc103 | 343 | Tabindex Atom = 0x4b208 |
344 | Table Atom = 0x58905 | ||
345 | Target Atom = 0x2ac06 | ||
346 | Tbody Atom = 0x2705 | ||
347 | Td Atom = 0x5e02 | ||
348 | Template Atom = 0x70e08 | ||
349 | Textarea Atom = 0x34608 | ||
350 | Tfoot Atom = 0xb205 | ||
351 | Th Atom = 0x13f02 | ||
352 | Thead Atom = 0x32405 | ||
353 | Time Atom = 0x11c04 | ||
354 | Title Atom = 0xca05 | ||
355 | Tr Atom = 0x7402 | ||
356 | Track Atom = 0x17c05 | ||
357 | Translate Atom = 0x1a609 | ||
358 | Tt Atom = 0x5102 | ||
359 | Type Atom = 0x8104 | ||
360 | Typemustmatch Atom = 0x2780d | ||
361 | U Atom = 0xb01 | ||
362 | Ul Atom = 0x6602 | ||
363 | Updateviacache Atom = 0x1200e | ||
364 | Usemap Atom = 0x59206 | ||
365 | Value Atom = 0x1505 | ||
366 | Var Atom = 0x15603 | ||
367 | Video Atom = 0x2d905 | ||
368 | Wbr Atom = 0x57003 | ||
369 | Width Atom = 0x64505 | ||
370 | Workertype Atom = 0x7160a | ||
371 | Wrap Atom = 0x72004 | ||
372 | Xmp Atom = 0xf903 | ||
342 | ) | 373 | ) |
343 | 374 | ||
344 | const hash0 = 0xc17da63e | 375 | const hash0 = 0x81cdf10e |
345 | 376 | ||
346 | const maxAtomLen = 19 | 377 | const maxAtomLen = 25 |
347 | 378 | ||
348 | var table = [1 << 9]Atom{ | 379 | var table = [1 << 9]Atom{ |
349 | 0x1: 0x48a0b, // onmousemove | 380 | 0x1: 0x8e0a, // mediagroup |
350 | 0x2: 0x5e209, // onwaiting | 381 | 0x2: 0x2cc04, // lang |
351 | 0x3: 0x1fa13, // onautocompleteerror | 382 | 0x4: 0x2c09, // accesskey |
352 | 0x4: 0x5fa06, // prompt | 383 | 0x5: 0x5708, // frameset |
353 | 0x7: 0x5eb07, // optimum | 384 | 0x7: 0x63608, // onselect |
354 | 0x8: 0x1604, // mark | 385 | 0x8: 0x70b06, // system |
355 | 0xa: 0x5ad07, // itemref | 386 | 0xa: 0x64505, // width |
356 | 0xb: 0x4fe0a, // onpageshow | 387 | 0xc: 0x2710b, // formenctype |
357 | 0xc: 0x57a06, // select | 388 | 0xd: 0x10102, // ol |
358 | 0xd: 0x17b09, // draggable | 389 | 0xe: 0x38b0b, // oncuechange |
359 | 0xe: 0x3e03, // nav | 390 | 0x10: 0x13403, // bdo |
360 | 0xf: 0x17507, // command | 391 | 0x11: 0xcf05, // audio |
361 | 0x11: 0xb01, // u | 392 | 0x12: 0x18309, // draggable |
362 | 0x14: 0x2d507, // headers | 393 | 0x14: 0x2d905, // video |
363 | 0x15: 0x44a08, // datalist | 394 | 0x15: 0x29902, // mn |
364 | 0x17: 0x4e04, // samp | 395 | 0x16: 0x37b04, // menu |
365 | 0x1a: 0x3fb09, // onkeydown | 396 | 0x17: 0x2b706, // poster |
366 | 0x1b: 0x55f08, // onscroll | 397 | 0x19: 0xb306, // footer |
367 | 0x1c: 0x15003, // col | 398 | 0x1a: 0x29006, // method |
368 | 0x20: 0x3c908, // itemprop | 399 | 0x1b: 0x2a008, // datetime |
369 | 0x21: 0x2780a, // http-equiv | 400 | 0x1c: 0x17607, // onabort |
370 | 0x22: 0x61d03, // sup | 401 | 0x1d: 0x1200e, // updateviacache |
371 | 0x24: 0x1d008, // required | 402 | 0x1e: 0xb905, // async |
372 | 0x2b: 0x25e07, // preload | 403 | 0x1f: 0x49106, // onload |
373 | 0x2c: 0x6040d, // onbeforeprint | 404 | 0x21: 0xd308, // oncancel |
374 | 0x2d: 0x3600b, // ondragenter | 405 | 0x22: 0x62508, // onseeked |
375 | 0x2e: 0x50902, // dt | 406 | 0x23: 0x2ea05, // image |
376 | 0x2f: 0x5a708, // onsubmit | 407 | 0x24: 0x5d412, // onrejectionhandled |
377 | 0x30: 0x27002, // hr | 408 | 0x26: 0x15d04, // link |
378 | 0x31: 0x32f0d, // oncontextmenu | 409 | 0x27: 0x51106, // output |
379 | 0x33: 0x29c05, // image | 410 | 0x28: 0x32504, // head |
380 | 0x34: 0x50d07, // onpause | 411 | 0x29: 0x4f30c, // onmouseleave |
381 | 0x35: 0x25906, // hgroup | 412 | 0x2a: 0x57307, // onpaste |
382 | 0x36: 0x7704, // ping | 413 | 0x2b: 0x59809, // onplaying |
383 | 0x37: 0x57808, // onselect | 414 | 0x2c: 0x1b407, // colspan |
384 | 0x3a: 0x11303, // div | 415 | 0x2f: 0x1af05, // color |
385 | 0x3b: 0x1fa0e, // onautocomplete | 416 | 0x30: 0x5f104, // size |
386 | 0x40: 0x2eb02, // mi | 417 | 0x31: 0x2d00a, // http-equiv |
387 | 0x41: 0x31c08, // seamless | 418 | 0x33: 0x601, // i |
388 | 0x42: 0x2807, // charset | 419 | 0x34: 0x54d0a, // onpagehide |
389 | 0x43: 0x8502, // id | 420 | 0x35: 0x68814, // onunhandledrejection |
390 | 0x44: 0x5200a, // onpopstate | 421 | 0x37: 0x41e07, // onerror |
391 | 0x45: 0x3ef03, // del | 422 | 0x3a: 0x11508, // basefont |
392 | 0x46: 0x2cb07, // marquee | 423 | 0x3f: 0x1303, // nav |
393 | 0x47: 0x3309, // accesskey | 424 | 0x40: 0x18004, // kind |
394 | 0x49: 0x8d06, // footer | 425 | 0x41: 0x34b08, // readonly |
395 | 0x4a: 0x44e04, // list | 426 | 0x42: 0x2f006, // mglyph |
396 | 0x4b: 0x2b005, // ismap | 427 | 0x44: 0x11102, // li |
397 | 0x51: 0x33804, // menu | 428 | 0x46: 0x2bd06, // hidden |
398 | 0x52: 0x2f04, // body | 429 | 0x47: 0x70803, // svg |
399 | 0x55: 0x9a08, // frameset | 430 | 0x48: 0x57704, // step |
400 | 0x56: 0x54a07, // onreset | 431 | 0x49: 0x22709, // integrity |
401 | 0x57: 0x12705, // blink | 432 | 0x4a: 0x57a06, // public |
402 | 0x58: 0xa105, // title | 433 | 0x4c: 0x19703, // col |
403 | 0x59: 0x38807, // article | 434 | 0x4d: 0x1680a, // blockquote |
404 | 0x5b: 0x22e02, // th | 435 | 0x4e: 0x34302, // h5 |
405 | 0x5d: 0x13101, // q | 436 | 0x50: 0x5ad08, // progress |
406 | 0x5e: 0x3cf04, // open | 437 | 0x51: 0x5f105, // sizes |
407 | 0x5f: 0x2fa04, // area | 438 | 0x52: 0x33902, // h4 |
408 | 0x61: 0x44206, // onload | 439 | 0x56: 0x32405, // thead |
409 | 0x62: 0xda04, // font | 440 | 0x57: 0x7e07, // keytype |
410 | 0x63: 0xd604, // base | 441 | 0x58: 0x5ab0a, // onprogress |
411 | 0x64: 0x16207, // colspan | 442 | 0x59: 0x43f09, // inputmode |
412 | 0x65: 0x53707, // keytype | 443 | 0x5a: 0x3a509, // ondragend |
413 | 0x66: 0x11e02, // dl | 444 | 0x5d: 0x39605, // oncut |
414 | 0x68: 0x1b008, // fieldset | 445 | 0x5e: 0x42b06, // spacer |
415 | 0x6a: 0x2eb03, // min | 446 | 0x5f: 0x19708, // colgroup |
416 | 0x6b: 0x11503, // var | 447 | 0x62: 0x14e02, // is |
417 | 0x6f: 0x2d506, // header | 448 | 0x65: 0xb902, // as |
418 | 0x70: 0x13f02, // rt | 449 | 0x66: 0x53c09, // onoffline |
419 | 0x71: 0x15008, // colgroup | 450 | 0x67: 0x32b06, // sorted |
420 | 0x72: 0x23502, // mn | 451 | 0x69: 0x48110, // onlanguagechange |
421 | 0x74: 0x13a07, // onabort | 452 | 0x6c: 0x4310c, // onhashchange |
422 | 0x75: 0x3906, // keygen | 453 | 0x6d: 0xa604, // name |
423 | 0x76: 0x4c209, // onoffline | 454 | 0x6e: 0xb205, // tfoot |
424 | 0x77: 0x21f09, // challenge | 455 | 0x6f: 0x55504, // desc |
425 | 0x78: 0x2b203, // map | 456 | 0x70: 0x33103, // max |
426 | 0x7a: 0x2e902, // h4 | 457 | 0x72: 0x1da06, // coords |
427 | 0x7b: 0x3b607, // onerror | 458 | 0x73: 0x2f502, // h3 |
428 | 0x7c: 0x2e109, // maxlength | 459 | 0x74: 0x6e10e, // onbeforeunload |
429 | 0x7d: 0x2f505, // mtext | 460 | 0x75: 0x3a04, // rows |
430 | 0x7e: 0xbb07, // sandbox | 461 | 0x76: 0x63806, // select |
431 | 0x7f: 0x58b06, // onsort | 462 | 0x77: 0xa805, // meter |
432 | 0x80: 0x100a, // malignmark | 463 | 0x78: 0x37f06, // itemid |
433 | 0x81: 0x45d04, // meta | 464 | 0x79: 0x5300c, // onmousewheel |
434 | 0x82: 0x7b05, // async | 465 | 0x7a: 0x5b406, // srcdoc |
435 | 0x83: 0x2a702, // h3 | 466 | 0x7d: 0x17c05, // track |
436 | 0x84: 0x26702, // dd | 467 | 0x7f: 0x30708, // itemtype |
437 | 0x85: 0x27004, // href | 468 | 0x82: 0x6302, // mo |
438 | 0x86: 0x6e0a, // mediagroup | 469 | 0x83: 0x40f08, // onchange |
439 | 0x87: 0x19406, // coords | 470 | 0x84: 0x32507, // headers |
440 | 0x88: 0x41107, // srclang | 471 | 0x85: 0x5c80c, // onratechange |
441 | 0x89: 0x34d0a, // ondblclick | 472 | 0x86: 0x60419, // onsecuritypolicyviolation |
442 | 0x8a: 0x4005, // value | 473 | 0x88: 0x49908, // datalist |
443 | 0x8c: 0xe908, // oncancel | 474 | 0x89: 0x4dc0b, // onmousedown |
444 | 0x8e: 0x3230a, // spellcheck | 475 | 0x8a: 0x1df04, // slot |
445 | 0x8f: 0x9a05, // frame | 476 | 0x8b: 0x4a410, // onloadedmetadata |
446 | 0x91: 0x12403, // big | 477 | 0x8c: 0x1a06, // accept |
447 | 0x94: 0x1f606, // action | 478 | 0x8d: 0x25006, // object |
448 | 0x95: 0x6903, // dir | 479 | 0x91: 0x6af0e, // onvolumechange |
449 | 0x97: 0x2fb08, // readonly | 480 | 0x92: 0x2107, // charset |
450 | 0x99: 0x42d05, // table | 481 | 0x93: 0x25e13, // onautocompleteerror |
451 | 0x9a: 0x61607, // summary | 482 | 0x94: 0x6913, // allowpaymentrequest |
452 | 0x9b: 0x12103, // wbr | 483 | 0x95: 0x2804, // body |
453 | 0x9c: 0x30a, // radiogroup | 484 | 0x96: 0xc407, // default |
454 | 0x9d: 0x6c04, // name | 485 | 0x97: 0x63808, // selected |
455 | 0x9f: 0x62306, // system | 486 | 0x98: 0x20604, // face |
456 | 0xa1: 0x15d05, // color | 487 | 0x99: 0x1d505, // shape |
457 | 0xa2: 0x7f06, // canvas | 488 | 0x9b: 0x68008, // ontoggle |
458 | 0xa3: 0x25504, // html | 489 | 0x9e: 0x64702, // dt |
459 | 0xa5: 0x56f09, // onseeking | 490 | 0x9f: 0x6d904, // mark |
460 | 0xac: 0x4f905, // shape | 491 | 0xa1: 0xb01, // u |
461 | 0xad: 0x25f03, // rel | 492 | 0xa4: 0x6a708, // onunload |
462 | 0xae: 0x28510, // oncanplaythrough | 493 | 0xa5: 0xde04, // loop |
463 | 0xaf: 0x3760a, // ondragover | 494 | 0xa6: 0x14d08, // disabled |
464 | 0xb0: 0x62608, // template | 495 | 0xaa: 0x41707, // onended |
465 | 0xb1: 0x1d80d, // foreignObject | 496 | 0xab: 0x6d30a, // malignmark |
466 | 0xb3: 0x9204, // rows | 497 | 0xad: 0x67709, // onsuspend |
467 | 0xb6: 0x44e07, // listing | 498 | 0xae: 0x34505, // mtext |
468 | 0xb7: 0x49c06, // output | 499 | 0xaf: 0x64b06, // onsort |
469 | 0xb9: 0x3310b, // contextmenu | 500 | 0xb0: 0x55908, // itemprop |
470 | 0xbb: 0x11f03, // low | 501 | 0xb3: 0x66d09, // itemscope |
471 | 0xbc: 0x1c602, // rp | 502 | 0xb4: 0x15c05, // blink |
472 | 0xbd: 0x5bb09, // onsuspend | 503 | 0xb6: 0x3a506, // ondrag |
473 | 0xbe: 0x13606, // button | 504 | 0xb7: 0x6602, // ul |
474 | 0xbf: 0x4db04, // desc | 505 | 0xb8: 0x25604, // form |
475 | 0xc1: 0x4e207, // section | 506 | 0xb9: 0xf307, // sandbox |
476 | 0xc2: 0x52a0a, // onprogress | 507 | 0xba: 0x5705, // frame |
477 | 0xc3: 0x59e09, // onstorage | 508 | 0xbb: 0x1505, // value |
478 | 0xc4: 0x2d204, // math | 509 | 0xbc: 0x65e09, // onstorage |
479 | 0xc5: 0x4503, // alt | 510 | 0xc0: 0x17b02, // rt |
480 | 0xc7: 0x8a02, // ul | 511 | 0xc2: 0x202, // br |
481 | 0xc8: 0x5107, // pattern | 512 | 0xc3: 0x20e08, // fieldset |
482 | 0xc9: 0x4b60c, // onmousewheel | 513 | 0xc4: 0x2780d, // typemustmatch |
483 | 0xca: 0x35709, // ondragend | 514 | 0xc5: 0x6108, // nomodule |
484 | 0xcb: 0xaf04, // ruby | 515 | 0xc6: 0x4007, // noembed |
485 | 0xcc: 0xc01, // p | 516 | 0xc7: 0x69a0d, // onbeforeprint |
486 | 0xcd: 0x31707, // onclose | 517 | 0xc8: 0x17206, // button |
487 | 0xce: 0x24205, // meter | 518 | 0xc9: 0x2dd07, // onclick |
488 | 0xcf: 0x11807, // bgsound | 519 | 0xca: 0x6fe07, // summary |
489 | 0xd2: 0x25106, // height | 520 | 0xcd: 0xac04, // ruby |
490 | 0xd4: 0x101, // b | 521 | 0xce: 0x5b905, // class |
491 | 0xd5: 0x2c308, // itemtype | 522 | 0xcf: 0x3e80b, // ondragstart |
492 | 0xd8: 0x1bb07, // caption | 523 | 0xd0: 0x21907, // caption |
493 | 0xd9: 0x10c08, // disabled | 524 | 0xd4: 0x850e, // allowusermedia |
494 | 0xdb: 0x33808, // menuitem | 525 | 0xd5: 0x4c30b, // onloadstart |
495 | 0xdc: 0x62003, // svg | 526 | 0xd9: 0x15403, // div |
496 | 0xdd: 0x18f05, // small | 527 | 0xda: 0x49d04, // list |
497 | 0xde: 0x44a04, // data | 528 | 0xdb: 0x32204, // math |
498 | 0xe0: 0x4cb08, // ononline | 529 | 0xdc: 0x43f05, // input |
499 | 0xe1: 0x2a206, // mglyph | 530 | 0xdf: 0x3de0a, // ondragover |
500 | 0xe3: 0x6505, // embed | 531 | 0xe0: 0x2c602, // h2 |
501 | 0xe4: 0x10502, // tr | 532 | 0xe2: 0x19e09, // plaintext |
502 | 0xe5: 0x46b0b, // onloadstart | 533 | 0xe4: 0x4e70c, // onmouseenter |
503 | 0xe7: 0x3c306, // srcdoc | 534 | 0xe7: 0x46d07, // checked |
504 | 0xeb: 0x5c408, // ontoggle | 535 | 0xe8: 0x46403, // pre |
505 | 0xed: 0xe703, // bdo | 536 | 0xea: 0x35308, // multiple |
506 | 0xee: 0x4702, // td | 537 | 0xeb: 0x16103, // bdi |
507 | 0xef: 0x8305, // aside | 538 | 0xec: 0x33109, // maxlength |
508 | 0xf0: 0x29402, // h2 | 539 | 0xed: 0x7701, // q |
509 | 0xf1: 0x52c08, // progress | 540 | 0xee: 0x61b0a, // onauxclick |
510 | 0xf2: 0x12c0a, // blockquote | 541 | 0xf0: 0x57003, // wbr |
511 | 0xf4: 0xf005, // label | 542 | 0xf2: 0x11504, // base |
512 | 0xf5: 0x601, // i | 543 | 0xf3: 0x6dd06, // option |
513 | 0xf7: 0x9207, // rowspan | 544 | 0xf5: 0x40710, // ondurationchange |
514 | 0xfb: 0x51709, // onplaying | 545 | 0xf7: 0x5508, // noframes |
515 | 0xfd: 0x2a103, // img | 546 | 0xf9: 0x3f908, // dropzone |
516 | 0xfe: 0xf608, // optgroup | 547 | 0xfb: 0x67105, // scope |
517 | 0xff: 0x42307, // content | 548 | 0xfc: 0x9c08, // reversed |
518 | 0x101: 0x53e0c, // onratechange | 549 | 0xfd: 0x3ae0b, // ondragenter |
519 | 0x103: 0x3da0c, // onhashchange | 550 | 0xfe: 0x3ee05, // start |
520 | 0x104: 0x4807, // details | 551 | 0xff: 0xf903, // xmp |
521 | 0x106: 0x40008, // download | 552 | 0x100: 0x5f507, // srclang |
522 | 0x109: 0x14009, // translate | 553 | 0x101: 0x2ef03, // img |
523 | 0x10b: 0x4230f, // contenteditable | 554 | 0x104: 0x101, // b |
524 | 0x10d: 0x36b0b, // ondragleave | 555 | 0x105: 0x23c03, // for |
525 | 0x10e: 0x2106, // accept | 556 | 0x106: 0xc105, // aside |
526 | 0x10f: 0x57a08, // selected | 557 | 0x107: 0x43d07, // oninput |
527 | 0x112: 0x1f20a, // formaction | 558 | 0x108: 0x34a04, // area |
528 | 0x113: 0x5b506, // center | 559 | 0x109: 0x28c0a, // formmethod |
529 | 0x115: 0x45510, // onloadedmetadata | 560 | 0x10a: 0x72004, // wrap |
530 | 0x116: 0x12804, // link | 561 | 0x10c: 0x22402, // rp |
531 | 0x117: 0xdd04, // time | 562 | 0x10d: 0x45f0a, // onkeypress |
532 | 0x118: 0x19f0b, // crossorigin | 563 | 0x10e: 0x5102, // tt |
533 | 0x119: 0x3bd07, // onfocus | 564 | 0x110: 0x33b02, // mi |
534 | 0x11a: 0x58704, // wrap | 565 | 0x111: 0x35b05, // muted |
535 | 0x11b: 0x42204, // icon | 566 | 0x112: 0xb003, // alt |
536 | 0x11d: 0x28105, // video | 567 | 0x113: 0x19004, // code |
537 | 0x11e: 0x4de05, // class | 568 | 0x114: 0x4202, // em |
538 | 0x121: 0x5d40e, // onvolumechange | 569 | 0x115: 0x3b90a, // ondragexit |
539 | 0x122: 0xaa06, // onblur | 570 | 0x117: 0x3d04, // span |
540 | 0x123: 0x2b909, // itemscope | 571 | 0x119: 0x30f08, // manifest |
541 | 0x124: 0x61105, // style | 572 | 0x11a: 0x37b08, // menuitem |
542 | 0x127: 0x41e06, // public | 573 | 0x11b: 0x57f07, // content |
543 | 0x129: 0x2320e, // formnovalidate | 574 | 0x11d: 0x6bd09, // onwaiting |
544 | 0x12a: 0x58206, // onshow | 575 | 0x11f: 0x4ba09, // onloadend |
545 | 0x12c: 0x51706, // onplay | 576 | 0x121: 0x3720d, // oncontextmenu |
546 | 0x12d: 0x3c804, // cite | 577 | 0x123: 0x5c206, // onblur |
547 | 0x12e: 0x2bc02, // ms | 578 | 0x124: 0x3f007, // article |
548 | 0x12f: 0xdb0c, // ontimeupdate | 579 | 0x125: 0xa303, // dir |
549 | 0x130: 0x10904, // kind | 580 | 0x126: 0xe704, // ping |
550 | 0x131: 0x2470a, // formtarget | 581 | 0x127: 0x23408, // required |
551 | 0x135: 0x3af07, // onended | 582 | 0x128: 0x44909, // oninvalid |
552 | 0x136: 0x26506, // hidden | 583 | 0x129: 0x6d405, // align |
553 | 0x137: 0x2c01, // s | 584 | 0x12b: 0x57e04, // icon |
554 | 0x139: 0x2280a, // formmethod | 585 | 0x12c: 0x64902, // h6 |
555 | 0x13a: 0x3e805, // input | 586 | 0x12d: 0x1b404, // cols |
556 | 0x13c: 0x50b02, // h6 | 587 | 0x12e: 0x2160a, // figcaption |
557 | 0x13d: 0xc902, // ol | 588 | 0x12f: 0x45209, // onkeydown |
558 | 0x13e: 0x3420b, // oncuechange | 589 | 0x130: 0x66708, // onsubmit |
559 | 0x13f: 0x1e50d, // foreignobject | 590 | 0x131: 0x13609, // oncanplay |
560 | 0x143: 0x4e70e, // onbeforeunload | 591 | 0x132: 0x70503, // sup |
561 | 0x144: 0x2bd05, // scope | 592 | 0x133: 0xc01, // p |
562 | 0x145: 0x39609, // onemptied | 593 | 0x135: 0x3fe09, // onemptied |
563 | 0x146: 0x14b05, // defer | 594 | 0x136: 0x38506, // oncopy |
564 | 0x147: 0xc103, // xmp | 595 | 0x137: 0x55804, // cite |
565 | 0x148: 0x39f10, // ondurationchange | 596 | 0x138: 0x39b0a, // ondblclick |
566 | 0x149: 0x1903, // kbd | 597 | 0x13a: 0x4ff0b, // onmousemove |
567 | 0x14c: 0x47609, // onmessage | 598 | 0x13c: 0x66903, // sub |
568 | 0x14d: 0x60006, // option | 599 | 0x13d: 0x47b03, // rel |
569 | 0x14e: 0x2eb09, // minlength | 600 | 0x13e: 0xe008, // optgroup |
570 | 0x14f: 0x32807, // checked | 601 | 0x142: 0x3a07, // rowspan |
571 | 0x150: 0xce08, // autoplay | 602 | 0x143: 0x36c06, // source |
572 | 0x152: 0x202, // br | 603 | 0x144: 0x1fe08, // noscript |
573 | 0x153: 0x2360a, // novalidate | 604 | 0x145: 0x55f04, // open |
574 | 0x156: 0x6307, // noembed | 605 | 0x146: 0x1ec03, // ins |
575 | 0x159: 0x31007, // onclick | 606 | 0x147: 0x23c0d, // foreignObject |
576 | 0x15a: 0x47f0b, // onmousedown | 607 | 0x148: 0x5a10a, // onpopstate |
577 | 0x15b: 0x3a708, // onchange | 608 | 0x14a: 0x27507, // enctype |
578 | 0x15e: 0x3f209, // oninvalid | 609 | 0x14b: 0x25e0e, // onautocomplete |
579 | 0x15f: 0x2bd06, // scoped | 610 | 0x14c: 0x34608, // textarea |
580 | 0x160: 0x18808, // controls | 611 | 0x14e: 0x2600c, // autocomplete |
581 | 0x161: 0x30b05, // muted | 612 | 0x14f: 0x14002, // hr |
582 | 0x162: 0x58d08, // sortable | 613 | 0x150: 0x1ce08, // controls |
583 | 0x163: 0x51106, // usemap | 614 | 0x151: 0xc302, // id |
584 | 0x164: 0x1b80a, // figcaption | 615 | 0x153: 0x21e0c, // onafterprint |
585 | 0x165: 0x35706, // ondrag | 616 | 0x155: 0x2490d, // foreignobject |
586 | 0x166: 0x26b04, // high | 617 | 0x156: 0x31b07, // marquee |
587 | 0x168: 0x3c303, // src | 618 | 0x157: 0x58e07, // onpause |
588 | 0x169: 0x15706, // poster | 619 | 0x158: 0x5e202, // dl |
589 | 0x16b: 0x1670e, // annotation-xml | 620 | 0x159: 0x12c06, // height |
590 | 0x16c: 0x5f704, // step | 621 | 0x15a: 0x33b03, // min |
591 | 0x16d: 0x4, // abbr | 622 | 0x15b: 0xa307, // dirname |
592 | 0x16e: 0x1b06, // dialog | 623 | 0x15c: 0x1a609, // translate |
593 | 0x170: 0x1202, // li | 624 | 0x15d: 0x13004, // html |
594 | 0x172: 0x3ed02, // mo | 625 | 0x15e: 0x33b09, // minlength |
595 | 0x175: 0x1d803, // for | 626 | 0x15f: 0x47a07, // preload |
596 | 0x176: 0x1a803, // ins | 627 | 0x160: 0x70e08, // template |
597 | 0x178: 0x55504, // size | 628 | 0x161: 0x3d30b, // ondragleave |
598 | 0x179: 0x43210, // onlanguagechange | 629 | 0x164: 0x5b403, // src |
599 | 0x17a: 0x8607, // default | 630 | 0x165: 0x31506, // strong |
600 | 0x17b: 0x1a03, // bdi | 631 | 0x167: 0x4c04, // samp |
601 | 0x17c: 0x4d30a, // onpagehide | 632 | 0x168: 0x6ed07, // address |
602 | 0x17d: 0x6907, // dirname | 633 | 0x169: 0x54508, // ononline |
603 | 0x17e: 0x21404, // type | 634 | 0x16b: 0xfb0b, // placeholder |
604 | 0x17f: 0x1f204, // form | 635 | 0x16c: 0x2ac06, // target |
605 | 0x181: 0x28509, // oncanplay | 636 | 0x16d: 0x1ee05, // small |
606 | 0x182: 0x6103, // dfn | 637 | 0x16e: 0x6c607, // onwheel |
607 | 0x183: 0x46308, // tabindex | 638 | 0x16f: 0x1b90a, // annotation |
608 | 0x186: 0x6502, // em | 639 | 0x170: 0x4680a, // spellcheck |
609 | 0x187: 0x27404, // lang | 640 | 0x171: 0x4607, // details |
610 | 0x189: 0x39108, // dropzone | 641 | 0x172: 0xbd06, // canvas |
611 | 0x18a: 0x4080a, // onkeypress | 642 | 0x173: 0xeb09, // autofocus |
612 | 0x18b: 0x23c08, // datetime | 643 | 0x174: 0xc05, // param |
613 | 0x18c: 0x16204, // cols | 644 | 0x176: 0x45708, // download |
614 | 0x18d: 0x1, // a | 645 | 0x177: 0x44603, // del |
615 | 0x18e: 0x4420c, // onloadeddata | 646 | 0x178: 0x36007, // onclose |
616 | 0x190: 0xa605, // audio | 647 | 0x179: 0x16003, // kbd |
617 | 0x192: 0x2e05, // tbody | 648 | 0x17a: 0x30106, // applet |
618 | 0x193: 0x22c06, // method | 649 | 0x17b: 0x2c804, // href |
619 | 0x195: 0xf404, // loop | 650 | 0x17c: 0x5ed08, // onresize |
620 | 0x196: 0x29606, // iframe | 651 | 0x17e: 0x4910c, // onloadeddata |
621 | 0x198: 0x2d504, // head | 652 | 0x180: 0x7402, // tr |
622 | 0x19e: 0x5f108, // manifest | 653 | 0x181: 0x2a80a, // formtarget |
623 | 0x19f: 0xb309, // autofocus | 654 | 0x182: 0xca05, // title |
624 | 0x1a0: 0x14904, // code | 655 | 0x183: 0x6f905, // style |
625 | 0x1a1: 0x55906, // strong | 656 | 0x184: 0x7a06, // strike |
626 | 0x1a2: 0x30308, // multiple | 657 | 0x185: 0x59206, // usemap |
627 | 0x1a3: 0xc05, // param | 658 | 0x186: 0x2e406, // iframe |
628 | 0x1a6: 0x21107, // enctype | 659 | 0x187: 0x1004, // main |
629 | 0x1a7: 0x5b304, // face | 660 | 0x189: 0x9707, // picture |
630 | 0x1a8: 0xfd09, // plaintext | 661 | 0x18c: 0x2fe05, // ismap |
631 | 0x1a9: 0x26e02, // h1 | 662 | 0x18e: 0x49904, // data |
632 | 0x1aa: 0x59509, // onstalled | 663 | 0x18f: 0xda05, // label |
633 | 0x1ad: 0x3d406, // script | 664 | 0x191: 0x3c50e, // referrerpolicy |
634 | 0x1ae: 0x2db06, // spacer | 665 | 0x192: 0x13f02, // th |
635 | 0x1af: 0x55108, // onresize | 666 | 0x194: 0x52a06, // prompt |
636 | 0x1b0: 0x4a20b, // onmouseover | 667 | 0x195: 0x5bd07, // section |
637 | 0x1b1: 0x5cc08, // onunload | 668 | 0x197: 0x6cd07, // optimum |
638 | 0x1b2: 0x56708, // onseeked | 669 | 0x198: 0x2c304, // high |
639 | 0x1b4: 0x2140d, // typemustmatch | 670 | 0x199: 0x14502, // h1 |
640 | 0x1b5: 0x1cc06, // figure | 671 | 0x19a: 0x65509, // onstalled |
641 | 0x1b6: 0x4950a, // onmouseout | 672 | 0x19b: 0x15603, // var |
642 | 0x1b7: 0x25e03, // pre | 673 | 0x19c: 0x11c04, // time |
643 | 0x1b8: 0x50705, // width | 674 | 0x19e: 0x67002, // ms |
644 | 0x1b9: 0x19906, // sorted | 675 | 0x19f: 0x32506, // header |
645 | 0x1bb: 0x5704, // nobr | 676 | 0x1a0: 0x4ce09, // onmessage |
646 | 0x1be: 0x5302, // tt | 677 | 0x1a1: 0x56205, // nonce |
647 | 0x1bf: 0x1105, // align | 678 | 0x1a2: 0x2560a, // formaction |
648 | 0x1c0: 0x3e607, // oninput | 679 | 0x1a3: 0x20806, // center |
649 | 0x1c3: 0x41807, // onkeyup | 680 | 0x1a4: 0x3704, // nobr |
650 | 0x1c6: 0x1c00c, // onafterprint | 681 | 0x1a5: 0x58905, // table |
651 | 0x1c7: 0x210e, // accept-charset | 682 | 0x1a6: 0x49d07, // listing |
652 | 0x1c8: 0x33c06, // itemid | 683 | 0x1a7: 0x18a06, // legend |
653 | 0x1c9: 0x3e809, // inputmode | 684 | 0x1a9: 0x28309, // challenge |
654 | 0x1cb: 0x53306, // strike | 685 | 0x1aa: 0x23006, // figure |
655 | 0x1cc: 0x5a903, // sub | 686 | 0x1ab: 0x8e05, // media |
656 | 0x1cd: 0x10505, // track | 687 | 0x1ae: 0x8104, // type |
657 | 0x1ce: 0x38605, // start | 688 | 0x1af: 0x11904, // font |
658 | 0x1d0: 0xd608, // basefont | 689 | 0x1b0: 0x4ce0e, // onmessageerror |
659 | 0x1d6: 0x1aa06, // source | 690 | 0x1b1: 0x36508, // seamless |
660 | 0x1d7: 0x18206, // legend | 691 | 0x1b2: 0x5f03, // dfn |
661 | 0x1d8: 0x2d405, // thead | 692 | 0x1b3: 0x19205, // defer |
662 | 0x1da: 0x8c05, // tfoot | 693 | 0x1b4: 0x6b03, // low |
663 | 0x1dd: 0x1ec06, // object | 694 | 0x1b5: 0x62d09, // onseeking |
664 | 0x1de: 0x6e05, // media | 695 | 0x1b6: 0x5170b, // onmouseover |
665 | 0x1df: 0x1670a, // annotation | 696 | 0x1b7: 0x29a0a, // novalidate |
666 | 0x1e0: 0x20d0b, // formenctype | 697 | 0x1b8: 0x7160a, // workertype |
667 | 0x1e2: 0x3d208, // noscript | 698 | 0x1ba: 0x3c107, // itemref |
668 | 0x1e4: 0x55505, // sizes | 699 | 0x1bd: 0x1, // a |
669 | 0x1e5: 0x1fc0c, // autocomplete | 700 | 0x1be: 0x30003, // map |
670 | 0x1e6: 0x9504, // span | 701 | 0x1bf: 0x11a0c, // ontimeupdate |
671 | 0x1e7: 0x9808, // noframes | 702 | 0x1c0: 0x14707, // bgsound |
672 | 0x1e8: 0x24b06, // target | 703 | 0x1c1: 0x3206, // keygen |
673 | 0x1e9: 0x38f06, // ondrop | 704 | 0x1c2: 0x2705, // tbody |
674 | 0x1ea: 0x2b306, // applet | 705 | 0x1c5: 0x64006, // onshow |
675 | 0x1ec: 0x5a08, // reversed | 706 | 0x1c7: 0x2501, // s |
676 | 0x1f0: 0x2a907, // isindex | 707 | 0x1c8: 0x4f07, // pattern |
677 | 0x1f3: 0x27008, // hreflang | 708 | 0x1cc: 0x13610, // oncanplaythrough |
678 | 0x1f5: 0x2f302, // h5 | 709 | 0x1ce: 0x2bf02, // dd |
679 | 0x1f6: 0x4f307, // address | 710 | 0x1cf: 0x6f306, // srcset |
680 | 0x1fa: 0x2e103, // max | 711 | 0x1d0: 0x15903, // big |
681 | 0x1fb: 0xc30b, // placeholder | 712 | 0x1d2: 0x64d08, // sortable |
682 | 0x1fc: 0x2f608, // textarea | 713 | 0x1d3: 0x47407, // onkeyup |
683 | 0x1fe: 0x4ad09, // onmouseup | 714 | 0x1d5: 0x59806, // onplay |
684 | 0x1ff: 0x3800b, // ondragstart | 715 | 0x1d7: 0x4ac04, // meta |
716 | 0x1d8: 0x3f706, // ondrop | ||
717 | 0x1da: 0x5fc08, // onscroll | ||
718 | 0x1db: 0x1e30b, // crossorigin | ||
719 | 0x1dc: 0x5670a, // onpageshow | ||
720 | 0x1dd: 0x4, // abbr | ||
721 | 0x1de: 0x5e02, // td | ||
722 | 0x1df: 0x57f0f, // contenteditable | ||
723 | 0x1e0: 0x25a06, // action | ||
724 | 0x1e1: 0x10a0b, // playsinline | ||
725 | 0x1e2: 0x42507, // onfocus | ||
726 | 0x1e3: 0x2c808, // hreflang | ||
727 | 0x1e5: 0x50a0a, // onmouseout | ||
728 | 0x1e6: 0x5e607, // onreset | ||
729 | 0x1e7: 0x10608, // autoplay | ||
730 | 0x1ea: 0x67106, // scoped | ||
731 | 0x1ec: 0x30a, // radiogroup | ||
732 | 0x1ee: 0x3740b, // contextmenu | ||
733 | 0x1ef: 0x52209, // onmouseup | ||
734 | 0x1f1: 0x2b206, // hgroup | ||
735 | 0x1f2: 0x1f00f, // allowfullscreen | ||
736 | 0x1f3: 0x4b208, // tabindex | ||
737 | 0x1f6: 0x2f707, // isindex | ||
738 | 0x1f7: 0x1a0e, // accept-charset | ||
739 | 0x1f8: 0x2960e, // formnovalidate | ||
740 | 0x1fb: 0x1b90e, // annotation-xml | ||
741 | 0x1fc: 0x4205, // embed | ||
742 | 0x1fd: 0x20006, // script | ||
743 | 0x1fe: 0x16206, // dialog | ||
744 | 0x1ff: 0x1c707, // command | ||
685 | } | 745 | } |
686 | 746 | ||
687 | const atomText = "abbradiogrouparamalignmarkbdialogaccept-charsetbodyaccesskey" + | 747 | const atomText = "abbradiogrouparamainavalueaccept-charsetbodyaccesskeygenobro" + |
688 | "genavaluealtdetailsampatternobreversedfnoembedirnamediagroup" + | 748 | "wspanoembedetailsampatternoframesetdfnomoduleallowpaymentreq" + |
689 | "ingasyncanvasidefaultfooterowspanoframesetitleaudionblurubya" + | 749 | "uestrikeytypeallowusermediagroupictureversedirnameterubyaltf" + |
690 | "utofocusandboxmplaceholderautoplaybasefontimeupdatebdoncance" + | 750 | "ooterasyncanvasidefaultitleaudioncancelabelooptgroupingautof" + |
691 | "labelooptgrouplaintextrackindisabledivarbgsoundlowbrbigblink" + | 751 | "ocusandboxmplaceholderautoplaysinlinebasefontimeupdateviacac" + |
692 | "blockquotebuttonabortranslatecodefercolgroupostercolorcolspa" + | 752 | "heightmlbdoncanplaythrough1bgsoundisabledivarbigblinkbdialog" + |
693 | "nnotation-xmlcommandraggablegendcontrolsmallcoordsortedcross" + | 753 | "blockquotebuttonabortrackindraggablegendcodefercolgrouplaint" + |
694 | "originsourcefieldsetfigcaptionafterprintfigurequiredforeignO" + | 754 | "extranslatecolorcolspannotation-xmlcommandcontrolshapecoords" + |
695 | "bjectforeignobjectformactionautocompleteerrorformenctypemust" + | 755 | "lotcrossoriginsmallowfullscreenoscriptfacenterfieldsetfigcap" + |
696 | "matchallengeformmethodformnovalidatetimeterformtargetheightm" + | 756 | "tionafterprintegrityfigurequiredforeignObjectforeignobjectfo" + |
697 | "lhgroupreloadhiddenhigh1hreflanghttp-equivideoncanplaythroug" + | 757 | "rmactionautocompleteerrorformenctypemustmatchallengeformmeth" + |
698 | "h2iframeimageimglyph3isindexismappletitemscopeditemtypemarqu" + | 758 | "odformnovalidatetimeformtargethgrouposterhiddenhigh2hreflang" + |
699 | "eematheaderspacermaxlength4minlength5mtextareadonlymultiplem" + | 759 | "http-equivideonclickiframeimageimglyph3isindexismappletitemt" + |
700 | "utedonclickoncloseamlesspellcheckedoncontextmenuitemidoncuec" + | 760 | "ypemanifestrongmarqueematheadersortedmaxlength4minlength5mte" + |
701 | "hangeondblclickondragendondragenterondragleaveondragoverondr" + | 761 | "xtareadonlymultiplemutedoncloseamlessourceoncontextmenuitemi" + |
702 | "agstarticleondropzonemptiedondurationchangeonendedonerroronf" + | 762 | "doncopyoncuechangeoncutondblclickondragendondragenterondrage" + |
703 | "ocusrcdocitempropenoscriptonhashchangeoninputmodeloninvalido" + | 763 | "xitemreferrerpolicyondragleaveondragoverondragstarticleondro" + |
704 | "nkeydownloadonkeypressrclangonkeyupublicontenteditableonlang" + | 764 | "pzonemptiedondurationchangeonendedonerroronfocuspaceronhashc" + |
705 | "uagechangeonloadeddatalistingonloadedmetadatabindexonloadsta" + | 765 | "hangeoninputmodeloninvalidonkeydownloadonkeypresspellchecked" + |
706 | "rtonmessageonmousedownonmousemoveonmouseoutputonmouseoveronm" + | 766 | "onkeyupreloadonlanguagechangeonloadeddatalistingonloadedmeta" + |
707 | "ouseuponmousewheelonofflineononlineonpagehidesclassectionbef" + | 767 | "databindexonloadendonloadstartonmessageerroronmousedownonmou" + |
708 | "oreunloaddresshapeonpageshowidth6onpausemaponplayingonpopsta" + | 768 | "seenteronmouseleaveonmousemoveonmouseoutputonmouseoveronmous" + |
709 | "teonprogresstrikeytypeonratechangeonresetonresizestrongonscr" + | 769 | "eupromptonmousewheelonofflineononlineonpagehidescitempropeno" + |
710 | "ollonseekedonseekingonselectedonshowraponsortableonstalledon" + | 770 | "nceonpageshowbronpastepublicontenteditableonpausemaponplayin" + |
711 | "storageonsubmitemrefacenteronsuspendontoggleonunloadonvolume" + | 771 | "gonpopstateonprogressrcdoclassectionbluronratechangeonreject" + |
712 | "changeonwaitingoptimumanifestepromptoptionbeforeprintstylesu" + | 772 | "ionhandledonresetonresizesrclangonscrollonsecuritypolicyviol" + |
713 | "mmarysupsvgsystemplate" | 773 | "ationauxclickonseekedonseekingonselectedonshowidth6onsortabl" + |
774 | "eonstalledonstorageonsubmitemscopedonsuspendontoggleonunhand" + | ||
775 | "ledrejectionbeforeprintonunloadonvolumechangeonwaitingonwhee" + | ||
776 | "loptimumalignmarkoptionbeforeunloaddressrcsetstylesummarysup" + | ||
777 | "svgsystemplateworkertypewrap" | ||
diff --git a/vendor/golang.org/x/net/html/const.go b/vendor/golang.org/x/net/html/const.go index 52f651f..b37e621 100644 --- a/vendor/golang.org/x/net/html/const.go +++ b/vendor/golang.org/x/net/html/const.go | |||
@@ -52,10 +52,12 @@ var isSpecialElementMap = map[string]bool{ | |||
52 | "iframe": true, | 52 | "iframe": true, |
53 | "img": true, | 53 | "img": true, |
54 | "input": true, | 54 | "input": true, |
55 | "isindex": true, | 55 | "isindex": true, // The 'isindex' element has been removed, but keep it for backwards compatibility. |
56 | "keygen": true, | ||
56 | "li": true, | 57 | "li": true, |
57 | "link": true, | 58 | "link": true, |
58 | "listing": true, | 59 | "listing": true, |
60 | "main": true, | ||
59 | "marquee": true, | 61 | "marquee": true, |
60 | "menu": true, | 62 | "menu": true, |
61 | "meta": true, | 63 | "meta": true, |
diff --git a/vendor/golang.org/x/net/http2/.gitignore b/vendor/golang.org/x/net/http2/.gitignore new file mode 100644 index 0000000..190f122 --- /dev/null +++ b/vendor/golang.org/x/net/http2/.gitignore | |||
@@ -0,0 +1,2 @@ | |||
1 | *~ | ||
2 | h2i/h2i | ||
diff --git a/vendor/golang.org/x/net/http2/Dockerfile b/vendor/golang.org/x/net/http2/Dockerfile new file mode 100644 index 0000000..53fc525 --- /dev/null +++ b/vendor/golang.org/x/net/http2/Dockerfile | |||
@@ -0,0 +1,51 @@ | |||
1 | # | ||
2 | # This Dockerfile builds a recent curl with HTTP/2 client support, using | ||
3 | # a recent nghttp2 build. | ||
4 | # | ||
5 | # See the Makefile for how to tag it. If Docker and that image is found, the | ||
6 | # Go tests use this curl binary for integration tests. | ||
7 | # | ||
8 | |||
9 | FROM ubuntu:trusty | ||
10 | |||
11 | RUN apt-get update && \ | ||
12 | apt-get upgrade -y && \ | ||
13 | apt-get install -y git-core build-essential wget | ||
14 | |||
15 | RUN apt-get install -y --no-install-recommends \ | ||
16 | autotools-dev libtool pkg-config zlib1g-dev \ | ||
17 | libcunit1-dev libssl-dev libxml2-dev libevent-dev \ | ||
18 | automake autoconf | ||
19 | |||
20 | # The list of packages nghttp2 recommends for h2load: | ||
21 | RUN apt-get install -y --no-install-recommends make binutils \ | ||
22 | autoconf automake autotools-dev \ | ||
23 | libtool pkg-config zlib1g-dev libcunit1-dev libssl-dev libxml2-dev \ | ||
24 | libev-dev libevent-dev libjansson-dev libjemalloc-dev \ | ||
25 | cython python3.4-dev python-setuptools | ||
26 | |||
27 | # Note: setting NGHTTP2_VER before the git clone, so an old git clone isn't cached: | ||
28 | ENV NGHTTP2_VER 895da9a | ||
29 | RUN cd /root && git clone https://github.com/tatsuhiro-t/nghttp2.git | ||
30 | |||
31 | WORKDIR /root/nghttp2 | ||
32 | RUN git reset --hard $NGHTTP2_VER | ||
33 | RUN autoreconf -i | ||
34 | RUN automake | ||
35 | RUN autoconf | ||
36 | RUN ./configure | ||
37 | RUN make | ||
38 | RUN make install | ||
39 | |||
40 | WORKDIR /root | ||
41 | RUN wget http://curl.haxx.se/download/curl-7.45.0.tar.gz | ||
42 | RUN tar -zxvf curl-7.45.0.tar.gz | ||
43 | WORKDIR /root/curl-7.45.0 | ||
44 | RUN ./configure --with-ssl --with-nghttp2=/usr/local | ||
45 | RUN make | ||
46 | RUN make install | ||
47 | RUN ldconfig | ||
48 | |||
49 | CMD ["-h"] | ||
50 | ENTRYPOINT ["/usr/local/bin/curl"] | ||
51 | |||
diff --git a/vendor/golang.org/x/net/http2/Makefile b/vendor/golang.org/x/net/http2/Makefile new file mode 100644 index 0000000..55fd826 --- /dev/null +++ b/vendor/golang.org/x/net/http2/Makefile | |||
@@ -0,0 +1,3 @@ | |||
1 | curlimage: | ||
2 | docker build -t gohttp2/curl . | ||
3 | |||
diff --git a/vendor/golang.org/x/net/http2/README b/vendor/golang.org/x/net/http2/README new file mode 100644 index 0000000..360d5aa --- /dev/null +++ b/vendor/golang.org/x/net/http2/README | |||
@@ -0,0 +1,20 @@ | |||
1 | This is a work-in-progress HTTP/2 implementation for Go. | ||
2 | |||
3 | It will eventually live in the Go standard library and won't require | ||
4 | any changes to your code to use. It will just be automatic. | ||
5 | |||
6 | Status: | ||
7 | |||
8 | * The server support is pretty good. A few things are missing | ||
9 | but are being worked on. | ||
10 | * The client work has just started but shares a lot of code | ||
11 | is coming along much quicker. | ||
12 | |||
13 | Docs are at https://godoc.org/golang.org/x/net/http2 | ||
14 | |||
15 | Demo test server at https://http2.golang.org/ | ||
16 | |||
17 | Help & bug reports welcome! | ||
18 | |||
19 | Contributing: https://golang.org/doc/contribute.html | ||
20 | Bugs: https://golang.org/issue/new?title=x/net/http2:+ | ||
diff --git a/vendor/golang.org/x/net/http2/ciphers.go b/vendor/golang.org/x/net/http2/ciphers.go new file mode 100644 index 0000000..698860b --- /dev/null +++ b/vendor/golang.org/x/net/http2/ciphers.go | |||
@@ -0,0 +1,641 @@ | |||
1 | // Copyright 2017 The Go Authors. All rights reserved. | ||
2 | // Use of this source code is governed by a BSD-style | ||
3 | // license that can be found in the LICENSE file. | ||
4 | |||
5 | package http2 | ||
6 | |||
7 | // A list of the possible cipher suite ids. Taken from | ||
8 | // http://www.iana.org/assignments/tls-parameters/tls-parameters.txt | ||
9 | |||
10 | const ( | ||
11 | cipher_TLS_NULL_WITH_NULL_NULL uint16 = 0x0000 | ||
12 | cipher_TLS_RSA_WITH_NULL_MD5 uint16 = 0x0001 | ||
13 | cipher_TLS_RSA_WITH_NULL_SHA uint16 = 0x0002 | ||
14 | cipher_TLS_RSA_EXPORT_WITH_RC4_40_MD5 uint16 = 0x0003 | ||
15 | cipher_TLS_RSA_WITH_RC4_128_MD5 uint16 = 0x0004 | ||
16 | cipher_TLS_RSA_WITH_RC4_128_SHA uint16 = 0x0005 | ||
17 | cipher_TLS_RSA_EXPORT_WITH_RC2_CBC_40_MD5 uint16 = 0x0006 | ||
18 | cipher_TLS_RSA_WITH_IDEA_CBC_SHA uint16 = 0x0007 | ||
19 | cipher_TLS_RSA_EXPORT_WITH_DES40_CBC_SHA uint16 = 0x0008 | ||
20 | cipher_TLS_RSA_WITH_DES_CBC_SHA uint16 = 0x0009 | ||
21 | cipher_TLS_RSA_WITH_3DES_EDE_CBC_SHA uint16 = 0x000A | ||
22 | cipher_TLS_DH_DSS_EXPORT_WITH_DES40_CBC_SHA uint16 = 0x000B | ||
23 | cipher_TLS_DH_DSS_WITH_DES_CBC_SHA uint16 = 0x000C | ||
24 | cipher_TLS_DH_DSS_WITH_3DES_EDE_CBC_SHA uint16 = 0x000D | ||
25 | cipher_TLS_DH_RSA_EXPORT_WITH_DES40_CBC_SHA uint16 = 0x000E | ||
26 | cipher_TLS_DH_RSA_WITH_DES_CBC_SHA uint16 = 0x000F | ||
27 | cipher_TLS_DH_RSA_WITH_3DES_EDE_CBC_SHA uint16 = 0x0010 | ||
28 | cipher_TLS_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA uint16 = 0x0011 | ||
29 | cipher_TLS_DHE_DSS_WITH_DES_CBC_SHA uint16 = 0x0012 | ||
30 | cipher_TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA uint16 = 0x0013 | ||
31 | cipher_TLS_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA uint16 = 0x0014 | ||
32 | cipher_TLS_DHE_RSA_WITH_DES_CBC_SHA uint16 = 0x0015 | ||
33 | cipher_TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA uint16 = 0x0016 | ||
34 | cipher_TLS_DH_anon_EXPORT_WITH_RC4_40_MD5 uint16 = 0x0017 | ||
35 | cipher_TLS_DH_anon_WITH_RC4_128_MD5 uint16 = 0x0018 | ||
36 | cipher_TLS_DH_anon_EXPORT_WITH_DES40_CBC_SHA uint16 = 0x0019 | ||
37 | cipher_TLS_DH_anon_WITH_DES_CBC_SHA uint16 = 0x001A | ||
38 | cipher_TLS_DH_anon_WITH_3DES_EDE_CBC_SHA uint16 = 0x001B | ||
39 | // Reserved uint16 = 0x001C-1D | ||
40 | cipher_TLS_KRB5_WITH_DES_CBC_SHA uint16 = 0x001E | ||
41 | cipher_TLS_KRB5_WITH_3DES_EDE_CBC_SHA uint16 = 0x001F | ||
42 | cipher_TLS_KRB5_WITH_RC4_128_SHA uint16 = 0x0020 | ||
43 | cipher_TLS_KRB5_WITH_IDEA_CBC_SHA uint16 = 0x0021 | ||
44 | cipher_TLS_KRB5_WITH_DES_CBC_MD5 uint16 = 0x0022 | ||
45 | cipher_TLS_KRB5_WITH_3DES_EDE_CBC_MD5 uint16 = 0x0023 | ||
46 | cipher_TLS_KRB5_WITH_RC4_128_MD5 uint16 = 0x0024 | ||
47 | cipher_TLS_KRB5_WITH_IDEA_CBC_MD5 uint16 = 0x0025 | ||
48 | cipher_TLS_KRB5_EXPORT_WITH_DES_CBC_40_SHA uint16 = 0x0026 | ||
49 | cipher_TLS_KRB5_EXPORT_WITH_RC2_CBC_40_SHA uint16 = 0x0027 | ||
50 | cipher_TLS_KRB5_EXPORT_WITH_RC4_40_SHA uint16 = 0x0028 | ||
51 | cipher_TLS_KRB5_EXPORT_WITH_DES_CBC_40_MD5 uint16 = 0x0029 | ||
52 | cipher_TLS_KRB5_EXPORT_WITH_RC2_CBC_40_MD5 uint16 = 0x002A | ||
53 | cipher_TLS_KRB5_EXPORT_WITH_RC4_40_MD5 uint16 = 0x002B | ||
54 | cipher_TLS_PSK_WITH_NULL_SHA uint16 = 0x002C | ||
55 | cipher_TLS_DHE_PSK_WITH_NULL_SHA uint16 = 0x002D | ||
56 | cipher_TLS_RSA_PSK_WITH_NULL_SHA uint16 = 0x002E | ||
57 | cipher_TLS_RSA_WITH_AES_128_CBC_SHA uint16 = 0x002F | ||
58 | cipher_TLS_DH_DSS_WITH_AES_128_CBC_SHA uint16 = 0x0030 | ||
59 | cipher_TLS_DH_RSA_WITH_AES_128_CBC_SHA uint16 = 0x0031 | ||
60 | cipher_TLS_DHE_DSS_WITH_AES_128_CBC_SHA uint16 = 0x0032 | ||
61 | cipher_TLS_DHE_RSA_WITH_AES_128_CBC_SHA uint16 = 0x0033 | ||
62 | cipher_TLS_DH_anon_WITH_AES_128_CBC_SHA uint16 = 0x0034 | ||
63 | cipher_TLS_RSA_WITH_AES_256_CBC_SHA uint16 = 0x0035 | ||
64 | cipher_TLS_DH_DSS_WITH_AES_256_CBC_SHA uint16 = 0x0036 | ||
65 | cipher_TLS_DH_RSA_WITH_AES_256_CBC_SHA uint16 = 0x0037 | ||
66 | cipher_TLS_DHE_DSS_WITH_AES_256_CBC_SHA uint16 = 0x0038 | ||
67 | cipher_TLS_DHE_RSA_WITH_AES_256_CBC_SHA uint16 = 0x0039 | ||
68 | cipher_TLS_DH_anon_WITH_AES_256_CBC_SHA uint16 = 0x003A | ||
69 | cipher_TLS_RSA_WITH_NULL_SHA256 uint16 = 0x003B | ||
70 | cipher_TLS_RSA_WITH_AES_128_CBC_SHA256 uint16 = 0x003C | ||
71 | cipher_TLS_RSA_WITH_AES_256_CBC_SHA256 uint16 = 0x003D | ||
72 | cipher_TLS_DH_DSS_WITH_AES_128_CBC_SHA256 uint16 = 0x003E | ||
73 | cipher_TLS_DH_RSA_WITH_AES_128_CBC_SHA256 uint16 = 0x003F | ||
74 | cipher_TLS_DHE_DSS_WITH_AES_128_CBC_SHA256 uint16 = 0x0040 | ||
75 | cipher_TLS_RSA_WITH_CAMELLIA_128_CBC_SHA uint16 = 0x0041 | ||
76 | cipher_TLS_DH_DSS_WITH_CAMELLIA_128_CBC_SHA uint16 = 0x0042 | ||
77 | cipher_TLS_DH_RSA_WITH_CAMELLIA_128_CBC_SHA uint16 = 0x0043 | ||
78 | cipher_TLS_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA uint16 = 0x0044 | ||
79 | cipher_TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA uint16 = 0x0045 | ||
80 | cipher_TLS_DH_anon_WITH_CAMELLIA_128_CBC_SHA uint16 = 0x0046 | ||
81 | // Reserved uint16 = 0x0047-4F | ||
82 | // Reserved uint16 = 0x0050-58 | ||
83 | // Reserved uint16 = 0x0059-5C | ||
84 | // Unassigned uint16 = 0x005D-5F | ||
85 | // Reserved uint16 = 0x0060-66 | ||
86 | cipher_TLS_DHE_RSA_WITH_AES_128_CBC_SHA256 uint16 = 0x0067 | ||
87 | cipher_TLS_DH_DSS_WITH_AES_256_CBC_SHA256 uint16 = 0x0068 | ||
88 | cipher_TLS_DH_RSA_WITH_AES_256_CBC_SHA256 uint16 = 0x0069 | ||
89 | cipher_TLS_DHE_DSS_WITH_AES_256_CBC_SHA256 uint16 = 0x006A | ||
90 | cipher_TLS_DHE_RSA_WITH_AES_256_CBC_SHA256 uint16 = 0x006B | ||
91 | cipher_TLS_DH_anon_WITH_AES_128_CBC_SHA256 uint16 = 0x006C | ||
92 | cipher_TLS_DH_anon_WITH_AES_256_CBC_SHA256 uint16 = 0x006D | ||
93 | // Unassigned uint16 = 0x006E-83 | ||
94 | cipher_TLS_RSA_WITH_CAMELLIA_256_CBC_SHA uint16 = 0x0084 | ||
95 | cipher_TLS_DH_DSS_WITH_CAMELLIA_256_CBC_SHA uint16 = 0x0085 | ||
96 | cipher_TLS_DH_RSA_WITH_CAMELLIA_256_CBC_SHA uint16 = 0x0086 | ||
97 | cipher_TLS_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA uint16 = 0x0087 | ||
98 | cipher_TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA uint16 = 0x0088 | ||
99 | cipher_TLS_DH_anon_WITH_CAMELLIA_256_CBC_SHA uint16 = 0x0089 | ||
100 | cipher_TLS_PSK_WITH_RC4_128_SHA uint16 = 0x008A | ||
101 | cipher_TLS_PSK_WITH_3DES_EDE_CBC_SHA uint16 = 0x008B | ||
102 | cipher_TLS_PSK_WITH_AES_128_CBC_SHA uint16 = 0x008C | ||
103 | cipher_TLS_PSK_WITH_AES_256_CBC_SHA uint16 = 0x008D | ||
104 | cipher_TLS_DHE_PSK_WITH_RC4_128_SHA uint16 = 0x008E | ||
105 | cipher_TLS_DHE_PSK_WITH_3DES_EDE_CBC_SHA uint16 = 0x008F | ||
106 | cipher_TLS_DHE_PSK_WITH_AES_128_CBC_SHA uint16 = 0x0090 | ||
107 | cipher_TLS_DHE_PSK_WITH_AES_256_CBC_SHA uint16 = 0x0091 | ||
108 | cipher_TLS_RSA_PSK_WITH_RC4_128_SHA uint16 = 0x0092 | ||
109 | cipher_TLS_RSA_PSK_WITH_3DES_EDE_CBC_SHA uint16 = 0x0093 | ||
110 | cipher_TLS_RSA_PSK_WITH_AES_128_CBC_SHA uint16 = 0x0094 | ||
111 | cipher_TLS_RSA_PSK_WITH_AES_256_CBC_SHA uint16 = 0x0095 | ||
112 | cipher_TLS_RSA_WITH_SEED_CBC_SHA uint16 = 0x0096 | ||
113 | cipher_TLS_DH_DSS_WITH_SEED_CBC_SHA uint16 = 0x0097 | ||
114 | cipher_TLS_DH_RSA_WITH_SEED_CBC_SHA uint16 = 0x0098 | ||
115 | cipher_TLS_DHE_DSS_WITH_SEED_CBC_SHA uint16 = 0x0099 | ||
116 | cipher_TLS_DHE_RSA_WITH_SEED_CBC_SHA uint16 = 0x009A | ||
117 | cipher_TLS_DH_anon_WITH_SEED_CBC_SHA uint16 = 0x009B | ||
118 | cipher_TLS_RSA_WITH_AES_128_GCM_SHA256 uint16 = 0x009C | ||
119 | cipher_TLS_RSA_WITH_AES_256_GCM_SHA384 uint16 = 0x009D | ||
120 | cipher_TLS_DHE_RSA_WITH_AES_128_GCM_SHA256 uint16 = 0x009E | ||
121 | cipher_TLS_DHE_RSA_WITH_AES_256_GCM_SHA384 uint16 = 0x009F | ||
122 | cipher_TLS_DH_RSA_WITH_AES_128_GCM_SHA256 uint16 = 0x00A0 | ||
123 | cipher_TLS_DH_RSA_WITH_AES_256_GCM_SHA384 uint16 = 0x00A1 | ||
124 | cipher_TLS_DHE_DSS_WITH_AES_128_GCM_SHA256 uint16 = 0x00A2 | ||
125 | cipher_TLS_DHE_DSS_WITH_AES_256_GCM_SHA384 uint16 = 0x00A3 | ||
126 | cipher_TLS_DH_DSS_WITH_AES_128_GCM_SHA256 uint16 = 0x00A4 | ||
127 | cipher_TLS_DH_DSS_WITH_AES_256_GCM_SHA384 uint16 = 0x00A5 | ||
128 | cipher_TLS_DH_anon_WITH_AES_128_GCM_SHA256 uint16 = 0x00A6 | ||
129 | cipher_TLS_DH_anon_WITH_AES_256_GCM_SHA384 uint16 = 0x00A7 | ||
130 | cipher_TLS_PSK_WITH_AES_128_GCM_SHA256 uint16 = 0x00A8 | ||
131 | cipher_TLS_PSK_WITH_AES_256_GCM_SHA384 uint16 = 0x00A9 | ||
132 | cipher_TLS_DHE_PSK_WITH_AES_128_GCM_SHA256 uint16 = 0x00AA | ||
133 | cipher_TLS_DHE_PSK_WITH_AES_256_GCM_SHA384 uint16 = 0x00AB | ||
134 | cipher_TLS_RSA_PSK_WITH_AES_128_GCM_SHA256 uint16 = 0x00AC | ||
135 | cipher_TLS_RSA_PSK_WITH_AES_256_GCM_SHA384 uint16 = 0x00AD | ||
136 | cipher_TLS_PSK_WITH_AES_128_CBC_SHA256 uint16 = 0x00AE | ||
137 | cipher_TLS_PSK_WITH_AES_256_CBC_SHA384 uint16 = 0x00AF | ||
138 | cipher_TLS_PSK_WITH_NULL_SHA256 uint16 = 0x00B0 | ||
139 | cipher_TLS_PSK_WITH_NULL_SHA384 uint16 = 0x00B1 | ||
140 | cipher_TLS_DHE_PSK_WITH_AES_128_CBC_SHA256 uint16 = 0x00B2 | ||
141 | cipher_TLS_DHE_PSK_WITH_AES_256_CBC_SHA384 uint16 = 0x00B3 | ||
142 | cipher_TLS_DHE_PSK_WITH_NULL_SHA256 uint16 = 0x00B4 | ||
143 | cipher_TLS_DHE_PSK_WITH_NULL_SHA384 uint16 = 0x00B5 | ||
144 | cipher_TLS_RSA_PSK_WITH_AES_128_CBC_SHA256 uint16 = 0x00B6 | ||
145 | cipher_TLS_RSA_PSK_WITH_AES_256_CBC_SHA384 uint16 = 0x00B7 | ||
146 | cipher_TLS_RSA_PSK_WITH_NULL_SHA256 uint16 = 0x00B8 | ||
147 | cipher_TLS_RSA_PSK_WITH_NULL_SHA384 uint16 = 0x00B9 | ||
148 | cipher_TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256 uint16 = 0x00BA | ||
149 | cipher_TLS_DH_DSS_WITH_CAMELLIA_128_CBC_SHA256 uint16 = 0x00BB | ||
150 | cipher_TLS_DH_RSA_WITH_CAMELLIA_128_CBC_SHA256 uint16 = 0x00BC | ||
151 | cipher_TLS_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA256 uint16 = 0x00BD | ||
152 | cipher_TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256 uint16 = 0x00BE | ||
153 | cipher_TLS_DH_anon_WITH_CAMELLIA_128_CBC_SHA256 uint16 = 0x00BF | ||
154 | cipher_TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256 uint16 = 0x00C0 | ||
155 | cipher_TLS_DH_DSS_WITH_CAMELLIA_256_CBC_SHA256 uint16 = 0x00C1 | ||
156 | cipher_TLS_DH_RSA_WITH_CAMELLIA_256_CBC_SHA256 uint16 = 0x00C2 | ||
157 | cipher_TLS_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA256 uint16 = 0x00C3 | ||
158 | cipher_TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256 uint16 = 0x00C4 | ||
159 | cipher_TLS_DH_anon_WITH_CAMELLIA_256_CBC_SHA256 uint16 = 0x00C5 | ||
160 | // Unassigned uint16 = 0x00C6-FE | ||
161 | cipher_TLS_EMPTY_RENEGOTIATION_INFO_SCSV uint16 = 0x00FF | ||
162 | // Unassigned uint16 = 0x01-55,* | ||
163 | cipher_TLS_FALLBACK_SCSV uint16 = 0x5600 | ||
164 | // Unassigned uint16 = 0x5601 - 0xC000 | ||
165 | cipher_TLS_ECDH_ECDSA_WITH_NULL_SHA uint16 = 0xC001 | ||
166 | cipher_TLS_ECDH_ECDSA_WITH_RC4_128_SHA uint16 = 0xC002 | ||
167 | cipher_TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA uint16 = 0xC003 | ||
168 | cipher_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA uint16 = 0xC004 | ||
169 | cipher_TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA uint16 = 0xC005 | ||
170 | cipher_TLS_ECDHE_ECDSA_WITH_NULL_SHA uint16 = 0xC006 | ||
171 | cipher_TLS_ECDHE_ECDSA_WITH_RC4_128_SHA uint16 = 0xC007 | ||
172 | cipher_TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA uint16 = 0xC008 | ||
173 | cipher_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA uint16 = 0xC009 | ||
174 | cipher_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA uint16 = 0xC00A | ||
175 | cipher_TLS_ECDH_RSA_WITH_NULL_SHA uint16 = 0xC00B | ||
176 | cipher_TLS_ECDH_RSA_WITH_RC4_128_SHA uint16 = 0xC00C | ||
177 | cipher_TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA uint16 = 0xC00D | ||
178 | cipher_TLS_ECDH_RSA_WITH_AES_128_CBC_SHA uint16 = 0xC00E | ||
179 | cipher_TLS_ECDH_RSA_WITH_AES_256_CBC_SHA uint16 = 0xC00F | ||
180 | cipher_TLS_ECDHE_RSA_WITH_NULL_SHA uint16 = 0xC010 | ||
181 | cipher_TLS_ECDHE_RSA_WITH_RC4_128_SHA uint16 = 0xC011 | ||
182 | cipher_TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA uint16 = 0xC012 | ||
183 | cipher_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA uint16 = 0xC013 | ||
184 | cipher_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA uint16 = 0xC014 | ||
185 | cipher_TLS_ECDH_anon_WITH_NULL_SHA uint16 = 0xC015 | ||
186 | cipher_TLS_ECDH_anon_WITH_RC4_128_SHA uint16 = 0xC016 | ||
187 | cipher_TLS_ECDH_anon_WITH_3DES_EDE_CBC_SHA uint16 = 0xC017 | ||
188 | cipher_TLS_ECDH_anon_WITH_AES_128_CBC_SHA uint16 = 0xC018 | ||
189 | cipher_TLS_ECDH_anon_WITH_AES_256_CBC_SHA uint16 = 0xC019 | ||
190 | cipher_TLS_SRP_SHA_WITH_3DES_EDE_CBC_SHA uint16 = 0xC01A | ||
191 | cipher_TLS_SRP_SHA_RSA_WITH_3DES_EDE_CBC_SHA uint16 = 0xC01B | ||
192 | cipher_TLS_SRP_SHA_DSS_WITH_3DES_EDE_CBC_SHA uint16 = 0xC01C | ||
193 | cipher_TLS_SRP_SHA_WITH_AES_128_CBC_SHA uint16 = 0xC01D | ||
194 | cipher_TLS_SRP_SHA_RSA_WITH_AES_128_CBC_SHA uint16 = 0xC01E | ||
195 | cipher_TLS_SRP_SHA_DSS_WITH_AES_128_CBC_SHA uint16 = 0xC01F | ||
196 | cipher_TLS_SRP_SHA_WITH_AES_256_CBC_SHA uint16 = 0xC020 | ||
197 | cipher_TLS_SRP_SHA_RSA_WITH_AES_256_CBC_SHA uint16 = 0xC021 | ||
198 | cipher_TLS_SRP_SHA_DSS_WITH_AES_256_CBC_SHA uint16 = 0xC022 | ||
199 | cipher_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 uint16 = 0xC023 | ||
200 | cipher_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384 uint16 = 0xC024 | ||
201 | cipher_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256 uint16 = 0xC025 | ||
202 | cipher_TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384 uint16 = 0xC026 | ||
203 | cipher_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 uint16 = 0xC027 | ||
204 | cipher_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384 uint16 = 0xC028 | ||
205 | cipher_TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256 uint16 = 0xC029 | ||
206 | cipher_TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384 uint16 = 0xC02A | ||
207 | cipher_TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 uint16 = 0xC02B | ||
208 | cipher_TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 uint16 = 0xC02C | ||
209 | cipher_TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256 uint16 = 0xC02D | ||
210 | cipher_TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384 uint16 = 0xC02E | ||
211 | cipher_TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 uint16 = 0xC02F | ||
212 | cipher_TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 uint16 = 0xC030 | ||
213 | cipher_TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256 uint16 = 0xC031 | ||
214 | cipher_TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384 uint16 = 0xC032 | ||
215 | cipher_TLS_ECDHE_PSK_WITH_RC4_128_SHA uint16 = 0xC033 | ||
216 | cipher_TLS_ECDHE_PSK_WITH_3DES_EDE_CBC_SHA uint16 = 0xC034 | ||
217 | cipher_TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA uint16 = 0xC035 | ||
218 | cipher_TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA uint16 = 0xC036 | ||
219 | cipher_TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256 uint16 = 0xC037 | ||
220 | cipher_TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA384 uint16 = 0xC038 | ||
221 | cipher_TLS_ECDHE_PSK_WITH_NULL_SHA uint16 = 0xC039 | ||
222 | cipher_TLS_ECDHE_PSK_WITH_NULL_SHA256 uint16 = 0xC03A | ||
223 | cipher_TLS_ECDHE_PSK_WITH_NULL_SHA384 uint16 = 0xC03B | ||
224 | cipher_TLS_RSA_WITH_ARIA_128_CBC_SHA256 uint16 = 0xC03C | ||
225 | cipher_TLS_RSA_WITH_ARIA_256_CBC_SHA384 uint16 = 0xC03D | ||
226 | cipher_TLS_DH_DSS_WITH_ARIA_128_CBC_SHA256 uint16 = 0xC03E | ||
227 | cipher_TLS_DH_DSS_WITH_ARIA_256_CBC_SHA384 uint16 = 0xC03F | ||
228 | cipher_TLS_DH_RSA_WITH_ARIA_128_CBC_SHA256 uint16 = 0xC040 | ||
229 | cipher_TLS_DH_RSA_WITH_ARIA_256_CBC_SHA384 uint16 = 0xC041 | ||
230 | cipher_TLS_DHE_DSS_WITH_ARIA_128_CBC_SHA256 uint16 = 0xC042 | ||
231 | cipher_TLS_DHE_DSS_WITH_ARIA_256_CBC_SHA384 uint16 = 0xC043 | ||
232 | cipher_TLS_DHE_RSA_WITH_ARIA_128_CBC_SHA256 uint16 = 0xC044 | ||
233 | cipher_TLS_DHE_RSA_WITH_ARIA_256_CBC_SHA384 uint16 = 0xC045 | ||
234 | cipher_TLS_DH_anon_WITH_ARIA_128_CBC_SHA256 uint16 = 0xC046 | ||
235 | cipher_TLS_DH_anon_WITH_ARIA_256_CBC_SHA384 uint16 = 0xC047 | ||
236 | cipher_TLS_ECDHE_ECDSA_WITH_ARIA_128_CBC_SHA256 uint16 = 0xC048 | ||
237 | cipher_TLS_ECDHE_ECDSA_WITH_ARIA_256_CBC_SHA384 uint16 = 0xC049 | ||
238 | cipher_TLS_ECDH_ECDSA_WITH_ARIA_128_CBC_SHA256 uint16 = 0xC04A | ||
239 | cipher_TLS_ECDH_ECDSA_WITH_ARIA_256_CBC_SHA384 uint16 = 0xC04B | ||
240 | cipher_TLS_ECDHE_RSA_WITH_ARIA_128_CBC_SHA256 uint16 = 0xC04C | ||
241 | cipher_TLS_ECDHE_RSA_WITH_ARIA_256_CBC_SHA384 uint16 = 0xC04D | ||
242 | cipher_TLS_ECDH_RSA_WITH_ARIA_128_CBC_SHA256 uint16 = 0xC04E | ||
243 | cipher_TLS_ECDH_RSA_WITH_ARIA_256_CBC_SHA384 uint16 = 0xC04F | ||
244 | cipher_TLS_RSA_WITH_ARIA_128_GCM_SHA256 uint16 = 0xC050 | ||
245 | cipher_TLS_RSA_WITH_ARIA_256_GCM_SHA384 uint16 = 0xC051 | ||
246 | cipher_TLS_DHE_RSA_WITH_ARIA_128_GCM_SHA256 uint16 = 0xC052 | ||
247 | cipher_TLS_DHE_RSA_WITH_ARIA_256_GCM_SHA384 uint16 = 0xC053 | ||
248 | cipher_TLS_DH_RSA_WITH_ARIA_128_GCM_SHA256 uint16 = 0xC054 | ||
249 | cipher_TLS_DH_RSA_WITH_ARIA_256_GCM_SHA384 uint16 = 0xC055 | ||
250 | cipher_TLS_DHE_DSS_WITH_ARIA_128_GCM_SHA256 uint16 = 0xC056 | ||
251 | cipher_TLS_DHE_DSS_WITH_ARIA_256_GCM_SHA384 uint16 = 0xC057 | ||
252 | cipher_TLS_DH_DSS_WITH_ARIA_128_GCM_SHA256 uint16 = 0xC058 | ||
253 | cipher_TLS_DH_DSS_WITH_ARIA_256_GCM_SHA384 uint16 = 0xC059 | ||
254 | cipher_TLS_DH_anon_WITH_ARIA_128_GCM_SHA256 uint16 = 0xC05A | ||
255 | cipher_TLS_DH_anon_WITH_ARIA_256_GCM_SHA384 uint16 = 0xC05B | ||
256 | cipher_TLS_ECDHE_ECDSA_WITH_ARIA_128_GCM_SHA256 uint16 = 0xC05C | ||
257 | cipher_TLS_ECDHE_ECDSA_WITH_ARIA_256_GCM_SHA384 uint16 = 0xC05D | ||
258 | cipher_TLS_ECDH_ECDSA_WITH_ARIA_128_GCM_SHA256 uint16 = 0xC05E | ||
259 | cipher_TLS_ECDH_ECDSA_WITH_ARIA_256_GCM_SHA384 uint16 = 0xC05F | ||
260 | cipher_TLS_ECDHE_RSA_WITH_ARIA_128_GCM_SHA256 uint16 = 0xC060 | ||
261 | cipher_TLS_ECDHE_RSA_WITH_ARIA_256_GCM_SHA384 uint16 = 0xC061 | ||
262 | cipher_TLS_ECDH_RSA_WITH_ARIA_128_GCM_SHA256 uint16 = 0xC062 | ||
263 | cipher_TLS_ECDH_RSA_WITH_ARIA_256_GCM_SHA384 uint16 = 0xC063 | ||
264 | cipher_TLS_PSK_WITH_ARIA_128_CBC_SHA256 uint16 = 0xC064 | ||
265 | cipher_TLS_PSK_WITH_ARIA_256_CBC_SHA384 uint16 = 0xC065 | ||
266 | cipher_TLS_DHE_PSK_WITH_ARIA_128_CBC_SHA256 uint16 = 0xC066 | ||
267 | cipher_TLS_DHE_PSK_WITH_ARIA_256_CBC_SHA384 uint16 = 0xC067 | ||
268 | cipher_TLS_RSA_PSK_WITH_ARIA_128_CBC_SHA256 uint16 = 0xC068 | ||
269 | cipher_TLS_RSA_PSK_WITH_ARIA_256_CBC_SHA384 uint16 = 0xC069 | ||
270 | cipher_TLS_PSK_WITH_ARIA_128_GCM_SHA256 uint16 = 0xC06A | ||
271 | cipher_TLS_PSK_WITH_ARIA_256_GCM_SHA384 uint16 = 0xC06B | ||
272 | cipher_TLS_DHE_PSK_WITH_ARIA_128_GCM_SHA256 uint16 = 0xC06C | ||
273 | cipher_TLS_DHE_PSK_WITH_ARIA_256_GCM_SHA384 uint16 = 0xC06D | ||
274 | cipher_TLS_RSA_PSK_WITH_ARIA_128_GCM_SHA256 uint16 = 0xC06E | ||
275 | cipher_TLS_RSA_PSK_WITH_ARIA_256_GCM_SHA384 uint16 = 0xC06F | ||
276 | cipher_TLS_ECDHE_PSK_WITH_ARIA_128_CBC_SHA256 uint16 = 0xC070 | ||
277 | cipher_TLS_ECDHE_PSK_WITH_ARIA_256_CBC_SHA384 uint16 = 0xC071 | ||
278 | cipher_TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_CBC_SHA256 uint16 = 0xC072 | ||
279 | cipher_TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_CBC_SHA384 uint16 = 0xC073 | ||
280 | cipher_TLS_ECDH_ECDSA_WITH_CAMELLIA_128_CBC_SHA256 uint16 = 0xC074 | ||
281 | cipher_TLS_ECDH_ECDSA_WITH_CAMELLIA_256_CBC_SHA384 uint16 = 0xC075 | ||
282 | cipher_TLS_ECDHE_RSA_WITH_CAMELLIA_128_CBC_SHA256 uint16 = 0xC076 | ||
283 | cipher_TLS_ECDHE_RSA_WITH_CAMELLIA_256_CBC_SHA384 uint16 = 0xC077 | ||
284 | cipher_TLS_ECDH_RSA_WITH_CAMELLIA_128_CBC_SHA256 uint16 = 0xC078 | ||
285 | cipher_TLS_ECDH_RSA_WITH_CAMELLIA_256_CBC_SHA384 uint16 = 0xC079 | ||
286 | cipher_TLS_RSA_WITH_CAMELLIA_128_GCM_SHA256 uint16 = 0xC07A | ||
287 | cipher_TLS_RSA_WITH_CAMELLIA_256_GCM_SHA384 uint16 = 0xC07B | ||
288 | cipher_TLS_DHE_RSA_WITH_CAMELLIA_128_GCM_SHA256 uint16 = 0xC07C | ||
289 | cipher_TLS_DHE_RSA_WITH_CAMELLIA_256_GCM_SHA384 uint16 = 0xC07D | ||
290 | cipher_TLS_DH_RSA_WITH_CAMELLIA_128_GCM_SHA256 uint16 = 0xC07E | ||
291 | cipher_TLS_DH_RSA_WITH_CAMELLIA_256_GCM_SHA384 uint16 = 0xC07F | ||
292 | cipher_TLS_DHE_DSS_WITH_CAMELLIA_128_GCM_SHA256 uint16 = 0xC080 | ||
293 | cipher_TLS_DHE_DSS_WITH_CAMELLIA_256_GCM_SHA384 uint16 = 0xC081 | ||
294 | cipher_TLS_DH_DSS_WITH_CAMELLIA_128_GCM_SHA256 uint16 = 0xC082 | ||
295 | cipher_TLS_DH_DSS_WITH_CAMELLIA_256_GCM_SHA384 uint16 = 0xC083 | ||
296 | cipher_TLS_DH_anon_WITH_CAMELLIA_128_GCM_SHA256 uint16 = 0xC084 | ||
297 | cipher_TLS_DH_anon_WITH_CAMELLIA_256_GCM_SHA384 uint16 = 0xC085 | ||
298 | cipher_TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_GCM_SHA256 uint16 = 0xC086 | ||
299 | cipher_TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_GCM_SHA384 uint16 = 0xC087 | ||
300 | cipher_TLS_ECDH_ECDSA_WITH_CAMELLIA_128_GCM_SHA256 uint16 = 0xC088 | ||
301 | cipher_TLS_ECDH_ECDSA_WITH_CAMELLIA_256_GCM_SHA384 uint16 = 0xC089 | ||
302 | cipher_TLS_ECDHE_RSA_WITH_CAMELLIA_128_GCM_SHA256 uint16 = 0xC08A | ||
303 | cipher_TLS_ECDHE_RSA_WITH_CAMELLIA_256_GCM_SHA384 uint16 = 0xC08B | ||
304 | cipher_TLS_ECDH_RSA_WITH_CAMELLIA_128_GCM_SHA256 uint16 = 0xC08C | ||
305 | cipher_TLS_ECDH_RSA_WITH_CAMELLIA_256_GCM_SHA384 uint16 = 0xC08D | ||
306 | cipher_TLS_PSK_WITH_CAMELLIA_128_GCM_SHA256 uint16 = 0xC08E | ||
307 | cipher_TLS_PSK_WITH_CAMELLIA_256_GCM_SHA384 uint16 = 0xC08F | ||
308 | cipher_TLS_DHE_PSK_WITH_CAMELLIA_128_GCM_SHA256 uint16 = 0xC090 | ||
309 | cipher_TLS_DHE_PSK_WITH_CAMELLIA_256_GCM_SHA384 uint16 = 0xC091 | ||
310 | cipher_TLS_RSA_PSK_WITH_CAMELLIA_128_GCM_SHA256 uint16 = 0xC092 | ||
311 | cipher_TLS_RSA_PSK_WITH_CAMELLIA_256_GCM_SHA384 uint16 = 0xC093 | ||
312 | cipher_TLS_PSK_WITH_CAMELLIA_128_CBC_SHA256 uint16 = 0xC094 | ||
313 | cipher_TLS_PSK_WITH_CAMELLIA_256_CBC_SHA384 uint16 = 0xC095 | ||
314 | cipher_TLS_DHE_PSK_WITH_CAMELLIA_128_CBC_SHA256 uint16 = 0xC096 | ||
315 | cipher_TLS_DHE_PSK_WITH_CAMELLIA_256_CBC_SHA384 uint16 = 0xC097 | ||
316 | cipher_TLS_RSA_PSK_WITH_CAMELLIA_128_CBC_SHA256 uint16 = 0xC098 | ||
317 | cipher_TLS_RSA_PSK_WITH_CAMELLIA_256_CBC_SHA384 uint16 = 0xC099 | ||
318 | cipher_TLS_ECDHE_PSK_WITH_CAMELLIA_128_CBC_SHA256 uint16 = 0xC09A | ||
319 | cipher_TLS_ECDHE_PSK_WITH_CAMELLIA_256_CBC_SHA384 uint16 = 0xC09B | ||
320 | cipher_TLS_RSA_WITH_AES_128_CCM uint16 = 0xC09C | ||
321 | cipher_TLS_RSA_WITH_AES_256_CCM uint16 = 0xC09D | ||
322 | cipher_TLS_DHE_RSA_WITH_AES_128_CCM uint16 = 0xC09E | ||
323 | cipher_TLS_DHE_RSA_WITH_AES_256_CCM uint16 = 0xC09F | ||
324 | cipher_TLS_RSA_WITH_AES_128_CCM_8 uint16 = 0xC0A0 | ||
325 | cipher_TLS_RSA_WITH_AES_256_CCM_8 uint16 = 0xC0A1 | ||
326 | cipher_TLS_DHE_RSA_WITH_AES_128_CCM_8 uint16 = 0xC0A2 | ||
327 | cipher_TLS_DHE_RSA_WITH_AES_256_CCM_8 uint16 = 0xC0A3 | ||
328 | cipher_TLS_PSK_WITH_AES_128_CCM uint16 = 0xC0A4 | ||
329 | cipher_TLS_PSK_WITH_AES_256_CCM uint16 = 0xC0A5 | ||
330 | cipher_TLS_DHE_PSK_WITH_AES_128_CCM uint16 = 0xC0A6 | ||
331 | cipher_TLS_DHE_PSK_WITH_AES_256_CCM uint16 = 0xC0A7 | ||
332 | cipher_TLS_PSK_WITH_AES_128_CCM_8 uint16 = 0xC0A8 | ||
333 | cipher_TLS_PSK_WITH_AES_256_CCM_8 uint16 = 0xC0A9 | ||
334 | cipher_TLS_PSK_DHE_WITH_AES_128_CCM_8 uint16 = 0xC0AA | ||
335 | cipher_TLS_PSK_DHE_WITH_AES_256_CCM_8 uint16 = 0xC0AB | ||
336 | cipher_TLS_ECDHE_ECDSA_WITH_AES_128_CCM uint16 = 0xC0AC | ||
337 | cipher_TLS_ECDHE_ECDSA_WITH_AES_256_CCM uint16 = 0xC0AD | ||
338 | cipher_TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8 uint16 = 0xC0AE | ||
339 | cipher_TLS_ECDHE_ECDSA_WITH_AES_256_CCM_8 uint16 = 0xC0AF | ||
340 | // Unassigned uint16 = 0xC0B0-FF | ||
341 | // Unassigned uint16 = 0xC1-CB,* | ||
342 | // Unassigned uint16 = 0xCC00-A7 | ||
343 | cipher_TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256 uint16 = 0xCCA8 | ||
344 | cipher_TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256 uint16 = 0xCCA9 | ||
345 | cipher_TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256 uint16 = 0xCCAA | ||
346 | cipher_TLS_PSK_WITH_CHACHA20_POLY1305_SHA256 uint16 = 0xCCAB | ||
347 | cipher_TLS_ECDHE_PSK_WITH_CHACHA20_POLY1305_SHA256 uint16 = 0xCCAC | ||
348 | cipher_TLS_DHE_PSK_WITH_CHACHA20_POLY1305_SHA256 uint16 = 0xCCAD | ||
349 | cipher_TLS_RSA_PSK_WITH_CHACHA20_POLY1305_SHA256 uint16 = 0xCCAE | ||
350 | ) | ||
351 | |||
352 | // isBadCipher reports whether the cipher is blacklisted by the HTTP/2 spec. | ||
353 | // References: | ||
354 | // https://tools.ietf.org/html/rfc7540#appendix-A | ||
355 | // Reject cipher suites from Appendix A. | ||
356 | // "This list includes those cipher suites that do not | ||
357 | // offer an ephemeral key exchange and those that are | ||
358 | // based on the TLS null, stream or block cipher type" | ||
359 | func isBadCipher(cipher uint16) bool { | ||
360 | switch cipher { | ||
361 | case cipher_TLS_NULL_WITH_NULL_NULL, | ||
362 | cipher_TLS_RSA_WITH_NULL_MD5, | ||
363 | cipher_TLS_RSA_WITH_NULL_SHA, | ||
364 | cipher_TLS_RSA_EXPORT_WITH_RC4_40_MD5, | ||
365 | cipher_TLS_RSA_WITH_RC4_128_MD5, | ||
366 | cipher_TLS_RSA_WITH_RC4_128_SHA, | ||
367 | cipher_TLS_RSA_EXPORT_WITH_RC2_CBC_40_MD5, | ||
368 | cipher_TLS_RSA_WITH_IDEA_CBC_SHA, | ||
369 | cipher_TLS_RSA_EXPORT_WITH_DES40_CBC_SHA, | ||
370 | cipher_TLS_RSA_WITH_DES_CBC_SHA, | ||
371 | cipher_TLS_RSA_WITH_3DES_EDE_CBC_SHA, | ||
372 | cipher_TLS_DH_DSS_EXPORT_WITH_DES40_CBC_SHA, | ||
373 | cipher_TLS_DH_DSS_WITH_DES_CBC_SHA, | ||
374 | cipher_TLS_DH_DSS_WITH_3DES_EDE_CBC_SHA, | ||
375 | cipher_TLS_DH_RSA_EXPORT_WITH_DES40_CBC_SHA, | ||
376 | cipher_TLS_DH_RSA_WITH_DES_CBC_SHA, | ||
377 | cipher_TLS_DH_RSA_WITH_3DES_EDE_CBC_SHA, | ||
378 | cipher_TLS_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA, | ||
379 | cipher_TLS_DHE_DSS_WITH_DES_CBC_SHA, | ||
380 | cipher_TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA, | ||
381 | cipher_TLS_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA, | ||
382 | cipher_TLS_DHE_RSA_WITH_DES_CBC_SHA, | ||
383 | cipher_TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA, | ||
384 | cipher_TLS_DH_anon_EXPORT_WITH_RC4_40_MD5, | ||
385 | cipher_TLS_DH_anon_WITH_RC4_128_MD5, | ||
386 | cipher_TLS_DH_anon_EXPORT_WITH_DES40_CBC_SHA, | ||
387 | cipher_TLS_DH_anon_WITH_DES_CBC_SHA, | ||
388 | cipher_TLS_DH_anon_WITH_3DES_EDE_CBC_SHA, | ||
389 | cipher_TLS_KRB5_WITH_DES_CBC_SHA, | ||
390 | cipher_TLS_KRB5_WITH_3DES_EDE_CBC_SHA, | ||
391 | cipher_TLS_KRB5_WITH_RC4_128_SHA, | ||
392 | cipher_TLS_KRB5_WITH_IDEA_CBC_SHA, | ||
393 | cipher_TLS_KRB5_WITH_DES_CBC_MD5, | ||
394 | cipher_TLS_KRB5_WITH_3DES_EDE_CBC_MD5, | ||
395 | cipher_TLS_KRB5_WITH_RC4_128_MD5, | ||
396 | cipher_TLS_KRB5_WITH_IDEA_CBC_MD5, | ||
397 | cipher_TLS_KRB5_EXPORT_WITH_DES_CBC_40_SHA, | ||
398 | cipher_TLS_KRB5_EXPORT_WITH_RC2_CBC_40_SHA, | ||
399 | cipher_TLS_KRB5_EXPORT_WITH_RC4_40_SHA, | ||
400 | cipher_TLS_KRB5_EXPORT_WITH_DES_CBC_40_MD5, | ||
401 | cipher_TLS_KRB5_EXPORT_WITH_RC2_CBC_40_MD5, | ||
402 | cipher_TLS_KRB5_EXPORT_WITH_RC4_40_MD5, | ||
403 | cipher_TLS_PSK_WITH_NULL_SHA, | ||
404 | cipher_TLS_DHE_PSK_WITH_NULL_SHA, | ||
405 | cipher_TLS_RSA_PSK_WITH_NULL_SHA, | ||
406 | cipher_TLS_RSA_WITH_AES_128_CBC_SHA, | ||
407 | cipher_TLS_DH_DSS_WITH_AES_128_CBC_SHA, | ||
408 | cipher_TLS_DH_RSA_WITH_AES_128_CBC_SHA, | ||
409 | cipher_TLS_DHE_DSS_WITH_AES_128_CBC_SHA, | ||
410 | cipher_TLS_DHE_RSA_WITH_AES_128_CBC_SHA, | ||
411 | cipher_TLS_DH_anon_WITH_AES_128_CBC_SHA, | ||
412 | cipher_TLS_RSA_WITH_AES_256_CBC_SHA, | ||
413 | cipher_TLS_DH_DSS_WITH_AES_256_CBC_SHA, | ||
414 | cipher_TLS_DH_RSA_WITH_AES_256_CBC_SHA, | ||
415 | cipher_TLS_DHE_DSS_WITH_AES_256_CBC_SHA, | ||
416 | cipher_TLS_DHE_RSA_WITH_AES_256_CBC_SHA, | ||
417 | cipher_TLS_DH_anon_WITH_AES_256_CBC_SHA, | ||
418 | cipher_TLS_RSA_WITH_NULL_SHA256, | ||
419 | cipher_TLS_RSA_WITH_AES_128_CBC_SHA256, | ||
420 | cipher_TLS_RSA_WITH_AES_256_CBC_SHA256, | ||
421 | cipher_TLS_DH_DSS_WITH_AES_128_CBC_SHA256, | ||
422 | cipher_TLS_DH_RSA_WITH_AES_128_CBC_SHA256, | ||
423 | cipher_TLS_DHE_DSS_WITH_AES_128_CBC_SHA256, | ||
424 | cipher_TLS_RSA_WITH_CAMELLIA_128_CBC_SHA, | ||
425 | cipher_TLS_DH_DSS_WITH_CAMELLIA_128_CBC_SHA, | ||
426 | cipher_TLS_DH_RSA_WITH_CAMELLIA_128_CBC_SHA, | ||
427 | cipher_TLS_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA, | ||
428 | cipher_TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA, | ||
429 | cipher_TLS_DH_anon_WITH_CAMELLIA_128_CBC_SHA, | ||
430 | cipher_TLS_DHE_RSA_WITH_AES_128_CBC_SHA256, | ||
431 | cipher_TLS_DH_DSS_WITH_AES_256_CBC_SHA256, | ||
432 | cipher_TLS_DH_RSA_WITH_AES_256_CBC_SHA256, | ||
433 | cipher_TLS_DHE_DSS_WITH_AES_256_CBC_SHA256, | ||
434 | cipher_TLS_DHE_RSA_WITH_AES_256_CBC_SHA256, | ||
435 | cipher_TLS_DH_anon_WITH_AES_128_CBC_SHA256, | ||
436 | cipher_TLS_DH_anon_WITH_AES_256_CBC_SHA256, | ||
437 | cipher_TLS_RSA_WITH_CAMELLIA_256_CBC_SHA, | ||
438 | cipher_TLS_DH_DSS_WITH_CAMELLIA_256_CBC_SHA, | ||
439 | cipher_TLS_DH_RSA_WITH_CAMELLIA_256_CBC_SHA, | ||
440 | cipher_TLS_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA, | ||
441 | cipher_TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA, | ||
442 | cipher_TLS_DH_anon_WITH_CAMELLIA_256_CBC_SHA, | ||
443 | cipher_TLS_PSK_WITH_RC4_128_SHA, | ||
444 | cipher_TLS_PSK_WITH_3DES_EDE_CBC_SHA, | ||
445 | cipher_TLS_PSK_WITH_AES_128_CBC_SHA, | ||
446 | cipher_TLS_PSK_WITH_AES_256_CBC_SHA, | ||
447 | cipher_TLS_DHE_PSK_WITH_RC4_128_SHA, | ||
448 | cipher_TLS_DHE_PSK_WITH_3DES_EDE_CBC_SHA, | ||
449 | cipher_TLS_DHE_PSK_WITH_AES_128_CBC_SHA, | ||
450 | cipher_TLS_DHE_PSK_WITH_AES_256_CBC_SHA, | ||
451 | cipher_TLS_RSA_PSK_WITH_RC4_128_SHA, | ||
452 | cipher_TLS_RSA_PSK_WITH_3DES_EDE_CBC_SHA, | ||
453 | cipher_TLS_RSA_PSK_WITH_AES_128_CBC_SHA, | ||
454 | cipher_TLS_RSA_PSK_WITH_AES_256_CBC_SHA, | ||
455 | cipher_TLS_RSA_WITH_SEED_CBC_SHA, | ||
456 | cipher_TLS_DH_DSS_WITH_SEED_CBC_SHA, | ||
457 | cipher_TLS_DH_RSA_WITH_SEED_CBC_SHA, | ||
458 | cipher_TLS_DHE_DSS_WITH_SEED_CBC_SHA, | ||
459 | cipher_TLS_DHE_RSA_WITH_SEED_CBC_SHA, | ||
460 | cipher_TLS_DH_anon_WITH_SEED_CBC_SHA, | ||
461 | cipher_TLS_RSA_WITH_AES_128_GCM_SHA256, | ||
462 | cipher_TLS_RSA_WITH_AES_256_GCM_SHA384, | ||
463 | cipher_TLS_DH_RSA_WITH_AES_128_GCM_SHA256, | ||
464 | cipher_TLS_DH_RSA_WITH_AES_256_GCM_SHA384, | ||
465 | cipher_TLS_DH_DSS_WITH_AES_128_GCM_SHA256, | ||
466 | cipher_TLS_DH_DSS_WITH_AES_256_GCM_SHA384, | ||
467 | cipher_TLS_DH_anon_WITH_AES_128_GCM_SHA256, | ||
468 | cipher_TLS_DH_anon_WITH_AES_256_GCM_SHA384, | ||
469 | cipher_TLS_PSK_WITH_AES_128_GCM_SHA256, | ||
470 | cipher_TLS_PSK_WITH_AES_256_GCM_SHA384, | ||
471 | cipher_TLS_RSA_PSK_WITH_AES_128_GCM_SHA256, | ||
472 | cipher_TLS_RSA_PSK_WITH_AES_256_GCM_SHA384, | ||
473 | cipher_TLS_PSK_WITH_AES_128_CBC_SHA256, | ||
474 | cipher_TLS_PSK_WITH_AES_256_CBC_SHA384, | ||
475 | cipher_TLS_PSK_WITH_NULL_SHA256, | ||
476 | cipher_TLS_PSK_WITH_NULL_SHA384, | ||
477 | cipher_TLS_DHE_PSK_WITH_AES_128_CBC_SHA256, | ||
478 | cipher_TLS_DHE_PSK_WITH_AES_256_CBC_SHA384, | ||
479 | cipher_TLS_DHE_PSK_WITH_NULL_SHA256, | ||
480 | cipher_TLS_DHE_PSK_WITH_NULL_SHA384, | ||
481 | cipher_TLS_RSA_PSK_WITH_AES_128_CBC_SHA256, | ||
482 | cipher_TLS_RSA_PSK_WITH_AES_256_CBC_SHA384, | ||
483 | cipher_TLS_RSA_PSK_WITH_NULL_SHA256, | ||
484 | cipher_TLS_RSA_PSK_WITH_NULL_SHA384, | ||
485 | cipher_TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256, | ||
486 | cipher_TLS_DH_DSS_WITH_CAMELLIA_128_CBC_SHA256, | ||
487 | cipher_TLS_DH_RSA_WITH_CAMELLIA_128_CBC_SHA256, | ||
488 | cipher_TLS_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA256, | ||
489 | cipher_TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256, | ||
490 | cipher_TLS_DH_anon_WITH_CAMELLIA_128_CBC_SHA256, | ||
491 | cipher_TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256, | ||
492 | cipher_TLS_DH_DSS_WITH_CAMELLIA_256_CBC_SHA256, | ||
493 | cipher_TLS_DH_RSA_WITH_CAMELLIA_256_CBC_SHA256, | ||
494 | cipher_TLS_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA256, | ||
495 | cipher_TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256, | ||
496 | cipher_TLS_DH_anon_WITH_CAMELLIA_256_CBC_SHA256, | ||
497 | cipher_TLS_EMPTY_RENEGOTIATION_INFO_SCSV, | ||
498 | cipher_TLS_ECDH_ECDSA_WITH_NULL_SHA, | ||
499 | cipher_TLS_ECDH_ECDSA_WITH_RC4_128_SHA, | ||
500 | cipher_TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA, | ||
501 | cipher_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA, | ||
502 | cipher_TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA, | ||
503 | cipher_TLS_ECDHE_ECDSA_WITH_NULL_SHA, | ||
504 | cipher_TLS_ECDHE_ECDSA_WITH_RC4_128_SHA, | ||
505 | cipher_TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA, | ||
506 | cipher_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA, | ||
507 | cipher_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA, | ||
508 | cipher_TLS_ECDH_RSA_WITH_NULL_SHA, | ||
509 | cipher_TLS_ECDH_RSA_WITH_RC4_128_SHA, | ||
510 | cipher_TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA, | ||
511 | cipher_TLS_ECDH_RSA_WITH_AES_128_CBC_SHA, | ||
512 | cipher_TLS_ECDH_RSA_WITH_AES_256_CBC_SHA, | ||
513 | cipher_TLS_ECDHE_RSA_WITH_NULL_SHA, | ||
514 | cipher_TLS_ECDHE_RSA_WITH_RC4_128_SHA, | ||
515 | cipher_TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA, | ||
516 | cipher_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA, | ||
517 | cipher_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA, | ||
518 | cipher_TLS_ECDH_anon_WITH_NULL_SHA, | ||
519 | cipher_TLS_ECDH_anon_WITH_RC4_128_SHA, | ||
520 | cipher_TLS_ECDH_anon_WITH_3DES_EDE_CBC_SHA, | ||
521 | cipher_TLS_ECDH_anon_WITH_AES_128_CBC_SHA, | ||
522 | cipher_TLS_ECDH_anon_WITH_AES_256_CBC_SHA, | ||
523 | cipher_TLS_SRP_SHA_WITH_3DES_EDE_CBC_SHA, | ||
524 | cipher_TLS_SRP_SHA_RSA_WITH_3DES_EDE_CBC_SHA, | ||
525 | cipher_TLS_SRP_SHA_DSS_WITH_3DES_EDE_CBC_SHA, | ||
526 | cipher_TLS_SRP_SHA_WITH_AES_128_CBC_SHA, | ||
527 | cipher_TLS_SRP_SHA_RSA_WITH_AES_128_CBC_SHA, | ||
528 | cipher_TLS_SRP_SHA_DSS_WITH_AES_128_CBC_SHA, | ||
529 | cipher_TLS_SRP_SHA_WITH_AES_256_CBC_SHA, | ||
530 | cipher_TLS_SRP_SHA_RSA_WITH_AES_256_CBC_SHA, | ||
531 | cipher_TLS_SRP_SHA_DSS_WITH_AES_256_CBC_SHA, | ||
532 | cipher_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256, | ||
533 | cipher_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384, | ||
534 | cipher_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256, | ||
535 | cipher_TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384, | ||
536 | cipher_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256, | ||
537 | cipher_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384, | ||
538 | cipher_TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256, | ||
539 | cipher_TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384, | ||
540 | cipher_TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256, | ||
541 | cipher_TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384, | ||
542 | cipher_TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256, | ||
543 | cipher_TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384, | ||
544 | cipher_TLS_ECDHE_PSK_WITH_RC4_128_SHA, | ||
545 | cipher_TLS_ECDHE_PSK_WITH_3DES_EDE_CBC_SHA, | ||
546 | cipher_TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA, | ||
547 | cipher_TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA, | ||
548 | cipher_TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256, | ||
549 | cipher_TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA384, | ||
550 | cipher_TLS_ECDHE_PSK_WITH_NULL_SHA, | ||
551 | cipher_TLS_ECDHE_PSK_WITH_NULL_SHA256, | ||
552 | cipher_TLS_ECDHE_PSK_WITH_NULL_SHA384, | ||
553 | cipher_TLS_RSA_WITH_ARIA_128_CBC_SHA256, | ||
554 | cipher_TLS_RSA_WITH_ARIA_256_CBC_SHA384, | ||
555 | cipher_TLS_DH_DSS_WITH_ARIA_128_CBC_SHA256, | ||
556 | cipher_TLS_DH_DSS_WITH_ARIA_256_CBC_SHA384, | ||
557 | cipher_TLS_DH_RSA_WITH_ARIA_128_CBC_SHA256, | ||
558 | cipher_TLS_DH_RSA_WITH_ARIA_256_CBC_SHA384, | ||
559 | cipher_TLS_DHE_DSS_WITH_ARIA_128_CBC_SHA256, | ||
560 | cipher_TLS_DHE_DSS_WITH_ARIA_256_CBC_SHA384, | ||
561 | cipher_TLS_DHE_RSA_WITH_ARIA_128_CBC_SHA256, | ||
562 | cipher_TLS_DHE_RSA_WITH_ARIA_256_CBC_SHA384, | ||
563 | cipher_TLS_DH_anon_WITH_ARIA_128_CBC_SHA256, | ||
564 | cipher_TLS_DH_anon_WITH_ARIA_256_CBC_SHA384, | ||
565 | cipher_TLS_ECDHE_ECDSA_WITH_ARIA_128_CBC_SHA256, | ||
566 | cipher_TLS_ECDHE_ECDSA_WITH_ARIA_256_CBC_SHA384, | ||
567 | cipher_TLS_ECDH_ECDSA_WITH_ARIA_128_CBC_SHA256, | ||
568 | cipher_TLS_ECDH_ECDSA_WITH_ARIA_256_CBC_SHA384, | ||
569 | cipher_TLS_ECDHE_RSA_WITH_ARIA_128_CBC_SHA256, | ||
570 | cipher_TLS_ECDHE_RSA_WITH_ARIA_256_CBC_SHA384, | ||
571 | cipher_TLS_ECDH_RSA_WITH_ARIA_128_CBC_SHA256, | ||
572 | cipher_TLS_ECDH_RSA_WITH_ARIA_256_CBC_SHA384, | ||
573 | cipher_TLS_RSA_WITH_ARIA_128_GCM_SHA256, | ||
574 | cipher_TLS_RSA_WITH_ARIA_256_GCM_SHA384, | ||
575 | cipher_TLS_DH_RSA_WITH_ARIA_128_GCM_SHA256, | ||
576 | cipher_TLS_DH_RSA_WITH_ARIA_256_GCM_SHA384, | ||
577 | cipher_TLS_DH_DSS_WITH_ARIA_128_GCM_SHA256, | ||
578 | cipher_TLS_DH_DSS_WITH_ARIA_256_GCM_SHA384, | ||
579 | cipher_TLS_DH_anon_WITH_ARIA_128_GCM_SHA256, | ||
580 | cipher_TLS_DH_anon_WITH_ARIA_256_GCM_SHA384, | ||
581 | cipher_TLS_ECDH_ECDSA_WITH_ARIA_128_GCM_SHA256, | ||
582 | cipher_TLS_ECDH_ECDSA_WITH_ARIA_256_GCM_SHA384, | ||
583 | cipher_TLS_ECDH_RSA_WITH_ARIA_128_GCM_SHA256, | ||
584 | cipher_TLS_ECDH_RSA_WITH_ARIA_256_GCM_SHA384, | ||
585 | cipher_TLS_PSK_WITH_ARIA_128_CBC_SHA256, | ||
586 | cipher_TLS_PSK_WITH_ARIA_256_CBC_SHA384, | ||
587 | cipher_TLS_DHE_PSK_WITH_ARIA_128_CBC_SHA256, | ||
588 | cipher_TLS_DHE_PSK_WITH_ARIA_256_CBC_SHA384, | ||
589 | cipher_TLS_RSA_PSK_WITH_ARIA_128_CBC_SHA256, | ||
590 | cipher_TLS_RSA_PSK_WITH_ARIA_256_CBC_SHA384, | ||
591 | cipher_TLS_PSK_WITH_ARIA_128_GCM_SHA256, | ||
592 | cipher_TLS_PSK_WITH_ARIA_256_GCM_SHA384, | ||
593 | cipher_TLS_RSA_PSK_WITH_ARIA_128_GCM_SHA256, | ||
594 | cipher_TLS_RSA_PSK_WITH_ARIA_256_GCM_SHA384, | ||
595 | cipher_TLS_ECDHE_PSK_WITH_ARIA_128_CBC_SHA256, | ||
596 | cipher_TLS_ECDHE_PSK_WITH_ARIA_256_CBC_SHA384, | ||
597 | cipher_TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_CBC_SHA256, | ||
598 | cipher_TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_CBC_SHA384, | ||
599 | cipher_TLS_ECDH_ECDSA_WITH_CAMELLIA_128_CBC_SHA256, | ||
600 | cipher_TLS_ECDH_ECDSA_WITH_CAMELLIA_256_CBC_SHA384, | ||
601 | cipher_TLS_ECDHE_RSA_WITH_CAMELLIA_128_CBC_SHA256, | ||
602 | cipher_TLS_ECDHE_RSA_WITH_CAMELLIA_256_CBC_SHA384, | ||
603 | cipher_TLS_ECDH_RSA_WITH_CAMELLIA_128_CBC_SHA256, | ||
604 | cipher_TLS_ECDH_RSA_WITH_CAMELLIA_256_CBC_SHA384, | ||
605 | cipher_TLS_RSA_WITH_CAMELLIA_128_GCM_SHA256, | ||
606 | cipher_TLS_RSA_WITH_CAMELLIA_256_GCM_SHA384, | ||
607 | cipher_TLS_DH_RSA_WITH_CAMELLIA_128_GCM_SHA256, | ||
608 | cipher_TLS_DH_RSA_WITH_CAMELLIA_256_GCM_SHA384, | ||
609 | cipher_TLS_DH_DSS_WITH_CAMELLIA_128_GCM_SHA256, | ||
610 | cipher_TLS_DH_DSS_WITH_CAMELLIA_256_GCM_SHA384, | ||
611 | cipher_TLS_DH_anon_WITH_CAMELLIA_128_GCM_SHA256, | ||
612 | cipher_TLS_DH_anon_WITH_CAMELLIA_256_GCM_SHA384, | ||
613 | cipher_TLS_ECDH_ECDSA_WITH_CAMELLIA_128_GCM_SHA256, | ||
614 | cipher_TLS_ECDH_ECDSA_WITH_CAMELLIA_256_GCM_SHA384, | ||
615 | cipher_TLS_ECDH_RSA_WITH_CAMELLIA_128_GCM_SHA256, | ||
616 | cipher_TLS_ECDH_RSA_WITH_CAMELLIA_256_GCM_SHA384, | ||
617 | cipher_TLS_PSK_WITH_CAMELLIA_128_GCM_SHA256, | ||
618 | cipher_TLS_PSK_WITH_CAMELLIA_256_GCM_SHA384, | ||
619 | cipher_TLS_RSA_PSK_WITH_CAMELLIA_128_GCM_SHA256, | ||
620 | cipher_TLS_RSA_PSK_WITH_CAMELLIA_256_GCM_SHA384, | ||
621 | cipher_TLS_PSK_WITH_CAMELLIA_128_CBC_SHA256, | ||
622 | cipher_TLS_PSK_WITH_CAMELLIA_256_CBC_SHA384, | ||
623 | cipher_TLS_DHE_PSK_WITH_CAMELLIA_128_CBC_SHA256, | ||
624 | cipher_TLS_DHE_PSK_WITH_CAMELLIA_256_CBC_SHA384, | ||
625 | cipher_TLS_RSA_PSK_WITH_CAMELLIA_128_CBC_SHA256, | ||
626 | cipher_TLS_RSA_PSK_WITH_CAMELLIA_256_CBC_SHA384, | ||
627 | cipher_TLS_ECDHE_PSK_WITH_CAMELLIA_128_CBC_SHA256, | ||
628 | cipher_TLS_ECDHE_PSK_WITH_CAMELLIA_256_CBC_SHA384, | ||
629 | cipher_TLS_RSA_WITH_AES_128_CCM, | ||
630 | cipher_TLS_RSA_WITH_AES_256_CCM, | ||
631 | cipher_TLS_RSA_WITH_AES_128_CCM_8, | ||
632 | cipher_TLS_RSA_WITH_AES_256_CCM_8, | ||
633 | cipher_TLS_PSK_WITH_AES_128_CCM, | ||
634 | cipher_TLS_PSK_WITH_AES_256_CCM, | ||
635 | cipher_TLS_PSK_WITH_AES_128_CCM_8, | ||
636 | cipher_TLS_PSK_WITH_AES_256_CCM_8: | ||
637 | return true | ||
638 | default: | ||
639 | return false | ||
640 | } | ||
641 | } | ||
diff --git a/vendor/golang.org/x/net/http2/client_conn_pool.go b/vendor/golang.org/x/net/http2/client_conn_pool.go new file mode 100644 index 0000000..bdf5652 --- /dev/null +++ b/vendor/golang.org/x/net/http2/client_conn_pool.go | |||
@@ -0,0 +1,256 @@ | |||
1 | // Copyright 2015 The Go Authors. All rights reserved. | ||
2 | // Use of this source code is governed by a BSD-style | ||
3 | // license that can be found in the LICENSE file. | ||
4 | |||
5 | // Transport code's client connection pooling. | ||
6 | |||
7 | package http2 | ||
8 | |||
9 | import ( | ||
10 | "crypto/tls" | ||
11 | "net/http" | ||
12 | "sync" | ||
13 | ) | ||
14 | |||
15 | // ClientConnPool manages a pool of HTTP/2 client connections. | ||
16 | type ClientConnPool interface { | ||
17 | GetClientConn(req *http.Request, addr string) (*ClientConn, error) | ||
18 | MarkDead(*ClientConn) | ||
19 | } | ||
20 | |||
21 | // clientConnPoolIdleCloser is the interface implemented by ClientConnPool | ||
22 | // implementations which can close their idle connections. | ||
23 | type clientConnPoolIdleCloser interface { | ||
24 | ClientConnPool | ||
25 | closeIdleConnections() | ||
26 | } | ||
27 | |||
28 | var ( | ||
29 | _ clientConnPoolIdleCloser = (*clientConnPool)(nil) | ||
30 | _ clientConnPoolIdleCloser = noDialClientConnPool{} | ||
31 | ) | ||
32 | |||
33 | // TODO: use singleflight for dialing and addConnCalls? | ||
34 | type clientConnPool struct { | ||
35 | t *Transport | ||
36 | |||
37 | mu sync.Mutex // TODO: maybe switch to RWMutex | ||
38 | // TODO: add support for sharing conns based on cert names | ||
39 | // (e.g. share conn for googleapis.com and appspot.com) | ||
40 | conns map[string][]*ClientConn // key is host:port | ||
41 | dialing map[string]*dialCall // currently in-flight dials | ||
42 | keys map[*ClientConn][]string | ||
43 | addConnCalls map[string]*addConnCall // in-flight addConnIfNeede calls | ||
44 | } | ||
45 | |||
46 | func (p *clientConnPool) GetClientConn(req *http.Request, addr string) (*ClientConn, error) { | ||
47 | return p.getClientConn(req, addr, dialOnMiss) | ||
48 | } | ||
49 | |||
50 | const ( | ||
51 | dialOnMiss = true | ||
52 | noDialOnMiss = false | ||
53 | ) | ||
54 | |||
55 | func (p *clientConnPool) getClientConn(req *http.Request, addr string, dialOnMiss bool) (*ClientConn, error) { | ||
56 | if isConnectionCloseRequest(req) && dialOnMiss { | ||
57 | // It gets its own connection. | ||
58 | const singleUse = true | ||
59 | cc, err := p.t.dialClientConn(addr, singleUse) | ||
60 | if err != nil { | ||
61 | return nil, err | ||
62 | } | ||
63 | return cc, nil | ||
64 | } | ||
65 | p.mu.Lock() | ||
66 | for _, cc := range p.conns[addr] { | ||
67 | if cc.CanTakeNewRequest() { | ||
68 | p.mu.Unlock() | ||
69 | return cc, nil | ||
70 | } | ||
71 | } | ||
72 | if !dialOnMiss { | ||
73 | p.mu.Unlock() | ||
74 | return nil, ErrNoCachedConn | ||
75 | } | ||
76 | call := p.getStartDialLocked(addr) | ||
77 | p.mu.Unlock() | ||
78 | <-call.done | ||
79 | return call.res, call.err | ||
80 | } | ||
81 | |||
82 | // dialCall is an in-flight Transport dial call to a host. | ||
83 | type dialCall struct { | ||
84 | p *clientConnPool | ||
85 | done chan struct{} // closed when done | ||
86 | res *ClientConn // valid after done is closed | ||
87 | err error // valid after done is closed | ||
88 | } | ||
89 | |||
90 | // requires p.mu is held. | ||
91 | func (p *clientConnPool) getStartDialLocked(addr string) *dialCall { | ||
92 | if call, ok := p.dialing[addr]; ok { | ||
93 | // A dial is already in-flight. Don't start another. | ||
94 | return call | ||
95 | } | ||
96 | call := &dialCall{p: p, done: make(chan struct{})} | ||
97 | if p.dialing == nil { | ||
98 | p.dialing = make(map[string]*dialCall) | ||
99 | } | ||
100 | p.dialing[addr] = call | ||
101 | go call.dial(addr) | ||
102 | return call | ||
103 | } | ||
104 | |||
105 | // run in its own goroutine. | ||
106 | func (c *dialCall) dial(addr string) { | ||
107 | const singleUse = false // shared conn | ||
108 | c.res, c.err = c.p.t.dialClientConn(addr, singleUse) | ||
109 | close(c.done) | ||
110 | |||
111 | c.p.mu.Lock() | ||
112 | delete(c.p.dialing, addr) | ||
113 | if c.err == nil { | ||
114 | c.p.addConnLocked(addr, c.res) | ||
115 | } | ||
116 | c.p.mu.Unlock() | ||
117 | } | ||
118 | |||
119 | // addConnIfNeeded makes a NewClientConn out of c if a connection for key doesn't | ||
120 | // already exist. It coalesces concurrent calls with the same key. | ||
121 | // This is used by the http1 Transport code when it creates a new connection. Because | ||
122 | // the http1 Transport doesn't de-dup TCP dials to outbound hosts (because it doesn't know | ||
123 | // the protocol), it can get into a situation where it has multiple TLS connections. | ||
124 | // This code decides which ones live or die. | ||
125 | // The return value used is whether c was used. | ||
126 | // c is never closed. | ||
127 | func (p *clientConnPool) addConnIfNeeded(key string, t *Transport, c *tls.Conn) (used bool, err error) { | ||
128 | p.mu.Lock() | ||
129 | for _, cc := range p.conns[key] { | ||
130 | if cc.CanTakeNewRequest() { | ||
131 | p.mu.Unlock() | ||
132 | return false, nil | ||
133 | } | ||
134 | } | ||
135 | call, dup := p.addConnCalls[key] | ||
136 | if !dup { | ||
137 | if p.addConnCalls == nil { | ||
138 | p.addConnCalls = make(map[string]*addConnCall) | ||
139 | } | ||
140 | call = &addConnCall{ | ||
141 | p: p, | ||
142 | done: make(chan struct{}), | ||
143 | } | ||
144 | p.addConnCalls[key] = call | ||
145 | go call.run(t, key, c) | ||
146 | } | ||
147 | p.mu.Unlock() | ||
148 | |||
149 | <-call.done | ||
150 | if call.err != nil { | ||
151 | return false, call.err | ||
152 | } | ||
153 | return !dup, nil | ||
154 | } | ||
155 | |||
156 | type addConnCall struct { | ||
157 | p *clientConnPool | ||
158 | done chan struct{} // closed when done | ||
159 | err error | ||
160 | } | ||
161 | |||
162 | func (c *addConnCall) run(t *Transport, key string, tc *tls.Conn) { | ||
163 | cc, err := t.NewClientConn(tc) | ||
164 | |||
165 | p := c.p | ||
166 | p.mu.Lock() | ||
167 | if err != nil { | ||
168 | c.err = err | ||
169 | } else { | ||
170 | p.addConnLocked(key, cc) | ||
171 | } | ||
172 | delete(p.addConnCalls, key) | ||
173 | p.mu.Unlock() | ||
174 | close(c.done) | ||
175 | } | ||
176 | |||
177 | func (p *clientConnPool) addConn(key string, cc *ClientConn) { | ||
178 | p.mu.Lock() | ||
179 | p.addConnLocked(key, cc) | ||
180 | p.mu.Unlock() | ||
181 | } | ||
182 | |||
183 | // p.mu must be held | ||
184 | func (p *clientConnPool) addConnLocked(key string, cc *ClientConn) { | ||
185 | for _, v := range p.conns[key] { | ||
186 | if v == cc { | ||
187 | return | ||
188 | } | ||
189 | } | ||
190 | if p.conns == nil { | ||
191 | p.conns = make(map[string][]*ClientConn) | ||
192 | } | ||
193 | if p.keys == nil { | ||
194 | p.keys = make(map[*ClientConn][]string) | ||
195 | } | ||
196 | p.conns[key] = append(p.conns[key], cc) | ||
197 | p.keys[cc] = append(p.keys[cc], key) | ||
198 | } | ||
199 | |||
200 | func (p *clientConnPool) MarkDead(cc *ClientConn) { | ||
201 | p.mu.Lock() | ||
202 | defer p.mu.Unlock() | ||
203 | for _, key := range p.keys[cc] { | ||
204 | vv, ok := p.conns[key] | ||
205 | if !ok { | ||
206 | continue | ||
207 | } | ||
208 | newList := filterOutClientConn(vv, cc) | ||
209 | if len(newList) > 0 { | ||
210 | p.conns[key] = newList | ||
211 | } else { | ||
212 | delete(p.conns, key) | ||
213 | } | ||
214 | } | ||
215 | delete(p.keys, cc) | ||
216 | } | ||
217 | |||
218 | func (p *clientConnPool) closeIdleConnections() { | ||
219 | p.mu.Lock() | ||
220 | defer p.mu.Unlock() | ||
221 | // TODO: don't close a cc if it was just added to the pool | ||
222 | // milliseconds ago and has never been used. There's currently | ||
223 | // a small race window with the HTTP/1 Transport's integration | ||
224 | // where it can add an idle conn just before using it, and | ||
225 | // somebody else can concurrently call CloseIdleConns and | ||
226 | // break some caller's RoundTrip. | ||
227 | for _, vv := range p.conns { | ||
228 | for _, cc := range vv { | ||
229 | cc.closeIfIdle() | ||
230 | } | ||
231 | } | ||
232 | } | ||
233 | |||
234 | func filterOutClientConn(in []*ClientConn, exclude *ClientConn) []*ClientConn { | ||
235 | out := in[:0] | ||
236 | for _, v := range in { | ||
237 | if v != exclude { | ||
238 | out = append(out, v) | ||
239 | } | ||
240 | } | ||
241 | // If we filtered it out, zero out the last item to prevent | ||
242 | // the GC from seeing it. | ||
243 | if len(in) != len(out) { | ||
244 | in[len(in)-1] = nil | ||
245 | } | ||
246 | return out | ||
247 | } | ||
248 | |||
249 | // noDialClientConnPool is an implementation of http2.ClientConnPool | ||
250 | // which never dials. We let the HTTP/1.1 client dial and use its TLS | ||
251 | // connection instead. | ||
252 | type noDialClientConnPool struct{ *clientConnPool } | ||
253 | |||
254 | func (p noDialClientConnPool) GetClientConn(req *http.Request, addr string) (*ClientConn, error) { | ||
255 | return p.getClientConn(req, addr, noDialOnMiss) | ||
256 | } | ||
diff --git a/vendor/golang.org/x/net/http2/configure_transport.go b/vendor/golang.org/x/net/http2/configure_transport.go new file mode 100644 index 0000000..b65fc6d --- /dev/null +++ b/vendor/golang.org/x/net/http2/configure_transport.go | |||
@@ -0,0 +1,80 @@ | |||
1 | // Copyright 2015 The Go Authors. All rights reserved. | ||
2 | // Use of this source code is governed by a BSD-style | ||
3 | // license that can be found in the LICENSE file. | ||
4 | |||
5 | // +build go1.6 | ||
6 | |||
7 | package http2 | ||
8 | |||
9 | import ( | ||
10 | "crypto/tls" | ||
11 | "fmt" | ||
12 | "net/http" | ||
13 | ) | ||
14 | |||
15 | func configureTransport(t1 *http.Transport) (*Transport, error) { | ||
16 | connPool := new(clientConnPool) | ||
17 | t2 := &Transport{ | ||
18 | ConnPool: noDialClientConnPool{connPool}, | ||
19 | t1: t1, | ||
20 | } | ||
21 | connPool.t = t2 | ||
22 | if err := registerHTTPSProtocol(t1, noDialH2RoundTripper{t2}); err != nil { | ||
23 | return nil, err | ||
24 | } | ||
25 | if t1.TLSClientConfig == nil { | ||
26 | t1.TLSClientConfig = new(tls.Config) | ||
27 | } | ||
28 | if !strSliceContains(t1.TLSClientConfig.NextProtos, "h2") { | ||
29 | t1.TLSClientConfig.NextProtos = append([]string{"h2"}, t1.TLSClientConfig.NextProtos...) | ||
30 | } | ||
31 | if !strSliceContains(t1.TLSClientConfig.NextProtos, "http/1.1") { | ||
32 | t1.TLSClientConfig.NextProtos = append(t1.TLSClientConfig.NextProtos, "http/1.1") | ||
33 | } | ||
34 | upgradeFn := func(authority string, c *tls.Conn) http.RoundTripper { | ||
35 | addr := authorityAddr("https", authority) | ||
36 | if used, err := connPool.addConnIfNeeded(addr, t2, c); err != nil { | ||
37 | go c.Close() | ||
38 | return erringRoundTripper{err} | ||
39 | } else if !used { | ||
40 | // Turns out we don't need this c. | ||
41 | // For example, two goroutines made requests to the same host | ||
42 | // at the same time, both kicking off TCP dials. (since protocol | ||
43 | // was unknown) | ||
44 | go c.Close() | ||
45 | } | ||
46 | return t2 | ||
47 | } | ||
48 | if m := t1.TLSNextProto; len(m) == 0 { | ||
49 | t1.TLSNextProto = map[string]func(string, *tls.Conn) http.RoundTripper{ | ||
50 | "h2": upgradeFn, | ||
51 | } | ||
52 | } else { | ||
53 | m["h2"] = upgradeFn | ||
54 | } | ||
55 | return t2, nil | ||
56 | } | ||
57 | |||
58 | // registerHTTPSProtocol calls Transport.RegisterProtocol but | ||
59 | // converting panics into errors. | ||
60 | func registerHTTPSProtocol(t *http.Transport, rt http.RoundTripper) (err error) { | ||
61 | defer func() { | ||
62 | if e := recover(); e != nil { | ||
63 | err = fmt.Errorf("%v", e) | ||
64 | } | ||
65 | }() | ||
66 | t.RegisterProtocol("https", rt) | ||
67 | return nil | ||
68 | } | ||
69 | |||
70 | // noDialH2RoundTripper is a RoundTripper which only tries to complete the request | ||
71 | // if there's already has a cached connection to the host. | ||
72 | type noDialH2RoundTripper struct{ t *Transport } | ||
73 | |||
74 | func (rt noDialH2RoundTripper) RoundTrip(req *http.Request) (*http.Response, error) { | ||
75 | res, err := rt.t.RoundTrip(req) | ||
76 | if err == ErrNoCachedConn { | ||
77 | return nil, http.ErrSkipAltProtocol | ||
78 | } | ||
79 | return res, err | ||
80 | } | ||
diff --git a/vendor/golang.org/x/net/http2/databuffer.go b/vendor/golang.org/x/net/http2/databuffer.go new file mode 100644 index 0000000..a3067f8 --- /dev/null +++ b/vendor/golang.org/x/net/http2/databuffer.go | |||
@@ -0,0 +1,146 @@ | |||
1 | // Copyright 2014 The Go Authors. All rights reserved. | ||
2 | // Use of this source code is governed by a BSD-style | ||
3 | // license that can be found in the LICENSE file. | ||
4 | |||
5 | package http2 | ||
6 | |||
7 | import ( | ||
8 | "errors" | ||
9 | "fmt" | ||
10 | "sync" | ||
11 | ) | ||
12 | |||
13 | // Buffer chunks are allocated from a pool to reduce pressure on GC. | ||
14 | // The maximum wasted space per dataBuffer is 2x the largest size class, | ||
15 | // which happens when the dataBuffer has multiple chunks and there is | ||
16 | // one unread byte in both the first and last chunks. We use a few size | ||
17 | // classes to minimize overheads for servers that typically receive very | ||
18 | // small request bodies. | ||
19 | // | ||
20 | // TODO: Benchmark to determine if the pools are necessary. The GC may have | ||
21 | // improved enough that we can instead allocate chunks like this: | ||
22 | // make([]byte, max(16<<10, expectedBytesRemaining)) | ||
23 | var ( | ||
24 | dataChunkSizeClasses = []int{ | ||
25 | 1 << 10, | ||
26 | 2 << 10, | ||
27 | 4 << 10, | ||
28 | 8 << 10, | ||
29 | 16 << 10, | ||
30 | } | ||
31 | dataChunkPools = [...]sync.Pool{ | ||
32 | {New: func() interface{} { return make([]byte, 1<<10) }}, | ||
33 | {New: func() interface{} { return make([]byte, 2<<10) }}, | ||
34 | {New: func() interface{} { return make([]byte, 4<<10) }}, | ||
35 | {New: func() interface{} { return make([]byte, 8<<10) }}, | ||
36 | {New: func() interface{} { return make([]byte, 16<<10) }}, | ||
37 | } | ||
38 | ) | ||
39 | |||
40 | func getDataBufferChunk(size int64) []byte { | ||
41 | i := 0 | ||
42 | for ; i < len(dataChunkSizeClasses)-1; i++ { | ||
43 | if size <= int64(dataChunkSizeClasses[i]) { | ||
44 | break | ||
45 | } | ||
46 | } | ||
47 | return dataChunkPools[i].Get().([]byte) | ||
48 | } | ||
49 | |||
50 | func putDataBufferChunk(p []byte) { | ||
51 | for i, n := range dataChunkSizeClasses { | ||
52 | if len(p) == n { | ||
53 | dataChunkPools[i].Put(p) | ||
54 | return | ||
55 | } | ||
56 | } | ||
57 | panic(fmt.Sprintf("unexpected buffer len=%v", len(p))) | ||
58 | } | ||
59 | |||
60 | // dataBuffer is an io.ReadWriter backed by a list of data chunks. | ||
61 | // Each dataBuffer is used to read DATA frames on a single stream. | ||
62 | // The buffer is divided into chunks so the server can limit the | ||
63 | // total memory used by a single connection without limiting the | ||
64 | // request body size on any single stream. | ||
65 | type dataBuffer struct { | ||
66 | chunks [][]byte | ||
67 | r int // next byte to read is chunks[0][r] | ||
68 | w int // next byte to write is chunks[len(chunks)-1][w] | ||
69 | size int // total buffered bytes | ||
70 | expected int64 // we expect at least this many bytes in future Write calls (ignored if <= 0) | ||
71 | } | ||
72 | |||
73 | var errReadEmpty = errors.New("read from empty dataBuffer") | ||
74 | |||
75 | // Read copies bytes from the buffer into p. | ||
76 | // It is an error to read when no data is available. | ||
77 | func (b *dataBuffer) Read(p []byte) (int, error) { | ||
78 | if b.size == 0 { | ||
79 | return 0, errReadEmpty | ||
80 | } | ||
81 | var ntotal int | ||
82 | for len(p) > 0 && b.size > 0 { | ||
83 | readFrom := b.bytesFromFirstChunk() | ||
84 | n := copy(p, readFrom) | ||
85 | p = p[n:] | ||
86 | ntotal += n | ||
87 | b.r += n | ||
88 | b.size -= n | ||
89 | // If the first chunk has been consumed, advance to the next chunk. | ||
90 | if b.r == len(b.chunks[0]) { | ||
91 | putDataBufferChunk(b.chunks[0]) | ||
92 | end := len(b.chunks) - 1 | ||
93 | copy(b.chunks[:end], b.chunks[1:]) | ||
94 | b.chunks[end] = nil | ||
95 | b.chunks = b.chunks[:end] | ||
96 | b.r = 0 | ||
97 | } | ||
98 | } | ||
99 | return ntotal, nil | ||
100 | } | ||
101 | |||
102 | func (b *dataBuffer) bytesFromFirstChunk() []byte { | ||
103 | if len(b.chunks) == 1 { | ||
104 | return b.chunks[0][b.r:b.w] | ||
105 | } | ||
106 | return b.chunks[0][b.r:] | ||
107 | } | ||
108 | |||
109 | // Len returns the number of bytes of the unread portion of the buffer. | ||
110 | func (b *dataBuffer) Len() int { | ||
111 | return b.size | ||
112 | } | ||
113 | |||
114 | // Write appends p to the buffer. | ||
115 | func (b *dataBuffer) Write(p []byte) (int, error) { | ||
116 | ntotal := len(p) | ||
117 | for len(p) > 0 { | ||
118 | // If the last chunk is empty, allocate a new chunk. Try to allocate | ||
119 | // enough to fully copy p plus any additional bytes we expect to | ||
120 | // receive. However, this may allocate less than len(p). | ||
121 | want := int64(len(p)) | ||
122 | if b.expected > want { | ||
123 | want = b.expected | ||
124 | } | ||
125 | chunk := b.lastChunkOrAlloc(want) | ||
126 | n := copy(chunk[b.w:], p) | ||
127 | p = p[n:] | ||
128 | b.w += n | ||
129 | b.size += n | ||
130 | b.expected -= int64(n) | ||
131 | } | ||
132 | return ntotal, nil | ||
133 | } | ||
134 | |||
135 | func (b *dataBuffer) lastChunkOrAlloc(want int64) []byte { | ||
136 | if len(b.chunks) != 0 { | ||
137 | last := b.chunks[len(b.chunks)-1] | ||
138 | if b.w < len(last) { | ||
139 | return last | ||
140 | } | ||
141 | } | ||
142 | chunk := getDataBufferChunk(want) | ||
143 | b.chunks = append(b.chunks, chunk) | ||
144 | b.w = 0 | ||
145 | return chunk | ||
146 | } | ||
diff --git a/vendor/golang.org/x/net/http2/errors.go b/vendor/golang.org/x/net/http2/errors.go new file mode 100644 index 0000000..71f2c46 --- /dev/null +++ b/vendor/golang.org/x/net/http2/errors.go | |||
@@ -0,0 +1,133 @@ | |||
1 | // Copyright 2014 The Go Authors. All rights reserved. | ||
2 | // Use of this source code is governed by a BSD-style | ||
3 | // license that can be found in the LICENSE file. | ||
4 | |||
5 | package http2 | ||
6 | |||
7 | import ( | ||
8 | "errors" | ||
9 | "fmt" | ||
10 | ) | ||
11 | |||
12 | // An ErrCode is an unsigned 32-bit error code as defined in the HTTP/2 spec. | ||
13 | type ErrCode uint32 | ||
14 | |||
15 | const ( | ||
16 | ErrCodeNo ErrCode = 0x0 | ||
17 | ErrCodeProtocol ErrCode = 0x1 | ||
18 | ErrCodeInternal ErrCode = 0x2 | ||
19 | ErrCodeFlowControl ErrCode = 0x3 | ||
20 | ErrCodeSettingsTimeout ErrCode = 0x4 | ||
21 | ErrCodeStreamClosed ErrCode = 0x5 | ||
22 | ErrCodeFrameSize ErrCode = 0x6 | ||
23 | ErrCodeRefusedStream ErrCode = 0x7 | ||
24 | ErrCodeCancel ErrCode = 0x8 | ||
25 | ErrCodeCompression ErrCode = 0x9 | ||
26 | ErrCodeConnect ErrCode = 0xa | ||
27 | ErrCodeEnhanceYourCalm ErrCode = 0xb | ||
28 | ErrCodeInadequateSecurity ErrCode = 0xc | ||
29 | ErrCodeHTTP11Required ErrCode = 0xd | ||
30 | ) | ||
31 | |||
32 | var errCodeName = map[ErrCode]string{ | ||
33 | ErrCodeNo: "NO_ERROR", | ||
34 | ErrCodeProtocol: "PROTOCOL_ERROR", | ||
35 | ErrCodeInternal: "INTERNAL_ERROR", | ||
36 | ErrCodeFlowControl: "FLOW_CONTROL_ERROR", | ||
37 | ErrCodeSettingsTimeout: "SETTINGS_TIMEOUT", | ||
38 | ErrCodeStreamClosed: "STREAM_CLOSED", | ||
39 | ErrCodeFrameSize: "FRAME_SIZE_ERROR", | ||
40 | ErrCodeRefusedStream: "REFUSED_STREAM", | ||
41 | ErrCodeCancel: "CANCEL", | ||
42 | ErrCodeCompression: "COMPRESSION_ERROR", | ||
43 | ErrCodeConnect: "CONNECT_ERROR", | ||
44 | ErrCodeEnhanceYourCalm: "ENHANCE_YOUR_CALM", | ||
45 | ErrCodeInadequateSecurity: "INADEQUATE_SECURITY", | ||
46 | ErrCodeHTTP11Required: "HTTP_1_1_REQUIRED", | ||
47 | } | ||
48 | |||
49 | func (e ErrCode) String() string { | ||
50 | if s, ok := errCodeName[e]; ok { | ||
51 | return s | ||
52 | } | ||
53 | return fmt.Sprintf("unknown error code 0x%x", uint32(e)) | ||
54 | } | ||
55 | |||
56 | // ConnectionError is an error that results in the termination of the | ||
57 | // entire connection. | ||
58 | type ConnectionError ErrCode | ||
59 | |||
60 | func (e ConnectionError) Error() string { return fmt.Sprintf("connection error: %s", ErrCode(e)) } | ||
61 | |||
62 | // StreamError is an error that only affects one stream within an | ||
63 | // HTTP/2 connection. | ||
64 | type StreamError struct { | ||
65 | StreamID uint32 | ||
66 | Code ErrCode | ||
67 | Cause error // optional additional detail | ||
68 | } | ||
69 | |||
70 | func streamError(id uint32, code ErrCode) StreamError { | ||
71 | return StreamError{StreamID: id, Code: code} | ||
72 | } | ||
73 | |||
74 | func (e StreamError) Error() string { | ||
75 | if e.Cause != nil { | ||
76 | return fmt.Sprintf("stream error: stream ID %d; %v; %v", e.StreamID, e.Code, e.Cause) | ||
77 | } | ||
78 | return fmt.Sprintf("stream error: stream ID %d; %v", e.StreamID, e.Code) | ||
79 | } | ||
80 | |||
81 | // 6.9.1 The Flow Control Window | ||
82 | // "If a sender receives a WINDOW_UPDATE that causes a flow control | ||
83 | // window to exceed this maximum it MUST terminate either the stream | ||
84 | // or the connection, as appropriate. For streams, [...]; for the | ||
85 | // connection, a GOAWAY frame with a FLOW_CONTROL_ERROR code." | ||
86 | type goAwayFlowError struct{} | ||
87 | |||
88 | func (goAwayFlowError) Error() string { return "connection exceeded flow control window size" } | ||
89 | |||
90 | // connError represents an HTTP/2 ConnectionError error code, along | ||
91 | // with a string (for debugging) explaining why. | ||
92 | // | ||
93 | // Errors of this type are only returned by the frame parser functions | ||
94 | // and converted into ConnectionError(Code), after stashing away | ||
95 | // the Reason into the Framer's errDetail field, accessible via | ||
96 | // the (*Framer).ErrorDetail method. | ||
97 | type connError struct { | ||
98 | Code ErrCode // the ConnectionError error code | ||
99 | Reason string // additional reason | ||
100 | } | ||
101 | |||
102 | func (e connError) Error() string { | ||
103 | return fmt.Sprintf("http2: connection error: %v: %v", e.Code, e.Reason) | ||
104 | } | ||
105 | |||
106 | type pseudoHeaderError string | ||
107 | |||
108 | func (e pseudoHeaderError) Error() string { | ||
109 | return fmt.Sprintf("invalid pseudo-header %q", string(e)) | ||
110 | } | ||
111 | |||
112 | type duplicatePseudoHeaderError string | ||
113 | |||
114 | func (e duplicatePseudoHeaderError) Error() string { | ||
115 | return fmt.Sprintf("duplicate pseudo-header %q", string(e)) | ||
116 | } | ||
117 | |||
118 | type headerFieldNameError string | ||
119 | |||
120 | func (e headerFieldNameError) Error() string { | ||
121 | return fmt.Sprintf("invalid header field name %q", string(e)) | ||
122 | } | ||
123 | |||
124 | type headerFieldValueError string | ||
125 | |||
126 | func (e headerFieldValueError) Error() string { | ||
127 | return fmt.Sprintf("invalid header field value %q", string(e)) | ||
128 | } | ||
129 | |||
130 | var ( | ||
131 | errMixPseudoHeaderTypes = errors.New("mix of request and response pseudo headers") | ||
132 | errPseudoAfterRegular = errors.New("pseudo header field after regular") | ||
133 | ) | ||
diff --git a/vendor/golang.org/x/net/http2/flow.go b/vendor/golang.org/x/net/http2/flow.go new file mode 100644 index 0000000..957de25 --- /dev/null +++ b/vendor/golang.org/x/net/http2/flow.go | |||
@@ -0,0 +1,50 @@ | |||
1 | // Copyright 2014 The Go Authors. All rights reserved. | ||
2 | // Use of this source code is governed by a BSD-style | ||
3 | // license that can be found in the LICENSE file. | ||
4 | |||
5 | // Flow control | ||
6 | |||
7 | package http2 | ||
8 | |||
9 | // flow is the flow control window's size. | ||
10 | type flow struct { | ||
11 | // n is the number of DATA bytes we're allowed to send. | ||
12 | // A flow is kept both on a conn and a per-stream. | ||
13 | n int32 | ||
14 | |||
15 | // conn points to the shared connection-level flow that is | ||
16 | // shared by all streams on that conn. It is nil for the flow | ||
17 | // that's on the conn directly. | ||
18 | conn *flow | ||
19 | } | ||
20 | |||
21 | func (f *flow) setConnFlow(cf *flow) { f.conn = cf } | ||
22 | |||
23 | func (f *flow) available() int32 { | ||
24 | n := f.n | ||
25 | if f.conn != nil && f.conn.n < n { | ||
26 | n = f.conn.n | ||
27 | } | ||
28 | return n | ||
29 | } | ||
30 | |||
31 | func (f *flow) take(n int32) { | ||
32 | if n > f.available() { | ||
33 | panic("internal error: took too much") | ||
34 | } | ||
35 | f.n -= n | ||
36 | if f.conn != nil { | ||
37 | f.conn.n -= n | ||
38 | } | ||
39 | } | ||
40 | |||
41 | // add adds n bytes (positive or negative) to the flow control window. | ||
42 | // It returns false if the sum would exceed 2^31-1. | ||
43 | func (f *flow) add(n int32) bool { | ||
44 | remain := (1<<31 - 1) - f.n | ||
45 | if n > remain { | ||
46 | return false | ||
47 | } | ||
48 | f.n += n | ||
49 | return true | ||
50 | } | ||
diff --git a/vendor/golang.org/x/net/http2/frame.go b/vendor/golang.org/x/net/http2/frame.go new file mode 100644 index 0000000..3b14890 --- /dev/null +++ b/vendor/golang.org/x/net/http2/frame.go | |||
@@ -0,0 +1,1579 @@ | |||
1 | // Copyright 2014 The Go Authors. All rights reserved. | ||
2 | // Use of this source code is governed by a BSD-style | ||
3 | // license that can be found in the LICENSE file. | ||
4 | |||
5 | package http2 | ||
6 | |||
7 | import ( | ||
8 | "bytes" | ||
9 | "encoding/binary" | ||
10 | "errors" | ||
11 | "fmt" | ||
12 | "io" | ||
13 | "log" | ||
14 | "strings" | ||
15 | "sync" | ||
16 | |||
17 | "golang.org/x/net/http2/hpack" | ||
18 | "golang.org/x/net/lex/httplex" | ||
19 | ) | ||
20 | |||
21 | const frameHeaderLen = 9 | ||
22 | |||
23 | var padZeros = make([]byte, 255) // zeros for padding | ||
24 | |||
25 | // A FrameType is a registered frame type as defined in | ||
26 | // http://http2.github.io/http2-spec/#rfc.section.11.2 | ||
27 | type FrameType uint8 | ||
28 | |||
29 | const ( | ||
30 | FrameData FrameType = 0x0 | ||
31 | FrameHeaders FrameType = 0x1 | ||
32 | FramePriority FrameType = 0x2 | ||
33 | FrameRSTStream FrameType = 0x3 | ||
34 | FrameSettings FrameType = 0x4 | ||
35 | FramePushPromise FrameType = 0x5 | ||
36 | FramePing FrameType = 0x6 | ||
37 | FrameGoAway FrameType = 0x7 | ||
38 | FrameWindowUpdate FrameType = 0x8 | ||
39 | FrameContinuation FrameType = 0x9 | ||
40 | ) | ||
41 | |||
42 | var frameName = map[FrameType]string{ | ||
43 | FrameData: "DATA", | ||
44 | FrameHeaders: "HEADERS", | ||
45 | FramePriority: "PRIORITY", | ||
46 | FrameRSTStream: "RST_STREAM", | ||
47 | FrameSettings: "SETTINGS", | ||
48 | FramePushPromise: "PUSH_PROMISE", | ||
49 | FramePing: "PING", | ||
50 | FrameGoAway: "GOAWAY", | ||
51 | FrameWindowUpdate: "WINDOW_UPDATE", | ||
52 | FrameContinuation: "CONTINUATION", | ||
53 | } | ||
54 | |||
55 | func (t FrameType) String() string { | ||
56 | if s, ok := frameName[t]; ok { | ||
57 | return s | ||
58 | } | ||
59 | return fmt.Sprintf("UNKNOWN_FRAME_TYPE_%d", uint8(t)) | ||
60 | } | ||
61 | |||
62 | // Flags is a bitmask of HTTP/2 flags. | ||
63 | // The meaning of flags varies depending on the frame type. | ||
64 | type Flags uint8 | ||
65 | |||
66 | // Has reports whether f contains all (0 or more) flags in v. | ||
67 | func (f Flags) Has(v Flags) bool { | ||
68 | return (f & v) == v | ||
69 | } | ||
70 | |||
71 | // Frame-specific FrameHeader flag bits. | ||
72 | const ( | ||
73 | // Data Frame | ||
74 | FlagDataEndStream Flags = 0x1 | ||
75 | FlagDataPadded Flags = 0x8 | ||
76 | |||
77 | // Headers Frame | ||
78 | FlagHeadersEndStream Flags = 0x1 | ||
79 | FlagHeadersEndHeaders Flags = 0x4 | ||
80 | FlagHeadersPadded Flags = 0x8 | ||
81 | FlagHeadersPriority Flags = 0x20 | ||
82 | |||
83 | // Settings Frame | ||
84 | FlagSettingsAck Flags = 0x1 | ||
85 | |||
86 | // Ping Frame | ||
87 | FlagPingAck Flags = 0x1 | ||
88 | |||
89 | // Continuation Frame | ||
90 | FlagContinuationEndHeaders Flags = 0x4 | ||
91 | |||
92 | FlagPushPromiseEndHeaders Flags = 0x4 | ||
93 | FlagPushPromisePadded Flags = 0x8 | ||
94 | ) | ||
95 | |||
96 | var flagName = map[FrameType]map[Flags]string{ | ||
97 | FrameData: { | ||
98 | FlagDataEndStream: "END_STREAM", | ||
99 | FlagDataPadded: "PADDED", | ||
100 | }, | ||
101 | FrameHeaders: { | ||
102 | FlagHeadersEndStream: "END_STREAM", | ||
103 | FlagHeadersEndHeaders: "END_HEADERS", | ||
104 | FlagHeadersPadded: "PADDED", | ||
105 | FlagHeadersPriority: "PRIORITY", | ||
106 | }, | ||
107 | FrameSettings: { | ||
108 | FlagSettingsAck: "ACK", | ||
109 | }, | ||
110 | FramePing: { | ||
111 | FlagPingAck: "ACK", | ||
112 | }, | ||
113 | FrameContinuation: { | ||
114 | FlagContinuationEndHeaders: "END_HEADERS", | ||
115 | }, | ||
116 | FramePushPromise: { | ||
117 | FlagPushPromiseEndHeaders: "END_HEADERS", | ||
118 | FlagPushPromisePadded: "PADDED", | ||
119 | }, | ||
120 | } | ||
121 | |||
122 | // a frameParser parses a frame given its FrameHeader and payload | ||
123 | // bytes. The length of payload will always equal fh.Length (which | ||
124 | // might be 0). | ||
125 | type frameParser func(fc *frameCache, fh FrameHeader, payload []byte) (Frame, error) | ||
126 | |||
127 | var frameParsers = map[FrameType]frameParser{ | ||
128 | FrameData: parseDataFrame, | ||
129 | FrameHeaders: parseHeadersFrame, | ||
130 | FramePriority: parsePriorityFrame, | ||
131 | FrameRSTStream: parseRSTStreamFrame, | ||
132 | FrameSettings: parseSettingsFrame, | ||
133 | FramePushPromise: parsePushPromise, | ||
134 | FramePing: parsePingFrame, | ||
135 | FrameGoAway: parseGoAwayFrame, | ||
136 | FrameWindowUpdate: parseWindowUpdateFrame, | ||
137 | FrameContinuation: parseContinuationFrame, | ||
138 | } | ||
139 | |||
140 | func typeFrameParser(t FrameType) frameParser { | ||
141 | if f := frameParsers[t]; f != nil { | ||
142 | return f | ||
143 | } | ||
144 | return parseUnknownFrame | ||
145 | } | ||
146 | |||
147 | // A FrameHeader is the 9 byte header of all HTTP/2 frames. | ||
148 | // | ||
149 | // See http://http2.github.io/http2-spec/#FrameHeader | ||
150 | type FrameHeader struct { | ||
151 | valid bool // caller can access []byte fields in the Frame | ||
152 | |||
153 | // Type is the 1 byte frame type. There are ten standard frame | ||
154 | // types, but extension frame types may be written by WriteRawFrame | ||
155 | // and will be returned by ReadFrame (as UnknownFrame). | ||
156 | Type FrameType | ||
157 | |||
158 | // Flags are the 1 byte of 8 potential bit flags per frame. | ||
159 | // They are specific to the frame type. | ||
160 | Flags Flags | ||
161 | |||
162 | // Length is the length of the frame, not including the 9 byte header. | ||
163 | // The maximum size is one byte less than 16MB (uint24), but only | ||
164 | // frames up to 16KB are allowed without peer agreement. | ||
165 | Length uint32 | ||
166 | |||
167 | // StreamID is which stream this frame is for. Certain frames | ||
168 | // are not stream-specific, in which case this field is 0. | ||
169 | StreamID uint32 | ||
170 | } | ||
171 | |||
172 | // Header returns h. It exists so FrameHeaders can be embedded in other | ||
173 | // specific frame types and implement the Frame interface. | ||
174 | func (h FrameHeader) Header() FrameHeader { return h } | ||
175 | |||
176 | func (h FrameHeader) String() string { | ||
177 | var buf bytes.Buffer | ||
178 | buf.WriteString("[FrameHeader ") | ||
179 | h.writeDebug(&buf) | ||
180 | buf.WriteByte(']') | ||
181 | return buf.String() | ||
182 | } | ||
183 | |||
184 | func (h FrameHeader) writeDebug(buf *bytes.Buffer) { | ||
185 | buf.WriteString(h.Type.String()) | ||
186 | if h.Flags != 0 { | ||
187 | buf.WriteString(" flags=") | ||
188 | set := 0 | ||
189 | for i := uint8(0); i < 8; i++ { | ||
190 | if h.Flags&(1<<i) == 0 { | ||
191 | continue | ||
192 | } | ||
193 | set++ | ||
194 | if set > 1 { | ||
195 | buf.WriteByte('|') | ||
196 | } | ||
197 | name := flagName[h.Type][Flags(1<<i)] | ||
198 | if name != "" { | ||
199 | buf.WriteString(name) | ||
200 | } else { | ||
201 | fmt.Fprintf(buf, "0x%x", 1<<i) | ||
202 | } | ||
203 | } | ||
204 | } | ||
205 | if h.StreamID != 0 { | ||
206 | fmt.Fprintf(buf, " stream=%d", h.StreamID) | ||
207 | } | ||
208 | fmt.Fprintf(buf, " len=%d", h.Length) | ||
209 | } | ||
210 | |||
211 | func (h *FrameHeader) checkValid() { | ||
212 | if !h.valid { | ||
213 | panic("Frame accessor called on non-owned Frame") | ||
214 | } | ||
215 | } | ||
216 | |||
217 | func (h *FrameHeader) invalidate() { h.valid = false } | ||
218 | |||
219 | // frame header bytes. | ||
220 | // Used only by ReadFrameHeader. | ||
221 | var fhBytes = sync.Pool{ | ||
222 | New: func() interface{} { | ||
223 | buf := make([]byte, frameHeaderLen) | ||
224 | return &buf | ||
225 | }, | ||
226 | } | ||
227 | |||
228 | // ReadFrameHeader reads 9 bytes from r and returns a FrameHeader. | ||
229 | // Most users should use Framer.ReadFrame instead. | ||
230 | func ReadFrameHeader(r io.Reader) (FrameHeader, error) { | ||
231 | bufp := fhBytes.Get().(*[]byte) | ||
232 | defer fhBytes.Put(bufp) | ||
233 | return readFrameHeader(*bufp, r) | ||
234 | } | ||
235 | |||
236 | func readFrameHeader(buf []byte, r io.Reader) (FrameHeader, error) { | ||
237 | _, err := io.ReadFull(r, buf[:frameHeaderLen]) | ||
238 | if err != nil { | ||
239 | return FrameHeader{}, err | ||
240 | } | ||
241 | return FrameHeader{ | ||
242 | Length: (uint32(buf[0])<<16 | uint32(buf[1])<<8 | uint32(buf[2])), | ||
243 | Type: FrameType(buf[3]), | ||
244 | Flags: Flags(buf[4]), | ||
245 | StreamID: binary.BigEndian.Uint32(buf[5:]) & (1<<31 - 1), | ||
246 | valid: true, | ||
247 | }, nil | ||
248 | } | ||
249 | |||
250 | // A Frame is the base interface implemented by all frame types. | ||
251 | // Callers will generally type-assert the specific frame type: | ||
252 | // *HeadersFrame, *SettingsFrame, *WindowUpdateFrame, etc. | ||
253 | // | ||
254 | // Frames are only valid until the next call to Framer.ReadFrame. | ||
255 | type Frame interface { | ||
256 | Header() FrameHeader | ||
257 | |||
258 | // invalidate is called by Framer.ReadFrame to make this | ||
259 | // frame's buffers as being invalid, since the subsequent | ||
260 | // frame will reuse them. | ||
261 | invalidate() | ||
262 | } | ||
263 | |||
264 | // A Framer reads and writes Frames. | ||
265 | type Framer struct { | ||
266 | r io.Reader | ||
267 | lastFrame Frame | ||
268 | errDetail error | ||
269 | |||
270 | // lastHeaderStream is non-zero if the last frame was an | ||
271 | // unfinished HEADERS/CONTINUATION. | ||
272 | lastHeaderStream uint32 | ||
273 | |||
274 | maxReadSize uint32 | ||
275 | headerBuf [frameHeaderLen]byte | ||
276 | |||
277 | // TODO: let getReadBuf be configurable, and use a less memory-pinning | ||
278 | // allocator in server.go to minimize memory pinned for many idle conns. | ||
279 | // Will probably also need to make frame invalidation have a hook too. | ||
280 | getReadBuf func(size uint32) []byte | ||
281 | readBuf []byte // cache for default getReadBuf | ||
282 | |||
283 | maxWriteSize uint32 // zero means unlimited; TODO: implement | ||
284 | |||
285 | w io.Writer | ||
286 | wbuf []byte | ||
287 | |||
288 | // AllowIllegalWrites permits the Framer's Write methods to | ||
289 | // write frames that do not conform to the HTTP/2 spec. This | ||
290 | // permits using the Framer to test other HTTP/2 | ||
291 | // implementations' conformance to the spec. | ||
292 | // If false, the Write methods will prefer to return an error | ||
293 | // rather than comply. | ||
294 | AllowIllegalWrites bool | ||
295 | |||
296 | // AllowIllegalReads permits the Framer's ReadFrame method | ||
297 | // to return non-compliant frames or frame orders. | ||
298 | // This is for testing and permits using the Framer to test | ||
299 | // other HTTP/2 implementations' conformance to the spec. | ||
300 | // It is not compatible with ReadMetaHeaders. | ||
301 | AllowIllegalReads bool | ||
302 | |||
303 | // ReadMetaHeaders if non-nil causes ReadFrame to merge | ||
304 | // HEADERS and CONTINUATION frames together and return | ||
305 | // MetaHeadersFrame instead. | ||
306 | ReadMetaHeaders *hpack.Decoder | ||
307 | |||
308 | // MaxHeaderListSize is the http2 MAX_HEADER_LIST_SIZE. | ||
309 | // It's used only if ReadMetaHeaders is set; 0 means a sane default | ||
310 | // (currently 16MB) | ||
311 | // If the limit is hit, MetaHeadersFrame.Truncated is set true. | ||
312 | MaxHeaderListSize uint32 | ||
313 | |||
314 | // TODO: track which type of frame & with which flags was sent | ||
315 | // last. Then return an error (unless AllowIllegalWrites) if | ||
316 | // we're in the middle of a header block and a | ||
317 | // non-Continuation or Continuation on a different stream is | ||
318 | // attempted to be written. | ||
319 | |||
320 | logReads, logWrites bool | ||
321 | |||
322 | debugFramer *Framer // only use for logging written writes | ||
323 | debugFramerBuf *bytes.Buffer | ||
324 | debugReadLoggerf func(string, ...interface{}) | ||
325 | debugWriteLoggerf func(string, ...interface{}) | ||
326 | |||
327 | frameCache *frameCache // nil if frames aren't reused (default) | ||
328 | } | ||
329 | |||
330 | func (fr *Framer) maxHeaderListSize() uint32 { | ||
331 | if fr.MaxHeaderListSize == 0 { | ||
332 | return 16 << 20 // sane default, per docs | ||
333 | } | ||
334 | return fr.MaxHeaderListSize | ||
335 | } | ||
336 | |||
337 | func (f *Framer) startWrite(ftype FrameType, flags Flags, streamID uint32) { | ||
338 | // Write the FrameHeader. | ||
339 | f.wbuf = append(f.wbuf[:0], | ||
340 | 0, // 3 bytes of length, filled in in endWrite | ||
341 | 0, | ||
342 | 0, | ||
343 | byte(ftype), | ||
344 | byte(flags), | ||
345 | byte(streamID>>24), | ||
346 | byte(streamID>>16), | ||
347 | byte(streamID>>8), | ||
348 | byte(streamID)) | ||
349 | } | ||
350 | |||
351 | func (f *Framer) endWrite() error { | ||
352 | // Now that we know the final size, fill in the FrameHeader in | ||
353 | // the space previously reserved for it. Abuse append. | ||
354 | length := len(f.wbuf) - frameHeaderLen | ||
355 | if length >= (1 << 24) { | ||
356 | return ErrFrameTooLarge | ||
357 | } | ||
358 | _ = append(f.wbuf[:0], | ||
359 | byte(length>>16), | ||
360 | byte(length>>8), | ||
361 | byte(length)) | ||
362 | if f.logWrites { | ||
363 | f.logWrite() | ||
364 | } | ||
365 | |||
366 | n, err := f.w.Write(f.wbuf) | ||
367 | if err == nil && n != len(f.wbuf) { | ||
368 | err = io.ErrShortWrite | ||
369 | } | ||
370 | return err | ||
371 | } | ||
372 | |||
373 | func (f *Framer) logWrite() { | ||
374 | if f.debugFramer == nil { | ||
375 | f.debugFramerBuf = new(bytes.Buffer) | ||
376 | f.debugFramer = NewFramer(nil, f.debugFramerBuf) | ||
377 | f.debugFramer.logReads = false // we log it ourselves, saying "wrote" below | ||
378 | // Let us read anything, even if we accidentally wrote it | ||
379 | // in the wrong order: | ||
380 | f.debugFramer.AllowIllegalReads = true | ||
381 | } | ||
382 | f.debugFramerBuf.Write(f.wbuf) | ||
383 | fr, err := f.debugFramer.ReadFrame() | ||
384 | if err != nil { | ||
385 | f.debugWriteLoggerf("http2: Framer %p: failed to decode just-written frame", f) | ||
386 | return | ||
387 | } | ||
388 | f.debugWriteLoggerf("http2: Framer %p: wrote %v", f, summarizeFrame(fr)) | ||
389 | } | ||
390 | |||
391 | func (f *Framer) writeByte(v byte) { f.wbuf = append(f.wbuf, v) } | ||
392 | func (f *Framer) writeBytes(v []byte) { f.wbuf = append(f.wbuf, v...) } | ||
393 | func (f *Framer) writeUint16(v uint16) { f.wbuf = append(f.wbuf, byte(v>>8), byte(v)) } | ||
394 | func (f *Framer) writeUint32(v uint32) { | ||
395 | f.wbuf = append(f.wbuf, byte(v>>24), byte(v>>16), byte(v>>8), byte(v)) | ||
396 | } | ||
397 | |||
398 | const ( | ||
399 | minMaxFrameSize = 1 << 14 | ||
400 | maxFrameSize = 1<<24 - 1 | ||
401 | ) | ||
402 | |||
403 | // SetReuseFrames allows the Framer to reuse Frames. | ||
404 | // If called on a Framer, Frames returned by calls to ReadFrame are only | ||
405 | // valid until the next call to ReadFrame. | ||
406 | func (fr *Framer) SetReuseFrames() { | ||
407 | if fr.frameCache != nil { | ||
408 | return | ||
409 | } | ||
410 | fr.frameCache = &frameCache{} | ||
411 | } | ||
412 | |||
413 | type frameCache struct { | ||
414 | dataFrame DataFrame | ||
415 | } | ||
416 | |||
417 | func (fc *frameCache) getDataFrame() *DataFrame { | ||
418 | if fc == nil { | ||
419 | return &DataFrame{} | ||
420 | } | ||
421 | return &fc.dataFrame | ||
422 | } | ||
423 | |||
424 | // NewFramer returns a Framer that writes frames to w and reads them from r. | ||
425 | func NewFramer(w io.Writer, r io.Reader) *Framer { | ||
426 | fr := &Framer{ | ||
427 | w: w, | ||
428 | r: r, | ||
429 | logReads: logFrameReads, | ||
430 | logWrites: logFrameWrites, | ||
431 | debugReadLoggerf: log.Printf, | ||
432 | debugWriteLoggerf: log.Printf, | ||
433 | } | ||
434 | fr.getReadBuf = func(size uint32) []byte { | ||
435 | if cap(fr.readBuf) >= int(size) { | ||
436 | return fr.readBuf[:size] | ||
437 | } | ||
438 | fr.readBuf = make([]byte, size) | ||
439 | return fr.readBuf | ||
440 | } | ||
441 | fr.SetMaxReadFrameSize(maxFrameSize) | ||
442 | return fr | ||
443 | } | ||
444 | |||
445 | // SetMaxReadFrameSize sets the maximum size of a frame | ||
446 | // that will be read by a subsequent call to ReadFrame. | ||
447 | // It is the caller's responsibility to advertise this | ||
448 | // limit with a SETTINGS frame. | ||
449 | func (fr *Framer) SetMaxReadFrameSize(v uint32) { | ||
450 | if v > maxFrameSize { | ||
451 | v = maxFrameSize | ||
452 | } | ||
453 | fr.maxReadSize = v | ||
454 | } | ||
455 | |||
456 | // ErrorDetail returns a more detailed error of the last error | ||
457 | // returned by Framer.ReadFrame. For instance, if ReadFrame | ||
458 | // returns a StreamError with code PROTOCOL_ERROR, ErrorDetail | ||
459 | // will say exactly what was invalid. ErrorDetail is not guaranteed | ||
460 | // to return a non-nil value and like the rest of the http2 package, | ||
461 | // its return value is not protected by an API compatibility promise. | ||
462 | // ErrorDetail is reset after the next call to ReadFrame. | ||
463 | func (fr *Framer) ErrorDetail() error { | ||
464 | return fr.errDetail | ||
465 | } | ||
466 | |||
467 | // ErrFrameTooLarge is returned from Framer.ReadFrame when the peer | ||
468 | // sends a frame that is larger than declared with SetMaxReadFrameSize. | ||
469 | var ErrFrameTooLarge = errors.New("http2: frame too large") | ||
470 | |||
471 | // terminalReadFrameError reports whether err is an unrecoverable | ||
472 | // error from ReadFrame and no other frames should be read. | ||
473 | func terminalReadFrameError(err error) bool { | ||
474 | if _, ok := err.(StreamError); ok { | ||
475 | return false | ||
476 | } | ||
477 | return err != nil | ||
478 | } | ||
479 | |||
480 | // ReadFrame reads a single frame. The returned Frame is only valid | ||
481 | // until the next call to ReadFrame. | ||
482 | // | ||
483 | // If the frame is larger than previously set with SetMaxReadFrameSize, the | ||
484 | // returned error is ErrFrameTooLarge. Other errors may be of type | ||
485 | // ConnectionError, StreamError, or anything else from the underlying | ||
486 | // reader. | ||
487 | func (fr *Framer) ReadFrame() (Frame, error) { | ||
488 | fr.errDetail = nil | ||
489 | if fr.lastFrame != nil { | ||
490 | fr.lastFrame.invalidate() | ||
491 | } | ||
492 | fh, err := readFrameHeader(fr.headerBuf[:], fr.r) | ||
493 | if err != nil { | ||
494 | return nil, err | ||
495 | } | ||
496 | if fh.Length > fr.maxReadSize { | ||
497 | return nil, ErrFrameTooLarge | ||
498 | } | ||
499 | payload := fr.getReadBuf(fh.Length) | ||
500 | if _, err := io.ReadFull(fr.r, payload); err != nil { | ||
501 | return nil, err | ||
502 | } | ||
503 | f, err := typeFrameParser(fh.Type)(fr.frameCache, fh, payload) | ||
504 | if err != nil { | ||
505 | if ce, ok := err.(connError); ok { | ||
506 | return nil, fr.connError(ce.Code, ce.Reason) | ||
507 | } | ||
508 | return nil, err | ||
509 | } | ||
510 | if err := fr.checkFrameOrder(f); err != nil { | ||
511 | return nil, err | ||
512 | } | ||
513 | if fr.logReads { | ||
514 | fr.debugReadLoggerf("http2: Framer %p: read %v", fr, summarizeFrame(f)) | ||
515 | } | ||
516 | if fh.Type == FrameHeaders && fr.ReadMetaHeaders != nil { | ||
517 | return fr.readMetaFrame(f.(*HeadersFrame)) | ||
518 | } | ||
519 | return f, nil | ||
520 | } | ||
521 | |||
522 | // connError returns ConnectionError(code) but first | ||
523 | // stashes away a public reason to the caller can optionally relay it | ||
524 | // to the peer before hanging up on them. This might help others debug | ||
525 | // their implementations. | ||
526 | func (fr *Framer) connError(code ErrCode, reason string) error { | ||
527 | fr.errDetail = errors.New(reason) | ||
528 | return ConnectionError(code) | ||
529 | } | ||
530 | |||
531 | // checkFrameOrder reports an error if f is an invalid frame to return | ||
532 | // next from ReadFrame. Mostly it checks whether HEADERS and | ||
533 | // CONTINUATION frames are contiguous. | ||
534 | func (fr *Framer) checkFrameOrder(f Frame) error { | ||
535 | last := fr.lastFrame | ||
536 | fr.lastFrame = f | ||
537 | if fr.AllowIllegalReads { | ||
538 | return nil | ||
539 | } | ||
540 | |||
541 | fh := f.Header() | ||
542 | if fr.lastHeaderStream != 0 { | ||
543 | if fh.Type != FrameContinuation { | ||
544 | return fr.connError(ErrCodeProtocol, | ||
545 | fmt.Sprintf("got %s for stream %d; expected CONTINUATION following %s for stream %d", | ||
546 | fh.Type, fh.StreamID, | ||
547 | last.Header().Type, fr.lastHeaderStream)) | ||
548 | } | ||
549 | if fh.StreamID != fr.lastHeaderStream { | ||
550 | return fr.connError(ErrCodeProtocol, | ||
551 | fmt.Sprintf("got CONTINUATION for stream %d; expected stream %d", | ||
552 | fh.StreamID, fr.lastHeaderStream)) | ||
553 | } | ||
554 | } else if fh.Type == FrameContinuation { | ||
555 | return fr.connError(ErrCodeProtocol, fmt.Sprintf("unexpected CONTINUATION for stream %d", fh.StreamID)) | ||
556 | } | ||
557 | |||
558 | switch fh.Type { | ||
559 | case FrameHeaders, FrameContinuation: | ||
560 | if fh.Flags.Has(FlagHeadersEndHeaders) { | ||
561 | fr.lastHeaderStream = 0 | ||
562 | } else { | ||
563 | fr.lastHeaderStream = fh.StreamID | ||
564 | } | ||
565 | } | ||
566 | |||
567 | return nil | ||
568 | } | ||
569 | |||
570 | // A DataFrame conveys arbitrary, variable-length sequences of octets | ||
571 | // associated with a stream. | ||
572 | // See http://http2.github.io/http2-spec/#rfc.section.6.1 | ||
573 | type DataFrame struct { | ||
574 | FrameHeader | ||
575 | data []byte | ||
576 | } | ||
577 | |||
578 | func (f *DataFrame) StreamEnded() bool { | ||
579 | return f.FrameHeader.Flags.Has(FlagDataEndStream) | ||
580 | } | ||
581 | |||
582 | // Data returns the frame's data octets, not including any padding | ||
583 | // size byte or padding suffix bytes. | ||
584 | // The caller must not retain the returned memory past the next | ||
585 | // call to ReadFrame. | ||
586 | func (f *DataFrame) Data() []byte { | ||
587 | f.checkValid() | ||
588 | return f.data | ||
589 | } | ||
590 | |||
591 | func parseDataFrame(fc *frameCache, fh FrameHeader, payload []byte) (Frame, error) { | ||
592 | if fh.StreamID == 0 { | ||
593 | // DATA frames MUST be associated with a stream. If a | ||
594 | // DATA frame is received whose stream identifier | ||
595 | // field is 0x0, the recipient MUST respond with a | ||
596 | // connection error (Section 5.4.1) of type | ||
597 | // PROTOCOL_ERROR. | ||
598 | return nil, connError{ErrCodeProtocol, "DATA frame with stream ID 0"} | ||
599 | } | ||
600 | f := fc.getDataFrame() | ||
601 | f.FrameHeader = fh | ||
602 | |||
603 | var padSize byte | ||
604 | if fh.Flags.Has(FlagDataPadded) { | ||
605 | var err error | ||
606 | payload, padSize, err = readByte(payload) | ||
607 | if err != nil { | ||
608 | return nil, err | ||
609 | } | ||
610 | } | ||
611 | if int(padSize) > len(payload) { | ||
612 | // If the length of the padding is greater than the | ||
613 | // length of the frame payload, the recipient MUST | ||
614 | // treat this as a connection error. | ||
615 | // Filed: https://github.com/http2/http2-spec/issues/610 | ||
616 | return nil, connError{ErrCodeProtocol, "pad size larger than data payload"} | ||
617 | } | ||
618 | f.data = payload[:len(payload)-int(padSize)] | ||
619 | return f, nil | ||
620 | } | ||
621 | |||
622 | var ( | ||
623 | errStreamID = errors.New("invalid stream ID") | ||
624 | errDepStreamID = errors.New("invalid dependent stream ID") | ||
625 | errPadLength = errors.New("pad length too large") | ||
626 | errPadBytes = errors.New("padding bytes must all be zeros unless AllowIllegalWrites is enabled") | ||
627 | ) | ||
628 | |||
629 | func validStreamIDOrZero(streamID uint32) bool { | ||
630 | return streamID&(1<<31) == 0 | ||
631 | } | ||
632 | |||
633 | func validStreamID(streamID uint32) bool { | ||
634 | return streamID != 0 && streamID&(1<<31) == 0 | ||
635 | } | ||
636 | |||
637 | // WriteData writes a DATA frame. | ||
638 | // | ||
639 | // It will perform exactly one Write to the underlying Writer. | ||
640 | // It is the caller's responsibility not to violate the maximum frame size | ||
641 | // and to not call other Write methods concurrently. | ||
642 | func (f *Framer) WriteData(streamID uint32, endStream bool, data []byte) error { | ||
643 | return f.WriteDataPadded(streamID, endStream, data, nil) | ||
644 | } | ||
645 | |||
646 | // WriteData writes a DATA frame with optional padding. | ||
647 | // | ||
648 | // If pad is nil, the padding bit is not sent. | ||
649 | // The length of pad must not exceed 255 bytes. | ||
650 | // The bytes of pad must all be zero, unless f.AllowIllegalWrites is set. | ||
651 | // | ||
652 | // It will perform exactly one Write to the underlying Writer. | ||
653 | // It is the caller's responsibility not to violate the maximum frame size | ||
654 | // and to not call other Write methods concurrently. | ||
655 | func (f *Framer) WriteDataPadded(streamID uint32, endStream bool, data, pad []byte) error { | ||
656 | if !validStreamID(streamID) && !f.AllowIllegalWrites { | ||
657 | return errStreamID | ||
658 | } | ||
659 | if len(pad) > 0 { | ||
660 | if len(pad) > 255 { | ||
661 | return errPadLength | ||
662 | } | ||
663 | if !f.AllowIllegalWrites { | ||
664 | for _, b := range pad { | ||
665 | if b != 0 { | ||
666 | // "Padding octets MUST be set to zero when sending." | ||
667 | return errPadBytes | ||
668 | } | ||
669 | } | ||
670 | } | ||
671 | } | ||
672 | var flags Flags | ||
673 | if endStream { | ||
674 | flags |= FlagDataEndStream | ||
675 | } | ||
676 | if pad != nil { | ||
677 | flags |= FlagDataPadded | ||
678 | } | ||
679 | f.startWrite(FrameData, flags, streamID) | ||
680 | if pad != nil { | ||
681 | f.wbuf = append(f.wbuf, byte(len(pad))) | ||
682 | } | ||
683 | f.wbuf = append(f.wbuf, data...) | ||
684 | f.wbuf = append(f.wbuf, pad...) | ||
685 | return f.endWrite() | ||
686 | } | ||
687 | |||
688 | // A SettingsFrame conveys configuration parameters that affect how | ||
689 | // endpoints communicate, such as preferences and constraints on peer | ||
690 | // behavior. | ||
691 | // | ||
692 | // See http://http2.github.io/http2-spec/#SETTINGS | ||
693 | type SettingsFrame struct { | ||
694 | FrameHeader | ||
695 | p []byte | ||
696 | } | ||
697 | |||
698 | func parseSettingsFrame(_ *frameCache, fh FrameHeader, p []byte) (Frame, error) { | ||
699 | if fh.Flags.Has(FlagSettingsAck) && fh.Length > 0 { | ||
700 | // When this (ACK 0x1) bit is set, the payload of the | ||
701 | // SETTINGS frame MUST be empty. Receipt of a | ||
702 | // SETTINGS frame with the ACK flag set and a length | ||
703 | // field value other than 0 MUST be treated as a | ||
704 | // connection error (Section 5.4.1) of type | ||
705 | // FRAME_SIZE_ERROR. | ||
706 | return nil, ConnectionError(ErrCodeFrameSize) | ||
707 | } | ||
708 | if fh.StreamID != 0 { | ||
709 | // SETTINGS frames always apply to a connection, | ||
710 | // never a single stream. The stream identifier for a | ||
711 | // SETTINGS frame MUST be zero (0x0). If an endpoint | ||
712 | // receives a SETTINGS frame whose stream identifier | ||
713 | // field is anything other than 0x0, the endpoint MUST | ||
714 | // respond with a connection error (Section 5.4.1) of | ||
715 | // type PROTOCOL_ERROR. | ||
716 | return nil, ConnectionError(ErrCodeProtocol) | ||
717 | } | ||
718 | if len(p)%6 != 0 { | ||
719 | // Expecting even number of 6 byte settings. | ||
720 | return nil, ConnectionError(ErrCodeFrameSize) | ||
721 | } | ||
722 | f := &SettingsFrame{FrameHeader: fh, p: p} | ||
723 | if v, ok := f.Value(SettingInitialWindowSize); ok && v > (1<<31)-1 { | ||
724 | // Values above the maximum flow control window size of 2^31 - 1 MUST | ||
725 | // be treated as a connection error (Section 5.4.1) of type | ||
726 | // FLOW_CONTROL_ERROR. | ||
727 | return nil, ConnectionError(ErrCodeFlowControl) | ||
728 | } | ||
729 | return f, nil | ||
730 | } | ||
731 | |||
732 | func (f *SettingsFrame) IsAck() bool { | ||
733 | return f.FrameHeader.Flags.Has(FlagSettingsAck) | ||
734 | } | ||
735 | |||
736 | func (f *SettingsFrame) Value(s SettingID) (v uint32, ok bool) { | ||
737 | f.checkValid() | ||
738 | buf := f.p | ||
739 | for len(buf) > 0 { | ||
740 | settingID := SettingID(binary.BigEndian.Uint16(buf[:2])) | ||
741 | if settingID == s { | ||
742 | return binary.BigEndian.Uint32(buf[2:6]), true | ||
743 | } | ||
744 | buf = buf[6:] | ||
745 | } | ||
746 | return 0, false | ||
747 | } | ||
748 | |||
749 | // ForeachSetting runs fn for each setting. | ||
750 | // It stops and returns the first error. | ||
751 | func (f *SettingsFrame) ForeachSetting(fn func(Setting) error) error { | ||
752 | f.checkValid() | ||
753 | buf := f.p | ||
754 | for len(buf) > 0 { | ||
755 | if err := fn(Setting{ | ||
756 | SettingID(binary.BigEndian.Uint16(buf[:2])), | ||
757 | binary.BigEndian.Uint32(buf[2:6]), | ||
758 | }); err != nil { | ||
759 | return err | ||
760 | } | ||
761 | buf = buf[6:] | ||
762 | } | ||
763 | return nil | ||
764 | } | ||
765 | |||
766 | // WriteSettings writes a SETTINGS frame with zero or more settings | ||
767 | // specified and the ACK bit not set. | ||
768 | // | ||
769 | // It will perform exactly one Write to the underlying Writer. | ||
770 | // It is the caller's responsibility to not call other Write methods concurrently. | ||
771 | func (f *Framer) WriteSettings(settings ...Setting) error { | ||
772 | f.startWrite(FrameSettings, 0, 0) | ||
773 | for _, s := range settings { | ||
774 | f.writeUint16(uint16(s.ID)) | ||
775 | f.writeUint32(s.Val) | ||
776 | } | ||
777 | return f.endWrite() | ||
778 | } | ||
779 | |||
780 | // WriteSettingsAck writes an empty SETTINGS frame with the ACK bit set. | ||
781 | // | ||
782 | // It will perform exactly one Write to the underlying Writer. | ||
783 | // It is the caller's responsibility to not call other Write methods concurrently. | ||
784 | func (f *Framer) WriteSettingsAck() error { | ||
785 | f.startWrite(FrameSettings, FlagSettingsAck, 0) | ||
786 | return f.endWrite() | ||
787 | } | ||
788 | |||
789 | // A PingFrame is a mechanism for measuring a minimal round trip time | ||
790 | // from the sender, as well as determining whether an idle connection | ||
791 | // is still functional. | ||
792 | // See http://http2.github.io/http2-spec/#rfc.section.6.7 | ||
793 | type PingFrame struct { | ||
794 | FrameHeader | ||
795 | Data [8]byte | ||
796 | } | ||
797 | |||
798 | func (f *PingFrame) IsAck() bool { return f.Flags.Has(FlagPingAck) } | ||
799 | |||
800 | func parsePingFrame(_ *frameCache, fh FrameHeader, payload []byte) (Frame, error) { | ||
801 | if len(payload) != 8 { | ||
802 | return nil, ConnectionError(ErrCodeFrameSize) | ||
803 | } | ||
804 | if fh.StreamID != 0 { | ||
805 | return nil, ConnectionError(ErrCodeProtocol) | ||
806 | } | ||
807 | f := &PingFrame{FrameHeader: fh} | ||
808 | copy(f.Data[:], payload) | ||
809 | return f, nil | ||
810 | } | ||
811 | |||
812 | func (f *Framer) WritePing(ack bool, data [8]byte) error { | ||
813 | var flags Flags | ||
814 | if ack { | ||
815 | flags = FlagPingAck | ||
816 | } | ||
817 | f.startWrite(FramePing, flags, 0) | ||
818 | f.writeBytes(data[:]) | ||
819 | return f.endWrite() | ||
820 | } | ||
821 | |||
822 | // A GoAwayFrame informs the remote peer to stop creating streams on this connection. | ||
823 | // See http://http2.github.io/http2-spec/#rfc.section.6.8 | ||
824 | type GoAwayFrame struct { | ||
825 | FrameHeader | ||
826 | LastStreamID uint32 | ||
827 | ErrCode ErrCode | ||
828 | debugData []byte | ||
829 | } | ||
830 | |||
831 | // DebugData returns any debug data in the GOAWAY frame. Its contents | ||
832 | // are not defined. | ||
833 | // The caller must not retain the returned memory past the next | ||
834 | // call to ReadFrame. | ||
835 | func (f *GoAwayFrame) DebugData() []byte { | ||
836 | f.checkValid() | ||
837 | return f.debugData | ||
838 | } | ||
839 | |||
840 | func parseGoAwayFrame(_ *frameCache, fh FrameHeader, p []byte) (Frame, error) { | ||
841 | if fh.StreamID != 0 { | ||
842 | return nil, ConnectionError(ErrCodeProtocol) | ||
843 | } | ||
844 | if len(p) < 8 { | ||
845 | return nil, ConnectionError(ErrCodeFrameSize) | ||
846 | } | ||
847 | return &GoAwayFrame{ | ||
848 | FrameHeader: fh, | ||
849 | LastStreamID: binary.BigEndian.Uint32(p[:4]) & (1<<31 - 1), | ||
850 | ErrCode: ErrCode(binary.BigEndian.Uint32(p[4:8])), | ||
851 | debugData: p[8:], | ||
852 | }, nil | ||
853 | } | ||
854 | |||
855 | func (f *Framer) WriteGoAway(maxStreamID uint32, code ErrCode, debugData []byte) error { | ||
856 | f.startWrite(FrameGoAway, 0, 0) | ||
857 | f.writeUint32(maxStreamID & (1<<31 - 1)) | ||
858 | f.writeUint32(uint32(code)) | ||
859 | f.writeBytes(debugData) | ||
860 | return f.endWrite() | ||
861 | } | ||
862 | |||
863 | // An UnknownFrame is the frame type returned when the frame type is unknown | ||
864 | // or no specific frame type parser exists. | ||
865 | type UnknownFrame struct { | ||
866 | FrameHeader | ||
867 | p []byte | ||
868 | } | ||
869 | |||
870 | // Payload returns the frame's payload (after the header). It is not | ||
871 | // valid to call this method after a subsequent call to | ||
872 | // Framer.ReadFrame, nor is it valid to retain the returned slice. | ||
873 | // The memory is owned by the Framer and is invalidated when the next | ||
874 | // frame is read. | ||
875 | func (f *UnknownFrame) Payload() []byte { | ||
876 | f.checkValid() | ||
877 | return f.p | ||
878 | } | ||
879 | |||
880 | func parseUnknownFrame(_ *frameCache, fh FrameHeader, p []byte) (Frame, error) { | ||
881 | return &UnknownFrame{fh, p}, nil | ||
882 | } | ||
883 | |||
884 | // A WindowUpdateFrame is used to implement flow control. | ||
885 | // See http://http2.github.io/http2-spec/#rfc.section.6.9 | ||
886 | type WindowUpdateFrame struct { | ||
887 | FrameHeader | ||
888 | Increment uint32 // never read with high bit set | ||
889 | } | ||
890 | |||
891 | func parseWindowUpdateFrame(_ *frameCache, fh FrameHeader, p []byte) (Frame, error) { | ||
892 | if len(p) != 4 { | ||
893 | return nil, ConnectionError(ErrCodeFrameSize) | ||
894 | } | ||
895 | inc := binary.BigEndian.Uint32(p[:4]) & 0x7fffffff // mask off high reserved bit | ||
896 | if inc == 0 { | ||
897 | // A receiver MUST treat the receipt of a | ||
898 | // WINDOW_UPDATE frame with an flow control window | ||
899 | // increment of 0 as a stream error (Section 5.4.2) of | ||
900 | // type PROTOCOL_ERROR; errors on the connection flow | ||
901 | // control window MUST be treated as a connection | ||
902 | // error (Section 5.4.1). | ||
903 | if fh.StreamID == 0 { | ||
904 | return nil, ConnectionError(ErrCodeProtocol) | ||
905 | } | ||
906 | return nil, streamError(fh.StreamID, ErrCodeProtocol) | ||
907 | } | ||
908 | return &WindowUpdateFrame{ | ||
909 | FrameHeader: fh, | ||
910 | Increment: inc, | ||
911 | }, nil | ||
912 | } | ||
913 | |||
914 | // WriteWindowUpdate writes a WINDOW_UPDATE frame. | ||
915 | // The increment value must be between 1 and 2,147,483,647, inclusive. | ||
916 | // If the Stream ID is zero, the window update applies to the | ||
917 | // connection as a whole. | ||
918 | func (f *Framer) WriteWindowUpdate(streamID, incr uint32) error { | ||
919 | // "The legal range for the increment to the flow control window is 1 to 2^31-1 (2,147,483,647) octets." | ||
920 | if (incr < 1 || incr > 2147483647) && !f.AllowIllegalWrites { | ||
921 | return errors.New("illegal window increment value") | ||
922 | } | ||
923 | f.startWrite(FrameWindowUpdate, 0, streamID) | ||
924 | f.writeUint32(incr) | ||
925 | return f.endWrite() | ||
926 | } | ||
927 | |||
928 | // A HeadersFrame is used to open a stream and additionally carries a | ||
929 | // header block fragment. | ||
930 | type HeadersFrame struct { | ||
931 | FrameHeader | ||
932 | |||
933 | // Priority is set if FlagHeadersPriority is set in the FrameHeader. | ||
934 | Priority PriorityParam | ||
935 | |||
936 | headerFragBuf []byte // not owned | ||
937 | } | ||
938 | |||
939 | func (f *HeadersFrame) HeaderBlockFragment() []byte { | ||
940 | f.checkValid() | ||
941 | return f.headerFragBuf | ||
942 | } | ||
943 | |||
944 | func (f *HeadersFrame) HeadersEnded() bool { | ||
945 | return f.FrameHeader.Flags.Has(FlagHeadersEndHeaders) | ||
946 | } | ||
947 | |||
948 | func (f *HeadersFrame) StreamEnded() bool { | ||
949 | return f.FrameHeader.Flags.Has(FlagHeadersEndStream) | ||
950 | } | ||
951 | |||
952 | func (f *HeadersFrame) HasPriority() bool { | ||
953 | return f.FrameHeader.Flags.Has(FlagHeadersPriority) | ||
954 | } | ||
955 | |||
956 | func parseHeadersFrame(_ *frameCache, fh FrameHeader, p []byte) (_ Frame, err error) { | ||
957 | hf := &HeadersFrame{ | ||
958 | FrameHeader: fh, | ||
959 | } | ||
960 | if fh.StreamID == 0 { | ||
961 | // HEADERS frames MUST be associated with a stream. If a HEADERS frame | ||
962 | // is received whose stream identifier field is 0x0, the recipient MUST | ||
963 | // respond with a connection error (Section 5.4.1) of type | ||
964 | // PROTOCOL_ERROR. | ||
965 | return nil, connError{ErrCodeProtocol, "HEADERS frame with stream ID 0"} | ||
966 | } | ||
967 | var padLength uint8 | ||
968 | if fh.Flags.Has(FlagHeadersPadded) { | ||
969 | if p, padLength, err = readByte(p); err != nil { | ||
970 | return | ||
971 | } | ||
972 | } | ||
973 | if fh.Flags.Has(FlagHeadersPriority) { | ||
974 | var v uint32 | ||
975 | p, v, err = readUint32(p) | ||
976 | if err != nil { | ||
977 | return nil, err | ||
978 | } | ||
979 | hf.Priority.StreamDep = v & 0x7fffffff | ||
980 | hf.Priority.Exclusive = (v != hf.Priority.StreamDep) // high bit was set | ||
981 | p, hf.Priority.Weight, err = readByte(p) | ||
982 | if err != nil { | ||
983 | return nil, err | ||
984 | } | ||
985 | } | ||
986 | if len(p)-int(padLength) <= 0 { | ||
987 | return nil, streamError(fh.StreamID, ErrCodeProtocol) | ||
988 | } | ||
989 | hf.headerFragBuf = p[:len(p)-int(padLength)] | ||
990 | return hf, nil | ||
991 | } | ||
992 | |||
993 | // HeadersFrameParam are the parameters for writing a HEADERS frame. | ||
994 | type HeadersFrameParam struct { | ||
995 | // StreamID is the required Stream ID to initiate. | ||
996 | StreamID uint32 | ||
997 | // BlockFragment is part (or all) of a Header Block. | ||
998 | BlockFragment []byte | ||
999 | |||
1000 | // EndStream indicates that the header block is the last that | ||
1001 | // the endpoint will send for the identified stream. Setting | ||
1002 | // this flag causes the stream to enter one of "half closed" | ||
1003 | // states. | ||
1004 | EndStream bool | ||
1005 | |||
1006 | // EndHeaders indicates that this frame contains an entire | ||
1007 | // header block and is not followed by any | ||
1008 | // CONTINUATION frames. | ||
1009 | EndHeaders bool | ||
1010 | |||
1011 | // PadLength is the optional number of bytes of zeros to add | ||
1012 | // to this frame. | ||
1013 | PadLength uint8 | ||
1014 | |||
1015 | // Priority, if non-zero, includes stream priority information | ||
1016 | // in the HEADER frame. | ||
1017 | Priority PriorityParam | ||
1018 | } | ||
1019 | |||
1020 | // WriteHeaders writes a single HEADERS frame. | ||
1021 | // | ||
1022 | // This is a low-level header writing method. Encoding headers and | ||
1023 | // splitting them into any necessary CONTINUATION frames is handled | ||
1024 | // elsewhere. | ||
1025 | // | ||
1026 | // It will perform exactly one Write to the underlying Writer. | ||
1027 | // It is the caller's responsibility to not call other Write methods concurrently. | ||
1028 | func (f *Framer) WriteHeaders(p HeadersFrameParam) error { | ||
1029 | if !validStreamID(p.StreamID) && !f.AllowIllegalWrites { | ||
1030 | return errStreamID | ||
1031 | } | ||
1032 | var flags Flags | ||
1033 | if p.PadLength != 0 { | ||
1034 | flags |= FlagHeadersPadded | ||
1035 | } | ||
1036 | if p.EndStream { | ||
1037 | flags |= FlagHeadersEndStream | ||
1038 | } | ||
1039 | if p.EndHeaders { | ||
1040 | flags |= FlagHeadersEndHeaders | ||
1041 | } | ||
1042 | if !p.Priority.IsZero() { | ||
1043 | flags |= FlagHeadersPriority | ||
1044 | } | ||
1045 | f.startWrite(FrameHeaders, flags, p.StreamID) | ||
1046 | if p.PadLength != 0 { | ||
1047 | f.writeByte(p.PadLength) | ||
1048 | } | ||
1049 | if !p.Priority.IsZero() { | ||
1050 | v := p.Priority.StreamDep | ||
1051 | if !validStreamIDOrZero(v) && !f.AllowIllegalWrites { | ||
1052 | return errDepStreamID | ||
1053 | } | ||
1054 | if p.Priority.Exclusive { | ||
1055 | v |= 1 << 31 | ||
1056 | } | ||
1057 | f.writeUint32(v) | ||
1058 | f.writeByte(p.Priority.Weight) | ||
1059 | } | ||
1060 | f.wbuf = append(f.wbuf, p.BlockFragment...) | ||
1061 | f.wbuf = append(f.wbuf, padZeros[:p.PadLength]...) | ||
1062 | return f.endWrite() | ||
1063 | } | ||
1064 | |||
1065 | // A PriorityFrame specifies the sender-advised priority of a stream. | ||
1066 | // See http://http2.github.io/http2-spec/#rfc.section.6.3 | ||
1067 | type PriorityFrame struct { | ||
1068 | FrameHeader | ||
1069 | PriorityParam | ||
1070 | } | ||
1071 | |||
1072 | // PriorityParam are the stream prioritzation parameters. | ||
1073 | type PriorityParam struct { | ||
1074 | // StreamDep is a 31-bit stream identifier for the | ||
1075 | // stream that this stream depends on. Zero means no | ||
1076 | // dependency. | ||
1077 | StreamDep uint32 | ||
1078 | |||
1079 | // Exclusive is whether the dependency is exclusive. | ||
1080 | Exclusive bool | ||
1081 | |||
1082 | // Weight is the stream's zero-indexed weight. It should be | ||
1083 | // set together with StreamDep, or neither should be set. Per | ||
1084 | // the spec, "Add one to the value to obtain a weight between | ||
1085 | // 1 and 256." | ||
1086 | Weight uint8 | ||
1087 | } | ||
1088 | |||
1089 | func (p PriorityParam) IsZero() bool { | ||
1090 | return p == PriorityParam{} | ||
1091 | } | ||
1092 | |||
1093 | func parsePriorityFrame(_ *frameCache, fh FrameHeader, payload []byte) (Frame, error) { | ||
1094 | if fh.StreamID == 0 { | ||
1095 | return nil, connError{ErrCodeProtocol, "PRIORITY frame with stream ID 0"} | ||
1096 | } | ||
1097 | if len(payload) != 5 { | ||
1098 | return nil, connError{ErrCodeFrameSize, fmt.Sprintf("PRIORITY frame payload size was %d; want 5", len(payload))} | ||
1099 | } | ||
1100 | v := binary.BigEndian.Uint32(payload[:4]) | ||
1101 | streamID := v & 0x7fffffff // mask off high bit | ||
1102 | return &PriorityFrame{ | ||
1103 | FrameHeader: fh, | ||
1104 | PriorityParam: PriorityParam{ | ||
1105 | Weight: payload[4], | ||
1106 | StreamDep: streamID, | ||
1107 | Exclusive: streamID != v, // was high bit set? | ||
1108 | }, | ||
1109 | }, nil | ||
1110 | } | ||
1111 | |||
1112 | // WritePriority writes a PRIORITY frame. | ||
1113 | // | ||
1114 | // It will perform exactly one Write to the underlying Writer. | ||
1115 | // It is the caller's responsibility to not call other Write methods concurrently. | ||
1116 | func (f *Framer) WritePriority(streamID uint32, p PriorityParam) error { | ||
1117 | if !validStreamID(streamID) && !f.AllowIllegalWrites { | ||
1118 | return errStreamID | ||
1119 | } | ||
1120 | if !validStreamIDOrZero(p.StreamDep) { | ||
1121 | return errDepStreamID | ||
1122 | } | ||
1123 | f.startWrite(FramePriority, 0, streamID) | ||
1124 | v := p.StreamDep | ||
1125 | if p.Exclusive { | ||
1126 | v |= 1 << 31 | ||
1127 | } | ||
1128 | f.writeUint32(v) | ||
1129 | f.writeByte(p.Weight) | ||
1130 | return f.endWrite() | ||
1131 | } | ||
1132 | |||
1133 | // A RSTStreamFrame allows for abnormal termination of a stream. | ||
1134 | // See http://http2.github.io/http2-spec/#rfc.section.6.4 | ||
1135 | type RSTStreamFrame struct { | ||
1136 | FrameHeader | ||
1137 | ErrCode ErrCode | ||
1138 | } | ||
1139 | |||
1140 | func parseRSTStreamFrame(_ *frameCache, fh FrameHeader, p []byte) (Frame, error) { | ||
1141 | if len(p) != 4 { | ||
1142 | return nil, ConnectionError(ErrCodeFrameSize) | ||
1143 | } | ||
1144 | if fh.StreamID == 0 { | ||
1145 | return nil, ConnectionError(ErrCodeProtocol) | ||
1146 | } | ||
1147 | return &RSTStreamFrame{fh, ErrCode(binary.BigEndian.Uint32(p[:4]))}, nil | ||
1148 | } | ||
1149 | |||
1150 | // WriteRSTStream writes a RST_STREAM frame. | ||
1151 | // | ||
1152 | // It will perform exactly one Write to the underlying Writer. | ||
1153 | // It is the caller's responsibility to not call other Write methods concurrently. | ||
1154 | func (f *Framer) WriteRSTStream(streamID uint32, code ErrCode) error { | ||
1155 | if !validStreamID(streamID) && !f.AllowIllegalWrites { | ||
1156 | return errStreamID | ||
1157 | } | ||
1158 | f.startWrite(FrameRSTStream, 0, streamID) | ||
1159 | f.writeUint32(uint32(code)) | ||
1160 | return f.endWrite() | ||
1161 | } | ||
1162 | |||
1163 | // A ContinuationFrame is used to continue a sequence of header block fragments. | ||
1164 | // See http://http2.github.io/http2-spec/#rfc.section.6.10 | ||
1165 | type ContinuationFrame struct { | ||
1166 | FrameHeader | ||
1167 | headerFragBuf []byte | ||
1168 | } | ||
1169 | |||
1170 | func parseContinuationFrame(_ *frameCache, fh FrameHeader, p []byte) (Frame, error) { | ||
1171 | if fh.StreamID == 0 { | ||
1172 | return nil, connError{ErrCodeProtocol, "CONTINUATION frame with stream ID 0"} | ||
1173 | } | ||
1174 | return &ContinuationFrame{fh, p}, nil | ||
1175 | } | ||
1176 | |||
1177 | func (f *ContinuationFrame) HeaderBlockFragment() []byte { | ||
1178 | f.checkValid() | ||
1179 | return f.headerFragBuf | ||
1180 | } | ||
1181 | |||
1182 | func (f *ContinuationFrame) HeadersEnded() bool { | ||
1183 | return f.FrameHeader.Flags.Has(FlagContinuationEndHeaders) | ||
1184 | } | ||
1185 | |||
1186 | // WriteContinuation writes a CONTINUATION frame. | ||
1187 | // | ||
1188 | // It will perform exactly one Write to the underlying Writer. | ||
1189 | // It is the caller's responsibility to not call other Write methods concurrently. | ||
1190 | func (f *Framer) WriteContinuation(streamID uint32, endHeaders bool, headerBlockFragment []byte) error { | ||
1191 | if !validStreamID(streamID) && !f.AllowIllegalWrites { | ||
1192 | return errStreamID | ||
1193 | } | ||
1194 | var flags Flags | ||
1195 | if endHeaders { | ||
1196 | flags |= FlagContinuationEndHeaders | ||
1197 | } | ||
1198 | f.startWrite(FrameContinuation, flags, streamID) | ||
1199 | f.wbuf = append(f.wbuf, headerBlockFragment...) | ||
1200 | return f.endWrite() | ||
1201 | } | ||
1202 | |||
1203 | // A PushPromiseFrame is used to initiate a server stream. | ||
1204 | // See http://http2.github.io/http2-spec/#rfc.section.6.6 | ||
1205 | type PushPromiseFrame struct { | ||
1206 | FrameHeader | ||
1207 | PromiseID uint32 | ||
1208 | headerFragBuf []byte // not owned | ||
1209 | } | ||
1210 | |||
1211 | func (f *PushPromiseFrame) HeaderBlockFragment() []byte { | ||
1212 | f.checkValid() | ||
1213 | return f.headerFragBuf | ||
1214 | } | ||
1215 | |||
1216 | func (f *PushPromiseFrame) HeadersEnded() bool { | ||
1217 | return f.FrameHeader.Flags.Has(FlagPushPromiseEndHeaders) | ||
1218 | } | ||
1219 | |||
1220 | func parsePushPromise(_ *frameCache, fh FrameHeader, p []byte) (_ Frame, err error) { | ||
1221 | pp := &PushPromiseFrame{ | ||
1222 | FrameHeader: fh, | ||
1223 | } | ||
1224 | if pp.StreamID == 0 { | ||
1225 | // PUSH_PROMISE frames MUST be associated with an existing, | ||
1226 | // peer-initiated stream. The stream identifier of a | ||
1227 | // PUSH_PROMISE frame indicates the stream it is associated | ||
1228 | // with. If the stream identifier field specifies the value | ||
1229 | // 0x0, a recipient MUST respond with a connection error | ||
1230 | // (Section 5.4.1) of type PROTOCOL_ERROR. | ||
1231 | return nil, ConnectionError(ErrCodeProtocol) | ||
1232 | } | ||
1233 | // The PUSH_PROMISE frame includes optional padding. | ||
1234 | // Padding fields and flags are identical to those defined for DATA frames | ||
1235 | var padLength uint8 | ||
1236 | if fh.Flags.Has(FlagPushPromisePadded) { | ||
1237 | if p, padLength, err = readByte(p); err != nil { | ||
1238 | return | ||
1239 | } | ||
1240 | } | ||
1241 | |||
1242 | p, pp.PromiseID, err = readUint32(p) | ||
1243 | if err != nil { | ||
1244 | return | ||
1245 | } | ||
1246 | pp.PromiseID = pp.PromiseID & (1<<31 - 1) | ||
1247 | |||
1248 | if int(padLength) > len(p) { | ||
1249 | // like the DATA frame, error out if padding is longer than the body. | ||
1250 | return nil, ConnectionError(ErrCodeProtocol) | ||
1251 | } | ||
1252 | pp.headerFragBuf = p[:len(p)-int(padLength)] | ||
1253 | return pp, nil | ||
1254 | } | ||
1255 | |||
1256 | // PushPromiseParam are the parameters for writing a PUSH_PROMISE frame. | ||
1257 | type PushPromiseParam struct { | ||
1258 | // StreamID is the required Stream ID to initiate. | ||
1259 | StreamID uint32 | ||
1260 | |||
1261 | // PromiseID is the required Stream ID which this | ||
1262 | // Push Promises | ||
1263 | PromiseID uint32 | ||
1264 | |||
1265 | // BlockFragment is part (or all) of a Header Block. | ||
1266 | BlockFragment []byte | ||
1267 | |||
1268 | // EndHeaders indicates that this frame contains an entire | ||
1269 | // header block and is not followed by any | ||
1270 | // CONTINUATION frames. | ||
1271 | EndHeaders bool | ||
1272 | |||
1273 | // PadLength is the optional number of bytes of zeros to add | ||
1274 | // to this frame. | ||
1275 | PadLength uint8 | ||
1276 | } | ||
1277 | |||
1278 | // WritePushPromise writes a single PushPromise Frame. | ||
1279 | // | ||
1280 | // As with Header Frames, This is the low level call for writing | ||
1281 | // individual frames. Continuation frames are handled elsewhere. | ||
1282 | // | ||
1283 | // It will perform exactly one Write to the underlying Writer. | ||
1284 | // It is the caller's responsibility to not call other Write methods concurrently. | ||
1285 | func (f *Framer) WritePushPromise(p PushPromiseParam) error { | ||
1286 | if !validStreamID(p.StreamID) && !f.AllowIllegalWrites { | ||
1287 | return errStreamID | ||
1288 | } | ||
1289 | var flags Flags | ||
1290 | if p.PadLength != 0 { | ||
1291 | flags |= FlagPushPromisePadded | ||
1292 | } | ||
1293 | if p.EndHeaders { | ||
1294 | flags |= FlagPushPromiseEndHeaders | ||
1295 | } | ||
1296 | f.startWrite(FramePushPromise, flags, p.StreamID) | ||
1297 | if p.PadLength != 0 { | ||
1298 | f.writeByte(p.PadLength) | ||
1299 | } | ||
1300 | if !validStreamID(p.PromiseID) && !f.AllowIllegalWrites { | ||
1301 | return errStreamID | ||
1302 | } | ||
1303 | f.writeUint32(p.PromiseID) | ||
1304 | f.wbuf = append(f.wbuf, p.BlockFragment...) | ||
1305 | f.wbuf = append(f.wbuf, padZeros[:p.PadLength]...) | ||
1306 | return f.endWrite() | ||
1307 | } | ||
1308 | |||
1309 | // WriteRawFrame writes a raw frame. This can be used to write | ||
1310 | // extension frames unknown to this package. | ||
1311 | func (f *Framer) WriteRawFrame(t FrameType, flags Flags, streamID uint32, payload []byte) error { | ||
1312 | f.startWrite(t, flags, streamID) | ||
1313 | f.writeBytes(payload) | ||
1314 | return f.endWrite() | ||
1315 | } | ||
1316 | |||
1317 | func readByte(p []byte) (remain []byte, b byte, err error) { | ||
1318 | if len(p) == 0 { | ||
1319 | return nil, 0, io.ErrUnexpectedEOF | ||
1320 | } | ||
1321 | return p[1:], p[0], nil | ||
1322 | } | ||
1323 | |||
1324 | func readUint32(p []byte) (remain []byte, v uint32, err error) { | ||
1325 | if len(p) < 4 { | ||
1326 | return nil, 0, io.ErrUnexpectedEOF | ||
1327 | } | ||
1328 | return p[4:], binary.BigEndian.Uint32(p[:4]), nil | ||
1329 | } | ||
1330 | |||
1331 | type streamEnder interface { | ||
1332 | StreamEnded() bool | ||
1333 | } | ||
1334 | |||
1335 | type headersEnder interface { | ||
1336 | HeadersEnded() bool | ||
1337 | } | ||
1338 | |||
1339 | type headersOrContinuation interface { | ||
1340 | headersEnder | ||
1341 | HeaderBlockFragment() []byte | ||
1342 | } | ||
1343 | |||
1344 | // A MetaHeadersFrame is the representation of one HEADERS frame and | ||
1345 | // zero or more contiguous CONTINUATION frames and the decoding of | ||
1346 | // their HPACK-encoded contents. | ||
1347 | // | ||
1348 | // This type of frame does not appear on the wire and is only returned | ||
1349 | // by the Framer when Framer.ReadMetaHeaders is set. | ||
1350 | type MetaHeadersFrame struct { | ||
1351 | *HeadersFrame | ||
1352 | |||
1353 | // Fields are the fields contained in the HEADERS and | ||
1354 | // CONTINUATION frames. The underlying slice is owned by the | ||
1355 | // Framer and must not be retained after the next call to | ||
1356 | // ReadFrame. | ||
1357 | // | ||
1358 | // Fields are guaranteed to be in the correct http2 order and | ||
1359 | // not have unknown pseudo header fields or invalid header | ||
1360 | // field names or values. Required pseudo header fields may be | ||
1361 | // missing, however. Use the MetaHeadersFrame.Pseudo accessor | ||
1362 | // method access pseudo headers. | ||
1363 | Fields []hpack.HeaderField | ||
1364 | |||
1365 | // Truncated is whether the max header list size limit was hit | ||
1366 | // and Fields is incomplete. The hpack decoder state is still | ||
1367 | // valid, however. | ||
1368 | Truncated bool | ||
1369 | } | ||
1370 | |||
1371 | // PseudoValue returns the given pseudo header field's value. | ||
1372 | // The provided pseudo field should not contain the leading colon. | ||
1373 | func (mh *MetaHeadersFrame) PseudoValue(pseudo string) string { | ||
1374 | for _, hf := range mh.Fields { | ||
1375 | if !hf.IsPseudo() { | ||
1376 | return "" | ||
1377 | } | ||
1378 | if hf.Name[1:] == pseudo { | ||
1379 | return hf.Value | ||
1380 | } | ||
1381 | } | ||
1382 | return "" | ||
1383 | } | ||
1384 | |||
1385 | // RegularFields returns the regular (non-pseudo) header fields of mh. | ||
1386 | // The caller does not own the returned slice. | ||
1387 | func (mh *MetaHeadersFrame) RegularFields() []hpack.HeaderField { | ||
1388 | for i, hf := range mh.Fields { | ||
1389 | if !hf.IsPseudo() { | ||
1390 | return mh.Fields[i:] | ||
1391 | } | ||
1392 | } | ||
1393 | return nil | ||
1394 | } | ||
1395 | |||
1396 | // PseudoFields returns the pseudo header fields of mh. | ||
1397 | // The caller does not own the returned slice. | ||
1398 | func (mh *MetaHeadersFrame) PseudoFields() []hpack.HeaderField { | ||
1399 | for i, hf := range mh.Fields { | ||
1400 | if !hf.IsPseudo() { | ||
1401 | return mh.Fields[:i] | ||
1402 | } | ||
1403 | } | ||
1404 | return mh.Fields | ||
1405 | } | ||
1406 | |||
1407 | func (mh *MetaHeadersFrame) checkPseudos() error { | ||
1408 | var isRequest, isResponse bool | ||
1409 | pf := mh.PseudoFields() | ||
1410 | for i, hf := range pf { | ||
1411 | switch hf.Name { | ||
1412 | case ":method", ":path", ":scheme", ":authority": | ||
1413 | isRequest = true | ||
1414 | case ":status": | ||
1415 | isResponse = true | ||
1416 | default: | ||
1417 | return pseudoHeaderError(hf.Name) | ||
1418 | } | ||
1419 | // Check for duplicates. | ||
1420 | // This would be a bad algorithm, but N is 4. | ||
1421 | // And this doesn't allocate. | ||
1422 | for _, hf2 := range pf[:i] { | ||
1423 | if hf.Name == hf2.Name { | ||
1424 | return duplicatePseudoHeaderError(hf.Name) | ||
1425 | } | ||
1426 | } | ||
1427 | } | ||
1428 | if isRequest && isResponse { | ||
1429 | return errMixPseudoHeaderTypes | ||
1430 | } | ||
1431 | return nil | ||
1432 | } | ||
1433 | |||
1434 | func (fr *Framer) maxHeaderStringLen() int { | ||
1435 | v := fr.maxHeaderListSize() | ||
1436 | if uint32(int(v)) == v { | ||
1437 | return int(v) | ||
1438 | } | ||
1439 | // They had a crazy big number for MaxHeaderBytes anyway, | ||
1440 | // so give them unlimited header lengths: | ||
1441 | return 0 | ||
1442 | } | ||
1443 | |||
1444 | // readMetaFrame returns 0 or more CONTINUATION frames from fr and | ||
1445 | // merge them into into the provided hf and returns a MetaHeadersFrame | ||
1446 | // with the decoded hpack values. | ||
1447 | func (fr *Framer) readMetaFrame(hf *HeadersFrame) (*MetaHeadersFrame, error) { | ||
1448 | if fr.AllowIllegalReads { | ||
1449 | return nil, errors.New("illegal use of AllowIllegalReads with ReadMetaHeaders") | ||
1450 | } | ||
1451 | mh := &MetaHeadersFrame{ | ||
1452 | HeadersFrame: hf, | ||
1453 | } | ||
1454 | var remainSize = fr.maxHeaderListSize() | ||
1455 | var sawRegular bool | ||
1456 | |||
1457 | var invalid error // pseudo header field errors | ||
1458 | hdec := fr.ReadMetaHeaders | ||
1459 | hdec.SetEmitEnabled(true) | ||
1460 | hdec.SetMaxStringLength(fr.maxHeaderStringLen()) | ||
1461 | hdec.SetEmitFunc(func(hf hpack.HeaderField) { | ||
1462 | if VerboseLogs && fr.logReads { | ||
1463 | fr.debugReadLoggerf("http2: decoded hpack field %+v", hf) | ||
1464 | } | ||
1465 | if !httplex.ValidHeaderFieldValue(hf.Value) { | ||
1466 | invalid = headerFieldValueError(hf.Value) | ||
1467 | } | ||
1468 | isPseudo := strings.HasPrefix(hf.Name, ":") | ||
1469 | if isPseudo { | ||
1470 | if sawRegular { | ||
1471 | invalid = errPseudoAfterRegular | ||
1472 | } | ||
1473 | } else { | ||
1474 | sawRegular = true | ||
1475 | if !validWireHeaderFieldName(hf.Name) { | ||
1476 | invalid = headerFieldNameError(hf.Name) | ||
1477 | } | ||
1478 | } | ||
1479 | |||
1480 | if invalid != nil { | ||
1481 | hdec.SetEmitEnabled(false) | ||
1482 | return | ||
1483 | } | ||
1484 | |||
1485 | size := hf.Size() | ||
1486 | if size > remainSize { | ||
1487 | hdec.SetEmitEnabled(false) | ||
1488 | mh.Truncated = true | ||
1489 | return | ||
1490 | } | ||
1491 | remainSize -= size | ||
1492 | |||
1493 | mh.Fields = append(mh.Fields, hf) | ||
1494 | }) | ||
1495 | // Lose reference to MetaHeadersFrame: | ||
1496 | defer hdec.SetEmitFunc(func(hf hpack.HeaderField) {}) | ||
1497 | |||
1498 | var hc headersOrContinuation = hf | ||
1499 | for { | ||
1500 | frag := hc.HeaderBlockFragment() | ||
1501 | if _, err := hdec.Write(frag); err != nil { | ||
1502 | return nil, ConnectionError(ErrCodeCompression) | ||
1503 | } | ||
1504 | |||
1505 | if hc.HeadersEnded() { | ||
1506 | break | ||
1507 | } | ||
1508 | if f, err := fr.ReadFrame(); err != nil { | ||
1509 | return nil, err | ||
1510 | } else { | ||
1511 | hc = f.(*ContinuationFrame) // guaranteed by checkFrameOrder | ||
1512 | } | ||
1513 | } | ||
1514 | |||
1515 | mh.HeadersFrame.headerFragBuf = nil | ||
1516 | mh.HeadersFrame.invalidate() | ||
1517 | |||
1518 | if err := hdec.Close(); err != nil { | ||
1519 | return nil, ConnectionError(ErrCodeCompression) | ||
1520 | } | ||
1521 | if invalid != nil { | ||
1522 | fr.errDetail = invalid | ||
1523 | if VerboseLogs { | ||
1524 | log.Printf("http2: invalid header: %v", invalid) | ||
1525 | } | ||
1526 | return nil, StreamError{mh.StreamID, ErrCodeProtocol, invalid} | ||
1527 | } | ||
1528 | if err := mh.checkPseudos(); err != nil { | ||
1529 | fr.errDetail = err | ||
1530 | if VerboseLogs { | ||
1531 | log.Printf("http2: invalid pseudo headers: %v", err) | ||
1532 | } | ||
1533 | return nil, StreamError{mh.StreamID, ErrCodeProtocol, err} | ||
1534 | } | ||
1535 | return mh, nil | ||
1536 | } | ||
1537 | |||
1538 | func summarizeFrame(f Frame) string { | ||
1539 | var buf bytes.Buffer | ||
1540 | f.Header().writeDebug(&buf) | ||
1541 | switch f := f.(type) { | ||
1542 | case *SettingsFrame: | ||
1543 | n := 0 | ||
1544 | f.ForeachSetting(func(s Setting) error { | ||
1545 | n++ | ||
1546 | if n == 1 { | ||
1547 | buf.WriteString(", settings:") | ||
1548 | } | ||
1549 | fmt.Fprintf(&buf, " %v=%v,", s.ID, s.Val) | ||
1550 | return nil | ||
1551 | }) | ||
1552 | if n > 0 { | ||
1553 | buf.Truncate(buf.Len() - 1) // remove trailing comma | ||
1554 | } | ||
1555 | case *DataFrame: | ||
1556 | data := f.Data() | ||
1557 | const max = 256 | ||
1558 | if len(data) > max { | ||
1559 | data = data[:max] | ||
1560 | } | ||
1561 | fmt.Fprintf(&buf, " data=%q", data) | ||
1562 | if len(f.Data()) > max { | ||
1563 | fmt.Fprintf(&buf, " (%d bytes omitted)", len(f.Data())-max) | ||
1564 | } | ||
1565 | case *WindowUpdateFrame: | ||
1566 | if f.StreamID == 0 { | ||
1567 | buf.WriteString(" (conn)") | ||
1568 | } | ||
1569 | fmt.Fprintf(&buf, " incr=%v", f.Increment) | ||
1570 | case *PingFrame: | ||
1571 | fmt.Fprintf(&buf, " ping=%q", f.Data[:]) | ||
1572 | case *GoAwayFrame: | ||
1573 | fmt.Fprintf(&buf, " LastStreamID=%v ErrCode=%v Debug=%q", | ||
1574 | f.LastStreamID, f.ErrCode, f.debugData) | ||
1575 | case *RSTStreamFrame: | ||
1576 | fmt.Fprintf(&buf, " ErrCode=%v", f.ErrCode) | ||
1577 | } | ||
1578 | return buf.String() | ||
1579 | } | ||
diff --git a/vendor/golang.org/x/net/http2/go16.go b/vendor/golang.org/x/net/http2/go16.go new file mode 100644 index 0000000..00b2e9e --- /dev/null +++ b/vendor/golang.org/x/net/http2/go16.go | |||
@@ -0,0 +1,16 @@ | |||
1 | // Copyright 2016 The Go Authors. All rights reserved. | ||
2 | // Use of this source code is governed by a BSD-style | ||
3 | // license that can be found in the LICENSE file. | ||
4 | |||
5 | // +build go1.6 | ||
6 | |||
7 | package http2 | ||
8 | |||
9 | import ( | ||
10 | "net/http" | ||
11 | "time" | ||
12 | ) | ||
13 | |||
14 | func transportExpectContinueTimeout(t1 *http.Transport) time.Duration { | ||
15 | return t1.ExpectContinueTimeout | ||
16 | } | ||
diff --git a/vendor/golang.org/x/net/http2/go17.go b/vendor/golang.org/x/net/http2/go17.go new file mode 100644 index 0000000..47b7fae --- /dev/null +++ b/vendor/golang.org/x/net/http2/go17.go | |||
@@ -0,0 +1,106 @@ | |||
1 | // Copyright 2016 The Go Authors. All rights reserved. | ||
2 | // Use of this source code is governed by a BSD-style | ||
3 | // license that can be found in the LICENSE file. | ||
4 | |||
5 | // +build go1.7 | ||
6 | |||
7 | package http2 | ||
8 | |||
9 | import ( | ||
10 | "context" | ||
11 | "net" | ||
12 | "net/http" | ||
13 | "net/http/httptrace" | ||
14 | "time" | ||
15 | ) | ||
16 | |||
17 | type contextContext interface { | ||
18 | context.Context | ||
19 | } | ||
20 | |||
21 | func serverConnBaseContext(c net.Conn, opts *ServeConnOpts) (ctx contextContext, cancel func()) { | ||
22 | ctx, cancel = context.WithCancel(context.Background()) | ||
23 | ctx = context.WithValue(ctx, http.LocalAddrContextKey, c.LocalAddr()) | ||
24 | if hs := opts.baseConfig(); hs != nil { | ||
25 | ctx = context.WithValue(ctx, http.ServerContextKey, hs) | ||
26 | } | ||
27 | return | ||
28 | } | ||
29 | |||
30 | func contextWithCancel(ctx contextContext) (_ contextContext, cancel func()) { | ||
31 | return context.WithCancel(ctx) | ||
32 | } | ||
33 | |||
34 | func requestWithContext(req *http.Request, ctx contextContext) *http.Request { | ||
35 | return req.WithContext(ctx) | ||
36 | } | ||
37 | |||
38 | type clientTrace httptrace.ClientTrace | ||
39 | |||
40 | func reqContext(r *http.Request) context.Context { return r.Context() } | ||
41 | |||
42 | func (t *Transport) idleConnTimeout() time.Duration { | ||
43 | if t.t1 != nil { | ||
44 | return t.t1.IdleConnTimeout | ||
45 | } | ||
46 | return 0 | ||
47 | } | ||
48 | |||
49 | func setResponseUncompressed(res *http.Response) { res.Uncompressed = true } | ||
50 | |||
51 | func traceGotConn(req *http.Request, cc *ClientConn) { | ||
52 | trace := httptrace.ContextClientTrace(req.Context()) | ||
53 | if trace == nil || trace.GotConn == nil { | ||
54 | return | ||
55 | } | ||
56 | ci := httptrace.GotConnInfo{Conn: cc.tconn} | ||
57 | cc.mu.Lock() | ||
58 | ci.Reused = cc.nextStreamID > 1 | ||
59 | ci.WasIdle = len(cc.streams) == 0 && ci.Reused | ||
60 | if ci.WasIdle && !cc.lastActive.IsZero() { | ||
61 | ci.IdleTime = time.Now().Sub(cc.lastActive) | ||
62 | } | ||
63 | cc.mu.Unlock() | ||
64 | |||
65 | trace.GotConn(ci) | ||
66 | } | ||
67 | |||
68 | func traceWroteHeaders(trace *clientTrace) { | ||
69 | if trace != nil && trace.WroteHeaders != nil { | ||
70 | trace.WroteHeaders() | ||
71 | } | ||
72 | } | ||
73 | |||
74 | func traceGot100Continue(trace *clientTrace) { | ||
75 | if trace != nil && trace.Got100Continue != nil { | ||
76 | trace.Got100Continue() | ||
77 | } | ||
78 | } | ||
79 | |||
80 | func traceWait100Continue(trace *clientTrace) { | ||
81 | if trace != nil && trace.Wait100Continue != nil { | ||
82 | trace.Wait100Continue() | ||
83 | } | ||
84 | } | ||
85 | |||
86 | func traceWroteRequest(trace *clientTrace, err error) { | ||
87 | if trace != nil && trace.WroteRequest != nil { | ||
88 | trace.WroteRequest(httptrace.WroteRequestInfo{Err: err}) | ||
89 | } | ||
90 | } | ||
91 | |||
92 | func traceFirstResponseByte(trace *clientTrace) { | ||
93 | if trace != nil && trace.GotFirstResponseByte != nil { | ||
94 | trace.GotFirstResponseByte() | ||
95 | } | ||
96 | } | ||
97 | |||
98 | func requestTrace(req *http.Request) *clientTrace { | ||
99 | trace := httptrace.ContextClientTrace(req.Context()) | ||
100 | return (*clientTrace)(trace) | ||
101 | } | ||
102 | |||
103 | // Ping sends a PING frame to the server and waits for the ack. | ||
104 | func (cc *ClientConn) Ping(ctx context.Context) error { | ||
105 | return cc.ping(ctx) | ||
106 | } | ||
diff --git a/vendor/golang.org/x/net/http2/go17_not18.go b/vendor/golang.org/x/net/http2/go17_not18.go new file mode 100644 index 0000000..b4c52ec --- /dev/null +++ b/vendor/golang.org/x/net/http2/go17_not18.go | |||
@@ -0,0 +1,36 @@ | |||
1 | // Copyright 2016 The Go Authors. All rights reserved. | ||
2 | // Use of this source code is governed by a BSD-style | ||
3 | // license that can be found in the LICENSE file. | ||
4 | |||
5 | // +build go1.7,!go1.8 | ||
6 | |||
7 | package http2 | ||
8 | |||
9 | import "crypto/tls" | ||
10 | |||
11 | // temporary copy of Go 1.7's private tls.Config.clone: | ||
12 | func cloneTLSConfig(c *tls.Config) *tls.Config { | ||
13 | return &tls.Config{ | ||
14 | Rand: c.Rand, | ||
15 | Time: c.Time, | ||
16 | Certificates: c.Certificates, | ||
17 | NameToCertificate: c.NameToCertificate, | ||
18 | GetCertificate: c.GetCertificate, | ||
19 | RootCAs: c.RootCAs, | ||
20 | NextProtos: c.NextProtos, | ||
21 | ServerName: c.ServerName, | ||
22 | ClientAuth: c.ClientAuth, | ||
23 | ClientCAs: c.ClientCAs, | ||
24 | InsecureSkipVerify: c.InsecureSkipVerify, | ||
25 | CipherSuites: c.CipherSuites, | ||
26 | PreferServerCipherSuites: c.PreferServerCipherSuites, | ||
27 | SessionTicketsDisabled: c.SessionTicketsDisabled, | ||
28 | SessionTicketKey: c.SessionTicketKey, | ||
29 | ClientSessionCache: c.ClientSessionCache, | ||
30 | MinVersion: c.MinVersion, | ||
31 | MaxVersion: c.MaxVersion, | ||
32 | CurvePreferences: c.CurvePreferences, | ||
33 | DynamicRecordSizingDisabled: c.DynamicRecordSizingDisabled, | ||
34 | Renegotiation: c.Renegotiation, | ||
35 | } | ||
36 | } | ||
diff --git a/vendor/golang.org/x/net/http2/go18.go b/vendor/golang.org/x/net/http2/go18.go new file mode 100644 index 0000000..4f30d22 --- /dev/null +++ b/vendor/golang.org/x/net/http2/go18.go | |||
@@ -0,0 +1,56 @@ | |||
1 | // Copyright 2015 The Go Authors. All rights reserved. | ||
2 | // Use of this source code is governed by a BSD-style | ||
3 | // license that can be found in the LICENSE file. | ||
4 | |||
5 | // +build go1.8 | ||
6 | |||
7 | package http2 | ||
8 | |||
9 | import ( | ||
10 | "crypto/tls" | ||
11 | "io" | ||
12 | "net/http" | ||
13 | ) | ||
14 | |||
15 | func cloneTLSConfig(c *tls.Config) *tls.Config { | ||
16 | c2 := c.Clone() | ||
17 | c2.GetClientCertificate = c.GetClientCertificate // golang.org/issue/19264 | ||
18 | return c2 | ||
19 | } | ||
20 | |||
21 | var _ http.Pusher = (*responseWriter)(nil) | ||
22 | |||
23 | // Push implements http.Pusher. | ||
24 | func (w *responseWriter) Push(target string, opts *http.PushOptions) error { | ||
25 | internalOpts := pushOptions{} | ||
26 | if opts != nil { | ||
27 | internalOpts.Method = opts.Method | ||
28 | internalOpts.Header = opts.Header | ||
29 | } | ||
30 | return w.push(target, internalOpts) | ||
31 | } | ||
32 | |||
33 | func configureServer18(h1 *http.Server, h2 *Server) error { | ||
34 | if h2.IdleTimeout == 0 { | ||
35 | if h1.IdleTimeout != 0 { | ||
36 | h2.IdleTimeout = h1.IdleTimeout | ||
37 | } else { | ||
38 | h2.IdleTimeout = h1.ReadTimeout | ||
39 | } | ||
40 | } | ||
41 | return nil | ||
42 | } | ||
43 | |||
44 | func shouldLogPanic(panicValue interface{}) bool { | ||
45 | return panicValue != nil && panicValue != http.ErrAbortHandler | ||
46 | } | ||
47 | |||
48 | func reqGetBody(req *http.Request) func() (io.ReadCloser, error) { | ||
49 | return req.GetBody | ||
50 | } | ||
51 | |||
52 | func reqBodyIsNoBody(body io.ReadCloser) bool { | ||
53 | return body == http.NoBody | ||
54 | } | ||
55 | |||
56 | func go18httpNoBody() io.ReadCloser { return http.NoBody } // for tests only | ||
diff --git a/vendor/golang.org/x/net/http2/go19.go b/vendor/golang.org/x/net/http2/go19.go new file mode 100644 index 0000000..38124ba --- /dev/null +++ b/vendor/golang.org/x/net/http2/go19.go | |||
@@ -0,0 +1,16 @@ | |||
1 | // Copyright 2015 The Go Authors. All rights reserved. | ||
2 | // Use of this source code is governed by a BSD-style | ||
3 | // license that can be found in the LICENSE file. | ||
4 | |||
5 | // +build go1.9 | ||
6 | |||
7 | package http2 | ||
8 | |||
9 | import ( | ||
10 | "net/http" | ||
11 | ) | ||
12 | |||
13 | func configureServer19(s *http.Server, conf *Server) error { | ||
14 | s.RegisterOnShutdown(conf.state.startGracefulShutdown) | ||
15 | return nil | ||
16 | } | ||
diff --git a/vendor/golang.org/x/net/http2/gotrack.go b/vendor/golang.org/x/net/http2/gotrack.go new file mode 100644 index 0000000..9933c9f --- /dev/null +++ b/vendor/golang.org/x/net/http2/gotrack.go | |||
@@ -0,0 +1,170 @@ | |||
1 | // Copyright 2014 The Go Authors. All rights reserved. | ||
2 | // Use of this source code is governed by a BSD-style | ||
3 | // license that can be found in the LICENSE file. | ||
4 | |||
5 | // Defensive debug-only utility to track that functions run on the | ||
6 | // goroutine that they're supposed to. | ||
7 | |||
8 | package http2 | ||
9 | |||
10 | import ( | ||
11 | "bytes" | ||
12 | "errors" | ||
13 | "fmt" | ||
14 | "os" | ||
15 | "runtime" | ||
16 | "strconv" | ||
17 | "sync" | ||
18 | ) | ||
19 | |||
20 | var DebugGoroutines = os.Getenv("DEBUG_HTTP2_GOROUTINES") == "1" | ||
21 | |||
22 | type goroutineLock uint64 | ||
23 | |||
24 | func newGoroutineLock() goroutineLock { | ||
25 | if !DebugGoroutines { | ||
26 | return 0 | ||
27 | } | ||
28 | return goroutineLock(curGoroutineID()) | ||
29 | } | ||
30 | |||
31 | func (g goroutineLock) check() { | ||
32 | if !DebugGoroutines { | ||
33 | return | ||
34 | } | ||
35 | if curGoroutineID() != uint64(g) { | ||
36 | panic("running on the wrong goroutine") | ||
37 | } | ||
38 | } | ||
39 | |||
40 | func (g goroutineLock) checkNotOn() { | ||
41 | if !DebugGoroutines { | ||
42 | return | ||
43 | } | ||
44 | if curGoroutineID() == uint64(g) { | ||
45 | panic("running on the wrong goroutine") | ||
46 | } | ||
47 | } | ||
48 | |||
49 | var goroutineSpace = []byte("goroutine ") | ||
50 | |||
51 | func curGoroutineID() uint64 { | ||
52 | bp := littleBuf.Get().(*[]byte) | ||
53 | defer littleBuf.Put(bp) | ||
54 | b := *bp | ||
55 | b = b[:runtime.Stack(b, false)] | ||
56 | // Parse the 4707 out of "goroutine 4707 [" | ||
57 | b = bytes.TrimPrefix(b, goroutineSpace) | ||
58 | i := bytes.IndexByte(b, ' ') | ||
59 | if i < 0 { | ||
60 | panic(fmt.Sprintf("No space found in %q", b)) | ||
61 | } | ||
62 | b = b[:i] | ||
63 | n, err := parseUintBytes(b, 10, 64) | ||
64 | if err != nil { | ||
65 | panic(fmt.Sprintf("Failed to parse goroutine ID out of %q: %v", b, err)) | ||
66 | } | ||
67 | return n | ||
68 | } | ||
69 | |||
70 | var littleBuf = sync.Pool{ | ||
71 | New: func() interface{} { | ||
72 | buf := make([]byte, 64) | ||
73 | return &buf | ||
74 | }, | ||
75 | } | ||
76 | |||
77 | // parseUintBytes is like strconv.ParseUint, but using a []byte. | ||
78 | func parseUintBytes(s []byte, base int, bitSize int) (n uint64, err error) { | ||
79 | var cutoff, maxVal uint64 | ||
80 | |||
81 | if bitSize == 0 { | ||
82 | bitSize = int(strconv.IntSize) | ||
83 | } | ||
84 | |||
85 | s0 := s | ||
86 | switch { | ||
87 | case len(s) < 1: | ||
88 | err = strconv.ErrSyntax | ||
89 | goto Error | ||
90 | |||
91 | case 2 <= base && base <= 36: | ||
92 | // valid base; nothing to do | ||
93 | |||
94 | case base == 0: | ||
95 | // Look for octal, hex prefix. | ||
96 | switch { | ||
97 | case s[0] == '0' && len(s) > 1 && (s[1] == 'x' || s[1] == 'X'): | ||
98 | base = 16 | ||
99 | s = s[2:] | ||
100 | if len(s) < 1 { | ||
101 | err = strconv.ErrSyntax | ||
102 | goto Error | ||
103 | } | ||
104 | case s[0] == '0': | ||
105 | base = 8 | ||
106 | default: | ||
107 | base = 10 | ||
108 | } | ||
109 | |||
110 | default: | ||
111 | err = errors.New("invalid base " + strconv.Itoa(base)) | ||
112 | goto Error | ||
113 | } | ||
114 | |||
115 | n = 0 | ||
116 | cutoff = cutoff64(base) | ||
117 | maxVal = 1<<uint(bitSize) - 1 | ||
118 | |||
119 | for i := 0; i < len(s); i++ { | ||
120 | var v byte | ||
121 | d := s[i] | ||
122 | switch { | ||
123 | case '0' <= d && d <= '9': | ||
124 | v = d - '0' | ||
125 | case 'a' <= d && d <= 'z': | ||
126 | v = d - 'a' + 10 | ||
127 | case 'A' <= d && d <= 'Z': | ||
128 | v = d - 'A' + 10 | ||
129 | default: | ||
130 | n = 0 | ||
131 | err = strconv.ErrSyntax | ||
132 | goto Error | ||
133 | } | ||
134 | if int(v) >= base { | ||
135 | n = 0 | ||
136 | err = strconv.ErrSyntax | ||
137 | goto Error | ||
138 | } | ||
139 | |||
140 | if n >= cutoff { | ||
141 | // n*base overflows | ||
142 | n = 1<<64 - 1 | ||
143 | err = strconv.ErrRange | ||
144 | goto Error | ||
145 | } | ||
146 | n *= uint64(base) | ||
147 | |||
148 | n1 := n + uint64(v) | ||
149 | if n1 < n || n1 > maxVal { | ||
150 | // n+v overflows | ||
151 | n = 1<<64 - 1 | ||
152 | err = strconv.ErrRange | ||
153 | goto Error | ||
154 | } | ||
155 | n = n1 | ||
156 | } | ||
157 | |||
158 | return n, nil | ||
159 | |||
160 | Error: | ||
161 | return n, &strconv.NumError{Func: "ParseUint", Num: string(s0), Err: err} | ||
162 | } | ||
163 | |||
164 | // Return the first number n such that n*base >= 1<<64. | ||
165 | func cutoff64(base int) uint64 { | ||
166 | if base < 2 { | ||
167 | return 0 | ||
168 | } | ||
169 | return (1<<64-1)/uint64(base) + 1 | ||
170 | } | ||
diff --git a/vendor/golang.org/x/net/http2/headermap.go b/vendor/golang.org/x/net/http2/headermap.go new file mode 100644 index 0000000..c2805f6 --- /dev/null +++ b/vendor/golang.org/x/net/http2/headermap.go | |||
@@ -0,0 +1,78 @@ | |||
1 | // Copyright 2014 The Go Authors. All rights reserved. | ||
2 | // Use of this source code is governed by a BSD-style | ||
3 | // license that can be found in the LICENSE file. | ||
4 | |||
5 | package http2 | ||
6 | |||
7 | import ( | ||
8 | "net/http" | ||
9 | "strings" | ||
10 | ) | ||
11 | |||
12 | var ( | ||
13 | commonLowerHeader = map[string]string{} // Go-Canonical-Case -> lower-case | ||
14 | commonCanonHeader = map[string]string{} // lower-case -> Go-Canonical-Case | ||
15 | ) | ||
16 | |||
17 | func init() { | ||
18 | for _, v := range []string{ | ||
19 | "accept", | ||
20 | "accept-charset", | ||
21 | "accept-encoding", | ||
22 | "accept-language", | ||
23 | "accept-ranges", | ||
24 | "age", | ||
25 | "access-control-allow-origin", | ||
26 | "allow", | ||
27 | "authorization", | ||
28 | "cache-control", | ||
29 | "content-disposition", | ||
30 | "content-encoding", | ||
31 | "content-language", | ||
32 | "content-length", | ||
33 | "content-location", | ||
34 | "content-range", | ||
35 | "content-type", | ||
36 | "cookie", | ||
37 | "date", | ||
38 | "etag", | ||
39 | "expect", | ||
40 | "expires", | ||
41 | "from", | ||
42 | "host", | ||
43 | "if-match", | ||
44 | "if-modified-since", | ||
45 | "if-none-match", | ||
46 | "if-unmodified-since", | ||
47 | "last-modified", | ||
48 | "link", | ||
49 | "location", | ||
50 | "max-forwards", | ||
51 | "proxy-authenticate", | ||
52 | "proxy-authorization", | ||
53 | "range", | ||
54 | "referer", | ||
55 | "refresh", | ||
56 | "retry-after", | ||
57 | "server", | ||
58 | "set-cookie", | ||
59 | "strict-transport-security", | ||
60 | "trailer", | ||
61 | "transfer-encoding", | ||
62 | "user-agent", | ||
63 | "vary", | ||
64 | "via", | ||
65 | "www-authenticate", | ||
66 | } { | ||
67 | chk := http.CanonicalHeaderKey(v) | ||
68 | commonLowerHeader[chk] = v | ||
69 | commonCanonHeader[v] = chk | ||
70 | } | ||
71 | } | ||
72 | |||
73 | func lowerHeader(v string) string { | ||
74 | if s, ok := commonLowerHeader[v]; ok { | ||
75 | return s | ||
76 | } | ||
77 | return strings.ToLower(v) | ||
78 | } | ||
diff --git a/vendor/golang.org/x/net/http2/hpack/encode.go b/vendor/golang.org/x/net/http2/hpack/encode.go new file mode 100644 index 0000000..54726c2 --- /dev/null +++ b/vendor/golang.org/x/net/http2/hpack/encode.go | |||
@@ -0,0 +1,240 @@ | |||
1 | // Copyright 2014 The Go Authors. All rights reserved. | ||
2 | // Use of this source code is governed by a BSD-style | ||
3 | // license that can be found in the LICENSE file. | ||
4 | |||
5 | package hpack | ||
6 | |||
7 | import ( | ||
8 | "io" | ||
9 | ) | ||
10 | |||
11 | const ( | ||
12 | uint32Max = ^uint32(0) | ||
13 | initialHeaderTableSize = 4096 | ||
14 | ) | ||
15 | |||
16 | type Encoder struct { | ||
17 | dynTab dynamicTable | ||
18 | // minSize is the minimum table size set by | ||
19 | // SetMaxDynamicTableSize after the previous Header Table Size | ||
20 | // Update. | ||
21 | minSize uint32 | ||
22 | // maxSizeLimit is the maximum table size this encoder | ||
23 | // supports. This will protect the encoder from too large | ||
24 | // size. | ||
25 | maxSizeLimit uint32 | ||
26 | // tableSizeUpdate indicates whether "Header Table Size | ||
27 | // Update" is required. | ||
28 | tableSizeUpdate bool | ||
29 | w io.Writer | ||
30 | buf []byte | ||
31 | } | ||
32 | |||
33 | // NewEncoder returns a new Encoder which performs HPACK encoding. An | ||
34 | // encoded data is written to w. | ||
35 | func NewEncoder(w io.Writer) *Encoder { | ||
36 | e := &Encoder{ | ||
37 | minSize: uint32Max, | ||
38 | maxSizeLimit: initialHeaderTableSize, | ||
39 | tableSizeUpdate: false, | ||
40 | w: w, | ||
41 | } | ||
42 | e.dynTab.table.init() | ||
43 | e.dynTab.setMaxSize(initialHeaderTableSize) | ||
44 | return e | ||
45 | } | ||
46 | |||
47 | // WriteField encodes f into a single Write to e's underlying Writer. | ||
48 | // This function may also produce bytes for "Header Table Size Update" | ||
49 | // if necessary. If produced, it is done before encoding f. | ||
50 | func (e *Encoder) WriteField(f HeaderField) error { | ||
51 | e.buf = e.buf[:0] | ||
52 | |||
53 | if e.tableSizeUpdate { | ||
54 | e.tableSizeUpdate = false | ||
55 | if e.minSize < e.dynTab.maxSize { | ||
56 | e.buf = appendTableSize(e.buf, e.minSize) | ||
57 | } | ||
58 | e.minSize = uint32Max | ||
59 | e.buf = appendTableSize(e.buf, e.dynTab.maxSize) | ||
60 | } | ||
61 | |||
62 | idx, nameValueMatch := e.searchTable(f) | ||
63 | if nameValueMatch { | ||
64 | e.buf = appendIndexed(e.buf, idx) | ||
65 | } else { | ||
66 | indexing := e.shouldIndex(f) | ||
67 | if indexing { | ||
68 | e.dynTab.add(f) | ||
69 | } | ||
70 | |||
71 | if idx == 0 { | ||
72 | e.buf = appendNewName(e.buf, f, indexing) | ||
73 | } else { | ||
74 | e.buf = appendIndexedName(e.buf, f, idx, indexing) | ||
75 | } | ||
76 | } | ||
77 | n, err := e.w.Write(e.buf) | ||
78 | if err == nil && n != len(e.buf) { | ||
79 | err = io.ErrShortWrite | ||
80 | } | ||
81 | return err | ||
82 | } | ||
83 | |||
84 | // searchTable searches f in both stable and dynamic header tables. | ||
85 | // The static header table is searched first. Only when there is no | ||
86 | // exact match for both name and value, the dynamic header table is | ||
87 | // then searched. If there is no match, i is 0. If both name and value | ||
88 | // match, i is the matched index and nameValueMatch becomes true. If | ||
89 | // only name matches, i points to that index and nameValueMatch | ||
90 | // becomes false. | ||
91 | func (e *Encoder) searchTable(f HeaderField) (i uint64, nameValueMatch bool) { | ||
92 | i, nameValueMatch = staticTable.search(f) | ||
93 | if nameValueMatch { | ||
94 | return i, true | ||
95 | } | ||
96 | |||
97 | j, nameValueMatch := e.dynTab.table.search(f) | ||
98 | if nameValueMatch || (i == 0 && j != 0) { | ||
99 | return j + uint64(staticTable.len()), nameValueMatch | ||
100 | } | ||
101 | |||
102 | return i, false | ||
103 | } | ||
104 | |||
105 | // SetMaxDynamicTableSize changes the dynamic header table size to v. | ||
106 | // The actual size is bounded by the value passed to | ||
107 | // SetMaxDynamicTableSizeLimit. | ||
108 | func (e *Encoder) SetMaxDynamicTableSize(v uint32) { | ||
109 | if v > e.maxSizeLimit { | ||
110 | v = e.maxSizeLimit | ||
111 | } | ||
112 | if v < e.minSize { | ||
113 | e.minSize = v | ||
114 | } | ||
115 | e.tableSizeUpdate = true | ||
116 | e.dynTab.setMaxSize(v) | ||
117 | } | ||
118 | |||
119 | // SetMaxDynamicTableSizeLimit changes the maximum value that can be | ||
120 | // specified in SetMaxDynamicTableSize to v. By default, it is set to | ||
121 | // 4096, which is the same size of the default dynamic header table | ||
122 | // size described in HPACK specification. If the current maximum | ||
123 | // dynamic header table size is strictly greater than v, "Header Table | ||
124 | // Size Update" will be done in the next WriteField call and the | ||
125 | // maximum dynamic header table size is truncated to v. | ||
126 | func (e *Encoder) SetMaxDynamicTableSizeLimit(v uint32) { | ||
127 | e.maxSizeLimit = v | ||
128 | if e.dynTab.maxSize > v { | ||
129 | e.tableSizeUpdate = true | ||
130 | e.dynTab.setMaxSize(v) | ||
131 | } | ||
132 | } | ||
133 | |||
134 | // shouldIndex reports whether f should be indexed. | ||
135 | func (e *Encoder) shouldIndex(f HeaderField) bool { | ||
136 | return !f.Sensitive && f.Size() <= e.dynTab.maxSize | ||
137 | } | ||
138 | |||
139 | // appendIndexed appends index i, as encoded in "Indexed Header Field" | ||
140 | // representation, to dst and returns the extended buffer. | ||
141 | func appendIndexed(dst []byte, i uint64) []byte { | ||
142 | first := len(dst) | ||
143 | dst = appendVarInt(dst, 7, i) | ||
144 | dst[first] |= 0x80 | ||
145 | return dst | ||
146 | } | ||
147 | |||
148 | // appendNewName appends f, as encoded in one of "Literal Header field | ||
149 | // - New Name" representation variants, to dst and returns the | ||
150 | // extended buffer. | ||
151 | // | ||
152 | // If f.Sensitive is true, "Never Indexed" representation is used. If | ||
153 | // f.Sensitive is false and indexing is true, "Inremental Indexing" | ||
154 | // representation is used. | ||
155 | func appendNewName(dst []byte, f HeaderField, indexing bool) []byte { | ||
156 | dst = append(dst, encodeTypeByte(indexing, f.Sensitive)) | ||
157 | dst = appendHpackString(dst, f.Name) | ||
158 | return appendHpackString(dst, f.Value) | ||
159 | } | ||
160 | |||
161 | // appendIndexedName appends f and index i referring indexed name | ||
162 | // entry, as encoded in one of "Literal Header field - Indexed Name" | ||
163 | // representation variants, to dst and returns the extended buffer. | ||
164 | // | ||
165 | // If f.Sensitive is true, "Never Indexed" representation is used. If | ||
166 | // f.Sensitive is false and indexing is true, "Incremental Indexing" | ||
167 | // representation is used. | ||
168 | func appendIndexedName(dst []byte, f HeaderField, i uint64, indexing bool) []byte { | ||
169 | first := len(dst) | ||
170 | var n byte | ||
171 | if indexing { | ||
172 | n = 6 | ||
173 | } else { | ||
174 | n = 4 | ||
175 | } | ||
176 | dst = appendVarInt(dst, n, i) | ||
177 | dst[first] |= encodeTypeByte(indexing, f.Sensitive) | ||
178 | return appendHpackString(dst, f.Value) | ||
179 | } | ||
180 | |||
181 | // appendTableSize appends v, as encoded in "Header Table Size Update" | ||
182 | // representation, to dst and returns the extended buffer. | ||
183 | func appendTableSize(dst []byte, v uint32) []byte { | ||
184 | first := len(dst) | ||
185 | dst = appendVarInt(dst, 5, uint64(v)) | ||
186 | dst[first] |= 0x20 | ||
187 | return dst | ||
188 | } | ||
189 | |||
190 | // appendVarInt appends i, as encoded in variable integer form using n | ||
191 | // bit prefix, to dst and returns the extended buffer. | ||
192 | // | ||
193 | // See | ||
194 | // http://http2.github.io/http2-spec/compression.html#integer.representation | ||
195 | func appendVarInt(dst []byte, n byte, i uint64) []byte { | ||
196 | k := uint64((1 << n) - 1) | ||
197 | if i < k { | ||
198 | return append(dst, byte(i)) | ||
199 | } | ||
200 | dst = append(dst, byte(k)) | ||
201 | i -= k | ||
202 | for ; i >= 128; i >>= 7 { | ||
203 | dst = append(dst, byte(0x80|(i&0x7f))) | ||
204 | } | ||
205 | return append(dst, byte(i)) | ||
206 | } | ||
207 | |||
208 | // appendHpackString appends s, as encoded in "String Literal" | ||
209 | // representation, to dst and returns the the extended buffer. | ||
210 | // | ||
211 | // s will be encoded in Huffman codes only when it produces strictly | ||
212 | // shorter byte string. | ||
213 | func appendHpackString(dst []byte, s string) []byte { | ||
214 | huffmanLength := HuffmanEncodeLength(s) | ||
215 | if huffmanLength < uint64(len(s)) { | ||
216 | first := len(dst) | ||
217 | dst = appendVarInt(dst, 7, huffmanLength) | ||
218 | dst = AppendHuffmanString(dst, s) | ||
219 | dst[first] |= 0x80 | ||
220 | } else { | ||
221 | dst = appendVarInt(dst, 7, uint64(len(s))) | ||
222 | dst = append(dst, s...) | ||
223 | } | ||
224 | return dst | ||
225 | } | ||
226 | |||
227 | // encodeTypeByte returns type byte. If sensitive is true, type byte | ||
228 | // for "Never Indexed" representation is returned. If sensitive is | ||
229 | // false and indexing is true, type byte for "Incremental Indexing" | ||
230 | // representation is returned. Otherwise, type byte for "Without | ||
231 | // Indexing" is returned. | ||
232 | func encodeTypeByte(indexing, sensitive bool) byte { | ||
233 | if sensitive { | ||
234 | return 0x10 | ||
235 | } | ||
236 | if indexing { | ||
237 | return 0x40 | ||
238 | } | ||
239 | return 0 | ||
240 | } | ||
diff --git a/vendor/golang.org/x/net/http2/hpack/hpack.go b/vendor/golang.org/x/net/http2/hpack/hpack.go new file mode 100644 index 0000000..176644a --- /dev/null +++ b/vendor/golang.org/x/net/http2/hpack/hpack.go | |||
@@ -0,0 +1,490 @@ | |||
1 | // Copyright 2014 The Go Authors. All rights reserved. | ||
2 | // Use of this source code is governed by a BSD-style | ||
3 | // license that can be found in the LICENSE file. | ||
4 | |||
5 | // Package hpack implements HPACK, a compression format for | ||
6 | // efficiently representing HTTP header fields in the context of HTTP/2. | ||
7 | // | ||
8 | // See http://tools.ietf.org/html/draft-ietf-httpbis-header-compression-09 | ||
9 | package hpack | ||
10 | |||
11 | import ( | ||
12 | "bytes" | ||
13 | "errors" | ||
14 | "fmt" | ||
15 | ) | ||
16 | |||
17 | // A DecodingError is something the spec defines as a decoding error. | ||
18 | type DecodingError struct { | ||
19 | Err error | ||
20 | } | ||
21 | |||
22 | func (de DecodingError) Error() string { | ||
23 | return fmt.Sprintf("decoding error: %v", de.Err) | ||
24 | } | ||
25 | |||
26 | // An InvalidIndexError is returned when an encoder references a table | ||
27 | // entry before the static table or after the end of the dynamic table. | ||
28 | type InvalidIndexError int | ||
29 | |||
30 | func (e InvalidIndexError) Error() string { | ||
31 | return fmt.Sprintf("invalid indexed representation index %d", int(e)) | ||
32 | } | ||
33 | |||
34 | // A HeaderField is a name-value pair. Both the name and value are | ||
35 | // treated as opaque sequences of octets. | ||
36 | type HeaderField struct { | ||
37 | Name, Value string | ||
38 | |||
39 | // Sensitive means that this header field should never be | ||
40 | // indexed. | ||
41 | Sensitive bool | ||
42 | } | ||
43 | |||
44 | // IsPseudo reports whether the header field is an http2 pseudo header. | ||
45 | // That is, it reports whether it starts with a colon. | ||
46 | // It is not otherwise guaranteed to be a valid pseudo header field, | ||
47 | // though. | ||
48 | func (hf HeaderField) IsPseudo() bool { | ||
49 | return len(hf.Name) != 0 && hf.Name[0] == ':' | ||
50 | } | ||
51 | |||
52 | func (hf HeaderField) String() string { | ||
53 | var suffix string | ||
54 | if hf.Sensitive { | ||
55 | suffix = " (sensitive)" | ||
56 | } | ||
57 | return fmt.Sprintf("header field %q = %q%s", hf.Name, hf.Value, suffix) | ||
58 | } | ||
59 | |||
60 | // Size returns the size of an entry per RFC 7541 section 4.1. | ||
61 | func (hf HeaderField) Size() uint32 { | ||
62 | // http://http2.github.io/http2-spec/compression.html#rfc.section.4.1 | ||
63 | // "The size of the dynamic table is the sum of the size of | ||
64 | // its entries. The size of an entry is the sum of its name's | ||
65 | // length in octets (as defined in Section 5.2), its value's | ||
66 | // length in octets (see Section 5.2), plus 32. The size of | ||
67 | // an entry is calculated using the length of the name and | ||
68 | // value without any Huffman encoding applied." | ||
69 | |||
70 | // This can overflow if somebody makes a large HeaderField | ||
71 | // Name and/or Value by hand, but we don't care, because that | ||
72 | // won't happen on the wire because the encoding doesn't allow | ||
73 | // it. | ||
74 | return uint32(len(hf.Name) + len(hf.Value) + 32) | ||
75 | } | ||
76 | |||
77 | // A Decoder is the decoding context for incremental processing of | ||
78 | // header blocks. | ||
79 | type Decoder struct { | ||
80 | dynTab dynamicTable | ||
81 | emit func(f HeaderField) | ||
82 | |||
83 | emitEnabled bool // whether calls to emit are enabled | ||
84 | maxStrLen int // 0 means unlimited | ||
85 | |||
86 | // buf is the unparsed buffer. It's only written to | ||
87 | // saveBuf if it was truncated in the middle of a header | ||
88 | // block. Because it's usually not owned, we can only | ||
89 | // process it under Write. | ||
90 | buf []byte // not owned; only valid during Write | ||
91 | |||
92 | // saveBuf is previous data passed to Write which we weren't able | ||
93 | // to fully parse before. Unlike buf, we own this data. | ||
94 | saveBuf bytes.Buffer | ||
95 | } | ||
96 | |||
97 | // NewDecoder returns a new decoder with the provided maximum dynamic | ||
98 | // table size. The emitFunc will be called for each valid field | ||
99 | // parsed, in the same goroutine as calls to Write, before Write returns. | ||
100 | func NewDecoder(maxDynamicTableSize uint32, emitFunc func(f HeaderField)) *Decoder { | ||
101 | d := &Decoder{ | ||
102 | emit: emitFunc, | ||
103 | emitEnabled: true, | ||
104 | } | ||
105 | d.dynTab.table.init() | ||
106 | d.dynTab.allowedMaxSize = maxDynamicTableSize | ||
107 | d.dynTab.setMaxSize(maxDynamicTableSize) | ||
108 | return d | ||
109 | } | ||
110 | |||
111 | // ErrStringLength is returned by Decoder.Write when the max string length | ||
112 | // (as configured by Decoder.SetMaxStringLength) would be violated. | ||
113 | var ErrStringLength = errors.New("hpack: string too long") | ||
114 | |||
115 | // SetMaxStringLength sets the maximum size of a HeaderField name or | ||
116 | // value string. If a string exceeds this length (even after any | ||
117 | // decompression), Write will return ErrStringLength. | ||
118 | // A value of 0 means unlimited and is the default from NewDecoder. | ||
119 | func (d *Decoder) SetMaxStringLength(n int) { | ||
120 | d.maxStrLen = n | ||
121 | } | ||
122 | |||
123 | // SetEmitFunc changes the callback used when new header fields | ||
124 | // are decoded. | ||
125 | // It must be non-nil. It does not affect EmitEnabled. | ||
126 | func (d *Decoder) SetEmitFunc(emitFunc func(f HeaderField)) { | ||
127 | d.emit = emitFunc | ||
128 | } | ||
129 | |||
130 | // SetEmitEnabled controls whether the emitFunc provided to NewDecoder | ||
131 | // should be called. The default is true. | ||
132 | // | ||
133 | // This facility exists to let servers enforce MAX_HEADER_LIST_SIZE | ||
134 | // while still decoding and keeping in-sync with decoder state, but | ||
135 | // without doing unnecessary decompression or generating unnecessary | ||
136 | // garbage for header fields past the limit. | ||
137 | func (d *Decoder) SetEmitEnabled(v bool) { d.emitEnabled = v } | ||
138 | |||
139 | // EmitEnabled reports whether calls to the emitFunc provided to NewDecoder | ||
140 | // are currently enabled. The default is true. | ||
141 | func (d *Decoder) EmitEnabled() bool { return d.emitEnabled } | ||
142 | |||
143 | // TODO: add method *Decoder.Reset(maxSize, emitFunc) to let callers re-use Decoders and their | ||
144 | // underlying buffers for garbage reasons. | ||
145 | |||
146 | func (d *Decoder) SetMaxDynamicTableSize(v uint32) { | ||
147 | d.dynTab.setMaxSize(v) | ||
148 | } | ||
149 | |||
150 | // SetAllowedMaxDynamicTableSize sets the upper bound that the encoded | ||
151 | // stream (via dynamic table size updates) may set the maximum size | ||
152 | // to. | ||
153 | func (d *Decoder) SetAllowedMaxDynamicTableSize(v uint32) { | ||
154 | d.dynTab.allowedMaxSize = v | ||
155 | } | ||
156 | |||
157 | type dynamicTable struct { | ||
158 | // http://http2.github.io/http2-spec/compression.html#rfc.section.2.3.2 | ||
159 | table headerFieldTable | ||
160 | size uint32 // in bytes | ||
161 | maxSize uint32 // current maxSize | ||
162 | allowedMaxSize uint32 // maxSize may go up to this, inclusive | ||
163 | } | ||
164 | |||
165 | func (dt *dynamicTable) setMaxSize(v uint32) { | ||
166 | dt.maxSize = v | ||
167 | dt.evict() | ||
168 | } | ||
169 | |||
170 | func (dt *dynamicTable) add(f HeaderField) { | ||
171 | dt.table.addEntry(f) | ||
172 | dt.size += f.Size() | ||
173 | dt.evict() | ||
174 | } | ||
175 | |||
176 | // If we're too big, evict old stuff. | ||
177 | func (dt *dynamicTable) evict() { | ||
178 | var n int | ||
179 | for dt.size > dt.maxSize && n < dt.table.len() { | ||
180 | dt.size -= dt.table.ents[n].Size() | ||
181 | n++ | ||
182 | } | ||
183 | dt.table.evictOldest(n) | ||
184 | } | ||
185 | |||
186 | func (d *Decoder) maxTableIndex() int { | ||
187 | // This should never overflow. RFC 7540 Section 6.5.2 limits the size of | ||
188 | // the dynamic table to 2^32 bytes, where each entry will occupy more than | ||
189 | // one byte. Further, the staticTable has a fixed, small length. | ||
190 | return d.dynTab.table.len() + staticTable.len() | ||
191 | } | ||
192 | |||
193 | func (d *Decoder) at(i uint64) (hf HeaderField, ok bool) { | ||
194 | // See Section 2.3.3. | ||
195 | if i == 0 { | ||
196 | return | ||
197 | } | ||
198 | if i <= uint64(staticTable.len()) { | ||
199 | return staticTable.ents[i-1], true | ||
200 | } | ||
201 | if i > uint64(d.maxTableIndex()) { | ||
202 | return | ||
203 | } | ||
204 | // In the dynamic table, newer entries have lower indices. | ||
205 | // However, dt.ents[0] is the oldest entry. Hence, dt.ents is | ||
206 | // the reversed dynamic table. | ||
207 | dt := d.dynTab.table | ||
208 | return dt.ents[dt.len()-(int(i)-staticTable.len())], true | ||
209 | } | ||
210 | |||
211 | // Decode decodes an entire block. | ||
212 | // | ||
213 | // TODO: remove this method and make it incremental later? This is | ||
214 | // easier for debugging now. | ||
215 | func (d *Decoder) DecodeFull(p []byte) ([]HeaderField, error) { | ||
216 | var hf []HeaderField | ||
217 | saveFunc := d.emit | ||
218 | defer func() { d.emit = saveFunc }() | ||
219 | d.emit = func(f HeaderField) { hf = append(hf, f) } | ||
220 | if _, err := d.Write(p); err != nil { | ||
221 | return nil, err | ||
222 | } | ||
223 | if err := d.Close(); err != nil { | ||
224 | return nil, err | ||
225 | } | ||
226 | return hf, nil | ||
227 | } | ||
228 | |||
229 | func (d *Decoder) Close() error { | ||
230 | if d.saveBuf.Len() > 0 { | ||
231 | d.saveBuf.Reset() | ||
232 | return DecodingError{errors.New("truncated headers")} | ||
233 | } | ||
234 | return nil | ||
235 | } | ||
236 | |||
237 | func (d *Decoder) Write(p []byte) (n int, err error) { | ||
238 | if len(p) == 0 { | ||
239 | // Prevent state machine CPU attacks (making us redo | ||
240 | // work up to the point of finding out we don't have | ||
241 | // enough data) | ||
242 | return | ||
243 | } | ||
244 | // Only copy the data if we have to. Optimistically assume | ||
245 | // that p will contain a complete header block. | ||
246 | if d.saveBuf.Len() == 0 { | ||
247 | d.buf = p | ||
248 | } else { | ||
249 | d.saveBuf.Write(p) | ||
250 | d.buf = d.saveBuf.Bytes() | ||
251 | d.saveBuf.Reset() | ||
252 | } | ||
253 | |||
254 | for len(d.buf) > 0 { | ||
255 | err = d.parseHeaderFieldRepr() | ||
256 | if err == errNeedMore { | ||
257 | // Extra paranoia, making sure saveBuf won't | ||
258 | // get too large. All the varint and string | ||
259 | // reading code earlier should already catch | ||
260 | // overlong things and return ErrStringLength, | ||
261 | // but keep this as a last resort. | ||
262 | const varIntOverhead = 8 // conservative | ||
263 | if d.maxStrLen != 0 && int64(len(d.buf)) > 2*(int64(d.maxStrLen)+varIntOverhead) { | ||
264 | return 0, ErrStringLength | ||
265 | } | ||
266 | d.saveBuf.Write(d.buf) | ||
267 | return len(p), nil | ||
268 | } | ||
269 | if err != nil { | ||
270 | break | ||
271 | } | ||
272 | } | ||
273 | return len(p), err | ||
274 | } | ||
275 | |||
276 | // errNeedMore is an internal sentinel error value that means the | ||
277 | // buffer is truncated and we need to read more data before we can | ||
278 | // continue parsing. | ||
279 | var errNeedMore = errors.New("need more data") | ||
280 | |||
281 | type indexType int | ||
282 | |||
283 | const ( | ||
284 | indexedTrue indexType = iota | ||
285 | indexedFalse | ||
286 | indexedNever | ||
287 | ) | ||
288 | |||
289 | func (v indexType) indexed() bool { return v == indexedTrue } | ||
290 | func (v indexType) sensitive() bool { return v == indexedNever } | ||
291 | |||
292 | // returns errNeedMore if there isn't enough data available. | ||
293 | // any other error is fatal. | ||
294 | // consumes d.buf iff it returns nil. | ||
295 | // precondition: must be called with len(d.buf) > 0 | ||
296 | func (d *Decoder) parseHeaderFieldRepr() error { | ||
297 | b := d.buf[0] | ||
298 | switch { | ||
299 | case b&128 != 0: | ||
300 | // Indexed representation. | ||
301 | // High bit set? | ||
302 | // http://http2.github.io/http2-spec/compression.html#rfc.section.6.1 | ||
303 | return d.parseFieldIndexed() | ||
304 | case b&192 == 64: | ||
305 | // 6.2.1 Literal Header Field with Incremental Indexing | ||
306 | // 0b10xxxxxx: top two bits are 10 | ||
307 | // http://http2.github.io/http2-spec/compression.html#rfc.section.6.2.1 | ||
308 | return d.parseFieldLiteral(6, indexedTrue) | ||
309 | case b&240 == 0: | ||
310 | // 6.2.2 Literal Header Field without Indexing | ||
311 | // 0b0000xxxx: top four bits are 0000 | ||
312 | // http://http2.github.io/http2-spec/compression.html#rfc.section.6.2.2 | ||
313 | return d.parseFieldLiteral(4, indexedFalse) | ||
314 | case b&240 == 16: | ||
315 | // 6.2.3 Literal Header Field never Indexed | ||
316 | // 0b0001xxxx: top four bits are 0001 | ||
317 | // http://http2.github.io/http2-spec/compression.html#rfc.section.6.2.3 | ||
318 | return d.parseFieldLiteral(4, indexedNever) | ||
319 | case b&224 == 32: | ||
320 | // 6.3 Dynamic Table Size Update | ||
321 | // Top three bits are '001'. | ||
322 | // http://http2.github.io/http2-spec/compression.html#rfc.section.6.3 | ||
323 | return d.parseDynamicTableSizeUpdate() | ||
324 | } | ||
325 | |||
326 | return DecodingError{errors.New("invalid encoding")} | ||
327 | } | ||
328 | |||
329 | // (same invariants and behavior as parseHeaderFieldRepr) | ||
330 | func (d *Decoder) parseFieldIndexed() error { | ||
331 | buf := d.buf | ||
332 | idx, buf, err := readVarInt(7, buf) | ||
333 | if err != nil { | ||
334 | return err | ||
335 | } | ||
336 | hf, ok := d.at(idx) | ||
337 | if !ok { | ||
338 | return DecodingError{InvalidIndexError(idx)} | ||
339 | } | ||
340 | d.buf = buf | ||
341 | return d.callEmit(HeaderField{Name: hf.Name, Value: hf.Value}) | ||
342 | } | ||
343 | |||
344 | // (same invariants and behavior as parseHeaderFieldRepr) | ||
345 | func (d *Decoder) parseFieldLiteral(n uint8, it indexType) error { | ||
346 | buf := d.buf | ||
347 | nameIdx, buf, err := readVarInt(n, buf) | ||
348 | if err != nil { | ||
349 | return err | ||
350 | } | ||
351 | |||
352 | var hf HeaderField | ||
353 | wantStr := d.emitEnabled || it.indexed() | ||
354 | if nameIdx > 0 { | ||
355 | ihf, ok := d.at(nameIdx) | ||
356 | if !ok { | ||
357 | return DecodingError{InvalidIndexError(nameIdx)} | ||
358 | } | ||
359 | hf.Name = ihf.Name | ||
360 | } else { | ||
361 | hf.Name, buf, err = d.readString(buf, wantStr) | ||
362 | if err != nil { | ||
363 | return err | ||
364 | } | ||
365 | } | ||
366 | hf.Value, buf, err = d.readString(buf, wantStr) | ||
367 | if err != nil { | ||
368 | return err | ||
369 | } | ||
370 | d.buf = buf | ||
371 | if it.indexed() { | ||
372 | d.dynTab.add(hf) | ||
373 | } | ||
374 | hf.Sensitive = it.sensitive() | ||
375 | return d.callEmit(hf) | ||
376 | } | ||
377 | |||
378 | func (d *Decoder) callEmit(hf HeaderField) error { | ||
379 | if d.maxStrLen != 0 { | ||
380 | if len(hf.Name) > d.maxStrLen || len(hf.Value) > d.maxStrLen { | ||
381 | return ErrStringLength | ||
382 | } | ||
383 | } | ||
384 | if d.emitEnabled { | ||
385 | d.emit(hf) | ||
386 | } | ||
387 | return nil | ||
388 | } | ||
389 | |||
390 | // (same invariants and behavior as parseHeaderFieldRepr) | ||
391 | func (d *Decoder) parseDynamicTableSizeUpdate() error { | ||
392 | buf := d.buf | ||
393 | size, buf, err := readVarInt(5, buf) | ||
394 | if err != nil { | ||
395 | return err | ||
396 | } | ||
397 | if size > uint64(d.dynTab.allowedMaxSize) { | ||
398 | return DecodingError{errors.New("dynamic table size update too large")} | ||
399 | } | ||
400 | d.dynTab.setMaxSize(uint32(size)) | ||
401 | d.buf = buf | ||
402 | return nil | ||
403 | } | ||
404 | |||
405 | var errVarintOverflow = DecodingError{errors.New("varint integer overflow")} | ||
406 | |||
407 | // readVarInt reads an unsigned variable length integer off the | ||
408 | // beginning of p. n is the parameter as described in | ||
409 | // http://http2.github.io/http2-spec/compression.html#rfc.section.5.1. | ||
410 | // | ||
411 | // n must always be between 1 and 8. | ||
412 | // | ||
413 | // The returned remain buffer is either a smaller suffix of p, or err != nil. | ||
414 | // The error is errNeedMore if p doesn't contain a complete integer. | ||
415 | func readVarInt(n byte, p []byte) (i uint64, remain []byte, err error) { | ||
416 | if n < 1 || n > 8 { | ||
417 | panic("bad n") | ||
418 | } | ||
419 | if len(p) == 0 { | ||
420 | return 0, p, errNeedMore | ||
421 | } | ||
422 | i = uint64(p[0]) | ||
423 | if n < 8 { | ||
424 | i &= (1 << uint64(n)) - 1 | ||
425 | } | ||
426 | if i < (1<<uint64(n))-1 { | ||
427 | return i, p[1:], nil | ||
428 | } | ||
429 | |||
430 | origP := p | ||
431 | p = p[1:] | ||
432 | var m uint64 | ||
433 | for len(p) > 0 { | ||
434 | b := p[0] | ||
435 | p = p[1:] | ||
436 | i += uint64(b&127) << m | ||
437 | if b&128 == 0 { | ||
438 | return i, p, nil | ||
439 | } | ||
440 | m += 7 | ||
441 | if m >= 63 { // TODO: proper overflow check. making this up. | ||
442 | return 0, origP, errVarintOverflow | ||
443 | } | ||
444 | } | ||
445 | return 0, origP, errNeedMore | ||
446 | } | ||
447 | |||
448 | // readString decodes an hpack string from p. | ||
449 | // | ||
450 | // wantStr is whether s will be used. If false, decompression and | ||
451 | // []byte->string garbage are skipped if s will be ignored | ||
452 | // anyway. This does mean that huffman decoding errors for non-indexed | ||
453 | // strings past the MAX_HEADER_LIST_SIZE are ignored, but the server | ||
454 | // is returning an error anyway, and because they're not indexed, the error | ||
455 | // won't affect the decoding state. | ||
456 | func (d *Decoder) readString(p []byte, wantStr bool) (s string, remain []byte, err error) { | ||
457 | if len(p) == 0 { | ||
458 | return "", p, errNeedMore | ||
459 | } | ||
460 | isHuff := p[0]&128 != 0 | ||
461 | strLen, p, err := readVarInt(7, p) | ||
462 | if err != nil { | ||
463 | return "", p, err | ||
464 | } | ||
465 | if d.maxStrLen != 0 && strLen > uint64(d.maxStrLen) { | ||
466 | return "", nil, ErrStringLength | ||
467 | } | ||
468 | if uint64(len(p)) < strLen { | ||
469 | return "", p, errNeedMore | ||
470 | } | ||
471 | if !isHuff { | ||
472 | if wantStr { | ||
473 | s = string(p[:strLen]) | ||
474 | } | ||
475 | return s, p[strLen:], nil | ||
476 | } | ||
477 | |||
478 | if wantStr { | ||
479 | buf := bufPool.Get().(*bytes.Buffer) | ||
480 | buf.Reset() // don't trust others | ||
481 | defer bufPool.Put(buf) | ||
482 | if err := huffmanDecode(buf, d.maxStrLen, p[:strLen]); err != nil { | ||
483 | buf.Reset() | ||
484 | return "", nil, err | ||
485 | } | ||
486 | s = buf.String() | ||
487 | buf.Reset() // be nice to GC | ||
488 | } | ||
489 | return s, p[strLen:], nil | ||
490 | } | ||
diff --git a/vendor/golang.org/x/net/http2/hpack/huffman.go b/vendor/golang.org/x/net/http2/hpack/huffman.go new file mode 100644 index 0000000..8850e39 --- /dev/null +++ b/vendor/golang.org/x/net/http2/hpack/huffman.go | |||
@@ -0,0 +1,212 @@ | |||
1 | // Copyright 2014 The Go Authors. All rights reserved. | ||
2 | // Use of this source code is governed by a BSD-style | ||
3 | // license that can be found in the LICENSE file. | ||
4 | |||
5 | package hpack | ||
6 | |||
7 | import ( | ||
8 | "bytes" | ||
9 | "errors" | ||
10 | "io" | ||
11 | "sync" | ||
12 | ) | ||
13 | |||
14 | var bufPool = sync.Pool{ | ||
15 | New: func() interface{} { return new(bytes.Buffer) }, | ||
16 | } | ||
17 | |||
18 | // HuffmanDecode decodes the string in v and writes the expanded | ||
19 | // result to w, returning the number of bytes written to w and the | ||
20 | // Write call's return value. At most one Write call is made. | ||
21 | func HuffmanDecode(w io.Writer, v []byte) (int, error) { | ||
22 | buf := bufPool.Get().(*bytes.Buffer) | ||
23 | buf.Reset() | ||
24 | defer bufPool.Put(buf) | ||
25 | if err := huffmanDecode(buf, 0, v); err != nil { | ||
26 | return 0, err | ||
27 | } | ||
28 | return w.Write(buf.Bytes()) | ||
29 | } | ||
30 | |||
31 | // HuffmanDecodeToString decodes the string in v. | ||
32 | func HuffmanDecodeToString(v []byte) (string, error) { | ||
33 | buf := bufPool.Get().(*bytes.Buffer) | ||
34 | buf.Reset() | ||
35 | defer bufPool.Put(buf) | ||
36 | if err := huffmanDecode(buf, 0, v); err != nil { | ||
37 | return "", err | ||
38 | } | ||
39 | return buf.String(), nil | ||
40 | } | ||
41 | |||
42 | // ErrInvalidHuffman is returned for errors found decoding | ||
43 | // Huffman-encoded strings. | ||
44 | var ErrInvalidHuffman = errors.New("hpack: invalid Huffman-encoded data") | ||
45 | |||
46 | // huffmanDecode decodes v to buf. | ||
47 | // If maxLen is greater than 0, attempts to write more to buf than | ||
48 | // maxLen bytes will return ErrStringLength. | ||
49 | func huffmanDecode(buf *bytes.Buffer, maxLen int, v []byte) error { | ||
50 | n := rootHuffmanNode | ||
51 | // cur is the bit buffer that has not been fed into n. | ||
52 | // cbits is the number of low order bits in cur that are valid. | ||
53 | // sbits is the number of bits of the symbol prefix being decoded. | ||
54 | cur, cbits, sbits := uint(0), uint8(0), uint8(0) | ||
55 | for _, b := range v { | ||
56 | cur = cur<<8 | uint(b) | ||
57 | cbits += 8 | ||
58 | sbits += 8 | ||
59 | for cbits >= 8 { | ||
60 | idx := byte(cur >> (cbits - 8)) | ||
61 | n = n.children[idx] | ||
62 | if n == nil { | ||
63 | return ErrInvalidHuffman | ||
64 | } | ||
65 | if n.children == nil { | ||
66 | if maxLen != 0 && buf.Len() == maxLen { | ||
67 | return ErrStringLength | ||
68 | } | ||
69 | buf.WriteByte(n.sym) | ||
70 | cbits -= n.codeLen | ||
71 | n = rootHuffmanNode | ||
72 | sbits = cbits | ||
73 | } else { | ||
74 | cbits -= 8 | ||
75 | } | ||
76 | } | ||
77 | } | ||
78 | for cbits > 0 { | ||
79 | n = n.children[byte(cur<<(8-cbits))] | ||
80 | if n == nil { | ||
81 | return ErrInvalidHuffman | ||
82 | } | ||
83 | if n.children != nil || n.codeLen > cbits { | ||
84 | break | ||
85 | } | ||
86 | if maxLen != 0 && buf.Len() == maxLen { | ||
87 | return ErrStringLength | ||
88 | } | ||
89 | buf.WriteByte(n.sym) | ||
90 | cbits -= n.codeLen | ||
91 | n = rootHuffmanNode | ||
92 | sbits = cbits | ||
93 | } | ||
94 | if sbits > 7 { | ||
95 | // Either there was an incomplete symbol, or overlong padding. | ||
96 | // Both are decoding errors per RFC 7541 section 5.2. | ||
97 | return ErrInvalidHuffman | ||
98 | } | ||
99 | if mask := uint(1<<cbits - 1); cur&mask != mask { | ||
100 | // Trailing bits must be a prefix of EOS per RFC 7541 section 5.2. | ||
101 | return ErrInvalidHuffman | ||
102 | } | ||
103 | |||
104 | return nil | ||
105 | } | ||
106 | |||
107 | type node struct { | ||
108 | // children is non-nil for internal nodes | ||
109 | children []*node | ||
110 | |||
111 | // The following are only valid if children is nil: | ||
112 | codeLen uint8 // number of bits that led to the output of sym | ||
113 | sym byte // output symbol | ||
114 | } | ||
115 | |||
116 | func newInternalNode() *node { | ||
117 | return &node{children: make([]*node, 256)} | ||
118 | } | ||
119 | |||
120 | var rootHuffmanNode = newInternalNode() | ||
121 | |||
122 | func init() { | ||
123 | if len(huffmanCodes) != 256 { | ||
124 | panic("unexpected size") | ||
125 | } | ||
126 | for i, code := range huffmanCodes { | ||
127 | addDecoderNode(byte(i), code, huffmanCodeLen[i]) | ||
128 | } | ||
129 | } | ||
130 | |||
131 | func addDecoderNode(sym byte, code uint32, codeLen uint8) { | ||
132 | cur := rootHuffmanNode | ||
133 | for codeLen > 8 { | ||
134 | codeLen -= 8 | ||
135 | i := uint8(code >> codeLen) | ||
136 | if cur.children[i] == nil { | ||
137 | cur.children[i] = newInternalNode() | ||
138 | } | ||
139 | cur = cur.children[i] | ||
140 | } | ||
141 | shift := 8 - codeLen | ||
142 | start, end := int(uint8(code<<shift)), int(1<<shift) | ||
143 | for i := start; i < start+end; i++ { | ||
144 | cur.children[i] = &node{sym: sym, codeLen: codeLen} | ||
145 | } | ||
146 | } | ||
147 | |||
148 | // AppendHuffmanString appends s, as encoded in Huffman codes, to dst | ||
149 | // and returns the extended buffer. | ||
150 | func AppendHuffmanString(dst []byte, s string) []byte { | ||
151 | rembits := uint8(8) | ||
152 | |||
153 | for i := 0; i < len(s); i++ { | ||
154 | if rembits == 8 { | ||
155 | dst = append(dst, 0) | ||
156 | } | ||
157 | dst, rembits = appendByteToHuffmanCode(dst, rembits, s[i]) | ||
158 | } | ||
159 | |||
160 | if rembits < 8 { | ||
161 | // special EOS symbol | ||
162 | code := uint32(0x3fffffff) | ||
163 | nbits := uint8(30) | ||
164 | |||
165 | t := uint8(code >> (nbits - rembits)) | ||
166 | dst[len(dst)-1] |= t | ||
167 | } | ||
168 | |||
169 | return dst | ||
170 | } | ||
171 | |||
172 | // HuffmanEncodeLength returns the number of bytes required to encode | ||
173 | // s in Huffman codes. The result is round up to byte boundary. | ||
174 | func HuffmanEncodeLength(s string) uint64 { | ||
175 | n := uint64(0) | ||
176 | for i := 0; i < len(s); i++ { | ||
177 | n += uint64(huffmanCodeLen[s[i]]) | ||
178 | } | ||
179 | return (n + 7) / 8 | ||
180 | } | ||
181 | |||
182 | // appendByteToHuffmanCode appends Huffman code for c to dst and | ||
183 | // returns the extended buffer and the remaining bits in the last | ||
184 | // element. The appending is not byte aligned and the remaining bits | ||
185 | // in the last element of dst is given in rembits. | ||
186 | func appendByteToHuffmanCode(dst []byte, rembits uint8, c byte) ([]byte, uint8) { | ||
187 | code := huffmanCodes[c] | ||
188 | nbits := huffmanCodeLen[c] | ||
189 | |||
190 | for { | ||
191 | if rembits > nbits { | ||
192 | t := uint8(code << (rembits - nbits)) | ||
193 | dst[len(dst)-1] |= t | ||
194 | rembits -= nbits | ||
195 | break | ||
196 | } | ||
197 | |||
198 | t := uint8(code >> (nbits - rembits)) | ||
199 | dst[len(dst)-1] |= t | ||
200 | |||
201 | nbits -= rembits | ||
202 | rembits = 8 | ||
203 | |||
204 | if nbits == 0 { | ||
205 | break | ||
206 | } | ||
207 | |||
208 | dst = append(dst, 0) | ||
209 | } | ||
210 | |||
211 | return dst, rembits | ||
212 | } | ||
diff --git a/vendor/golang.org/x/net/http2/hpack/tables.go b/vendor/golang.org/x/net/http2/hpack/tables.go new file mode 100644 index 0000000..a66cfbe --- /dev/null +++ b/vendor/golang.org/x/net/http2/hpack/tables.go | |||
@@ -0,0 +1,479 @@ | |||
1 | // Copyright 2014 The Go Authors. All rights reserved. | ||
2 | // Use of this source code is governed by a BSD-style | ||
3 | // license that can be found in the LICENSE file. | ||
4 | |||
5 | package hpack | ||
6 | |||
7 | import ( | ||
8 | "fmt" | ||
9 | ) | ||
10 | |||
11 | // headerFieldTable implements a list of HeaderFields. | ||
12 | // This is used to implement the static and dynamic tables. | ||
13 | type headerFieldTable struct { | ||
14 | // For static tables, entries are never evicted. | ||
15 | // | ||
16 | // For dynamic tables, entries are evicted from ents[0] and added to the end. | ||
17 | // Each entry has a unique id that starts at one and increments for each | ||
18 | // entry that is added. This unique id is stable across evictions, meaning | ||
19 | // it can be used as a pointer to a specific entry. As in hpack, unique ids | ||
20 | // are 1-based. The unique id for ents[k] is k + evictCount + 1. | ||
21 | // | ||
22 | // Zero is not a valid unique id. | ||
23 | // | ||
24 | // evictCount should not overflow in any remotely practical situation. In | ||
25 | // practice, we will have one dynamic table per HTTP/2 connection. If we | ||
26 | // assume a very powerful server that handles 1M QPS per connection and each | ||
27 | // request adds (then evicts) 100 entries from the table, it would still take | ||
28 | // 2M years for evictCount to overflow. | ||
29 | ents []HeaderField | ||
30 | evictCount uint64 | ||
31 | |||
32 | // byName maps a HeaderField name to the unique id of the newest entry with | ||
33 | // the same name. See above for a definition of "unique id". | ||
34 | byName map[string]uint64 | ||
35 | |||
36 | // byNameValue maps a HeaderField name/value pair to the unique id of the newest | ||
37 | // entry with the same name and value. See above for a definition of "unique id". | ||
38 | byNameValue map[pairNameValue]uint64 | ||
39 | } | ||
40 | |||
41 | type pairNameValue struct { | ||
42 | name, value string | ||
43 | } | ||
44 | |||
45 | func (t *headerFieldTable) init() { | ||
46 | t.byName = make(map[string]uint64) | ||
47 | t.byNameValue = make(map[pairNameValue]uint64) | ||
48 | } | ||
49 | |||
50 | // len reports the number of entries in the table. | ||
51 | func (t *headerFieldTable) len() int { | ||
52 | return len(t.ents) | ||
53 | } | ||
54 | |||
55 | // addEntry adds a new entry. | ||
56 | func (t *headerFieldTable) addEntry(f HeaderField) { | ||
57 | id := uint64(t.len()) + t.evictCount + 1 | ||
58 | t.byName[f.Name] = id | ||
59 | t.byNameValue[pairNameValue{f.Name, f.Value}] = id | ||
60 | t.ents = append(t.ents, f) | ||
61 | } | ||
62 | |||
63 | // evictOldest evicts the n oldest entries in the table. | ||
64 | func (t *headerFieldTable) evictOldest(n int) { | ||
65 | if n > t.len() { | ||
66 | panic(fmt.Sprintf("evictOldest(%v) on table with %v entries", n, t.len())) | ||
67 | } | ||
68 | for k := 0; k < n; k++ { | ||
69 | f := t.ents[k] | ||
70 | id := t.evictCount + uint64(k) + 1 | ||
71 | if t.byName[f.Name] == id { | ||
72 | delete(t.byName, f.Name) | ||
73 | } | ||
74 | if p := (pairNameValue{f.Name, f.Value}); t.byNameValue[p] == id { | ||
75 | delete(t.byNameValue, p) | ||
76 | } | ||
77 | } | ||
78 | copy(t.ents, t.ents[n:]) | ||
79 | for k := t.len() - n; k < t.len(); k++ { | ||
80 | t.ents[k] = HeaderField{} // so strings can be garbage collected | ||
81 | } | ||
82 | t.ents = t.ents[:t.len()-n] | ||
83 | if t.evictCount+uint64(n) < t.evictCount { | ||
84 | panic("evictCount overflow") | ||
85 | } | ||
86 | t.evictCount += uint64(n) | ||
87 | } | ||
88 | |||
89 | // search finds f in the table. If there is no match, i is 0. | ||
90 | // If both name and value match, i is the matched index and nameValueMatch | ||
91 | // becomes true. If only name matches, i points to that index and | ||
92 | // nameValueMatch becomes false. | ||
93 | // | ||
94 | // The returned index is a 1-based HPACK index. For dynamic tables, HPACK says | ||
95 | // that index 1 should be the newest entry, but t.ents[0] is the oldest entry, | ||
96 | // meaning t.ents is reversed for dynamic tables. Hence, when t is a dynamic | ||
97 | // table, the return value i actually refers to the entry t.ents[t.len()-i]. | ||
98 | // | ||
99 | // All tables are assumed to be a dynamic tables except for the global | ||
100 | // staticTable pointer. | ||
101 | // | ||
102 | // See Section 2.3.3. | ||
103 | func (t *headerFieldTable) search(f HeaderField) (i uint64, nameValueMatch bool) { | ||
104 | if !f.Sensitive { | ||
105 | if id := t.byNameValue[pairNameValue{f.Name, f.Value}]; id != 0 { | ||
106 | return t.idToIndex(id), true | ||
107 | } | ||
108 | } | ||
109 | if id := t.byName[f.Name]; id != 0 { | ||
110 | return t.idToIndex(id), false | ||
111 | } | ||
112 | return 0, false | ||
113 | } | ||
114 | |||
115 | // idToIndex converts a unique id to an HPACK index. | ||
116 | // See Section 2.3.3. | ||
117 | func (t *headerFieldTable) idToIndex(id uint64) uint64 { | ||
118 | if id <= t.evictCount { | ||
119 | panic(fmt.Sprintf("id (%v) <= evictCount (%v)", id, t.evictCount)) | ||
120 | } | ||
121 | k := id - t.evictCount - 1 // convert id to an index t.ents[k] | ||
122 | if t != staticTable { | ||
123 | return uint64(t.len()) - k // dynamic table | ||
124 | } | ||
125 | return k + 1 | ||
126 | } | ||
127 | |||
128 | // http://tools.ietf.org/html/draft-ietf-httpbis-header-compression-07#appendix-B | ||
129 | var staticTable = newStaticTable() | ||
130 | var staticTableEntries = [...]HeaderField{ | ||
131 | {Name: ":authority"}, | ||
132 | {Name: ":method", Value: "GET"}, | ||
133 | {Name: ":method", Value: "POST"}, | ||
134 | {Name: ":path", Value: "/"}, | ||
135 | {Name: ":path", Value: "/index.html"}, | ||
136 | {Name: ":scheme", Value: "http"}, | ||
137 | {Name: ":scheme", Value: "https"}, | ||
138 | {Name: ":status", Value: "200"}, | ||
139 | {Name: ":status", Value: "204"}, | ||
140 | {Name: ":status", Value: "206"}, | ||
141 | {Name: ":status", Value: "304"}, | ||
142 | {Name: ":status", Value: "400"}, | ||
143 | {Name: ":status", Value: "404"}, | ||
144 | {Name: ":status", Value: "500"}, | ||
145 | {Name: "accept-charset"}, | ||
146 | {Name: "accept-encoding", Value: "gzip, deflate"}, | ||
147 | {Name: "accept-language"}, | ||
148 | {Name: "accept-ranges"}, | ||
149 | {Name: "accept"}, | ||
150 | {Name: "access-control-allow-origin"}, | ||
151 | {Name: "age"}, | ||
152 | {Name: "allow"}, | ||
153 | {Name: "authorization"}, | ||
154 | {Name: "cache-control"}, | ||
155 | {Name: "content-disposition"}, | ||
156 | {Name: "content-encoding"}, | ||
157 | {Name: "content-language"}, | ||
158 | {Name: "content-length"}, | ||
159 | {Name: "content-location"}, | ||
160 | {Name: "content-range"}, | ||
161 | {Name: "content-type"}, | ||
162 | {Name: "cookie"}, | ||
163 | {Name: "date"}, | ||
164 | {Name: "etag"}, | ||
165 | {Name: "expect"}, | ||
166 | {Name: "expires"}, | ||
167 | {Name: "from"}, | ||
168 | {Name: "host"}, | ||
169 | {Name: "if-match"}, | ||
170 | {Name: "if-modified-since"}, | ||
171 | {Name: "if-none-match"}, | ||
172 | {Name: "if-range"}, | ||
173 | {Name: "if-unmodified-since"}, | ||
174 | {Name: "last-modified"}, | ||
175 | {Name: "link"}, | ||
176 | {Name: "location"}, | ||
177 | {Name: "max-forwards"}, | ||
178 | {Name: "proxy-authenticate"}, | ||
179 | {Name: "proxy-authorization"}, | ||
180 | {Name: "range"}, | ||
181 | {Name: "referer"}, | ||
182 | {Name: "refresh"}, | ||
183 | {Name: "retry-after"}, | ||
184 | {Name: "server"}, | ||
185 | {Name: "set-cookie"}, | ||
186 | {Name: "strict-transport-security"}, | ||
187 | {Name: "transfer-encoding"}, | ||
188 | {Name: "user-agent"}, | ||
189 | {Name: "vary"}, | ||
190 | {Name: "via"}, | ||
191 | {Name: "www-authenticate"}, | ||
192 | } | ||
193 | |||
194 | func newStaticTable() *headerFieldTable { | ||
195 | t := &headerFieldTable{} | ||
196 | t.init() | ||
197 | for _, e := range staticTableEntries[:] { | ||
198 | t.addEntry(e) | ||
199 | } | ||
200 | return t | ||
201 | } | ||
202 | |||
203 | var huffmanCodes = [256]uint32{ | ||
204 | 0x1ff8, | ||
205 | 0x7fffd8, | ||
206 | 0xfffffe2, | ||
207 | 0xfffffe3, | ||
208 | 0xfffffe4, | ||
209 | 0xfffffe5, | ||
210 | 0xfffffe6, | ||
211 | 0xfffffe7, | ||
212 | 0xfffffe8, | ||
213 | 0xffffea, | ||
214 | 0x3ffffffc, | ||
215 | 0xfffffe9, | ||
216 | 0xfffffea, | ||
217 | 0x3ffffffd, | ||
218 | 0xfffffeb, | ||
219 | 0xfffffec, | ||
220 | 0xfffffed, | ||
221 | 0xfffffee, | ||
222 | 0xfffffef, | ||
223 | 0xffffff0, | ||
224 | 0xffffff1, | ||
225 | 0xffffff2, | ||
226 | 0x3ffffffe, | ||
227 | 0xffffff3, | ||
228 | 0xffffff4, | ||
229 | 0xffffff5, | ||
230 | 0xffffff6, | ||
231 | 0xffffff7, | ||
232 | 0xffffff8, | ||
233 | 0xffffff9, | ||
234 | 0xffffffa, | ||
235 | 0xffffffb, | ||
236 | 0x14, | ||
237 | 0x3f8, | ||
238 | 0x3f9, | ||
239 | 0xffa, | ||
240 | 0x1ff9, | ||
241 | 0x15, | ||
242 | 0xf8, | ||
243 | 0x7fa, | ||
244 | 0x3fa, | ||
245 | 0x3fb, | ||
246 | 0xf9, | ||
247 | 0x7fb, | ||
248 | 0xfa, | ||
249 | 0x16, | ||
250 | 0x17, | ||
251 | 0x18, | ||
252 | 0x0, | ||
253 | 0x1, | ||
254 | 0x2, | ||
255 | 0x19, | ||
256 | 0x1a, | ||
257 | 0x1b, | ||
258 | 0x1c, | ||
259 | 0x1d, | ||
260 | 0x1e, | ||
261 | 0x1f, | ||
262 | 0x5c, | ||
263 | 0xfb, | ||
264 | 0x7ffc, | ||
265 | 0x20, | ||
266 | 0xffb, | ||
267 | 0x3fc, | ||
268 | 0x1ffa, | ||
269 | 0x21, | ||
270 | 0x5d, | ||
271 | 0x5e, | ||
272 | 0x5f, | ||
273 | 0x60, | ||
274 | 0x61, | ||
275 | 0x62, | ||
276 | 0x63, | ||
277 | 0x64, | ||
278 | 0x65, | ||
279 | 0x66, | ||
280 | 0x67, | ||
281 | 0x68, | ||
282 | 0x69, | ||
283 | 0x6a, | ||
284 | 0x6b, | ||
285 | 0x6c, | ||
286 | 0x6d, | ||
287 | 0x6e, | ||
288 | 0x6f, | ||
289 | 0x70, | ||
290 | 0x71, | ||
291 | 0x72, | ||
292 | 0xfc, | ||
293 | 0x73, | ||
294 | 0xfd, | ||
295 | 0x1ffb, | ||
296 | 0x7fff0, | ||
297 | 0x1ffc, | ||
298 | 0x3ffc, | ||
299 | 0x22, | ||
300 | 0x7ffd, | ||
301 | 0x3, | ||
302 | 0x23, | ||
303 | 0x4, | ||
304 | 0x24, | ||
305 | 0x5, | ||
306 | 0x25, | ||
307 | 0x26, | ||
308 | 0x27, | ||
309 | 0x6, | ||
310 | 0x74, | ||
311 | 0x75, | ||
312 | 0x28, | ||
313 | 0x29, | ||
314 | 0x2a, | ||
315 | 0x7, | ||
316 | 0x2b, | ||
317 | 0x76, | ||
318 | 0x2c, | ||
319 | 0x8, | ||
320 | 0x9, | ||
321 | 0x2d, | ||
322 | 0x77, | ||
323 | 0x78, | ||
324 | 0x79, | ||
325 | 0x7a, | ||
326 | 0x7b, | ||
327 | 0x7ffe, | ||
328 | 0x7fc, | ||
329 | 0x3ffd, | ||
330 | 0x1ffd, | ||
331 | 0xffffffc, | ||
332 | 0xfffe6, | ||
333 | 0x3fffd2, | ||
334 | 0xfffe7, | ||
335 | 0xfffe8, | ||
336 | 0x3fffd3, | ||
337 | 0x3fffd4, | ||
338 | 0x3fffd5, | ||
339 | 0x7fffd9, | ||
340 | 0x3fffd6, | ||
341 | 0x7fffda, | ||
342 | 0x7fffdb, | ||
343 | 0x7fffdc, | ||
344 | 0x7fffdd, | ||
345 | 0x7fffde, | ||
346 | 0xffffeb, | ||
347 | 0x7fffdf, | ||
348 | 0xffffec, | ||
349 | 0xffffed, | ||
350 | 0x3fffd7, | ||
351 | 0x7fffe0, | ||
352 | 0xffffee, | ||
353 | 0x7fffe1, | ||
354 | 0x7fffe2, | ||
355 | 0x7fffe3, | ||
356 | 0x7fffe4, | ||
357 | 0x1fffdc, | ||
358 | 0x3fffd8, | ||
359 | 0x7fffe5, | ||
360 | 0x3fffd9, | ||
361 | 0x7fffe6, | ||
362 | 0x7fffe7, | ||
363 | 0xffffef, | ||
364 | 0x3fffda, | ||
365 | 0x1fffdd, | ||
366 | 0xfffe9, | ||
367 | 0x3fffdb, | ||
368 | 0x3fffdc, | ||
369 | 0x7fffe8, | ||
370 | 0x7fffe9, | ||
371 | 0x1fffde, | ||
372 | 0x7fffea, | ||
373 | 0x3fffdd, | ||
374 | 0x3fffde, | ||
375 | 0xfffff0, | ||
376 | 0x1fffdf, | ||
377 | 0x3fffdf, | ||
378 | 0x7fffeb, | ||
379 | 0x7fffec, | ||
380 | 0x1fffe0, | ||
381 | 0x1fffe1, | ||
382 | 0x3fffe0, | ||
383 | 0x1fffe2, | ||
384 | 0x7fffed, | ||
385 | 0x3fffe1, | ||
386 | 0x7fffee, | ||
387 | 0x7fffef, | ||
388 | 0xfffea, | ||
389 | 0x3fffe2, | ||
390 | 0x3fffe3, | ||
391 | 0x3fffe4, | ||
392 | 0x7ffff0, | ||
393 | 0x3fffe5, | ||
394 | 0x3fffe6, | ||
395 | 0x7ffff1, | ||
396 | 0x3ffffe0, | ||
397 | 0x3ffffe1, | ||
398 | 0xfffeb, | ||
399 | 0x7fff1, | ||
400 | 0x3fffe7, | ||
401 | 0x7ffff2, | ||
402 | 0x3fffe8, | ||
403 | 0x1ffffec, | ||
404 | 0x3ffffe2, | ||
405 | 0x3ffffe3, | ||
406 | 0x3ffffe4, | ||
407 | 0x7ffffde, | ||
408 | 0x7ffffdf, | ||
409 | 0x3ffffe5, | ||
410 | 0xfffff1, | ||
411 | 0x1ffffed, | ||
412 | 0x7fff2, | ||
413 | 0x1fffe3, | ||
414 | 0x3ffffe6, | ||
415 | 0x7ffffe0, | ||
416 | 0x7ffffe1, | ||
417 | 0x3ffffe7, | ||
418 | 0x7ffffe2, | ||
419 | 0xfffff2, | ||
420 | 0x1fffe4, | ||
421 | 0x1fffe5, | ||
422 | 0x3ffffe8, | ||
423 | 0x3ffffe9, | ||
424 | 0xffffffd, | ||
425 | 0x7ffffe3, | ||
426 | 0x7ffffe4, | ||
427 | 0x7ffffe5, | ||
428 | 0xfffec, | ||
429 | 0xfffff3, | ||
430 | 0xfffed, | ||
431 | 0x1fffe6, | ||
432 | 0x3fffe9, | ||
433 | 0x1fffe7, | ||
434 | 0x1fffe8, | ||
435 | 0x7ffff3, | ||
436 | 0x3fffea, | ||
437 | 0x3fffeb, | ||
438 | 0x1ffffee, | ||
439 | 0x1ffffef, | ||
440 | 0xfffff4, | ||
441 | 0xfffff5, | ||
442 | 0x3ffffea, | ||
443 | 0x7ffff4, | ||
444 | 0x3ffffeb, | ||
445 | 0x7ffffe6, | ||
446 | 0x3ffffec, | ||
447 | 0x3ffffed, | ||
448 | 0x7ffffe7, | ||
449 | 0x7ffffe8, | ||
450 | 0x7ffffe9, | ||
451 | 0x7ffffea, | ||
452 | 0x7ffffeb, | ||
453 | 0xffffffe, | ||
454 | 0x7ffffec, | ||
455 | 0x7ffffed, | ||
456 | 0x7ffffee, | ||
457 | 0x7ffffef, | ||
458 | 0x7fffff0, | ||
459 | 0x3ffffee, | ||
460 | } | ||
461 | |||
462 | var huffmanCodeLen = [256]uint8{ | ||
463 | 13, 23, 28, 28, 28, 28, 28, 28, 28, 24, 30, 28, 28, 30, 28, 28, | ||
464 | 28, 28, 28, 28, 28, 28, 30, 28, 28, 28, 28, 28, 28, 28, 28, 28, | ||
465 | 6, 10, 10, 12, 13, 6, 8, 11, 10, 10, 8, 11, 8, 6, 6, 6, | ||
466 | 5, 5, 5, 6, 6, 6, 6, 6, 6, 6, 7, 8, 15, 6, 12, 10, | ||
467 | 13, 6, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, | ||
468 | 7, 7, 7, 7, 7, 7, 7, 7, 8, 7, 8, 13, 19, 13, 14, 6, | ||
469 | 15, 5, 6, 5, 6, 5, 6, 6, 6, 5, 7, 7, 6, 6, 6, 5, | ||
470 | 6, 7, 6, 5, 5, 6, 7, 7, 7, 7, 7, 15, 11, 14, 13, 28, | ||
471 | 20, 22, 20, 20, 22, 22, 22, 23, 22, 23, 23, 23, 23, 23, 24, 23, | ||
472 | 24, 24, 22, 23, 24, 23, 23, 23, 23, 21, 22, 23, 22, 23, 23, 24, | ||
473 | 22, 21, 20, 22, 22, 23, 23, 21, 23, 22, 22, 24, 21, 22, 23, 23, | ||
474 | 21, 21, 22, 21, 23, 22, 23, 23, 20, 22, 22, 22, 23, 22, 22, 23, | ||
475 | 26, 26, 20, 19, 22, 23, 22, 25, 26, 26, 26, 27, 27, 26, 24, 25, | ||
476 | 19, 21, 26, 27, 27, 26, 27, 24, 21, 21, 26, 26, 28, 27, 27, 27, | ||
477 | 20, 24, 20, 21, 22, 21, 21, 23, 22, 22, 25, 25, 24, 24, 26, 23, | ||
478 | 26, 27, 26, 26, 27, 27, 27, 27, 27, 28, 27, 27, 27, 27, 27, 26, | ||
479 | } | ||
diff --git a/vendor/golang.org/x/net/http2/http2.go b/vendor/golang.org/x/net/http2/http2.go new file mode 100644 index 0000000..d565f40 --- /dev/null +++ b/vendor/golang.org/x/net/http2/http2.go | |||
@@ -0,0 +1,391 @@ | |||
1 | // Copyright 2014 The Go Authors. All rights reserved. | ||
2 | // Use of this source code is governed by a BSD-style | ||
3 | // license that can be found in the LICENSE file. | ||
4 | |||
5 | // Package http2 implements the HTTP/2 protocol. | ||
6 | // | ||
7 | // This package is low-level and intended to be used directly by very | ||
8 | // few people. Most users will use it indirectly through the automatic | ||
9 | // use by the net/http package (from Go 1.6 and later). | ||
10 | // For use in earlier Go versions see ConfigureServer. (Transport support | ||
11 | // requires Go 1.6 or later) | ||
12 | // | ||
13 | // See https://http2.github.io/ for more information on HTTP/2. | ||
14 | // | ||
15 | // See https://http2.golang.org/ for a test server running this code. | ||
16 | // | ||
17 | package http2 // import "golang.org/x/net/http2" | ||
18 | |||
19 | import ( | ||
20 | "bufio" | ||
21 | "crypto/tls" | ||
22 | "errors" | ||
23 | "fmt" | ||
24 | "io" | ||
25 | "net/http" | ||
26 | "os" | ||
27 | "sort" | ||
28 | "strconv" | ||
29 | "strings" | ||
30 | "sync" | ||
31 | |||
32 | "golang.org/x/net/lex/httplex" | ||
33 | ) | ||
34 | |||
35 | var ( | ||
36 | VerboseLogs bool | ||
37 | logFrameWrites bool | ||
38 | logFrameReads bool | ||
39 | inTests bool | ||
40 | ) | ||
41 | |||
42 | func init() { | ||
43 | e := os.Getenv("GODEBUG") | ||
44 | if strings.Contains(e, "http2debug=1") { | ||
45 | VerboseLogs = true | ||
46 | } | ||
47 | if strings.Contains(e, "http2debug=2") { | ||
48 | VerboseLogs = true | ||
49 | logFrameWrites = true | ||
50 | logFrameReads = true | ||
51 | } | ||
52 | } | ||
53 | |||
54 | const ( | ||
55 | // ClientPreface is the string that must be sent by new | ||
56 | // connections from clients. | ||
57 | ClientPreface = "PRI * HTTP/2.0\r\n\r\nSM\r\n\r\n" | ||
58 | |||
59 | // SETTINGS_MAX_FRAME_SIZE default | ||
60 | // http://http2.github.io/http2-spec/#rfc.section.6.5.2 | ||
61 | initialMaxFrameSize = 16384 | ||
62 | |||
63 | // NextProtoTLS is the NPN/ALPN protocol negotiated during | ||
64 | // HTTP/2's TLS setup. | ||
65 | NextProtoTLS = "h2" | ||
66 | |||
67 | // http://http2.github.io/http2-spec/#SettingValues | ||
68 | initialHeaderTableSize = 4096 | ||
69 | |||
70 | initialWindowSize = 65535 // 6.9.2 Initial Flow Control Window Size | ||
71 | |||
72 | defaultMaxReadFrameSize = 1 << 20 | ||
73 | ) | ||
74 | |||
75 | var ( | ||
76 | clientPreface = []byte(ClientPreface) | ||
77 | ) | ||
78 | |||
79 | type streamState int | ||
80 | |||
81 | // HTTP/2 stream states. | ||
82 | // | ||
83 | // See http://tools.ietf.org/html/rfc7540#section-5.1. | ||
84 | // | ||
85 | // For simplicity, the server code merges "reserved (local)" into | ||
86 | // "half-closed (remote)". This is one less state transition to track. | ||
87 | // The only downside is that we send PUSH_PROMISEs slightly less | ||
88 | // liberally than allowable. More discussion here: | ||
89 | // https://lists.w3.org/Archives/Public/ietf-http-wg/2016JulSep/0599.html | ||
90 | // | ||
91 | // "reserved (remote)" is omitted since the client code does not | ||
92 | // support server push. | ||
93 | const ( | ||
94 | stateIdle streamState = iota | ||
95 | stateOpen | ||
96 | stateHalfClosedLocal | ||
97 | stateHalfClosedRemote | ||
98 | stateClosed | ||
99 | ) | ||
100 | |||
101 | var stateName = [...]string{ | ||
102 | stateIdle: "Idle", | ||
103 | stateOpen: "Open", | ||
104 | stateHalfClosedLocal: "HalfClosedLocal", | ||
105 | stateHalfClosedRemote: "HalfClosedRemote", | ||
106 | stateClosed: "Closed", | ||
107 | } | ||
108 | |||
109 | func (st streamState) String() string { | ||
110 | return stateName[st] | ||
111 | } | ||
112 | |||
113 | // Setting is a setting parameter: which setting it is, and its value. | ||
114 | type Setting struct { | ||
115 | // ID is which setting is being set. | ||
116 | // See http://http2.github.io/http2-spec/#SettingValues | ||
117 | ID SettingID | ||
118 | |||
119 | // Val is the value. | ||
120 | Val uint32 | ||
121 | } | ||
122 | |||
123 | func (s Setting) String() string { | ||
124 | return fmt.Sprintf("[%v = %d]", s.ID, s.Val) | ||
125 | } | ||
126 | |||
127 | // Valid reports whether the setting is valid. | ||
128 | func (s Setting) Valid() error { | ||
129 | // Limits and error codes from 6.5.2 Defined SETTINGS Parameters | ||
130 | switch s.ID { | ||
131 | case SettingEnablePush: | ||
132 | if s.Val != 1 && s.Val != 0 { | ||
133 | return ConnectionError(ErrCodeProtocol) | ||
134 | } | ||
135 | case SettingInitialWindowSize: | ||
136 | if s.Val > 1<<31-1 { | ||
137 | return ConnectionError(ErrCodeFlowControl) | ||
138 | } | ||
139 | case SettingMaxFrameSize: | ||
140 | if s.Val < 16384 || s.Val > 1<<24-1 { | ||
141 | return ConnectionError(ErrCodeProtocol) | ||
142 | } | ||
143 | } | ||
144 | return nil | ||
145 | } | ||
146 | |||
147 | // A SettingID is an HTTP/2 setting as defined in | ||
148 | // http://http2.github.io/http2-spec/#iana-settings | ||
149 | type SettingID uint16 | ||
150 | |||
151 | const ( | ||
152 | SettingHeaderTableSize SettingID = 0x1 | ||
153 | SettingEnablePush SettingID = 0x2 | ||
154 | SettingMaxConcurrentStreams SettingID = 0x3 | ||
155 | SettingInitialWindowSize SettingID = 0x4 | ||
156 | SettingMaxFrameSize SettingID = 0x5 | ||
157 | SettingMaxHeaderListSize SettingID = 0x6 | ||
158 | ) | ||
159 | |||
160 | var settingName = map[SettingID]string{ | ||
161 | SettingHeaderTableSize: "HEADER_TABLE_SIZE", | ||
162 | SettingEnablePush: "ENABLE_PUSH", | ||
163 | SettingMaxConcurrentStreams: "MAX_CONCURRENT_STREAMS", | ||
164 | SettingInitialWindowSize: "INITIAL_WINDOW_SIZE", | ||
165 | SettingMaxFrameSize: "MAX_FRAME_SIZE", | ||
166 | SettingMaxHeaderListSize: "MAX_HEADER_LIST_SIZE", | ||
167 | } | ||
168 | |||
169 | func (s SettingID) String() string { | ||
170 | if v, ok := settingName[s]; ok { | ||
171 | return v | ||
172 | } | ||
173 | return fmt.Sprintf("UNKNOWN_SETTING_%d", uint16(s)) | ||
174 | } | ||
175 | |||
176 | var ( | ||
177 | errInvalidHeaderFieldName = errors.New("http2: invalid header field name") | ||
178 | errInvalidHeaderFieldValue = errors.New("http2: invalid header field value") | ||
179 | ) | ||
180 | |||
181 | // validWireHeaderFieldName reports whether v is a valid header field | ||
182 | // name (key). See httplex.ValidHeaderName for the base rules. | ||
183 | // | ||
184 | // Further, http2 says: | ||
185 | // "Just as in HTTP/1.x, header field names are strings of ASCII | ||
186 | // characters that are compared in a case-insensitive | ||
187 | // fashion. However, header field names MUST be converted to | ||
188 | // lowercase prior to their encoding in HTTP/2. " | ||
189 | func validWireHeaderFieldName(v string) bool { | ||
190 | if len(v) == 0 { | ||
191 | return false | ||
192 | } | ||
193 | for _, r := range v { | ||
194 | if !httplex.IsTokenRune(r) { | ||
195 | return false | ||
196 | } | ||
197 | if 'A' <= r && r <= 'Z' { | ||
198 | return false | ||
199 | } | ||
200 | } | ||
201 | return true | ||
202 | } | ||
203 | |||
204 | var httpCodeStringCommon = map[int]string{} // n -> strconv.Itoa(n) | ||
205 | |||
206 | func init() { | ||
207 | for i := 100; i <= 999; i++ { | ||
208 | if v := http.StatusText(i); v != "" { | ||
209 | httpCodeStringCommon[i] = strconv.Itoa(i) | ||
210 | } | ||
211 | } | ||
212 | } | ||
213 | |||
214 | func httpCodeString(code int) string { | ||
215 | if s, ok := httpCodeStringCommon[code]; ok { | ||
216 | return s | ||
217 | } | ||
218 | return strconv.Itoa(code) | ||
219 | } | ||
220 | |||
221 | // from pkg io | ||
222 | type stringWriter interface { | ||
223 | WriteString(s string) (n int, err error) | ||
224 | } | ||
225 | |||
226 | // A gate lets two goroutines coordinate their activities. | ||
227 | type gate chan struct{} | ||
228 | |||
229 | func (g gate) Done() { g <- struct{}{} } | ||
230 | func (g gate) Wait() { <-g } | ||
231 | |||
232 | // A closeWaiter is like a sync.WaitGroup but only goes 1 to 0 (open to closed). | ||
233 | type closeWaiter chan struct{} | ||
234 | |||
235 | // Init makes a closeWaiter usable. | ||
236 | // It exists because so a closeWaiter value can be placed inside a | ||
237 | // larger struct and have the Mutex and Cond's memory in the same | ||
238 | // allocation. | ||
239 | func (cw *closeWaiter) Init() { | ||
240 | *cw = make(chan struct{}) | ||
241 | } | ||
242 | |||
243 | // Close marks the closeWaiter as closed and unblocks any waiters. | ||
244 | func (cw closeWaiter) Close() { | ||
245 | close(cw) | ||
246 | } | ||
247 | |||
248 | // Wait waits for the closeWaiter to become closed. | ||
249 | func (cw closeWaiter) Wait() { | ||
250 | <-cw | ||
251 | } | ||
252 | |||
253 | // bufferedWriter is a buffered writer that writes to w. | ||
254 | // Its buffered writer is lazily allocated as needed, to minimize | ||
255 | // idle memory usage with many connections. | ||
256 | type bufferedWriter struct { | ||
257 | w io.Writer // immutable | ||
258 | bw *bufio.Writer // non-nil when data is buffered | ||
259 | } | ||
260 | |||
261 | func newBufferedWriter(w io.Writer) *bufferedWriter { | ||
262 | return &bufferedWriter{w: w} | ||
263 | } | ||
264 | |||
265 | // bufWriterPoolBufferSize is the size of bufio.Writer's | ||
266 | // buffers created using bufWriterPool. | ||
267 | // | ||
268 | // TODO: pick a less arbitrary value? this is a bit under | ||
269 | // (3 x typical 1500 byte MTU) at least. Other than that, | ||
270 | // not much thought went into it. | ||
271 | const bufWriterPoolBufferSize = 4 << 10 | ||
272 | |||
273 | var bufWriterPool = sync.Pool{ | ||
274 | New: func() interface{} { | ||
275 | return bufio.NewWriterSize(nil, bufWriterPoolBufferSize) | ||
276 | }, | ||
277 | } | ||
278 | |||
279 | func (w *bufferedWriter) Available() int { | ||
280 | if w.bw == nil { | ||
281 | return bufWriterPoolBufferSize | ||
282 | } | ||
283 | return w.bw.Available() | ||
284 | } | ||
285 | |||
286 | func (w *bufferedWriter) Write(p []byte) (n int, err error) { | ||
287 | if w.bw == nil { | ||
288 | bw := bufWriterPool.Get().(*bufio.Writer) | ||
289 | bw.Reset(w.w) | ||
290 | w.bw = bw | ||
291 | } | ||
292 | return w.bw.Write(p) | ||
293 | } | ||
294 | |||
295 | func (w *bufferedWriter) Flush() error { | ||
296 | bw := w.bw | ||
297 | if bw == nil { | ||
298 | return nil | ||
299 | } | ||
300 | err := bw.Flush() | ||
301 | bw.Reset(nil) | ||
302 | bufWriterPool.Put(bw) | ||
303 | w.bw = nil | ||
304 | return err | ||
305 | } | ||
306 | |||
307 | func mustUint31(v int32) uint32 { | ||
308 | if v < 0 || v > 2147483647 { | ||
309 | panic("out of range") | ||
310 | } | ||
311 | return uint32(v) | ||
312 | } | ||
313 | |||
314 | // bodyAllowedForStatus reports whether a given response status code | ||
315 | // permits a body. See RFC 2616, section 4.4. | ||
316 | func bodyAllowedForStatus(status int) bool { | ||
317 | switch { | ||
318 | case status >= 100 && status <= 199: | ||
319 | return false | ||
320 | case status == 204: | ||
321 | return false | ||
322 | case status == 304: | ||
323 | return false | ||
324 | } | ||
325 | return true | ||
326 | } | ||
327 | |||
328 | type httpError struct { | ||
329 | msg string | ||
330 | timeout bool | ||
331 | } | ||
332 | |||
333 | func (e *httpError) Error() string { return e.msg } | ||
334 | func (e *httpError) Timeout() bool { return e.timeout } | ||
335 | func (e *httpError) Temporary() bool { return true } | ||
336 | |||
337 | var errTimeout error = &httpError{msg: "http2: timeout awaiting response headers", timeout: true} | ||
338 | |||
339 | type connectionStater interface { | ||
340 | ConnectionState() tls.ConnectionState | ||
341 | } | ||
342 | |||
343 | var sorterPool = sync.Pool{New: func() interface{} { return new(sorter) }} | ||
344 | |||
345 | type sorter struct { | ||
346 | v []string // owned by sorter | ||
347 | } | ||
348 | |||
349 | func (s *sorter) Len() int { return len(s.v) } | ||
350 | func (s *sorter) Swap(i, j int) { s.v[i], s.v[j] = s.v[j], s.v[i] } | ||
351 | func (s *sorter) Less(i, j int) bool { return s.v[i] < s.v[j] } | ||
352 | |||
353 | // Keys returns the sorted keys of h. | ||
354 | // | ||
355 | // The returned slice is only valid until s used again or returned to | ||
356 | // its pool. | ||
357 | func (s *sorter) Keys(h http.Header) []string { | ||
358 | keys := s.v[:0] | ||
359 | for k := range h { | ||
360 | keys = append(keys, k) | ||
361 | } | ||
362 | s.v = keys | ||
363 | sort.Sort(s) | ||
364 | return keys | ||
365 | } | ||
366 | |||
367 | func (s *sorter) SortStrings(ss []string) { | ||
368 | // Our sorter works on s.v, which sorter owns, so | ||
369 | // stash it away while we sort the user's buffer. | ||
370 | save := s.v | ||
371 | s.v = ss | ||
372 | sort.Sort(s) | ||
373 | s.v = save | ||
374 | } | ||
375 | |||
376 | // validPseudoPath reports whether v is a valid :path pseudo-header | ||
377 | // value. It must be either: | ||
378 | // | ||
379 | // *) a non-empty string starting with '/' | ||
380 | // *) the string '*', for OPTIONS requests. | ||
381 | // | ||
382 | // For now this is only used a quick check for deciding when to clean | ||
383 | // up Opaque URLs before sending requests from the Transport. | ||
384 | // See golang.org/issue/16847 | ||
385 | // | ||
386 | // We used to enforce that the path also didn't start with "//", but | ||
387 | // Google's GFE accepts such paths and Chrome sends them, so ignore | ||
388 | // that part of the spec. See golang.org/issue/19103. | ||
389 | func validPseudoPath(v string) bool { | ||
390 | return (len(v) > 0 && v[0] == '/') || v == "*" | ||
391 | } | ||
diff --git a/vendor/golang.org/x/net/http2/not_go16.go b/vendor/golang.org/x/net/http2/not_go16.go new file mode 100644 index 0000000..508cebc --- /dev/null +++ b/vendor/golang.org/x/net/http2/not_go16.go | |||
@@ -0,0 +1,21 @@ | |||
1 | // Copyright 2015 The Go Authors. All rights reserved. | ||
2 | // Use of this source code is governed by a BSD-style | ||
3 | // license that can be found in the LICENSE file. | ||
4 | |||
5 | // +build !go1.6 | ||
6 | |||
7 | package http2 | ||
8 | |||
9 | import ( | ||
10 | "net/http" | ||
11 | "time" | ||
12 | ) | ||
13 | |||
14 | func configureTransport(t1 *http.Transport) (*Transport, error) { | ||
15 | return nil, errTransportVersion | ||
16 | } | ||
17 | |||
18 | func transportExpectContinueTimeout(t1 *http.Transport) time.Duration { | ||
19 | return 0 | ||
20 | |||
21 | } | ||
diff --git a/vendor/golang.org/x/net/http2/not_go17.go b/vendor/golang.org/x/net/http2/not_go17.go new file mode 100644 index 0000000..140434a --- /dev/null +++ b/vendor/golang.org/x/net/http2/not_go17.go | |||
@@ -0,0 +1,87 @@ | |||
1 | // Copyright 2016 The Go Authors. All rights reserved. | ||
2 | // Use of this source code is governed by a BSD-style | ||
3 | // license that can be found in the LICENSE file. | ||
4 | |||
5 | // +build !go1.7 | ||
6 | |||
7 | package http2 | ||
8 | |||
9 | import ( | ||
10 | "crypto/tls" | ||
11 | "net" | ||
12 | "net/http" | ||
13 | "time" | ||
14 | ) | ||
15 | |||
16 | type contextContext interface { | ||
17 | Done() <-chan struct{} | ||
18 | Err() error | ||
19 | } | ||
20 | |||
21 | type fakeContext struct{} | ||
22 | |||
23 | func (fakeContext) Done() <-chan struct{} { return nil } | ||
24 | func (fakeContext) Err() error { panic("should not be called") } | ||
25 | |||
26 | func reqContext(r *http.Request) fakeContext { | ||
27 | return fakeContext{} | ||
28 | } | ||
29 | |||
30 | func setResponseUncompressed(res *http.Response) { | ||
31 | // Nothing. | ||
32 | } | ||
33 | |||
34 | type clientTrace struct{} | ||
35 | |||
36 | func requestTrace(*http.Request) *clientTrace { return nil } | ||
37 | func traceGotConn(*http.Request, *ClientConn) {} | ||
38 | func traceFirstResponseByte(*clientTrace) {} | ||
39 | func traceWroteHeaders(*clientTrace) {} | ||
40 | func traceWroteRequest(*clientTrace, error) {} | ||
41 | func traceGot100Continue(trace *clientTrace) {} | ||
42 | func traceWait100Continue(trace *clientTrace) {} | ||
43 | |||
44 | func nop() {} | ||
45 | |||
46 | func serverConnBaseContext(c net.Conn, opts *ServeConnOpts) (ctx contextContext, cancel func()) { | ||
47 | return nil, nop | ||
48 | } | ||
49 | |||
50 | func contextWithCancel(ctx contextContext) (_ contextContext, cancel func()) { | ||
51 | return ctx, nop | ||
52 | } | ||
53 | |||
54 | func requestWithContext(req *http.Request, ctx contextContext) *http.Request { | ||
55 | return req | ||
56 | } | ||
57 | |||
58 | // temporary copy of Go 1.6's private tls.Config.clone: | ||
59 | func cloneTLSConfig(c *tls.Config) *tls.Config { | ||
60 | return &tls.Config{ | ||
61 | Rand: c.Rand, | ||
62 | Time: c.Time, | ||
63 | Certificates: c.Certificates, | ||
64 | NameToCertificate: c.NameToCertificate, | ||
65 | GetCertificate: c.GetCertificate, | ||
66 | RootCAs: c.RootCAs, | ||
67 | NextProtos: c.NextProtos, | ||
68 | ServerName: c.ServerName, | ||
69 | ClientAuth: c.ClientAuth, | ||
70 | ClientCAs: c.ClientCAs, | ||
71 | InsecureSkipVerify: c.InsecureSkipVerify, | ||
72 | CipherSuites: c.CipherSuites, | ||
73 | PreferServerCipherSuites: c.PreferServerCipherSuites, | ||
74 | SessionTicketsDisabled: c.SessionTicketsDisabled, | ||
75 | SessionTicketKey: c.SessionTicketKey, | ||
76 | ClientSessionCache: c.ClientSessionCache, | ||
77 | MinVersion: c.MinVersion, | ||
78 | MaxVersion: c.MaxVersion, | ||
79 | CurvePreferences: c.CurvePreferences, | ||
80 | } | ||
81 | } | ||
82 | |||
83 | func (cc *ClientConn) Ping(ctx contextContext) error { | ||
84 | return cc.ping(ctx) | ||
85 | } | ||
86 | |||
87 | func (t *Transport) idleConnTimeout() time.Duration { return 0 } | ||
diff --git a/vendor/golang.org/x/net/http2/not_go18.go b/vendor/golang.org/x/net/http2/not_go18.go new file mode 100644 index 0000000..6f8d3f8 --- /dev/null +++ b/vendor/golang.org/x/net/http2/not_go18.go | |||
@@ -0,0 +1,29 @@ | |||
1 | // Copyright 2016 The Go Authors. All rights reserved. | ||
2 | // Use of this source code is governed by a BSD-style | ||
3 | // license that can be found in the LICENSE file. | ||
4 | |||
5 | // +build !go1.8 | ||
6 | |||
7 | package http2 | ||
8 | |||
9 | import ( | ||
10 | "io" | ||
11 | "net/http" | ||
12 | ) | ||
13 | |||
14 | func configureServer18(h1 *http.Server, h2 *Server) error { | ||
15 | // No IdleTimeout to sync prior to Go 1.8. | ||
16 | return nil | ||
17 | } | ||
18 | |||
19 | func shouldLogPanic(panicValue interface{}) bool { | ||
20 | return panicValue != nil | ||
21 | } | ||
22 | |||
23 | func reqGetBody(req *http.Request) func() (io.ReadCloser, error) { | ||
24 | return nil | ||
25 | } | ||
26 | |||
27 | func reqBodyIsNoBody(io.ReadCloser) bool { return false } | ||
28 | |||
29 | func go18httpNoBody() io.ReadCloser { return nil } // for tests only | ||
diff --git a/vendor/golang.org/x/net/http2/not_go19.go b/vendor/golang.org/x/net/http2/not_go19.go new file mode 100644 index 0000000..5ae0772 --- /dev/null +++ b/vendor/golang.org/x/net/http2/not_go19.go | |||
@@ -0,0 +1,16 @@ | |||
1 | // Copyright 2016 The Go Authors. All rights reserved. | ||
2 | // Use of this source code is governed by a BSD-style | ||
3 | // license that can be found in the LICENSE file. | ||
4 | |||
5 | // +build !go1.9 | ||
6 | |||
7 | package http2 | ||
8 | |||
9 | import ( | ||
10 | "net/http" | ||
11 | ) | ||
12 | |||
13 | func configureServer19(s *http.Server, conf *Server) error { | ||
14 | // not supported prior to go1.9 | ||
15 | return nil | ||
16 | } | ||
diff --git a/vendor/golang.org/x/net/http2/pipe.go b/vendor/golang.org/x/net/http2/pipe.go new file mode 100644 index 0000000..a614009 --- /dev/null +++ b/vendor/golang.org/x/net/http2/pipe.go | |||
@@ -0,0 +1,163 @@ | |||
1 | // Copyright 2014 The Go Authors. All rights reserved. | ||
2 | // Use of this source code is governed by a BSD-style | ||
3 | // license that can be found in the LICENSE file. | ||
4 | |||
5 | package http2 | ||
6 | |||
7 | import ( | ||
8 | "errors" | ||
9 | "io" | ||
10 | "sync" | ||
11 | ) | ||
12 | |||
13 | // pipe is a goroutine-safe io.Reader/io.Writer pair. It's like | ||
14 | // io.Pipe except there are no PipeReader/PipeWriter halves, and the | ||
15 | // underlying buffer is an interface. (io.Pipe is always unbuffered) | ||
16 | type pipe struct { | ||
17 | mu sync.Mutex | ||
18 | c sync.Cond // c.L lazily initialized to &p.mu | ||
19 | b pipeBuffer // nil when done reading | ||
20 | err error // read error once empty. non-nil means closed. | ||
21 | breakErr error // immediate read error (caller doesn't see rest of b) | ||
22 | donec chan struct{} // closed on error | ||
23 | readFn func() // optional code to run in Read before error | ||
24 | } | ||
25 | |||
26 | type pipeBuffer interface { | ||
27 | Len() int | ||
28 | io.Writer | ||
29 | io.Reader | ||
30 | } | ||
31 | |||
32 | func (p *pipe) Len() int { | ||
33 | p.mu.Lock() | ||
34 | defer p.mu.Unlock() | ||
35 | if p.b == nil { | ||
36 | return 0 | ||
37 | } | ||
38 | return p.b.Len() | ||
39 | } | ||
40 | |||
41 | // Read waits until data is available and copies bytes | ||
42 | // from the buffer into p. | ||
43 | func (p *pipe) Read(d []byte) (n int, err error) { | ||
44 | p.mu.Lock() | ||
45 | defer p.mu.Unlock() | ||
46 | if p.c.L == nil { | ||
47 | p.c.L = &p.mu | ||
48 | } | ||
49 | for { | ||
50 | if p.breakErr != nil { | ||
51 | return 0, p.breakErr | ||
52 | } | ||
53 | if p.b != nil && p.b.Len() > 0 { | ||
54 | return p.b.Read(d) | ||
55 | } | ||
56 | if p.err != nil { | ||
57 | if p.readFn != nil { | ||
58 | p.readFn() // e.g. copy trailers | ||
59 | p.readFn = nil // not sticky like p.err | ||
60 | } | ||
61 | p.b = nil | ||
62 | return 0, p.err | ||
63 | } | ||
64 | p.c.Wait() | ||
65 | } | ||
66 | } | ||
67 | |||
68 | var errClosedPipeWrite = errors.New("write on closed buffer") | ||
69 | |||
70 | // Write copies bytes from p into the buffer and wakes a reader. | ||
71 | // It is an error to write more data than the buffer can hold. | ||
72 | func (p *pipe) Write(d []byte) (n int, err error) { | ||
73 | p.mu.Lock() | ||
74 | defer p.mu.Unlock() | ||
75 | if p.c.L == nil { | ||
76 | p.c.L = &p.mu | ||
77 | } | ||
78 | defer p.c.Signal() | ||
79 | if p.err != nil { | ||
80 | return 0, errClosedPipeWrite | ||
81 | } | ||
82 | if p.breakErr != nil { | ||
83 | return len(d), nil // discard when there is no reader | ||
84 | } | ||
85 | return p.b.Write(d) | ||
86 | } | ||
87 | |||
88 | // CloseWithError causes the next Read (waking up a current blocked | ||
89 | // Read if needed) to return the provided err after all data has been | ||
90 | // read. | ||
91 | // | ||
92 | // The error must be non-nil. | ||
93 | func (p *pipe) CloseWithError(err error) { p.closeWithError(&p.err, err, nil) } | ||
94 | |||
95 | // BreakWithError causes the next Read (waking up a current blocked | ||
96 | // Read if needed) to return the provided err immediately, without | ||
97 | // waiting for unread data. | ||
98 | func (p *pipe) BreakWithError(err error) { p.closeWithError(&p.breakErr, err, nil) } | ||
99 | |||
100 | // closeWithErrorAndCode is like CloseWithError but also sets some code to run | ||
101 | // in the caller's goroutine before returning the error. | ||
102 | func (p *pipe) closeWithErrorAndCode(err error, fn func()) { p.closeWithError(&p.err, err, fn) } | ||
103 | |||
104 | func (p *pipe) closeWithError(dst *error, err error, fn func()) { | ||
105 | if err == nil { | ||
106 | panic("err must be non-nil") | ||
107 | } | ||
108 | p.mu.Lock() | ||
109 | defer p.mu.Unlock() | ||
110 | if p.c.L == nil { | ||
111 | p.c.L = &p.mu | ||
112 | } | ||
113 | defer p.c.Signal() | ||
114 | if *dst != nil { | ||
115 | // Already been done. | ||
116 | return | ||
117 | } | ||
118 | p.readFn = fn | ||
119 | if dst == &p.breakErr { | ||
120 | p.b = nil | ||
121 | } | ||
122 | *dst = err | ||
123 | p.closeDoneLocked() | ||
124 | } | ||
125 | |||
126 | // requires p.mu be held. | ||
127 | func (p *pipe) closeDoneLocked() { | ||
128 | if p.donec == nil { | ||
129 | return | ||
130 | } | ||
131 | // Close if unclosed. This isn't racy since we always | ||
132 | // hold p.mu while closing. | ||
133 | select { | ||
134 | case <-p.donec: | ||
135 | default: | ||
136 | close(p.donec) | ||
137 | } | ||
138 | } | ||
139 | |||
140 | // Err returns the error (if any) first set by BreakWithError or CloseWithError. | ||
141 | func (p *pipe) Err() error { | ||
142 | p.mu.Lock() | ||
143 | defer p.mu.Unlock() | ||
144 | if p.breakErr != nil { | ||
145 | return p.breakErr | ||
146 | } | ||
147 | return p.err | ||
148 | } | ||
149 | |||
150 | // Done returns a channel which is closed if and when this pipe is closed | ||
151 | // with CloseWithError. | ||
152 | func (p *pipe) Done() <-chan struct{} { | ||
153 | p.mu.Lock() | ||
154 | defer p.mu.Unlock() | ||
155 | if p.donec == nil { | ||
156 | p.donec = make(chan struct{}) | ||
157 | if p.err != nil || p.breakErr != nil { | ||
158 | // Already hit an error. | ||
159 | p.closeDoneLocked() | ||
160 | } | ||
161 | } | ||
162 | return p.donec | ||
163 | } | ||
diff --git a/vendor/golang.org/x/net/http2/server.go b/vendor/golang.org/x/net/http2/server.go new file mode 100644 index 0000000..eae143d --- /dev/null +++ b/vendor/golang.org/x/net/http2/server.go | |||
@@ -0,0 +1,2857 @@ | |||
1 | // Copyright 2014 The Go Authors. All rights reserved. | ||
2 | // Use of this source code is governed by a BSD-style | ||
3 | // license that can be found in the LICENSE file. | ||
4 | |||
5 | // TODO: turn off the serve goroutine when idle, so | ||
6 | // an idle conn only has the readFrames goroutine active. (which could | ||
7 | // also be optimized probably to pin less memory in crypto/tls). This | ||
8 | // would involve tracking when the serve goroutine is active (atomic | ||
9 | // int32 read/CAS probably?) and starting it up when frames arrive, | ||
10 | // and shutting it down when all handlers exit. the occasional PING | ||
11 | // packets could use time.AfterFunc to call sc.wakeStartServeLoop() | ||
12 | // (which is a no-op if already running) and then queue the PING write | ||
13 | // as normal. The serve loop would then exit in most cases (if no | ||
14 | // Handlers running) and not be woken up again until the PING packet | ||
15 | // returns. | ||
16 | |||
17 | // TODO (maybe): add a mechanism for Handlers to going into | ||
18 | // half-closed-local mode (rw.(io.Closer) test?) but not exit their | ||
19 | // handler, and continue to be able to read from the | ||
20 | // Request.Body. This would be a somewhat semantic change from HTTP/1 | ||
21 | // (or at least what we expose in net/http), so I'd probably want to | ||
22 | // add it there too. For now, this package says that returning from | ||
23 | // the Handler ServeHTTP function means you're both done reading and | ||
24 | // done writing, without a way to stop just one or the other. | ||
25 | |||
26 | package http2 | ||
27 | |||
28 | import ( | ||
29 | "bufio" | ||
30 | "bytes" | ||
31 | "crypto/tls" | ||
32 | "errors" | ||
33 | "fmt" | ||
34 | "io" | ||
35 | "log" | ||
36 | "math" | ||
37 | "net" | ||
38 | "net/http" | ||
39 | "net/textproto" | ||
40 | "net/url" | ||
41 | "os" | ||
42 | "reflect" | ||
43 | "runtime" | ||
44 | "strconv" | ||
45 | "strings" | ||
46 | "sync" | ||
47 | "time" | ||
48 | |||
49 | "golang.org/x/net/http2/hpack" | ||
50 | ) | ||
51 | |||
52 | const ( | ||
53 | prefaceTimeout = 10 * time.Second | ||
54 | firstSettingsTimeout = 2 * time.Second // should be in-flight with preface anyway | ||
55 | handlerChunkWriteSize = 4 << 10 | ||
56 | defaultMaxStreams = 250 // TODO: make this 100 as the GFE seems to? | ||
57 | ) | ||
58 | |||
59 | var ( | ||
60 | errClientDisconnected = errors.New("client disconnected") | ||
61 | errClosedBody = errors.New("body closed by handler") | ||
62 | errHandlerComplete = errors.New("http2: request body closed due to handler exiting") | ||
63 | errStreamClosed = errors.New("http2: stream closed") | ||
64 | ) | ||
65 | |||
66 | var responseWriterStatePool = sync.Pool{ | ||
67 | New: func() interface{} { | ||
68 | rws := &responseWriterState{} | ||
69 | rws.bw = bufio.NewWriterSize(chunkWriter{rws}, handlerChunkWriteSize) | ||
70 | return rws | ||
71 | }, | ||
72 | } | ||
73 | |||
74 | // Test hooks. | ||
75 | var ( | ||
76 | testHookOnConn func() | ||
77 | testHookGetServerConn func(*serverConn) | ||
78 | testHookOnPanicMu *sync.Mutex // nil except in tests | ||
79 | testHookOnPanic func(sc *serverConn, panicVal interface{}) (rePanic bool) | ||
80 | ) | ||
81 | |||
82 | // Server is an HTTP/2 server. | ||
83 | type Server struct { | ||
84 | // MaxHandlers limits the number of http.Handler ServeHTTP goroutines | ||
85 | // which may run at a time over all connections. | ||
86 | // Negative or zero no limit. | ||
87 | // TODO: implement | ||
88 | MaxHandlers int | ||
89 | |||
90 | // MaxConcurrentStreams optionally specifies the number of | ||
91 | // concurrent streams that each client may have open at a | ||
92 | // time. This is unrelated to the number of http.Handler goroutines | ||
93 | // which may be active globally, which is MaxHandlers. | ||
94 | // If zero, MaxConcurrentStreams defaults to at least 100, per | ||
95 | // the HTTP/2 spec's recommendations. | ||
96 | MaxConcurrentStreams uint32 | ||
97 | |||
98 | // MaxReadFrameSize optionally specifies the largest frame | ||
99 | // this server is willing to read. A valid value is between | ||
100 | // 16k and 16M, inclusive. If zero or otherwise invalid, a | ||
101 | // default value is used. | ||
102 | MaxReadFrameSize uint32 | ||
103 | |||
104 | // PermitProhibitedCipherSuites, if true, permits the use of | ||
105 | // cipher suites prohibited by the HTTP/2 spec. | ||
106 | PermitProhibitedCipherSuites bool | ||
107 | |||
108 | // IdleTimeout specifies how long until idle clients should be | ||
109 | // closed with a GOAWAY frame. PING frames are not considered | ||
110 | // activity for the purposes of IdleTimeout. | ||
111 | IdleTimeout time.Duration | ||
112 | |||
113 | // MaxUploadBufferPerConnection is the size of the initial flow | ||
114 | // control window for each connections. The HTTP/2 spec does not | ||
115 | // allow this to be smaller than 65535 or larger than 2^32-1. | ||
116 | // If the value is outside this range, a default value will be | ||
117 | // used instead. | ||
118 | MaxUploadBufferPerConnection int32 | ||
119 | |||
120 | // MaxUploadBufferPerStream is the size of the initial flow control | ||
121 | // window for each stream. The HTTP/2 spec does not allow this to | ||
122 | // be larger than 2^32-1. If the value is zero or larger than the | ||
123 | // maximum, a default value will be used instead. | ||
124 | MaxUploadBufferPerStream int32 | ||
125 | |||
126 | // NewWriteScheduler constructs a write scheduler for a connection. | ||
127 | // If nil, a default scheduler is chosen. | ||
128 | NewWriteScheduler func() WriteScheduler | ||
129 | |||
130 | // Internal state. This is a pointer (rather than embedded directly) | ||
131 | // so that we don't embed a Mutex in this struct, which will make the | ||
132 | // struct non-copyable, which might break some callers. | ||
133 | state *serverInternalState | ||
134 | } | ||
135 | |||
136 | func (s *Server) initialConnRecvWindowSize() int32 { | ||
137 | if s.MaxUploadBufferPerConnection > initialWindowSize { | ||
138 | return s.MaxUploadBufferPerConnection | ||
139 | } | ||
140 | return 1 << 20 | ||
141 | } | ||
142 | |||
143 | func (s *Server) initialStreamRecvWindowSize() int32 { | ||
144 | if s.MaxUploadBufferPerStream > 0 { | ||
145 | return s.MaxUploadBufferPerStream | ||
146 | } | ||
147 | return 1 << 20 | ||
148 | } | ||
149 | |||
150 | func (s *Server) maxReadFrameSize() uint32 { | ||
151 | if v := s.MaxReadFrameSize; v >= minMaxFrameSize && v <= maxFrameSize { | ||
152 | return v | ||
153 | } | ||
154 | return defaultMaxReadFrameSize | ||
155 | } | ||
156 | |||
157 | func (s *Server) maxConcurrentStreams() uint32 { | ||
158 | if v := s.MaxConcurrentStreams; v > 0 { | ||
159 | return v | ||
160 | } | ||
161 | return defaultMaxStreams | ||
162 | } | ||
163 | |||
164 | type serverInternalState struct { | ||
165 | mu sync.Mutex | ||
166 | activeConns map[*serverConn]struct{} | ||
167 | } | ||
168 | |||
169 | func (s *serverInternalState) registerConn(sc *serverConn) { | ||
170 | if s == nil { | ||
171 | return // if the Server was used without calling ConfigureServer | ||
172 | } | ||
173 | s.mu.Lock() | ||
174 | s.activeConns[sc] = struct{}{} | ||
175 | s.mu.Unlock() | ||
176 | } | ||
177 | |||
178 | func (s *serverInternalState) unregisterConn(sc *serverConn) { | ||
179 | if s == nil { | ||
180 | return // if the Server was used without calling ConfigureServer | ||
181 | } | ||
182 | s.mu.Lock() | ||
183 | delete(s.activeConns, sc) | ||
184 | s.mu.Unlock() | ||
185 | } | ||
186 | |||
187 | func (s *serverInternalState) startGracefulShutdown() { | ||
188 | if s == nil { | ||
189 | return // if the Server was used without calling ConfigureServer | ||
190 | } | ||
191 | s.mu.Lock() | ||
192 | for sc := range s.activeConns { | ||
193 | sc.startGracefulShutdown() | ||
194 | } | ||
195 | s.mu.Unlock() | ||
196 | } | ||
197 | |||
198 | // ConfigureServer adds HTTP/2 support to a net/http Server. | ||
199 | // | ||
200 | // The configuration conf may be nil. | ||
201 | // | ||
202 | // ConfigureServer must be called before s begins serving. | ||
203 | func ConfigureServer(s *http.Server, conf *Server) error { | ||
204 | if s == nil { | ||
205 | panic("nil *http.Server") | ||
206 | } | ||
207 | if conf == nil { | ||
208 | conf = new(Server) | ||
209 | } | ||
210 | conf.state = &serverInternalState{activeConns: make(map[*serverConn]struct{})} | ||
211 | if err := configureServer18(s, conf); err != nil { | ||
212 | return err | ||
213 | } | ||
214 | if err := configureServer19(s, conf); err != nil { | ||
215 | return err | ||
216 | } | ||
217 | |||
218 | if s.TLSConfig == nil { | ||
219 | s.TLSConfig = new(tls.Config) | ||
220 | } else if s.TLSConfig.CipherSuites != nil { | ||
221 | // If they already provided a CipherSuite list, return | ||
222 | // an error if it has a bad order or is missing | ||
223 | // ECDHE_RSA_WITH_AES_128_GCM_SHA256. | ||
224 | const requiredCipher = tls.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 | ||
225 | haveRequired := false | ||
226 | sawBad := false | ||
227 | for i, cs := range s.TLSConfig.CipherSuites { | ||
228 | if cs == requiredCipher { | ||
229 | haveRequired = true | ||
230 | } | ||
231 | if isBadCipher(cs) { | ||
232 | sawBad = true | ||
233 | } else if sawBad { | ||
234 | return fmt.Errorf("http2: TLSConfig.CipherSuites index %d contains an HTTP/2-approved cipher suite (%#04x), but it comes after unapproved cipher suites. With this configuration, clients that don't support previous, approved cipher suites may be given an unapproved one and reject the connection.", i, cs) | ||
235 | } | ||
236 | } | ||
237 | if !haveRequired { | ||
238 | return fmt.Errorf("http2: TLSConfig.CipherSuites is missing HTTP/2-required TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256") | ||
239 | } | ||
240 | } | ||
241 | |||
242 | // Note: not setting MinVersion to tls.VersionTLS12, | ||
243 | // as we don't want to interfere with HTTP/1.1 traffic | ||
244 | // on the user's server. We enforce TLS 1.2 later once | ||
245 | // we accept a connection. Ideally this should be done | ||
246 | // during next-proto selection, but using TLS <1.2 with | ||
247 | // HTTP/2 is still the client's bug. | ||
248 | |||
249 | s.TLSConfig.PreferServerCipherSuites = true | ||
250 | |||
251 | haveNPN := false | ||
252 | for _, p := range s.TLSConfig.NextProtos { | ||
253 | if p == NextProtoTLS { | ||
254 | haveNPN = true | ||
255 | break | ||
256 | } | ||
257 | } | ||
258 | if !haveNPN { | ||
259 | s.TLSConfig.NextProtos = append(s.TLSConfig.NextProtos, NextProtoTLS) | ||
260 | } | ||
261 | |||
262 | if s.TLSNextProto == nil { | ||
263 | s.TLSNextProto = map[string]func(*http.Server, *tls.Conn, http.Handler){} | ||
264 | } | ||
265 | protoHandler := func(hs *http.Server, c *tls.Conn, h http.Handler) { | ||
266 | if testHookOnConn != nil { | ||
267 | testHookOnConn() | ||
268 | } | ||
269 | conf.ServeConn(c, &ServeConnOpts{ | ||
270 | Handler: h, | ||
271 | BaseConfig: hs, | ||
272 | }) | ||
273 | } | ||
274 | s.TLSNextProto[NextProtoTLS] = protoHandler | ||
275 | return nil | ||
276 | } | ||
277 | |||
278 | // ServeConnOpts are options for the Server.ServeConn method. | ||
279 | type ServeConnOpts struct { | ||
280 | // BaseConfig optionally sets the base configuration | ||
281 | // for values. If nil, defaults are used. | ||
282 | BaseConfig *http.Server | ||
283 | |||
284 | // Handler specifies which handler to use for processing | ||
285 | // requests. If nil, BaseConfig.Handler is used. If BaseConfig | ||
286 | // or BaseConfig.Handler is nil, http.DefaultServeMux is used. | ||
287 | Handler http.Handler | ||
288 | } | ||
289 | |||
290 | func (o *ServeConnOpts) baseConfig() *http.Server { | ||
291 | if o != nil && o.BaseConfig != nil { | ||
292 | return o.BaseConfig | ||
293 | } | ||
294 | return new(http.Server) | ||
295 | } | ||
296 | |||
297 | func (o *ServeConnOpts) handler() http.Handler { | ||
298 | if o != nil { | ||
299 | if o.Handler != nil { | ||
300 | return o.Handler | ||
301 | } | ||
302 | if o.BaseConfig != nil && o.BaseConfig.Handler != nil { | ||
303 | return o.BaseConfig.Handler | ||
304 | } | ||
305 | } | ||
306 | return http.DefaultServeMux | ||
307 | } | ||
308 | |||
309 | // ServeConn serves HTTP/2 requests on the provided connection and | ||
310 | // blocks until the connection is no longer readable. | ||
311 | // | ||
312 | // ServeConn starts speaking HTTP/2 assuming that c has not had any | ||
313 | // reads or writes. It writes its initial settings frame and expects | ||
314 | // to be able to read the preface and settings frame from the | ||
315 | // client. If c has a ConnectionState method like a *tls.Conn, the | ||
316 | // ConnectionState is used to verify the TLS ciphersuite and to set | ||
317 | // the Request.TLS field in Handlers. | ||
318 | // | ||
319 | // ServeConn does not support h2c by itself. Any h2c support must be | ||
320 | // implemented in terms of providing a suitably-behaving net.Conn. | ||
321 | // | ||
322 | // The opts parameter is optional. If nil, default values are used. | ||
323 | func (s *Server) ServeConn(c net.Conn, opts *ServeConnOpts) { | ||
324 | baseCtx, cancel := serverConnBaseContext(c, opts) | ||
325 | defer cancel() | ||
326 | |||
327 | sc := &serverConn{ | ||
328 | srv: s, | ||
329 | hs: opts.baseConfig(), | ||
330 | conn: c, | ||
331 | baseCtx: baseCtx, | ||
332 | remoteAddrStr: c.RemoteAddr().String(), | ||
333 | bw: newBufferedWriter(c), | ||
334 | handler: opts.handler(), | ||
335 | streams: make(map[uint32]*stream), | ||
336 | readFrameCh: make(chan readFrameResult), | ||
337 | wantWriteFrameCh: make(chan FrameWriteRequest, 8), | ||
338 | serveMsgCh: make(chan interface{}, 8), | ||
339 | wroteFrameCh: make(chan frameWriteResult, 1), // buffered; one send in writeFrameAsync | ||
340 | bodyReadCh: make(chan bodyReadMsg), // buffering doesn't matter either way | ||
341 | doneServing: make(chan struct{}), | ||
342 | clientMaxStreams: math.MaxUint32, // Section 6.5.2: "Initially, there is no limit to this value" | ||
343 | advMaxStreams: s.maxConcurrentStreams(), | ||
344 | initialStreamSendWindowSize: initialWindowSize, | ||
345 | maxFrameSize: initialMaxFrameSize, | ||
346 | headerTableSize: initialHeaderTableSize, | ||
347 | serveG: newGoroutineLock(), | ||
348 | pushEnabled: true, | ||
349 | } | ||
350 | |||
351 | s.state.registerConn(sc) | ||
352 | defer s.state.unregisterConn(sc) | ||
353 | |||
354 | // The net/http package sets the write deadline from the | ||
355 | // http.Server.WriteTimeout during the TLS handshake, but then | ||
356 | // passes the connection off to us with the deadline already set. | ||
357 | // Write deadlines are set per stream in serverConn.newStream. | ||
358 | // Disarm the net.Conn write deadline here. | ||
359 | if sc.hs.WriteTimeout != 0 { | ||
360 | sc.conn.SetWriteDeadline(time.Time{}) | ||
361 | } | ||
362 | |||
363 | if s.NewWriteScheduler != nil { | ||
364 | sc.writeSched = s.NewWriteScheduler() | ||
365 | } else { | ||
366 | sc.writeSched = NewRandomWriteScheduler() | ||
367 | } | ||
368 | |||
369 | // These start at the RFC-specified defaults. If there is a higher | ||
370 | // configured value for inflow, that will be updated when we send a | ||
371 | // WINDOW_UPDATE shortly after sending SETTINGS. | ||
372 | sc.flow.add(initialWindowSize) | ||
373 | sc.inflow.add(initialWindowSize) | ||
374 | sc.hpackEncoder = hpack.NewEncoder(&sc.headerWriteBuf) | ||
375 | |||
376 | fr := NewFramer(sc.bw, c) | ||
377 | fr.ReadMetaHeaders = hpack.NewDecoder(initialHeaderTableSize, nil) | ||
378 | fr.MaxHeaderListSize = sc.maxHeaderListSize() | ||
379 | fr.SetMaxReadFrameSize(s.maxReadFrameSize()) | ||
380 | sc.framer = fr | ||
381 | |||
382 | if tc, ok := c.(connectionStater); ok { | ||
383 | sc.tlsState = new(tls.ConnectionState) | ||
384 | *sc.tlsState = tc.ConnectionState() | ||
385 | // 9.2 Use of TLS Features | ||
386 | // An implementation of HTTP/2 over TLS MUST use TLS | ||
387 | // 1.2 or higher with the restrictions on feature set | ||
388 | // and cipher suite described in this section. Due to | ||
389 | // implementation limitations, it might not be | ||
390 | // possible to fail TLS negotiation. An endpoint MUST | ||
391 | // immediately terminate an HTTP/2 connection that | ||
392 | // does not meet the TLS requirements described in | ||
393 | // this section with a connection error (Section | ||
394 | // 5.4.1) of type INADEQUATE_SECURITY. | ||
395 | if sc.tlsState.Version < tls.VersionTLS12 { | ||
396 | sc.rejectConn(ErrCodeInadequateSecurity, "TLS version too low") | ||
397 | return | ||
398 | } | ||
399 | |||
400 | if sc.tlsState.ServerName == "" { | ||
401 | // Client must use SNI, but we don't enforce that anymore, | ||
402 | // since it was causing problems when connecting to bare IP | ||
403 | // addresses during development. | ||
404 | // | ||
405 | // TODO: optionally enforce? Or enforce at the time we receive | ||
406 | // a new request, and verify the the ServerName matches the :authority? | ||
407 | // But that precludes proxy situations, perhaps. | ||
408 | // | ||
409 | // So for now, do nothing here again. | ||
410 | } | ||
411 | |||
412 | if !s.PermitProhibitedCipherSuites && isBadCipher(sc.tlsState.CipherSuite) { | ||
413 | // "Endpoints MAY choose to generate a connection error | ||
414 | // (Section 5.4.1) of type INADEQUATE_SECURITY if one of | ||
415 | // the prohibited cipher suites are negotiated." | ||
416 | // | ||
417 | // We choose that. In my opinion, the spec is weak | ||
418 | // here. It also says both parties must support at least | ||
419 | // TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 so there's no | ||
420 | // excuses here. If we really must, we could allow an | ||
421 | // "AllowInsecureWeakCiphers" option on the server later. | ||
422 | // Let's see how it plays out first. | ||
423 | sc.rejectConn(ErrCodeInadequateSecurity, fmt.Sprintf("Prohibited TLS 1.2 Cipher Suite: %x", sc.tlsState.CipherSuite)) | ||
424 | return | ||
425 | } | ||
426 | } | ||
427 | |||
428 | if hook := testHookGetServerConn; hook != nil { | ||
429 | hook(sc) | ||
430 | } | ||
431 | sc.serve() | ||
432 | } | ||
433 | |||
434 | func (sc *serverConn) rejectConn(err ErrCode, debug string) { | ||
435 | sc.vlogf("http2: server rejecting conn: %v, %s", err, debug) | ||
436 | // ignoring errors. hanging up anyway. | ||
437 | sc.framer.WriteGoAway(0, err, []byte(debug)) | ||
438 | sc.bw.Flush() | ||
439 | sc.conn.Close() | ||
440 | } | ||
441 | |||
442 | type serverConn struct { | ||
443 | // Immutable: | ||
444 | srv *Server | ||
445 | hs *http.Server | ||
446 | conn net.Conn | ||
447 | bw *bufferedWriter // writing to conn | ||
448 | handler http.Handler | ||
449 | baseCtx contextContext | ||
450 | framer *Framer | ||
451 | doneServing chan struct{} // closed when serverConn.serve ends | ||
452 | readFrameCh chan readFrameResult // written by serverConn.readFrames | ||
453 | wantWriteFrameCh chan FrameWriteRequest // from handlers -> serve | ||
454 | wroteFrameCh chan frameWriteResult // from writeFrameAsync -> serve, tickles more frame writes | ||
455 | bodyReadCh chan bodyReadMsg // from handlers -> serve | ||
456 | serveMsgCh chan interface{} // misc messages & code to send to / run on the serve loop | ||
457 | flow flow // conn-wide (not stream-specific) outbound flow control | ||
458 | inflow flow // conn-wide inbound flow control | ||
459 | tlsState *tls.ConnectionState // shared by all handlers, like net/http | ||
460 | remoteAddrStr string | ||
461 | writeSched WriteScheduler | ||
462 | |||
463 | // Everything following is owned by the serve loop; use serveG.check(): | ||
464 | serveG goroutineLock // used to verify funcs are on serve() | ||
465 | pushEnabled bool | ||
466 | sawFirstSettings bool // got the initial SETTINGS frame after the preface | ||
467 | needToSendSettingsAck bool | ||
468 | unackedSettings int // how many SETTINGS have we sent without ACKs? | ||
469 | clientMaxStreams uint32 // SETTINGS_MAX_CONCURRENT_STREAMS from client (our PUSH_PROMISE limit) | ||
470 | advMaxStreams uint32 // our SETTINGS_MAX_CONCURRENT_STREAMS advertised the client | ||
471 | curClientStreams uint32 // number of open streams initiated by the client | ||
472 | curPushedStreams uint32 // number of open streams initiated by server push | ||
473 | maxClientStreamID uint32 // max ever seen from client (odd), or 0 if there have been no client requests | ||
474 | maxPushPromiseID uint32 // ID of the last push promise (even), or 0 if there have been no pushes | ||
475 | streams map[uint32]*stream | ||
476 | initialStreamSendWindowSize int32 | ||
477 | maxFrameSize int32 | ||
478 | headerTableSize uint32 | ||
479 | peerMaxHeaderListSize uint32 // zero means unknown (default) | ||
480 | canonHeader map[string]string // http2-lower-case -> Go-Canonical-Case | ||
481 | writingFrame bool // started writing a frame (on serve goroutine or separate) | ||
482 | writingFrameAsync bool // started a frame on its own goroutine but haven't heard back on wroteFrameCh | ||
483 | needsFrameFlush bool // last frame write wasn't a flush | ||
484 | inGoAway bool // we've started to or sent GOAWAY | ||
485 | inFrameScheduleLoop bool // whether we're in the scheduleFrameWrite loop | ||
486 | needToSendGoAway bool // we need to schedule a GOAWAY frame write | ||
487 | goAwayCode ErrCode | ||
488 | shutdownTimer *time.Timer // nil until used | ||
489 | idleTimer *time.Timer // nil if unused | ||
490 | |||
491 | // Owned by the writeFrameAsync goroutine: | ||
492 | headerWriteBuf bytes.Buffer | ||
493 | hpackEncoder *hpack.Encoder | ||
494 | |||
495 | // Used by startGracefulShutdown. | ||
496 | shutdownOnce sync.Once | ||
497 | } | ||
498 | |||
499 | func (sc *serverConn) maxHeaderListSize() uint32 { | ||
500 | n := sc.hs.MaxHeaderBytes | ||
501 | if n <= 0 { | ||
502 | n = http.DefaultMaxHeaderBytes | ||
503 | } | ||
504 | // http2's count is in a slightly different unit and includes 32 bytes per pair. | ||
505 | // So, take the net/http.Server value and pad it up a bit, assuming 10 headers. | ||
506 | const perFieldOverhead = 32 // per http2 spec | ||
507 | const typicalHeaders = 10 // conservative | ||
508 | return uint32(n + typicalHeaders*perFieldOverhead) | ||
509 | } | ||
510 | |||
511 | func (sc *serverConn) curOpenStreams() uint32 { | ||
512 | sc.serveG.check() | ||
513 | return sc.curClientStreams + sc.curPushedStreams | ||
514 | } | ||
515 | |||
516 | // stream represents a stream. This is the minimal metadata needed by | ||
517 | // the serve goroutine. Most of the actual stream state is owned by | ||
518 | // the http.Handler's goroutine in the responseWriter. Because the | ||
519 | // responseWriter's responseWriterState is recycled at the end of a | ||
520 | // handler, this struct intentionally has no pointer to the | ||
521 | // *responseWriter{,State} itself, as the Handler ending nils out the | ||
522 | // responseWriter's state field. | ||
523 | type stream struct { | ||
524 | // immutable: | ||
525 | sc *serverConn | ||
526 | id uint32 | ||
527 | body *pipe // non-nil if expecting DATA frames | ||
528 | cw closeWaiter // closed wait stream transitions to closed state | ||
529 | ctx contextContext | ||
530 | cancelCtx func() | ||
531 | |||
532 | // owned by serverConn's serve loop: | ||
533 | bodyBytes int64 // body bytes seen so far | ||
534 | declBodyBytes int64 // or -1 if undeclared | ||
535 | flow flow // limits writing from Handler to client | ||
536 | inflow flow // what the client is allowed to POST/etc to us | ||
537 | parent *stream // or nil | ||
538 | numTrailerValues int64 | ||
539 | weight uint8 | ||
540 | state streamState | ||
541 | resetQueued bool // RST_STREAM queued for write; set by sc.resetStream | ||
542 | gotTrailerHeader bool // HEADER frame for trailers was seen | ||
543 | wroteHeaders bool // whether we wrote headers (not status 100) | ||
544 | writeDeadline *time.Timer // nil if unused | ||
545 | |||
546 | trailer http.Header // accumulated trailers | ||
547 | reqTrailer http.Header // handler's Request.Trailer | ||
548 | } | ||
549 | |||
550 | func (sc *serverConn) Framer() *Framer { return sc.framer } | ||
551 | func (sc *serverConn) CloseConn() error { return sc.conn.Close() } | ||
552 | func (sc *serverConn) Flush() error { return sc.bw.Flush() } | ||
553 | func (sc *serverConn) HeaderEncoder() (*hpack.Encoder, *bytes.Buffer) { | ||
554 | return sc.hpackEncoder, &sc.headerWriteBuf | ||
555 | } | ||
556 | |||
557 | func (sc *serverConn) state(streamID uint32) (streamState, *stream) { | ||
558 | sc.serveG.check() | ||
559 | // http://tools.ietf.org/html/rfc7540#section-5.1 | ||
560 | if st, ok := sc.streams[streamID]; ok { | ||
561 | return st.state, st | ||
562 | } | ||
563 | // "The first use of a new stream identifier implicitly closes all | ||
564 | // streams in the "idle" state that might have been initiated by | ||
565 | // that peer with a lower-valued stream identifier. For example, if | ||
566 | // a client sends a HEADERS frame on stream 7 without ever sending a | ||
567 | // frame on stream 5, then stream 5 transitions to the "closed" | ||
568 | // state when the first frame for stream 7 is sent or received." | ||
569 | if streamID%2 == 1 { | ||
570 | if streamID <= sc.maxClientStreamID { | ||
571 | return stateClosed, nil | ||
572 | } | ||
573 | } else { | ||
574 | if streamID <= sc.maxPushPromiseID { | ||
575 | return stateClosed, nil | ||
576 | } | ||
577 | } | ||
578 | return stateIdle, nil | ||
579 | } | ||
580 | |||
581 | // setConnState calls the net/http ConnState hook for this connection, if configured. | ||
582 | // Note that the net/http package does StateNew and StateClosed for us. | ||
583 | // There is currently no plan for StateHijacked or hijacking HTTP/2 connections. | ||
584 | func (sc *serverConn) setConnState(state http.ConnState) { | ||
585 | if sc.hs.ConnState != nil { | ||
586 | sc.hs.ConnState(sc.conn, state) | ||
587 | } | ||
588 | } | ||
589 | |||
590 | func (sc *serverConn) vlogf(format string, args ...interface{}) { | ||
591 | if VerboseLogs { | ||
592 | sc.logf(format, args...) | ||
593 | } | ||
594 | } | ||
595 | |||
596 | func (sc *serverConn) logf(format string, args ...interface{}) { | ||
597 | if lg := sc.hs.ErrorLog; lg != nil { | ||
598 | lg.Printf(format, args...) | ||
599 | } else { | ||
600 | log.Printf(format, args...) | ||
601 | } | ||
602 | } | ||
603 | |||
604 | // errno returns v's underlying uintptr, else 0. | ||
605 | // | ||
606 | // TODO: remove this helper function once http2 can use build | ||
607 | // tags. See comment in isClosedConnError. | ||
608 | func errno(v error) uintptr { | ||
609 | if rv := reflect.ValueOf(v); rv.Kind() == reflect.Uintptr { | ||
610 | return uintptr(rv.Uint()) | ||
611 | } | ||
612 | return 0 | ||
613 | } | ||
614 | |||
615 | // isClosedConnError reports whether err is an error from use of a closed | ||
616 | // network connection. | ||
617 | func isClosedConnError(err error) bool { | ||
618 | if err == nil { | ||
619 | return false | ||
620 | } | ||
621 | |||
622 | // TODO: remove this string search and be more like the Windows | ||
623 | // case below. That might involve modifying the standard library | ||
624 | // to return better error types. | ||
625 | str := err.Error() | ||
626 | if strings.Contains(str, "use of closed network connection") { | ||
627 | return true | ||
628 | } | ||
629 | |||
630 | // TODO(bradfitz): x/tools/cmd/bundle doesn't really support | ||
631 | // build tags, so I can't make an http2_windows.go file with | ||
632 | // Windows-specific stuff. Fix that and move this, once we | ||
633 | // have a way to bundle this into std's net/http somehow. | ||
634 | if runtime.GOOS == "windows" { | ||
635 | if oe, ok := err.(*net.OpError); ok && oe.Op == "read" { | ||
636 | if se, ok := oe.Err.(*os.SyscallError); ok && se.Syscall == "wsarecv" { | ||
637 | const WSAECONNABORTED = 10053 | ||
638 | const WSAECONNRESET = 10054 | ||
639 | if n := errno(se.Err); n == WSAECONNRESET || n == WSAECONNABORTED { | ||
640 | return true | ||
641 | } | ||
642 | } | ||
643 | } | ||
644 | } | ||
645 | return false | ||
646 | } | ||
647 | |||
648 | func (sc *serverConn) condlogf(err error, format string, args ...interface{}) { | ||
649 | if err == nil { | ||
650 | return | ||
651 | } | ||
652 | if err == io.EOF || err == io.ErrUnexpectedEOF || isClosedConnError(err) { | ||
653 | // Boring, expected errors. | ||
654 | sc.vlogf(format, args...) | ||
655 | } else { | ||
656 | sc.logf(format, args...) | ||
657 | } | ||
658 | } | ||
659 | |||
660 | func (sc *serverConn) canonicalHeader(v string) string { | ||
661 | sc.serveG.check() | ||
662 | cv, ok := commonCanonHeader[v] | ||
663 | if ok { | ||
664 | return cv | ||
665 | } | ||
666 | cv, ok = sc.canonHeader[v] | ||
667 | if ok { | ||
668 | return cv | ||
669 | } | ||
670 | if sc.canonHeader == nil { | ||
671 | sc.canonHeader = make(map[string]string) | ||
672 | } | ||
673 | cv = http.CanonicalHeaderKey(v) | ||
674 | sc.canonHeader[v] = cv | ||
675 | return cv | ||
676 | } | ||
677 | |||
678 | type readFrameResult struct { | ||
679 | f Frame // valid until readMore is called | ||
680 | err error | ||
681 | |||
682 | // readMore should be called once the consumer no longer needs or | ||
683 | // retains f. After readMore, f is invalid and more frames can be | ||
684 | // read. | ||
685 | readMore func() | ||
686 | } | ||
687 | |||
688 | // readFrames is the loop that reads incoming frames. | ||
689 | // It takes care to only read one frame at a time, blocking until the | ||
690 | // consumer is done with the frame. | ||
691 | // It's run on its own goroutine. | ||
692 | func (sc *serverConn) readFrames() { | ||
693 | gate := make(gate) | ||
694 | gateDone := gate.Done | ||
695 | for { | ||
696 | f, err := sc.framer.ReadFrame() | ||
697 | select { | ||
698 | case sc.readFrameCh <- readFrameResult{f, err, gateDone}: | ||
699 | case <-sc.doneServing: | ||
700 | return | ||
701 | } | ||
702 | select { | ||
703 | case <-gate: | ||
704 | case <-sc.doneServing: | ||
705 | return | ||
706 | } | ||
707 | if terminalReadFrameError(err) { | ||
708 | return | ||
709 | } | ||
710 | } | ||
711 | } | ||
712 | |||
713 | // frameWriteResult is the message passed from writeFrameAsync to the serve goroutine. | ||
714 | type frameWriteResult struct { | ||
715 | wr FrameWriteRequest // what was written (or attempted) | ||
716 | err error // result of the writeFrame call | ||
717 | } | ||
718 | |||
719 | // writeFrameAsync runs in its own goroutine and writes a single frame | ||
720 | // and then reports when it's done. | ||
721 | // At most one goroutine can be running writeFrameAsync at a time per | ||
722 | // serverConn. | ||
723 | func (sc *serverConn) writeFrameAsync(wr FrameWriteRequest) { | ||
724 | err := wr.write.writeFrame(sc) | ||
725 | sc.wroteFrameCh <- frameWriteResult{wr, err} | ||
726 | } | ||
727 | |||
728 | func (sc *serverConn) closeAllStreamsOnConnClose() { | ||
729 | sc.serveG.check() | ||
730 | for _, st := range sc.streams { | ||
731 | sc.closeStream(st, errClientDisconnected) | ||
732 | } | ||
733 | } | ||
734 | |||
735 | func (sc *serverConn) stopShutdownTimer() { | ||
736 | sc.serveG.check() | ||
737 | if t := sc.shutdownTimer; t != nil { | ||
738 | t.Stop() | ||
739 | } | ||
740 | } | ||
741 | |||
742 | func (sc *serverConn) notePanic() { | ||
743 | // Note: this is for serverConn.serve panicking, not http.Handler code. | ||
744 | if testHookOnPanicMu != nil { | ||
745 | testHookOnPanicMu.Lock() | ||
746 | defer testHookOnPanicMu.Unlock() | ||
747 | } | ||
748 | if testHookOnPanic != nil { | ||
749 | if e := recover(); e != nil { | ||
750 | if testHookOnPanic(sc, e) { | ||
751 | panic(e) | ||
752 | } | ||
753 | } | ||
754 | } | ||
755 | } | ||
756 | |||
757 | func (sc *serverConn) serve() { | ||
758 | sc.serveG.check() | ||
759 | defer sc.notePanic() | ||
760 | defer sc.conn.Close() | ||
761 | defer sc.closeAllStreamsOnConnClose() | ||
762 | defer sc.stopShutdownTimer() | ||
763 | defer close(sc.doneServing) // unblocks handlers trying to send | ||
764 | |||
765 | if VerboseLogs { | ||
766 | sc.vlogf("http2: server connection from %v on %p", sc.conn.RemoteAddr(), sc.hs) | ||
767 | } | ||
768 | |||
769 | sc.writeFrame(FrameWriteRequest{ | ||
770 | write: writeSettings{ | ||
771 | {SettingMaxFrameSize, sc.srv.maxReadFrameSize()}, | ||
772 | {SettingMaxConcurrentStreams, sc.advMaxStreams}, | ||
773 | {SettingMaxHeaderListSize, sc.maxHeaderListSize()}, | ||
774 | {SettingInitialWindowSize, uint32(sc.srv.initialStreamRecvWindowSize())}, | ||
775 | }, | ||
776 | }) | ||
777 | sc.unackedSettings++ | ||
778 | |||
779 | // Each connection starts with intialWindowSize inflow tokens. | ||
780 | // If a higher value is configured, we add more tokens. | ||
781 | if diff := sc.srv.initialConnRecvWindowSize() - initialWindowSize; diff > 0 { | ||
782 | sc.sendWindowUpdate(nil, int(diff)) | ||
783 | } | ||
784 | |||
785 | if err := sc.readPreface(); err != nil { | ||
786 | sc.condlogf(err, "http2: server: error reading preface from client %v: %v", sc.conn.RemoteAddr(), err) | ||
787 | return | ||
788 | } | ||
789 | // Now that we've got the preface, get us out of the | ||
790 | // "StateNew" state. We can't go directly to idle, though. | ||
791 | // Active means we read some data and anticipate a request. We'll | ||
792 | // do another Active when we get a HEADERS frame. | ||
793 | sc.setConnState(http.StateActive) | ||
794 | sc.setConnState(http.StateIdle) | ||
795 | |||
796 | if sc.srv.IdleTimeout != 0 { | ||
797 | sc.idleTimer = time.AfterFunc(sc.srv.IdleTimeout, sc.onIdleTimer) | ||
798 | defer sc.idleTimer.Stop() | ||
799 | } | ||
800 | |||
801 | go sc.readFrames() // closed by defer sc.conn.Close above | ||
802 | |||
803 | settingsTimer := time.AfterFunc(firstSettingsTimeout, sc.onSettingsTimer) | ||
804 | defer settingsTimer.Stop() | ||
805 | |||
806 | loopNum := 0 | ||
807 | for { | ||
808 | loopNum++ | ||
809 | select { | ||
810 | case wr := <-sc.wantWriteFrameCh: | ||
811 | if se, ok := wr.write.(StreamError); ok { | ||
812 | sc.resetStream(se) | ||
813 | break | ||
814 | } | ||
815 | sc.writeFrame(wr) | ||
816 | case res := <-sc.wroteFrameCh: | ||
817 | sc.wroteFrame(res) | ||
818 | case res := <-sc.readFrameCh: | ||
819 | if !sc.processFrameFromReader(res) { | ||
820 | return | ||
821 | } | ||
822 | res.readMore() | ||
823 | if settingsTimer != nil { | ||
824 | settingsTimer.Stop() | ||
825 | settingsTimer = nil | ||
826 | } | ||
827 | case m := <-sc.bodyReadCh: | ||
828 | sc.noteBodyRead(m.st, m.n) | ||
829 | case msg := <-sc.serveMsgCh: | ||
830 | switch v := msg.(type) { | ||
831 | case func(int): | ||
832 | v(loopNum) // for testing | ||
833 | case *serverMessage: | ||
834 | switch v { | ||
835 | case settingsTimerMsg: | ||
836 | sc.logf("timeout waiting for SETTINGS frames from %v", sc.conn.RemoteAddr()) | ||
837 | return | ||
838 | case idleTimerMsg: | ||
839 | sc.vlogf("connection is idle") | ||
840 | sc.goAway(ErrCodeNo) | ||
841 | case shutdownTimerMsg: | ||
842 | sc.vlogf("GOAWAY close timer fired; closing conn from %v", sc.conn.RemoteAddr()) | ||
843 | return | ||
844 | case gracefulShutdownMsg: | ||
845 | sc.startGracefulShutdownInternal() | ||
846 | default: | ||
847 | panic("unknown timer") | ||
848 | } | ||
849 | case *startPushRequest: | ||
850 | sc.startPush(v) | ||
851 | default: | ||
852 | panic(fmt.Sprintf("unexpected type %T", v)) | ||
853 | } | ||
854 | } | ||
855 | |||
856 | if sc.inGoAway && sc.curOpenStreams() == 0 && !sc.needToSendGoAway && !sc.writingFrame { | ||
857 | return | ||
858 | } | ||
859 | } | ||
860 | } | ||
861 | |||
862 | func (sc *serverConn) awaitGracefulShutdown(sharedCh <-chan struct{}, privateCh chan struct{}) { | ||
863 | select { | ||
864 | case <-sc.doneServing: | ||
865 | case <-sharedCh: | ||
866 | close(privateCh) | ||
867 | } | ||
868 | } | ||
869 | |||
870 | type serverMessage int | ||
871 | |||
872 | // Message values sent to serveMsgCh. | ||
873 | var ( | ||
874 | settingsTimerMsg = new(serverMessage) | ||
875 | idleTimerMsg = new(serverMessage) | ||
876 | shutdownTimerMsg = new(serverMessage) | ||
877 | gracefulShutdownMsg = new(serverMessage) | ||
878 | ) | ||
879 | |||
880 | func (sc *serverConn) onSettingsTimer() { sc.sendServeMsg(settingsTimerMsg) } | ||
881 | func (sc *serverConn) onIdleTimer() { sc.sendServeMsg(idleTimerMsg) } | ||
882 | func (sc *serverConn) onShutdownTimer() { sc.sendServeMsg(shutdownTimerMsg) } | ||
883 | |||
884 | func (sc *serverConn) sendServeMsg(msg interface{}) { | ||
885 | sc.serveG.checkNotOn() // NOT | ||
886 | select { | ||
887 | case sc.serveMsgCh <- msg: | ||
888 | case <-sc.doneServing: | ||
889 | } | ||
890 | } | ||
891 | |||
892 | // readPreface reads the ClientPreface greeting from the peer | ||
893 | // or returns an error on timeout or an invalid greeting. | ||
894 | func (sc *serverConn) readPreface() error { | ||
895 | errc := make(chan error, 1) | ||
896 | go func() { | ||
897 | // Read the client preface | ||
898 | buf := make([]byte, len(ClientPreface)) | ||
899 | if _, err := io.ReadFull(sc.conn, buf); err != nil { | ||
900 | errc <- err | ||
901 | } else if !bytes.Equal(buf, clientPreface) { | ||
902 | errc <- fmt.Errorf("bogus greeting %q", buf) | ||
903 | } else { | ||
904 | errc <- nil | ||
905 | } | ||
906 | }() | ||
907 | timer := time.NewTimer(prefaceTimeout) // TODO: configurable on *Server? | ||
908 | defer timer.Stop() | ||
909 | select { | ||
910 | case <-timer.C: | ||
911 | return errors.New("timeout waiting for client preface") | ||
912 | case err := <-errc: | ||
913 | if err == nil { | ||
914 | if VerboseLogs { | ||
915 | sc.vlogf("http2: server: client %v said hello", sc.conn.RemoteAddr()) | ||
916 | } | ||
917 | } | ||
918 | return err | ||
919 | } | ||
920 | } | ||
921 | |||
922 | var errChanPool = sync.Pool{ | ||
923 | New: func() interface{} { return make(chan error, 1) }, | ||
924 | } | ||
925 | |||
926 | var writeDataPool = sync.Pool{ | ||
927 | New: func() interface{} { return new(writeData) }, | ||
928 | } | ||
929 | |||
930 | // writeDataFromHandler writes DATA response frames from a handler on | ||
931 | // the given stream. | ||
932 | func (sc *serverConn) writeDataFromHandler(stream *stream, data []byte, endStream bool) error { | ||
933 | ch := errChanPool.Get().(chan error) | ||
934 | writeArg := writeDataPool.Get().(*writeData) | ||
935 | *writeArg = writeData{stream.id, data, endStream} | ||
936 | err := sc.writeFrameFromHandler(FrameWriteRequest{ | ||
937 | write: writeArg, | ||
938 | stream: stream, | ||
939 | done: ch, | ||
940 | }) | ||
941 | if err != nil { | ||
942 | return err | ||
943 | } | ||
944 | var frameWriteDone bool // the frame write is done (successfully or not) | ||
945 | select { | ||
946 | case err = <-ch: | ||
947 | frameWriteDone = true | ||
948 | case <-sc.doneServing: | ||
949 | return errClientDisconnected | ||
950 | case <-stream.cw: | ||
951 | // If both ch and stream.cw were ready (as might | ||
952 | // happen on the final Write after an http.Handler | ||
953 | // ends), prefer the write result. Otherwise this | ||
954 | // might just be us successfully closing the stream. | ||
955 | // The writeFrameAsync and serve goroutines guarantee | ||
956 | // that the ch send will happen before the stream.cw | ||
957 | // close. | ||
958 | select { | ||
959 | case err = <-ch: | ||
960 | frameWriteDone = true | ||
961 | default: | ||
962 | return errStreamClosed | ||
963 | } | ||
964 | } | ||
965 | errChanPool.Put(ch) | ||
966 | if frameWriteDone { | ||
967 | writeDataPool.Put(writeArg) | ||
968 | } | ||
969 | return err | ||
970 | } | ||
971 | |||
972 | // writeFrameFromHandler sends wr to sc.wantWriteFrameCh, but aborts | ||
973 | // if the connection has gone away. | ||
974 | // | ||
975 | // This must not be run from the serve goroutine itself, else it might | ||
976 | // deadlock writing to sc.wantWriteFrameCh (which is only mildly | ||
977 | // buffered and is read by serve itself). If you're on the serve | ||
978 | // goroutine, call writeFrame instead. | ||
979 | func (sc *serverConn) writeFrameFromHandler(wr FrameWriteRequest) error { | ||
980 | sc.serveG.checkNotOn() // NOT | ||
981 | select { | ||
982 | case sc.wantWriteFrameCh <- wr: | ||
983 | return nil | ||
984 | case <-sc.doneServing: | ||
985 | // Serve loop is gone. | ||
986 | // Client has closed their connection to the server. | ||
987 | return errClientDisconnected | ||
988 | } | ||
989 | } | ||
990 | |||
991 | // writeFrame schedules a frame to write and sends it if there's nothing | ||
992 | // already being written. | ||
993 | // | ||
994 | // There is no pushback here (the serve goroutine never blocks). It's | ||
995 | // the http.Handlers that block, waiting for their previous frames to | ||
996 | // make it onto the wire | ||
997 | // | ||
998 | // If you're not on the serve goroutine, use writeFrameFromHandler instead. | ||
999 | func (sc *serverConn) writeFrame(wr FrameWriteRequest) { | ||
1000 | sc.serveG.check() | ||
1001 | |||
1002 | // If true, wr will not be written and wr.done will not be signaled. | ||
1003 | var ignoreWrite bool | ||
1004 | |||
1005 | // We are not allowed to write frames on closed streams. RFC 7540 Section | ||
1006 | // 5.1.1 says: "An endpoint MUST NOT send frames other than PRIORITY on | ||
1007 | // a closed stream." Our server never sends PRIORITY, so that exception | ||
1008 | // does not apply. | ||
1009 | // | ||
1010 | // The serverConn might close an open stream while the stream's handler | ||
1011 | // is still running. For example, the server might close a stream when it | ||
1012 | // receives bad data from the client. If this happens, the handler might | ||
1013 | // attempt to write a frame after the stream has been closed (since the | ||
1014 | // handler hasn't yet been notified of the close). In this case, we simply | ||
1015 | // ignore the frame. The handler will notice that the stream is closed when | ||
1016 | // it waits for the frame to be written. | ||
1017 | // | ||
1018 | // As an exception to this rule, we allow sending RST_STREAM after close. | ||
1019 | // This allows us to immediately reject new streams without tracking any | ||
1020 | // state for those streams (except for the queued RST_STREAM frame). This | ||
1021 | // may result in duplicate RST_STREAMs in some cases, but the client should | ||
1022 | // ignore those. | ||
1023 | if wr.StreamID() != 0 { | ||
1024 | _, isReset := wr.write.(StreamError) | ||
1025 | if state, _ := sc.state(wr.StreamID()); state == stateClosed && !isReset { | ||
1026 | ignoreWrite = true | ||
1027 | } | ||
1028 | } | ||
1029 | |||
1030 | // Don't send a 100-continue response if we've already sent headers. | ||
1031 | // See golang.org/issue/14030. | ||
1032 | switch wr.write.(type) { | ||
1033 | case *writeResHeaders: | ||
1034 | wr.stream.wroteHeaders = true | ||
1035 | case write100ContinueHeadersFrame: | ||
1036 | if wr.stream.wroteHeaders { | ||
1037 | // We do not need to notify wr.done because this frame is | ||
1038 | // never written with wr.done != nil. | ||
1039 | if wr.done != nil { | ||
1040 | panic("wr.done != nil for write100ContinueHeadersFrame") | ||
1041 | } | ||
1042 | ignoreWrite = true | ||
1043 | } | ||
1044 | } | ||
1045 | |||
1046 | if !ignoreWrite { | ||
1047 | sc.writeSched.Push(wr) | ||
1048 | } | ||
1049 | sc.scheduleFrameWrite() | ||
1050 | } | ||
1051 | |||
1052 | // startFrameWrite starts a goroutine to write wr (in a separate | ||
1053 | // goroutine since that might block on the network), and updates the | ||
1054 | // serve goroutine's state about the world, updated from info in wr. | ||
1055 | func (sc *serverConn) startFrameWrite(wr FrameWriteRequest) { | ||
1056 | sc.serveG.check() | ||
1057 | if sc.writingFrame { | ||
1058 | panic("internal error: can only be writing one frame at a time") | ||
1059 | } | ||
1060 | |||
1061 | st := wr.stream | ||
1062 | if st != nil { | ||
1063 | switch st.state { | ||
1064 | case stateHalfClosedLocal: | ||
1065 | switch wr.write.(type) { | ||
1066 | case StreamError, handlerPanicRST, writeWindowUpdate: | ||
1067 | // RFC 7540 Section 5.1 allows sending RST_STREAM, PRIORITY, and WINDOW_UPDATE | ||
1068 | // in this state. (We never send PRIORITY from the server, so that is not checked.) | ||
1069 | default: | ||
1070 | panic(fmt.Sprintf("internal error: attempt to send frame on a half-closed-local stream: %v", wr)) | ||
1071 | } | ||
1072 | case stateClosed: | ||
1073 | panic(fmt.Sprintf("internal error: attempt to send frame on a closed stream: %v", wr)) | ||
1074 | } | ||
1075 | } | ||
1076 | if wpp, ok := wr.write.(*writePushPromise); ok { | ||
1077 | var err error | ||
1078 | wpp.promisedID, err = wpp.allocatePromisedID() | ||
1079 | if err != nil { | ||
1080 | sc.writingFrameAsync = false | ||
1081 | wr.replyToWriter(err) | ||
1082 | return | ||
1083 | } | ||
1084 | } | ||
1085 | |||
1086 | sc.writingFrame = true | ||
1087 | sc.needsFrameFlush = true | ||
1088 | if wr.write.staysWithinBuffer(sc.bw.Available()) { | ||
1089 | sc.writingFrameAsync = false | ||
1090 | err := wr.write.writeFrame(sc) | ||
1091 | sc.wroteFrame(frameWriteResult{wr, err}) | ||
1092 | } else { | ||
1093 | sc.writingFrameAsync = true | ||
1094 | go sc.writeFrameAsync(wr) | ||
1095 | } | ||
1096 | } | ||
1097 | |||
1098 | // errHandlerPanicked is the error given to any callers blocked in a read from | ||
1099 | // Request.Body when the main goroutine panics. Since most handlers read in the | ||
1100 | // the main ServeHTTP goroutine, this will show up rarely. | ||
1101 | var errHandlerPanicked = errors.New("http2: handler panicked") | ||
1102 | |||
1103 | // wroteFrame is called on the serve goroutine with the result of | ||
1104 | // whatever happened on writeFrameAsync. | ||
1105 | func (sc *serverConn) wroteFrame(res frameWriteResult) { | ||
1106 | sc.serveG.check() | ||
1107 | if !sc.writingFrame { | ||
1108 | panic("internal error: expected to be already writing a frame") | ||
1109 | } | ||
1110 | sc.writingFrame = false | ||
1111 | sc.writingFrameAsync = false | ||
1112 | |||
1113 | wr := res.wr | ||
1114 | |||
1115 | if writeEndsStream(wr.write) { | ||
1116 | st := wr.stream | ||
1117 | if st == nil { | ||
1118 | panic("internal error: expecting non-nil stream") | ||
1119 | } | ||
1120 | switch st.state { | ||
1121 | case stateOpen: | ||
1122 | // Here we would go to stateHalfClosedLocal in | ||
1123 | // theory, but since our handler is done and | ||
1124 | // the net/http package provides no mechanism | ||
1125 | // for closing a ResponseWriter while still | ||
1126 | // reading data (see possible TODO at top of | ||
1127 | // this file), we go into closed state here | ||
1128 | // anyway, after telling the peer we're | ||
1129 | // hanging up on them. We'll transition to | ||
1130 | // stateClosed after the RST_STREAM frame is | ||
1131 | // written. | ||
1132 | st.state = stateHalfClosedLocal | ||
1133 | // Section 8.1: a server MAY request that the client abort | ||
1134 | // transmission of a request without error by sending a | ||
1135 | // RST_STREAM with an error code of NO_ERROR after sending | ||
1136 | // a complete response. | ||
1137 | sc.resetStream(streamError(st.id, ErrCodeNo)) | ||
1138 | case stateHalfClosedRemote: | ||
1139 | sc.closeStream(st, errHandlerComplete) | ||
1140 | } | ||
1141 | } else { | ||
1142 | switch v := wr.write.(type) { | ||
1143 | case StreamError: | ||
1144 | // st may be unknown if the RST_STREAM was generated to reject bad input. | ||
1145 | if st, ok := sc.streams[v.StreamID]; ok { | ||
1146 | sc.closeStream(st, v) | ||
1147 | } | ||
1148 | case handlerPanicRST: | ||
1149 | sc.closeStream(wr.stream, errHandlerPanicked) | ||
1150 | } | ||
1151 | } | ||
1152 | |||
1153 | // Reply (if requested) to unblock the ServeHTTP goroutine. | ||
1154 | wr.replyToWriter(res.err) | ||
1155 | |||
1156 | sc.scheduleFrameWrite() | ||
1157 | } | ||
1158 | |||
1159 | // scheduleFrameWrite tickles the frame writing scheduler. | ||
1160 | // | ||
1161 | // If a frame is already being written, nothing happens. This will be called again | ||
1162 | // when the frame is done being written. | ||
1163 | // | ||
1164 | // If a frame isn't being written we need to send one, the best frame | ||
1165 | // to send is selected, preferring first things that aren't | ||
1166 | // stream-specific (e.g. ACKing settings), and then finding the | ||
1167 | // highest priority stream. | ||
1168 | // | ||
1169 | // If a frame isn't being written and there's nothing else to send, we | ||
1170 | // flush the write buffer. | ||
1171 | func (sc *serverConn) scheduleFrameWrite() { | ||
1172 | sc.serveG.check() | ||
1173 | if sc.writingFrame || sc.inFrameScheduleLoop { | ||
1174 | return | ||
1175 | } | ||
1176 | sc.inFrameScheduleLoop = true | ||
1177 | for !sc.writingFrameAsync { | ||
1178 | if sc.needToSendGoAway { | ||
1179 | sc.needToSendGoAway = false | ||
1180 | sc.startFrameWrite(FrameWriteRequest{ | ||
1181 | write: &writeGoAway{ | ||
1182 | maxStreamID: sc.maxClientStreamID, | ||
1183 | code: sc.goAwayCode, | ||
1184 | }, | ||
1185 | }) | ||
1186 | continue | ||
1187 | } | ||
1188 | if sc.needToSendSettingsAck { | ||
1189 | sc.needToSendSettingsAck = false | ||
1190 | sc.startFrameWrite(FrameWriteRequest{write: writeSettingsAck{}}) | ||
1191 | continue | ||
1192 | } | ||
1193 | if !sc.inGoAway || sc.goAwayCode == ErrCodeNo { | ||
1194 | if wr, ok := sc.writeSched.Pop(); ok { | ||
1195 | sc.startFrameWrite(wr) | ||
1196 | continue | ||
1197 | } | ||
1198 | } | ||
1199 | if sc.needsFrameFlush { | ||
1200 | sc.startFrameWrite(FrameWriteRequest{write: flushFrameWriter{}}) | ||
1201 | sc.needsFrameFlush = false // after startFrameWrite, since it sets this true | ||
1202 | continue | ||
1203 | } | ||
1204 | break | ||
1205 | } | ||
1206 | sc.inFrameScheduleLoop = false | ||
1207 | } | ||
1208 | |||
1209 | // startGracefulShutdown gracefully shuts down a connection. This | ||
1210 | // sends GOAWAY with ErrCodeNo to tell the client we're gracefully | ||
1211 | // shutting down. The connection isn't closed until all current | ||
1212 | // streams are done. | ||
1213 | // | ||
1214 | // startGracefulShutdown returns immediately; it does not wait until | ||
1215 | // the connection has shut down. | ||
1216 | func (sc *serverConn) startGracefulShutdown() { | ||
1217 | sc.serveG.checkNotOn() // NOT | ||
1218 | sc.shutdownOnce.Do(func() { sc.sendServeMsg(gracefulShutdownMsg) }) | ||
1219 | } | ||
1220 | |||
1221 | func (sc *serverConn) startGracefulShutdownInternal() { | ||
1222 | sc.goAwayIn(ErrCodeNo, 0) | ||
1223 | } | ||
1224 | |||
1225 | func (sc *serverConn) goAway(code ErrCode) { | ||
1226 | sc.serveG.check() | ||
1227 | var forceCloseIn time.Duration | ||
1228 | if code != ErrCodeNo { | ||
1229 | forceCloseIn = 250 * time.Millisecond | ||
1230 | } else { | ||
1231 | // TODO: configurable | ||
1232 | forceCloseIn = 1 * time.Second | ||
1233 | } | ||
1234 | sc.goAwayIn(code, forceCloseIn) | ||
1235 | } | ||
1236 | |||
1237 | func (sc *serverConn) goAwayIn(code ErrCode, forceCloseIn time.Duration) { | ||
1238 | sc.serveG.check() | ||
1239 | if sc.inGoAway { | ||
1240 | return | ||
1241 | } | ||
1242 | if forceCloseIn != 0 { | ||
1243 | sc.shutDownIn(forceCloseIn) | ||
1244 | } | ||
1245 | sc.inGoAway = true | ||
1246 | sc.needToSendGoAway = true | ||
1247 | sc.goAwayCode = code | ||
1248 | sc.scheduleFrameWrite() | ||
1249 | } | ||
1250 | |||
1251 | func (sc *serverConn) shutDownIn(d time.Duration) { | ||
1252 | sc.serveG.check() | ||
1253 | sc.shutdownTimer = time.AfterFunc(d, sc.onShutdownTimer) | ||
1254 | } | ||
1255 | |||
1256 | func (sc *serverConn) resetStream(se StreamError) { | ||
1257 | sc.serveG.check() | ||
1258 | sc.writeFrame(FrameWriteRequest{write: se}) | ||
1259 | if st, ok := sc.streams[se.StreamID]; ok { | ||
1260 | st.resetQueued = true | ||
1261 | } | ||
1262 | } | ||
1263 | |||
1264 | // processFrameFromReader processes the serve loop's read from readFrameCh from the | ||
1265 | // frame-reading goroutine. | ||
1266 | // processFrameFromReader returns whether the connection should be kept open. | ||
1267 | func (sc *serverConn) processFrameFromReader(res readFrameResult) bool { | ||
1268 | sc.serveG.check() | ||
1269 | err := res.err | ||
1270 | if err != nil { | ||
1271 | if err == ErrFrameTooLarge { | ||
1272 | sc.goAway(ErrCodeFrameSize) | ||
1273 | return true // goAway will close the loop | ||
1274 | } | ||
1275 | clientGone := err == io.EOF || err == io.ErrUnexpectedEOF || isClosedConnError(err) | ||
1276 | if clientGone { | ||
1277 | // TODO: could we also get into this state if | ||
1278 | // the peer does a half close | ||
1279 | // (e.g. CloseWrite) because they're done | ||
1280 | // sending frames but they're still wanting | ||
1281 | // our open replies? Investigate. | ||
1282 | // TODO: add CloseWrite to crypto/tls.Conn first | ||
1283 | // so we have a way to test this? I suppose | ||
1284 | // just for testing we could have a non-TLS mode. | ||
1285 | return false | ||
1286 | } | ||
1287 | } else { | ||
1288 | f := res.f | ||
1289 | if VerboseLogs { | ||
1290 | sc.vlogf("http2: server read frame %v", summarizeFrame(f)) | ||
1291 | } | ||
1292 | err = sc.processFrame(f) | ||
1293 | if err == nil { | ||
1294 | return true | ||
1295 | } | ||
1296 | } | ||
1297 | |||
1298 | switch ev := err.(type) { | ||
1299 | case StreamError: | ||
1300 | sc.resetStream(ev) | ||
1301 | return true | ||
1302 | case goAwayFlowError: | ||
1303 | sc.goAway(ErrCodeFlowControl) | ||
1304 | return true | ||
1305 | case ConnectionError: | ||
1306 | sc.logf("http2: server connection error from %v: %v", sc.conn.RemoteAddr(), ev) | ||
1307 | sc.goAway(ErrCode(ev)) | ||
1308 | return true // goAway will handle shutdown | ||
1309 | default: | ||
1310 | if res.err != nil { | ||
1311 | sc.vlogf("http2: server closing client connection; error reading frame from client %s: %v", sc.conn.RemoteAddr(), err) | ||
1312 | } else { | ||
1313 | sc.logf("http2: server closing client connection: %v", err) | ||
1314 | } | ||
1315 | return false | ||
1316 | } | ||
1317 | } | ||
1318 | |||
1319 | func (sc *serverConn) processFrame(f Frame) error { | ||
1320 | sc.serveG.check() | ||
1321 | |||
1322 | // First frame received must be SETTINGS. | ||
1323 | if !sc.sawFirstSettings { | ||
1324 | if _, ok := f.(*SettingsFrame); !ok { | ||
1325 | return ConnectionError(ErrCodeProtocol) | ||
1326 | } | ||
1327 | sc.sawFirstSettings = true | ||
1328 | } | ||
1329 | |||
1330 | switch f := f.(type) { | ||
1331 | case *SettingsFrame: | ||
1332 | return sc.processSettings(f) | ||
1333 | case *MetaHeadersFrame: | ||
1334 | return sc.processHeaders(f) | ||
1335 | case *WindowUpdateFrame: | ||
1336 | return sc.processWindowUpdate(f) | ||
1337 | case *PingFrame: | ||
1338 | return sc.processPing(f) | ||
1339 | case *DataFrame: | ||
1340 | return sc.processData(f) | ||
1341 | case *RSTStreamFrame: | ||
1342 | return sc.processResetStream(f) | ||
1343 | case *PriorityFrame: | ||
1344 | return sc.processPriority(f) | ||
1345 | case *GoAwayFrame: | ||
1346 | return sc.processGoAway(f) | ||
1347 | case *PushPromiseFrame: | ||
1348 | // A client cannot push. Thus, servers MUST treat the receipt of a PUSH_PROMISE | ||
1349 | // frame as a connection error (Section 5.4.1) of type PROTOCOL_ERROR. | ||
1350 | return ConnectionError(ErrCodeProtocol) | ||
1351 | default: | ||
1352 | sc.vlogf("http2: server ignoring frame: %v", f.Header()) | ||
1353 | return nil | ||
1354 | } | ||
1355 | } | ||
1356 | |||
1357 | func (sc *serverConn) processPing(f *PingFrame) error { | ||
1358 | sc.serveG.check() | ||
1359 | if f.IsAck() { | ||
1360 | // 6.7 PING: " An endpoint MUST NOT respond to PING frames | ||
1361 | // containing this flag." | ||
1362 | return nil | ||
1363 | } | ||
1364 | if f.StreamID != 0 { | ||
1365 | // "PING frames are not associated with any individual | ||
1366 | // stream. If a PING frame is received with a stream | ||
1367 | // identifier field value other than 0x0, the recipient MUST | ||
1368 | // respond with a connection error (Section 5.4.1) of type | ||
1369 | // PROTOCOL_ERROR." | ||
1370 | return ConnectionError(ErrCodeProtocol) | ||
1371 | } | ||
1372 | if sc.inGoAway && sc.goAwayCode != ErrCodeNo { | ||
1373 | return nil | ||
1374 | } | ||
1375 | sc.writeFrame(FrameWriteRequest{write: writePingAck{f}}) | ||
1376 | return nil | ||
1377 | } | ||
1378 | |||
1379 | func (sc *serverConn) processWindowUpdate(f *WindowUpdateFrame) error { | ||
1380 | sc.serveG.check() | ||
1381 | switch { | ||
1382 | case f.StreamID != 0: // stream-level flow control | ||
1383 | state, st := sc.state(f.StreamID) | ||
1384 | if state == stateIdle { | ||
1385 | // Section 5.1: "Receiving any frame other than HEADERS | ||
1386 | // or PRIORITY on a stream in this state MUST be | ||
1387 | // treated as a connection error (Section 5.4.1) of | ||
1388 | // type PROTOCOL_ERROR." | ||
1389 | return ConnectionError(ErrCodeProtocol) | ||
1390 | } | ||
1391 | if st == nil { | ||
1392 | // "WINDOW_UPDATE can be sent by a peer that has sent a | ||
1393 | // frame bearing the END_STREAM flag. This means that a | ||
1394 | // receiver could receive a WINDOW_UPDATE frame on a "half | ||
1395 | // closed (remote)" or "closed" stream. A receiver MUST | ||
1396 | // NOT treat this as an error, see Section 5.1." | ||
1397 | return nil | ||
1398 | } | ||
1399 | if !st.flow.add(int32(f.Increment)) { | ||
1400 | return streamError(f.StreamID, ErrCodeFlowControl) | ||
1401 | } | ||
1402 | default: // connection-level flow control | ||
1403 | if !sc.flow.add(int32(f.Increment)) { | ||
1404 | return goAwayFlowError{} | ||
1405 | } | ||
1406 | } | ||
1407 | sc.scheduleFrameWrite() | ||
1408 | return nil | ||
1409 | } | ||
1410 | |||
1411 | func (sc *serverConn) processResetStream(f *RSTStreamFrame) error { | ||
1412 | sc.serveG.check() | ||
1413 | |||
1414 | state, st := sc.state(f.StreamID) | ||
1415 | if state == stateIdle { | ||
1416 | // 6.4 "RST_STREAM frames MUST NOT be sent for a | ||
1417 | // stream in the "idle" state. If a RST_STREAM frame | ||
1418 | // identifying an idle stream is received, the | ||
1419 | // recipient MUST treat this as a connection error | ||
1420 | // (Section 5.4.1) of type PROTOCOL_ERROR. | ||
1421 | return ConnectionError(ErrCodeProtocol) | ||
1422 | } | ||
1423 | if st != nil { | ||
1424 | st.cancelCtx() | ||
1425 | sc.closeStream(st, streamError(f.StreamID, f.ErrCode)) | ||
1426 | } | ||
1427 | return nil | ||
1428 | } | ||
1429 | |||
1430 | func (sc *serverConn) closeStream(st *stream, err error) { | ||
1431 | sc.serveG.check() | ||
1432 | if st.state == stateIdle || st.state == stateClosed { | ||
1433 | panic(fmt.Sprintf("invariant; can't close stream in state %v", st.state)) | ||
1434 | } | ||
1435 | st.state = stateClosed | ||
1436 | if st.writeDeadline != nil { | ||
1437 | st.writeDeadline.Stop() | ||
1438 | } | ||
1439 | if st.isPushed() { | ||
1440 | sc.curPushedStreams-- | ||
1441 | } else { | ||
1442 | sc.curClientStreams-- | ||
1443 | } | ||
1444 | delete(sc.streams, st.id) | ||
1445 | if len(sc.streams) == 0 { | ||
1446 | sc.setConnState(http.StateIdle) | ||
1447 | if sc.srv.IdleTimeout != 0 { | ||
1448 | sc.idleTimer.Reset(sc.srv.IdleTimeout) | ||
1449 | } | ||
1450 | if h1ServerKeepAlivesDisabled(sc.hs) { | ||
1451 | sc.startGracefulShutdownInternal() | ||
1452 | } | ||
1453 | } | ||
1454 | if p := st.body; p != nil { | ||
1455 | // Return any buffered unread bytes worth of conn-level flow control. | ||
1456 | // See golang.org/issue/16481 | ||
1457 | sc.sendWindowUpdate(nil, p.Len()) | ||
1458 | |||
1459 | p.CloseWithError(err) | ||
1460 | } | ||
1461 | st.cw.Close() // signals Handler's CloseNotifier, unblocks writes, etc | ||
1462 | sc.writeSched.CloseStream(st.id) | ||
1463 | } | ||
1464 | |||
1465 | func (sc *serverConn) processSettings(f *SettingsFrame) error { | ||
1466 | sc.serveG.check() | ||
1467 | if f.IsAck() { | ||
1468 | sc.unackedSettings-- | ||
1469 | if sc.unackedSettings < 0 { | ||
1470 | // Why is the peer ACKing settings we never sent? | ||
1471 | // The spec doesn't mention this case, but | ||
1472 | // hang up on them anyway. | ||
1473 | return ConnectionError(ErrCodeProtocol) | ||
1474 | } | ||
1475 | return nil | ||
1476 | } | ||
1477 | if err := f.ForeachSetting(sc.processSetting); err != nil { | ||
1478 | return err | ||
1479 | } | ||
1480 | sc.needToSendSettingsAck = true | ||
1481 | sc.scheduleFrameWrite() | ||
1482 | return nil | ||
1483 | } | ||
1484 | |||
1485 | func (sc *serverConn) processSetting(s Setting) error { | ||
1486 | sc.serveG.check() | ||
1487 | if err := s.Valid(); err != nil { | ||
1488 | return err | ||
1489 | } | ||
1490 | if VerboseLogs { | ||
1491 | sc.vlogf("http2: server processing setting %v", s) | ||
1492 | } | ||
1493 | switch s.ID { | ||
1494 | case SettingHeaderTableSize: | ||
1495 | sc.headerTableSize = s.Val | ||
1496 | sc.hpackEncoder.SetMaxDynamicTableSize(s.Val) | ||
1497 | case SettingEnablePush: | ||
1498 | sc.pushEnabled = s.Val != 0 | ||
1499 | case SettingMaxConcurrentStreams: | ||
1500 | sc.clientMaxStreams = s.Val | ||
1501 | case SettingInitialWindowSize: | ||
1502 | return sc.processSettingInitialWindowSize(s.Val) | ||
1503 | case SettingMaxFrameSize: | ||
1504 | sc.maxFrameSize = int32(s.Val) // the maximum valid s.Val is < 2^31 | ||
1505 | case SettingMaxHeaderListSize: | ||
1506 | sc.peerMaxHeaderListSize = s.Val | ||
1507 | default: | ||
1508 | // Unknown setting: "An endpoint that receives a SETTINGS | ||
1509 | // frame with any unknown or unsupported identifier MUST | ||
1510 | // ignore that setting." | ||
1511 | if VerboseLogs { | ||
1512 | sc.vlogf("http2: server ignoring unknown setting %v", s) | ||
1513 | } | ||
1514 | } | ||
1515 | return nil | ||
1516 | } | ||
1517 | |||
1518 | func (sc *serverConn) processSettingInitialWindowSize(val uint32) error { | ||
1519 | sc.serveG.check() | ||
1520 | // Note: val already validated to be within range by | ||
1521 | // processSetting's Valid call. | ||
1522 | |||
1523 | // "A SETTINGS frame can alter the initial flow control window | ||
1524 | // size for all current streams. When the value of | ||
1525 | // SETTINGS_INITIAL_WINDOW_SIZE changes, a receiver MUST | ||
1526 | // adjust the size of all stream flow control windows that it | ||
1527 | // maintains by the difference between the new value and the | ||
1528 | // old value." | ||
1529 | old := sc.initialStreamSendWindowSize | ||
1530 | sc.initialStreamSendWindowSize = int32(val) | ||
1531 | growth := int32(val) - old // may be negative | ||
1532 | for _, st := range sc.streams { | ||
1533 | if !st.flow.add(growth) { | ||
1534 | // 6.9.2 Initial Flow Control Window Size | ||
1535 | // "An endpoint MUST treat a change to | ||
1536 | // SETTINGS_INITIAL_WINDOW_SIZE that causes any flow | ||
1537 | // control window to exceed the maximum size as a | ||
1538 | // connection error (Section 5.4.1) of type | ||
1539 | // FLOW_CONTROL_ERROR." | ||
1540 | return ConnectionError(ErrCodeFlowControl) | ||
1541 | } | ||
1542 | } | ||
1543 | return nil | ||
1544 | } | ||
1545 | |||
1546 | func (sc *serverConn) processData(f *DataFrame) error { | ||
1547 | sc.serveG.check() | ||
1548 | if sc.inGoAway && sc.goAwayCode != ErrCodeNo { | ||
1549 | return nil | ||
1550 | } | ||
1551 | data := f.Data() | ||
1552 | |||
1553 | // "If a DATA frame is received whose stream is not in "open" | ||
1554 | // or "half closed (local)" state, the recipient MUST respond | ||
1555 | // with a stream error (Section 5.4.2) of type STREAM_CLOSED." | ||
1556 | id := f.Header().StreamID | ||
1557 | state, st := sc.state(id) | ||
1558 | if id == 0 || state == stateIdle { | ||
1559 | // Section 5.1: "Receiving any frame other than HEADERS | ||
1560 | // or PRIORITY on a stream in this state MUST be | ||
1561 | // treated as a connection error (Section 5.4.1) of | ||
1562 | // type PROTOCOL_ERROR." | ||
1563 | return ConnectionError(ErrCodeProtocol) | ||
1564 | } | ||
1565 | if st == nil || state != stateOpen || st.gotTrailerHeader || st.resetQueued { | ||
1566 | // This includes sending a RST_STREAM if the stream is | ||
1567 | // in stateHalfClosedLocal (which currently means that | ||
1568 | // the http.Handler returned, so it's done reading & | ||
1569 | // done writing). Try to stop the client from sending | ||
1570 | // more DATA. | ||
1571 | |||
1572 | // But still enforce their connection-level flow control, | ||
1573 | // and return any flow control bytes since we're not going | ||
1574 | // to consume them. | ||
1575 | if sc.inflow.available() < int32(f.Length) { | ||
1576 | return streamError(id, ErrCodeFlowControl) | ||
1577 | } | ||
1578 | // Deduct the flow control from inflow, since we're | ||
1579 | // going to immediately add it back in | ||
1580 | // sendWindowUpdate, which also schedules sending the | ||
1581 | // frames. | ||
1582 | sc.inflow.take(int32(f.Length)) | ||
1583 | sc.sendWindowUpdate(nil, int(f.Length)) // conn-level | ||
1584 | |||
1585 | if st != nil && st.resetQueued { | ||
1586 | // Already have a stream error in flight. Don't send another. | ||
1587 | return nil | ||
1588 | } | ||
1589 | return streamError(id, ErrCodeStreamClosed) | ||
1590 | } | ||
1591 | if st.body == nil { | ||
1592 | panic("internal error: should have a body in this state") | ||
1593 | } | ||
1594 | |||
1595 | // Sender sending more than they'd declared? | ||
1596 | if st.declBodyBytes != -1 && st.bodyBytes+int64(len(data)) > st.declBodyBytes { | ||
1597 | st.body.CloseWithError(fmt.Errorf("sender tried to send more than declared Content-Length of %d bytes", st.declBodyBytes)) | ||
1598 | return streamError(id, ErrCodeStreamClosed) | ||
1599 | } | ||
1600 | if f.Length > 0 { | ||
1601 | // Check whether the client has flow control quota. | ||
1602 | if st.inflow.available() < int32(f.Length) { | ||
1603 | return streamError(id, ErrCodeFlowControl) | ||
1604 | } | ||
1605 | st.inflow.take(int32(f.Length)) | ||
1606 | |||
1607 | if len(data) > 0 { | ||
1608 | wrote, err := st.body.Write(data) | ||
1609 | if err != nil { | ||
1610 | return streamError(id, ErrCodeStreamClosed) | ||
1611 | } | ||
1612 | if wrote != len(data) { | ||
1613 | panic("internal error: bad Writer") | ||
1614 | } | ||
1615 | st.bodyBytes += int64(len(data)) | ||
1616 | } | ||
1617 | |||
1618 | // Return any padded flow control now, since we won't | ||
1619 | // refund it later on body reads. | ||
1620 | if pad := int32(f.Length) - int32(len(data)); pad > 0 { | ||
1621 | sc.sendWindowUpdate32(nil, pad) | ||
1622 | sc.sendWindowUpdate32(st, pad) | ||
1623 | } | ||
1624 | } | ||
1625 | if f.StreamEnded() { | ||
1626 | st.endStream() | ||
1627 | } | ||
1628 | return nil | ||
1629 | } | ||
1630 | |||
1631 | func (sc *serverConn) processGoAway(f *GoAwayFrame) error { | ||
1632 | sc.serveG.check() | ||
1633 | if f.ErrCode != ErrCodeNo { | ||
1634 | sc.logf("http2: received GOAWAY %+v, starting graceful shutdown", f) | ||
1635 | } else { | ||
1636 | sc.vlogf("http2: received GOAWAY %+v, starting graceful shutdown", f) | ||
1637 | } | ||
1638 | sc.startGracefulShutdownInternal() | ||
1639 | // http://tools.ietf.org/html/rfc7540#section-6.8 | ||
1640 | // We should not create any new streams, which means we should disable push. | ||
1641 | sc.pushEnabled = false | ||
1642 | return nil | ||
1643 | } | ||
1644 | |||
1645 | // isPushed reports whether the stream is server-initiated. | ||
1646 | func (st *stream) isPushed() bool { | ||
1647 | return st.id%2 == 0 | ||
1648 | } | ||
1649 | |||
1650 | // endStream closes a Request.Body's pipe. It is called when a DATA | ||
1651 | // frame says a request body is over (or after trailers). | ||
1652 | func (st *stream) endStream() { | ||
1653 | sc := st.sc | ||
1654 | sc.serveG.check() | ||
1655 | |||
1656 | if st.declBodyBytes != -1 && st.declBodyBytes != st.bodyBytes { | ||
1657 | st.body.CloseWithError(fmt.Errorf("request declared a Content-Length of %d but only wrote %d bytes", | ||
1658 | st.declBodyBytes, st.bodyBytes)) | ||
1659 | } else { | ||
1660 | st.body.closeWithErrorAndCode(io.EOF, st.copyTrailersToHandlerRequest) | ||
1661 | st.body.CloseWithError(io.EOF) | ||
1662 | } | ||
1663 | st.state = stateHalfClosedRemote | ||
1664 | } | ||
1665 | |||
1666 | // copyTrailersToHandlerRequest is run in the Handler's goroutine in | ||
1667 | // its Request.Body.Read just before it gets io.EOF. | ||
1668 | func (st *stream) copyTrailersToHandlerRequest() { | ||
1669 | for k, vv := range st.trailer { | ||
1670 | if _, ok := st.reqTrailer[k]; ok { | ||
1671 | // Only copy it over it was pre-declared. | ||
1672 | st.reqTrailer[k] = vv | ||
1673 | } | ||
1674 | } | ||
1675 | } | ||
1676 | |||
1677 | // onWriteTimeout is run on its own goroutine (from time.AfterFunc) | ||
1678 | // when the stream's WriteTimeout has fired. | ||
1679 | func (st *stream) onWriteTimeout() { | ||
1680 | st.sc.writeFrameFromHandler(FrameWriteRequest{write: streamError(st.id, ErrCodeInternal)}) | ||
1681 | } | ||
1682 | |||
1683 | func (sc *serverConn) processHeaders(f *MetaHeadersFrame) error { | ||
1684 | sc.serveG.check() | ||
1685 | id := f.StreamID | ||
1686 | if sc.inGoAway { | ||
1687 | // Ignore. | ||
1688 | return nil | ||
1689 | } | ||
1690 | // http://tools.ietf.org/html/rfc7540#section-5.1.1 | ||
1691 | // Streams initiated by a client MUST use odd-numbered stream | ||
1692 | // identifiers. [...] An endpoint that receives an unexpected | ||
1693 | // stream identifier MUST respond with a connection error | ||
1694 | // (Section 5.4.1) of type PROTOCOL_ERROR. | ||
1695 | if id%2 != 1 { | ||
1696 | return ConnectionError(ErrCodeProtocol) | ||
1697 | } | ||
1698 | // A HEADERS frame can be used to create a new stream or | ||
1699 | // send a trailer for an open one. If we already have a stream | ||
1700 | // open, let it process its own HEADERS frame (trailers at this | ||
1701 | // point, if it's valid). | ||
1702 | if st := sc.streams[f.StreamID]; st != nil { | ||
1703 | if st.resetQueued { | ||
1704 | // We're sending RST_STREAM to close the stream, so don't bother | ||
1705 | // processing this frame. | ||
1706 | return nil | ||
1707 | } | ||
1708 | return st.processTrailerHeaders(f) | ||
1709 | } | ||
1710 | |||
1711 | // [...] The identifier of a newly established stream MUST be | ||
1712 | // numerically greater than all streams that the initiating | ||
1713 | // endpoint has opened or reserved. [...] An endpoint that | ||
1714 | // receives an unexpected stream identifier MUST respond with | ||
1715 | // a connection error (Section 5.4.1) of type PROTOCOL_ERROR. | ||
1716 | if id <= sc.maxClientStreamID { | ||
1717 | return ConnectionError(ErrCodeProtocol) | ||
1718 | } | ||
1719 | sc.maxClientStreamID = id | ||
1720 | |||
1721 | if sc.idleTimer != nil { | ||
1722 | sc.idleTimer.Stop() | ||
1723 | } | ||
1724 | |||
1725 | // http://tools.ietf.org/html/rfc7540#section-5.1.2 | ||
1726 | // [...] Endpoints MUST NOT exceed the limit set by their peer. An | ||
1727 | // endpoint that receives a HEADERS frame that causes their | ||
1728 | // advertised concurrent stream limit to be exceeded MUST treat | ||
1729 | // this as a stream error (Section 5.4.2) of type PROTOCOL_ERROR | ||
1730 | // or REFUSED_STREAM. | ||
1731 | if sc.curClientStreams+1 > sc.advMaxStreams { | ||
1732 | if sc.unackedSettings == 0 { | ||
1733 | // They should know better. | ||
1734 | return streamError(id, ErrCodeProtocol) | ||
1735 | } | ||
1736 | // Assume it's a network race, where they just haven't | ||
1737 | // received our last SETTINGS update. But actually | ||
1738 | // this can't happen yet, because we don't yet provide | ||
1739 | // a way for users to adjust server parameters at | ||
1740 | // runtime. | ||
1741 | return streamError(id, ErrCodeRefusedStream) | ||
1742 | } | ||
1743 | |||
1744 | initialState := stateOpen | ||
1745 | if f.StreamEnded() { | ||
1746 | initialState = stateHalfClosedRemote | ||
1747 | } | ||
1748 | st := sc.newStream(id, 0, initialState) | ||
1749 | |||
1750 | if f.HasPriority() { | ||
1751 | if err := checkPriority(f.StreamID, f.Priority); err != nil { | ||
1752 | return err | ||
1753 | } | ||
1754 | sc.writeSched.AdjustStream(st.id, f.Priority) | ||
1755 | } | ||
1756 | |||
1757 | rw, req, err := sc.newWriterAndRequest(st, f) | ||
1758 | if err != nil { | ||
1759 | return err | ||
1760 | } | ||
1761 | st.reqTrailer = req.Trailer | ||
1762 | if st.reqTrailer != nil { | ||
1763 | st.trailer = make(http.Header) | ||
1764 | } | ||
1765 | st.body = req.Body.(*requestBody).pipe // may be nil | ||
1766 | st.declBodyBytes = req.ContentLength | ||
1767 | |||
1768 | handler := sc.handler.ServeHTTP | ||
1769 | if f.Truncated { | ||
1770 | // Their header list was too long. Send a 431 error. | ||
1771 | handler = handleHeaderListTooLong | ||
1772 | } else if err := checkValidHTTP2RequestHeaders(req.Header); err != nil { | ||
1773 | handler = new400Handler(err) | ||
1774 | } | ||
1775 | |||
1776 | // The net/http package sets the read deadline from the | ||
1777 | // http.Server.ReadTimeout during the TLS handshake, but then | ||
1778 | // passes the connection off to us with the deadline already | ||
1779 | // set. Disarm it here after the request headers are read, | ||
1780 | // similar to how the http1 server works. Here it's | ||
1781 | // technically more like the http1 Server's ReadHeaderTimeout | ||
1782 | // (in Go 1.8), though. That's a more sane option anyway. | ||
1783 | if sc.hs.ReadTimeout != 0 { | ||
1784 | sc.conn.SetReadDeadline(time.Time{}) | ||
1785 | } | ||
1786 | |||
1787 | go sc.runHandler(rw, req, handler) | ||
1788 | return nil | ||
1789 | } | ||
1790 | |||
1791 | func (st *stream) processTrailerHeaders(f *MetaHeadersFrame) error { | ||
1792 | sc := st.sc | ||
1793 | sc.serveG.check() | ||
1794 | if st.gotTrailerHeader { | ||
1795 | return ConnectionError(ErrCodeProtocol) | ||
1796 | } | ||
1797 | st.gotTrailerHeader = true | ||
1798 | if !f.StreamEnded() { | ||
1799 | return streamError(st.id, ErrCodeProtocol) | ||
1800 | } | ||
1801 | |||
1802 | if len(f.PseudoFields()) > 0 { | ||
1803 | return streamError(st.id, ErrCodeProtocol) | ||
1804 | } | ||
1805 | if st.trailer != nil { | ||
1806 | for _, hf := range f.RegularFields() { | ||
1807 | key := sc.canonicalHeader(hf.Name) | ||
1808 | if !ValidTrailerHeader(key) { | ||
1809 | // TODO: send more details to the peer somehow. But http2 has | ||
1810 | // no way to send debug data at a stream level. Discuss with | ||
1811 | // HTTP folk. | ||
1812 | return streamError(st.id, ErrCodeProtocol) | ||
1813 | } | ||
1814 | st.trailer[key] = append(st.trailer[key], hf.Value) | ||
1815 | } | ||
1816 | } | ||
1817 | st.endStream() | ||
1818 | return nil | ||
1819 | } | ||
1820 | |||
1821 | func checkPriority(streamID uint32, p PriorityParam) error { | ||
1822 | if streamID == p.StreamDep { | ||
1823 | // Section 5.3.1: "A stream cannot depend on itself. An endpoint MUST treat | ||
1824 | // this as a stream error (Section 5.4.2) of type PROTOCOL_ERROR." | ||
1825 | // Section 5.3.3 says that a stream can depend on one of its dependencies, | ||
1826 | // so it's only self-dependencies that are forbidden. | ||
1827 | return streamError(streamID, ErrCodeProtocol) | ||
1828 | } | ||
1829 | return nil | ||
1830 | } | ||
1831 | |||
1832 | func (sc *serverConn) processPriority(f *PriorityFrame) error { | ||
1833 | if sc.inGoAway { | ||
1834 | return nil | ||
1835 | } | ||
1836 | if err := checkPriority(f.StreamID, f.PriorityParam); err != nil { | ||
1837 | return err | ||
1838 | } | ||
1839 | sc.writeSched.AdjustStream(f.StreamID, f.PriorityParam) | ||
1840 | return nil | ||
1841 | } | ||
1842 | |||
1843 | func (sc *serverConn) newStream(id, pusherID uint32, state streamState) *stream { | ||
1844 | sc.serveG.check() | ||
1845 | if id == 0 { | ||
1846 | panic("internal error: cannot create stream with id 0") | ||
1847 | } | ||
1848 | |||
1849 | ctx, cancelCtx := contextWithCancel(sc.baseCtx) | ||
1850 | st := &stream{ | ||
1851 | sc: sc, | ||
1852 | id: id, | ||
1853 | state: state, | ||
1854 | ctx: ctx, | ||
1855 | cancelCtx: cancelCtx, | ||
1856 | } | ||
1857 | st.cw.Init() | ||
1858 | st.flow.conn = &sc.flow // link to conn-level counter | ||
1859 | st.flow.add(sc.initialStreamSendWindowSize) | ||
1860 | st.inflow.conn = &sc.inflow // link to conn-level counter | ||
1861 | st.inflow.add(sc.srv.initialStreamRecvWindowSize()) | ||
1862 | if sc.hs.WriteTimeout != 0 { | ||
1863 | st.writeDeadline = time.AfterFunc(sc.hs.WriteTimeout, st.onWriteTimeout) | ||
1864 | } | ||
1865 | |||
1866 | sc.streams[id] = st | ||
1867 | sc.writeSched.OpenStream(st.id, OpenStreamOptions{PusherID: pusherID}) | ||
1868 | if st.isPushed() { | ||
1869 | sc.curPushedStreams++ | ||
1870 | } else { | ||
1871 | sc.curClientStreams++ | ||
1872 | } | ||
1873 | if sc.curOpenStreams() == 1 { | ||
1874 | sc.setConnState(http.StateActive) | ||
1875 | } | ||
1876 | |||
1877 | return st | ||
1878 | } | ||
1879 | |||
1880 | func (sc *serverConn) newWriterAndRequest(st *stream, f *MetaHeadersFrame) (*responseWriter, *http.Request, error) { | ||
1881 | sc.serveG.check() | ||
1882 | |||
1883 | rp := requestParam{ | ||
1884 | method: f.PseudoValue("method"), | ||
1885 | scheme: f.PseudoValue("scheme"), | ||
1886 | authority: f.PseudoValue("authority"), | ||
1887 | path: f.PseudoValue("path"), | ||
1888 | } | ||
1889 | |||
1890 | isConnect := rp.method == "CONNECT" | ||
1891 | if isConnect { | ||
1892 | if rp.path != "" || rp.scheme != "" || rp.authority == "" { | ||
1893 | return nil, nil, streamError(f.StreamID, ErrCodeProtocol) | ||
1894 | } | ||
1895 | } else if rp.method == "" || rp.path == "" || (rp.scheme != "https" && rp.scheme != "http") { | ||
1896 | // See 8.1.2.6 Malformed Requests and Responses: | ||
1897 | // | ||
1898 | // Malformed requests or responses that are detected | ||
1899 | // MUST be treated as a stream error (Section 5.4.2) | ||
1900 | // of type PROTOCOL_ERROR." | ||
1901 | // | ||
1902 | // 8.1.2.3 Request Pseudo-Header Fields | ||
1903 | // "All HTTP/2 requests MUST include exactly one valid | ||
1904 | // value for the :method, :scheme, and :path | ||
1905 | // pseudo-header fields" | ||
1906 | return nil, nil, streamError(f.StreamID, ErrCodeProtocol) | ||
1907 | } | ||
1908 | |||
1909 | bodyOpen := !f.StreamEnded() | ||
1910 | if rp.method == "HEAD" && bodyOpen { | ||
1911 | // HEAD requests can't have bodies | ||
1912 | return nil, nil, streamError(f.StreamID, ErrCodeProtocol) | ||
1913 | } | ||
1914 | |||
1915 | rp.header = make(http.Header) | ||
1916 | for _, hf := range f.RegularFields() { | ||
1917 | rp.header.Add(sc.canonicalHeader(hf.Name), hf.Value) | ||
1918 | } | ||
1919 | if rp.authority == "" { | ||
1920 | rp.authority = rp.header.Get("Host") | ||
1921 | } | ||
1922 | |||
1923 | rw, req, err := sc.newWriterAndRequestNoBody(st, rp) | ||
1924 | if err != nil { | ||
1925 | return nil, nil, err | ||
1926 | } | ||
1927 | if bodyOpen { | ||
1928 | if vv, ok := rp.header["Content-Length"]; ok { | ||
1929 | req.ContentLength, _ = strconv.ParseInt(vv[0], 10, 64) | ||
1930 | } else { | ||
1931 | req.ContentLength = -1 | ||
1932 | } | ||
1933 | req.Body.(*requestBody).pipe = &pipe{ | ||
1934 | b: &dataBuffer{expected: req.ContentLength}, | ||
1935 | } | ||
1936 | } | ||
1937 | return rw, req, nil | ||
1938 | } | ||
1939 | |||
1940 | type requestParam struct { | ||
1941 | method string | ||
1942 | scheme, authority, path string | ||
1943 | header http.Header | ||
1944 | } | ||
1945 | |||
1946 | func (sc *serverConn) newWriterAndRequestNoBody(st *stream, rp requestParam) (*responseWriter, *http.Request, error) { | ||
1947 | sc.serveG.check() | ||
1948 | |||
1949 | var tlsState *tls.ConnectionState // nil if not scheme https | ||
1950 | if rp.scheme == "https" { | ||
1951 | tlsState = sc.tlsState | ||
1952 | } | ||
1953 | |||
1954 | needsContinue := rp.header.Get("Expect") == "100-continue" | ||
1955 | if needsContinue { | ||
1956 | rp.header.Del("Expect") | ||
1957 | } | ||
1958 | // Merge Cookie headers into one "; "-delimited value. | ||
1959 | if cookies := rp.header["Cookie"]; len(cookies) > 1 { | ||
1960 | rp.header.Set("Cookie", strings.Join(cookies, "; ")) | ||
1961 | } | ||
1962 | |||
1963 | // Setup Trailers | ||
1964 | var trailer http.Header | ||
1965 | for _, v := range rp.header["Trailer"] { | ||
1966 | for _, key := range strings.Split(v, ",") { | ||
1967 | key = http.CanonicalHeaderKey(strings.TrimSpace(key)) | ||
1968 | switch key { | ||
1969 | case "Transfer-Encoding", "Trailer", "Content-Length": | ||
1970 | // Bogus. (copy of http1 rules) | ||
1971 | // Ignore. | ||
1972 | default: | ||
1973 | if trailer == nil { | ||
1974 | trailer = make(http.Header) | ||
1975 | } | ||
1976 | trailer[key] = nil | ||
1977 | } | ||
1978 | } | ||
1979 | } | ||
1980 | delete(rp.header, "Trailer") | ||
1981 | |||
1982 | var url_ *url.URL | ||
1983 | var requestURI string | ||
1984 | if rp.method == "CONNECT" { | ||
1985 | url_ = &url.URL{Host: rp.authority} | ||
1986 | requestURI = rp.authority // mimic HTTP/1 server behavior | ||
1987 | } else { | ||
1988 | var err error | ||
1989 | url_, err = url.ParseRequestURI(rp.path) | ||
1990 | if err != nil { | ||
1991 | return nil, nil, streamError(st.id, ErrCodeProtocol) | ||
1992 | } | ||
1993 | requestURI = rp.path | ||
1994 | } | ||
1995 | |||
1996 | body := &requestBody{ | ||
1997 | conn: sc, | ||
1998 | stream: st, | ||
1999 | needsContinue: needsContinue, | ||
2000 | } | ||
2001 | req := &http.Request{ | ||
2002 | Method: rp.method, | ||
2003 | URL: url_, | ||
2004 | RemoteAddr: sc.remoteAddrStr, | ||
2005 | Header: rp.header, | ||
2006 | RequestURI: requestURI, | ||
2007 | Proto: "HTTP/2.0", | ||
2008 | ProtoMajor: 2, | ||
2009 | ProtoMinor: 0, | ||
2010 | TLS: tlsState, | ||
2011 | Host: rp.authority, | ||
2012 | Body: body, | ||
2013 | Trailer: trailer, | ||
2014 | } | ||
2015 | req = requestWithContext(req, st.ctx) | ||
2016 | |||
2017 | rws := responseWriterStatePool.Get().(*responseWriterState) | ||
2018 | bwSave := rws.bw | ||
2019 | *rws = responseWriterState{} // zero all the fields | ||
2020 | rws.conn = sc | ||
2021 | rws.bw = bwSave | ||
2022 | rws.bw.Reset(chunkWriter{rws}) | ||
2023 | rws.stream = st | ||
2024 | rws.req = req | ||
2025 | rws.body = body | ||
2026 | |||
2027 | rw := &responseWriter{rws: rws} | ||
2028 | return rw, req, nil | ||
2029 | } | ||
2030 | |||
2031 | // Run on its own goroutine. | ||
2032 | func (sc *serverConn) runHandler(rw *responseWriter, req *http.Request, handler func(http.ResponseWriter, *http.Request)) { | ||
2033 | didPanic := true | ||
2034 | defer func() { | ||
2035 | rw.rws.stream.cancelCtx() | ||
2036 | if didPanic { | ||
2037 | e := recover() | ||
2038 | sc.writeFrameFromHandler(FrameWriteRequest{ | ||
2039 | write: handlerPanicRST{rw.rws.stream.id}, | ||
2040 | stream: rw.rws.stream, | ||
2041 | }) | ||
2042 | // Same as net/http: | ||
2043 | if shouldLogPanic(e) { | ||
2044 | const size = 64 << 10 | ||
2045 | buf := make([]byte, size) | ||
2046 | buf = buf[:runtime.Stack(buf, false)] | ||
2047 | sc.logf("http2: panic serving %v: %v\n%s", sc.conn.RemoteAddr(), e, buf) | ||
2048 | } | ||
2049 | return | ||
2050 | } | ||
2051 | rw.handlerDone() | ||
2052 | }() | ||
2053 | handler(rw, req) | ||
2054 | didPanic = false | ||
2055 | } | ||
2056 | |||
2057 | func handleHeaderListTooLong(w http.ResponseWriter, r *http.Request) { | ||
2058 | // 10.5.1 Limits on Header Block Size: | ||
2059 | // .. "A server that receives a larger header block than it is | ||
2060 | // willing to handle can send an HTTP 431 (Request Header Fields Too | ||
2061 | // Large) status code" | ||
2062 | const statusRequestHeaderFieldsTooLarge = 431 // only in Go 1.6+ | ||
2063 | w.WriteHeader(statusRequestHeaderFieldsTooLarge) | ||
2064 | io.WriteString(w, "<h1>HTTP Error 431</h1><p>Request Header Field(s) Too Large</p>") | ||
2065 | } | ||
2066 | |||
2067 | // called from handler goroutines. | ||
2068 | // h may be nil. | ||
2069 | func (sc *serverConn) writeHeaders(st *stream, headerData *writeResHeaders) error { | ||
2070 | sc.serveG.checkNotOn() // NOT on | ||
2071 | var errc chan error | ||
2072 | if headerData.h != nil { | ||
2073 | // If there's a header map (which we don't own), so we have to block on | ||
2074 | // waiting for this frame to be written, so an http.Flush mid-handler | ||
2075 | // writes out the correct value of keys, before a handler later potentially | ||
2076 | // mutates it. | ||
2077 | errc = errChanPool.Get().(chan error) | ||
2078 | } | ||
2079 | if err := sc.writeFrameFromHandler(FrameWriteRequest{ | ||
2080 | write: headerData, | ||
2081 | stream: st, | ||
2082 | done: errc, | ||
2083 | }); err != nil { | ||
2084 | return err | ||
2085 | } | ||
2086 | if errc != nil { | ||
2087 | select { | ||
2088 | case err := <-errc: | ||
2089 | errChanPool.Put(errc) | ||
2090 | return err | ||
2091 | case <-sc.doneServing: | ||
2092 | return errClientDisconnected | ||
2093 | case <-st.cw: | ||
2094 | return errStreamClosed | ||
2095 | } | ||
2096 | } | ||
2097 | return nil | ||
2098 | } | ||
2099 | |||
2100 | // called from handler goroutines. | ||
2101 | func (sc *serverConn) write100ContinueHeaders(st *stream) { | ||
2102 | sc.writeFrameFromHandler(FrameWriteRequest{ | ||
2103 | write: write100ContinueHeadersFrame{st.id}, | ||
2104 | stream: st, | ||
2105 | }) | ||
2106 | } | ||
2107 | |||
2108 | // A bodyReadMsg tells the server loop that the http.Handler read n | ||
2109 | // bytes of the DATA from the client on the given stream. | ||
2110 | type bodyReadMsg struct { | ||
2111 | st *stream | ||
2112 | n int | ||
2113 | } | ||
2114 | |||
2115 | // called from handler goroutines. | ||
2116 | // Notes that the handler for the given stream ID read n bytes of its body | ||
2117 | // and schedules flow control tokens to be sent. | ||
2118 | func (sc *serverConn) noteBodyReadFromHandler(st *stream, n int, err error) { | ||
2119 | sc.serveG.checkNotOn() // NOT on | ||
2120 | if n > 0 { | ||
2121 | select { | ||
2122 | case sc.bodyReadCh <- bodyReadMsg{st, n}: | ||
2123 | case <-sc.doneServing: | ||
2124 | } | ||
2125 | } | ||
2126 | } | ||
2127 | |||
2128 | func (sc *serverConn) noteBodyRead(st *stream, n int) { | ||
2129 | sc.serveG.check() | ||
2130 | sc.sendWindowUpdate(nil, n) // conn-level | ||
2131 | if st.state != stateHalfClosedRemote && st.state != stateClosed { | ||
2132 | // Don't send this WINDOW_UPDATE if the stream is closed | ||
2133 | // remotely. | ||
2134 | sc.sendWindowUpdate(st, n) | ||
2135 | } | ||
2136 | } | ||
2137 | |||
2138 | // st may be nil for conn-level | ||
2139 | func (sc *serverConn) sendWindowUpdate(st *stream, n int) { | ||
2140 | sc.serveG.check() | ||
2141 | // "The legal range for the increment to the flow control | ||
2142 | // window is 1 to 2^31-1 (2,147,483,647) octets." | ||
2143 | // A Go Read call on 64-bit machines could in theory read | ||
2144 | // a larger Read than this. Very unlikely, but we handle it here | ||
2145 | // rather than elsewhere for now. | ||
2146 | const maxUint31 = 1<<31 - 1 | ||
2147 | for n >= maxUint31 { | ||
2148 | sc.sendWindowUpdate32(st, maxUint31) | ||
2149 | n -= maxUint31 | ||
2150 | } | ||
2151 | sc.sendWindowUpdate32(st, int32(n)) | ||
2152 | } | ||
2153 | |||
2154 | // st may be nil for conn-level | ||
2155 | func (sc *serverConn) sendWindowUpdate32(st *stream, n int32) { | ||
2156 | sc.serveG.check() | ||
2157 | if n == 0 { | ||
2158 | return | ||
2159 | } | ||
2160 | if n < 0 { | ||
2161 | panic("negative update") | ||
2162 | } | ||
2163 | var streamID uint32 | ||
2164 | if st != nil { | ||
2165 | streamID = st.id | ||
2166 | } | ||
2167 | sc.writeFrame(FrameWriteRequest{ | ||
2168 | write: writeWindowUpdate{streamID: streamID, n: uint32(n)}, | ||
2169 | stream: st, | ||
2170 | }) | ||
2171 | var ok bool | ||
2172 | if st == nil { | ||
2173 | ok = sc.inflow.add(n) | ||
2174 | } else { | ||
2175 | ok = st.inflow.add(n) | ||
2176 | } | ||
2177 | if !ok { | ||
2178 | panic("internal error; sent too many window updates without decrements?") | ||
2179 | } | ||
2180 | } | ||
2181 | |||
2182 | // requestBody is the Handler's Request.Body type. | ||
2183 | // Read and Close may be called concurrently. | ||
2184 | type requestBody struct { | ||
2185 | stream *stream | ||
2186 | conn *serverConn | ||
2187 | closed bool // for use by Close only | ||
2188 | sawEOF bool // for use by Read only | ||
2189 | pipe *pipe // non-nil if we have a HTTP entity message body | ||
2190 | needsContinue bool // need to send a 100-continue | ||
2191 | } | ||
2192 | |||
2193 | func (b *requestBody) Close() error { | ||
2194 | if b.pipe != nil && !b.closed { | ||
2195 | b.pipe.BreakWithError(errClosedBody) | ||
2196 | } | ||
2197 | b.closed = true | ||
2198 | return nil | ||
2199 | } | ||
2200 | |||
2201 | func (b *requestBody) Read(p []byte) (n int, err error) { | ||
2202 | if b.needsContinue { | ||
2203 | b.needsContinue = false | ||
2204 | b.conn.write100ContinueHeaders(b.stream) | ||
2205 | } | ||
2206 | if b.pipe == nil || b.sawEOF { | ||
2207 | return 0, io.EOF | ||
2208 | } | ||
2209 | n, err = b.pipe.Read(p) | ||
2210 | if err == io.EOF { | ||
2211 | b.sawEOF = true | ||
2212 | } | ||
2213 | if b.conn == nil && inTests { | ||
2214 | return | ||
2215 | } | ||
2216 | b.conn.noteBodyReadFromHandler(b.stream, n, err) | ||
2217 | return | ||
2218 | } | ||
2219 | |||
2220 | // responseWriter is the http.ResponseWriter implementation. It's | ||
2221 | // intentionally small (1 pointer wide) to minimize garbage. The | ||
2222 | // responseWriterState pointer inside is zeroed at the end of a | ||
2223 | // request (in handlerDone) and calls on the responseWriter thereafter | ||
2224 | // simply crash (caller's mistake), but the much larger responseWriterState | ||
2225 | // and buffers are reused between multiple requests. | ||
2226 | type responseWriter struct { | ||
2227 | rws *responseWriterState | ||
2228 | } | ||
2229 | |||
2230 | // Optional http.ResponseWriter interfaces implemented. | ||
2231 | var ( | ||
2232 | _ http.CloseNotifier = (*responseWriter)(nil) | ||
2233 | _ http.Flusher = (*responseWriter)(nil) | ||
2234 | _ stringWriter = (*responseWriter)(nil) | ||
2235 | ) | ||
2236 | |||
2237 | type responseWriterState struct { | ||
2238 | // immutable within a request: | ||
2239 | stream *stream | ||
2240 | req *http.Request | ||
2241 | body *requestBody // to close at end of request, if DATA frames didn't | ||
2242 | conn *serverConn | ||
2243 | |||
2244 | // TODO: adjust buffer writing sizes based on server config, frame size updates from peer, etc | ||
2245 | bw *bufio.Writer // writing to a chunkWriter{this *responseWriterState} | ||
2246 | |||
2247 | // mutated by http.Handler goroutine: | ||
2248 | handlerHeader http.Header // nil until called | ||
2249 | snapHeader http.Header // snapshot of handlerHeader at WriteHeader time | ||
2250 | trailers []string // set in writeChunk | ||
2251 | status int // status code passed to WriteHeader | ||
2252 | wroteHeader bool // WriteHeader called (explicitly or implicitly). Not necessarily sent to user yet. | ||
2253 | sentHeader bool // have we sent the header frame? | ||
2254 | handlerDone bool // handler has finished | ||
2255 | dirty bool // a Write failed; don't reuse this responseWriterState | ||
2256 | |||
2257 | sentContentLen int64 // non-zero if handler set a Content-Length header | ||
2258 | wroteBytes int64 | ||
2259 | |||
2260 | closeNotifierMu sync.Mutex // guards closeNotifierCh | ||
2261 | closeNotifierCh chan bool // nil until first used | ||
2262 | } | ||
2263 | |||
2264 | type chunkWriter struct{ rws *responseWriterState } | ||
2265 | |||
2266 | func (cw chunkWriter) Write(p []byte) (n int, err error) { return cw.rws.writeChunk(p) } | ||
2267 | |||
2268 | func (rws *responseWriterState) hasTrailers() bool { return len(rws.trailers) != 0 } | ||
2269 | |||
2270 | // declareTrailer is called for each Trailer header when the | ||
2271 | // response header is written. It notes that a header will need to be | ||
2272 | // written in the trailers at the end of the response. | ||
2273 | func (rws *responseWriterState) declareTrailer(k string) { | ||
2274 | k = http.CanonicalHeaderKey(k) | ||
2275 | if !ValidTrailerHeader(k) { | ||
2276 | // Forbidden by RFC 2616 14.40. | ||
2277 | rws.conn.logf("ignoring invalid trailer %q", k) | ||
2278 | return | ||
2279 | } | ||
2280 | if !strSliceContains(rws.trailers, k) { | ||
2281 | rws.trailers = append(rws.trailers, k) | ||
2282 | } | ||
2283 | } | ||
2284 | |||
2285 | // writeChunk writes chunks from the bufio.Writer. But because | ||
2286 | // bufio.Writer may bypass its chunking, sometimes p may be | ||
2287 | // arbitrarily large. | ||
2288 | // | ||
2289 | // writeChunk is also responsible (on the first chunk) for sending the | ||
2290 | // HEADER response. | ||
2291 | func (rws *responseWriterState) writeChunk(p []byte) (n int, err error) { | ||
2292 | if !rws.wroteHeader { | ||
2293 | rws.writeHeader(200) | ||
2294 | } | ||
2295 | |||
2296 | isHeadResp := rws.req.Method == "HEAD" | ||
2297 | if !rws.sentHeader { | ||
2298 | rws.sentHeader = true | ||
2299 | var ctype, clen string | ||
2300 | if clen = rws.snapHeader.Get("Content-Length"); clen != "" { | ||
2301 | rws.snapHeader.Del("Content-Length") | ||
2302 | clen64, err := strconv.ParseInt(clen, 10, 64) | ||
2303 | if err == nil && clen64 >= 0 { | ||
2304 | rws.sentContentLen = clen64 | ||
2305 | } else { | ||
2306 | clen = "" | ||
2307 | } | ||
2308 | } | ||
2309 | if clen == "" && rws.handlerDone && bodyAllowedForStatus(rws.status) && (len(p) > 0 || !isHeadResp) { | ||
2310 | clen = strconv.Itoa(len(p)) | ||
2311 | } | ||
2312 | _, hasContentType := rws.snapHeader["Content-Type"] | ||
2313 | if !hasContentType && bodyAllowedForStatus(rws.status) { | ||
2314 | ctype = http.DetectContentType(p) | ||
2315 | } | ||
2316 | var date string | ||
2317 | if _, ok := rws.snapHeader["Date"]; !ok { | ||
2318 | // TODO(bradfitz): be faster here, like net/http? measure. | ||
2319 | date = time.Now().UTC().Format(http.TimeFormat) | ||
2320 | } | ||
2321 | |||
2322 | for _, v := range rws.snapHeader["Trailer"] { | ||
2323 | foreachHeaderElement(v, rws.declareTrailer) | ||
2324 | } | ||
2325 | |||
2326 | endStream := (rws.handlerDone && !rws.hasTrailers() && len(p) == 0) || isHeadResp | ||
2327 | err = rws.conn.writeHeaders(rws.stream, &writeResHeaders{ | ||
2328 | streamID: rws.stream.id, | ||
2329 | httpResCode: rws.status, | ||
2330 | h: rws.snapHeader, | ||
2331 | endStream: endStream, | ||
2332 | contentType: ctype, | ||
2333 | contentLength: clen, | ||
2334 | date: date, | ||
2335 | }) | ||
2336 | if err != nil { | ||
2337 | rws.dirty = true | ||
2338 | return 0, err | ||
2339 | } | ||
2340 | if endStream { | ||
2341 | return 0, nil | ||
2342 | } | ||
2343 | } | ||
2344 | if isHeadResp { | ||
2345 | return len(p), nil | ||
2346 | } | ||
2347 | if len(p) == 0 && !rws.handlerDone { | ||
2348 | return 0, nil | ||
2349 | } | ||
2350 | |||
2351 | if rws.handlerDone { | ||
2352 | rws.promoteUndeclaredTrailers() | ||
2353 | } | ||
2354 | |||
2355 | endStream := rws.handlerDone && !rws.hasTrailers() | ||
2356 | if len(p) > 0 || endStream { | ||
2357 | // only send a 0 byte DATA frame if we're ending the stream. | ||
2358 | if err := rws.conn.writeDataFromHandler(rws.stream, p, endStream); err != nil { | ||
2359 | rws.dirty = true | ||
2360 | return 0, err | ||
2361 | } | ||
2362 | } | ||
2363 | |||
2364 | if rws.handlerDone && rws.hasTrailers() { | ||
2365 | err = rws.conn.writeHeaders(rws.stream, &writeResHeaders{ | ||
2366 | streamID: rws.stream.id, | ||
2367 | h: rws.handlerHeader, | ||
2368 | trailers: rws.trailers, | ||
2369 | endStream: true, | ||
2370 | }) | ||
2371 | if err != nil { | ||
2372 | rws.dirty = true | ||
2373 | } | ||
2374 | return len(p), err | ||
2375 | } | ||
2376 | return len(p), nil | ||
2377 | } | ||
2378 | |||
2379 | // TrailerPrefix is a magic prefix for ResponseWriter.Header map keys | ||
2380 | // that, if present, signals that the map entry is actually for | ||
2381 | // the response trailers, and not the response headers. The prefix | ||
2382 | // is stripped after the ServeHTTP call finishes and the values are | ||
2383 | // sent in the trailers. | ||
2384 | // | ||
2385 | // This mechanism is intended only for trailers that are not known | ||
2386 | // prior to the headers being written. If the set of trailers is fixed | ||
2387 | // or known before the header is written, the normal Go trailers mechanism | ||
2388 | // is preferred: | ||
2389 | // https://golang.org/pkg/net/http/#ResponseWriter | ||
2390 | // https://golang.org/pkg/net/http/#example_ResponseWriter_trailers | ||
2391 | const TrailerPrefix = "Trailer:" | ||
2392 | |||
2393 | // promoteUndeclaredTrailers permits http.Handlers to set trailers | ||
2394 | // after the header has already been flushed. Because the Go | ||
2395 | // ResponseWriter interface has no way to set Trailers (only the | ||
2396 | // Header), and because we didn't want to expand the ResponseWriter | ||
2397 | // interface, and because nobody used trailers, and because RFC 2616 | ||
2398 | // says you SHOULD (but not must) predeclare any trailers in the | ||
2399 | // header, the official ResponseWriter rules said trailers in Go must | ||
2400 | // be predeclared, and then we reuse the same ResponseWriter.Header() | ||
2401 | // map to mean both Headers and Trailers. When it's time to write the | ||
2402 | // Trailers, we pick out the fields of Headers that were declared as | ||
2403 | // trailers. That worked for a while, until we found the first major | ||
2404 | // user of Trailers in the wild: gRPC (using them only over http2), | ||
2405 | // and gRPC libraries permit setting trailers mid-stream without | ||
2406 | // predeclarnig them. So: change of plans. We still permit the old | ||
2407 | // way, but we also permit this hack: if a Header() key begins with | ||
2408 | // "Trailer:", the suffix of that key is a Trailer. Because ':' is an | ||
2409 | // invalid token byte anyway, there is no ambiguity. (And it's already | ||
2410 | // filtered out) It's mildly hacky, but not terrible. | ||
2411 | // | ||
2412 | // This method runs after the Handler is done and promotes any Header | ||
2413 | // fields to be trailers. | ||
2414 | func (rws *responseWriterState) promoteUndeclaredTrailers() { | ||
2415 | for k, vv := range rws.handlerHeader { | ||
2416 | if !strings.HasPrefix(k, TrailerPrefix) { | ||
2417 | continue | ||
2418 | } | ||
2419 | trailerKey := strings.TrimPrefix(k, TrailerPrefix) | ||
2420 | rws.declareTrailer(trailerKey) | ||
2421 | rws.handlerHeader[http.CanonicalHeaderKey(trailerKey)] = vv | ||
2422 | } | ||
2423 | |||
2424 | if len(rws.trailers) > 1 { | ||
2425 | sorter := sorterPool.Get().(*sorter) | ||
2426 | sorter.SortStrings(rws.trailers) | ||
2427 | sorterPool.Put(sorter) | ||
2428 | } | ||
2429 | } | ||
2430 | |||
2431 | func (w *responseWriter) Flush() { | ||
2432 | rws := w.rws | ||
2433 | if rws == nil { | ||
2434 | panic("Header called after Handler finished") | ||
2435 | } | ||
2436 | if rws.bw.Buffered() > 0 { | ||
2437 | if err := rws.bw.Flush(); err != nil { | ||
2438 | // Ignore the error. The frame writer already knows. | ||
2439 | return | ||
2440 | } | ||
2441 | } else { | ||
2442 | // The bufio.Writer won't call chunkWriter.Write | ||
2443 | // (writeChunk with zero bytes, so we have to do it | ||
2444 | // ourselves to force the HTTP response header and/or | ||
2445 | // final DATA frame (with END_STREAM) to be sent. | ||
2446 | rws.writeChunk(nil) | ||
2447 | } | ||
2448 | } | ||
2449 | |||
2450 | func (w *responseWriter) CloseNotify() <-chan bool { | ||
2451 | rws := w.rws | ||
2452 | if rws == nil { | ||
2453 | panic("CloseNotify called after Handler finished") | ||
2454 | } | ||
2455 | rws.closeNotifierMu.Lock() | ||
2456 | ch := rws.closeNotifierCh | ||
2457 | if ch == nil { | ||
2458 | ch = make(chan bool, 1) | ||
2459 | rws.closeNotifierCh = ch | ||
2460 | cw := rws.stream.cw | ||
2461 | go func() { | ||
2462 | cw.Wait() // wait for close | ||
2463 | ch <- true | ||
2464 | }() | ||
2465 | } | ||
2466 | rws.closeNotifierMu.Unlock() | ||
2467 | return ch | ||
2468 | } | ||
2469 | |||
2470 | func (w *responseWriter) Header() http.Header { | ||
2471 | rws := w.rws | ||
2472 | if rws == nil { | ||
2473 | panic("Header called after Handler finished") | ||
2474 | } | ||
2475 | if rws.handlerHeader == nil { | ||
2476 | rws.handlerHeader = make(http.Header) | ||
2477 | } | ||
2478 | return rws.handlerHeader | ||
2479 | } | ||
2480 | |||
2481 | func (w *responseWriter) WriteHeader(code int) { | ||
2482 | rws := w.rws | ||
2483 | if rws == nil { | ||
2484 | panic("WriteHeader called after Handler finished") | ||
2485 | } | ||
2486 | rws.writeHeader(code) | ||
2487 | } | ||
2488 | |||
2489 | func (rws *responseWriterState) writeHeader(code int) { | ||
2490 | if !rws.wroteHeader { | ||
2491 | rws.wroteHeader = true | ||
2492 | rws.status = code | ||
2493 | if len(rws.handlerHeader) > 0 { | ||
2494 | rws.snapHeader = cloneHeader(rws.handlerHeader) | ||
2495 | } | ||
2496 | } | ||
2497 | } | ||
2498 | |||
2499 | func cloneHeader(h http.Header) http.Header { | ||
2500 | h2 := make(http.Header, len(h)) | ||
2501 | for k, vv := range h { | ||
2502 | vv2 := make([]string, len(vv)) | ||
2503 | copy(vv2, vv) | ||
2504 | h2[k] = vv2 | ||
2505 | } | ||
2506 | return h2 | ||
2507 | } | ||
2508 | |||
2509 | // The Life Of A Write is like this: | ||
2510 | // | ||
2511 | // * Handler calls w.Write or w.WriteString -> | ||
2512 | // * -> rws.bw (*bufio.Writer) -> | ||
2513 | // * (Handler might call Flush) | ||
2514 | // * -> chunkWriter{rws} | ||
2515 | // * -> responseWriterState.writeChunk(p []byte) | ||
2516 | // * -> responseWriterState.writeChunk (most of the magic; see comment there) | ||
2517 | func (w *responseWriter) Write(p []byte) (n int, err error) { | ||
2518 | return w.write(len(p), p, "") | ||
2519 | } | ||
2520 | |||
2521 | func (w *responseWriter) WriteString(s string) (n int, err error) { | ||
2522 | return w.write(len(s), nil, s) | ||
2523 | } | ||
2524 | |||
2525 | // either dataB or dataS is non-zero. | ||
2526 | func (w *responseWriter) write(lenData int, dataB []byte, dataS string) (n int, err error) { | ||
2527 | rws := w.rws | ||
2528 | if rws == nil { | ||
2529 | panic("Write called after Handler finished") | ||
2530 | } | ||
2531 | if !rws.wroteHeader { | ||
2532 | w.WriteHeader(200) | ||
2533 | } | ||
2534 | if !bodyAllowedForStatus(rws.status) { | ||
2535 | return 0, http.ErrBodyNotAllowed | ||
2536 | } | ||
2537 | rws.wroteBytes += int64(len(dataB)) + int64(len(dataS)) // only one can be set | ||
2538 | if rws.sentContentLen != 0 && rws.wroteBytes > rws.sentContentLen { | ||
2539 | // TODO: send a RST_STREAM | ||
2540 | return 0, errors.New("http2: handler wrote more than declared Content-Length") | ||
2541 | } | ||
2542 | |||
2543 | if dataB != nil { | ||
2544 | return rws.bw.Write(dataB) | ||
2545 | } else { | ||
2546 | return rws.bw.WriteString(dataS) | ||
2547 | } | ||
2548 | } | ||
2549 | |||
2550 | func (w *responseWriter) handlerDone() { | ||
2551 | rws := w.rws | ||
2552 | dirty := rws.dirty | ||
2553 | rws.handlerDone = true | ||
2554 | w.Flush() | ||
2555 | w.rws = nil | ||
2556 | if !dirty { | ||
2557 | // Only recycle the pool if all prior Write calls to | ||
2558 | // the serverConn goroutine completed successfully. If | ||
2559 | // they returned earlier due to resets from the peer | ||
2560 | // there might still be write goroutines outstanding | ||
2561 | // from the serverConn referencing the rws memory. See | ||
2562 | // issue 20704. | ||
2563 | responseWriterStatePool.Put(rws) | ||
2564 | } | ||
2565 | } | ||
2566 | |||
2567 | // Push errors. | ||
2568 | var ( | ||
2569 | ErrRecursivePush = errors.New("http2: recursive push not allowed") | ||
2570 | ErrPushLimitReached = errors.New("http2: push would exceed peer's SETTINGS_MAX_CONCURRENT_STREAMS") | ||
2571 | ) | ||
2572 | |||
2573 | // pushOptions is the internal version of http.PushOptions, which we | ||
2574 | // cannot include here because it's only defined in Go 1.8 and later. | ||
2575 | type pushOptions struct { | ||
2576 | Method string | ||
2577 | Header http.Header | ||
2578 | } | ||
2579 | |||
2580 | func (w *responseWriter) push(target string, opts pushOptions) error { | ||
2581 | st := w.rws.stream | ||
2582 | sc := st.sc | ||
2583 | sc.serveG.checkNotOn() | ||
2584 | |||
2585 | // No recursive pushes: "PUSH_PROMISE frames MUST only be sent on a peer-initiated stream." | ||
2586 | // http://tools.ietf.org/html/rfc7540#section-6.6 | ||
2587 | if st.isPushed() { | ||
2588 | return ErrRecursivePush | ||
2589 | } | ||
2590 | |||
2591 | // Default options. | ||
2592 | if opts.Method == "" { | ||
2593 | opts.Method = "GET" | ||
2594 | } | ||
2595 | if opts.Header == nil { | ||
2596 | opts.Header = http.Header{} | ||
2597 | } | ||
2598 | wantScheme := "http" | ||
2599 | if w.rws.req.TLS != nil { | ||
2600 | wantScheme = "https" | ||
2601 | } | ||
2602 | |||
2603 | // Validate the request. | ||
2604 | u, err := url.Parse(target) | ||
2605 | if err != nil { | ||
2606 | return err | ||
2607 | } | ||
2608 | if u.Scheme == "" { | ||
2609 | if !strings.HasPrefix(target, "/") { | ||
2610 | return fmt.Errorf("target must be an absolute URL or an absolute path: %q", target) | ||
2611 | } | ||
2612 | u.Scheme = wantScheme | ||
2613 | u.Host = w.rws.req.Host | ||
2614 | } else { | ||
2615 | if u.Scheme != wantScheme { | ||
2616 | return fmt.Errorf("cannot push URL with scheme %q from request with scheme %q", u.Scheme, wantScheme) | ||
2617 | } | ||
2618 | if u.Host == "" { | ||
2619 | return errors.New("URL must have a host") | ||
2620 | } | ||
2621 | } | ||
2622 | for k := range opts.Header { | ||
2623 | if strings.HasPrefix(k, ":") { | ||
2624 | return fmt.Errorf("promised request headers cannot include pseudo header %q", k) | ||
2625 | } | ||
2626 | // These headers are meaningful only if the request has a body, | ||
2627 | // but PUSH_PROMISE requests cannot have a body. | ||
2628 | // http://tools.ietf.org/html/rfc7540#section-8.2 | ||
2629 | // Also disallow Host, since the promised URL must be absolute. | ||
2630 | switch strings.ToLower(k) { | ||
2631 | case "content-length", "content-encoding", "trailer", "te", "expect", "host": | ||
2632 | return fmt.Errorf("promised request headers cannot include %q", k) | ||
2633 | } | ||
2634 | } | ||
2635 | if err := checkValidHTTP2RequestHeaders(opts.Header); err != nil { | ||
2636 | return err | ||
2637 | } | ||
2638 | |||
2639 | // The RFC effectively limits promised requests to GET and HEAD: | ||
2640 | // "Promised requests MUST be cacheable [GET, HEAD, or POST], and MUST be safe [GET or HEAD]" | ||
2641 | // http://tools.ietf.org/html/rfc7540#section-8.2 | ||
2642 | if opts.Method != "GET" && opts.Method != "HEAD" { | ||
2643 | return fmt.Errorf("method %q must be GET or HEAD", opts.Method) | ||
2644 | } | ||
2645 | |||
2646 | msg := &startPushRequest{ | ||
2647 | parent: st, | ||
2648 | method: opts.Method, | ||
2649 | url: u, | ||
2650 | header: cloneHeader(opts.Header), | ||
2651 | done: errChanPool.Get().(chan error), | ||
2652 | } | ||
2653 | |||
2654 | select { | ||
2655 | case <-sc.doneServing: | ||
2656 | return errClientDisconnected | ||
2657 | case <-st.cw: | ||
2658 | return errStreamClosed | ||
2659 | case sc.serveMsgCh <- msg: | ||
2660 | } | ||
2661 | |||
2662 | select { | ||
2663 | case <-sc.doneServing: | ||
2664 | return errClientDisconnected | ||
2665 | case <-st.cw: | ||
2666 | return errStreamClosed | ||
2667 | case err := <-msg.done: | ||
2668 | errChanPool.Put(msg.done) | ||
2669 | return err | ||
2670 | } | ||
2671 | } | ||
2672 | |||
2673 | type startPushRequest struct { | ||
2674 | parent *stream | ||
2675 | method string | ||
2676 | url *url.URL | ||
2677 | header http.Header | ||
2678 | done chan error | ||
2679 | } | ||
2680 | |||
2681 | func (sc *serverConn) startPush(msg *startPushRequest) { | ||
2682 | sc.serveG.check() | ||
2683 | |||
2684 | // http://tools.ietf.org/html/rfc7540#section-6.6. | ||
2685 | // PUSH_PROMISE frames MUST only be sent on a peer-initiated stream that | ||
2686 | // is in either the "open" or "half-closed (remote)" state. | ||
2687 | if msg.parent.state != stateOpen && msg.parent.state != stateHalfClosedRemote { | ||
2688 | // responseWriter.Push checks that the stream is peer-initiaed. | ||
2689 | msg.done <- errStreamClosed | ||
2690 | return | ||
2691 | } | ||
2692 | |||
2693 | // http://tools.ietf.org/html/rfc7540#section-6.6. | ||
2694 | if !sc.pushEnabled { | ||
2695 | msg.done <- http.ErrNotSupported | ||
2696 | return | ||
2697 | } | ||
2698 | |||
2699 | // PUSH_PROMISE frames must be sent in increasing order by stream ID, so | ||
2700 | // we allocate an ID for the promised stream lazily, when the PUSH_PROMISE | ||
2701 | // is written. Once the ID is allocated, we start the request handler. | ||
2702 | allocatePromisedID := func() (uint32, error) { | ||
2703 | sc.serveG.check() | ||
2704 | |||
2705 | // Check this again, just in case. Technically, we might have received | ||
2706 | // an updated SETTINGS by the time we got around to writing this frame. | ||
2707 | if !sc.pushEnabled { | ||
2708 | return 0, http.ErrNotSupported | ||
2709 | } | ||
2710 | // http://tools.ietf.org/html/rfc7540#section-6.5.2. | ||
2711 | if sc.curPushedStreams+1 > sc.clientMaxStreams { | ||
2712 | return 0, ErrPushLimitReached | ||
2713 | } | ||
2714 | |||
2715 | // http://tools.ietf.org/html/rfc7540#section-5.1.1. | ||
2716 | // Streams initiated by the server MUST use even-numbered identifiers. | ||
2717 | // A server that is unable to establish a new stream identifier can send a GOAWAY | ||
2718 | // frame so that the client is forced to open a new connection for new streams. | ||
2719 | if sc.maxPushPromiseID+2 >= 1<<31 { | ||
2720 | sc.startGracefulShutdownInternal() | ||
2721 | return 0, ErrPushLimitReached | ||
2722 | } | ||
2723 | sc.maxPushPromiseID += 2 | ||
2724 | promisedID := sc.maxPushPromiseID | ||
2725 | |||
2726 | // http://tools.ietf.org/html/rfc7540#section-8.2. | ||
2727 | // Strictly speaking, the new stream should start in "reserved (local)", then | ||
2728 | // transition to "half closed (remote)" after sending the initial HEADERS, but | ||
2729 | // we start in "half closed (remote)" for simplicity. | ||
2730 | // See further comments at the definition of stateHalfClosedRemote. | ||
2731 | promised := sc.newStream(promisedID, msg.parent.id, stateHalfClosedRemote) | ||
2732 | rw, req, err := sc.newWriterAndRequestNoBody(promised, requestParam{ | ||
2733 | method: msg.method, | ||
2734 | scheme: msg.url.Scheme, | ||
2735 | authority: msg.url.Host, | ||
2736 | path: msg.url.RequestURI(), | ||
2737 | header: cloneHeader(msg.header), // clone since handler runs concurrently with writing the PUSH_PROMISE | ||
2738 | }) | ||
2739 | if err != nil { | ||
2740 | // Should not happen, since we've already validated msg.url. | ||
2741 | panic(fmt.Sprintf("newWriterAndRequestNoBody(%+v): %v", msg.url, err)) | ||
2742 | } | ||
2743 | |||
2744 | go sc.runHandler(rw, req, sc.handler.ServeHTTP) | ||
2745 | return promisedID, nil | ||
2746 | } | ||
2747 | |||
2748 | sc.writeFrame(FrameWriteRequest{ | ||
2749 | write: &writePushPromise{ | ||
2750 | streamID: msg.parent.id, | ||
2751 | method: msg.method, | ||
2752 | url: msg.url, | ||
2753 | h: msg.header, | ||
2754 | allocatePromisedID: allocatePromisedID, | ||
2755 | }, | ||
2756 | stream: msg.parent, | ||
2757 | done: msg.done, | ||
2758 | }) | ||
2759 | } | ||
2760 | |||
2761 | // foreachHeaderElement splits v according to the "#rule" construction | ||
2762 | // in RFC 2616 section 2.1 and calls fn for each non-empty element. | ||
2763 | func foreachHeaderElement(v string, fn func(string)) { | ||
2764 | v = textproto.TrimString(v) | ||
2765 | if v == "" { | ||
2766 | return | ||
2767 | } | ||
2768 | if !strings.Contains(v, ",") { | ||
2769 | fn(v) | ||
2770 | return | ||
2771 | } | ||
2772 | for _, f := range strings.Split(v, ",") { | ||
2773 | if f = textproto.TrimString(f); f != "" { | ||
2774 | fn(f) | ||
2775 | } | ||
2776 | } | ||
2777 | } | ||
2778 | |||
2779 | // From http://httpwg.org/specs/rfc7540.html#rfc.section.8.1.2.2 | ||
2780 | var connHeaders = []string{ | ||
2781 | "Connection", | ||
2782 | "Keep-Alive", | ||
2783 | "Proxy-Connection", | ||
2784 | "Transfer-Encoding", | ||
2785 | "Upgrade", | ||
2786 | } | ||
2787 | |||
2788 | // checkValidHTTP2RequestHeaders checks whether h is a valid HTTP/2 request, | ||
2789 | // per RFC 7540 Section 8.1.2.2. | ||
2790 | // The returned error is reported to users. | ||
2791 | func checkValidHTTP2RequestHeaders(h http.Header) error { | ||
2792 | for _, k := range connHeaders { | ||
2793 | if _, ok := h[k]; ok { | ||
2794 | return fmt.Errorf("request header %q is not valid in HTTP/2", k) | ||
2795 | } | ||
2796 | } | ||
2797 | te := h["Te"] | ||
2798 | if len(te) > 0 && (len(te) > 1 || (te[0] != "trailers" && te[0] != "")) { | ||
2799 | return errors.New(`request header "TE" may only be "trailers" in HTTP/2`) | ||
2800 | } | ||
2801 | return nil | ||
2802 | } | ||
2803 | |||
2804 | func new400Handler(err error) http.HandlerFunc { | ||
2805 | return func(w http.ResponseWriter, r *http.Request) { | ||
2806 | http.Error(w, err.Error(), http.StatusBadRequest) | ||
2807 | } | ||
2808 | } | ||
2809 | |||
2810 | // ValidTrailerHeader reports whether name is a valid header field name to appear | ||
2811 | // in trailers. | ||
2812 | // See: http://tools.ietf.org/html/rfc7230#section-4.1.2 | ||
2813 | func ValidTrailerHeader(name string) bool { | ||
2814 | name = http.CanonicalHeaderKey(name) | ||
2815 | if strings.HasPrefix(name, "If-") || badTrailer[name] { | ||
2816 | return false | ||
2817 | } | ||
2818 | return true | ||
2819 | } | ||
2820 | |||
2821 | var badTrailer = map[string]bool{ | ||
2822 | "Authorization": true, | ||
2823 | "Cache-Control": true, | ||
2824 | "Connection": true, | ||
2825 | "Content-Encoding": true, | ||
2826 | "Content-Length": true, | ||
2827 | "Content-Range": true, | ||
2828 | "Content-Type": true, | ||
2829 | "Expect": true, | ||
2830 | "Host": true, | ||
2831 | "Keep-Alive": true, | ||
2832 | "Max-Forwards": true, | ||
2833 | "Pragma": true, | ||
2834 | "Proxy-Authenticate": true, | ||
2835 | "Proxy-Authorization": true, | ||
2836 | "Proxy-Connection": true, | ||
2837 | "Range": true, | ||
2838 | "Realm": true, | ||
2839 | "Te": true, | ||
2840 | "Trailer": true, | ||
2841 | "Transfer-Encoding": true, | ||
2842 | "Www-Authenticate": true, | ||
2843 | } | ||
2844 | |||
2845 | // h1ServerKeepAlivesDisabled reports whether hs has its keep-alives | ||
2846 | // disabled. See comments on h1ServerShutdownChan above for why | ||
2847 | // the code is written this way. | ||
2848 | func h1ServerKeepAlivesDisabled(hs *http.Server) bool { | ||
2849 | var x interface{} = hs | ||
2850 | type I interface { | ||
2851 | doKeepAlives() bool | ||
2852 | } | ||
2853 | if hs, ok := x.(I); ok { | ||
2854 | return !hs.doKeepAlives() | ||
2855 | } | ||
2856 | return false | ||
2857 | } | ||
diff --git a/vendor/golang.org/x/net/http2/transport.go b/vendor/golang.org/x/net/http2/transport.go new file mode 100644 index 0000000..adb77ff --- /dev/null +++ b/vendor/golang.org/x/net/http2/transport.go | |||
@@ -0,0 +1,2275 @@ | |||
1 | // Copyright 2015 The Go Authors. All rights reserved. | ||
2 | // Use of this source code is governed by a BSD-style | ||
3 | // license that can be found in the LICENSE file. | ||
4 | |||
5 | // Transport code. | ||
6 | |||
7 | package http2 | ||
8 | |||
9 | import ( | ||
10 | "bufio" | ||
11 | "bytes" | ||
12 | "compress/gzip" | ||
13 | "crypto/rand" | ||
14 | "crypto/tls" | ||
15 | "errors" | ||
16 | "fmt" | ||
17 | "io" | ||
18 | "io/ioutil" | ||
19 | "log" | ||
20 | "math" | ||
21 | mathrand "math/rand" | ||
22 | "net" | ||
23 | "net/http" | ||
24 | "sort" | ||
25 | "strconv" | ||
26 | "strings" | ||
27 | "sync" | ||
28 | "time" | ||
29 | |||
30 | "golang.org/x/net/http2/hpack" | ||
31 | "golang.org/x/net/idna" | ||
32 | "golang.org/x/net/lex/httplex" | ||
33 | ) | ||
34 | |||
35 | const ( | ||
36 | // transportDefaultConnFlow is how many connection-level flow control | ||
37 | // tokens we give the server at start-up, past the default 64k. | ||
38 | transportDefaultConnFlow = 1 << 30 | ||
39 | |||
40 | // transportDefaultStreamFlow is how many stream-level flow | ||
41 | // control tokens we announce to the peer, and how many bytes | ||
42 | // we buffer per stream. | ||
43 | transportDefaultStreamFlow = 4 << 20 | ||
44 | |||
45 | // transportDefaultStreamMinRefresh is the minimum number of bytes we'll send | ||
46 | // a stream-level WINDOW_UPDATE for at a time. | ||
47 | transportDefaultStreamMinRefresh = 4 << 10 | ||
48 | |||
49 | defaultUserAgent = "Go-http-client/2.0" | ||
50 | ) | ||
51 | |||
52 | // Transport is an HTTP/2 Transport. | ||
53 | // | ||
54 | // A Transport internally caches connections to servers. It is safe | ||
55 | // for concurrent use by multiple goroutines. | ||
56 | type Transport struct { | ||
57 | // DialTLS specifies an optional dial function for creating | ||
58 | // TLS connections for requests. | ||
59 | // | ||
60 | // If DialTLS is nil, tls.Dial is used. | ||
61 | // | ||
62 | // If the returned net.Conn has a ConnectionState method like tls.Conn, | ||
63 | // it will be used to set http.Response.TLS. | ||
64 | DialTLS func(network, addr string, cfg *tls.Config) (net.Conn, error) | ||
65 | |||
66 | // TLSClientConfig specifies the TLS configuration to use with | ||
67 | // tls.Client. If nil, the default configuration is used. | ||
68 | TLSClientConfig *tls.Config | ||
69 | |||
70 | // ConnPool optionally specifies an alternate connection pool to use. | ||
71 | // If nil, the default is used. | ||
72 | ConnPool ClientConnPool | ||
73 | |||
74 | // DisableCompression, if true, prevents the Transport from | ||
75 | // requesting compression with an "Accept-Encoding: gzip" | ||
76 | // request header when the Request contains no existing | ||
77 | // Accept-Encoding value. If the Transport requests gzip on | ||
78 | // its own and gets a gzipped response, it's transparently | ||
79 | // decoded in the Response.Body. However, if the user | ||
80 | // explicitly requested gzip it is not automatically | ||
81 | // uncompressed. | ||
82 | DisableCompression bool | ||
83 | |||
84 | // AllowHTTP, if true, permits HTTP/2 requests using the insecure, | ||
85 | // plain-text "http" scheme. Note that this does not enable h2c support. | ||
86 | AllowHTTP bool | ||
87 | |||
88 | // MaxHeaderListSize is the http2 SETTINGS_MAX_HEADER_LIST_SIZE to | ||
89 | // send in the initial settings frame. It is how many bytes | ||
90 | // of response headers are allowed. Unlike the http2 spec, zero here | ||
91 | // means to use a default limit (currently 10MB). If you actually | ||
92 | // want to advertise an ulimited value to the peer, Transport | ||
93 | // interprets the highest possible value here (0xffffffff or 1<<32-1) | ||
94 | // to mean no limit. | ||
95 | MaxHeaderListSize uint32 | ||
96 | |||
97 | // t1, if non-nil, is the standard library Transport using | ||
98 | // this transport. Its settings are used (but not its | ||
99 | // RoundTrip method, etc). | ||
100 | t1 *http.Transport | ||
101 | |||
102 | connPoolOnce sync.Once | ||
103 | connPoolOrDef ClientConnPool // non-nil version of ConnPool | ||
104 | } | ||
105 | |||
106 | func (t *Transport) maxHeaderListSize() uint32 { | ||
107 | if t.MaxHeaderListSize == 0 { | ||
108 | return 10 << 20 | ||
109 | } | ||
110 | if t.MaxHeaderListSize == 0xffffffff { | ||
111 | return 0 | ||
112 | } | ||
113 | return t.MaxHeaderListSize | ||
114 | } | ||
115 | |||
116 | func (t *Transport) disableCompression() bool { | ||
117 | return t.DisableCompression || (t.t1 != nil && t.t1.DisableCompression) | ||
118 | } | ||
119 | |||
120 | var errTransportVersion = errors.New("http2: ConfigureTransport is only supported starting at Go 1.6") | ||
121 | |||
122 | // ConfigureTransport configures a net/http HTTP/1 Transport to use HTTP/2. | ||
123 | // It requires Go 1.6 or later and returns an error if the net/http package is too old | ||
124 | // or if t1 has already been HTTP/2-enabled. | ||
125 | func ConfigureTransport(t1 *http.Transport) error { | ||
126 | _, err := configureTransport(t1) // in configure_transport.go (go1.6) or not_go16.go | ||
127 | return err | ||
128 | } | ||
129 | |||
130 | func (t *Transport) connPool() ClientConnPool { | ||
131 | t.connPoolOnce.Do(t.initConnPool) | ||
132 | return t.connPoolOrDef | ||
133 | } | ||
134 | |||
135 | func (t *Transport) initConnPool() { | ||
136 | if t.ConnPool != nil { | ||
137 | t.connPoolOrDef = t.ConnPool | ||
138 | } else { | ||
139 | t.connPoolOrDef = &clientConnPool{t: t} | ||
140 | } | ||
141 | } | ||
142 | |||
143 | // ClientConn is the state of a single HTTP/2 client connection to an | ||
144 | // HTTP/2 server. | ||
145 | type ClientConn struct { | ||
146 | t *Transport | ||
147 | tconn net.Conn // usually *tls.Conn, except specialized impls | ||
148 | tlsState *tls.ConnectionState // nil only for specialized impls | ||
149 | singleUse bool // whether being used for a single http.Request | ||
150 | |||
151 | // readLoop goroutine fields: | ||
152 | readerDone chan struct{} // closed on error | ||
153 | readerErr error // set before readerDone is closed | ||
154 | |||
155 | idleTimeout time.Duration // or 0 for never | ||
156 | idleTimer *time.Timer | ||
157 | |||
158 | mu sync.Mutex // guards following | ||
159 | cond *sync.Cond // hold mu; broadcast on flow/closed changes | ||
160 | flow flow // our conn-level flow control quota (cs.flow is per stream) | ||
161 | inflow flow // peer's conn-level flow control | ||
162 | closed bool | ||
163 | wantSettingsAck bool // we sent a SETTINGS frame and haven't heard back | ||
164 | goAway *GoAwayFrame // if non-nil, the GoAwayFrame we received | ||
165 | goAwayDebug string // goAway frame's debug data, retained as a string | ||
166 | streams map[uint32]*clientStream // client-initiated | ||
167 | nextStreamID uint32 | ||
168 | pendingRequests int // requests blocked and waiting to be sent because len(streams) == maxConcurrentStreams | ||
169 | pings map[[8]byte]chan struct{} // in flight ping data to notification channel | ||
170 | bw *bufio.Writer | ||
171 | br *bufio.Reader | ||
172 | fr *Framer | ||
173 | lastActive time.Time | ||
174 | // Settings from peer: (also guarded by mu) | ||
175 | maxFrameSize uint32 | ||
176 | maxConcurrentStreams uint32 | ||
177 | peerMaxHeaderListSize uint64 | ||
178 | initialWindowSize uint32 | ||
179 | |||
180 | hbuf bytes.Buffer // HPACK encoder writes into this | ||
181 | henc *hpack.Encoder | ||
182 | freeBuf [][]byte | ||
183 | |||
184 | wmu sync.Mutex // held while writing; acquire AFTER mu if holding both | ||
185 | werr error // first write error that has occurred | ||
186 | } | ||
187 | |||
188 | // clientStream is the state for a single HTTP/2 stream. One of these | ||
189 | // is created for each Transport.RoundTrip call. | ||
190 | type clientStream struct { | ||
191 | cc *ClientConn | ||
192 | req *http.Request | ||
193 | trace *clientTrace // or nil | ||
194 | ID uint32 | ||
195 | resc chan resAndError | ||
196 | bufPipe pipe // buffered pipe with the flow-controlled response payload | ||
197 | startedWrite bool // started request body write; guarded by cc.mu | ||
198 | requestedGzip bool | ||
199 | on100 func() // optional code to run if get a 100 continue response | ||
200 | |||
201 | flow flow // guarded by cc.mu | ||
202 | inflow flow // guarded by cc.mu | ||
203 | bytesRemain int64 // -1 means unknown; owned by transportResponseBody.Read | ||
204 | readErr error // sticky read error; owned by transportResponseBody.Read | ||
205 | stopReqBody error // if non-nil, stop writing req body; guarded by cc.mu | ||
206 | didReset bool // whether we sent a RST_STREAM to the server; guarded by cc.mu | ||
207 | |||
208 | peerReset chan struct{} // closed on peer reset | ||
209 | resetErr error // populated before peerReset is closed | ||
210 | |||
211 | done chan struct{} // closed when stream remove from cc.streams map; close calls guarded by cc.mu | ||
212 | |||
213 | // owned by clientConnReadLoop: | ||
214 | firstByte bool // got the first response byte | ||
215 | pastHeaders bool // got first MetaHeadersFrame (actual headers) | ||
216 | pastTrailers bool // got optional second MetaHeadersFrame (trailers) | ||
217 | |||
218 | trailer http.Header // accumulated trailers | ||
219 | resTrailer *http.Header // client's Response.Trailer | ||
220 | } | ||
221 | |||
222 | // awaitRequestCancel waits for the user to cancel a request or for the done | ||
223 | // channel to be signaled. A non-nil error is returned only if the request was | ||
224 | // canceled. | ||
225 | func awaitRequestCancel(req *http.Request, done <-chan struct{}) error { | ||
226 | ctx := reqContext(req) | ||
227 | if req.Cancel == nil && ctx.Done() == nil { | ||
228 | return nil | ||
229 | } | ||
230 | select { | ||
231 | case <-req.Cancel: | ||
232 | return errRequestCanceled | ||
233 | case <-ctx.Done(): | ||
234 | return ctx.Err() | ||
235 | case <-done: | ||
236 | return nil | ||
237 | } | ||
238 | } | ||
239 | |||
240 | // awaitRequestCancel waits for the user to cancel a request, its context to | ||
241 | // expire, or for the request to be done (any way it might be removed from the | ||
242 | // cc.streams map: peer reset, successful completion, TCP connection breakage, | ||
243 | // etc). If the request is canceled, then cs will be canceled and closed. | ||
244 | func (cs *clientStream) awaitRequestCancel(req *http.Request) { | ||
245 | if err := awaitRequestCancel(req, cs.done); err != nil { | ||
246 | cs.cancelStream() | ||
247 | cs.bufPipe.CloseWithError(err) | ||
248 | } | ||
249 | } | ||
250 | |||
251 | func (cs *clientStream) cancelStream() { | ||
252 | cc := cs.cc | ||
253 | cc.mu.Lock() | ||
254 | didReset := cs.didReset | ||
255 | cs.didReset = true | ||
256 | cc.mu.Unlock() | ||
257 | |||
258 | if !didReset { | ||
259 | cc.writeStreamReset(cs.ID, ErrCodeCancel, nil) | ||
260 | cc.forgetStreamID(cs.ID) | ||
261 | } | ||
262 | } | ||
263 | |||
264 | // checkResetOrDone reports any error sent in a RST_STREAM frame by the | ||
265 | // server, or errStreamClosed if the stream is complete. | ||
266 | func (cs *clientStream) checkResetOrDone() error { | ||
267 | select { | ||
268 | case <-cs.peerReset: | ||
269 | return cs.resetErr | ||
270 | case <-cs.done: | ||
271 | return errStreamClosed | ||
272 | default: | ||
273 | return nil | ||
274 | } | ||
275 | } | ||
276 | |||
277 | func (cs *clientStream) abortRequestBodyWrite(err error) { | ||
278 | if err == nil { | ||
279 | panic("nil error") | ||
280 | } | ||
281 | cc := cs.cc | ||
282 | cc.mu.Lock() | ||
283 | cs.stopReqBody = err | ||
284 | cc.cond.Broadcast() | ||
285 | cc.mu.Unlock() | ||
286 | } | ||
287 | |||
288 | type stickyErrWriter struct { | ||
289 | w io.Writer | ||
290 | err *error | ||
291 | } | ||
292 | |||
293 | func (sew stickyErrWriter) Write(p []byte) (n int, err error) { | ||
294 | if *sew.err != nil { | ||
295 | return 0, *sew.err | ||
296 | } | ||
297 | n, err = sew.w.Write(p) | ||
298 | *sew.err = err | ||
299 | return | ||
300 | } | ||
301 | |||
302 | var ErrNoCachedConn = errors.New("http2: no cached connection was available") | ||
303 | |||
304 | // RoundTripOpt are options for the Transport.RoundTripOpt method. | ||
305 | type RoundTripOpt struct { | ||
306 | // OnlyCachedConn controls whether RoundTripOpt may | ||
307 | // create a new TCP connection. If set true and | ||
308 | // no cached connection is available, RoundTripOpt | ||
309 | // will return ErrNoCachedConn. | ||
310 | OnlyCachedConn bool | ||
311 | } | ||
312 | |||
313 | func (t *Transport) RoundTrip(req *http.Request) (*http.Response, error) { | ||
314 | return t.RoundTripOpt(req, RoundTripOpt{}) | ||
315 | } | ||
316 | |||
317 | // authorityAddr returns a given authority (a host/IP, or host:port / ip:port) | ||
318 | // and returns a host:port. The port 443 is added if needed. | ||
319 | func authorityAddr(scheme string, authority string) (addr string) { | ||
320 | host, port, err := net.SplitHostPort(authority) | ||
321 | if err != nil { // authority didn't have a port | ||
322 | port = "443" | ||
323 | if scheme == "http" { | ||
324 | port = "80" | ||
325 | } | ||
326 | host = authority | ||
327 | } | ||
328 | if a, err := idna.ToASCII(host); err == nil { | ||
329 | host = a | ||
330 | } | ||
331 | // IPv6 address literal, without a port: | ||
332 | if strings.HasPrefix(host, "[") && strings.HasSuffix(host, "]") { | ||
333 | return host + ":" + port | ||
334 | } | ||
335 | return net.JoinHostPort(host, port) | ||
336 | } | ||
337 | |||
338 | // RoundTripOpt is like RoundTrip, but takes options. | ||
339 | func (t *Transport) RoundTripOpt(req *http.Request, opt RoundTripOpt) (*http.Response, error) { | ||
340 | if !(req.URL.Scheme == "https" || (req.URL.Scheme == "http" && t.AllowHTTP)) { | ||
341 | return nil, errors.New("http2: unsupported scheme") | ||
342 | } | ||
343 | |||
344 | addr := authorityAddr(req.URL.Scheme, req.URL.Host) | ||
345 | for retry := 0; ; retry++ { | ||
346 | cc, err := t.connPool().GetClientConn(req, addr) | ||
347 | if err != nil { | ||
348 | t.vlogf("http2: Transport failed to get client conn for %s: %v", addr, err) | ||
349 | return nil, err | ||
350 | } | ||
351 | traceGotConn(req, cc) | ||
352 | res, err := cc.RoundTrip(req) | ||
353 | if err != nil && retry <= 6 { | ||
354 | afterBodyWrite := false | ||
355 | if e, ok := err.(afterReqBodyWriteError); ok { | ||
356 | err = e | ||
357 | afterBodyWrite = true | ||
358 | } | ||
359 | if req, err = shouldRetryRequest(req, err, afterBodyWrite); err == nil { | ||
360 | // After the first retry, do exponential backoff with 10% jitter. | ||
361 | if retry == 0 { | ||
362 | continue | ||
363 | } | ||
364 | backoff := float64(uint(1) << (uint(retry) - 1)) | ||
365 | backoff += backoff * (0.1 * mathrand.Float64()) | ||
366 | select { | ||
367 | case <-time.After(time.Second * time.Duration(backoff)): | ||
368 | continue | ||
369 | case <-reqContext(req).Done(): | ||
370 | return nil, reqContext(req).Err() | ||
371 | } | ||
372 | } | ||
373 | } | ||
374 | if err != nil { | ||
375 | t.vlogf("RoundTrip failure: %v", err) | ||
376 | return nil, err | ||
377 | } | ||
378 | return res, nil | ||
379 | } | ||
380 | } | ||
381 | |||
382 | // CloseIdleConnections closes any connections which were previously | ||
383 | // connected from previous requests but are now sitting idle. | ||
384 | // It does not interrupt any connections currently in use. | ||
385 | func (t *Transport) CloseIdleConnections() { | ||
386 | if cp, ok := t.connPool().(clientConnPoolIdleCloser); ok { | ||
387 | cp.closeIdleConnections() | ||
388 | } | ||
389 | } | ||
390 | |||
391 | var ( | ||
392 | errClientConnClosed = errors.New("http2: client conn is closed") | ||
393 | errClientConnUnusable = errors.New("http2: client conn not usable") | ||
394 | errClientConnGotGoAway = errors.New("http2: Transport received Server's graceful shutdown GOAWAY") | ||
395 | ) | ||
396 | |||
397 | // afterReqBodyWriteError is a wrapper around errors returned by ClientConn.RoundTrip. | ||
398 | // It is used to signal that err happened after part of Request.Body was sent to the server. | ||
399 | type afterReqBodyWriteError struct { | ||
400 | err error | ||
401 | } | ||
402 | |||
403 | func (e afterReqBodyWriteError) Error() string { | ||
404 | return e.err.Error() + "; some request body already written" | ||
405 | } | ||
406 | |||
407 | // shouldRetryRequest is called by RoundTrip when a request fails to get | ||
408 | // response headers. It is always called with a non-nil error. | ||
409 | // It returns either a request to retry (either the same request, or a | ||
410 | // modified clone), or an error if the request can't be replayed. | ||
411 | func shouldRetryRequest(req *http.Request, err error, afterBodyWrite bool) (*http.Request, error) { | ||
412 | if !canRetryError(err) { | ||
413 | return nil, err | ||
414 | } | ||
415 | if !afterBodyWrite { | ||
416 | return req, nil | ||
417 | } | ||
418 | // If the Body is nil (or http.NoBody), it's safe to reuse | ||
419 | // this request and its Body. | ||
420 | if req.Body == nil || reqBodyIsNoBody(req.Body) { | ||
421 | return req, nil | ||
422 | } | ||
423 | // Otherwise we depend on the Request having its GetBody | ||
424 | // func defined. | ||
425 | getBody := reqGetBody(req) // Go 1.8: getBody = req.GetBody | ||
426 | if getBody == nil { | ||
427 | return nil, fmt.Errorf("http2: Transport: cannot retry err [%v] after Request.Body was written; define Request.GetBody to avoid this error", err) | ||
428 | } | ||
429 | body, err := getBody() | ||
430 | if err != nil { | ||
431 | return nil, err | ||
432 | } | ||
433 | newReq := *req | ||
434 | newReq.Body = body | ||
435 | return &newReq, nil | ||
436 | } | ||
437 | |||
438 | func canRetryError(err error) bool { | ||
439 | if err == errClientConnUnusable || err == errClientConnGotGoAway { | ||
440 | return true | ||
441 | } | ||
442 | if se, ok := err.(StreamError); ok { | ||
443 | return se.Code == ErrCodeRefusedStream | ||
444 | } | ||
445 | return false | ||
446 | } | ||
447 | |||
448 | func (t *Transport) dialClientConn(addr string, singleUse bool) (*ClientConn, error) { | ||
449 | host, _, err := net.SplitHostPort(addr) | ||
450 | if err != nil { | ||
451 | return nil, err | ||
452 | } | ||
453 | tconn, err := t.dialTLS()("tcp", addr, t.newTLSConfig(host)) | ||
454 | if err != nil { | ||
455 | return nil, err | ||
456 | } | ||
457 | return t.newClientConn(tconn, singleUse) | ||
458 | } | ||
459 | |||
460 | func (t *Transport) newTLSConfig(host string) *tls.Config { | ||
461 | cfg := new(tls.Config) | ||
462 | if t.TLSClientConfig != nil { | ||
463 | *cfg = *cloneTLSConfig(t.TLSClientConfig) | ||
464 | } | ||
465 | if !strSliceContains(cfg.NextProtos, NextProtoTLS) { | ||
466 | cfg.NextProtos = append([]string{NextProtoTLS}, cfg.NextProtos...) | ||
467 | } | ||
468 | if cfg.ServerName == "" { | ||
469 | cfg.ServerName = host | ||
470 | } | ||
471 | return cfg | ||
472 | } | ||
473 | |||
474 | func (t *Transport) dialTLS() func(string, string, *tls.Config) (net.Conn, error) { | ||
475 | if t.DialTLS != nil { | ||
476 | return t.DialTLS | ||
477 | } | ||
478 | return t.dialTLSDefault | ||
479 | } | ||
480 | |||
481 | func (t *Transport) dialTLSDefault(network, addr string, cfg *tls.Config) (net.Conn, error) { | ||
482 | cn, err := tls.Dial(network, addr, cfg) | ||
483 | if err != nil { | ||
484 | return nil, err | ||
485 | } | ||
486 | if err := cn.Handshake(); err != nil { | ||
487 | return nil, err | ||
488 | } | ||
489 | if !cfg.InsecureSkipVerify { | ||
490 | if err := cn.VerifyHostname(cfg.ServerName); err != nil { | ||
491 | return nil, err | ||
492 | } | ||
493 | } | ||
494 | state := cn.ConnectionState() | ||
495 | if p := state.NegotiatedProtocol; p != NextProtoTLS { | ||
496 | return nil, fmt.Errorf("http2: unexpected ALPN protocol %q; want %q", p, NextProtoTLS) | ||
497 | } | ||
498 | if !state.NegotiatedProtocolIsMutual { | ||
499 | return nil, errors.New("http2: could not negotiate protocol mutually") | ||
500 | } | ||
501 | return cn, nil | ||
502 | } | ||
503 | |||
504 | // disableKeepAlives reports whether connections should be closed as | ||
505 | // soon as possible after handling the first request. | ||
506 | func (t *Transport) disableKeepAlives() bool { | ||
507 | return t.t1 != nil && t.t1.DisableKeepAlives | ||
508 | } | ||
509 | |||
510 | func (t *Transport) expectContinueTimeout() time.Duration { | ||
511 | if t.t1 == nil { | ||
512 | return 0 | ||
513 | } | ||
514 | return transportExpectContinueTimeout(t.t1) | ||
515 | } | ||
516 | |||
517 | func (t *Transport) NewClientConn(c net.Conn) (*ClientConn, error) { | ||
518 | return t.newClientConn(c, false) | ||
519 | } | ||
520 | |||
521 | func (t *Transport) newClientConn(c net.Conn, singleUse bool) (*ClientConn, error) { | ||
522 | cc := &ClientConn{ | ||
523 | t: t, | ||
524 | tconn: c, | ||
525 | readerDone: make(chan struct{}), | ||
526 | nextStreamID: 1, | ||
527 | maxFrameSize: 16 << 10, // spec default | ||
528 | initialWindowSize: 65535, // spec default | ||
529 | maxConcurrentStreams: 1000, // "infinite", per spec. 1000 seems good enough. | ||
530 | peerMaxHeaderListSize: 0xffffffffffffffff, // "infinite", per spec. Use 2^64-1 instead. | ||
531 | streams: make(map[uint32]*clientStream), | ||
532 | singleUse: singleUse, | ||
533 | wantSettingsAck: true, | ||
534 | pings: make(map[[8]byte]chan struct{}), | ||
535 | } | ||
536 | if d := t.idleConnTimeout(); d != 0 { | ||
537 | cc.idleTimeout = d | ||
538 | cc.idleTimer = time.AfterFunc(d, cc.onIdleTimeout) | ||
539 | } | ||
540 | if VerboseLogs { | ||
541 | t.vlogf("http2: Transport creating client conn %p to %v", cc, c.RemoteAddr()) | ||
542 | } | ||
543 | |||
544 | cc.cond = sync.NewCond(&cc.mu) | ||
545 | cc.flow.add(int32(initialWindowSize)) | ||
546 | |||
547 | // TODO: adjust this writer size to account for frame size + | ||
548 | // MTU + crypto/tls record padding. | ||
549 | cc.bw = bufio.NewWriter(stickyErrWriter{c, &cc.werr}) | ||
550 | cc.br = bufio.NewReader(c) | ||
551 | cc.fr = NewFramer(cc.bw, cc.br) | ||
552 | cc.fr.ReadMetaHeaders = hpack.NewDecoder(initialHeaderTableSize, nil) | ||
553 | cc.fr.MaxHeaderListSize = t.maxHeaderListSize() | ||
554 | |||
555 | // TODO: SetMaxDynamicTableSize, SetMaxDynamicTableSizeLimit on | ||
556 | // henc in response to SETTINGS frames? | ||
557 | cc.henc = hpack.NewEncoder(&cc.hbuf) | ||
558 | |||
559 | if cs, ok := c.(connectionStater); ok { | ||
560 | state := cs.ConnectionState() | ||
561 | cc.tlsState = &state | ||
562 | } | ||
563 | |||
564 | initialSettings := []Setting{ | ||
565 | {ID: SettingEnablePush, Val: 0}, | ||
566 | {ID: SettingInitialWindowSize, Val: transportDefaultStreamFlow}, | ||
567 | } | ||
568 | if max := t.maxHeaderListSize(); max != 0 { | ||
569 | initialSettings = append(initialSettings, Setting{ID: SettingMaxHeaderListSize, Val: max}) | ||
570 | } | ||
571 | |||
572 | cc.bw.Write(clientPreface) | ||
573 | cc.fr.WriteSettings(initialSettings...) | ||
574 | cc.fr.WriteWindowUpdate(0, transportDefaultConnFlow) | ||
575 | cc.inflow.add(transportDefaultConnFlow + initialWindowSize) | ||
576 | cc.bw.Flush() | ||
577 | if cc.werr != nil { | ||
578 | return nil, cc.werr | ||
579 | } | ||
580 | |||
581 | go cc.readLoop() | ||
582 | return cc, nil | ||
583 | } | ||
584 | |||
585 | func (cc *ClientConn) setGoAway(f *GoAwayFrame) { | ||
586 | cc.mu.Lock() | ||
587 | defer cc.mu.Unlock() | ||
588 | |||
589 | old := cc.goAway | ||
590 | cc.goAway = f | ||
591 | |||
592 | // Merge the previous and current GoAway error frames. | ||
593 | if cc.goAwayDebug == "" { | ||
594 | cc.goAwayDebug = string(f.DebugData()) | ||
595 | } | ||
596 | if old != nil && old.ErrCode != ErrCodeNo { | ||
597 | cc.goAway.ErrCode = old.ErrCode | ||
598 | } | ||
599 | last := f.LastStreamID | ||
600 | for streamID, cs := range cc.streams { | ||
601 | if streamID > last { | ||
602 | select { | ||
603 | case cs.resc <- resAndError{err: errClientConnGotGoAway}: | ||
604 | default: | ||
605 | } | ||
606 | } | ||
607 | } | ||
608 | } | ||
609 | |||
610 | // CanTakeNewRequest reports whether the connection can take a new request, | ||
611 | // meaning it has not been closed or received or sent a GOAWAY. | ||
612 | func (cc *ClientConn) CanTakeNewRequest() bool { | ||
613 | cc.mu.Lock() | ||
614 | defer cc.mu.Unlock() | ||
615 | return cc.canTakeNewRequestLocked() | ||
616 | } | ||
617 | |||
618 | func (cc *ClientConn) canTakeNewRequestLocked() bool { | ||
619 | if cc.singleUse && cc.nextStreamID > 1 { | ||
620 | return false | ||
621 | } | ||
622 | return cc.goAway == nil && !cc.closed && | ||
623 | int64(cc.nextStreamID)+int64(cc.pendingRequests) < math.MaxInt32 | ||
624 | } | ||
625 | |||
626 | // onIdleTimeout is called from a time.AfterFunc goroutine. It will | ||
627 | // only be called when we're idle, but because we're coming from a new | ||
628 | // goroutine, there could be a new request coming in at the same time, | ||
629 | // so this simply calls the synchronized closeIfIdle to shut down this | ||
630 | // connection. The timer could just call closeIfIdle, but this is more | ||
631 | // clear. | ||
632 | func (cc *ClientConn) onIdleTimeout() { | ||
633 | cc.closeIfIdle() | ||
634 | } | ||
635 | |||
636 | func (cc *ClientConn) closeIfIdle() { | ||
637 | cc.mu.Lock() | ||
638 | if len(cc.streams) > 0 { | ||
639 | cc.mu.Unlock() | ||
640 | return | ||
641 | } | ||
642 | cc.closed = true | ||
643 | nextID := cc.nextStreamID | ||
644 | // TODO: do clients send GOAWAY too? maybe? Just Close: | ||
645 | cc.mu.Unlock() | ||
646 | |||
647 | if VerboseLogs { | ||
648 | cc.vlogf("http2: Transport closing idle conn %p (forSingleUse=%v, maxStream=%v)", cc, cc.singleUse, nextID-2) | ||
649 | } | ||
650 | cc.tconn.Close() | ||
651 | } | ||
652 | |||
653 | const maxAllocFrameSize = 512 << 10 | ||
654 | |||
655 | // frameBuffer returns a scratch buffer suitable for writing DATA frames. | ||
656 | // They're capped at the min of the peer's max frame size or 512KB | ||
657 | // (kinda arbitrarily), but definitely capped so we don't allocate 4GB | ||
658 | // bufers. | ||
659 | func (cc *ClientConn) frameScratchBuffer() []byte { | ||
660 | cc.mu.Lock() | ||
661 | size := cc.maxFrameSize | ||
662 | if size > maxAllocFrameSize { | ||
663 | size = maxAllocFrameSize | ||
664 | } | ||
665 | for i, buf := range cc.freeBuf { | ||
666 | if len(buf) >= int(size) { | ||
667 | cc.freeBuf[i] = nil | ||
668 | cc.mu.Unlock() | ||
669 | return buf[:size] | ||
670 | } | ||
671 | } | ||
672 | cc.mu.Unlock() | ||
673 | return make([]byte, size) | ||
674 | } | ||
675 | |||
676 | func (cc *ClientConn) putFrameScratchBuffer(buf []byte) { | ||
677 | cc.mu.Lock() | ||
678 | defer cc.mu.Unlock() | ||
679 | const maxBufs = 4 // arbitrary; 4 concurrent requests per conn? investigate. | ||
680 | if len(cc.freeBuf) < maxBufs { | ||
681 | cc.freeBuf = append(cc.freeBuf, buf) | ||
682 | return | ||
683 | } | ||
684 | for i, old := range cc.freeBuf { | ||
685 | if old == nil { | ||
686 | cc.freeBuf[i] = buf | ||
687 | return | ||
688 | } | ||
689 | } | ||
690 | // forget about it. | ||
691 | } | ||
692 | |||
693 | // errRequestCanceled is a copy of net/http's errRequestCanceled because it's not | ||
694 | // exported. At least they'll be DeepEqual for h1-vs-h2 comparisons tests. | ||
695 | var errRequestCanceled = errors.New("net/http: request canceled") | ||
696 | |||
697 | func commaSeparatedTrailers(req *http.Request) (string, error) { | ||
698 | keys := make([]string, 0, len(req.Trailer)) | ||
699 | for k := range req.Trailer { | ||
700 | k = http.CanonicalHeaderKey(k) | ||
701 | switch k { | ||
702 | case "Transfer-Encoding", "Trailer", "Content-Length": | ||
703 | return "", &badStringError{"invalid Trailer key", k} | ||
704 | } | ||
705 | keys = append(keys, k) | ||
706 | } | ||
707 | if len(keys) > 0 { | ||
708 | sort.Strings(keys) | ||
709 | return strings.Join(keys, ","), nil | ||
710 | } | ||
711 | return "", nil | ||
712 | } | ||
713 | |||
714 | func (cc *ClientConn) responseHeaderTimeout() time.Duration { | ||
715 | if cc.t.t1 != nil { | ||
716 | return cc.t.t1.ResponseHeaderTimeout | ||
717 | } | ||
718 | // No way to do this (yet?) with just an http2.Transport. Probably | ||
719 | // no need. Request.Cancel this is the new way. We only need to support | ||
720 | // this for compatibility with the old http.Transport fields when | ||
721 | // we're doing transparent http2. | ||
722 | return 0 | ||
723 | } | ||
724 | |||
725 | // checkConnHeaders checks whether req has any invalid connection-level headers. | ||
726 | // per RFC 7540 section 8.1.2.2: Connection-Specific Header Fields. | ||
727 | // Certain headers are special-cased as okay but not transmitted later. | ||
728 | func checkConnHeaders(req *http.Request) error { | ||
729 | if v := req.Header.Get("Upgrade"); v != "" { | ||
730 | return fmt.Errorf("http2: invalid Upgrade request header: %q", req.Header["Upgrade"]) | ||
731 | } | ||
732 | if vv := req.Header["Transfer-Encoding"]; len(vv) > 0 && (len(vv) > 1 || vv[0] != "" && vv[0] != "chunked") { | ||
733 | return fmt.Errorf("http2: invalid Transfer-Encoding request header: %q", vv) | ||
734 | } | ||
735 | if vv := req.Header["Connection"]; len(vv) > 0 && (len(vv) > 1 || vv[0] != "" && vv[0] != "close" && vv[0] != "keep-alive") { | ||
736 | return fmt.Errorf("http2: invalid Connection request header: %q", vv) | ||
737 | } | ||
738 | return nil | ||
739 | } | ||
740 | |||
741 | // actualContentLength returns a sanitized version of | ||
742 | // req.ContentLength, where 0 actually means zero (not unknown) and -1 | ||
743 | // means unknown. | ||
744 | func actualContentLength(req *http.Request) int64 { | ||
745 | if req.Body == nil || reqBodyIsNoBody(req.Body) { | ||
746 | return 0 | ||
747 | } | ||
748 | if req.ContentLength != 0 { | ||
749 | return req.ContentLength | ||
750 | } | ||
751 | return -1 | ||
752 | } | ||
753 | |||
754 | func (cc *ClientConn) RoundTrip(req *http.Request) (*http.Response, error) { | ||
755 | if err := checkConnHeaders(req); err != nil { | ||
756 | return nil, err | ||
757 | } | ||
758 | if cc.idleTimer != nil { | ||
759 | cc.idleTimer.Stop() | ||
760 | } | ||
761 | |||
762 | trailers, err := commaSeparatedTrailers(req) | ||
763 | if err != nil { | ||
764 | return nil, err | ||
765 | } | ||
766 | hasTrailers := trailers != "" | ||
767 | |||
768 | cc.mu.Lock() | ||
769 | if err := cc.awaitOpenSlotForRequest(req); err != nil { | ||
770 | cc.mu.Unlock() | ||
771 | return nil, err | ||
772 | } | ||
773 | |||
774 | body := req.Body | ||
775 | contentLen := actualContentLength(req) | ||
776 | hasBody := contentLen != 0 | ||
777 | |||
778 | // TODO(bradfitz): this is a copy of the logic in net/http. Unify somewhere? | ||
779 | var requestedGzip bool | ||
780 | if !cc.t.disableCompression() && | ||
781 | req.Header.Get("Accept-Encoding") == "" && | ||
782 | req.Header.Get("Range") == "" && | ||
783 | req.Method != "HEAD" { | ||
784 | // Request gzip only, not deflate. Deflate is ambiguous and | ||
785 | // not as universally supported anyway. | ||
786 | // See: http://www.gzip.org/zlib/zlib_faq.html#faq38 | ||
787 | // | ||
788 | // Note that we don't request this for HEAD requests, | ||
789 | // due to a bug in nginx: | ||
790 | // http://trac.nginx.org/nginx/ticket/358 | ||
791 | // https://golang.org/issue/5522 | ||
792 | // | ||
793 | // We don't request gzip if the request is for a range, since | ||
794 | // auto-decoding a portion of a gzipped document will just fail | ||
795 | // anyway. See https://golang.org/issue/8923 | ||
796 | requestedGzip = true | ||
797 | } | ||
798 | |||
799 | // we send: HEADERS{1}, CONTINUATION{0,} + DATA{0,} (DATA is | ||
800 | // sent by writeRequestBody below, along with any Trailers, | ||
801 | // again in form HEADERS{1}, CONTINUATION{0,}) | ||
802 | hdrs, err := cc.encodeHeaders(req, requestedGzip, trailers, contentLen) | ||
803 | if err != nil { | ||
804 | cc.mu.Unlock() | ||
805 | return nil, err | ||
806 | } | ||
807 | |||
808 | cs := cc.newStream() | ||
809 | cs.req = req | ||
810 | cs.trace = requestTrace(req) | ||
811 | cs.requestedGzip = requestedGzip | ||
812 | bodyWriter := cc.t.getBodyWriterState(cs, body) | ||
813 | cs.on100 = bodyWriter.on100 | ||
814 | |||
815 | cc.wmu.Lock() | ||
816 | endStream := !hasBody && !hasTrailers | ||
817 | werr := cc.writeHeaders(cs.ID, endStream, hdrs) | ||
818 | cc.wmu.Unlock() | ||
819 | traceWroteHeaders(cs.trace) | ||
820 | cc.mu.Unlock() | ||
821 | |||
822 | if werr != nil { | ||
823 | if hasBody { | ||
824 | req.Body.Close() // per RoundTripper contract | ||
825 | bodyWriter.cancel() | ||
826 | } | ||
827 | cc.forgetStreamID(cs.ID) | ||
828 | // Don't bother sending a RST_STREAM (our write already failed; | ||
829 | // no need to keep writing) | ||
830 | traceWroteRequest(cs.trace, werr) | ||
831 | return nil, werr | ||
832 | } | ||
833 | |||
834 | var respHeaderTimer <-chan time.Time | ||
835 | if hasBody { | ||
836 | bodyWriter.scheduleBodyWrite() | ||
837 | } else { | ||
838 | traceWroteRequest(cs.trace, nil) | ||
839 | if d := cc.responseHeaderTimeout(); d != 0 { | ||
840 | timer := time.NewTimer(d) | ||
841 | defer timer.Stop() | ||
842 | respHeaderTimer = timer.C | ||
843 | } | ||
844 | } | ||
845 | |||
846 | readLoopResCh := cs.resc | ||
847 | bodyWritten := false | ||
848 | ctx := reqContext(req) | ||
849 | |||
850 | handleReadLoopResponse := func(re resAndError) (*http.Response, error) { | ||
851 | res := re.res | ||
852 | if re.err != nil || res.StatusCode > 299 { | ||
853 | // On error or status code 3xx, 4xx, 5xx, etc abort any | ||
854 | // ongoing write, assuming that the server doesn't care | ||
855 | // about our request body. If the server replied with 1xx or | ||
856 | // 2xx, however, then assume the server DOES potentially | ||
857 | // want our body (e.g. full-duplex streaming: | ||
858 | // golang.org/issue/13444). If it turns out the server | ||
859 | // doesn't, they'll RST_STREAM us soon enough. This is a | ||
860 | // heuristic to avoid adding knobs to Transport. Hopefully | ||
861 | // we can keep it. | ||
862 | bodyWriter.cancel() | ||
863 | cs.abortRequestBodyWrite(errStopReqBodyWrite) | ||
864 | } | ||
865 | if re.err != nil { | ||
866 | cc.mu.Lock() | ||
867 | afterBodyWrite := cs.startedWrite | ||
868 | cc.mu.Unlock() | ||
869 | cc.forgetStreamID(cs.ID) | ||
870 | if afterBodyWrite { | ||
871 | return nil, afterReqBodyWriteError{re.err} | ||
872 | } | ||
873 | return nil, re.err | ||
874 | } | ||
875 | res.Request = req | ||
876 | res.TLS = cc.tlsState | ||
877 | return res, nil | ||
878 | } | ||
879 | |||
880 | for { | ||
881 | select { | ||
882 | case re := <-readLoopResCh: | ||
883 | return handleReadLoopResponse(re) | ||
884 | case <-respHeaderTimer: | ||
885 | if !hasBody || bodyWritten { | ||
886 | cc.writeStreamReset(cs.ID, ErrCodeCancel, nil) | ||
887 | } else { | ||
888 | bodyWriter.cancel() | ||
889 | cs.abortRequestBodyWrite(errStopReqBodyWriteAndCancel) | ||
890 | } | ||
891 | cc.forgetStreamID(cs.ID) | ||
892 | return nil, errTimeout | ||
893 | case <-ctx.Done(): | ||
894 | if !hasBody || bodyWritten { | ||
895 | cc.writeStreamReset(cs.ID, ErrCodeCancel, nil) | ||
896 | } else { | ||
897 | bodyWriter.cancel() | ||
898 | cs.abortRequestBodyWrite(errStopReqBodyWriteAndCancel) | ||
899 | } | ||
900 | cc.forgetStreamID(cs.ID) | ||
901 | return nil, ctx.Err() | ||
902 | case <-req.Cancel: | ||
903 | if !hasBody || bodyWritten { | ||
904 | cc.writeStreamReset(cs.ID, ErrCodeCancel, nil) | ||
905 | } else { | ||
906 | bodyWriter.cancel() | ||
907 | cs.abortRequestBodyWrite(errStopReqBodyWriteAndCancel) | ||
908 | } | ||
909 | cc.forgetStreamID(cs.ID) | ||
910 | return nil, errRequestCanceled | ||
911 | case <-cs.peerReset: | ||
912 | // processResetStream already removed the | ||
913 | // stream from the streams map; no need for | ||
914 | // forgetStreamID. | ||
915 | return nil, cs.resetErr | ||
916 | case err := <-bodyWriter.resc: | ||
917 | // Prefer the read loop's response, if available. Issue 16102. | ||
918 | select { | ||
919 | case re := <-readLoopResCh: | ||
920 | return handleReadLoopResponse(re) | ||
921 | default: | ||
922 | } | ||
923 | if err != nil { | ||
924 | return nil, err | ||
925 | } | ||
926 | bodyWritten = true | ||
927 | if d := cc.responseHeaderTimeout(); d != 0 { | ||
928 | timer := time.NewTimer(d) | ||
929 | defer timer.Stop() | ||
930 | respHeaderTimer = timer.C | ||
931 | } | ||
932 | } | ||
933 | } | ||
934 | } | ||
935 | |||
936 | // awaitOpenSlotForRequest waits until len(streams) < maxConcurrentStreams. | ||
937 | // Must hold cc.mu. | ||
938 | func (cc *ClientConn) awaitOpenSlotForRequest(req *http.Request) error { | ||
939 | var waitingForConn chan struct{} | ||
940 | var waitingForConnErr error // guarded by cc.mu | ||
941 | for { | ||
942 | cc.lastActive = time.Now() | ||
943 | if cc.closed || !cc.canTakeNewRequestLocked() { | ||
944 | return errClientConnUnusable | ||
945 | } | ||
946 | if int64(len(cc.streams))+1 <= int64(cc.maxConcurrentStreams) { | ||
947 | if waitingForConn != nil { | ||
948 | close(waitingForConn) | ||
949 | } | ||
950 | return nil | ||
951 | } | ||
952 | // Unfortunately, we cannot wait on a condition variable and channel at | ||
953 | // the same time, so instead, we spin up a goroutine to check if the | ||
954 | // request is canceled while we wait for a slot to open in the connection. | ||
955 | if waitingForConn == nil { | ||
956 | waitingForConn = make(chan struct{}) | ||
957 | go func() { | ||
958 | if err := awaitRequestCancel(req, waitingForConn); err != nil { | ||
959 | cc.mu.Lock() | ||
960 | waitingForConnErr = err | ||
961 | cc.cond.Broadcast() | ||
962 | cc.mu.Unlock() | ||
963 | } | ||
964 | }() | ||
965 | } | ||
966 | cc.pendingRequests++ | ||
967 | cc.cond.Wait() | ||
968 | cc.pendingRequests-- | ||
969 | if waitingForConnErr != nil { | ||
970 | return waitingForConnErr | ||
971 | } | ||
972 | } | ||
973 | } | ||
974 | |||
975 | // requires cc.wmu be held | ||
976 | func (cc *ClientConn) writeHeaders(streamID uint32, endStream bool, hdrs []byte) error { | ||
977 | first := true // first frame written (HEADERS is first, then CONTINUATION) | ||
978 | frameSize := int(cc.maxFrameSize) | ||
979 | for len(hdrs) > 0 && cc.werr == nil { | ||
980 | chunk := hdrs | ||
981 | if len(chunk) > frameSize { | ||
982 | chunk = chunk[:frameSize] | ||
983 | } | ||
984 | hdrs = hdrs[len(chunk):] | ||
985 | endHeaders := len(hdrs) == 0 | ||
986 | if first { | ||
987 | cc.fr.WriteHeaders(HeadersFrameParam{ | ||
988 | StreamID: streamID, | ||
989 | BlockFragment: chunk, | ||
990 | EndStream: endStream, | ||
991 | EndHeaders: endHeaders, | ||
992 | }) | ||
993 | first = false | ||
994 | } else { | ||
995 | cc.fr.WriteContinuation(streamID, endHeaders, chunk) | ||
996 | } | ||
997 | } | ||
998 | // TODO(bradfitz): this Flush could potentially block (as | ||
999 | // could the WriteHeaders call(s) above), which means they | ||
1000 | // wouldn't respond to Request.Cancel being readable. That's | ||
1001 | // rare, but this should probably be in a goroutine. | ||
1002 | cc.bw.Flush() | ||
1003 | return cc.werr | ||
1004 | } | ||
1005 | |||
1006 | // internal error values; they don't escape to callers | ||
1007 | var ( | ||
1008 | // abort request body write; don't send cancel | ||
1009 | errStopReqBodyWrite = errors.New("http2: aborting request body write") | ||
1010 | |||
1011 | // abort request body write, but send stream reset of cancel. | ||
1012 | errStopReqBodyWriteAndCancel = errors.New("http2: canceling request") | ||
1013 | ) | ||
1014 | |||
1015 | func (cs *clientStream) writeRequestBody(body io.Reader, bodyCloser io.Closer) (err error) { | ||
1016 | cc := cs.cc | ||
1017 | sentEnd := false // whether we sent the final DATA frame w/ END_STREAM | ||
1018 | buf := cc.frameScratchBuffer() | ||
1019 | defer cc.putFrameScratchBuffer(buf) | ||
1020 | |||
1021 | defer func() { | ||
1022 | traceWroteRequest(cs.trace, err) | ||
1023 | // TODO: write h12Compare test showing whether | ||
1024 | // Request.Body is closed by the Transport, | ||
1025 | // and in multiple cases: server replies <=299 and >299 | ||
1026 | // while still writing request body | ||
1027 | cerr := bodyCloser.Close() | ||
1028 | if err == nil { | ||
1029 | err = cerr | ||
1030 | } | ||
1031 | }() | ||
1032 | |||
1033 | req := cs.req | ||
1034 | hasTrailers := req.Trailer != nil | ||
1035 | |||
1036 | var sawEOF bool | ||
1037 | for !sawEOF { | ||
1038 | n, err := body.Read(buf) | ||
1039 | if err == io.EOF { | ||
1040 | sawEOF = true | ||
1041 | err = nil | ||
1042 | } else if err != nil { | ||
1043 | return err | ||
1044 | } | ||
1045 | |||
1046 | remain := buf[:n] | ||
1047 | for len(remain) > 0 && err == nil { | ||
1048 | var allowed int32 | ||
1049 | allowed, err = cs.awaitFlowControl(len(remain)) | ||
1050 | switch { | ||
1051 | case err == errStopReqBodyWrite: | ||
1052 | return err | ||
1053 | case err == errStopReqBodyWriteAndCancel: | ||
1054 | cc.writeStreamReset(cs.ID, ErrCodeCancel, nil) | ||
1055 | return err | ||
1056 | case err != nil: | ||
1057 | return err | ||
1058 | } | ||
1059 | cc.wmu.Lock() | ||
1060 | data := remain[:allowed] | ||
1061 | remain = remain[allowed:] | ||
1062 | sentEnd = sawEOF && len(remain) == 0 && !hasTrailers | ||
1063 | err = cc.fr.WriteData(cs.ID, sentEnd, data) | ||
1064 | if err == nil { | ||
1065 | // TODO(bradfitz): this flush is for latency, not bandwidth. | ||
1066 | // Most requests won't need this. Make this opt-in or | ||
1067 | // opt-out? Use some heuristic on the body type? Nagel-like | ||
1068 | // timers? Based on 'n'? Only last chunk of this for loop, | ||
1069 | // unless flow control tokens are low? For now, always. | ||
1070 | // If we change this, see comment below. | ||
1071 | err = cc.bw.Flush() | ||
1072 | } | ||
1073 | cc.wmu.Unlock() | ||
1074 | } | ||
1075 | if err != nil { | ||
1076 | return err | ||
1077 | } | ||
1078 | } | ||
1079 | |||
1080 | if sentEnd { | ||
1081 | // Already sent END_STREAM (which implies we have no | ||
1082 | // trailers) and flushed, because currently all | ||
1083 | // WriteData frames above get a flush. So we're done. | ||
1084 | return nil | ||
1085 | } | ||
1086 | |||
1087 | var trls []byte | ||
1088 | if hasTrailers { | ||
1089 | cc.mu.Lock() | ||
1090 | trls, err = cc.encodeTrailers(req) | ||
1091 | cc.mu.Unlock() | ||
1092 | if err != nil { | ||
1093 | cc.writeStreamReset(cs.ID, ErrCodeInternal, err) | ||
1094 | cc.forgetStreamID(cs.ID) | ||
1095 | return err | ||
1096 | } | ||
1097 | } | ||
1098 | |||
1099 | cc.wmu.Lock() | ||
1100 | defer cc.wmu.Unlock() | ||
1101 | |||
1102 | // Two ways to send END_STREAM: either with trailers, or | ||
1103 | // with an empty DATA frame. | ||
1104 | if len(trls) > 0 { | ||
1105 | err = cc.writeHeaders(cs.ID, true, trls) | ||
1106 | } else { | ||
1107 | err = cc.fr.WriteData(cs.ID, true, nil) | ||
1108 | } | ||
1109 | if ferr := cc.bw.Flush(); ferr != nil && err == nil { | ||
1110 | err = ferr | ||
1111 | } | ||
1112 | return err | ||
1113 | } | ||
1114 | |||
1115 | // awaitFlowControl waits for [1, min(maxBytes, cc.cs.maxFrameSize)] flow | ||
1116 | // control tokens from the server. | ||
1117 | // It returns either the non-zero number of tokens taken or an error | ||
1118 | // if the stream is dead. | ||
1119 | func (cs *clientStream) awaitFlowControl(maxBytes int) (taken int32, err error) { | ||
1120 | cc := cs.cc | ||
1121 | cc.mu.Lock() | ||
1122 | defer cc.mu.Unlock() | ||
1123 | for { | ||
1124 | if cc.closed { | ||
1125 | return 0, errClientConnClosed | ||
1126 | } | ||
1127 | if cs.stopReqBody != nil { | ||
1128 | return 0, cs.stopReqBody | ||
1129 | } | ||
1130 | if err := cs.checkResetOrDone(); err != nil { | ||
1131 | return 0, err | ||
1132 | } | ||
1133 | if a := cs.flow.available(); a > 0 { | ||
1134 | take := a | ||
1135 | if int(take) > maxBytes { | ||
1136 | |||
1137 | take = int32(maxBytes) // can't truncate int; take is int32 | ||
1138 | } | ||
1139 | if take > int32(cc.maxFrameSize) { | ||
1140 | take = int32(cc.maxFrameSize) | ||
1141 | } | ||
1142 | cs.flow.take(take) | ||
1143 | return take, nil | ||
1144 | } | ||
1145 | cc.cond.Wait() | ||
1146 | } | ||
1147 | } | ||
1148 | |||
1149 | type badStringError struct { | ||
1150 | what string | ||
1151 | str string | ||
1152 | } | ||
1153 | |||
1154 | func (e *badStringError) Error() string { return fmt.Sprintf("%s %q", e.what, e.str) } | ||
1155 | |||
1156 | // requires cc.mu be held. | ||
1157 | func (cc *ClientConn) encodeHeaders(req *http.Request, addGzipHeader bool, trailers string, contentLength int64) ([]byte, error) { | ||
1158 | cc.hbuf.Reset() | ||
1159 | |||
1160 | host := req.Host | ||
1161 | if host == "" { | ||
1162 | host = req.URL.Host | ||
1163 | } | ||
1164 | host, err := httplex.PunycodeHostPort(host) | ||
1165 | if err != nil { | ||
1166 | return nil, err | ||
1167 | } | ||
1168 | |||
1169 | var path string | ||
1170 | if req.Method != "CONNECT" { | ||
1171 | path = req.URL.RequestURI() | ||
1172 | if !validPseudoPath(path) { | ||
1173 | orig := path | ||
1174 | path = strings.TrimPrefix(path, req.URL.Scheme+"://"+host) | ||
1175 | if !validPseudoPath(path) { | ||
1176 | if req.URL.Opaque != "" { | ||
1177 | return nil, fmt.Errorf("invalid request :path %q from URL.Opaque = %q", orig, req.URL.Opaque) | ||
1178 | } else { | ||
1179 | return nil, fmt.Errorf("invalid request :path %q", orig) | ||
1180 | } | ||
1181 | } | ||
1182 | } | ||
1183 | } | ||
1184 | |||
1185 | // Check for any invalid headers and return an error before we | ||
1186 | // potentially pollute our hpack state. (We want to be able to | ||
1187 | // continue to reuse the hpack encoder for future requests) | ||
1188 | for k, vv := range req.Header { | ||
1189 | if !httplex.ValidHeaderFieldName(k) { | ||
1190 | return nil, fmt.Errorf("invalid HTTP header name %q", k) | ||
1191 | } | ||
1192 | for _, v := range vv { | ||
1193 | if !httplex.ValidHeaderFieldValue(v) { | ||
1194 | return nil, fmt.Errorf("invalid HTTP header value %q for header %q", v, k) | ||
1195 | } | ||
1196 | } | ||
1197 | } | ||
1198 | |||
1199 | enumerateHeaders := func(f func(name, value string)) { | ||
1200 | // 8.1.2.3 Request Pseudo-Header Fields | ||
1201 | // The :path pseudo-header field includes the path and query parts of the | ||
1202 | // target URI (the path-absolute production and optionally a '?' character | ||
1203 | // followed by the query production (see Sections 3.3 and 3.4 of | ||
1204 | // [RFC3986]). | ||
1205 | f(":authority", host) | ||
1206 | f(":method", req.Method) | ||
1207 | if req.Method != "CONNECT" { | ||
1208 | f(":path", path) | ||
1209 | f(":scheme", req.URL.Scheme) | ||
1210 | } | ||
1211 | if trailers != "" { | ||
1212 | f("trailer", trailers) | ||
1213 | } | ||
1214 | |||
1215 | var didUA bool | ||
1216 | for k, vv := range req.Header { | ||
1217 | if strings.EqualFold(k, "host") || strings.EqualFold(k, "content-length") { | ||
1218 | // Host is :authority, already sent. | ||
1219 | // Content-Length is automatic, set below. | ||
1220 | continue | ||
1221 | } else if strings.EqualFold(k, "connection") || strings.EqualFold(k, "proxy-connection") || | ||
1222 | strings.EqualFold(k, "transfer-encoding") || strings.EqualFold(k, "upgrade") || | ||
1223 | strings.EqualFold(k, "keep-alive") { | ||
1224 | // Per 8.1.2.2 Connection-Specific Header | ||
1225 | // Fields, don't send connection-specific | ||
1226 | // fields. We have already checked if any | ||
1227 | // are error-worthy so just ignore the rest. | ||
1228 | continue | ||
1229 | } else if strings.EqualFold(k, "user-agent") { | ||
1230 | // Match Go's http1 behavior: at most one | ||
1231 | // User-Agent. If set to nil or empty string, | ||
1232 | // then omit it. Otherwise if not mentioned, | ||
1233 | // include the default (below). | ||
1234 | didUA = true | ||
1235 | if len(vv) < 1 { | ||
1236 | continue | ||
1237 | } | ||
1238 | vv = vv[:1] | ||
1239 | if vv[0] == "" { | ||
1240 | continue | ||
1241 | } | ||
1242 | |||
1243 | } | ||
1244 | |||
1245 | for _, v := range vv { | ||
1246 | f(k, v) | ||
1247 | } | ||
1248 | } | ||
1249 | if shouldSendReqContentLength(req.Method, contentLength) { | ||
1250 | f("content-length", strconv.FormatInt(contentLength, 10)) | ||
1251 | } | ||
1252 | if addGzipHeader { | ||
1253 | f("accept-encoding", "gzip") | ||
1254 | } | ||
1255 | if !didUA { | ||
1256 | f("user-agent", defaultUserAgent) | ||
1257 | } | ||
1258 | } | ||
1259 | |||
1260 | // Do a first pass over the headers counting bytes to ensure | ||
1261 | // we don't exceed cc.peerMaxHeaderListSize. This is done as a | ||
1262 | // separate pass before encoding the headers to prevent | ||
1263 | // modifying the hpack state. | ||
1264 | hlSize := uint64(0) | ||
1265 | enumerateHeaders(func(name, value string) { | ||
1266 | hf := hpack.HeaderField{Name: name, Value: value} | ||
1267 | hlSize += uint64(hf.Size()) | ||
1268 | }) | ||
1269 | |||
1270 | if hlSize > cc.peerMaxHeaderListSize { | ||
1271 | return nil, errRequestHeaderListSize | ||
1272 | } | ||
1273 | |||
1274 | // Header list size is ok. Write the headers. | ||
1275 | enumerateHeaders(func(name, value string) { | ||
1276 | cc.writeHeader(strings.ToLower(name), value) | ||
1277 | }) | ||
1278 | |||
1279 | return cc.hbuf.Bytes(), nil | ||
1280 | } | ||
1281 | |||
1282 | // shouldSendReqContentLength reports whether the http2.Transport should send | ||
1283 | // a "content-length" request header. This logic is basically a copy of the net/http | ||
1284 | // transferWriter.shouldSendContentLength. | ||
1285 | // The contentLength is the corrected contentLength (so 0 means actually 0, not unknown). | ||
1286 | // -1 means unknown. | ||
1287 | func shouldSendReqContentLength(method string, contentLength int64) bool { | ||
1288 | if contentLength > 0 { | ||
1289 | return true | ||
1290 | } | ||
1291 | if contentLength < 0 { | ||
1292 | return false | ||
1293 | } | ||
1294 | // For zero bodies, whether we send a content-length depends on the method. | ||
1295 | // It also kinda doesn't matter for http2 either way, with END_STREAM. | ||
1296 | switch method { | ||
1297 | case "POST", "PUT", "PATCH": | ||
1298 | return true | ||
1299 | default: | ||
1300 | return false | ||
1301 | } | ||
1302 | } | ||
1303 | |||
1304 | // requires cc.mu be held. | ||
1305 | func (cc *ClientConn) encodeTrailers(req *http.Request) ([]byte, error) { | ||
1306 | cc.hbuf.Reset() | ||
1307 | |||
1308 | hlSize := uint64(0) | ||
1309 | for k, vv := range req.Trailer { | ||
1310 | for _, v := range vv { | ||
1311 | hf := hpack.HeaderField{Name: k, Value: v} | ||
1312 | hlSize += uint64(hf.Size()) | ||
1313 | } | ||
1314 | } | ||
1315 | if hlSize > cc.peerMaxHeaderListSize { | ||
1316 | return nil, errRequestHeaderListSize | ||
1317 | } | ||
1318 | |||
1319 | for k, vv := range req.Trailer { | ||
1320 | // Transfer-Encoding, etc.. have already been filtered at the | ||
1321 | // start of RoundTrip | ||
1322 | lowKey := strings.ToLower(k) | ||
1323 | for _, v := range vv { | ||
1324 | cc.writeHeader(lowKey, v) | ||
1325 | } | ||
1326 | } | ||
1327 | return cc.hbuf.Bytes(), nil | ||
1328 | } | ||
1329 | |||
1330 | func (cc *ClientConn) writeHeader(name, value string) { | ||
1331 | if VerboseLogs { | ||
1332 | log.Printf("http2: Transport encoding header %q = %q", name, value) | ||
1333 | } | ||
1334 | cc.henc.WriteField(hpack.HeaderField{Name: name, Value: value}) | ||
1335 | } | ||
1336 | |||
1337 | type resAndError struct { | ||
1338 | res *http.Response | ||
1339 | err error | ||
1340 | } | ||
1341 | |||
1342 | // requires cc.mu be held. | ||
1343 | func (cc *ClientConn) newStream() *clientStream { | ||
1344 | cs := &clientStream{ | ||
1345 | cc: cc, | ||
1346 | ID: cc.nextStreamID, | ||
1347 | resc: make(chan resAndError, 1), | ||
1348 | peerReset: make(chan struct{}), | ||
1349 | done: make(chan struct{}), | ||
1350 | } | ||
1351 | cs.flow.add(int32(cc.initialWindowSize)) | ||
1352 | cs.flow.setConnFlow(&cc.flow) | ||
1353 | cs.inflow.add(transportDefaultStreamFlow) | ||
1354 | cs.inflow.setConnFlow(&cc.inflow) | ||
1355 | cc.nextStreamID += 2 | ||
1356 | cc.streams[cs.ID] = cs | ||
1357 | return cs | ||
1358 | } | ||
1359 | |||
1360 | func (cc *ClientConn) forgetStreamID(id uint32) { | ||
1361 | cc.streamByID(id, true) | ||
1362 | } | ||
1363 | |||
1364 | func (cc *ClientConn) streamByID(id uint32, andRemove bool) *clientStream { | ||
1365 | cc.mu.Lock() | ||
1366 | defer cc.mu.Unlock() | ||
1367 | cs := cc.streams[id] | ||
1368 | if andRemove && cs != nil && !cc.closed { | ||
1369 | cc.lastActive = time.Now() | ||
1370 | delete(cc.streams, id) | ||
1371 | if len(cc.streams) == 0 && cc.idleTimer != nil { | ||
1372 | cc.idleTimer.Reset(cc.idleTimeout) | ||
1373 | } | ||
1374 | close(cs.done) | ||
1375 | // Wake up checkResetOrDone via clientStream.awaitFlowControl and | ||
1376 | // wake up RoundTrip if there is a pending request. | ||
1377 | cc.cond.Broadcast() | ||
1378 | } | ||
1379 | return cs | ||
1380 | } | ||
1381 | |||
1382 | // clientConnReadLoop is the state owned by the clientConn's frame-reading readLoop. | ||
1383 | type clientConnReadLoop struct { | ||
1384 | cc *ClientConn | ||
1385 | activeRes map[uint32]*clientStream // keyed by streamID | ||
1386 | closeWhenIdle bool | ||
1387 | } | ||
1388 | |||
1389 | // readLoop runs in its own goroutine and reads and dispatches frames. | ||
1390 | func (cc *ClientConn) readLoop() { | ||
1391 | rl := &clientConnReadLoop{ | ||
1392 | cc: cc, | ||
1393 | activeRes: make(map[uint32]*clientStream), | ||
1394 | } | ||
1395 | |||
1396 | defer rl.cleanup() | ||
1397 | cc.readerErr = rl.run() | ||
1398 | if ce, ok := cc.readerErr.(ConnectionError); ok { | ||
1399 | cc.wmu.Lock() | ||
1400 | cc.fr.WriteGoAway(0, ErrCode(ce), nil) | ||
1401 | cc.wmu.Unlock() | ||
1402 | } | ||
1403 | } | ||
1404 | |||
1405 | // GoAwayError is returned by the Transport when the server closes the | ||
1406 | // TCP connection after sending a GOAWAY frame. | ||
1407 | type GoAwayError struct { | ||
1408 | LastStreamID uint32 | ||
1409 | ErrCode ErrCode | ||
1410 | DebugData string | ||
1411 | } | ||
1412 | |||
1413 | func (e GoAwayError) Error() string { | ||
1414 | return fmt.Sprintf("http2: server sent GOAWAY and closed the connection; LastStreamID=%v, ErrCode=%v, debug=%q", | ||
1415 | e.LastStreamID, e.ErrCode, e.DebugData) | ||
1416 | } | ||
1417 | |||
1418 | func isEOFOrNetReadError(err error) bool { | ||
1419 | if err == io.EOF { | ||
1420 | return true | ||
1421 | } | ||
1422 | ne, ok := err.(*net.OpError) | ||
1423 | return ok && ne.Op == "read" | ||
1424 | } | ||
1425 | |||
1426 | func (rl *clientConnReadLoop) cleanup() { | ||
1427 | cc := rl.cc | ||
1428 | defer cc.tconn.Close() | ||
1429 | defer cc.t.connPool().MarkDead(cc) | ||
1430 | defer close(cc.readerDone) | ||
1431 | |||
1432 | if cc.idleTimer != nil { | ||
1433 | cc.idleTimer.Stop() | ||
1434 | } | ||
1435 | |||
1436 | // Close any response bodies if the server closes prematurely. | ||
1437 | // TODO: also do this if we've written the headers but not | ||
1438 | // gotten a response yet. | ||
1439 | err := cc.readerErr | ||
1440 | cc.mu.Lock() | ||
1441 | if cc.goAway != nil && isEOFOrNetReadError(err) { | ||
1442 | err = GoAwayError{ | ||
1443 | LastStreamID: cc.goAway.LastStreamID, | ||
1444 | ErrCode: cc.goAway.ErrCode, | ||
1445 | DebugData: cc.goAwayDebug, | ||
1446 | } | ||
1447 | } else if err == io.EOF { | ||
1448 | err = io.ErrUnexpectedEOF | ||
1449 | } | ||
1450 | for _, cs := range rl.activeRes { | ||
1451 | cs.bufPipe.CloseWithError(err) | ||
1452 | } | ||
1453 | for _, cs := range cc.streams { | ||
1454 | select { | ||
1455 | case cs.resc <- resAndError{err: err}: | ||
1456 | default: | ||
1457 | } | ||
1458 | close(cs.done) | ||
1459 | } | ||
1460 | cc.closed = true | ||
1461 | cc.cond.Broadcast() | ||
1462 | cc.mu.Unlock() | ||
1463 | } | ||
1464 | |||
1465 | func (rl *clientConnReadLoop) run() error { | ||
1466 | cc := rl.cc | ||
1467 | rl.closeWhenIdle = cc.t.disableKeepAlives() || cc.singleUse | ||
1468 | gotReply := false // ever saw a HEADERS reply | ||
1469 | gotSettings := false | ||
1470 | for { | ||
1471 | f, err := cc.fr.ReadFrame() | ||
1472 | if err != nil { | ||
1473 | cc.vlogf("http2: Transport readFrame error on conn %p: (%T) %v", cc, err, err) | ||
1474 | } | ||
1475 | if se, ok := err.(StreamError); ok { | ||
1476 | if cs := cc.streamByID(se.StreamID, false); cs != nil { | ||
1477 | cs.cc.writeStreamReset(cs.ID, se.Code, err) | ||
1478 | cs.cc.forgetStreamID(cs.ID) | ||
1479 | if se.Cause == nil { | ||
1480 | se.Cause = cc.fr.errDetail | ||
1481 | } | ||
1482 | rl.endStreamError(cs, se) | ||
1483 | } | ||
1484 | continue | ||
1485 | } else if err != nil { | ||
1486 | return err | ||
1487 | } | ||
1488 | if VerboseLogs { | ||
1489 | cc.vlogf("http2: Transport received %s", summarizeFrame(f)) | ||
1490 | } | ||
1491 | if !gotSettings { | ||
1492 | if _, ok := f.(*SettingsFrame); !ok { | ||
1493 | cc.logf("protocol error: received %T before a SETTINGS frame", f) | ||
1494 | return ConnectionError(ErrCodeProtocol) | ||
1495 | } | ||
1496 | gotSettings = true | ||
1497 | } | ||
1498 | maybeIdle := false // whether frame might transition us to idle | ||
1499 | |||
1500 | switch f := f.(type) { | ||
1501 | case *MetaHeadersFrame: | ||
1502 | err = rl.processHeaders(f) | ||
1503 | maybeIdle = true | ||
1504 | gotReply = true | ||
1505 | case *DataFrame: | ||
1506 | err = rl.processData(f) | ||
1507 | maybeIdle = true | ||
1508 | case *GoAwayFrame: | ||
1509 | err = rl.processGoAway(f) | ||
1510 | maybeIdle = true | ||
1511 | case *RSTStreamFrame: | ||
1512 | err = rl.processResetStream(f) | ||
1513 | maybeIdle = true | ||
1514 | case *SettingsFrame: | ||
1515 | err = rl.processSettings(f) | ||
1516 | case *PushPromiseFrame: | ||
1517 | err = rl.processPushPromise(f) | ||
1518 | case *WindowUpdateFrame: | ||
1519 | err = rl.processWindowUpdate(f) | ||
1520 | case *PingFrame: | ||
1521 | err = rl.processPing(f) | ||
1522 | default: | ||
1523 | cc.logf("Transport: unhandled response frame type %T", f) | ||
1524 | } | ||
1525 | if err != nil { | ||
1526 | if VerboseLogs { | ||
1527 | cc.vlogf("http2: Transport conn %p received error from processing frame %v: %v", cc, summarizeFrame(f), err) | ||
1528 | } | ||
1529 | return err | ||
1530 | } | ||
1531 | if rl.closeWhenIdle && gotReply && maybeIdle && len(rl.activeRes) == 0 { | ||
1532 | cc.closeIfIdle() | ||
1533 | } | ||
1534 | } | ||
1535 | } | ||
1536 | |||
1537 | func (rl *clientConnReadLoop) processHeaders(f *MetaHeadersFrame) error { | ||
1538 | cc := rl.cc | ||
1539 | cs := cc.streamByID(f.StreamID, f.StreamEnded()) | ||
1540 | if cs == nil { | ||
1541 | // We'd get here if we canceled a request while the | ||
1542 | // server had its response still in flight. So if this | ||
1543 | // was just something we canceled, ignore it. | ||
1544 | return nil | ||
1545 | } | ||
1546 | if !cs.firstByte { | ||
1547 | if cs.trace != nil { | ||
1548 | // TODO(bradfitz): move first response byte earlier, | ||
1549 | // when we first read the 9 byte header, not waiting | ||
1550 | // until all the HEADERS+CONTINUATION frames have been | ||
1551 | // merged. This works for now. | ||
1552 | traceFirstResponseByte(cs.trace) | ||
1553 | } | ||
1554 | cs.firstByte = true | ||
1555 | } | ||
1556 | if !cs.pastHeaders { | ||
1557 | cs.pastHeaders = true | ||
1558 | } else { | ||
1559 | return rl.processTrailers(cs, f) | ||
1560 | } | ||
1561 | |||
1562 | res, err := rl.handleResponse(cs, f) | ||
1563 | if err != nil { | ||
1564 | if _, ok := err.(ConnectionError); ok { | ||
1565 | return err | ||
1566 | } | ||
1567 | // Any other error type is a stream error. | ||
1568 | cs.cc.writeStreamReset(f.StreamID, ErrCodeProtocol, err) | ||
1569 | cs.resc <- resAndError{err: err} | ||
1570 | return nil // return nil from process* funcs to keep conn alive | ||
1571 | } | ||
1572 | if res == nil { | ||
1573 | // (nil, nil) special case. See handleResponse docs. | ||
1574 | return nil | ||
1575 | } | ||
1576 | if res.Body != noBody { | ||
1577 | rl.activeRes[cs.ID] = cs | ||
1578 | } | ||
1579 | cs.resTrailer = &res.Trailer | ||
1580 | cs.resc <- resAndError{res: res} | ||
1581 | return nil | ||
1582 | } | ||
1583 | |||
1584 | // may return error types nil, or ConnectionError. Any other error value | ||
1585 | // is a StreamError of type ErrCodeProtocol. The returned error in that case | ||
1586 | // is the detail. | ||
1587 | // | ||
1588 | // As a special case, handleResponse may return (nil, nil) to skip the | ||
1589 | // frame (currently only used for 100 expect continue). This special | ||
1590 | // case is going away after Issue 13851 is fixed. | ||
1591 | func (rl *clientConnReadLoop) handleResponse(cs *clientStream, f *MetaHeadersFrame) (*http.Response, error) { | ||
1592 | if f.Truncated { | ||
1593 | return nil, errResponseHeaderListSize | ||
1594 | } | ||
1595 | |||
1596 | status := f.PseudoValue("status") | ||
1597 | if status == "" { | ||
1598 | return nil, errors.New("missing status pseudo header") | ||
1599 | } | ||
1600 | statusCode, err := strconv.Atoi(status) | ||
1601 | if err != nil { | ||
1602 | return nil, errors.New("malformed non-numeric status pseudo header") | ||
1603 | } | ||
1604 | |||
1605 | if statusCode == 100 { | ||
1606 | traceGot100Continue(cs.trace) | ||
1607 | if cs.on100 != nil { | ||
1608 | cs.on100() // forces any write delay timer to fire | ||
1609 | } | ||
1610 | cs.pastHeaders = false // do it all again | ||
1611 | return nil, nil | ||
1612 | } | ||
1613 | |||
1614 | header := make(http.Header) | ||
1615 | res := &http.Response{ | ||
1616 | Proto: "HTTP/2.0", | ||
1617 | ProtoMajor: 2, | ||
1618 | Header: header, | ||
1619 | StatusCode: statusCode, | ||
1620 | Status: status + " " + http.StatusText(statusCode), | ||
1621 | } | ||
1622 | for _, hf := range f.RegularFields() { | ||
1623 | key := http.CanonicalHeaderKey(hf.Name) | ||
1624 | if key == "Trailer" { | ||
1625 | t := res.Trailer | ||
1626 | if t == nil { | ||
1627 | t = make(http.Header) | ||
1628 | res.Trailer = t | ||
1629 | } | ||
1630 | foreachHeaderElement(hf.Value, func(v string) { | ||
1631 | t[http.CanonicalHeaderKey(v)] = nil | ||
1632 | }) | ||
1633 | } else { | ||
1634 | header[key] = append(header[key], hf.Value) | ||
1635 | } | ||
1636 | } | ||
1637 | |||
1638 | streamEnded := f.StreamEnded() | ||
1639 | isHead := cs.req.Method == "HEAD" | ||
1640 | if !streamEnded || isHead { | ||
1641 | res.ContentLength = -1 | ||
1642 | if clens := res.Header["Content-Length"]; len(clens) == 1 { | ||
1643 | if clen64, err := strconv.ParseInt(clens[0], 10, 64); err == nil { | ||
1644 | res.ContentLength = clen64 | ||
1645 | } else { | ||
1646 | // TODO: care? unlike http/1, it won't mess up our framing, so it's | ||
1647 | // more safe smuggling-wise to ignore. | ||
1648 | } | ||
1649 | } else if len(clens) > 1 { | ||
1650 | // TODO: care? unlike http/1, it won't mess up our framing, so it's | ||
1651 | // more safe smuggling-wise to ignore. | ||
1652 | } | ||
1653 | } | ||
1654 | |||
1655 | if streamEnded || isHead { | ||
1656 | res.Body = noBody | ||
1657 | return res, nil | ||
1658 | } | ||
1659 | |||
1660 | cs.bufPipe = pipe{b: &dataBuffer{expected: res.ContentLength}} | ||
1661 | cs.bytesRemain = res.ContentLength | ||
1662 | res.Body = transportResponseBody{cs} | ||
1663 | go cs.awaitRequestCancel(cs.req) | ||
1664 | |||
1665 | if cs.requestedGzip && res.Header.Get("Content-Encoding") == "gzip" { | ||
1666 | res.Header.Del("Content-Encoding") | ||
1667 | res.Header.Del("Content-Length") | ||
1668 | res.ContentLength = -1 | ||
1669 | res.Body = &gzipReader{body: res.Body} | ||
1670 | setResponseUncompressed(res) | ||
1671 | } | ||
1672 | return res, nil | ||
1673 | } | ||
1674 | |||
1675 | func (rl *clientConnReadLoop) processTrailers(cs *clientStream, f *MetaHeadersFrame) error { | ||
1676 | if cs.pastTrailers { | ||
1677 | // Too many HEADERS frames for this stream. | ||
1678 | return ConnectionError(ErrCodeProtocol) | ||
1679 | } | ||
1680 | cs.pastTrailers = true | ||
1681 | if !f.StreamEnded() { | ||
1682 | // We expect that any headers for trailers also | ||
1683 | // has END_STREAM. | ||
1684 | return ConnectionError(ErrCodeProtocol) | ||
1685 | } | ||
1686 | if len(f.PseudoFields()) > 0 { | ||
1687 | // No pseudo header fields are defined for trailers. | ||
1688 | // TODO: ConnectionError might be overly harsh? Check. | ||
1689 | return ConnectionError(ErrCodeProtocol) | ||
1690 | } | ||
1691 | |||
1692 | trailer := make(http.Header) | ||
1693 | for _, hf := range f.RegularFields() { | ||
1694 | key := http.CanonicalHeaderKey(hf.Name) | ||
1695 | trailer[key] = append(trailer[key], hf.Value) | ||
1696 | } | ||
1697 | cs.trailer = trailer | ||
1698 | |||
1699 | rl.endStream(cs) | ||
1700 | return nil | ||
1701 | } | ||
1702 | |||
1703 | // transportResponseBody is the concrete type of Transport.RoundTrip's | ||
1704 | // Response.Body. It is an io.ReadCloser. On Read, it reads from cs.body. | ||
1705 | // On Close it sends RST_STREAM if EOF wasn't already seen. | ||
1706 | type transportResponseBody struct { | ||
1707 | cs *clientStream | ||
1708 | } | ||
1709 | |||
1710 | func (b transportResponseBody) Read(p []byte) (n int, err error) { | ||
1711 | cs := b.cs | ||
1712 | cc := cs.cc | ||
1713 | |||
1714 | if cs.readErr != nil { | ||
1715 | return 0, cs.readErr | ||
1716 | } | ||
1717 | n, err = b.cs.bufPipe.Read(p) | ||
1718 | if cs.bytesRemain != -1 { | ||
1719 | if int64(n) > cs.bytesRemain { | ||
1720 | n = int(cs.bytesRemain) | ||
1721 | if err == nil { | ||
1722 | err = errors.New("net/http: server replied with more than declared Content-Length; truncated") | ||
1723 | cc.writeStreamReset(cs.ID, ErrCodeProtocol, err) | ||
1724 | } | ||
1725 | cs.readErr = err | ||
1726 | return int(cs.bytesRemain), err | ||
1727 | } | ||
1728 | cs.bytesRemain -= int64(n) | ||
1729 | if err == io.EOF && cs.bytesRemain > 0 { | ||
1730 | err = io.ErrUnexpectedEOF | ||
1731 | cs.readErr = err | ||
1732 | return n, err | ||
1733 | } | ||
1734 | } | ||
1735 | if n == 0 { | ||
1736 | // No flow control tokens to send back. | ||
1737 | return | ||
1738 | } | ||
1739 | |||
1740 | cc.mu.Lock() | ||
1741 | defer cc.mu.Unlock() | ||
1742 | |||
1743 | var connAdd, streamAdd int32 | ||
1744 | // Check the conn-level first, before the stream-level. | ||
1745 | if v := cc.inflow.available(); v < transportDefaultConnFlow/2 { | ||
1746 | connAdd = transportDefaultConnFlow - v | ||
1747 | cc.inflow.add(connAdd) | ||
1748 | } | ||
1749 | if err == nil { // No need to refresh if the stream is over or failed. | ||
1750 | // Consider any buffered body data (read from the conn but not | ||
1751 | // consumed by the client) when computing flow control for this | ||
1752 | // stream. | ||
1753 | v := int(cs.inflow.available()) + cs.bufPipe.Len() | ||
1754 | if v < transportDefaultStreamFlow-transportDefaultStreamMinRefresh { | ||
1755 | streamAdd = int32(transportDefaultStreamFlow - v) | ||
1756 | cs.inflow.add(streamAdd) | ||
1757 | } | ||
1758 | } | ||
1759 | if connAdd != 0 || streamAdd != 0 { | ||
1760 | cc.wmu.Lock() | ||
1761 | defer cc.wmu.Unlock() | ||
1762 | if connAdd != 0 { | ||
1763 | cc.fr.WriteWindowUpdate(0, mustUint31(connAdd)) | ||
1764 | } | ||
1765 | if streamAdd != 0 { | ||
1766 | cc.fr.WriteWindowUpdate(cs.ID, mustUint31(streamAdd)) | ||
1767 | } | ||
1768 | cc.bw.Flush() | ||
1769 | } | ||
1770 | return | ||
1771 | } | ||
1772 | |||
1773 | var errClosedResponseBody = errors.New("http2: response body closed") | ||
1774 | |||
1775 | func (b transportResponseBody) Close() error { | ||
1776 | cs := b.cs | ||
1777 | cc := cs.cc | ||
1778 | |||
1779 | serverSentStreamEnd := cs.bufPipe.Err() == io.EOF | ||
1780 | unread := cs.bufPipe.Len() | ||
1781 | |||
1782 | if unread > 0 || !serverSentStreamEnd { | ||
1783 | cc.mu.Lock() | ||
1784 | cc.wmu.Lock() | ||
1785 | if !serverSentStreamEnd { | ||
1786 | cc.fr.WriteRSTStream(cs.ID, ErrCodeCancel) | ||
1787 | cs.didReset = true | ||
1788 | } | ||
1789 | // Return connection-level flow control. | ||
1790 | if unread > 0 { | ||
1791 | cc.inflow.add(int32(unread)) | ||
1792 | cc.fr.WriteWindowUpdate(0, uint32(unread)) | ||
1793 | } | ||
1794 | cc.bw.Flush() | ||
1795 | cc.wmu.Unlock() | ||
1796 | cc.mu.Unlock() | ||
1797 | } | ||
1798 | |||
1799 | cs.bufPipe.BreakWithError(errClosedResponseBody) | ||
1800 | cc.forgetStreamID(cs.ID) | ||
1801 | return nil | ||
1802 | } | ||
1803 | |||
1804 | func (rl *clientConnReadLoop) processData(f *DataFrame) error { | ||
1805 | cc := rl.cc | ||
1806 | cs := cc.streamByID(f.StreamID, f.StreamEnded()) | ||
1807 | data := f.Data() | ||
1808 | if cs == nil { | ||
1809 | cc.mu.Lock() | ||
1810 | neverSent := cc.nextStreamID | ||
1811 | cc.mu.Unlock() | ||
1812 | if f.StreamID >= neverSent { | ||
1813 | // We never asked for this. | ||
1814 | cc.logf("http2: Transport received unsolicited DATA frame; closing connection") | ||
1815 | return ConnectionError(ErrCodeProtocol) | ||
1816 | } | ||
1817 | // We probably did ask for this, but canceled. Just ignore it. | ||
1818 | // TODO: be stricter here? only silently ignore things which | ||
1819 | // we canceled, but not things which were closed normally | ||
1820 | // by the peer? Tough without accumulating too much state. | ||
1821 | |||
1822 | // But at least return their flow control: | ||
1823 | if f.Length > 0 { | ||
1824 | cc.mu.Lock() | ||
1825 | cc.inflow.add(int32(f.Length)) | ||
1826 | cc.mu.Unlock() | ||
1827 | |||
1828 | cc.wmu.Lock() | ||
1829 | cc.fr.WriteWindowUpdate(0, uint32(f.Length)) | ||
1830 | cc.bw.Flush() | ||
1831 | cc.wmu.Unlock() | ||
1832 | } | ||
1833 | return nil | ||
1834 | } | ||
1835 | if !cs.firstByte { | ||
1836 | cc.logf("protocol error: received DATA before a HEADERS frame") | ||
1837 | rl.endStreamError(cs, StreamError{ | ||
1838 | StreamID: f.StreamID, | ||
1839 | Code: ErrCodeProtocol, | ||
1840 | }) | ||
1841 | return nil | ||
1842 | } | ||
1843 | if f.Length > 0 { | ||
1844 | // Check connection-level flow control. | ||
1845 | cc.mu.Lock() | ||
1846 | if cs.inflow.available() >= int32(f.Length) { | ||
1847 | cs.inflow.take(int32(f.Length)) | ||
1848 | } else { | ||
1849 | cc.mu.Unlock() | ||
1850 | return ConnectionError(ErrCodeFlowControl) | ||
1851 | } | ||
1852 | // Return any padded flow control now, since we won't | ||
1853 | // refund it later on body reads. | ||
1854 | var refund int | ||
1855 | if pad := int(f.Length) - len(data); pad > 0 { | ||
1856 | refund += pad | ||
1857 | } | ||
1858 | // Return len(data) now if the stream is already closed, | ||
1859 | // since data will never be read. | ||
1860 | didReset := cs.didReset | ||
1861 | if didReset { | ||
1862 | refund += len(data) | ||
1863 | } | ||
1864 | if refund > 0 { | ||
1865 | cc.inflow.add(int32(refund)) | ||
1866 | cc.wmu.Lock() | ||
1867 | cc.fr.WriteWindowUpdate(0, uint32(refund)) | ||
1868 | if !didReset { | ||
1869 | cs.inflow.add(int32(refund)) | ||
1870 | cc.fr.WriteWindowUpdate(cs.ID, uint32(refund)) | ||
1871 | } | ||
1872 | cc.bw.Flush() | ||
1873 | cc.wmu.Unlock() | ||
1874 | } | ||
1875 | cc.mu.Unlock() | ||
1876 | |||
1877 | if len(data) > 0 && !didReset { | ||
1878 | if _, err := cs.bufPipe.Write(data); err != nil { | ||
1879 | rl.endStreamError(cs, err) | ||
1880 | return err | ||
1881 | } | ||
1882 | } | ||
1883 | } | ||
1884 | |||
1885 | if f.StreamEnded() { | ||
1886 | rl.endStream(cs) | ||
1887 | } | ||
1888 | return nil | ||
1889 | } | ||
1890 | |||
1891 | var errInvalidTrailers = errors.New("http2: invalid trailers") | ||
1892 | |||
1893 | func (rl *clientConnReadLoop) endStream(cs *clientStream) { | ||
1894 | // TODO: check that any declared content-length matches, like | ||
1895 | // server.go's (*stream).endStream method. | ||
1896 | rl.endStreamError(cs, nil) | ||
1897 | } | ||
1898 | |||
1899 | func (rl *clientConnReadLoop) endStreamError(cs *clientStream, err error) { | ||
1900 | var code func() | ||
1901 | if err == nil { | ||
1902 | err = io.EOF | ||
1903 | code = cs.copyTrailers | ||
1904 | } | ||
1905 | cs.bufPipe.closeWithErrorAndCode(err, code) | ||
1906 | delete(rl.activeRes, cs.ID) | ||
1907 | if isConnectionCloseRequest(cs.req) { | ||
1908 | rl.closeWhenIdle = true | ||
1909 | } | ||
1910 | |||
1911 | select { | ||
1912 | case cs.resc <- resAndError{err: err}: | ||
1913 | default: | ||
1914 | } | ||
1915 | } | ||
1916 | |||
1917 | func (cs *clientStream) copyTrailers() { | ||
1918 | for k, vv := range cs.trailer { | ||
1919 | t := cs.resTrailer | ||
1920 | if *t == nil { | ||
1921 | *t = make(http.Header) | ||
1922 | } | ||
1923 | (*t)[k] = vv | ||
1924 | } | ||
1925 | } | ||
1926 | |||
1927 | func (rl *clientConnReadLoop) processGoAway(f *GoAwayFrame) error { | ||
1928 | cc := rl.cc | ||
1929 | cc.t.connPool().MarkDead(cc) | ||
1930 | if f.ErrCode != 0 { | ||
1931 | // TODO: deal with GOAWAY more. particularly the error code | ||
1932 | cc.vlogf("transport got GOAWAY with error code = %v", f.ErrCode) | ||
1933 | } | ||
1934 | cc.setGoAway(f) | ||
1935 | return nil | ||
1936 | } | ||
1937 | |||
1938 | func (rl *clientConnReadLoop) processSettings(f *SettingsFrame) error { | ||
1939 | cc := rl.cc | ||
1940 | cc.mu.Lock() | ||
1941 | defer cc.mu.Unlock() | ||
1942 | |||
1943 | if f.IsAck() { | ||
1944 | if cc.wantSettingsAck { | ||
1945 | cc.wantSettingsAck = false | ||
1946 | return nil | ||
1947 | } | ||
1948 | return ConnectionError(ErrCodeProtocol) | ||
1949 | } | ||
1950 | |||
1951 | err := f.ForeachSetting(func(s Setting) error { | ||
1952 | switch s.ID { | ||
1953 | case SettingMaxFrameSize: | ||
1954 | cc.maxFrameSize = s.Val | ||
1955 | case SettingMaxConcurrentStreams: | ||
1956 | cc.maxConcurrentStreams = s.Val | ||
1957 | case SettingMaxHeaderListSize: | ||
1958 | cc.peerMaxHeaderListSize = uint64(s.Val) | ||
1959 | case SettingInitialWindowSize: | ||
1960 | // Values above the maximum flow-control | ||
1961 | // window size of 2^31-1 MUST be treated as a | ||
1962 | // connection error (Section 5.4.1) of type | ||
1963 | // FLOW_CONTROL_ERROR. | ||
1964 | if s.Val > math.MaxInt32 { | ||
1965 | return ConnectionError(ErrCodeFlowControl) | ||
1966 | } | ||
1967 | |||
1968 | // Adjust flow control of currently-open | ||
1969 | // frames by the difference of the old initial | ||
1970 | // window size and this one. | ||
1971 | delta := int32(s.Val) - int32(cc.initialWindowSize) | ||
1972 | for _, cs := range cc.streams { | ||
1973 | cs.flow.add(delta) | ||
1974 | } | ||
1975 | cc.cond.Broadcast() | ||
1976 | |||
1977 | cc.initialWindowSize = s.Val | ||
1978 | default: | ||
1979 | // TODO(bradfitz): handle more settings? SETTINGS_HEADER_TABLE_SIZE probably. | ||
1980 | cc.vlogf("Unhandled Setting: %v", s) | ||
1981 | } | ||
1982 | return nil | ||
1983 | }) | ||
1984 | if err != nil { | ||
1985 | return err | ||
1986 | } | ||
1987 | |||
1988 | cc.wmu.Lock() | ||
1989 | defer cc.wmu.Unlock() | ||
1990 | |||
1991 | cc.fr.WriteSettingsAck() | ||
1992 | cc.bw.Flush() | ||
1993 | return cc.werr | ||
1994 | } | ||
1995 | |||
1996 | func (rl *clientConnReadLoop) processWindowUpdate(f *WindowUpdateFrame) error { | ||
1997 | cc := rl.cc | ||
1998 | cs := cc.streamByID(f.StreamID, false) | ||
1999 | if f.StreamID != 0 && cs == nil { | ||
2000 | return nil | ||
2001 | } | ||
2002 | |||
2003 | cc.mu.Lock() | ||
2004 | defer cc.mu.Unlock() | ||
2005 | |||
2006 | fl := &cc.flow | ||
2007 | if cs != nil { | ||
2008 | fl = &cs.flow | ||
2009 | } | ||
2010 | if !fl.add(int32(f.Increment)) { | ||
2011 | return ConnectionError(ErrCodeFlowControl) | ||
2012 | } | ||
2013 | cc.cond.Broadcast() | ||
2014 | return nil | ||
2015 | } | ||
2016 | |||
2017 | func (rl *clientConnReadLoop) processResetStream(f *RSTStreamFrame) error { | ||
2018 | cs := rl.cc.streamByID(f.StreamID, true) | ||
2019 | if cs == nil { | ||
2020 | // TODO: return error if server tries to RST_STEAM an idle stream | ||
2021 | return nil | ||
2022 | } | ||
2023 | select { | ||
2024 | case <-cs.peerReset: | ||
2025 | // Already reset. | ||
2026 | // This is the only goroutine | ||
2027 | // which closes this, so there | ||
2028 | // isn't a race. | ||
2029 | default: | ||
2030 | err := streamError(cs.ID, f.ErrCode) | ||
2031 | cs.resetErr = err | ||
2032 | close(cs.peerReset) | ||
2033 | cs.bufPipe.CloseWithError(err) | ||
2034 | cs.cc.cond.Broadcast() // wake up checkResetOrDone via clientStream.awaitFlowControl | ||
2035 | } | ||
2036 | delete(rl.activeRes, cs.ID) | ||
2037 | return nil | ||
2038 | } | ||
2039 | |||
2040 | // Ping sends a PING frame to the server and waits for the ack. | ||
2041 | // Public implementation is in go17.go and not_go17.go | ||
2042 | func (cc *ClientConn) ping(ctx contextContext) error { | ||
2043 | c := make(chan struct{}) | ||
2044 | // Generate a random payload | ||
2045 | var p [8]byte | ||
2046 | for { | ||
2047 | if _, err := rand.Read(p[:]); err != nil { | ||
2048 | return err | ||
2049 | } | ||
2050 | cc.mu.Lock() | ||
2051 | // check for dup before insert | ||
2052 | if _, found := cc.pings[p]; !found { | ||
2053 | cc.pings[p] = c | ||
2054 | cc.mu.Unlock() | ||
2055 | break | ||
2056 | } | ||
2057 | cc.mu.Unlock() | ||
2058 | } | ||
2059 | cc.wmu.Lock() | ||
2060 | if err := cc.fr.WritePing(false, p); err != nil { | ||
2061 | cc.wmu.Unlock() | ||
2062 | return err | ||
2063 | } | ||
2064 | if err := cc.bw.Flush(); err != nil { | ||
2065 | cc.wmu.Unlock() | ||
2066 | return err | ||
2067 | } | ||
2068 | cc.wmu.Unlock() | ||
2069 | select { | ||
2070 | case <-c: | ||
2071 | return nil | ||
2072 | case <-ctx.Done(): | ||
2073 | return ctx.Err() | ||
2074 | case <-cc.readerDone: | ||
2075 | // connection closed | ||
2076 | return cc.readerErr | ||
2077 | } | ||
2078 | } | ||
2079 | |||
2080 | func (rl *clientConnReadLoop) processPing(f *PingFrame) error { | ||
2081 | if f.IsAck() { | ||
2082 | cc := rl.cc | ||
2083 | cc.mu.Lock() | ||
2084 | defer cc.mu.Unlock() | ||
2085 | // If ack, notify listener if any | ||
2086 | if c, ok := cc.pings[f.Data]; ok { | ||
2087 | close(c) | ||
2088 | delete(cc.pings, f.Data) | ||
2089 | } | ||
2090 | return nil | ||
2091 | } | ||
2092 | cc := rl.cc | ||
2093 | cc.wmu.Lock() | ||
2094 | defer cc.wmu.Unlock() | ||
2095 | if err := cc.fr.WritePing(true, f.Data); err != nil { | ||
2096 | return err | ||
2097 | } | ||
2098 | return cc.bw.Flush() | ||
2099 | } | ||
2100 | |||
2101 | func (rl *clientConnReadLoop) processPushPromise(f *PushPromiseFrame) error { | ||
2102 | // We told the peer we don't want them. | ||
2103 | // Spec says: | ||
2104 | // "PUSH_PROMISE MUST NOT be sent if the SETTINGS_ENABLE_PUSH | ||
2105 | // setting of the peer endpoint is set to 0. An endpoint that | ||
2106 | // has set this setting and has received acknowledgement MUST | ||
2107 | // treat the receipt of a PUSH_PROMISE frame as a connection | ||
2108 | // error (Section 5.4.1) of type PROTOCOL_ERROR." | ||
2109 | return ConnectionError(ErrCodeProtocol) | ||
2110 | } | ||
2111 | |||
2112 | func (cc *ClientConn) writeStreamReset(streamID uint32, code ErrCode, err error) { | ||
2113 | // TODO: map err to more interesting error codes, once the | ||
2114 | // HTTP community comes up with some. But currently for | ||
2115 | // RST_STREAM there's no equivalent to GOAWAY frame's debug | ||
2116 | // data, and the error codes are all pretty vague ("cancel"). | ||
2117 | cc.wmu.Lock() | ||
2118 | cc.fr.WriteRSTStream(streamID, code) | ||
2119 | cc.bw.Flush() | ||
2120 | cc.wmu.Unlock() | ||
2121 | } | ||
2122 | |||
2123 | var ( | ||
2124 | errResponseHeaderListSize = errors.New("http2: response header list larger than advertised limit") | ||
2125 | errRequestHeaderListSize = errors.New("http2: request header list larger than peer's advertised limit") | ||
2126 | errPseudoTrailers = errors.New("http2: invalid pseudo header in trailers") | ||
2127 | ) | ||
2128 | |||
2129 | func (cc *ClientConn) logf(format string, args ...interface{}) { | ||
2130 | cc.t.logf(format, args...) | ||
2131 | } | ||
2132 | |||
2133 | func (cc *ClientConn) vlogf(format string, args ...interface{}) { | ||
2134 | cc.t.vlogf(format, args...) | ||
2135 | } | ||
2136 | |||
2137 | func (t *Transport) vlogf(format string, args ...interface{}) { | ||
2138 | if VerboseLogs { | ||
2139 | t.logf(format, args...) | ||
2140 | } | ||
2141 | } | ||
2142 | |||
2143 | func (t *Transport) logf(format string, args ...interface{}) { | ||
2144 | log.Printf(format, args...) | ||
2145 | } | ||
2146 | |||
2147 | var noBody io.ReadCloser = ioutil.NopCloser(bytes.NewReader(nil)) | ||
2148 | |||
2149 | func strSliceContains(ss []string, s string) bool { | ||
2150 | for _, v := range ss { | ||
2151 | if v == s { | ||
2152 | return true | ||
2153 | } | ||
2154 | } | ||
2155 | return false | ||
2156 | } | ||
2157 | |||
2158 | type erringRoundTripper struct{ err error } | ||
2159 | |||
2160 | func (rt erringRoundTripper) RoundTrip(*http.Request) (*http.Response, error) { return nil, rt.err } | ||
2161 | |||
2162 | // gzipReader wraps a response body so it can lazily | ||
2163 | // call gzip.NewReader on the first call to Read | ||
2164 | type gzipReader struct { | ||
2165 | body io.ReadCloser // underlying Response.Body | ||
2166 | zr *gzip.Reader // lazily-initialized gzip reader | ||
2167 | zerr error // sticky error | ||
2168 | } | ||
2169 | |||
2170 | func (gz *gzipReader) Read(p []byte) (n int, err error) { | ||
2171 | if gz.zerr != nil { | ||
2172 | return 0, gz.zerr | ||
2173 | } | ||
2174 | if gz.zr == nil { | ||
2175 | gz.zr, err = gzip.NewReader(gz.body) | ||
2176 | if err != nil { | ||
2177 | gz.zerr = err | ||
2178 | return 0, err | ||
2179 | } | ||
2180 | } | ||
2181 | return gz.zr.Read(p) | ||
2182 | } | ||
2183 | |||
2184 | func (gz *gzipReader) Close() error { | ||
2185 | return gz.body.Close() | ||
2186 | } | ||
2187 | |||
2188 | type errorReader struct{ err error } | ||
2189 | |||
2190 | func (r errorReader) Read(p []byte) (int, error) { return 0, r.err } | ||
2191 | |||
2192 | // bodyWriterState encapsulates various state around the Transport's writing | ||
2193 | // of the request body, particularly regarding doing delayed writes of the body | ||
2194 | // when the request contains "Expect: 100-continue". | ||
2195 | type bodyWriterState struct { | ||
2196 | cs *clientStream | ||
2197 | timer *time.Timer // if non-nil, we're doing a delayed write | ||
2198 | fnonce *sync.Once // to call fn with | ||
2199 | fn func() // the code to run in the goroutine, writing the body | ||
2200 | resc chan error // result of fn's execution | ||
2201 | delay time.Duration // how long we should delay a delayed write for | ||
2202 | } | ||
2203 | |||
2204 | func (t *Transport) getBodyWriterState(cs *clientStream, body io.Reader) (s bodyWriterState) { | ||
2205 | s.cs = cs | ||
2206 | if body == nil { | ||
2207 | return | ||
2208 | } | ||
2209 | resc := make(chan error, 1) | ||
2210 | s.resc = resc | ||
2211 | s.fn = func() { | ||
2212 | cs.cc.mu.Lock() | ||
2213 | cs.startedWrite = true | ||
2214 | cs.cc.mu.Unlock() | ||
2215 | resc <- cs.writeRequestBody(body, cs.req.Body) | ||
2216 | } | ||
2217 | s.delay = t.expectContinueTimeout() | ||
2218 | if s.delay == 0 || | ||
2219 | !httplex.HeaderValuesContainsToken( | ||
2220 | cs.req.Header["Expect"], | ||
2221 | "100-continue") { | ||
2222 | return | ||
2223 | } | ||
2224 | s.fnonce = new(sync.Once) | ||
2225 | |||
2226 | // Arm the timer with a very large duration, which we'll | ||
2227 | // intentionally lower later. It has to be large now because | ||
2228 | // we need a handle to it before writing the headers, but the | ||
2229 | // s.delay value is defined to not start until after the | ||
2230 | // request headers were written. | ||
2231 | const hugeDuration = 365 * 24 * time.Hour | ||
2232 | s.timer = time.AfterFunc(hugeDuration, func() { | ||
2233 | s.fnonce.Do(s.fn) | ||
2234 | }) | ||
2235 | return | ||
2236 | } | ||
2237 | |||
2238 | func (s bodyWriterState) cancel() { | ||
2239 | if s.timer != nil { | ||
2240 | s.timer.Stop() | ||
2241 | } | ||
2242 | } | ||
2243 | |||
2244 | func (s bodyWriterState) on100() { | ||
2245 | if s.timer == nil { | ||
2246 | // If we didn't do a delayed write, ignore the server's | ||
2247 | // bogus 100 continue response. | ||
2248 | return | ||
2249 | } | ||
2250 | s.timer.Stop() | ||
2251 | go func() { s.fnonce.Do(s.fn) }() | ||
2252 | } | ||
2253 | |||
2254 | // scheduleBodyWrite starts writing the body, either immediately (in | ||
2255 | // the common case) or after the delay timeout. It should not be | ||
2256 | // called until after the headers have been written. | ||
2257 | func (s bodyWriterState) scheduleBodyWrite() { | ||
2258 | if s.timer == nil { | ||
2259 | // We're not doing a delayed write (see | ||
2260 | // getBodyWriterState), so just start the writing | ||
2261 | // goroutine immediately. | ||
2262 | go s.fn() | ||
2263 | return | ||
2264 | } | ||
2265 | traceWait100Continue(s.cs.trace) | ||
2266 | if s.timer.Stop() { | ||
2267 | s.timer.Reset(s.delay) | ||
2268 | } | ||
2269 | } | ||
2270 | |||
2271 | // isConnectionCloseRequest reports whether req should use its own | ||
2272 | // connection for a single request and then close the connection. | ||
2273 | func isConnectionCloseRequest(req *http.Request) bool { | ||
2274 | return req.Close || httplex.HeaderValuesContainsToken(req.Header["Connection"], "close") | ||
2275 | } | ||
diff --git a/vendor/golang.org/x/net/http2/write.go b/vendor/golang.org/x/net/http2/write.go new file mode 100644 index 0000000..6b0dfae --- /dev/null +++ b/vendor/golang.org/x/net/http2/write.go | |||
@@ -0,0 +1,370 @@ | |||
1 | // Copyright 2014 The Go Authors. All rights reserved. | ||
2 | // Use of this source code is governed by a BSD-style | ||
3 | // license that can be found in the LICENSE file. | ||
4 | |||
5 | package http2 | ||
6 | |||
7 | import ( | ||
8 | "bytes" | ||
9 | "fmt" | ||
10 | "log" | ||
11 | "net/http" | ||
12 | "net/url" | ||
13 | "time" | ||
14 | |||
15 | "golang.org/x/net/http2/hpack" | ||
16 | "golang.org/x/net/lex/httplex" | ||
17 | ) | ||
18 | |||
19 | // writeFramer is implemented by any type that is used to write frames. | ||
20 | type writeFramer interface { | ||
21 | writeFrame(writeContext) error | ||
22 | |||
23 | // staysWithinBuffer reports whether this writer promises that | ||
24 | // it will only write less than or equal to size bytes, and it | ||
25 | // won't Flush the write context. | ||
26 | staysWithinBuffer(size int) bool | ||
27 | } | ||
28 | |||
29 | // writeContext is the interface needed by the various frame writer | ||
30 | // types below. All the writeFrame methods below are scheduled via the | ||
31 | // frame writing scheduler (see writeScheduler in writesched.go). | ||
32 | // | ||
33 | // This interface is implemented by *serverConn. | ||
34 | // | ||
35 | // TODO: decide whether to a) use this in the client code (which didn't | ||
36 | // end up using this yet, because it has a simpler design, not | ||
37 | // currently implementing priorities), or b) delete this and | ||
38 | // make the server code a bit more concrete. | ||
39 | type writeContext interface { | ||
40 | Framer() *Framer | ||
41 | Flush() error | ||
42 | CloseConn() error | ||
43 | // HeaderEncoder returns an HPACK encoder that writes to the | ||
44 | // returned buffer. | ||
45 | HeaderEncoder() (*hpack.Encoder, *bytes.Buffer) | ||
46 | } | ||
47 | |||
48 | // writeEndsStream reports whether w writes a frame that will transition | ||
49 | // the stream to a half-closed local state. This returns false for RST_STREAM, | ||
50 | // which closes the entire stream (not just the local half). | ||
51 | func writeEndsStream(w writeFramer) bool { | ||
52 | switch v := w.(type) { | ||
53 | case *writeData: | ||
54 | return v.endStream | ||
55 | case *writeResHeaders: | ||
56 | return v.endStream | ||
57 | case nil: | ||
58 | // This can only happen if the caller reuses w after it's | ||
59 | // been intentionally nil'ed out to prevent use. Keep this | ||
60 | // here to catch future refactoring breaking it. | ||
61 | panic("writeEndsStream called on nil writeFramer") | ||
62 | } | ||
63 | return false | ||
64 | } | ||
65 | |||
66 | type flushFrameWriter struct{} | ||
67 | |||
68 | func (flushFrameWriter) writeFrame(ctx writeContext) error { | ||
69 | return ctx.Flush() | ||
70 | } | ||
71 | |||
72 | func (flushFrameWriter) staysWithinBuffer(max int) bool { return false } | ||
73 | |||
74 | type writeSettings []Setting | ||
75 | |||
76 | func (s writeSettings) staysWithinBuffer(max int) bool { | ||
77 | const settingSize = 6 // uint16 + uint32 | ||
78 | return frameHeaderLen+settingSize*len(s) <= max | ||
79 | |||
80 | } | ||
81 | |||
82 | func (s writeSettings) writeFrame(ctx writeContext) error { | ||
83 | return ctx.Framer().WriteSettings([]Setting(s)...) | ||
84 | } | ||
85 | |||
86 | type writeGoAway struct { | ||
87 | maxStreamID uint32 | ||
88 | code ErrCode | ||
89 | } | ||
90 | |||
91 | func (p *writeGoAway) writeFrame(ctx writeContext) error { | ||
92 | err := ctx.Framer().WriteGoAway(p.maxStreamID, p.code, nil) | ||
93 | if p.code != 0 { | ||
94 | ctx.Flush() // ignore error: we're hanging up on them anyway | ||
95 | time.Sleep(50 * time.Millisecond) | ||
96 | ctx.CloseConn() | ||
97 | } | ||
98 | return err | ||
99 | } | ||
100 | |||
101 | func (*writeGoAway) staysWithinBuffer(max int) bool { return false } // flushes | ||
102 | |||
103 | type writeData struct { | ||
104 | streamID uint32 | ||
105 | p []byte | ||
106 | endStream bool | ||
107 | } | ||
108 | |||
109 | func (w *writeData) String() string { | ||
110 | return fmt.Sprintf("writeData(stream=%d, p=%d, endStream=%v)", w.streamID, len(w.p), w.endStream) | ||
111 | } | ||
112 | |||
113 | func (w *writeData) writeFrame(ctx writeContext) error { | ||
114 | return ctx.Framer().WriteData(w.streamID, w.endStream, w.p) | ||
115 | } | ||
116 | |||
117 | func (w *writeData) staysWithinBuffer(max int) bool { | ||
118 | return frameHeaderLen+len(w.p) <= max | ||
119 | } | ||
120 | |||
121 | // handlerPanicRST is the message sent from handler goroutines when | ||
122 | // the handler panics. | ||
123 | type handlerPanicRST struct { | ||
124 | StreamID uint32 | ||
125 | } | ||
126 | |||
127 | func (hp handlerPanicRST) writeFrame(ctx writeContext) error { | ||
128 | return ctx.Framer().WriteRSTStream(hp.StreamID, ErrCodeInternal) | ||
129 | } | ||
130 | |||
131 | func (hp handlerPanicRST) staysWithinBuffer(max int) bool { return frameHeaderLen+4 <= max } | ||
132 | |||
133 | func (se StreamError) writeFrame(ctx writeContext) error { | ||
134 | return ctx.Framer().WriteRSTStream(se.StreamID, se.Code) | ||
135 | } | ||
136 | |||
137 | func (se StreamError) staysWithinBuffer(max int) bool { return frameHeaderLen+4 <= max } | ||
138 | |||
139 | type writePingAck struct{ pf *PingFrame } | ||
140 | |||
141 | func (w writePingAck) writeFrame(ctx writeContext) error { | ||
142 | return ctx.Framer().WritePing(true, w.pf.Data) | ||
143 | } | ||
144 | |||
145 | func (w writePingAck) staysWithinBuffer(max int) bool { return frameHeaderLen+len(w.pf.Data) <= max } | ||
146 | |||
147 | type writeSettingsAck struct{} | ||
148 | |||
149 | func (writeSettingsAck) writeFrame(ctx writeContext) error { | ||
150 | return ctx.Framer().WriteSettingsAck() | ||
151 | } | ||
152 | |||
153 | func (writeSettingsAck) staysWithinBuffer(max int) bool { return frameHeaderLen <= max } | ||
154 | |||
155 | // splitHeaderBlock splits headerBlock into fragments so that each fragment fits | ||
156 | // in a single frame, then calls fn for each fragment. firstFrag/lastFrag are true | ||
157 | // for the first/last fragment, respectively. | ||
158 | func splitHeaderBlock(ctx writeContext, headerBlock []byte, fn func(ctx writeContext, frag []byte, firstFrag, lastFrag bool) error) error { | ||
159 | // For now we're lazy and just pick the minimum MAX_FRAME_SIZE | ||
160 | // that all peers must support (16KB). Later we could care | ||
161 | // more and send larger frames if the peer advertised it, but | ||
162 | // there's little point. Most headers are small anyway (so we | ||
163 | // generally won't have CONTINUATION frames), and extra frames | ||
164 | // only waste 9 bytes anyway. | ||
165 | const maxFrameSize = 16384 | ||
166 | |||
167 | first := true | ||
168 | for len(headerBlock) > 0 { | ||
169 | frag := headerBlock | ||
170 | if len(frag) > maxFrameSize { | ||
171 | frag = frag[:maxFrameSize] | ||
172 | } | ||
173 | headerBlock = headerBlock[len(frag):] | ||
174 | if err := fn(ctx, frag, first, len(headerBlock) == 0); err != nil { | ||
175 | return err | ||
176 | } | ||
177 | first = false | ||
178 | } | ||
179 | return nil | ||
180 | } | ||
181 | |||
182 | // writeResHeaders is a request to write a HEADERS and 0+ CONTINUATION frames | ||
183 | // for HTTP response headers or trailers from a server handler. | ||
184 | type writeResHeaders struct { | ||
185 | streamID uint32 | ||
186 | httpResCode int // 0 means no ":status" line | ||
187 | h http.Header // may be nil | ||
188 | trailers []string // if non-nil, which keys of h to write. nil means all. | ||
189 | endStream bool | ||
190 | |||
191 | date string | ||
192 | contentType string | ||
193 | contentLength string | ||
194 | } | ||
195 | |||
196 | func encKV(enc *hpack.Encoder, k, v string) { | ||
197 | if VerboseLogs { | ||
198 | log.Printf("http2: server encoding header %q = %q", k, v) | ||
199 | } | ||
200 | enc.WriteField(hpack.HeaderField{Name: k, Value: v}) | ||
201 | } | ||
202 | |||
203 | func (w *writeResHeaders) staysWithinBuffer(max int) bool { | ||
204 | // TODO: this is a common one. It'd be nice to return true | ||
205 | // here and get into the fast path if we could be clever and | ||
206 | // calculate the size fast enough, or at least a conservative | ||
207 | // uppper bound that usually fires. (Maybe if w.h and | ||
208 | // w.trailers are nil, so we don't need to enumerate it.) | ||
209 | // Otherwise I'm afraid that just calculating the length to | ||
210 | // answer this question would be slower than the ~2µs benefit. | ||
211 | return false | ||
212 | } | ||
213 | |||
214 | func (w *writeResHeaders) writeFrame(ctx writeContext) error { | ||
215 | enc, buf := ctx.HeaderEncoder() | ||
216 | buf.Reset() | ||
217 | |||
218 | if w.httpResCode != 0 { | ||
219 | encKV(enc, ":status", httpCodeString(w.httpResCode)) | ||
220 | } | ||
221 | |||
222 | encodeHeaders(enc, w.h, w.trailers) | ||
223 | |||
224 | if w.contentType != "" { | ||
225 | encKV(enc, "content-type", w.contentType) | ||
226 | } | ||
227 | if w.contentLength != "" { | ||
228 | encKV(enc, "content-length", w.contentLength) | ||
229 | } | ||
230 | if w.date != "" { | ||
231 | encKV(enc, "date", w.date) | ||
232 | } | ||
233 | |||
234 | headerBlock := buf.Bytes() | ||
235 | if len(headerBlock) == 0 && w.trailers == nil { | ||
236 | panic("unexpected empty hpack") | ||
237 | } | ||
238 | |||
239 | return splitHeaderBlock(ctx, headerBlock, w.writeHeaderBlock) | ||
240 | } | ||
241 | |||
242 | func (w *writeResHeaders) writeHeaderBlock(ctx writeContext, frag []byte, firstFrag, lastFrag bool) error { | ||
243 | if firstFrag { | ||
244 | return ctx.Framer().WriteHeaders(HeadersFrameParam{ | ||
245 | StreamID: w.streamID, | ||
246 | BlockFragment: frag, | ||
247 | EndStream: w.endStream, | ||
248 | EndHeaders: lastFrag, | ||
249 | }) | ||
250 | } else { | ||
251 | return ctx.Framer().WriteContinuation(w.streamID, lastFrag, frag) | ||
252 | } | ||
253 | } | ||
254 | |||
255 | // writePushPromise is a request to write a PUSH_PROMISE and 0+ CONTINUATION frames. | ||
256 | type writePushPromise struct { | ||
257 | streamID uint32 // pusher stream | ||
258 | method string // for :method | ||
259 | url *url.URL // for :scheme, :authority, :path | ||
260 | h http.Header | ||
261 | |||
262 | // Creates an ID for a pushed stream. This runs on serveG just before | ||
263 | // the frame is written. The returned ID is copied to promisedID. | ||
264 | allocatePromisedID func() (uint32, error) | ||
265 | promisedID uint32 | ||
266 | } | ||
267 | |||
268 | func (w *writePushPromise) staysWithinBuffer(max int) bool { | ||
269 | // TODO: see writeResHeaders.staysWithinBuffer | ||
270 | return false | ||
271 | } | ||
272 | |||
273 | func (w *writePushPromise) writeFrame(ctx writeContext) error { | ||
274 | enc, buf := ctx.HeaderEncoder() | ||
275 | buf.Reset() | ||
276 | |||
277 | encKV(enc, ":method", w.method) | ||
278 | encKV(enc, ":scheme", w.url.Scheme) | ||
279 | encKV(enc, ":authority", w.url.Host) | ||
280 | encKV(enc, ":path", w.url.RequestURI()) | ||
281 | encodeHeaders(enc, w.h, nil) | ||
282 | |||
283 | headerBlock := buf.Bytes() | ||
284 | if len(headerBlock) == 0 { | ||
285 | panic("unexpected empty hpack") | ||
286 | } | ||
287 | |||
288 | return splitHeaderBlock(ctx, headerBlock, w.writeHeaderBlock) | ||
289 | } | ||
290 | |||
291 | func (w *writePushPromise) writeHeaderBlock(ctx writeContext, frag []byte, firstFrag, lastFrag bool) error { | ||
292 | if firstFrag { | ||
293 | return ctx.Framer().WritePushPromise(PushPromiseParam{ | ||
294 | StreamID: w.streamID, | ||
295 | PromiseID: w.promisedID, | ||
296 | BlockFragment: frag, | ||
297 | EndHeaders: lastFrag, | ||
298 | }) | ||
299 | } else { | ||
300 | return ctx.Framer().WriteContinuation(w.streamID, lastFrag, frag) | ||
301 | } | ||
302 | } | ||
303 | |||
304 | type write100ContinueHeadersFrame struct { | ||
305 | streamID uint32 | ||
306 | } | ||
307 | |||
308 | func (w write100ContinueHeadersFrame) writeFrame(ctx writeContext) error { | ||
309 | enc, buf := ctx.HeaderEncoder() | ||
310 | buf.Reset() | ||
311 | encKV(enc, ":status", "100") | ||
312 | return ctx.Framer().WriteHeaders(HeadersFrameParam{ | ||
313 | StreamID: w.streamID, | ||
314 | BlockFragment: buf.Bytes(), | ||
315 | EndStream: false, | ||
316 | EndHeaders: true, | ||
317 | }) | ||
318 | } | ||
319 | |||
320 | func (w write100ContinueHeadersFrame) staysWithinBuffer(max int) bool { | ||
321 | // Sloppy but conservative: | ||
322 | return 9+2*(len(":status")+len("100")) <= max | ||
323 | } | ||
324 | |||
325 | type writeWindowUpdate struct { | ||
326 | streamID uint32 // or 0 for conn-level | ||
327 | n uint32 | ||
328 | } | ||
329 | |||
330 | func (wu writeWindowUpdate) staysWithinBuffer(max int) bool { return frameHeaderLen+4 <= max } | ||
331 | |||
332 | func (wu writeWindowUpdate) writeFrame(ctx writeContext) error { | ||
333 | return ctx.Framer().WriteWindowUpdate(wu.streamID, wu.n) | ||
334 | } | ||
335 | |||
336 | // encodeHeaders encodes an http.Header. If keys is not nil, then (k, h[k]) | ||
337 | // is encoded only only if k is in keys. | ||
338 | func encodeHeaders(enc *hpack.Encoder, h http.Header, keys []string) { | ||
339 | if keys == nil { | ||
340 | sorter := sorterPool.Get().(*sorter) | ||
341 | // Using defer here, since the returned keys from the | ||
342 | // sorter.Keys method is only valid until the sorter | ||
343 | // is returned: | ||
344 | defer sorterPool.Put(sorter) | ||
345 | keys = sorter.Keys(h) | ||
346 | } | ||
347 | for _, k := range keys { | ||
348 | vv := h[k] | ||
349 | k = lowerHeader(k) | ||
350 | if !validWireHeaderFieldName(k) { | ||
351 | // Skip it as backup paranoia. Per | ||
352 | // golang.org/issue/14048, these should | ||
353 | // already be rejected at a higher level. | ||
354 | continue | ||
355 | } | ||
356 | isTE := k == "transfer-encoding" | ||
357 | for _, v := range vv { | ||
358 | if !httplex.ValidHeaderFieldValue(v) { | ||
359 | // TODO: return an error? golang.org/issue/14048 | ||
360 | // For now just omit it. | ||
361 | continue | ||
362 | } | ||
363 | // TODO: more of "8.1.2.2 Connection-Specific Header Fields" | ||
364 | if isTE && v != "trailers" { | ||
365 | continue | ||
366 | } | ||
367 | encKV(enc, k, v) | ||
368 | } | ||
369 | } | ||
370 | } | ||
diff --git a/vendor/golang.org/x/net/http2/writesched.go b/vendor/golang.org/x/net/http2/writesched.go new file mode 100644 index 0000000..4fe3073 --- /dev/null +++ b/vendor/golang.org/x/net/http2/writesched.go | |||
@@ -0,0 +1,242 @@ | |||
1 | // Copyright 2014 The Go Authors. All rights reserved. | ||
2 | // Use of this source code is governed by a BSD-style | ||
3 | // license that can be found in the LICENSE file. | ||
4 | |||
5 | package http2 | ||
6 | |||
7 | import "fmt" | ||
8 | |||
9 | // WriteScheduler is the interface implemented by HTTP/2 write schedulers. | ||
10 | // Methods are never called concurrently. | ||
11 | type WriteScheduler interface { | ||
12 | // OpenStream opens a new stream in the write scheduler. | ||
13 | // It is illegal to call this with streamID=0 or with a streamID that is | ||
14 | // already open -- the call may panic. | ||
15 | OpenStream(streamID uint32, options OpenStreamOptions) | ||
16 | |||
17 | // CloseStream closes a stream in the write scheduler. Any frames queued on | ||
18 | // this stream should be discarded. It is illegal to call this on a stream | ||
19 | // that is not open -- the call may panic. | ||
20 | CloseStream(streamID uint32) | ||
21 | |||
22 | // AdjustStream adjusts the priority of the given stream. This may be called | ||
23 | // on a stream that has not yet been opened or has been closed. Note that | ||
24 | // RFC 7540 allows PRIORITY frames to be sent on streams in any state. See: | ||
25 | // https://tools.ietf.org/html/rfc7540#section-5.1 | ||
26 | AdjustStream(streamID uint32, priority PriorityParam) | ||
27 | |||
28 | // Push queues a frame in the scheduler. In most cases, this will not be | ||
29 | // called with wr.StreamID()!=0 unless that stream is currently open. The one | ||
30 | // exception is RST_STREAM frames, which may be sent on idle or closed streams. | ||
31 | Push(wr FrameWriteRequest) | ||
32 | |||
33 | // Pop dequeues the next frame to write. Returns false if no frames can | ||
34 | // be written. Frames with a given wr.StreamID() are Pop'd in the same | ||
35 | // order they are Push'd. | ||
36 | Pop() (wr FrameWriteRequest, ok bool) | ||
37 | } | ||
38 | |||
39 | // OpenStreamOptions specifies extra options for WriteScheduler.OpenStream. | ||
40 | type OpenStreamOptions struct { | ||
41 | // PusherID is zero if the stream was initiated by the client. Otherwise, | ||
42 | // PusherID names the stream that pushed the newly opened stream. | ||
43 | PusherID uint32 | ||
44 | } | ||
45 | |||
46 | // FrameWriteRequest is a request to write a frame. | ||
47 | type FrameWriteRequest struct { | ||
48 | // write is the interface value that does the writing, once the | ||
49 | // WriteScheduler has selected this frame to write. The write | ||
50 | // functions are all defined in write.go. | ||
51 | write writeFramer | ||
52 | |||
53 | // stream is the stream on which this frame will be written. | ||
54 | // nil for non-stream frames like PING and SETTINGS. | ||
55 | stream *stream | ||
56 | |||
57 | // done, if non-nil, must be a buffered channel with space for | ||
58 | // 1 message and is sent the return value from write (or an | ||
59 | // earlier error) when the frame has been written. | ||
60 | done chan error | ||
61 | } | ||
62 | |||
63 | // StreamID returns the id of the stream this frame will be written to. | ||
64 | // 0 is used for non-stream frames such as PING and SETTINGS. | ||
65 | func (wr FrameWriteRequest) StreamID() uint32 { | ||
66 | if wr.stream == nil { | ||
67 | if se, ok := wr.write.(StreamError); ok { | ||
68 | // (*serverConn).resetStream doesn't set | ||
69 | // stream because it doesn't necessarily have | ||
70 | // one. So special case this type of write | ||
71 | // message. | ||
72 | return se.StreamID | ||
73 | } | ||
74 | return 0 | ||
75 | } | ||
76 | return wr.stream.id | ||
77 | } | ||
78 | |||
79 | // DataSize returns the number of flow control bytes that must be consumed | ||
80 | // to write this entire frame. This is 0 for non-DATA frames. | ||
81 | func (wr FrameWriteRequest) DataSize() int { | ||
82 | if wd, ok := wr.write.(*writeData); ok { | ||
83 | return len(wd.p) | ||
84 | } | ||
85 | return 0 | ||
86 | } | ||
87 | |||
88 | // Consume consumes min(n, available) bytes from this frame, where available | ||
89 | // is the number of flow control bytes available on the stream. Consume returns | ||
90 | // 0, 1, or 2 frames, where the integer return value gives the number of frames | ||
91 | // returned. | ||
92 | // | ||
93 | // If flow control prevents consuming any bytes, this returns (_, _, 0). If | ||
94 | // the entire frame was consumed, this returns (wr, _, 1). Otherwise, this | ||
95 | // returns (consumed, rest, 2), where 'consumed' contains the consumed bytes and | ||
96 | // 'rest' contains the remaining bytes. The consumed bytes are deducted from the | ||
97 | // underlying stream's flow control budget. | ||
98 | func (wr FrameWriteRequest) Consume(n int32) (FrameWriteRequest, FrameWriteRequest, int) { | ||
99 | var empty FrameWriteRequest | ||
100 | |||
101 | // Non-DATA frames are always consumed whole. | ||
102 | wd, ok := wr.write.(*writeData) | ||
103 | if !ok || len(wd.p) == 0 { | ||
104 | return wr, empty, 1 | ||
105 | } | ||
106 | |||
107 | // Might need to split after applying limits. | ||
108 | allowed := wr.stream.flow.available() | ||
109 | if n < allowed { | ||
110 | allowed = n | ||
111 | } | ||
112 | if wr.stream.sc.maxFrameSize < allowed { | ||
113 | allowed = wr.stream.sc.maxFrameSize | ||
114 | } | ||
115 | if allowed <= 0 { | ||
116 | return empty, empty, 0 | ||
117 | } | ||
118 | if len(wd.p) > int(allowed) { | ||
119 | wr.stream.flow.take(allowed) | ||
120 | consumed := FrameWriteRequest{ | ||
121 | stream: wr.stream, | ||
122 | write: &writeData{ | ||
123 | streamID: wd.streamID, | ||
124 | p: wd.p[:allowed], | ||
125 | // Even if the original had endStream set, there | ||
126 | // are bytes remaining because len(wd.p) > allowed, | ||
127 | // so we know endStream is false. | ||
128 | endStream: false, | ||
129 | }, | ||
130 | // Our caller is blocking on the final DATA frame, not | ||
131 | // this intermediate frame, so no need to wait. | ||
132 | done: nil, | ||
133 | } | ||
134 | rest := FrameWriteRequest{ | ||
135 | stream: wr.stream, | ||
136 | write: &writeData{ | ||
137 | streamID: wd.streamID, | ||
138 | p: wd.p[allowed:], | ||
139 | endStream: wd.endStream, | ||
140 | }, | ||
141 | done: wr.done, | ||
142 | } | ||
143 | return consumed, rest, 2 | ||
144 | } | ||
145 | |||
146 | // The frame is consumed whole. | ||
147 | // NB: This cast cannot overflow because allowed is <= math.MaxInt32. | ||
148 | wr.stream.flow.take(int32(len(wd.p))) | ||
149 | return wr, empty, 1 | ||
150 | } | ||
151 | |||
152 | // String is for debugging only. | ||
153 | func (wr FrameWriteRequest) String() string { | ||
154 | var des string | ||
155 | if s, ok := wr.write.(fmt.Stringer); ok { | ||
156 | des = s.String() | ||
157 | } else { | ||
158 | des = fmt.Sprintf("%T", wr.write) | ||
159 | } | ||
160 | return fmt.Sprintf("[FrameWriteRequest stream=%d, ch=%v, writer=%v]", wr.StreamID(), wr.done != nil, des) | ||
161 | } | ||
162 | |||
163 | // replyToWriter sends err to wr.done and panics if the send must block | ||
164 | // This does nothing if wr.done is nil. | ||
165 | func (wr *FrameWriteRequest) replyToWriter(err error) { | ||
166 | if wr.done == nil { | ||
167 | return | ||
168 | } | ||
169 | select { | ||
170 | case wr.done <- err: | ||
171 | default: | ||
172 | panic(fmt.Sprintf("unbuffered done channel passed in for type %T", wr.write)) | ||
173 | } | ||
174 | wr.write = nil // prevent use (assume it's tainted after wr.done send) | ||
175 | } | ||
176 | |||
177 | // writeQueue is used by implementations of WriteScheduler. | ||
178 | type writeQueue struct { | ||
179 | s []FrameWriteRequest | ||
180 | } | ||
181 | |||
182 | func (q *writeQueue) empty() bool { return len(q.s) == 0 } | ||
183 | |||
184 | func (q *writeQueue) push(wr FrameWriteRequest) { | ||
185 | q.s = append(q.s, wr) | ||
186 | } | ||
187 | |||
188 | func (q *writeQueue) shift() FrameWriteRequest { | ||
189 | if len(q.s) == 0 { | ||
190 | panic("invalid use of queue") | ||
191 | } | ||
192 | wr := q.s[0] | ||
193 | // TODO: less copy-happy queue. | ||
194 | copy(q.s, q.s[1:]) | ||
195 | q.s[len(q.s)-1] = FrameWriteRequest{} | ||
196 | q.s = q.s[:len(q.s)-1] | ||
197 | return wr | ||
198 | } | ||
199 | |||
200 | // consume consumes up to n bytes from q.s[0]. If the frame is | ||
201 | // entirely consumed, it is removed from the queue. If the frame | ||
202 | // is partially consumed, the frame is kept with the consumed | ||
203 | // bytes removed. Returns true iff any bytes were consumed. | ||
204 | func (q *writeQueue) consume(n int32) (FrameWriteRequest, bool) { | ||
205 | if len(q.s) == 0 { | ||
206 | return FrameWriteRequest{}, false | ||
207 | } | ||
208 | consumed, rest, numresult := q.s[0].Consume(n) | ||
209 | switch numresult { | ||
210 | case 0: | ||
211 | return FrameWriteRequest{}, false | ||
212 | case 1: | ||
213 | q.shift() | ||
214 | case 2: | ||
215 | q.s[0] = rest | ||
216 | } | ||
217 | return consumed, true | ||
218 | } | ||
219 | |||
220 | type writeQueuePool []*writeQueue | ||
221 | |||
222 | // put inserts an unused writeQueue into the pool. | ||
223 | func (p *writeQueuePool) put(q *writeQueue) { | ||
224 | for i := range q.s { | ||
225 | q.s[i] = FrameWriteRequest{} | ||
226 | } | ||
227 | q.s = q.s[:0] | ||
228 | *p = append(*p, q) | ||
229 | } | ||
230 | |||
231 | // get returns an empty writeQueue. | ||
232 | func (p *writeQueuePool) get() *writeQueue { | ||
233 | ln := len(*p) | ||
234 | if ln == 0 { | ||
235 | return new(writeQueue) | ||
236 | } | ||
237 | x := ln - 1 | ||
238 | q := (*p)[x] | ||
239 | (*p)[x] = nil | ||
240 | *p = (*p)[:x] | ||
241 | return q | ||
242 | } | ||
diff --git a/vendor/golang.org/x/net/http2/writesched_priority.go b/vendor/golang.org/x/net/http2/writesched_priority.go new file mode 100644 index 0000000..848fed6 --- /dev/null +++ b/vendor/golang.org/x/net/http2/writesched_priority.go | |||
@@ -0,0 +1,452 @@ | |||
1 | // Copyright 2016 The Go Authors. All rights reserved. | ||
2 | // Use of this source code is governed by a BSD-style | ||
3 | // license that can be found in the LICENSE file. | ||
4 | |||
5 | package http2 | ||
6 | |||
7 | import ( | ||
8 | "fmt" | ||
9 | "math" | ||
10 | "sort" | ||
11 | ) | ||
12 | |||
13 | // RFC 7540, Section 5.3.5: the default weight is 16. | ||
14 | const priorityDefaultWeight = 15 // 16 = 15 + 1 | ||
15 | |||
16 | // PriorityWriteSchedulerConfig configures a priorityWriteScheduler. | ||
17 | type PriorityWriteSchedulerConfig struct { | ||
18 | // MaxClosedNodesInTree controls the maximum number of closed streams to | ||
19 | // retain in the priority tree. Setting this to zero saves a small amount | ||
20 | // of memory at the cost of performance. | ||
21 | // | ||
22 | // See RFC 7540, Section 5.3.4: | ||
23 | // "It is possible for a stream to become closed while prioritization | ||
24 | // information ... is in transit. ... This potentially creates suboptimal | ||
25 | // prioritization, since the stream could be given a priority that is | ||
26 | // different from what is intended. To avoid these problems, an endpoint | ||
27 | // SHOULD retain stream prioritization state for a period after streams | ||
28 | // become closed. The longer state is retained, the lower the chance that | ||
29 | // streams are assigned incorrect or default priority values." | ||
30 | MaxClosedNodesInTree int | ||
31 | |||
32 | // MaxIdleNodesInTree controls the maximum number of idle streams to | ||
33 | // retain in the priority tree. Setting this to zero saves a small amount | ||
34 | // of memory at the cost of performance. | ||
35 | // | ||
36 | // See RFC 7540, Section 5.3.4: | ||
37 | // Similarly, streams that are in the "idle" state can be assigned | ||
38 | // priority or become a parent of other streams. This allows for the | ||
39 | // creation of a grouping node in the dependency tree, which enables | ||
40 | // more flexible expressions of priority. Idle streams begin with a | ||
41 | // default priority (Section 5.3.5). | ||
42 | MaxIdleNodesInTree int | ||
43 | |||
44 | // ThrottleOutOfOrderWrites enables write throttling to help ensure that | ||
45 | // data is delivered in priority order. This works around a race where | ||
46 | // stream B depends on stream A and both streams are about to call Write | ||
47 | // to queue DATA frames. If B wins the race, a naive scheduler would eagerly | ||
48 | // write as much data from B as possible, but this is suboptimal because A | ||
49 | // is a higher-priority stream. With throttling enabled, we write a small | ||
50 | // amount of data from B to minimize the amount of bandwidth that B can | ||
51 | // steal from A. | ||
52 | ThrottleOutOfOrderWrites bool | ||
53 | } | ||
54 | |||
55 | // NewPriorityWriteScheduler constructs a WriteScheduler that schedules | ||
56 | // frames by following HTTP/2 priorities as described in RFC 7540 Section 5.3. | ||
57 | // If cfg is nil, default options are used. | ||
58 | func NewPriorityWriteScheduler(cfg *PriorityWriteSchedulerConfig) WriteScheduler { | ||
59 | if cfg == nil { | ||
60 | // For justification of these defaults, see: | ||
61 | // https://docs.google.com/document/d/1oLhNg1skaWD4_DtaoCxdSRN5erEXrH-KnLrMwEpOtFY | ||
62 | cfg = &PriorityWriteSchedulerConfig{ | ||
63 | MaxClosedNodesInTree: 10, | ||
64 | MaxIdleNodesInTree: 10, | ||
65 | ThrottleOutOfOrderWrites: false, | ||
66 | } | ||
67 | } | ||
68 | |||
69 | ws := &priorityWriteScheduler{ | ||
70 | nodes: make(map[uint32]*priorityNode), | ||
71 | maxClosedNodesInTree: cfg.MaxClosedNodesInTree, | ||
72 | maxIdleNodesInTree: cfg.MaxIdleNodesInTree, | ||
73 | enableWriteThrottle: cfg.ThrottleOutOfOrderWrites, | ||
74 | } | ||
75 | ws.nodes[0] = &ws.root | ||
76 | if cfg.ThrottleOutOfOrderWrites { | ||
77 | ws.writeThrottleLimit = 1024 | ||
78 | } else { | ||
79 | ws.writeThrottleLimit = math.MaxInt32 | ||
80 | } | ||
81 | return ws | ||
82 | } | ||
83 | |||
84 | type priorityNodeState int | ||
85 | |||
86 | const ( | ||
87 | priorityNodeOpen priorityNodeState = iota | ||
88 | priorityNodeClosed | ||
89 | priorityNodeIdle | ||
90 | ) | ||
91 | |||
92 | // priorityNode is a node in an HTTP/2 priority tree. | ||
93 | // Each node is associated with a single stream ID. | ||
94 | // See RFC 7540, Section 5.3. | ||
95 | type priorityNode struct { | ||
96 | q writeQueue // queue of pending frames to write | ||
97 | id uint32 // id of the stream, or 0 for the root of the tree | ||
98 | weight uint8 // the actual weight is weight+1, so the value is in [1,256] | ||
99 | state priorityNodeState // open | closed | idle | ||
100 | bytes int64 // number of bytes written by this node, or 0 if closed | ||
101 | subtreeBytes int64 // sum(node.bytes) of all nodes in this subtree | ||
102 | |||
103 | // These links form the priority tree. | ||
104 | parent *priorityNode | ||
105 | kids *priorityNode // start of the kids list | ||
106 | prev, next *priorityNode // doubly-linked list of siblings | ||
107 | } | ||
108 | |||
109 | func (n *priorityNode) setParent(parent *priorityNode) { | ||
110 | if n == parent { | ||
111 | panic("setParent to self") | ||
112 | } | ||
113 | if n.parent == parent { | ||
114 | return | ||
115 | } | ||
116 | // Unlink from current parent. | ||
117 | if parent := n.parent; parent != nil { | ||
118 | if n.prev == nil { | ||
119 | parent.kids = n.next | ||
120 | } else { | ||
121 | n.prev.next = n.next | ||
122 | } | ||
123 | if n.next != nil { | ||
124 | n.next.prev = n.prev | ||
125 | } | ||
126 | } | ||
127 | // Link to new parent. | ||
128 | // If parent=nil, remove n from the tree. | ||
129 | // Always insert at the head of parent.kids (this is assumed by walkReadyInOrder). | ||
130 | n.parent = parent | ||
131 | if parent == nil { | ||
132 | n.next = nil | ||
133 | n.prev = nil | ||
134 | } else { | ||
135 | n.next = parent.kids | ||
136 | n.prev = nil | ||
137 | if n.next != nil { | ||
138 | n.next.prev = n | ||
139 | } | ||
140 | parent.kids = n | ||
141 | } | ||
142 | } | ||
143 | |||
144 | func (n *priorityNode) addBytes(b int64) { | ||
145 | n.bytes += b | ||
146 | for ; n != nil; n = n.parent { | ||
147 | n.subtreeBytes += b | ||
148 | } | ||
149 | } | ||
150 | |||
151 | // walkReadyInOrder iterates over the tree in priority order, calling f for each node | ||
152 | // with a non-empty write queue. When f returns true, this funcion returns true and the | ||
153 | // walk halts. tmp is used as scratch space for sorting. | ||
154 | // | ||
155 | // f(n, openParent) takes two arguments: the node to visit, n, and a bool that is true | ||
156 | // if any ancestor p of n is still open (ignoring the root node). | ||
157 | func (n *priorityNode) walkReadyInOrder(openParent bool, tmp *[]*priorityNode, f func(*priorityNode, bool) bool) bool { | ||
158 | if !n.q.empty() && f(n, openParent) { | ||
159 | return true | ||
160 | } | ||
161 | if n.kids == nil { | ||
162 | return false | ||
163 | } | ||
164 | |||
165 | // Don't consider the root "open" when updating openParent since | ||
166 | // we can't send data frames on the root stream (only control frames). | ||
167 | if n.id != 0 { | ||
168 | openParent = openParent || (n.state == priorityNodeOpen) | ||
169 | } | ||
170 | |||
171 | // Common case: only one kid or all kids have the same weight. | ||
172 | // Some clients don't use weights; other clients (like web browsers) | ||
173 | // use mostly-linear priority trees. | ||
174 | w := n.kids.weight | ||
175 | needSort := false | ||
176 | for k := n.kids.next; k != nil; k = k.next { | ||
177 | if k.weight != w { | ||
178 | needSort = true | ||
179 | break | ||
180 | } | ||
181 | } | ||
182 | if !needSort { | ||
183 | for k := n.kids; k != nil; k = k.next { | ||
184 | if k.walkReadyInOrder(openParent, tmp, f) { | ||
185 | return true | ||
186 | } | ||
187 | } | ||
188 | return false | ||
189 | } | ||
190 | |||
191 | // Uncommon case: sort the child nodes. We remove the kids from the parent, | ||
192 | // then re-insert after sorting so we can reuse tmp for future sort calls. | ||
193 | *tmp = (*tmp)[:0] | ||
194 | for n.kids != nil { | ||
195 | *tmp = append(*tmp, n.kids) | ||
196 | n.kids.setParent(nil) | ||
197 | } | ||
198 | sort.Sort(sortPriorityNodeSiblings(*tmp)) | ||
199 | for i := len(*tmp) - 1; i >= 0; i-- { | ||
200 | (*tmp)[i].setParent(n) // setParent inserts at the head of n.kids | ||
201 | } | ||
202 | for k := n.kids; k != nil; k = k.next { | ||
203 | if k.walkReadyInOrder(openParent, tmp, f) { | ||
204 | return true | ||
205 | } | ||
206 | } | ||
207 | return false | ||
208 | } | ||
209 | |||
210 | type sortPriorityNodeSiblings []*priorityNode | ||
211 | |||
212 | func (z sortPriorityNodeSiblings) Len() int { return len(z) } | ||
213 | func (z sortPriorityNodeSiblings) Swap(i, k int) { z[i], z[k] = z[k], z[i] } | ||
214 | func (z sortPriorityNodeSiblings) Less(i, k int) bool { | ||
215 | // Prefer the subtree that has sent fewer bytes relative to its weight. | ||
216 | // See sections 5.3.2 and 5.3.4. | ||
217 | wi, bi := float64(z[i].weight+1), float64(z[i].subtreeBytes) | ||
218 | wk, bk := float64(z[k].weight+1), float64(z[k].subtreeBytes) | ||
219 | if bi == 0 && bk == 0 { | ||
220 | return wi >= wk | ||
221 | } | ||
222 | if bk == 0 { | ||
223 | return false | ||
224 | } | ||
225 | return bi/bk <= wi/wk | ||
226 | } | ||
227 | |||
228 | type priorityWriteScheduler struct { | ||
229 | // root is the root of the priority tree, where root.id = 0. | ||
230 | // The root queues control frames that are not associated with any stream. | ||
231 | root priorityNode | ||
232 | |||
233 | // nodes maps stream ids to priority tree nodes. | ||
234 | nodes map[uint32]*priorityNode | ||
235 | |||
236 | // maxID is the maximum stream id in nodes. | ||
237 | maxID uint32 | ||
238 | |||
239 | // lists of nodes that have been closed or are idle, but are kept in | ||
240 | // the tree for improved prioritization. When the lengths exceed either | ||
241 | // maxClosedNodesInTree or maxIdleNodesInTree, old nodes are discarded. | ||
242 | closedNodes, idleNodes []*priorityNode | ||
243 | |||
244 | // From the config. | ||
245 | maxClosedNodesInTree int | ||
246 | maxIdleNodesInTree int | ||
247 | writeThrottleLimit int32 | ||
248 | enableWriteThrottle bool | ||
249 | |||
250 | // tmp is scratch space for priorityNode.walkReadyInOrder to reduce allocations. | ||
251 | tmp []*priorityNode | ||
252 | |||
253 | // pool of empty queues for reuse. | ||
254 | queuePool writeQueuePool | ||
255 | } | ||
256 | |||
257 | func (ws *priorityWriteScheduler) OpenStream(streamID uint32, options OpenStreamOptions) { | ||
258 | // The stream may be currently idle but cannot be opened or closed. | ||
259 | if curr := ws.nodes[streamID]; curr != nil { | ||
260 | if curr.state != priorityNodeIdle { | ||
261 | panic(fmt.Sprintf("stream %d already opened", streamID)) | ||
262 | } | ||
263 | curr.state = priorityNodeOpen | ||
264 | return | ||
265 | } | ||
266 | |||
267 | // RFC 7540, Section 5.3.5: | ||
268 | // "All streams are initially assigned a non-exclusive dependency on stream 0x0. | ||
269 | // Pushed streams initially depend on their associated stream. In both cases, | ||
270 | // streams are assigned a default weight of 16." | ||
271 | parent := ws.nodes[options.PusherID] | ||
272 | if parent == nil { | ||
273 | parent = &ws.root | ||
274 | } | ||
275 | n := &priorityNode{ | ||
276 | q: *ws.queuePool.get(), | ||
277 | id: streamID, | ||
278 | weight: priorityDefaultWeight, | ||
279 | state: priorityNodeOpen, | ||
280 | } | ||
281 | n.setParent(parent) | ||
282 | ws.nodes[streamID] = n | ||
283 | if streamID > ws.maxID { | ||
284 | ws.maxID = streamID | ||
285 | } | ||
286 | } | ||
287 | |||
288 | func (ws *priorityWriteScheduler) CloseStream(streamID uint32) { | ||
289 | if streamID == 0 { | ||
290 | panic("violation of WriteScheduler interface: cannot close stream 0") | ||
291 | } | ||
292 | if ws.nodes[streamID] == nil { | ||
293 | panic(fmt.Sprintf("violation of WriteScheduler interface: unknown stream %d", streamID)) | ||
294 | } | ||
295 | if ws.nodes[streamID].state != priorityNodeOpen { | ||
296 | panic(fmt.Sprintf("violation of WriteScheduler interface: stream %d already closed", streamID)) | ||
297 | } | ||
298 | |||
299 | n := ws.nodes[streamID] | ||
300 | n.state = priorityNodeClosed | ||
301 | n.addBytes(-n.bytes) | ||
302 | |||
303 | q := n.q | ||
304 | ws.queuePool.put(&q) | ||
305 | n.q.s = nil | ||
306 | if ws.maxClosedNodesInTree > 0 { | ||
307 | ws.addClosedOrIdleNode(&ws.closedNodes, ws.maxClosedNodesInTree, n) | ||
308 | } else { | ||
309 | ws.removeNode(n) | ||
310 | } | ||
311 | } | ||
312 | |||
313 | func (ws *priorityWriteScheduler) AdjustStream(streamID uint32, priority PriorityParam) { | ||
314 | if streamID == 0 { | ||
315 | panic("adjustPriority on root") | ||
316 | } | ||
317 | |||
318 | // If streamID does not exist, there are two cases: | ||
319 | // - A closed stream that has been removed (this will have ID <= maxID) | ||
320 | // - An idle stream that is being used for "grouping" (this will have ID > maxID) | ||
321 | n := ws.nodes[streamID] | ||
322 | if n == nil { | ||
323 | if streamID <= ws.maxID || ws.maxIdleNodesInTree == 0 { | ||
324 | return | ||
325 | } | ||
326 | ws.maxID = streamID | ||
327 | n = &priorityNode{ | ||
328 | q: *ws.queuePool.get(), | ||
329 | id: streamID, | ||
330 | weight: priorityDefaultWeight, | ||
331 | state: priorityNodeIdle, | ||
332 | } | ||
333 | n.setParent(&ws.root) | ||
334 | ws.nodes[streamID] = n | ||
335 | ws.addClosedOrIdleNode(&ws.idleNodes, ws.maxIdleNodesInTree, n) | ||
336 | } | ||
337 | |||
338 | // Section 5.3.1: A dependency on a stream that is not currently in the tree | ||
339 | // results in that stream being given a default priority (Section 5.3.5). | ||
340 | parent := ws.nodes[priority.StreamDep] | ||
341 | if parent == nil { | ||
342 | n.setParent(&ws.root) | ||
343 | n.weight = priorityDefaultWeight | ||
344 | return | ||
345 | } | ||
346 | |||
347 | // Ignore if the client tries to make a node its own parent. | ||
348 | if n == parent { | ||
349 | return | ||
350 | } | ||
351 | |||
352 | // Section 5.3.3: | ||
353 | // "If a stream is made dependent on one of its own dependencies, the | ||
354 | // formerly dependent stream is first moved to be dependent on the | ||
355 | // reprioritized stream's previous parent. The moved dependency retains | ||
356 | // its weight." | ||
357 | // | ||
358 | // That is: if parent depends on n, move parent to depend on n.parent. | ||
359 | for x := parent.parent; x != nil; x = x.parent { | ||
360 | if x == n { | ||
361 | parent.setParent(n.parent) | ||
362 | break | ||
363 | } | ||
364 | } | ||
365 | |||
366 | // Section 5.3.3: The exclusive flag causes the stream to become the sole | ||
367 | // dependency of its parent stream, causing other dependencies to become | ||
368 | // dependent on the exclusive stream. | ||
369 | if priority.Exclusive { | ||
370 | k := parent.kids | ||
371 | for k != nil { | ||
372 | next := k.next | ||
373 | if k != n { | ||
374 | k.setParent(n) | ||
375 | } | ||
376 | k = next | ||
377 | } | ||
378 | } | ||
379 | |||
380 | n.setParent(parent) | ||
381 | n.weight = priority.Weight | ||
382 | } | ||
383 | |||
384 | func (ws *priorityWriteScheduler) Push(wr FrameWriteRequest) { | ||
385 | var n *priorityNode | ||
386 | if id := wr.StreamID(); id == 0 { | ||
387 | n = &ws.root | ||
388 | } else { | ||
389 | n = ws.nodes[id] | ||
390 | if n == nil { | ||
391 | // id is an idle or closed stream. wr should not be a HEADERS or | ||
392 | // DATA frame. However, wr can be a RST_STREAM. In this case, we | ||
393 | // push wr onto the root, rather than creating a new priorityNode, | ||
394 | // since RST_STREAM is tiny and the stream's priority is unknown | ||
395 | // anyway. See issue #17919. | ||
396 | if wr.DataSize() > 0 { | ||
397 | panic("add DATA on non-open stream") | ||
398 | } | ||
399 | n = &ws.root | ||
400 | } | ||
401 | } | ||
402 | n.q.push(wr) | ||
403 | } | ||
404 | |||
405 | func (ws *priorityWriteScheduler) Pop() (wr FrameWriteRequest, ok bool) { | ||
406 | ws.root.walkReadyInOrder(false, &ws.tmp, func(n *priorityNode, openParent bool) bool { | ||
407 | limit := int32(math.MaxInt32) | ||
408 | if openParent { | ||
409 | limit = ws.writeThrottleLimit | ||
410 | } | ||
411 | wr, ok = n.q.consume(limit) | ||
412 | if !ok { | ||
413 | return false | ||
414 | } | ||
415 | n.addBytes(int64(wr.DataSize())) | ||
416 | // If B depends on A and B continuously has data available but A | ||
417 | // does not, gradually increase the throttling limit to allow B to | ||
418 | // steal more and more bandwidth from A. | ||
419 | if openParent { | ||
420 | ws.writeThrottleLimit += 1024 | ||
421 | if ws.writeThrottleLimit < 0 { | ||
422 | ws.writeThrottleLimit = math.MaxInt32 | ||
423 | } | ||
424 | } else if ws.enableWriteThrottle { | ||
425 | ws.writeThrottleLimit = 1024 | ||
426 | } | ||
427 | return true | ||
428 | }) | ||
429 | return wr, ok | ||
430 | } | ||
431 | |||
432 | func (ws *priorityWriteScheduler) addClosedOrIdleNode(list *[]*priorityNode, maxSize int, n *priorityNode) { | ||
433 | if maxSize == 0 { | ||
434 | return | ||
435 | } | ||
436 | if len(*list) == maxSize { | ||
437 | // Remove the oldest node, then shift left. | ||
438 | ws.removeNode((*list)[0]) | ||
439 | x := (*list)[1:] | ||
440 | copy(*list, x) | ||
441 | *list = (*list)[:len(x)] | ||
442 | } | ||
443 | *list = append(*list, n) | ||
444 | } | ||
445 | |||
446 | func (ws *priorityWriteScheduler) removeNode(n *priorityNode) { | ||
447 | for k := n.kids; k != nil; k = k.next { | ||
448 | k.setParent(n.parent) | ||
449 | } | ||
450 | n.setParent(nil) | ||
451 | delete(ws.nodes, n.id) | ||
452 | } | ||
diff --git a/vendor/golang.org/x/net/http2/writesched_random.go b/vendor/golang.org/x/net/http2/writesched_random.go new file mode 100644 index 0000000..36d7919 --- /dev/null +++ b/vendor/golang.org/x/net/http2/writesched_random.go | |||
@@ -0,0 +1,72 @@ | |||
1 | // Copyright 2014 The Go Authors. All rights reserved. | ||
2 | // Use of this source code is governed by a BSD-style | ||
3 | // license that can be found in the LICENSE file. | ||
4 | |||
5 | package http2 | ||
6 | |||
7 | import "math" | ||
8 | |||
9 | // NewRandomWriteScheduler constructs a WriteScheduler that ignores HTTP/2 | ||
10 | // priorities. Control frames like SETTINGS and PING are written before DATA | ||
11 | // frames, but if no control frames are queued and multiple streams have queued | ||
12 | // HEADERS or DATA frames, Pop selects a ready stream arbitrarily. | ||
13 | func NewRandomWriteScheduler() WriteScheduler { | ||
14 | return &randomWriteScheduler{sq: make(map[uint32]*writeQueue)} | ||
15 | } | ||
16 | |||
17 | type randomWriteScheduler struct { | ||
18 | // zero are frames not associated with a specific stream. | ||
19 | zero writeQueue | ||
20 | |||
21 | // sq contains the stream-specific queues, keyed by stream ID. | ||
22 | // When a stream is idle or closed, it's deleted from the map. | ||
23 | sq map[uint32]*writeQueue | ||
24 | |||
25 | // pool of empty queues for reuse. | ||
26 | queuePool writeQueuePool | ||
27 | } | ||
28 | |||
29 | func (ws *randomWriteScheduler) OpenStream(streamID uint32, options OpenStreamOptions) { | ||
30 | // no-op: idle streams are not tracked | ||
31 | } | ||
32 | |||
33 | func (ws *randomWriteScheduler) CloseStream(streamID uint32) { | ||
34 | q, ok := ws.sq[streamID] | ||
35 | if !ok { | ||
36 | return | ||
37 | } | ||
38 | delete(ws.sq, streamID) | ||
39 | ws.queuePool.put(q) | ||
40 | } | ||
41 | |||
42 | func (ws *randomWriteScheduler) AdjustStream(streamID uint32, priority PriorityParam) { | ||
43 | // no-op: priorities are ignored | ||
44 | } | ||
45 | |||
46 | func (ws *randomWriteScheduler) Push(wr FrameWriteRequest) { | ||
47 | id := wr.StreamID() | ||
48 | if id == 0 { | ||
49 | ws.zero.push(wr) | ||
50 | return | ||
51 | } | ||
52 | q, ok := ws.sq[id] | ||
53 | if !ok { | ||
54 | q = ws.queuePool.get() | ||
55 | ws.sq[id] = q | ||
56 | } | ||
57 | q.push(wr) | ||
58 | } | ||
59 | |||
60 | func (ws *randomWriteScheduler) Pop() (FrameWriteRequest, bool) { | ||
61 | // Control frames first. | ||
62 | if !ws.zero.empty() { | ||
63 | return ws.zero.shift(), true | ||
64 | } | ||
65 | // Iterate over all non-idle streams until finding one that can be consumed. | ||
66 | for _, q := range ws.sq { | ||
67 | if wr, ok := q.consume(math.MaxInt32); ok { | ||
68 | return wr, true | ||
69 | } | ||
70 | } | ||
71 | return FrameWriteRequest{}, false | ||
72 | } | ||
diff --git a/vendor/golang.org/x/net/idna/idna.go b/vendor/golang.org/x/net/idna/idna.go new file mode 100644 index 0000000..ec8232b --- /dev/null +++ b/vendor/golang.org/x/net/idna/idna.go | |||
@@ -0,0 +1,680 @@ | |||
1 | // Code generated by running "go generate" in golang.org/x/text. DO NOT EDIT. | ||
2 | |||
3 | // Copyright 2016 The Go Authors. All rights reserved. | ||
4 | // Use of this source code is governed by a BSD-style | ||
5 | // license that can be found in the LICENSE file. | ||
6 | |||
7 | // Package idna implements IDNA2008 using the compatibility processing | ||
8 | // defined by UTS (Unicode Technical Standard) #46, which defines a standard to | ||
9 | // deal with the transition from IDNA2003. | ||
10 | // | ||
11 | // IDNA2008 (Internationalized Domain Names for Applications), is defined in RFC | ||
12 | // 5890, RFC 5891, RFC 5892, RFC 5893 and RFC 5894. | ||
13 | // UTS #46 is defined in http://www.unicode.org/reports/tr46. | ||
14 | // See http://unicode.org/cldr/utility/idna.jsp for a visualization of the | ||
15 | // differences between these two standards. | ||
16 | package idna // import "golang.org/x/net/idna" | ||
17 | |||
18 | import ( | ||
19 | "fmt" | ||
20 | "strings" | ||
21 | "unicode/utf8" | ||
22 | |||
23 | "golang.org/x/text/secure/bidirule" | ||
24 | "golang.org/x/text/unicode/norm" | ||
25 | ) | ||
26 | |||
27 | // NOTE: Unlike common practice in Go APIs, the functions will return a | ||
28 | // sanitized domain name in case of errors. Browsers sometimes use a partially | ||
29 | // evaluated string as lookup. | ||
30 | // TODO: the current error handling is, in my opinion, the least opinionated. | ||
31 | // Other strategies are also viable, though: | ||
32 | // Option 1) Return an empty string in case of error, but allow the user to | ||
33 | // specify explicitly which errors to ignore. | ||
34 | // Option 2) Return the partially evaluated string if it is itself a valid | ||
35 | // string, otherwise return the empty string in case of error. | ||
36 | // Option 3) Option 1 and 2. | ||
37 | // Option 4) Always return an empty string for now and implement Option 1 as | ||
38 | // needed, and document that the return string may not be empty in case of | ||
39 | // error in the future. | ||
40 | // I think Option 1 is best, but it is quite opinionated. | ||
41 | |||
42 | // ToASCII is a wrapper for Punycode.ToASCII. | ||
43 | func ToASCII(s string) (string, error) { | ||
44 | return Punycode.process(s, true) | ||
45 | } | ||
46 | |||
47 | // ToUnicode is a wrapper for Punycode.ToUnicode. | ||
48 | func ToUnicode(s string) (string, error) { | ||
49 | return Punycode.process(s, false) | ||
50 | } | ||
51 | |||
52 | // An Option configures a Profile at creation time. | ||
53 | type Option func(*options) | ||
54 | |||
55 | // Transitional sets a Profile to use the Transitional mapping as defined in UTS | ||
56 | // #46. This will cause, for example, "ß" to be mapped to "ss". Using the | ||
57 | // transitional mapping provides a compromise between IDNA2003 and IDNA2008 | ||
58 | // compatibility. It is used by most browsers when resolving domain names. This | ||
59 | // option is only meaningful if combined with MapForLookup. | ||
60 | func Transitional(transitional bool) Option { | ||
61 | return func(o *options) { o.transitional = true } | ||
62 | } | ||
63 | |||
64 | // VerifyDNSLength sets whether a Profile should fail if any of the IDN parts | ||
65 | // are longer than allowed by the RFC. | ||
66 | func VerifyDNSLength(verify bool) Option { | ||
67 | return func(o *options) { o.verifyDNSLength = verify } | ||
68 | } | ||
69 | |||
70 | // RemoveLeadingDots removes leading label separators. Leading runes that map to | ||
71 | // dots, such as U+3002, are removed as well. | ||
72 | // | ||
73 | // This is the behavior suggested by the UTS #46 and is adopted by some | ||
74 | // browsers. | ||
75 | func RemoveLeadingDots(remove bool) Option { | ||
76 | return func(o *options) { o.removeLeadingDots = remove } | ||
77 | } | ||
78 | |||
79 | // ValidateLabels sets whether to check the mandatory label validation criteria | ||
80 | // as defined in Section 5.4 of RFC 5891. This includes testing for correct use | ||
81 | // of hyphens ('-'), normalization, validity of runes, and the context rules. | ||
82 | func ValidateLabels(enable bool) Option { | ||
83 | return func(o *options) { | ||
84 | // Don't override existing mappings, but set one that at least checks | ||
85 | // normalization if it is not set. | ||
86 | if o.mapping == nil && enable { | ||
87 | o.mapping = normalize | ||
88 | } | ||
89 | o.trie = trie | ||
90 | o.validateLabels = enable | ||
91 | o.fromPuny = validateFromPunycode | ||
92 | } | ||
93 | } | ||
94 | |||
95 | // StrictDomainName limits the set of permissable ASCII characters to those | ||
96 | // allowed in domain names as defined in RFC 1034 (A-Z, a-z, 0-9 and the | ||
97 | // hyphen). This is set by default for MapForLookup and ValidateForRegistration. | ||
98 | // | ||
99 | // This option is useful, for instance, for browsers that allow characters | ||
100 | // outside this range, for example a '_' (U+005F LOW LINE). See | ||
101 | // http://www.rfc-editor.org/std/std3.txt for more details This option | ||
102 | // corresponds to the UseSTD3ASCIIRules option in UTS #46. | ||
103 | func StrictDomainName(use bool) Option { | ||
104 | return func(o *options) { | ||
105 | o.trie = trie | ||
106 | o.useSTD3Rules = use | ||
107 | o.fromPuny = validateFromPunycode | ||
108 | } | ||
109 | } | ||
110 | |||
111 | // NOTE: the following options pull in tables. The tables should not be linked | ||
112 | // in as long as the options are not used. | ||
113 | |||
114 | // BidiRule enables the Bidi rule as defined in RFC 5893. Any application | ||
115 | // that relies on proper validation of labels should include this rule. | ||
116 | func BidiRule() Option { | ||
117 | return func(o *options) { o.bidirule = bidirule.ValidString } | ||
118 | } | ||
119 | |||
120 | // ValidateForRegistration sets validation options to verify that a given IDN is | ||
121 | // properly formatted for registration as defined by Section 4 of RFC 5891. | ||
122 | func ValidateForRegistration() Option { | ||
123 | return func(o *options) { | ||
124 | o.mapping = validateRegistration | ||
125 | StrictDomainName(true)(o) | ||
126 | ValidateLabels(true)(o) | ||
127 | VerifyDNSLength(true)(o) | ||
128 | BidiRule()(o) | ||
129 | } | ||
130 | } | ||
131 | |||
132 | // MapForLookup sets validation and mapping options such that a given IDN is | ||
133 | // transformed for domain name lookup according to the requirements set out in | ||
134 | // Section 5 of RFC 5891. The mappings follow the recommendations of RFC 5894, | ||
135 | // RFC 5895 and UTS 46. It does not add the Bidi Rule. Use the BidiRule option | ||
136 | // to add this check. | ||
137 | // | ||
138 | // The mappings include normalization and mapping case, width and other | ||
139 | // compatibility mappings. | ||
140 | func MapForLookup() Option { | ||
141 | return func(o *options) { | ||
142 | o.mapping = validateAndMap | ||
143 | StrictDomainName(true)(o) | ||
144 | ValidateLabels(true)(o) | ||
145 | RemoveLeadingDots(true)(o) | ||
146 | } | ||
147 | } | ||
148 | |||
149 | type options struct { | ||
150 | transitional bool | ||
151 | useSTD3Rules bool | ||
152 | validateLabels bool | ||
153 | verifyDNSLength bool | ||
154 | removeLeadingDots bool | ||
155 | |||
156 | trie *idnaTrie | ||
157 | |||
158 | // fromPuny calls validation rules when converting A-labels to U-labels. | ||
159 | fromPuny func(p *Profile, s string) error | ||
160 | |||
161 | // mapping implements a validation and mapping step as defined in RFC 5895 | ||
162 | // or UTS 46, tailored to, for example, domain registration or lookup. | ||
163 | mapping func(p *Profile, s string) (string, error) | ||
164 | |||
165 | // bidirule, if specified, checks whether s conforms to the Bidi Rule | ||
166 | // defined in RFC 5893. | ||
167 | bidirule func(s string) bool | ||
168 | } | ||
169 | |||
170 | // A Profile defines the configuration of an IDNA mapper. | ||
171 | type Profile struct { | ||
172 | options | ||
173 | } | ||
174 | |||
175 | func apply(o *options, opts []Option) { | ||
176 | for _, f := range opts { | ||
177 | f(o) | ||
178 | } | ||
179 | } | ||
180 | |||
181 | // New creates a new Profile. | ||
182 | // | ||
183 | // With no options, the returned Profile is the most permissive and equals the | ||
184 | // Punycode Profile. Options can be passed to further restrict the Profile. The | ||
185 | // MapForLookup and ValidateForRegistration options set a collection of options, | ||
186 | // for lookup and registration purposes respectively, which can be tailored by | ||
187 | // adding more fine-grained options, where later options override earlier | ||
188 | // options. | ||
189 | func New(o ...Option) *Profile { | ||
190 | p := &Profile{} | ||
191 | apply(&p.options, o) | ||
192 | return p | ||
193 | } | ||
194 | |||
195 | // ToASCII converts a domain or domain label to its ASCII form. For example, | ||
196 | // ToASCII("bücher.example.com") is "xn--bcher-kva.example.com", and | ||
197 | // ToASCII("golang") is "golang". If an error is encountered it will return | ||
198 | // an error and a (partially) processed result. | ||
199 | func (p *Profile) ToASCII(s string) (string, error) { | ||
200 | return p.process(s, true) | ||
201 | } | ||
202 | |||
203 | // ToUnicode converts a domain or domain label to its Unicode form. For example, | ||
204 | // ToUnicode("xn--bcher-kva.example.com") is "bücher.example.com", and | ||
205 | // ToUnicode("golang") is "golang". If an error is encountered it will return | ||
206 | // an error and a (partially) processed result. | ||
207 | func (p *Profile) ToUnicode(s string) (string, error) { | ||
208 | pp := *p | ||
209 | pp.transitional = false | ||
210 | return pp.process(s, false) | ||
211 | } | ||
212 | |||
213 | // String reports a string with a description of the profile for debugging | ||
214 | // purposes. The string format may change with different versions. | ||
215 | func (p *Profile) String() string { | ||
216 | s := "" | ||
217 | if p.transitional { | ||
218 | s = "Transitional" | ||
219 | } else { | ||
220 | s = "NonTransitional" | ||
221 | } | ||
222 | if p.useSTD3Rules { | ||
223 | s += ":UseSTD3Rules" | ||
224 | } | ||
225 | if p.validateLabels { | ||
226 | s += ":ValidateLabels" | ||
227 | } | ||
228 | if p.verifyDNSLength { | ||
229 | s += ":VerifyDNSLength" | ||
230 | } | ||
231 | return s | ||
232 | } | ||
233 | |||
234 | var ( | ||
235 | // Punycode is a Profile that does raw punycode processing with a minimum | ||
236 | // of validation. | ||
237 | Punycode *Profile = punycode | ||
238 | |||
239 | // Lookup is the recommended profile for looking up domain names, according | ||
240 | // to Section 5 of RFC 5891. The exact configuration of this profile may | ||
241 | // change over time. | ||
242 | Lookup *Profile = lookup | ||
243 | |||
244 | // Display is the recommended profile for displaying domain names. | ||
245 | // The configuration of this profile may change over time. | ||
246 | Display *Profile = display | ||
247 | |||
248 | // Registration is the recommended profile for checking whether a given | ||
249 | // IDN is valid for registration, according to Section 4 of RFC 5891. | ||
250 | Registration *Profile = registration | ||
251 | |||
252 | punycode = &Profile{} | ||
253 | lookup = &Profile{options{ | ||
254 | transitional: true, | ||
255 | useSTD3Rules: true, | ||
256 | validateLabels: true, | ||
257 | removeLeadingDots: true, | ||
258 | trie: trie, | ||
259 | fromPuny: validateFromPunycode, | ||
260 | mapping: validateAndMap, | ||
261 | bidirule: bidirule.ValidString, | ||
262 | }} | ||
263 | display = &Profile{options{ | ||
264 | useSTD3Rules: true, | ||
265 | validateLabels: true, | ||
266 | removeLeadingDots: true, | ||
267 | trie: trie, | ||
268 | fromPuny: validateFromPunycode, | ||
269 | mapping: validateAndMap, | ||
270 | bidirule: bidirule.ValidString, | ||
271 | }} | ||
272 | registration = &Profile{options{ | ||
273 | useSTD3Rules: true, | ||
274 | validateLabels: true, | ||
275 | verifyDNSLength: true, | ||
276 | trie: trie, | ||
277 | fromPuny: validateFromPunycode, | ||
278 | mapping: validateRegistration, | ||
279 | bidirule: bidirule.ValidString, | ||
280 | }} | ||
281 | |||
282 | // TODO: profiles | ||
283 | // Register: recommended for approving domain names: don't do any mappings | ||
284 | // but rather reject on invalid input. Bundle or block deviation characters. | ||
285 | ) | ||
286 | |||
287 | type labelError struct{ label, code_ string } | ||
288 | |||
289 | func (e labelError) code() string { return e.code_ } | ||
290 | func (e labelError) Error() string { | ||
291 | return fmt.Sprintf("idna: invalid label %q", e.label) | ||
292 | } | ||
293 | |||
294 | type runeError rune | ||
295 | |||
296 | func (e runeError) code() string { return "P1" } | ||
297 | func (e runeError) Error() string { | ||
298 | return fmt.Sprintf("idna: disallowed rune %U", e) | ||
299 | } | ||
300 | |||
301 | // process implements the algorithm described in section 4 of UTS #46, | ||
302 | // see http://www.unicode.org/reports/tr46. | ||
303 | func (p *Profile) process(s string, toASCII bool) (string, error) { | ||
304 | var err error | ||
305 | if p.mapping != nil { | ||
306 | s, err = p.mapping(p, s) | ||
307 | } | ||
308 | // Remove leading empty labels. | ||
309 | if p.removeLeadingDots { | ||
310 | for ; len(s) > 0 && s[0] == '.'; s = s[1:] { | ||
311 | } | ||
312 | } | ||
313 | // It seems like we should only create this error on ToASCII, but the | ||
314 | // UTS 46 conformance tests suggests we should always check this. | ||
315 | if err == nil && p.verifyDNSLength && s == "" { | ||
316 | err = &labelError{s, "A4"} | ||
317 | } | ||
318 | labels := labelIter{orig: s} | ||
319 | for ; !labels.done(); labels.next() { | ||
320 | label := labels.label() | ||
321 | if label == "" { | ||
322 | // Empty labels are not okay. The label iterator skips the last | ||
323 | // label if it is empty. | ||
324 | if err == nil && p.verifyDNSLength { | ||
325 | err = &labelError{s, "A4"} | ||
326 | } | ||
327 | continue | ||
328 | } | ||
329 | if strings.HasPrefix(label, acePrefix) { | ||
330 | u, err2 := decode(label[len(acePrefix):]) | ||
331 | if err2 != nil { | ||
332 | if err == nil { | ||
333 | err = err2 | ||
334 | } | ||
335 | // Spec says keep the old label. | ||
336 | continue | ||
337 | } | ||
338 | labels.set(u) | ||
339 | if err == nil && p.validateLabels { | ||
340 | err = p.fromPuny(p, u) | ||
341 | } | ||
342 | if err == nil { | ||
343 | // This should be called on NonTransitional, according to the | ||
344 | // spec, but that currently does not have any effect. Use the | ||
345 | // original profile to preserve options. | ||
346 | err = p.validateLabel(u) | ||
347 | } | ||
348 | } else if err == nil { | ||
349 | err = p.validateLabel(label) | ||
350 | } | ||
351 | } | ||
352 | if toASCII { | ||
353 | for labels.reset(); !labels.done(); labels.next() { | ||
354 | label := labels.label() | ||
355 | if !ascii(label) { | ||
356 | a, err2 := encode(acePrefix, label) | ||
357 | if err == nil { | ||
358 | err = err2 | ||
359 | } | ||
360 | label = a | ||
361 | labels.set(a) | ||
362 | } | ||
363 | n := len(label) | ||
364 | if p.verifyDNSLength && err == nil && (n == 0 || n > 63) { | ||
365 | err = &labelError{label, "A4"} | ||
366 | } | ||
367 | } | ||
368 | } | ||
369 | s = labels.result() | ||
370 | if toASCII && p.verifyDNSLength && err == nil { | ||
371 | // Compute the length of the domain name minus the root label and its dot. | ||
372 | n := len(s) | ||
373 | if n > 0 && s[n-1] == '.' { | ||
374 | n-- | ||
375 | } | ||
376 | if len(s) < 1 || n > 253 { | ||
377 | err = &labelError{s, "A4"} | ||
378 | } | ||
379 | } | ||
380 | return s, err | ||
381 | } | ||
382 | |||
383 | func normalize(p *Profile, s string) (string, error) { | ||
384 | return norm.NFC.String(s), nil | ||
385 | } | ||
386 | |||
387 | func validateRegistration(p *Profile, s string) (string, error) { | ||
388 | if !norm.NFC.IsNormalString(s) { | ||
389 | return s, &labelError{s, "V1"} | ||
390 | } | ||
391 | for i := 0; i < len(s); { | ||
392 | v, sz := trie.lookupString(s[i:]) | ||
393 | // Copy bytes not copied so far. | ||
394 | switch p.simplify(info(v).category()) { | ||
395 | // TODO: handle the NV8 defined in the Unicode idna data set to allow | ||
396 | // for strict conformance to IDNA2008. | ||
397 | case valid, deviation: | ||
398 | case disallowed, mapped, unknown, ignored: | ||
399 | r, _ := utf8.DecodeRuneInString(s[i:]) | ||
400 | return s, runeError(r) | ||
401 | } | ||
402 | i += sz | ||
403 | } | ||
404 | return s, nil | ||
405 | } | ||
406 | |||
407 | func validateAndMap(p *Profile, s string) (string, error) { | ||
408 | var ( | ||
409 | err error | ||
410 | b []byte | ||
411 | k int | ||
412 | ) | ||
413 | for i := 0; i < len(s); { | ||
414 | v, sz := trie.lookupString(s[i:]) | ||
415 | start := i | ||
416 | i += sz | ||
417 | // Copy bytes not copied so far. | ||
418 | switch p.simplify(info(v).category()) { | ||
419 | case valid: | ||
420 | continue | ||
421 | case disallowed: | ||
422 | if err == nil { | ||
423 | r, _ := utf8.DecodeRuneInString(s[start:]) | ||
424 | err = runeError(r) | ||
425 | } | ||
426 | continue | ||
427 | case mapped, deviation: | ||
428 | b = append(b, s[k:start]...) | ||
429 | b = info(v).appendMapping(b, s[start:i]) | ||
430 | case ignored: | ||
431 | b = append(b, s[k:start]...) | ||
432 | // drop the rune | ||
433 | case unknown: | ||
434 | b = append(b, s[k:start]...) | ||
435 | b = append(b, "\ufffd"...) | ||
436 | } | ||
437 | k = i | ||
438 | } | ||
439 | if k == 0 { | ||
440 | // No changes so far. | ||
441 | s = norm.NFC.String(s) | ||
442 | } else { | ||
443 | b = append(b, s[k:]...) | ||
444 | if norm.NFC.QuickSpan(b) != len(b) { | ||
445 | b = norm.NFC.Bytes(b) | ||
446 | } | ||
447 | // TODO: the punycode converters require strings as input. | ||
448 | s = string(b) | ||
449 | } | ||
450 | return s, err | ||
451 | } | ||
452 | |||
453 | // A labelIter allows iterating over domain name labels. | ||
454 | type labelIter struct { | ||
455 | orig string | ||
456 | slice []string | ||
457 | curStart int | ||
458 | curEnd int | ||
459 | i int | ||
460 | } | ||
461 | |||
462 | func (l *labelIter) reset() { | ||
463 | l.curStart = 0 | ||
464 | l.curEnd = 0 | ||
465 | l.i = 0 | ||
466 | } | ||
467 | |||
468 | func (l *labelIter) done() bool { | ||
469 | return l.curStart >= len(l.orig) | ||
470 | } | ||
471 | |||
472 | func (l *labelIter) result() string { | ||
473 | if l.slice != nil { | ||
474 | return strings.Join(l.slice, ".") | ||
475 | } | ||
476 | return l.orig | ||
477 | } | ||
478 | |||
479 | func (l *labelIter) label() string { | ||
480 | if l.slice != nil { | ||
481 | return l.slice[l.i] | ||
482 | } | ||
483 | p := strings.IndexByte(l.orig[l.curStart:], '.') | ||
484 | l.curEnd = l.curStart + p | ||
485 | if p == -1 { | ||
486 | l.curEnd = len(l.orig) | ||
487 | } | ||
488 | return l.orig[l.curStart:l.curEnd] | ||
489 | } | ||
490 | |||
491 | // next sets the value to the next label. It skips the last label if it is empty. | ||
492 | func (l *labelIter) next() { | ||
493 | l.i++ | ||
494 | if l.slice != nil { | ||
495 | if l.i >= len(l.slice) || l.i == len(l.slice)-1 && l.slice[l.i] == "" { | ||
496 | l.curStart = len(l.orig) | ||
497 | } | ||
498 | } else { | ||
499 | l.curStart = l.curEnd + 1 | ||
500 | if l.curStart == len(l.orig)-1 && l.orig[l.curStart] == '.' { | ||
501 | l.curStart = len(l.orig) | ||
502 | } | ||
503 | } | ||
504 | } | ||
505 | |||
506 | func (l *labelIter) set(s string) { | ||
507 | if l.slice == nil { | ||
508 | l.slice = strings.Split(l.orig, ".") | ||
509 | } | ||
510 | l.slice[l.i] = s | ||
511 | } | ||
512 | |||
513 | // acePrefix is the ASCII Compatible Encoding prefix. | ||
514 | const acePrefix = "xn--" | ||
515 | |||
516 | func (p *Profile) simplify(cat category) category { | ||
517 | switch cat { | ||
518 | case disallowedSTD3Mapped: | ||
519 | if p.useSTD3Rules { | ||
520 | cat = disallowed | ||
521 | } else { | ||
522 | cat = mapped | ||
523 | } | ||
524 | case disallowedSTD3Valid: | ||
525 | if p.useSTD3Rules { | ||
526 | cat = disallowed | ||
527 | } else { | ||
528 | cat = valid | ||
529 | } | ||
530 | case deviation: | ||
531 | if !p.transitional { | ||
532 | cat = valid | ||
533 | } | ||
534 | case validNV8, validXV8: | ||
535 | // TODO: handle V2008 | ||
536 | cat = valid | ||
537 | } | ||
538 | return cat | ||
539 | } | ||
540 | |||
541 | func validateFromPunycode(p *Profile, s string) error { | ||
542 | if !norm.NFC.IsNormalString(s) { | ||
543 | return &labelError{s, "V1"} | ||
544 | } | ||
545 | for i := 0; i < len(s); { | ||
546 | v, sz := trie.lookupString(s[i:]) | ||
547 | if c := p.simplify(info(v).category()); c != valid && c != deviation { | ||
548 | return &labelError{s, "V6"} | ||
549 | } | ||
550 | i += sz | ||
551 | } | ||
552 | return nil | ||
553 | } | ||
554 | |||
555 | const ( | ||
556 | zwnj = "\u200c" | ||
557 | zwj = "\u200d" | ||
558 | ) | ||
559 | |||
560 | type joinState int8 | ||
561 | |||
562 | const ( | ||
563 | stateStart joinState = iota | ||
564 | stateVirama | ||
565 | stateBefore | ||
566 | stateBeforeVirama | ||
567 | stateAfter | ||
568 | stateFAIL | ||
569 | ) | ||
570 | |||
571 | var joinStates = [][numJoinTypes]joinState{ | ||
572 | stateStart: { | ||
573 | joiningL: stateBefore, | ||
574 | joiningD: stateBefore, | ||
575 | joinZWNJ: stateFAIL, | ||
576 | joinZWJ: stateFAIL, | ||
577 | joinVirama: stateVirama, | ||
578 | }, | ||
579 | stateVirama: { | ||
580 | joiningL: stateBefore, | ||
581 | joiningD: stateBefore, | ||
582 | }, | ||
583 | stateBefore: { | ||
584 | joiningL: stateBefore, | ||
585 | joiningD: stateBefore, | ||
586 | joiningT: stateBefore, | ||
587 | joinZWNJ: stateAfter, | ||
588 | joinZWJ: stateFAIL, | ||
589 | joinVirama: stateBeforeVirama, | ||
590 | }, | ||
591 | stateBeforeVirama: { | ||
592 | joiningL: stateBefore, | ||
593 | joiningD: stateBefore, | ||
594 | joiningT: stateBefore, | ||
595 | }, | ||
596 | stateAfter: { | ||
597 | joiningL: stateFAIL, | ||
598 | joiningD: stateBefore, | ||
599 | joiningT: stateAfter, | ||
600 | joiningR: stateStart, | ||
601 | joinZWNJ: stateFAIL, | ||
602 | joinZWJ: stateFAIL, | ||
603 | joinVirama: stateAfter, // no-op as we can't accept joiners here | ||
604 | }, | ||
605 | stateFAIL: { | ||
606 | 0: stateFAIL, | ||
607 | joiningL: stateFAIL, | ||
608 | joiningD: stateFAIL, | ||
609 | joiningT: stateFAIL, | ||
610 | joiningR: stateFAIL, | ||
611 | joinZWNJ: stateFAIL, | ||
612 | joinZWJ: stateFAIL, | ||
613 | joinVirama: stateFAIL, | ||
614 | }, | ||
615 | } | ||
616 | |||
617 | // validateLabel validates the criteria from Section 4.1. Item 1, 4, and 6 are | ||
618 | // already implicitly satisfied by the overall implementation. | ||
619 | func (p *Profile) validateLabel(s string) error { | ||
620 | if s == "" { | ||
621 | if p.verifyDNSLength { | ||
622 | return &labelError{s, "A4"} | ||
623 | } | ||
624 | return nil | ||
625 | } | ||
626 | if p.bidirule != nil && !p.bidirule(s) { | ||
627 | return &labelError{s, "B"} | ||
628 | } | ||
629 | if !p.validateLabels { | ||
630 | return nil | ||
631 | } | ||
632 | trie := p.trie // p.validateLabels is only set if trie is set. | ||
633 | if len(s) > 4 && s[2] == '-' && s[3] == '-' { | ||
634 | return &labelError{s, "V2"} | ||
635 | } | ||
636 | if s[0] == '-' || s[len(s)-1] == '-' { | ||
637 | return &labelError{s, "V3"} | ||
638 | } | ||
639 | // TODO: merge the use of this in the trie. | ||
640 | v, sz := trie.lookupString(s) | ||
641 | x := info(v) | ||
642 | if x.isModifier() { | ||
643 | return &labelError{s, "V5"} | ||
644 | } | ||
645 | // Quickly return in the absence of zero-width (non) joiners. | ||
646 | if strings.Index(s, zwj) == -1 && strings.Index(s, zwnj) == -1 { | ||
647 | return nil | ||
648 | } | ||
649 | st := stateStart | ||
650 | for i := 0; ; { | ||
651 | jt := x.joinType() | ||
652 | if s[i:i+sz] == zwj { | ||
653 | jt = joinZWJ | ||
654 | } else if s[i:i+sz] == zwnj { | ||
655 | jt = joinZWNJ | ||
656 | } | ||
657 | st = joinStates[st][jt] | ||
658 | if x.isViramaModifier() { | ||
659 | st = joinStates[st][joinVirama] | ||
660 | } | ||
661 | if i += sz; i == len(s) { | ||
662 | break | ||
663 | } | ||
664 | v, sz = trie.lookupString(s[i:]) | ||
665 | x = info(v) | ||
666 | } | ||
667 | if st == stateFAIL || st == stateAfter { | ||
668 | return &labelError{s, "C"} | ||
669 | } | ||
670 | return nil | ||
671 | } | ||
672 | |||
673 | func ascii(s string) bool { | ||
674 | for i := 0; i < len(s); i++ { | ||
675 | if s[i] >= utf8.RuneSelf { | ||
676 | return false | ||
677 | } | ||
678 | } | ||
679 | return true | ||
680 | } | ||
diff --git a/vendor/golang.org/x/net/idna/punycode.go b/vendor/golang.org/x/net/idna/punycode.go new file mode 100644 index 0000000..02c7d59 --- /dev/null +++ b/vendor/golang.org/x/net/idna/punycode.go | |||
@@ -0,0 +1,203 @@ | |||
1 | // Code generated by running "go generate" in golang.org/x/text. DO NOT EDIT. | ||
2 | |||
3 | // Copyright 2016 The Go Authors. All rights reserved. | ||
4 | // Use of this source code is governed by a BSD-style | ||
5 | // license that can be found in the LICENSE file. | ||
6 | |||
7 | package idna | ||
8 | |||
9 | // This file implements the Punycode algorithm from RFC 3492. | ||
10 | |||
11 | import ( | ||
12 | "math" | ||
13 | "strings" | ||
14 | "unicode/utf8" | ||
15 | ) | ||
16 | |||
17 | // These parameter values are specified in section 5. | ||
18 | // | ||
19 | // All computation is done with int32s, so that overflow behavior is identical | ||
20 | // regardless of whether int is 32-bit or 64-bit. | ||
21 | const ( | ||
22 | base int32 = 36 | ||
23 | damp int32 = 700 | ||
24 | initialBias int32 = 72 | ||
25 | initialN int32 = 128 | ||
26 | skew int32 = 38 | ||
27 | tmax int32 = 26 | ||
28 | tmin int32 = 1 | ||
29 | ) | ||
30 | |||
31 | func punyError(s string) error { return &labelError{s, "A3"} } | ||
32 | |||
33 | // decode decodes a string as specified in section 6.2. | ||
34 | func decode(encoded string) (string, error) { | ||
35 | if encoded == "" { | ||
36 | return "", nil | ||
37 | } | ||
38 | pos := 1 + strings.LastIndex(encoded, "-") | ||
39 | if pos == 1 { | ||
40 | return "", punyError(encoded) | ||
41 | } | ||
42 | if pos == len(encoded) { | ||
43 | return encoded[:len(encoded)-1], nil | ||
44 | } | ||
45 | output := make([]rune, 0, len(encoded)) | ||
46 | if pos != 0 { | ||
47 | for _, r := range encoded[:pos-1] { | ||
48 | output = append(output, r) | ||
49 | } | ||
50 | } | ||
51 | i, n, bias := int32(0), initialN, initialBias | ||
52 | for pos < len(encoded) { | ||
53 | oldI, w := i, int32(1) | ||
54 | for k := base; ; k += base { | ||
55 | if pos == len(encoded) { | ||
56 | return "", punyError(encoded) | ||
57 | } | ||
58 | digit, ok := decodeDigit(encoded[pos]) | ||
59 | if !ok { | ||
60 | return "", punyError(encoded) | ||
61 | } | ||
62 | pos++ | ||
63 | i += digit * w | ||
64 | if i < 0 { | ||
65 | return "", punyError(encoded) | ||
66 | } | ||
67 | t := k - bias | ||
68 | if t < tmin { | ||
69 | t = tmin | ||
70 | } else if t > tmax { | ||
71 | t = tmax | ||
72 | } | ||
73 | if digit < t { | ||
74 | break | ||
75 | } | ||
76 | w *= base - t | ||
77 | if w >= math.MaxInt32/base { | ||
78 | return "", punyError(encoded) | ||
79 | } | ||
80 | } | ||
81 | x := int32(len(output) + 1) | ||
82 | bias = adapt(i-oldI, x, oldI == 0) | ||
83 | n += i / x | ||
84 | i %= x | ||
85 | if n > utf8.MaxRune || len(output) >= 1024 { | ||
86 | return "", punyError(encoded) | ||
87 | } | ||
88 | output = append(output, 0) | ||
89 | copy(output[i+1:], output[i:]) | ||
90 | output[i] = n | ||
91 | i++ | ||
92 | } | ||
93 | return string(output), nil | ||
94 | } | ||
95 | |||
96 | // encode encodes a string as specified in section 6.3 and prepends prefix to | ||
97 | // the result. | ||
98 | // | ||
99 | // The "while h < length(input)" line in the specification becomes "for | ||
100 | // remaining != 0" in the Go code, because len(s) in Go is in bytes, not runes. | ||
101 | func encode(prefix, s string) (string, error) { | ||
102 | output := make([]byte, len(prefix), len(prefix)+1+2*len(s)) | ||
103 | copy(output, prefix) | ||
104 | delta, n, bias := int32(0), initialN, initialBias | ||
105 | b, remaining := int32(0), int32(0) | ||
106 | for _, r := range s { | ||
107 | if r < 0x80 { | ||
108 | b++ | ||
109 | output = append(output, byte(r)) | ||
110 | } else { | ||
111 | remaining++ | ||
112 | } | ||
113 | } | ||
114 | h := b | ||
115 | if b > 0 { | ||
116 | output = append(output, '-') | ||
117 | } | ||
118 | for remaining != 0 { | ||
119 | m := int32(0x7fffffff) | ||
120 | for _, r := range s { | ||
121 | if m > r && r >= n { | ||
122 | m = r | ||
123 | } | ||
124 | } | ||
125 | delta += (m - n) * (h + 1) | ||
126 | if delta < 0 { | ||
127 | return "", punyError(s) | ||
128 | } | ||
129 | n = m | ||
130 | for _, r := range s { | ||
131 | if r < n { | ||
132 | delta++ | ||
133 | if delta < 0 { | ||
134 | return "", punyError(s) | ||
135 | } | ||
136 | continue | ||
137 | } | ||
138 | if r > n { | ||
139 | continue | ||
140 | } | ||
141 | q := delta | ||
142 | for k := base; ; k += base { | ||
143 | t := k - bias | ||
144 | if t < tmin { | ||
145 | t = tmin | ||
146 | } else if t > tmax { | ||
147 | t = tmax | ||
148 | } | ||
149 | if q < t { | ||
150 | break | ||
151 | } | ||
152 | output = append(output, encodeDigit(t+(q-t)%(base-t))) | ||
153 | q = (q - t) / (base - t) | ||
154 | } | ||
155 | output = append(output, encodeDigit(q)) | ||
156 | bias = adapt(delta, h+1, h == b) | ||
157 | delta = 0 | ||
158 | h++ | ||
159 | remaining-- | ||
160 | } | ||
161 | delta++ | ||
162 | n++ | ||
163 | } | ||
164 | return string(output), nil | ||
165 | } | ||
166 | |||
167 | func decodeDigit(x byte) (digit int32, ok bool) { | ||
168 | switch { | ||
169 | case '0' <= x && x <= '9': | ||
170 | return int32(x - ('0' - 26)), true | ||
171 | case 'A' <= x && x <= 'Z': | ||
172 | return int32(x - 'A'), true | ||
173 | case 'a' <= x && x <= 'z': | ||
174 | return int32(x - 'a'), true | ||
175 | } | ||
176 | return 0, false | ||
177 | } | ||
178 | |||
179 | func encodeDigit(digit int32) byte { | ||
180 | switch { | ||
181 | case 0 <= digit && digit < 26: | ||
182 | return byte(digit + 'a') | ||
183 | case 26 <= digit && digit < 36: | ||
184 | return byte(digit + ('0' - 26)) | ||
185 | } | ||
186 | panic("idna: internal error in punycode encoding") | ||
187 | } | ||
188 | |||
189 | // adapt is the bias adaptation function specified in section 6.1. | ||
190 | func adapt(delta, numPoints int32, firstTime bool) int32 { | ||
191 | if firstTime { | ||
192 | delta /= damp | ||
193 | } else { | ||
194 | delta /= 2 | ||
195 | } | ||
196 | delta += delta / numPoints | ||
197 | k := int32(0) | ||
198 | for delta > ((base-tmin)*tmax)/2 { | ||
199 | delta /= base - tmin | ||
200 | k += base | ||
201 | } | ||
202 | return k + (base-tmin+1)*delta/(delta+skew) | ||
203 | } | ||
diff --git a/vendor/golang.org/x/net/idna/tables.go b/vendor/golang.org/x/net/idna/tables.go new file mode 100644 index 0000000..d281934 --- /dev/null +++ b/vendor/golang.org/x/net/idna/tables.go | |||
@@ -0,0 +1,4477 @@ | |||
1 | // Code generated by running "go generate" in golang.org/x/text. DO NOT EDIT. | ||
2 | |||
3 | package idna | ||
4 | |||
5 | // UnicodeVersion is the Unicode version from which the tables in this package are derived. | ||
6 | const UnicodeVersion = "9.0.0" | ||
7 | |||
8 | var mappings string = "" + // Size: 8176 bytes | ||
9 | "\x00\x01 \x03 ̈\x01a\x03 ̄\x012\x013\x03 ́\x03 ̧\x011\x01o\x051⁄4\x051⁄2" + | ||
10 | "\x053⁄4\x03i̇\x03l·\x03ʼn\x01s\x03dž\x03ⱥ\x03ⱦ\x01h\x01j\x01r\x01w\x01y" + | ||
11 | "\x03 ̆\x03 ̇\x03 ̊\x03 ̨\x03 ̃\x03 ̋\x01l\x01x\x04̈́\x03 ι\x01;\x05 ̈́" + | ||
12 | "\x04եւ\x04اٴ\x04وٴ\x04ۇٴ\x04يٴ\x06क़\x06ख़\x06ग़\x06ज़\x06ड़\x06ढ़\x06फ़" + | ||
13 | "\x06य़\x06ড়\x06ঢ়\x06য়\x06ਲ਼\x06ਸ਼\x06ਖ਼\x06ਗ਼\x06ਜ਼\x06ਫ਼\x06ଡ଼\x06ଢ଼" + | ||
14 | "\x06ํา\x06ໍາ\x06ຫນ\x06ຫມ\x06གྷ\x06ཌྷ\x06དྷ\x06བྷ\x06ཛྷ\x06ཀྵ\x06ཱི\x06ཱུ" + | ||
15 | "\x06ྲྀ\x09ྲཱྀ\x06ླྀ\x09ླཱྀ\x06ཱྀ\x06ྒྷ\x06ྜྷ\x06ྡྷ\x06ྦྷ\x06ྫྷ\x06ྐྵ\x02" + | ||
16 | "в\x02д\x02о\x02с\x02т\x02ъ\x02ѣ\x02æ\x01b\x01d\x01e\x02ǝ\x01g\x01i\x01k" + | ||
17 | "\x01m\x01n\x02ȣ\x01p\x01t\x01u\x02ɐ\x02ɑ\x02ə\x02ɛ\x02ɜ\x02ŋ\x02ɔ\x02ɯ" + | ||
18 | "\x01v\x02β\x02γ\x02δ\x02φ\x02χ\x02ρ\x02н\x02ɒ\x01c\x02ɕ\x02ð\x01f\x02ɟ" + | ||
19 | "\x02ɡ\x02ɥ\x02ɨ\x02ɩ\x02ɪ\x02ʝ\x02ɭ\x02ʟ\x02ɱ\x02ɰ\x02ɲ\x02ɳ\x02ɴ\x02ɵ" + | ||
20 | "\x02ɸ\x02ʂ\x02ʃ\x02ƫ\x02ʉ\x02ʊ\x02ʋ\x02ʌ\x01z\x02ʐ\x02ʑ\x02ʒ\x02θ\x02ss" + | ||
21 | "\x02ά\x02έ\x02ή\x02ί\x02ό\x02ύ\x02ώ\x05ἀι\x05ἁι\x05ἂι\x05ἃι\x05ἄι\x05ἅι" + | ||
22 | "\x05ἆι\x05ἇι\x05ἠι\x05ἡι\x05ἢι\x05ἣι\x05ἤι\x05ἥι\x05ἦι\x05ἧι\x05ὠι\x05ὡι" + | ||
23 | "\x05ὢι\x05ὣι\x05ὤι\x05ὥι\x05ὦι\x05ὧι\x05ὰι\x04αι\x04άι\x05ᾶι\x02ι\x05 ̈͂" + | ||
24 | "\x05ὴι\x04ηι\x04ήι\x05ῆι\x05 ̓̀\x05 ̓́\x05 ̓͂\x02ΐ\x05 ̔̀\x05 ̔́\x05 ̔͂" + | ||
25 | "\x02ΰ\x05 ̈̀\x01`\x05ὼι\x04ωι\x04ώι\x05ῶι\x06′′\x09′′′\x06‵‵\x09‵‵‵\x02!" + | ||
26 | "!\x02??\x02?!\x02!?\x0c′′′′\x010\x014\x015\x016\x017\x018\x019\x01+\x01=" + | ||
27 | "\x01(\x01)\x02rs\x02ħ\x02no\x01q\x02sm\x02tm\x02ω\x02å\x02א\x02ב\x02ג" + | ||
28 | "\x02ד\x02π\x051⁄7\x051⁄9\x061⁄10\x051⁄3\x052⁄3\x051⁄5\x052⁄5\x053⁄5\x054" + | ||
29 | "⁄5\x051⁄6\x055⁄6\x051⁄8\x053⁄8\x055⁄8\x057⁄8\x041⁄\x02ii\x02iv\x02vi" + | ||
30 | "\x04viii\x02ix\x02xi\x050⁄3\x06∫∫\x09∫∫∫\x06∮∮\x09∮∮∮\x0210\x0211\x0212" + | ||
31 | "\x0213\x0214\x0215\x0216\x0217\x0218\x0219\x0220\x04(10)\x04(11)\x04(12)" + | ||
32 | "\x04(13)\x04(14)\x04(15)\x04(16)\x04(17)\x04(18)\x04(19)\x04(20)\x0c∫∫∫∫" + | ||
33 | "\x02==\x05⫝̸\x02ɫ\x02ɽ\x02ȿ\x02ɀ\x01.\x04 ゙\x04 ゚\x06より\x06コト\x05(ᄀ)\x05" + | ||
34 | "(ᄂ)\x05(ᄃ)\x05(ᄅ)\x05(ᄆ)\x05(ᄇ)\x05(ᄉ)\x05(ᄋ)\x05(ᄌ)\x05(ᄎ)\x05(ᄏ)\x05(ᄐ" + | ||
35 | ")\x05(ᄑ)\x05(ᄒ)\x05(가)\x05(나)\x05(다)\x05(라)\x05(마)\x05(바)\x05(사)\x05(아)" + | ||
36 | "\x05(자)\x05(차)\x05(카)\x05(타)\x05(파)\x05(하)\x05(주)\x08(오전)\x08(오후)\x05(一)" + | ||
37 | "\x05(二)\x05(三)\x05(四)\x05(五)\x05(六)\x05(七)\x05(八)\x05(九)\x05(十)\x05(月)" + | ||
38 | "\x05(火)\x05(水)\x05(木)\x05(金)\x05(土)\x05(日)\x05(株)\x05(有)\x05(社)\x05(名)" + | ||
39 | "\x05(特)\x05(財)\x05(祝)\x05(労)\x05(代)\x05(呼)\x05(学)\x05(監)\x05(企)\x05(資)" + | ||
40 | "\x05(協)\x05(祭)\x05(休)\x05(自)\x05(至)\x0221\x0222\x0223\x0224\x0225\x0226" + | ||
41 | "\x0227\x0228\x0229\x0230\x0231\x0232\x0233\x0234\x0235\x06참고\x06주의\x0236" + | ||
42 | "\x0237\x0238\x0239\x0240\x0241\x0242\x0243\x0244\x0245\x0246\x0247\x0248" + | ||
43 | "\x0249\x0250\x041月\x042月\x043月\x044月\x045月\x046月\x047月\x048月\x049月\x0510" + | ||
44 | "月\x0511月\x0512月\x02hg\x02ev\x0cアパート\x0cアルファ\x0cアンペア\x09アール\x0cイニング\x09" + | ||
45 | "インチ\x09ウォン\x0fエスクード\x0cエーカー\x09オンス\x09オーム\x09カイリ\x0cカラット\x0cカロリー\x09ガロ" + | ||
46 | "ン\x09ガンマ\x06ギガ\x09ギニー\x0cキュリー\x0cギルダー\x06キロ\x0fキログラム\x12キロメートル\x0fキロワッ" + | ||
47 | "ト\x09グラム\x0fグラムトン\x0fクルゼイロ\x0cクローネ\x09ケース\x09コルナ\x09コーポ\x0cサイクル\x0fサンチ" + | ||
48 | "ーム\x0cシリング\x09センチ\x09セント\x09ダース\x06デシ\x06ドル\x06トン\x06ナノ\x09ノット\x09ハイツ" + | ||
49 | "\x0fパーセント\x09パーツ\x0cバーレル\x0fピアストル\x09ピクル\x06ピコ\x06ビル\x0fファラッド\x0cフィート" + | ||
50 | "\x0fブッシェル\x09フラン\x0fヘクタール\x06ペソ\x09ペニヒ\x09ヘルツ\x09ペンス\x09ページ\x09ベータ\x0cポイ" + | ||
51 | "ント\x09ボルト\x06ホン\x09ポンド\x09ホール\x09ホーン\x0cマイクロ\x09マイル\x09マッハ\x09マルク\x0fマ" + | ||
52 | "ンション\x0cミクロン\x06ミリ\x0fミリバール\x06メガ\x0cメガトン\x0cメートル\x09ヤード\x09ヤール\x09ユアン" + | ||
53 | "\x0cリットル\x06リラ\x09ルピー\x0cルーブル\x06レム\x0fレントゲン\x09ワット\x040点\x041点\x042点" + | ||
54 | "\x043点\x044点\x045点\x046点\x047点\x048点\x049点\x0510点\x0511点\x0512点\x0513点" + | ||
55 | "\x0514点\x0515点\x0516点\x0517点\x0518点\x0519点\x0520点\x0521点\x0522点\x0523点" + | ||
56 | "\x0524点\x02da\x02au\x02ov\x02pc\x02dm\x02iu\x06平成\x06昭和\x06大正\x06明治\x0c株" + | ||
57 | "式会社\x02pa\x02na\x02ma\x02ka\x02kb\x02mb\x02gb\x04kcal\x02pf\x02nf\x02m" + | ||
58 | "g\x02kg\x02hz\x02ml\x02dl\x02kl\x02fm\x02nm\x02mm\x02cm\x02km\x02m2\x02m" + | ||
59 | "3\x05m∕s\x06m∕s2\x07rad∕s\x08rad∕s2\x02ps\x02ns\x02ms\x02pv\x02nv\x02mv" + | ||
60 | "\x02kv\x02pw\x02nw\x02mw\x02kw\x02bq\x02cc\x02cd\x06c∕kg\x02db\x02gy\x02" + | ||
61 | "ha\x02hp\x02in\x02kk\x02kt\x02lm\x02ln\x02lx\x02ph\x02pr\x02sr\x02sv\x02" + | ||
62 | "wb\x05v∕m\x05a∕m\x041日\x042日\x043日\x044日\x045日\x046日\x047日\x048日\x049日" + | ||
63 | "\x0510日\x0511日\x0512日\x0513日\x0514日\x0515日\x0516日\x0517日\x0518日\x0519日" + | ||
64 | "\x0520日\x0521日\x0522日\x0523日\x0524日\x0525日\x0526日\x0527日\x0528日\x0529日" + | ||
65 | "\x0530日\x0531日\x02ь\x02ɦ\x02ɬ\x02ʞ\x02ʇ\x02œ\x04𤋮\x04𢡊\x04𢡄\x04𣏕\x04𥉉" + | ||
66 | "\x04𥳐\x04𧻓\x02ff\x02fi\x02fl\x02st\x04մն\x04մե\x04մի\x04վն\x04մխ\x04יִ" + | ||
67 | "\x04ײַ\x02ע\x02ה\x02כ\x02ל\x02ם\x02ר\x02ת\x04שׁ\x04שׂ\x06שּׁ\x06שּׂ\x04א" + | ||
68 | "ַ\x04אָ\x04אּ\x04בּ\x04גּ\x04דּ\x04הּ\x04וּ\x04זּ\x04טּ\x04יּ\x04ךּ\x04" + | ||
69 | "כּ\x04לּ\x04מּ\x04נּ\x04סּ\x04ףּ\x04פּ\x04צּ\x04קּ\x04רּ\x04שּ\x04תּ" + | ||
70 | "\x04וֹ\x04בֿ\x04כֿ\x04פֿ\x04אל\x02ٱ\x02ٻ\x02پ\x02ڀ\x02ٺ\x02ٿ\x02ٹ\x02ڤ" + | ||
71 | "\x02ڦ\x02ڄ\x02ڃ\x02چ\x02ڇ\x02ڍ\x02ڌ\x02ڎ\x02ڈ\x02ژ\x02ڑ\x02ک\x02گ\x02ڳ" + | ||
72 | "\x02ڱ\x02ں\x02ڻ\x02ۀ\x02ہ\x02ھ\x02ے\x02ۓ\x02ڭ\x02ۇ\x02ۆ\x02ۈ\x02ۋ\x02ۅ" + | ||
73 | "\x02ۉ\x02ې\x02ى\x04ئا\x04ئە\x04ئو\x04ئۇ\x04ئۆ\x04ئۈ\x04ئې\x04ئى\x02ی\x04" + | ||
74 | "ئج\x04ئح\x04ئم\x04ئي\x04بج\x04بح\x04بخ\x04بم\x04بى\x04بي\x04تج\x04تح" + | ||
75 | "\x04تخ\x04تم\x04تى\x04تي\x04ثج\x04ثم\x04ثى\x04ثي\x04جح\x04جم\x04حج\x04حم" + | ||
76 | "\x04خج\x04خح\x04خم\x04سج\x04سح\x04سخ\x04سم\x04صح\x04صم\x04ضج\x04ضح\x04ضخ" + | ||
77 | "\x04ضم\x04طح\x04طم\x04ظم\x04عج\x04عم\x04غج\x04غم\x04فج\x04فح\x04فخ\x04فم" + | ||
78 | "\x04فى\x04في\x04قح\x04قم\x04قى\x04قي\x04كا\x04كج\x04كح\x04كخ\x04كل\x04كم" + | ||
79 | "\x04كى\x04كي\x04لج\x04لح\x04لخ\x04لم\x04لى\x04لي\x04مج\x04مح\x04مخ\x04مم" + | ||
80 | "\x04مى\x04مي\x04نج\x04نح\x04نخ\x04نم\x04نى\x04ني\x04هج\x04هم\x04هى\x04هي" + | ||
81 | "\x04يج\x04يح\x04يخ\x04يم\x04يى\x04يي\x04ذٰ\x04رٰ\x04ىٰ\x05 ٌّ\x05 ٍّ\x05" + | ||
82 | " َّ\x05 ُّ\x05 ِّ\x05 ّٰ\x04ئر\x04ئز\x04ئن\x04بر\x04بز\x04بن\x04تر\x04تز" + | ||
83 | "\x04تن\x04ثر\x04ثز\x04ثن\x04ما\x04نر\x04نز\x04نن\x04ير\x04يز\x04ين\x04ئخ" + | ||
84 | "\x04ئه\x04به\x04ته\x04صخ\x04له\x04نه\x04هٰ\x04يه\x04ثه\x04سه\x04شم\x04شه" + | ||
85 | "\x06ـَّ\x06ـُّ\x06ـِّ\x04طى\x04طي\x04عى\x04عي\x04غى\x04غي\x04سى\x04سي" + | ||
86 | "\x04شى\x04شي\x04حى\x04حي\x04جى\x04جي\x04خى\x04خي\x04صى\x04صي\x04ضى\x04ضي" + | ||
87 | "\x04شج\x04شح\x04شخ\x04شر\x04سر\x04صر\x04ضر\x04اً\x06تجم\x06تحج\x06تحم" + | ||
88 | "\x06تخم\x06تمج\x06تمح\x06تمخ\x06جمح\x06حمي\x06حمى\x06سحج\x06سجح\x06سجى" + | ||
89 | "\x06سمح\x06سمج\x06سمم\x06صحح\x06صمم\x06شحم\x06شجي\x06شمخ\x06شمم\x06ضحى" + | ||
90 | "\x06ضخم\x06طمح\x06طمم\x06طمي\x06عجم\x06عمم\x06عمى\x06غمم\x06غمي\x06غمى" + | ||
91 | "\x06فخم\x06قمح\x06قمم\x06لحم\x06لحي\x06لحى\x06لجج\x06لخم\x06لمح\x06محج" + | ||
92 | "\x06محم\x06محي\x06مجح\x06مجم\x06مخج\x06مخم\x06مجخ\x06همج\x06همم\x06نحم" + | ||
93 | "\x06نحى\x06نجم\x06نجى\x06نمي\x06نمى\x06يمم\x06بخي\x06تجي\x06تجى\x06تخي" + | ||
94 | "\x06تخى\x06تمي\x06تمى\x06جمي\x06جحى\x06جمى\x06سخى\x06صحي\x06شحي\x06ضحي" + | ||
95 | "\x06لجي\x06لمي\x06يحي\x06يجي\x06يمي\x06ممي\x06قمي\x06نحي\x06عمي\x06كمي" + | ||
96 | "\x06نجح\x06مخي\x06لجم\x06كمم\x06جحي\x06حجي\x06مجي\x06فمي\x06بحي\x06سخي" + | ||
97 | "\x06نجي\x06صلے\x06قلے\x08الله\x08اكبر\x08محمد\x08صلعم\x08رسول\x08عليه" + | ||
98 | "\x08وسلم\x06صلى!صلى الله عليه وسلم\x0fجل جلاله\x08ریال\x01,\x01:\x01!" + | ||
99 | "\x01?\x01_\x01{\x01}\x01[\x01]\x01#\x01&\x01*\x01-\x01<\x01>\x01\\\x01$" + | ||
100 | "\x01%\x01@\x04ـً\x04ـَ\x04ـُ\x04ـِ\x04ـّ\x04ـْ\x02ء\x02آ\x02أ\x02ؤ\x02إ" + | ||
101 | "\x02ئ\x02ا\x02ب\x02ة\x02ت\x02ث\x02ج\x02ح\x02خ\x02د\x02ذ\x02ر\x02ز\x02س" + | ||
102 | "\x02ش\x02ص\x02ض\x02ط\x02ظ\x02ع\x02غ\x02ف\x02ق\x02ك\x02ل\x02م\x02ن\x02ه" + | ||
103 | "\x02و\x02ي\x04لآ\x04لأ\x04لإ\x04لا\x01\x22\x01'\x01/\x01^\x01|\x01~\x02¢" + | ||
104 | "\x02£\x02¬\x02¦\x02¥\x08𝅗𝅥\x08𝅘𝅥\x0c𝅘𝅥𝅮\x0c𝅘𝅥𝅯\x0c𝅘𝅥𝅰\x0c𝅘𝅥𝅱\x0c𝅘𝅥𝅲\x08𝆹" + | ||
105 | "𝅥\x08𝆺𝅥\x0c𝆹𝅥𝅮\x0c𝆺𝅥𝅮\x0c𝆹𝅥𝅯\x0c𝆺𝅥𝅯\x02ı\x02ȷ\x02α\x02ε\x02ζ\x02η\x02" + | ||
106 | "κ\x02λ\x02μ\x02ν\x02ξ\x02ο\x02σ\x02τ\x02υ\x02ψ\x03∇\x03∂\x02ϝ\x02ٮ\x02ڡ" + | ||
107 | "\x02ٯ\x020,\x021,\x022,\x023,\x024,\x025,\x026,\x027,\x028,\x029,\x03(a)" + | ||
108 | "\x03(b)\x03(c)\x03(d)\x03(e)\x03(f)\x03(g)\x03(h)\x03(i)\x03(j)\x03(k)" + | ||
109 | "\x03(l)\x03(m)\x03(n)\x03(o)\x03(p)\x03(q)\x03(r)\x03(s)\x03(t)\x03(u)" + | ||
110 | "\x03(v)\x03(w)\x03(x)\x03(y)\x03(z)\x07〔s〕\x02wz\x02hv\x02sd\x03ppv\x02w" + | ||
111 | "c\x02mc\x02md\x02dj\x06ほか\x06ココ\x03サ\x03手\x03字\x03双\x03デ\x03二\x03多\x03解" + | ||
112 | "\x03天\x03交\x03映\x03無\x03料\x03前\x03後\x03再\x03新\x03初\x03終\x03生\x03販\x03声" + | ||
113 | "\x03吹\x03演\x03投\x03捕\x03一\x03三\x03遊\x03左\x03中\x03右\x03指\x03走\x03打\x03禁" + | ||
114 | "\x03空\x03合\x03満\x03有\x03月\x03申\x03割\x03営\x03配\x09〔本〕\x09〔三〕\x09〔二〕\x09〔安" + | ||
115 | "〕\x09〔点〕\x09〔打〕\x09〔盗〕\x09〔勝〕\x09〔敗〕\x03得\x03可\x03丽\x03丸\x03乁\x03你\x03" + | ||
116 | "侮\x03侻\x03倂\x03偺\x03備\x03僧\x03像\x03㒞\x03免\x03兔\x03兤\x03具\x03㒹\x03內\x03" + | ||
117 | "冗\x03冤\x03仌\x03冬\x03况\x03凵\x03刃\x03㓟\x03刻\x03剆\x03剷\x03㔕\x03勇\x03勉\x03" + | ||
118 | "勤\x03勺\x03包\x03匆\x03北\x03卉\x03卑\x03博\x03即\x03卽\x03卿\x03灰\x03及\x03叟\x03" + | ||
119 | "叫\x03叱\x03吆\x03咞\x03吸\x03呈\x03周\x03咢\x03哶\x03唐\x03啓\x03啣\x03善\x03喙\x03" + | ||
120 | "喫\x03喳\x03嗂\x03圖\x03嘆\x03圗\x03噑\x03噴\x03切\x03壮\x03城\x03埴\x03堍\x03型\x03" + | ||
121 | "堲\x03報\x03墬\x03売\x03壷\x03夆\x03夢\x03奢\x03姬\x03娛\x03娧\x03姘\x03婦\x03㛮\x03" + | ||
122 | "嬈\x03嬾\x03寃\x03寘\x03寧\x03寳\x03寿\x03将\x03尢\x03㞁\x03屠\x03屮\x03峀\x03岍\x03" + | ||
123 | "嵃\x03嵮\x03嵫\x03嵼\x03巡\x03巢\x03㠯\x03巽\x03帨\x03帽\x03幩\x03㡢\x03㡼\x03庰\x03" + | ||
124 | "庳\x03庶\x03廊\x03廾\x03舁\x03弢\x03㣇\x03形\x03彫\x03㣣\x03徚\x03忍\x03志\x03忹\x03" + | ||
125 | "悁\x03㤺\x03㤜\x03悔\x03惇\x03慈\x03慌\x03慎\x03慺\x03憎\x03憲\x03憤\x03憯\x03懞\x03" + | ||
126 | "懲\x03懶\x03成\x03戛\x03扝\x03抱\x03拔\x03捐\x03挽\x03拼\x03捨\x03掃\x03揤\x03搢\x03" + | ||
127 | "揅\x03掩\x03㨮\x03摩\x03摾\x03撝\x03摷\x03㩬\x03敏\x03敬\x03旣\x03書\x03晉\x03㬙\x03" + | ||
128 | "暑\x03㬈\x03㫤\x03冒\x03冕\x03最\x03暜\x03肭\x03䏙\x03朗\x03望\x03朡\x03杞\x03杓\x03" + | ||
129 | "㭉\x03柺\x03枅\x03桒\x03梅\x03梎\x03栟\x03椔\x03㮝\x03楂\x03榣\x03槪\x03檨\x03櫛\x03" + | ||
130 | "㰘\x03次\x03歔\x03㱎\x03歲\x03殟\x03殺\x03殻\x03汎\x03沿\x03泍\x03汧\x03洖\x03派\x03" + | ||
131 | "海\x03流\x03浩\x03浸\x03涅\x03洴\x03港\x03湮\x03㴳\x03滋\x03滇\x03淹\x03潮\x03濆\x03" + | ||
132 | "瀹\x03瀞\x03瀛\x03㶖\x03灊\x03災\x03灷\x03炭\x03煅\x03熜\x03爨\x03爵\x03牐\x03犀\x03" + | ||
133 | "犕\x03獺\x03王\x03㺬\x03玥\x03㺸\x03瑇\x03瑜\x03瑱\x03璅\x03瓊\x03㼛\x03甤\x03甾\x03" + | ||
134 | "異\x03瘐\x03㿼\x03䀈\x03直\x03眞\x03真\x03睊\x03䀹\x03瞋\x03䁆\x03䂖\x03硎\x03碌\x03" + | ||
135 | "磌\x03䃣\x03祖\x03福\x03秫\x03䄯\x03穀\x03穊\x03穏\x03䈂\x03篆\x03築\x03䈧\x03糒\x03" + | ||
136 | "䊠\x03糨\x03糣\x03紀\x03絣\x03䌁\x03緇\x03縂\x03繅\x03䌴\x03䍙\x03罺\x03羕\x03翺\x03" + | ||
137 | "者\x03聠\x03聰\x03䏕\x03育\x03脃\x03䐋\x03脾\x03媵\x03舄\x03辞\x03䑫\x03芑\x03芋\x03" + | ||
138 | "芝\x03劳\x03花\x03芳\x03芽\x03苦\x03若\x03茝\x03荣\x03莭\x03茣\x03莽\x03菧\x03著\x03" + | ||
139 | "荓\x03菊\x03菌\x03菜\x03䔫\x03蓱\x03蓳\x03蔖\x03蕤\x03䕝\x03䕡\x03䕫\x03虐\x03虜\x03" + | ||
140 | "虧\x03虩\x03蚩\x03蚈\x03蜎\x03蛢\x03蝹\x03蜨\x03蝫\x03螆\x03蟡\x03蠁\x03䗹\x03衠\x03" + | ||
141 | "衣\x03裗\x03裞\x03䘵\x03裺\x03㒻\x03䚾\x03䛇\x03誠\x03諭\x03變\x03豕\x03貫\x03賁\x03" + | ||
142 | "贛\x03起\x03跋\x03趼\x03跰\x03軔\x03輸\x03邔\x03郱\x03鄑\x03鄛\x03鈸\x03鋗\x03鋘\x03" + | ||
143 | "鉼\x03鏹\x03鐕\x03開\x03䦕\x03閷\x03䧦\x03雃\x03嶲\x03霣\x03䩮\x03䩶\x03韠\x03䪲\x03" + | ||
144 | "頋\x03頩\x03飢\x03䬳\x03餩\x03馧\x03駂\x03駾\x03䯎\x03鬒\x03鱀\x03鳽\x03䳎\x03䳭\x03" + | ||
145 | "鵧\x03䳸\x03麻\x03䵖\x03黹\x03黾\x03鼅\x03鼏\x03鼖\x03鼻" | ||
146 | |||
147 | var xorData string = "" + // Size: 4855 bytes | ||
148 | "\x02\x0c\x09\x02\xb0\xec\x02\xad\xd8\x02\xad\xd9\x02\x06\x07\x02\x0f\x12" + | ||
149 | "\x02\x0f\x1f\x02\x0f\x1d\x02\x01\x13\x02\x0f\x16\x02\x0f\x0b\x02\x0f3" + | ||
150 | "\x02\x0f7\x02\x0f?\x02\x0f/\x02\x0f*\x02\x0c&\x02\x0c*\x02\x0c;\x02\x0c9" + | ||
151 | "\x02\x0c%\x02\xab\xed\x02\xab\xe2\x02\xab\xe3\x02\xa9\xe0\x02\xa9\xe1" + | ||
152 | "\x02\xa9\xe6\x02\xa3\xcb\x02\xa3\xc8\x02\xa3\xc9\x02\x01#\x02\x01\x08" + | ||
153 | "\x02\x0e>\x02\x0e'\x02\x0f\x03\x02\x03\x0d\x02\x03\x09\x02\x03\x17\x02" + | ||
154 | "\x03\x0e\x02\x02\x03\x02\x011\x02\x01\x00\x02\x01\x10\x02\x03<\x02\x07" + | ||
155 | "\x0d\x02\x02\x0c\x02\x0c0\x02\x01\x03\x02\x01\x01\x02\x01 \x02\x01\x22" + | ||
156 | "\x02\x01)\x02\x01\x0a\x02\x01\x0c\x02\x02\x06\x02\x02\x02\x02\x03\x10" + | ||
157 | "\x03\x037 \x03\x0b+\x03\x02\x01\x04\x02\x01\x02\x02\x019\x02\x03\x1c\x02" + | ||
158 | "\x02$\x03\x80p$\x02\x03:\x02\x03\x0a\x03\xc1r.\x03\xc1r,\x03\xc1r\x02" + | ||
159 | "\x02\x02:\x02\x02>\x02\x02,\x02\x02\x10\x02\x02\x00\x03\xc1s<\x03\xc1s*" + | ||
160 | "\x03\xc2L$\x03\xc2L;\x02\x09)\x02\x0a\x19\x03\x83\xab\xe3\x03\x83\xab" + | ||
161 | "\xf2\x03 4\xe0\x03\x81\xab\xea\x03\x81\xab\xf3\x03 4\xef\x03\x96\xe1\xcd" + | ||
162 | "\x03\x84\xe5\xc3\x02\x0d\x11\x03\x8b\xec\xcb\x03\x94\xec\xcf\x03\x9a\xec" + | ||
163 | "\xc2\x03\x8b\xec\xdb\x03\x94\xec\xdf\x03\x9a\xec\xd2\x03\x01\x0c!\x03" + | ||
164 | "\x01\x0c#\x03ʠ\x9d\x03ʣ\x9c\x03ʢ\x9f\x03ʥ\x9e\x03ʤ\x91\x03ʧ\x90\x03ʦ\x93" + | ||
165 | "\x03ʩ\x92\x03ʨ\x95\x03\xca\xf3\xb5\x03\xca\xf0\xb4\x03\xca\xf1\xb7\x03" + | ||
166 | "\xca\xf6\xb6\x03\xca\xf7\x89\x03\xca\xf4\x88\x03\xca\xf5\x8b\x03\xca\xfa" + | ||
167 | "\x8a\x03\xca\xfb\x8d\x03\xca\xf8\x8c\x03\xca\xf9\x8f\x03\xca\xfe\x8e\x03" + | ||
168 | "\xca\xff\x81\x03\xca\xfc\x80\x03\xca\xfd\x83\x03\xca\xe2\x82\x03\xca\xe3" + | ||
169 | "\x85\x03\xca\xe0\x84\x03\xca\xe1\x87\x03\xca\xe6\x86\x03\xca\xe7\x99\x03" + | ||
170 | "\xca\xe4\x98\x03\xca\xe5\x9b\x03\xca\xea\x9a\x03\xca\xeb\x9d\x03\xca\xe8" + | ||
171 | "\x9c\x03ؓ\x89\x03ߔ\x8b\x02\x010\x03\x03\x04\x1e\x03\x04\x15\x12\x03\x0b" + | ||
172 | "\x05,\x03\x06\x04\x00\x03\x06\x04)\x03\x06\x044\x03\x06\x04<\x03\x06\x05" + | ||
173 | "\x1d\x03\x06\x06\x00\x03\x06\x06\x0a\x03\x06\x06'\x03\x06\x062\x03\x0786" + | ||
174 | "\x03\x079/\x03\x079 \x03\x07:\x0e\x03\x07:\x1b\x03\x07:%\x03\x07;/\x03" + | ||
175 | "\x07;%\x03\x074\x11\x03\x076\x09\x03\x077*\x03\x070\x01\x03\x070\x0f\x03" + | ||
176 | "\x070.\x03\x071\x16\x03\x071\x04\x03\x0710\x03\x072\x18\x03\x072-\x03" + | ||
177 | "\x073\x14\x03\x073>\x03\x07'\x09\x03\x07 \x00\x03\x07\x1f\x0b\x03\x07" + | ||
178 | "\x18#\x03\x07\x18(\x03\x07\x186\x03\x07\x18\x03\x03\x07\x19\x16\x03\x07" + | ||
179 | "\x116\x03\x07\x12'\x03\x07\x13\x10\x03\x07\x0c&\x03\x07\x0c\x08\x03\x07" + | ||
180 | "\x0c\x13\x03\x07\x0d\x02\x03\x07\x0d\x1c\x03\x07\x0b5\x03\x07\x0b\x0a" + | ||
181 | "\x03\x07\x0b\x01\x03\x07\x0b\x0f\x03\x07\x05\x00\x03\x07\x05\x09\x03\x07" + | ||
182 | "\x05\x0b\x03\x07\x07\x01\x03\x07\x07\x08\x03\x07\x00<\x03\x07\x00+\x03" + | ||
183 | "\x07\x01)\x03\x07\x01\x1b\x03\x07\x01\x08\x03\x07\x03?\x03\x0445\x03\x04" + | ||
184 | "4\x08\x03\x0454\x03\x04)/\x03\x04)5\x03\x04+\x05\x03\x04+\x14\x03\x04+ " + | ||
185 | "\x03\x04+<\x03\x04*&\x03\x04*\x22\x03\x04&8\x03\x04!\x01\x03\x04!\x22" + | ||
186 | "\x03\x04\x11+\x03\x04\x10.\x03\x04\x104\x03\x04\x13=\x03\x04\x12\x04\x03" + | ||
187 | "\x04\x12\x0a\x03\x04\x0d\x1d\x03\x04\x0d\x07\x03\x04\x0d \x03\x05<>\x03" + | ||
188 | "\x055<\x03\x055!\x03\x055#\x03\x055&\x03\x054\x1d\x03\x054\x02\x03\x054" + | ||
189 | "\x07\x03\x0571\x03\x053\x1a\x03\x053\x16\x03\x05.<\x03\x05.\x07\x03\x05)" + | ||
190 | ":\x03\x05)<\x03\x05)\x0c\x03\x05)\x15\x03\x05+-\x03\x05+5\x03\x05$\x1e" + | ||
191 | "\x03\x05$\x14\x03\x05'\x04\x03\x05'\x14\x03\x05&\x02\x03\x05\x226\x03" + | ||
192 | "\x05\x22\x0c\x03\x05\x22\x1c\x03\x05\x19\x0a\x03\x05\x1b\x09\x03\x05\x1b" + | ||
193 | "\x0c\x03\x05\x14\x07\x03\x05\x16?\x03\x05\x16\x0c\x03\x05\x0c\x05\x03" + | ||
194 | "\x05\x0e\x0f\x03\x05\x01\x0e\x03\x05\x00(\x03\x05\x030\x03\x05\x03\x06" + | ||
195 | "\x03\x0a==\x03\x0a=1\x03\x0a=,\x03\x0a=\x0c\x03\x0a??\x03\x0a<\x08\x03" + | ||
196 | "\x0a9!\x03\x0a9)\x03\x0a97\x03\x0a99\x03\x0a6\x0a\x03\x0a6\x1c\x03\x0a6" + | ||
197 | "\x17\x03\x0a7'\x03\x0a78\x03\x0a73\x03\x0a'\x01\x03\x0a'&\x03\x0a\x1f" + | ||
198 | "\x0e\x03\x0a\x1f\x03\x03\x0a\x1f3\x03\x0a\x1b/\x03\x0a\x18\x19\x03\x0a" + | ||
199 | "\x19\x01\x03\x0a\x16\x14\x03\x0a\x0e\x22\x03\x0a\x0f\x10\x03\x0a\x0f\x02" + | ||
200 | "\x03\x0a\x0f \x03\x0a\x0c\x04\x03\x0a\x0b>\x03\x0a\x0b+\x03\x0a\x08/\x03" + | ||
201 | "\x0a\x046\x03\x0a\x05\x14\x03\x0a\x00\x04\x03\x0a\x00\x10\x03\x0a\x00" + | ||
202 | "\x14\x03\x0b<3\x03\x0b;*\x03\x0b9\x22\x03\x0b9)\x03\x0b97\x03\x0b+\x10" + | ||
203 | "\x03\x0b((\x03\x0b&5\x03\x0b$\x1c\x03\x0b$\x12\x03\x0b%\x04\x03\x0b#<" + | ||
204 | "\x03\x0b#0\x03\x0b#\x0d\x03\x0b#\x19\x03\x0b!:\x03\x0b!\x1f\x03\x0b!\x00" + | ||
205 | "\x03\x0b\x1e5\x03\x0b\x1c\x1d\x03\x0b\x1d-\x03\x0b\x1d(\x03\x0b\x18.\x03" + | ||
206 | "\x0b\x18 \x03\x0b\x18\x16\x03\x0b\x14\x13\x03\x0b\x15$\x03\x0b\x15\x22" + | ||
207 | "\x03\x0b\x12\x1b\x03\x0b\x12\x10\x03\x0b\x132\x03\x0b\x13=\x03\x0b\x12" + | ||
208 | "\x18\x03\x0b\x0c&\x03\x0b\x061\x03\x0b\x06:\x03\x0b\x05#\x03\x0b\x05<" + | ||
209 | "\x03\x0b\x04\x0b\x03\x0b\x04\x04\x03\x0b\x04\x1b\x03\x0b\x042\x03\x0b" + | ||
210 | "\x041\x03\x0b\x03\x03\x03\x0b\x03\x1d\x03\x0b\x03/\x03\x0b\x03+\x03\x0b" + | ||
211 | "\x02\x1b\x03\x0b\x02\x00\x03\x0b\x01\x1e\x03\x0b\x01\x08\x03\x0b\x015" + | ||
212 | "\x03\x06\x0d9\x03\x06\x0d=\x03\x06\x0d?\x03\x02\x001\x03\x02\x003\x03" + | ||
213 | "\x02\x02\x19\x03\x02\x006\x03\x02\x02\x1b\x03\x02\x004\x03\x02\x00<\x03" + | ||
214 | "\x02\x02\x0a\x03\x02\x02\x0e\x03\x02\x01\x1a\x03\x02\x01\x07\x03\x02\x01" + | ||
215 | "\x05\x03\x02\x01\x0b\x03\x02\x01%\x03\x02\x01\x0c\x03\x02\x01\x04\x03" + | ||
216 | "\x02\x01\x1c\x03\x02\x00.\x03\x02\x002\x03\x02\x00>\x03\x02\x00\x12\x03" + | ||
217 | "\x02\x00\x16\x03\x02\x011\x03\x02\x013\x03\x02\x02 \x03\x02\x02%\x03\x02" + | ||
218 | "\x02$\x03\x02\x028\x03\x02\x02;\x03\x02\x024\x03\x02\x012\x03\x02\x022" + | ||
219 | "\x03\x02\x02/\x03\x02\x01,\x03\x02\x01\x13\x03\x02\x01\x16\x03\x02\x01" + | ||
220 | "\x11\x03\x02\x01\x1e\x03\x02\x01\x15\x03\x02\x01\x17\x03\x02\x01\x0f\x03" + | ||
221 | "\x02\x01\x08\x03\x02\x00?\x03\x02\x03\x07\x03\x02\x03\x0d\x03\x02\x03" + | ||
222 | "\x13\x03\x02\x03\x1d\x03\x02\x03\x1f\x03\x02\x00\x03\x03\x02\x00\x0d\x03" + | ||
223 | "\x02\x00\x01\x03\x02\x00\x1b\x03\x02\x00\x19\x03\x02\x00\x18\x03\x02\x00" + | ||
224 | "\x13\x03\x02\x00/\x03\x07>\x12\x03\x07<\x1f\x03\x07>\x1d\x03\x06\x1d\x0e" + | ||
225 | "\x03\x07>\x1c\x03\x07>:\x03\x07>\x13\x03\x04\x12+\x03\x07?\x03\x03\x07>" + | ||
226 | "\x02\x03\x06\x224\x03\x06\x1a.\x03\x07<%\x03\x06\x1c\x0b\x03\x0609\x03" + | ||
227 | "\x05\x1f\x01\x03\x04'\x08\x03\x93\xfd\xf5\x03\x02\x0d \x03\x02\x0d#\x03" + | ||
228 | "\x02\x0d!\x03\x02\x0d&\x03\x02\x0d\x22\x03\x02\x0d/\x03\x02\x0d,\x03\x02" + | ||
229 | "\x0d$\x03\x02\x0d'\x03\x02\x0d%\x03\x02\x0d;\x03\x02\x0d=\x03\x02\x0d?" + | ||
230 | "\x03\x099.\x03\x08\x0b7\x03\x08\x02\x14\x03\x08\x14\x0d\x03\x08.:\x03" + | ||
231 | "\x089'\x03\x0f\x0b\x18\x03\x0f\x1c1\x03\x0f\x17&\x03\x0f9\x1f\x03\x0f0" + | ||
232 | "\x0c\x03\x0e\x0a9\x03\x0e\x056\x03\x0e\x1c#\x03\x0f\x13\x0e\x03\x072\x00" + | ||
233 | "\x03\x070\x0d\x03\x072\x0b\x03\x06\x11\x18\x03\x070\x10\x03\x06\x0f(\x03" + | ||
234 | "\x072\x05\x03\x06\x0f,\x03\x073\x15\x03\x06\x07\x08\x03\x05\x16\x02\x03" + | ||
235 | "\x04\x0b \x03\x05:8\x03\x05\x16%\x03\x0a\x0d\x1f\x03\x06\x16\x10\x03\x05" + | ||
236 | "\x1d5\x03\x05*;\x03\x05\x16\x1b\x03\x04.-\x03\x06\x1a\x19\x03\x04\x03," + | ||
237 | "\x03\x0b87\x03\x04/\x0a\x03\x06\x00,\x03\x04-\x01\x03\x04\x1e-\x03\x06/(" + | ||
238 | "\x03\x0a\x0b5\x03\x06\x0e7\x03\x06\x07.\x03\x0597\x03\x0a*%\x03\x0760" + | ||
239 | "\x03\x06\x0c;\x03\x05'\x00\x03\x072.\x03\x072\x08\x03\x06=\x01\x03\x06" + | ||
240 | "\x05\x1b\x03\x06\x06\x12\x03\x06$=\x03\x06'\x0d\x03\x04\x11\x0f\x03\x076" + | ||
241 | ",\x03\x06\x07;\x03\x06.,\x03\x86\xf9\xea\x03\x8f\xff\xeb\x02\x092\x02" + | ||
242 | "\x095\x02\x094\x02\x09;\x02\x09>\x02\x098\x02\x09*\x02\x09/\x02\x09,\x02" + | ||
243 | "\x09%\x02\x09&\x02\x09#\x02\x09 \x02\x08!\x02\x08%\x02\x08$\x02\x08+\x02" + | ||
244 | "\x08.\x02\x08*\x02\x08&\x02\x088\x02\x08>\x02\x084\x02\x086\x02\x080\x02" + | ||
245 | "\x08\x10\x02\x08\x17\x02\x08\x12\x02\x08\x1d\x02\x08\x1f\x02\x08\x13\x02" + | ||
246 | "\x08\x15\x02\x08\x14\x02\x08\x0c\x03\x8b\xfd\xd0\x03\x81\xec\xc6\x03\x87" + | ||
247 | "\xe0\x8a\x03-2\xe3\x03\x80\xef\xe4\x03-2\xea\x03\x88\xe6\xeb\x03\x8e\xe6" + | ||
248 | "\xe8\x03\x84\xe6\xe9\x03\x97\xe6\xee\x03-2\xf9\x03-2\xf6\x03\x8e\xe3\xad" + | ||
249 | "\x03\x80\xe3\x92\x03\x88\xe3\x90\x03\x8e\xe3\x90\x03\x80\xe3\x97\x03\x88" + | ||
250 | "\xe3\x95\x03\x88\xfe\xcb\x03\x8e\xfe\xca\x03\x84\xfe\xcd\x03\x91\xef\xc9" + | ||
251 | "\x03-2\xc1\x03-2\xc0\x03-2\xcb\x03\x88@\x09\x03\x8e@\x08\x03\x8f\xe0\xf5" + | ||
252 | "\x03\x8e\xe6\xf9\x03\x8e\xe0\xfa\x03\x93\xff\xf4\x03\x84\xee\xd3\x03\x0b" + | ||
253 | "(\x04\x023 \x021;\x02\x01*\x03\x0b#\x10\x03\x0b 0\x03\x0b!\x10\x03\x0b!0" + | ||
254 | "\x03\x07\x15\x08\x03\x09?5\x03\x07\x1f\x08\x03\x07\x17\x0b\x03\x09\x1f" + | ||
255 | "\x15\x03\x0b\x1c7\x03\x0a+#\x03\x06\x1a\x1b\x03\x06\x1a\x14\x03\x0a\x01" + | ||
256 | "\x18\x03\x06#\x1b\x03\x0a2\x0c\x03\x0a\x01\x04\x03\x09#;\x03\x08='\x03" + | ||
257 | "\x08\x1a\x0a\x03\x07</\x03\x07:+\x03\x07\x07*\x03\x06&\x1c\x03\x09\x0c" + | ||
258 | "\x16\x03\x09\x10\x0e\x03\x08'\x0f\x03\x08+\x09\x03\x074%\x03\x06!3\x03" + | ||
259 | "\x06\x03+\x03\x0b\x1e\x19\x03\x0a))\x03\x09\x08\x19\x03\x08,\x05\x03\x07" + | ||
260 | "<2\x03\x06\x1c>\x03\x0a\x111\x03\x09\x1b\x09\x03\x073.\x03\x07\x01\x00" + | ||
261 | "\x03\x09/,\x03\x07#>\x03\x07\x048\x03\x0a\x1f\x22\x03\x098>\x03\x09\x11" + | ||
262 | "\x00\x03\x08/\x17\x03\x06'\x22\x03\x0b\x1a+\x03\x0a\x22\x19\x03\x0a/1" + | ||
263 | "\x03\x0974\x03\x09\x0f\x22\x03\x08,\x22\x03\x08?\x14\x03\x07$5\x03\x07<3" + | ||
264 | "\x03\x07=*\x03\x07\x13\x18\x03\x068\x0a\x03\x06\x09\x16\x03\x06\x13\x00" + | ||
265 | "\x03\x08\x067\x03\x08\x01\x03\x03\x08\x12\x1d\x03\x07+7\x03\x06(;\x03" + | ||
266 | "\x06\x1c?\x03\x07\x0e\x17\x03\x0a\x06\x1d\x03\x0a\x19\x07\x03\x08\x14$" + | ||
267 | "\x03\x07$;\x03\x08,$\x03\x08\x06\x0d\x03\x07\x16\x0a\x03\x06>>\x03\x0a" + | ||
268 | "\x06\x12\x03\x0a\x14)\x03\x09\x0d\x1f\x03\x09\x12\x17\x03\x09\x19\x01" + | ||
269 | "\x03\x08\x11 \x03\x08\x1d'\x03\x06<\x1a\x03\x0a.\x00\x03\x07'\x18\x03" + | ||
270 | "\x0a\x22\x08\x03\x08\x0d\x0a\x03\x08\x13)\x03\x07*)\x03\x06<,\x03\x07" + | ||
271 | "\x0b\x1a\x03\x09.\x14\x03\x09\x0d\x1e\x03\x07\x0e#\x03\x0b\x1d'\x03\x0a" + | ||
272 | "\x0a8\x03\x09%2\x03\x08+&\x03\x080\x12\x03\x0a)4\x03\x08\x06\x1f\x03\x0b" + | ||
273 | "\x1b\x1a\x03\x0a\x1b\x0f\x03\x0b\x1d*\x03\x09\x16$\x03\x090\x11\x03\x08" + | ||
274 | "\x11\x08\x03\x0a*(\x03\x0a\x042\x03\x089,\x03\x074'\x03\x07\x0f\x05\x03" + | ||
275 | "\x09\x0b\x0a\x03\x07\x1b\x01\x03\x09\x17:\x03\x09.\x0d\x03\x07.\x11\x03" + | ||
276 | "\x09+\x15\x03\x080\x13\x03\x0b\x1f\x19\x03\x0a \x11\x03\x0a\x220\x03\x09" + | ||
277 | "\x07;\x03\x08\x16\x1c\x03\x07,\x13\x03\x07\x0e/\x03\x06\x221\x03\x0a." + | ||
278 | "\x0a\x03\x0a7\x02\x03\x0a\x032\x03\x0a\x1d.\x03\x091\x06\x03\x09\x19:" + | ||
279 | "\x03\x08\x02/\x03\x060+\x03\x06\x0f-\x03\x06\x1c\x1f\x03\x06\x1d\x07\x03" + | ||
280 | "\x0a,\x11\x03\x09=\x0d\x03\x09\x0b;\x03\x07\x1b/\x03\x0a\x1f:\x03\x09 " + | ||
281 | "\x1f\x03\x09.\x10\x03\x094\x0b\x03\x09\x1a1\x03\x08#\x1a\x03\x084\x1d" + | ||
282 | "\x03\x08\x01\x1f\x03\x08\x11\x22\x03\x07'8\x03\x07\x1a>\x03\x0757\x03" + | ||
283 | "\x06&9\x03\x06+\x11\x03\x0a.\x0b\x03\x0a,>\x03\x0a4#\x03\x08%\x17\x03" + | ||
284 | "\x07\x05\x22\x03\x07\x0c\x0b\x03\x0a\x1d+\x03\x0a\x19\x16\x03\x09+\x1f" + | ||
285 | "\x03\x09\x08\x0b\x03\x08\x16\x18\x03\x08+\x12\x03\x0b\x1d\x0c\x03\x0a=" + | ||
286 | "\x10\x03\x0a\x09\x0d\x03\x0a\x10\x11\x03\x09&0\x03\x08(\x1f\x03\x087\x07" + | ||
287 | "\x03\x08\x185\x03\x07'6\x03\x06.\x05\x03\x06=\x04\x03\x06;;\x03\x06\x06," + | ||
288 | "\x03\x0b\x18>\x03\x08\x00\x18\x03\x06 \x03\x03\x06<\x00\x03\x09%\x18\x03" + | ||
289 | "\x0b\x1c<\x03\x0a%!\x03\x0a\x09\x12\x03\x0a\x16\x02\x03\x090'\x03\x09" + | ||
290 | "\x0e=\x03\x08 \x0e\x03\x08>\x03\x03\x074>\x03\x06&?\x03\x06\x19\x09\x03" + | ||
291 | "\x06?(\x03\x0a-\x0e\x03\x09:3\x03\x098:\x03\x09\x12\x0b\x03\x09\x1d\x17" + | ||
292 | "\x03\x087\x05\x03\x082\x14\x03\x08\x06%\x03\x08\x13\x1f\x03\x06\x06\x0e" + | ||
293 | "\x03\x0a\x22<\x03\x09/<\x03\x06>+\x03\x0a'?\x03\x0a\x13\x0c\x03\x09\x10<" + | ||
294 | "\x03\x07\x1b=\x03\x0a\x19\x13\x03\x09\x22\x1d\x03\x09\x07\x0d\x03\x08)" + | ||
295 | "\x1c\x03\x06=\x1a\x03\x0a/4\x03\x0a7\x11\x03\x0a\x16:\x03\x09?3\x03\x09:" + | ||
296 | "/\x03\x09\x05\x0a\x03\x09\x14\x06\x03\x087\x22\x03\x080\x07\x03\x08\x1a" + | ||
297 | "\x1f\x03\x07\x04(\x03\x07\x04\x09\x03\x06 %\x03\x06<\x08\x03\x0a+\x14" + | ||
298 | "\x03\x09\x1d\x16\x03\x0a70\x03\x08 >\x03\x0857\x03\x070\x0a\x03\x06=\x12" + | ||
299 | "\x03\x06\x16%\x03\x06\x1d,\x03\x099#\x03\x09\x10>\x03\x07 \x1e\x03\x08" + | ||
300 | "\x0c<\x03\x08\x0b\x18\x03\x08\x15+\x03\x08,:\x03\x08%\x22\x03\x07\x0a$" + | ||
301 | "\x03\x0b\x1c=\x03\x07+\x08\x03\x0a/\x05\x03\x0a \x07\x03\x0a\x12'\x03" + | ||
302 | "\x09#\x11\x03\x08\x1b\x15\x03\x0a\x06\x01\x03\x09\x1c\x1b\x03\x0922\x03" + | ||
303 | "\x07\x14<\x03\x07\x09\x04\x03\x061\x04\x03\x07\x0e\x01\x03\x0a\x13\x18" + | ||
304 | "\x03\x0a-\x0c\x03\x0a?\x0d\x03\x0a\x09\x0a\x03\x091&\x03\x0a/\x0b\x03" + | ||
305 | "\x08$<\x03\x083\x1d\x03\x08\x0c$\x03\x08\x0d\x07\x03\x08\x0d?\x03\x08" + | ||
306 | "\x0e\x14\x03\x065\x0a\x03\x08\x1a#\x03\x08\x16#\x03\x0702\x03\x07\x03" + | ||
307 | "\x1a\x03\x06(\x1d\x03\x06+\x1b\x03\x06\x0b\x05\x03\x06\x0b\x17\x03\x06" + | ||
308 | "\x0c\x04\x03\x06\x1e\x19\x03\x06+0\x03\x062\x18\x03\x0b\x16\x1e\x03\x0a+" + | ||
309 | "\x16\x03\x0a-?\x03\x0a#:\x03\x0a#\x10\x03\x0a%$\x03\x0a>+\x03\x0a01\x03" + | ||
310 | "\x0a1\x10\x03\x0a\x099\x03\x0a\x0a\x12\x03\x0a\x19\x1f\x03\x0a\x19\x12" + | ||
311 | "\x03\x09*)\x03\x09-\x16\x03\x09.1\x03\x09.2\x03\x09<\x0e\x03\x09> \x03" + | ||
312 | "\x093\x12\x03\x09\x0b\x01\x03\x09\x1c2\x03\x09\x11\x1c\x03\x09\x15%\x03" + | ||
313 | "\x08,&\x03\x08!\x22\x03\x089(\x03\x08\x0b\x1a\x03\x08\x0d2\x03\x08\x0c" + | ||
314 | "\x04\x03\x08\x0c\x06\x03\x08\x0c\x1f\x03\x08\x0c\x0c\x03\x08\x0f\x1f\x03" + | ||
315 | "\x08\x0f\x1d\x03\x08\x00\x14\x03\x08\x03\x14\x03\x08\x06\x16\x03\x08\x1e" + | ||
316 | "#\x03\x08\x11\x11\x03\x08\x10\x18\x03\x08\x14(\x03\x07)\x1e\x03\x07.1" + | ||
317 | "\x03\x07 $\x03\x07 '\x03\x078\x08\x03\x07\x0d0\x03\x07\x0f7\x03\x07\x05#" + | ||
318 | "\x03\x07\x05\x1a\x03\x07\x1a7\x03\x07\x1d-\x03\x07\x17\x10\x03\x06)\x1f" + | ||
319 | "\x03\x062\x0b\x03\x066\x16\x03\x06\x09\x11\x03\x09(\x1e\x03\x07!5\x03" + | ||
320 | "\x0b\x11\x16\x03\x0a/\x04\x03\x0a,\x1a\x03\x0b\x173\x03\x0a,1\x03\x0a/5" + | ||
321 | "\x03\x0a\x221\x03\x0a\x22\x0d\x03\x0a?%\x03\x0a<,\x03\x0a?#\x03\x0a>\x19" + | ||
322 | "\x03\x0a\x08&\x03\x0a\x0b\x0e\x03\x0a\x0c:\x03\x0a\x0c+\x03\x0a\x03\x22" + | ||
323 | "\x03\x0a\x06)\x03\x0a\x11\x10\x03\x0a\x11\x1a\x03\x0a\x17-\x03\x0a\x14(" + | ||
324 | "\x03\x09)\x1e\x03\x09/\x09\x03\x09.\x00\x03\x09,\x07\x03\x09/*\x03\x09-9" + | ||
325 | "\x03\x09\x228\x03\x09%\x09\x03\x09:\x12\x03\x09;\x1d\x03\x09?\x06\x03" + | ||
326 | "\x093%\x03\x096\x05\x03\x096\x08\x03\x097\x02\x03\x09\x07,\x03\x09\x04," + | ||
327 | "\x03\x09\x1f\x16\x03\x09\x11\x03\x03\x09\x11\x12\x03\x09\x168\x03\x08*" + | ||
328 | "\x05\x03\x08/2\x03\x084:\x03\x08\x22+\x03\x08 0\x03\x08&\x0a\x03\x08;" + | ||
329 | "\x10\x03\x08>$\x03\x08>\x18\x03\x0829\x03\x082:\x03\x081,\x03\x081<\x03" + | ||
330 | "\x081\x1c\x03\x087#\x03\x087*\x03\x08\x09'\x03\x08\x00\x1d\x03\x08\x05-" + | ||
331 | "\x03\x08\x1f4\x03\x08\x1d\x04\x03\x08\x16\x0f\x03\x07*7\x03\x07'!\x03" + | ||
332 | "\x07%\x1b\x03\x077\x0c\x03\x07\x0c1\x03\x07\x0c.\x03\x07\x00\x06\x03\x07" + | ||
333 | "\x01\x02\x03\x07\x010\x03\x07\x06=\x03\x07\x01\x03\x03\x07\x01\x13\x03" + | ||
334 | "\x07\x06\x06\x03\x07\x05\x0a\x03\x07\x1f\x09\x03\x07\x17:\x03\x06*1\x03" + | ||
335 | "\x06-\x1d\x03\x06\x223\x03\x062:\x03\x060$\x03\x066\x1e\x03\x064\x12\x03" + | ||
336 | "\x0645\x03\x06\x0b\x00\x03\x06\x0b7\x03\x06\x07\x1f\x03\x06\x15\x12\x03" + | ||
337 | "\x0c\x05\x0f\x03\x0b+\x0b\x03\x0b+-\x03\x06\x16\x1b\x03\x06\x15\x17\x03" + | ||
338 | "\x89\xca\xea\x03\x89\xca\xe8\x03\x0c8\x10\x03\x0c8\x01\x03\x0c8\x0f\x03" + | ||
339 | "\x0d8%\x03\x0d8!\x03\x0c8-\x03\x0c8/\x03\x0c8+\x03\x0c87\x03\x0c85\x03" + | ||
340 | "\x0c9\x09\x03\x0c9\x0d\x03\x0c9\x0f\x03\x0c9\x0b\x03\xcfu\x0c\x03\xcfu" + | ||
341 | "\x0f\x03\xcfu\x0e\x03\xcfu\x09\x03\x0c9\x10\x03\x0d9\x0c\x03\xcf`;\x03" + | ||
342 | "\xcf`>\x03\xcf`9\x03\xcf`8\x03\xcf`7\x03\xcf`*\x03\xcf`-\x03\xcf`,\x03" + | ||
343 | "\x0d\x1b\x1a\x03\x0d\x1b&\x03\x0c=.\x03\x0c=%\x03\x0c>\x1e\x03\x0c>\x14" + | ||
344 | "\x03\x0c?\x06\x03\x0c?\x0b\x03\x0c?\x0c\x03\x0c?\x0d\x03\x0c?\x02\x03" + | ||
345 | "\x0c>\x0f\x03\x0c>\x08\x03\x0c>\x09\x03\x0c>,\x03\x0c>\x0c\x03\x0c?\x13" + | ||
346 | "\x03\x0c?\x16\x03\x0c?\x15\x03\x0c?\x1c\x03\x0c?\x1f\x03\x0c?\x1d\x03" + | ||
347 | "\x0c?\x1a\x03\x0c?\x17\x03\x0c?\x08\x03\x0c?\x09\x03\x0c?\x0e\x03\x0c?" + | ||
348 | "\x04\x03\x0c?\x05\x03\x0c<?\x03\x0c=\x00\x03\x0c=\x06\x03\x0c=\x05\x03" + | ||
349 | "\x0c=\x0c\x03\x0c=\x0f\x03\x0c=\x0d\x03\x0c=\x0b\x03\x0c=\x07\x03\x0c=" + | ||
350 | "\x19\x03\x0c=\x15\x03\x0c=\x11\x03\x0c=1\x03\x0c=3\x03\x0c=0\x03\x0c=>" + | ||
351 | "\x03\x0c=2\x03\x0c=6\x03\x0c<\x07\x03\x0c<\x05\x03\x0e:!\x03\x0e:#\x03" + | ||
352 | "\x0e8\x09\x03\x0e:&\x03\x0e8\x0b\x03\x0e:$\x03\x0e:,\x03\x0e8\x1a\x03" + | ||
353 | "\x0e8\x1e\x03\x0e:*\x03\x0e:7\x03\x0e:5\x03\x0e:;\x03\x0e:\x15\x03\x0e:<" + | ||
354 | "\x03\x0e:4\x03\x0e:'\x03\x0e:-\x03\x0e:%\x03\x0e:?\x03\x0e:=\x03\x0e:)" + | ||
355 | "\x03\x0e:/\x03\xcfs'\x03\x0d=\x0f\x03\x0d+*\x03\x0d99\x03\x0d9;\x03\x0d9" + | ||
356 | "?\x03\x0d)\x0d\x03\x0d(%\x02\x01\x18\x02\x01(\x02\x01\x1e\x03\x0f$!\x03" + | ||
357 | "\x0f87\x03\x0f4\x0e\x03\x0f5\x1d\x03\x06'\x03\x03\x0f\x08\x18\x03\x0f" + | ||
358 | "\x0d\x1b\x03\x0e2=\x03\x0e;\x08\x03\x0e:\x0b\x03\x0e\x06$\x03\x0e\x0d)" + | ||
359 | "\x03\x0e\x16\x1f\x03\x0e\x16\x1b\x03\x0d$\x0a\x03\x05,\x1d\x03\x0d. \x03" + | ||
360 | "\x0d.#\x03\x0c(/\x03\x09%\x02\x03\x0d90\x03\x0d\x0e4\x03\x0d\x0d\x0f\x03" + | ||
361 | "\x0c#\x00\x03\x0c,\x1e\x03\x0c2\x0e\x03\x0c\x01\x17\x03\x0c\x09:\x03\x0e" + | ||
362 | "\x173\x03\x0c\x08\x03\x03\x0c\x11\x07\x03\x0c\x10\x18\x03\x0c\x1f\x1c" + | ||
363 | "\x03\x0c\x19\x0e\x03\x0c\x1a\x1f\x03\x0f0>\x03\x0b->\x03\x0b<+\x03\x0b8" + | ||
364 | "\x13\x03\x0b\x043\x03\x0b\x14\x03\x03\x0b\x16%\x03\x0d\x22&\x03\x0b\x1a" + | ||
365 | "\x1a\x03\x0b\x1a\x04\x03\x0a%9\x03\x0a&2\x03\x0a&0\x03\x0a!\x1a\x03\x0a!" + | ||
366 | "7\x03\x0a5\x10\x03\x0a=4\x03\x0a?\x0e\x03\x0a>\x10\x03\x0a\x00 \x03\x0a" + | ||
367 | "\x0f:\x03\x0a\x0f9\x03\x0a\x0b\x0a\x03\x0a\x17%\x03\x0a\x1b-\x03\x09-" + | ||
368 | "\x1a\x03\x09,4\x03\x09.,\x03\x09)\x09\x03\x096!\x03\x091\x1f\x03\x093" + | ||
369 | "\x16\x03\x0c+\x1f\x03\x098 \x03\x098=\x03\x0c(\x1a\x03\x0c(\x16\x03\x09" + | ||
370 | "\x0a+\x03\x09\x16\x12\x03\x09\x13\x0e\x03\x09\x153\x03\x08)!\x03\x09\x1a" + | ||
371 | "\x01\x03\x09\x18\x01\x03\x08%#\x03\x08>\x22\x03\x08\x05%\x03\x08\x02*" + | ||
372 | "\x03\x08\x15;\x03\x08\x1b7\x03\x0f\x07\x1d\x03\x0f\x04\x03\x03\x070\x0c" + | ||
373 | "\x03\x07;\x0b\x03\x07\x08\x17\x03\x07\x12\x06\x03\x06/-\x03\x0671\x03" + | ||
374 | "\x065+\x03\x06>7\x03\x06\x049\x03\x05+\x1e\x03\x05,\x17\x03\x05 \x1d\x03" + | ||
375 | "\x05\x22\x05\x03\x050\x1d" | ||
376 | |||
377 | // lookup returns the trie value for the first UTF-8 encoding in s and | ||
378 | // the width in bytes of this encoding. The size will be 0 if s does not | ||
379 | // hold enough bytes to complete the encoding. len(s) must be greater than 0. | ||
380 | func (t *idnaTrie) lookup(s []byte) (v uint16, sz int) { | ||
381 | c0 := s[0] | ||
382 | switch { | ||
383 | case c0 < 0x80: // is ASCII | ||
384 | return idnaValues[c0], 1 | ||
385 | case c0 < 0xC2: | ||
386 | return 0, 1 // Illegal UTF-8: not a starter, not ASCII. | ||
387 | case c0 < 0xE0: // 2-byte UTF-8 | ||
388 | if len(s) < 2 { | ||
389 | return 0, 0 | ||
390 | } | ||
391 | i := idnaIndex[c0] | ||
392 | c1 := s[1] | ||
393 | if c1 < 0x80 || 0xC0 <= c1 { | ||
394 | return 0, 1 // Illegal UTF-8: not a continuation byte. | ||
395 | } | ||
396 | return t.lookupValue(uint32(i), c1), 2 | ||
397 | case c0 < 0xF0: // 3-byte UTF-8 | ||
398 | if len(s) < 3 { | ||
399 | return 0, 0 | ||
400 | } | ||
401 | i := idnaIndex[c0] | ||
402 | c1 := s[1] | ||
403 | if c1 < 0x80 || 0xC0 <= c1 { | ||
404 | return 0, 1 // Illegal UTF-8: not a continuation byte. | ||
405 | } | ||
406 | o := uint32(i)<<6 + uint32(c1) | ||
407 | i = idnaIndex[o] | ||
408 | c2 := s[2] | ||
409 | if c2 < 0x80 || 0xC0 <= c2 { | ||
410 | return 0, 2 // Illegal UTF-8: not a continuation byte. | ||
411 | } | ||
412 | return t.lookupValue(uint32(i), c2), 3 | ||
413 | case c0 < 0xF8: // 4-byte UTF-8 | ||
414 | if len(s) < 4 { | ||
415 | return 0, 0 | ||
416 | } | ||
417 | i := idnaIndex[c0] | ||
418 | c1 := s[1] | ||
419 | if c1 < 0x80 || 0xC0 <= c1 { | ||
420 | return 0, 1 // Illegal UTF-8: not a continuation byte. | ||
421 | } | ||
422 | o := uint32(i)<<6 + uint32(c1) | ||
423 | i = idnaIndex[o] | ||
424 | c2 := s[2] | ||
425 | if c2 < 0x80 || 0xC0 <= c2 { | ||
426 | return 0, 2 // Illegal UTF-8: not a continuation byte. | ||
427 | } | ||
428 | o = uint32(i)<<6 + uint32(c2) | ||
429 | i = idnaIndex[o] | ||
430 | c3 := s[3] | ||
431 | if c3 < 0x80 || 0xC0 <= c3 { | ||
432 | return 0, 3 // Illegal UTF-8: not a continuation byte. | ||
433 | } | ||
434 | return t.lookupValue(uint32(i), c3), 4 | ||
435 | } | ||
436 | // Illegal rune | ||
437 | return 0, 1 | ||
438 | } | ||
439 | |||
440 | // lookupUnsafe returns the trie value for the first UTF-8 encoding in s. | ||
441 | // s must start with a full and valid UTF-8 encoded rune. | ||
442 | func (t *idnaTrie) lookupUnsafe(s []byte) uint16 { | ||
443 | c0 := s[0] | ||
444 | if c0 < 0x80 { // is ASCII | ||
445 | return idnaValues[c0] | ||
446 | } | ||
447 | i := idnaIndex[c0] | ||
448 | if c0 < 0xE0 { // 2-byte UTF-8 | ||
449 | return t.lookupValue(uint32(i), s[1]) | ||
450 | } | ||
451 | i = idnaIndex[uint32(i)<<6+uint32(s[1])] | ||
452 | if c0 < 0xF0 { // 3-byte UTF-8 | ||
453 | return t.lookupValue(uint32(i), s[2]) | ||
454 | } | ||
455 | i = idnaIndex[uint32(i)<<6+uint32(s[2])] | ||
456 | if c0 < 0xF8 { // 4-byte UTF-8 | ||
457 | return t.lookupValue(uint32(i), s[3]) | ||
458 | } | ||
459 | return 0 | ||
460 | } | ||
461 | |||
462 | // lookupString returns the trie value for the first UTF-8 encoding in s and | ||
463 | // the width in bytes of this encoding. The size will be 0 if s does not | ||
464 | // hold enough bytes to complete the encoding. len(s) must be greater than 0. | ||
465 | func (t *idnaTrie) lookupString(s string) (v uint16, sz int) { | ||
466 | c0 := s[0] | ||
467 | switch { | ||
468 | case c0 < 0x80: // is ASCII | ||
469 | return idnaValues[c0], 1 | ||
470 | case c0 < 0xC2: | ||
471 | return 0, 1 // Illegal UTF-8: not a starter, not ASCII. | ||
472 | case c0 < 0xE0: // 2-byte UTF-8 | ||
473 | if len(s) < 2 { | ||
474 | return 0, 0 | ||
475 | } | ||
476 | i := idnaIndex[c0] | ||
477 | c1 := s[1] | ||
478 | if c1 < 0x80 || 0xC0 <= c1 { | ||
479 | return 0, 1 // Illegal UTF-8: not a continuation byte. | ||
480 | } | ||
481 | return t.lookupValue(uint32(i), c1), 2 | ||
482 | case c0 < 0xF0: // 3-byte UTF-8 | ||
483 | if len(s) < 3 { | ||
484 | return 0, 0 | ||
485 | } | ||
486 | i := idnaIndex[c0] | ||
487 | c1 := s[1] | ||
488 | if c1 < 0x80 || 0xC0 <= c1 { | ||
489 | return 0, 1 // Illegal UTF-8: not a continuation byte. | ||
490 | } | ||
491 | o := uint32(i)<<6 + uint32(c1) | ||
492 | i = idnaIndex[o] | ||
493 | c2 := s[2] | ||
494 | if c2 < 0x80 || 0xC0 <= c2 { | ||
495 | return 0, 2 // Illegal UTF-8: not a continuation byte. | ||
496 | } | ||
497 | return t.lookupValue(uint32(i), c2), 3 | ||
498 | case c0 < 0xF8: // 4-byte UTF-8 | ||
499 | if len(s) < 4 { | ||
500 | return 0, 0 | ||
501 | } | ||
502 | i := idnaIndex[c0] | ||
503 | c1 := s[1] | ||
504 | if c1 < 0x80 || 0xC0 <= c1 { | ||
505 | return 0, 1 // Illegal UTF-8: not a continuation byte. | ||
506 | } | ||
507 | o := uint32(i)<<6 + uint32(c1) | ||
508 | i = idnaIndex[o] | ||
509 | c2 := s[2] | ||
510 | if c2 < 0x80 || 0xC0 <= c2 { | ||
511 | return 0, 2 // Illegal UTF-8: not a continuation byte. | ||
512 | } | ||
513 | o = uint32(i)<<6 + uint32(c2) | ||
514 | i = idnaIndex[o] | ||
515 | c3 := s[3] | ||
516 | if c3 < 0x80 || 0xC0 <= c3 { | ||
517 | return 0, 3 // Illegal UTF-8: not a continuation byte. | ||
518 | } | ||
519 | return t.lookupValue(uint32(i), c3), 4 | ||
520 | } | ||
521 | // Illegal rune | ||
522 | return 0, 1 | ||
523 | } | ||
524 | |||
525 | // lookupStringUnsafe returns the trie value for the first UTF-8 encoding in s. | ||
526 | // s must start with a full and valid UTF-8 encoded rune. | ||
527 | func (t *idnaTrie) lookupStringUnsafe(s string) uint16 { | ||
528 | c0 := s[0] | ||
529 | if c0 < 0x80 { // is ASCII | ||
530 | return idnaValues[c0] | ||
531 | } | ||
532 | i := idnaIndex[c0] | ||
533 | if c0 < 0xE0 { // 2-byte UTF-8 | ||
534 | return t.lookupValue(uint32(i), s[1]) | ||
535 | } | ||
536 | i = idnaIndex[uint32(i)<<6+uint32(s[1])] | ||
537 | if c0 < 0xF0 { // 3-byte UTF-8 | ||
538 | return t.lookupValue(uint32(i), s[2]) | ||
539 | } | ||
540 | i = idnaIndex[uint32(i)<<6+uint32(s[2])] | ||
541 | if c0 < 0xF8 { // 4-byte UTF-8 | ||
542 | return t.lookupValue(uint32(i), s[3]) | ||
543 | } | ||
544 | return 0 | ||
545 | } | ||
546 | |||
547 | // idnaTrie. Total size: 28496 bytes (27.83 KiB). Checksum: 43288b883596640e. | ||
548 | type idnaTrie struct{} | ||
549 | |||
550 | func newIdnaTrie(i int) *idnaTrie { | ||
551 | return &idnaTrie{} | ||
552 | } | ||
553 | |||
554 | // lookupValue determines the type of block n and looks up the value for b. | ||
555 | func (t *idnaTrie) lookupValue(n uint32, b byte) uint16 { | ||
556 | switch { | ||
557 | case n < 123: | ||
558 | return uint16(idnaValues[n<<6+uint32(b)]) | ||
559 | default: | ||
560 | n -= 123 | ||
561 | return uint16(idnaSparse.lookup(n, b)) | ||
562 | } | ||
563 | } | ||
564 | |||
565 | // idnaValues: 125 blocks, 8000 entries, 16000 bytes | ||
566 | // The third block is the zero block. | ||
567 | var idnaValues = [8000]uint16{ | ||
568 | // Block 0x0, offset 0x0 | ||
569 | 0x00: 0x0080, 0x01: 0x0080, 0x02: 0x0080, 0x03: 0x0080, 0x04: 0x0080, 0x05: 0x0080, | ||
570 | 0x06: 0x0080, 0x07: 0x0080, 0x08: 0x0080, 0x09: 0x0080, 0x0a: 0x0080, 0x0b: 0x0080, | ||
571 | 0x0c: 0x0080, 0x0d: 0x0080, 0x0e: 0x0080, 0x0f: 0x0080, 0x10: 0x0080, 0x11: 0x0080, | ||
572 | 0x12: 0x0080, 0x13: 0x0080, 0x14: 0x0080, 0x15: 0x0080, 0x16: 0x0080, 0x17: 0x0080, | ||
573 | 0x18: 0x0080, 0x19: 0x0080, 0x1a: 0x0080, 0x1b: 0x0080, 0x1c: 0x0080, 0x1d: 0x0080, | ||
574 | 0x1e: 0x0080, 0x1f: 0x0080, 0x20: 0x0080, 0x21: 0x0080, 0x22: 0x0080, 0x23: 0x0080, | ||
575 | 0x24: 0x0080, 0x25: 0x0080, 0x26: 0x0080, 0x27: 0x0080, 0x28: 0x0080, 0x29: 0x0080, | ||
576 | 0x2a: 0x0080, 0x2b: 0x0080, 0x2c: 0x0080, 0x2d: 0x0008, 0x2e: 0x0008, 0x2f: 0x0080, | ||
577 | 0x30: 0x0008, 0x31: 0x0008, 0x32: 0x0008, 0x33: 0x0008, 0x34: 0x0008, 0x35: 0x0008, | ||
578 | 0x36: 0x0008, 0x37: 0x0008, 0x38: 0x0008, 0x39: 0x0008, 0x3a: 0x0080, 0x3b: 0x0080, | ||
579 | 0x3c: 0x0080, 0x3d: 0x0080, 0x3e: 0x0080, 0x3f: 0x0080, | ||
580 | // Block 0x1, offset 0x40 | ||
581 | 0x40: 0x0080, 0x41: 0xe105, 0x42: 0xe105, 0x43: 0xe105, 0x44: 0xe105, 0x45: 0xe105, | ||
582 | 0x46: 0xe105, 0x47: 0xe105, 0x48: 0xe105, 0x49: 0xe105, 0x4a: 0xe105, 0x4b: 0xe105, | ||
583 | 0x4c: 0xe105, 0x4d: 0xe105, 0x4e: 0xe105, 0x4f: 0xe105, 0x50: 0xe105, 0x51: 0xe105, | ||
584 | 0x52: 0xe105, 0x53: 0xe105, 0x54: 0xe105, 0x55: 0xe105, 0x56: 0xe105, 0x57: 0xe105, | ||
585 | 0x58: 0xe105, 0x59: 0xe105, 0x5a: 0xe105, 0x5b: 0x0080, 0x5c: 0x0080, 0x5d: 0x0080, | ||
586 | 0x5e: 0x0080, 0x5f: 0x0080, 0x60: 0x0080, 0x61: 0x0008, 0x62: 0x0008, 0x63: 0x0008, | ||
587 | 0x64: 0x0008, 0x65: 0x0008, 0x66: 0x0008, 0x67: 0x0008, 0x68: 0x0008, 0x69: 0x0008, | ||
588 | 0x6a: 0x0008, 0x6b: 0x0008, 0x6c: 0x0008, 0x6d: 0x0008, 0x6e: 0x0008, 0x6f: 0x0008, | ||
589 | 0x70: 0x0008, 0x71: 0x0008, 0x72: 0x0008, 0x73: 0x0008, 0x74: 0x0008, 0x75: 0x0008, | ||
590 | 0x76: 0x0008, 0x77: 0x0008, 0x78: 0x0008, 0x79: 0x0008, 0x7a: 0x0008, 0x7b: 0x0080, | ||
591 | 0x7c: 0x0080, 0x7d: 0x0080, 0x7e: 0x0080, 0x7f: 0x0080, | ||
592 | // Block 0x2, offset 0x80 | ||
593 | // Block 0x3, offset 0xc0 | ||
594 | 0xc0: 0x0040, 0xc1: 0x0040, 0xc2: 0x0040, 0xc3: 0x0040, 0xc4: 0x0040, 0xc5: 0x0040, | ||
595 | 0xc6: 0x0040, 0xc7: 0x0040, 0xc8: 0x0040, 0xc9: 0x0040, 0xca: 0x0040, 0xcb: 0x0040, | ||
596 | 0xcc: 0x0040, 0xcd: 0x0040, 0xce: 0x0040, 0xcf: 0x0040, 0xd0: 0x0040, 0xd1: 0x0040, | ||
597 | 0xd2: 0x0040, 0xd3: 0x0040, 0xd4: 0x0040, 0xd5: 0x0040, 0xd6: 0x0040, 0xd7: 0x0040, | ||
598 | 0xd8: 0x0040, 0xd9: 0x0040, 0xda: 0x0040, 0xdb: 0x0040, 0xdc: 0x0040, 0xdd: 0x0040, | ||
599 | 0xde: 0x0040, 0xdf: 0x0040, 0xe0: 0x000a, 0xe1: 0x0018, 0xe2: 0x0018, 0xe3: 0x0018, | ||
600 | 0xe4: 0x0018, 0xe5: 0x0018, 0xe6: 0x0018, 0xe7: 0x0018, 0xe8: 0x001a, 0xe9: 0x0018, | ||
601 | 0xea: 0x0039, 0xeb: 0x0018, 0xec: 0x0018, 0xed: 0x03c0, 0xee: 0x0018, 0xef: 0x004a, | ||
602 | 0xf0: 0x0018, 0xf1: 0x0018, 0xf2: 0x0069, 0xf3: 0x0079, 0xf4: 0x008a, 0xf5: 0x0005, | ||
603 | 0xf6: 0x0018, 0xf7: 0x0008, 0xf8: 0x00aa, 0xf9: 0x00c9, 0xfa: 0x00d9, 0xfb: 0x0018, | ||
604 | 0xfc: 0x00e9, 0xfd: 0x0119, 0xfe: 0x0149, 0xff: 0x0018, | ||
605 | // Block 0x4, offset 0x100 | ||
606 | 0x100: 0xe00d, 0x101: 0x0008, 0x102: 0xe00d, 0x103: 0x0008, 0x104: 0xe00d, 0x105: 0x0008, | ||
607 | 0x106: 0xe00d, 0x107: 0x0008, 0x108: 0xe00d, 0x109: 0x0008, 0x10a: 0xe00d, 0x10b: 0x0008, | ||
608 | 0x10c: 0xe00d, 0x10d: 0x0008, 0x10e: 0xe00d, 0x10f: 0x0008, 0x110: 0xe00d, 0x111: 0x0008, | ||
609 | 0x112: 0xe00d, 0x113: 0x0008, 0x114: 0xe00d, 0x115: 0x0008, 0x116: 0xe00d, 0x117: 0x0008, | ||
610 | 0x118: 0xe00d, 0x119: 0x0008, 0x11a: 0xe00d, 0x11b: 0x0008, 0x11c: 0xe00d, 0x11d: 0x0008, | ||
611 | 0x11e: 0xe00d, 0x11f: 0x0008, 0x120: 0xe00d, 0x121: 0x0008, 0x122: 0xe00d, 0x123: 0x0008, | ||
612 | 0x124: 0xe00d, 0x125: 0x0008, 0x126: 0xe00d, 0x127: 0x0008, 0x128: 0xe00d, 0x129: 0x0008, | ||
613 | 0x12a: 0xe00d, 0x12b: 0x0008, 0x12c: 0xe00d, 0x12d: 0x0008, 0x12e: 0xe00d, 0x12f: 0x0008, | ||
614 | 0x130: 0x0179, 0x131: 0x0008, 0x132: 0x0035, 0x133: 0x004d, 0x134: 0xe00d, 0x135: 0x0008, | ||
615 | 0x136: 0xe00d, 0x137: 0x0008, 0x138: 0x0008, 0x139: 0xe01d, 0x13a: 0x0008, 0x13b: 0xe03d, | ||
616 | 0x13c: 0x0008, 0x13d: 0xe01d, 0x13e: 0x0008, 0x13f: 0x0199, | ||
617 | // Block 0x5, offset 0x140 | ||
618 | 0x140: 0x0199, 0x141: 0xe01d, 0x142: 0x0008, 0x143: 0xe03d, 0x144: 0x0008, 0x145: 0xe01d, | ||
619 | 0x146: 0x0008, 0x147: 0xe07d, 0x148: 0x0008, 0x149: 0x01b9, 0x14a: 0xe00d, 0x14b: 0x0008, | ||
620 | 0x14c: 0xe00d, 0x14d: 0x0008, 0x14e: 0xe00d, 0x14f: 0x0008, 0x150: 0xe00d, 0x151: 0x0008, | ||
621 | 0x152: 0xe00d, 0x153: 0x0008, 0x154: 0xe00d, 0x155: 0x0008, 0x156: 0xe00d, 0x157: 0x0008, | ||
622 | 0x158: 0xe00d, 0x159: 0x0008, 0x15a: 0xe00d, 0x15b: 0x0008, 0x15c: 0xe00d, 0x15d: 0x0008, | ||
623 | 0x15e: 0xe00d, 0x15f: 0x0008, 0x160: 0xe00d, 0x161: 0x0008, 0x162: 0xe00d, 0x163: 0x0008, | ||
624 | 0x164: 0xe00d, 0x165: 0x0008, 0x166: 0xe00d, 0x167: 0x0008, 0x168: 0xe00d, 0x169: 0x0008, | ||
625 | 0x16a: 0xe00d, 0x16b: 0x0008, 0x16c: 0xe00d, 0x16d: 0x0008, 0x16e: 0xe00d, 0x16f: 0x0008, | ||
626 | 0x170: 0xe00d, 0x171: 0x0008, 0x172: 0xe00d, 0x173: 0x0008, 0x174: 0xe00d, 0x175: 0x0008, | ||
627 | 0x176: 0xe00d, 0x177: 0x0008, 0x178: 0x0065, 0x179: 0xe01d, 0x17a: 0x0008, 0x17b: 0xe03d, | ||
628 | 0x17c: 0x0008, 0x17d: 0xe01d, 0x17e: 0x0008, 0x17f: 0x01d9, | ||
629 | // Block 0x6, offset 0x180 | ||
630 | 0x180: 0x0008, 0x181: 0x007d, 0x182: 0xe00d, 0x183: 0x0008, 0x184: 0xe00d, 0x185: 0x0008, | ||
631 | 0x186: 0x007d, 0x187: 0xe07d, 0x188: 0x0008, 0x189: 0x0095, 0x18a: 0x00ad, 0x18b: 0xe03d, | ||
632 | 0x18c: 0x0008, 0x18d: 0x0008, 0x18e: 0x00c5, 0x18f: 0x00dd, 0x190: 0x00f5, 0x191: 0xe01d, | ||
633 | 0x192: 0x0008, 0x193: 0x010d, 0x194: 0x0125, 0x195: 0x0008, 0x196: 0x013d, 0x197: 0x013d, | ||
634 | 0x198: 0xe00d, 0x199: 0x0008, 0x19a: 0x0008, 0x19b: 0x0008, 0x19c: 0x010d, 0x19d: 0x0155, | ||
635 | 0x19e: 0x0008, 0x19f: 0x016d, 0x1a0: 0xe00d, 0x1a1: 0x0008, 0x1a2: 0xe00d, 0x1a3: 0x0008, | ||
636 | 0x1a4: 0xe00d, 0x1a5: 0x0008, 0x1a6: 0x0185, 0x1a7: 0xe07d, 0x1a8: 0x0008, 0x1a9: 0x019d, | ||
637 | 0x1aa: 0x0008, 0x1ab: 0x0008, 0x1ac: 0xe00d, 0x1ad: 0x0008, 0x1ae: 0x0185, 0x1af: 0xe0fd, | ||
638 | 0x1b0: 0x0008, 0x1b1: 0x01b5, 0x1b2: 0x01cd, 0x1b3: 0xe03d, 0x1b4: 0x0008, 0x1b5: 0xe01d, | ||
639 | 0x1b6: 0x0008, 0x1b7: 0x01e5, 0x1b8: 0xe00d, 0x1b9: 0x0008, 0x1ba: 0x0008, 0x1bb: 0x0008, | ||
640 | 0x1bc: 0xe00d, 0x1bd: 0x0008, 0x1be: 0x0008, 0x1bf: 0x0008, | ||
641 | // Block 0x7, offset 0x1c0 | ||
642 | 0x1c0: 0x0008, 0x1c1: 0x0008, 0x1c2: 0x0008, 0x1c3: 0x0008, 0x1c4: 0x01e9, 0x1c5: 0x01e9, | ||
643 | 0x1c6: 0x01e9, 0x1c7: 0x01fd, 0x1c8: 0x0215, 0x1c9: 0x022d, 0x1ca: 0x0245, 0x1cb: 0x025d, | ||
644 | 0x1cc: 0x0275, 0x1cd: 0xe01d, 0x1ce: 0x0008, 0x1cf: 0xe0fd, 0x1d0: 0x0008, 0x1d1: 0xe01d, | ||
645 | 0x1d2: 0x0008, 0x1d3: 0xe03d, 0x1d4: 0x0008, 0x1d5: 0xe01d, 0x1d6: 0x0008, 0x1d7: 0xe07d, | ||
646 | 0x1d8: 0x0008, 0x1d9: 0xe01d, 0x1da: 0x0008, 0x1db: 0xe03d, 0x1dc: 0x0008, 0x1dd: 0x0008, | ||
647 | 0x1de: 0xe00d, 0x1df: 0x0008, 0x1e0: 0xe00d, 0x1e1: 0x0008, 0x1e2: 0xe00d, 0x1e3: 0x0008, | ||
648 | 0x1e4: 0xe00d, 0x1e5: 0x0008, 0x1e6: 0xe00d, 0x1e7: 0x0008, 0x1e8: 0xe00d, 0x1e9: 0x0008, | ||
649 | 0x1ea: 0xe00d, 0x1eb: 0x0008, 0x1ec: 0xe00d, 0x1ed: 0x0008, 0x1ee: 0xe00d, 0x1ef: 0x0008, | ||
650 | 0x1f0: 0x0008, 0x1f1: 0x028d, 0x1f2: 0x02a5, 0x1f3: 0x02bd, 0x1f4: 0xe00d, 0x1f5: 0x0008, | ||
651 | 0x1f6: 0x02d5, 0x1f7: 0x02ed, 0x1f8: 0xe00d, 0x1f9: 0x0008, 0x1fa: 0xe00d, 0x1fb: 0x0008, | ||
652 | 0x1fc: 0xe00d, 0x1fd: 0x0008, 0x1fe: 0xe00d, 0x1ff: 0x0008, | ||
653 | // Block 0x8, offset 0x200 | ||
654 | 0x200: 0xe00d, 0x201: 0x0008, 0x202: 0xe00d, 0x203: 0x0008, 0x204: 0xe00d, 0x205: 0x0008, | ||
655 | 0x206: 0xe00d, 0x207: 0x0008, 0x208: 0xe00d, 0x209: 0x0008, 0x20a: 0xe00d, 0x20b: 0x0008, | ||
656 | 0x20c: 0xe00d, 0x20d: 0x0008, 0x20e: 0xe00d, 0x20f: 0x0008, 0x210: 0xe00d, 0x211: 0x0008, | ||
657 | 0x212: 0xe00d, 0x213: 0x0008, 0x214: 0xe00d, 0x215: 0x0008, 0x216: 0xe00d, 0x217: 0x0008, | ||
658 | 0x218: 0xe00d, 0x219: 0x0008, 0x21a: 0xe00d, 0x21b: 0x0008, 0x21c: 0xe00d, 0x21d: 0x0008, | ||
659 | 0x21e: 0xe00d, 0x21f: 0x0008, 0x220: 0x0305, 0x221: 0x0008, 0x222: 0xe00d, 0x223: 0x0008, | ||
660 | 0x224: 0xe00d, 0x225: 0x0008, 0x226: 0xe00d, 0x227: 0x0008, 0x228: 0xe00d, 0x229: 0x0008, | ||
661 | 0x22a: 0xe00d, 0x22b: 0x0008, 0x22c: 0xe00d, 0x22d: 0x0008, 0x22e: 0xe00d, 0x22f: 0x0008, | ||
662 | 0x230: 0xe00d, 0x231: 0x0008, 0x232: 0xe00d, 0x233: 0x0008, 0x234: 0x0008, 0x235: 0x0008, | ||
663 | 0x236: 0x0008, 0x237: 0x0008, 0x238: 0x0008, 0x239: 0x0008, 0x23a: 0x0209, 0x23b: 0xe03d, | ||
664 | 0x23c: 0x0008, 0x23d: 0x031d, 0x23e: 0x0229, 0x23f: 0x0008, | ||
665 | // Block 0x9, offset 0x240 | ||
666 | 0x240: 0x0008, 0x241: 0x0008, 0x242: 0x0018, 0x243: 0x0018, 0x244: 0x0018, 0x245: 0x0018, | ||
667 | 0x246: 0x0008, 0x247: 0x0008, 0x248: 0x0008, 0x249: 0x0008, 0x24a: 0x0008, 0x24b: 0x0008, | ||
668 | 0x24c: 0x0008, 0x24d: 0x0008, 0x24e: 0x0008, 0x24f: 0x0008, 0x250: 0x0008, 0x251: 0x0008, | ||
669 | 0x252: 0x0018, 0x253: 0x0018, 0x254: 0x0018, 0x255: 0x0018, 0x256: 0x0018, 0x257: 0x0018, | ||
670 | 0x258: 0x029a, 0x259: 0x02ba, 0x25a: 0x02da, 0x25b: 0x02fa, 0x25c: 0x031a, 0x25d: 0x033a, | ||
671 | 0x25e: 0x0018, 0x25f: 0x0018, 0x260: 0x03ad, 0x261: 0x0359, 0x262: 0x01d9, 0x263: 0x0369, | ||
672 | 0x264: 0x03c5, 0x265: 0x0018, 0x266: 0x0018, 0x267: 0x0018, 0x268: 0x0018, 0x269: 0x0018, | ||
673 | 0x26a: 0x0018, 0x26b: 0x0018, 0x26c: 0x0008, 0x26d: 0x0018, 0x26e: 0x0008, 0x26f: 0x0018, | ||
674 | 0x270: 0x0018, 0x271: 0x0018, 0x272: 0x0018, 0x273: 0x0018, 0x274: 0x0018, 0x275: 0x0018, | ||
675 | 0x276: 0x0018, 0x277: 0x0018, 0x278: 0x0018, 0x279: 0x0018, 0x27a: 0x0018, 0x27b: 0x0018, | ||
676 | 0x27c: 0x0018, 0x27d: 0x0018, 0x27e: 0x0018, 0x27f: 0x0018, | ||
677 | // Block 0xa, offset 0x280 | ||
678 | 0x280: 0x03dd, 0x281: 0x03dd, 0x282: 0x1308, 0x283: 0x03f5, 0x284: 0x0379, 0x285: 0x040d, | ||
679 | 0x286: 0x1308, 0x287: 0x1308, 0x288: 0x1308, 0x289: 0x1308, 0x28a: 0x1308, 0x28b: 0x1308, | ||
680 | 0x28c: 0x1308, 0x28d: 0x1308, 0x28e: 0x1308, 0x28f: 0x13c0, 0x290: 0x1308, 0x291: 0x1308, | ||
681 | 0x292: 0x1308, 0x293: 0x1308, 0x294: 0x1308, 0x295: 0x1308, 0x296: 0x1308, 0x297: 0x1308, | ||
682 | 0x298: 0x1308, 0x299: 0x1308, 0x29a: 0x1308, 0x29b: 0x1308, 0x29c: 0x1308, 0x29d: 0x1308, | ||
683 | 0x29e: 0x1308, 0x29f: 0x1308, 0x2a0: 0x1308, 0x2a1: 0x1308, 0x2a2: 0x1308, 0x2a3: 0x1308, | ||
684 | 0x2a4: 0x1308, 0x2a5: 0x1308, 0x2a6: 0x1308, 0x2a7: 0x1308, 0x2a8: 0x1308, 0x2a9: 0x1308, | ||
685 | 0x2aa: 0x1308, 0x2ab: 0x1308, 0x2ac: 0x1308, 0x2ad: 0x1308, 0x2ae: 0x1308, 0x2af: 0x1308, | ||
686 | 0x2b0: 0xe00d, 0x2b1: 0x0008, 0x2b2: 0xe00d, 0x2b3: 0x0008, 0x2b4: 0x0425, 0x2b5: 0x0008, | ||
687 | 0x2b6: 0xe00d, 0x2b7: 0x0008, 0x2b8: 0x0040, 0x2b9: 0x0040, 0x2ba: 0x03a2, 0x2bb: 0x0008, | ||
688 | 0x2bc: 0x0008, 0x2bd: 0x0008, 0x2be: 0x03c2, 0x2bf: 0x043d, | ||
689 | // Block 0xb, offset 0x2c0 | ||
690 | 0x2c0: 0x0040, 0x2c1: 0x0040, 0x2c2: 0x0040, 0x2c3: 0x0040, 0x2c4: 0x008a, 0x2c5: 0x03d2, | ||
691 | 0x2c6: 0xe155, 0x2c7: 0x0455, 0x2c8: 0xe12d, 0x2c9: 0xe13d, 0x2ca: 0xe12d, 0x2cb: 0x0040, | ||
692 | 0x2cc: 0x03dd, 0x2cd: 0x0040, 0x2ce: 0x046d, 0x2cf: 0x0485, 0x2d0: 0x0008, 0x2d1: 0xe105, | ||
693 | 0x2d2: 0xe105, 0x2d3: 0xe105, 0x2d4: 0xe105, 0x2d5: 0xe105, 0x2d6: 0xe105, 0x2d7: 0xe105, | ||
694 | 0x2d8: 0xe105, 0x2d9: 0xe105, 0x2da: 0xe105, 0x2db: 0xe105, 0x2dc: 0xe105, 0x2dd: 0xe105, | ||
695 | 0x2de: 0xe105, 0x2df: 0xe105, 0x2e0: 0x049d, 0x2e1: 0x049d, 0x2e2: 0x0040, 0x2e3: 0x049d, | ||
696 | 0x2e4: 0x049d, 0x2e5: 0x049d, 0x2e6: 0x049d, 0x2e7: 0x049d, 0x2e8: 0x049d, 0x2e9: 0x049d, | ||
697 | 0x2ea: 0x049d, 0x2eb: 0x049d, 0x2ec: 0x0008, 0x2ed: 0x0008, 0x2ee: 0x0008, 0x2ef: 0x0008, | ||
698 | 0x2f0: 0x0008, 0x2f1: 0x0008, 0x2f2: 0x0008, 0x2f3: 0x0008, 0x2f4: 0x0008, 0x2f5: 0x0008, | ||
699 | 0x2f6: 0x0008, 0x2f7: 0x0008, 0x2f8: 0x0008, 0x2f9: 0x0008, 0x2fa: 0x0008, 0x2fb: 0x0008, | ||
700 | 0x2fc: 0x0008, 0x2fd: 0x0008, 0x2fe: 0x0008, 0x2ff: 0x0008, | ||
701 | // Block 0xc, offset 0x300 | ||
702 | 0x300: 0x0008, 0x301: 0x0008, 0x302: 0xe00f, 0x303: 0x0008, 0x304: 0x0008, 0x305: 0x0008, | ||
703 | 0x306: 0x0008, 0x307: 0x0008, 0x308: 0x0008, 0x309: 0x0008, 0x30a: 0x0008, 0x30b: 0x0008, | ||
704 | 0x30c: 0x0008, 0x30d: 0x0008, 0x30e: 0x0008, 0x30f: 0xe0c5, 0x310: 0x04b5, 0x311: 0x04cd, | ||
705 | 0x312: 0xe0bd, 0x313: 0xe0f5, 0x314: 0xe0fd, 0x315: 0xe09d, 0x316: 0xe0b5, 0x317: 0x0008, | ||
706 | 0x318: 0xe00d, 0x319: 0x0008, 0x31a: 0xe00d, 0x31b: 0x0008, 0x31c: 0xe00d, 0x31d: 0x0008, | ||
707 | 0x31e: 0xe00d, 0x31f: 0x0008, 0x320: 0xe00d, 0x321: 0x0008, 0x322: 0xe00d, 0x323: 0x0008, | ||
708 | 0x324: 0xe00d, 0x325: 0x0008, 0x326: 0xe00d, 0x327: 0x0008, 0x328: 0xe00d, 0x329: 0x0008, | ||
709 | 0x32a: 0xe00d, 0x32b: 0x0008, 0x32c: 0xe00d, 0x32d: 0x0008, 0x32e: 0xe00d, 0x32f: 0x0008, | ||
710 | 0x330: 0x04e5, 0x331: 0xe185, 0x332: 0xe18d, 0x333: 0x0008, 0x334: 0x04fd, 0x335: 0x03dd, | ||
711 | 0x336: 0x0018, 0x337: 0xe07d, 0x338: 0x0008, 0x339: 0xe1d5, 0x33a: 0xe00d, 0x33b: 0x0008, | ||
712 | 0x33c: 0x0008, 0x33d: 0x0515, 0x33e: 0x052d, 0x33f: 0x052d, | ||
713 | // Block 0xd, offset 0x340 | ||
714 | 0x340: 0x0008, 0x341: 0x0008, 0x342: 0x0008, 0x343: 0x0008, 0x344: 0x0008, 0x345: 0x0008, | ||
715 | 0x346: 0x0008, 0x347: 0x0008, 0x348: 0x0008, 0x349: 0x0008, 0x34a: 0x0008, 0x34b: 0x0008, | ||
716 | 0x34c: 0x0008, 0x34d: 0x0008, 0x34e: 0x0008, 0x34f: 0x0008, 0x350: 0x0008, 0x351: 0x0008, | ||
717 | 0x352: 0x0008, 0x353: 0x0008, 0x354: 0x0008, 0x355: 0x0008, 0x356: 0x0008, 0x357: 0x0008, | ||
718 | 0x358: 0x0008, 0x359: 0x0008, 0x35a: 0x0008, 0x35b: 0x0008, 0x35c: 0x0008, 0x35d: 0x0008, | ||
719 | 0x35e: 0x0008, 0x35f: 0x0008, 0x360: 0xe00d, 0x361: 0x0008, 0x362: 0xe00d, 0x363: 0x0008, | ||
720 | 0x364: 0xe00d, 0x365: 0x0008, 0x366: 0xe00d, 0x367: 0x0008, 0x368: 0xe00d, 0x369: 0x0008, | ||
721 | 0x36a: 0xe00d, 0x36b: 0x0008, 0x36c: 0xe00d, 0x36d: 0x0008, 0x36e: 0xe00d, 0x36f: 0x0008, | ||
722 | 0x370: 0xe00d, 0x371: 0x0008, 0x372: 0xe00d, 0x373: 0x0008, 0x374: 0xe00d, 0x375: 0x0008, | ||
723 | 0x376: 0xe00d, 0x377: 0x0008, 0x378: 0xe00d, 0x379: 0x0008, 0x37a: 0xe00d, 0x37b: 0x0008, | ||
724 | 0x37c: 0xe00d, 0x37d: 0x0008, 0x37e: 0xe00d, 0x37f: 0x0008, | ||
725 | // Block 0xe, offset 0x380 | ||
726 | 0x380: 0xe00d, 0x381: 0x0008, 0x382: 0x0018, 0x383: 0x1308, 0x384: 0x1308, 0x385: 0x1308, | ||
727 | 0x386: 0x1308, 0x387: 0x1308, 0x388: 0x1318, 0x389: 0x1318, 0x38a: 0xe00d, 0x38b: 0x0008, | ||
728 | 0x38c: 0xe00d, 0x38d: 0x0008, 0x38e: 0xe00d, 0x38f: 0x0008, 0x390: 0xe00d, 0x391: 0x0008, | ||
729 | 0x392: 0xe00d, 0x393: 0x0008, 0x394: 0xe00d, 0x395: 0x0008, 0x396: 0xe00d, 0x397: 0x0008, | ||
730 | 0x398: 0xe00d, 0x399: 0x0008, 0x39a: 0xe00d, 0x39b: 0x0008, 0x39c: 0xe00d, 0x39d: 0x0008, | ||
731 | 0x39e: 0xe00d, 0x39f: 0x0008, 0x3a0: 0xe00d, 0x3a1: 0x0008, 0x3a2: 0xe00d, 0x3a3: 0x0008, | ||
732 | 0x3a4: 0xe00d, 0x3a5: 0x0008, 0x3a6: 0xe00d, 0x3a7: 0x0008, 0x3a8: 0xe00d, 0x3a9: 0x0008, | ||
733 | 0x3aa: 0xe00d, 0x3ab: 0x0008, 0x3ac: 0xe00d, 0x3ad: 0x0008, 0x3ae: 0xe00d, 0x3af: 0x0008, | ||
734 | 0x3b0: 0xe00d, 0x3b1: 0x0008, 0x3b2: 0xe00d, 0x3b3: 0x0008, 0x3b4: 0xe00d, 0x3b5: 0x0008, | ||
735 | 0x3b6: 0xe00d, 0x3b7: 0x0008, 0x3b8: 0xe00d, 0x3b9: 0x0008, 0x3ba: 0xe00d, 0x3bb: 0x0008, | ||
736 | 0x3bc: 0xe00d, 0x3bd: 0x0008, 0x3be: 0xe00d, 0x3bf: 0x0008, | ||
737 | // Block 0xf, offset 0x3c0 | ||
738 | 0x3c0: 0x0040, 0x3c1: 0xe01d, 0x3c2: 0x0008, 0x3c3: 0xe03d, 0x3c4: 0x0008, 0x3c5: 0xe01d, | ||
739 | 0x3c6: 0x0008, 0x3c7: 0xe07d, 0x3c8: 0x0008, 0x3c9: 0xe01d, 0x3ca: 0x0008, 0x3cb: 0xe03d, | ||
740 | 0x3cc: 0x0008, 0x3cd: 0xe01d, 0x3ce: 0x0008, 0x3cf: 0x0008, 0x3d0: 0xe00d, 0x3d1: 0x0008, | ||
741 | 0x3d2: 0xe00d, 0x3d3: 0x0008, 0x3d4: 0xe00d, 0x3d5: 0x0008, 0x3d6: 0xe00d, 0x3d7: 0x0008, | ||
742 | 0x3d8: 0xe00d, 0x3d9: 0x0008, 0x3da: 0xe00d, 0x3db: 0x0008, 0x3dc: 0xe00d, 0x3dd: 0x0008, | ||
743 | 0x3de: 0xe00d, 0x3df: 0x0008, 0x3e0: 0xe00d, 0x3e1: 0x0008, 0x3e2: 0xe00d, 0x3e3: 0x0008, | ||
744 | 0x3e4: 0xe00d, 0x3e5: 0x0008, 0x3e6: 0xe00d, 0x3e7: 0x0008, 0x3e8: 0xe00d, 0x3e9: 0x0008, | ||
745 | 0x3ea: 0xe00d, 0x3eb: 0x0008, 0x3ec: 0xe00d, 0x3ed: 0x0008, 0x3ee: 0xe00d, 0x3ef: 0x0008, | ||
746 | 0x3f0: 0xe00d, 0x3f1: 0x0008, 0x3f2: 0xe00d, 0x3f3: 0x0008, 0x3f4: 0xe00d, 0x3f5: 0x0008, | ||
747 | 0x3f6: 0xe00d, 0x3f7: 0x0008, 0x3f8: 0xe00d, 0x3f9: 0x0008, 0x3fa: 0xe00d, 0x3fb: 0x0008, | ||
748 | 0x3fc: 0xe00d, 0x3fd: 0x0008, 0x3fe: 0xe00d, 0x3ff: 0x0008, | ||
749 | // Block 0x10, offset 0x400 | ||
750 | 0x400: 0xe00d, 0x401: 0x0008, 0x402: 0xe00d, 0x403: 0x0008, 0x404: 0xe00d, 0x405: 0x0008, | ||
751 | 0x406: 0xe00d, 0x407: 0x0008, 0x408: 0xe00d, 0x409: 0x0008, 0x40a: 0xe00d, 0x40b: 0x0008, | ||
752 | 0x40c: 0xe00d, 0x40d: 0x0008, 0x40e: 0xe00d, 0x40f: 0x0008, 0x410: 0xe00d, 0x411: 0x0008, | ||
753 | 0x412: 0xe00d, 0x413: 0x0008, 0x414: 0xe00d, 0x415: 0x0008, 0x416: 0xe00d, 0x417: 0x0008, | ||
754 | 0x418: 0xe00d, 0x419: 0x0008, 0x41a: 0xe00d, 0x41b: 0x0008, 0x41c: 0xe00d, 0x41d: 0x0008, | ||
755 | 0x41e: 0xe00d, 0x41f: 0x0008, 0x420: 0xe00d, 0x421: 0x0008, 0x422: 0xe00d, 0x423: 0x0008, | ||
756 | 0x424: 0xe00d, 0x425: 0x0008, 0x426: 0xe00d, 0x427: 0x0008, 0x428: 0xe00d, 0x429: 0x0008, | ||
757 | 0x42a: 0xe00d, 0x42b: 0x0008, 0x42c: 0xe00d, 0x42d: 0x0008, 0x42e: 0xe00d, 0x42f: 0x0008, | ||
758 | 0x430: 0x0040, 0x431: 0x03f5, 0x432: 0x03f5, 0x433: 0x03f5, 0x434: 0x03f5, 0x435: 0x03f5, | ||
759 | 0x436: 0x03f5, 0x437: 0x03f5, 0x438: 0x03f5, 0x439: 0x03f5, 0x43a: 0x03f5, 0x43b: 0x03f5, | ||
760 | 0x43c: 0x03f5, 0x43d: 0x03f5, 0x43e: 0x03f5, 0x43f: 0x03f5, | ||
761 | // Block 0x11, offset 0x440 | ||
762 | 0x440: 0x0040, 0x441: 0x0040, 0x442: 0x0040, 0x443: 0x0040, 0x444: 0x0040, 0x445: 0x0040, | ||
763 | 0x446: 0x0018, 0x447: 0x0018, 0x448: 0x0018, 0x449: 0x0018, 0x44a: 0x0018, 0x44b: 0x0018, | ||
764 | 0x44c: 0x0018, 0x44d: 0x0018, 0x44e: 0x0018, 0x44f: 0x0018, 0x450: 0x1308, 0x451: 0x1308, | ||
765 | 0x452: 0x1308, 0x453: 0x1308, 0x454: 0x1308, 0x455: 0x1308, 0x456: 0x1308, 0x457: 0x1308, | ||
766 | 0x458: 0x1308, 0x459: 0x1308, 0x45a: 0x1308, 0x45b: 0x0018, 0x45c: 0x0340, 0x45d: 0x0040, | ||
767 | 0x45e: 0x0018, 0x45f: 0x0018, 0x460: 0x0208, 0x461: 0x0008, 0x462: 0x0408, 0x463: 0x0408, | ||
768 | 0x464: 0x0408, 0x465: 0x0408, 0x466: 0x0208, 0x467: 0x0408, 0x468: 0x0208, 0x469: 0x0408, | ||
769 | 0x46a: 0x0208, 0x46b: 0x0208, 0x46c: 0x0208, 0x46d: 0x0208, 0x46e: 0x0208, 0x46f: 0x0408, | ||
770 | 0x470: 0x0408, 0x471: 0x0408, 0x472: 0x0408, 0x473: 0x0208, 0x474: 0x0208, 0x475: 0x0208, | ||
771 | 0x476: 0x0208, 0x477: 0x0208, 0x478: 0x0208, 0x479: 0x0208, 0x47a: 0x0208, 0x47b: 0x0208, | ||
772 | 0x47c: 0x0208, 0x47d: 0x0208, 0x47e: 0x0208, 0x47f: 0x0208, | ||
773 | // Block 0x12, offset 0x480 | ||
774 | 0x480: 0x0408, 0x481: 0x0208, 0x482: 0x0208, 0x483: 0x0408, 0x484: 0x0408, 0x485: 0x0408, | ||
775 | 0x486: 0x0408, 0x487: 0x0408, 0x488: 0x0408, 0x489: 0x0408, 0x48a: 0x0408, 0x48b: 0x0408, | ||
776 | 0x48c: 0x0208, 0x48d: 0x0408, 0x48e: 0x0208, 0x48f: 0x0408, 0x490: 0x0208, 0x491: 0x0208, | ||
777 | 0x492: 0x0408, 0x493: 0x0408, 0x494: 0x0018, 0x495: 0x0408, 0x496: 0x1308, 0x497: 0x1308, | ||
778 | 0x498: 0x1308, 0x499: 0x1308, 0x49a: 0x1308, 0x49b: 0x1308, 0x49c: 0x1308, 0x49d: 0x0040, | ||
779 | 0x49e: 0x0018, 0x49f: 0x1308, 0x4a0: 0x1308, 0x4a1: 0x1308, 0x4a2: 0x1308, 0x4a3: 0x1308, | ||
780 | 0x4a4: 0x1308, 0x4a5: 0x0008, 0x4a6: 0x0008, 0x4a7: 0x1308, 0x4a8: 0x1308, 0x4a9: 0x0018, | ||
781 | 0x4aa: 0x1308, 0x4ab: 0x1308, 0x4ac: 0x1308, 0x4ad: 0x1308, 0x4ae: 0x0408, 0x4af: 0x0408, | ||
782 | 0x4b0: 0x0008, 0x4b1: 0x0008, 0x4b2: 0x0008, 0x4b3: 0x0008, 0x4b4: 0x0008, 0x4b5: 0x0008, | ||
783 | 0x4b6: 0x0008, 0x4b7: 0x0008, 0x4b8: 0x0008, 0x4b9: 0x0008, 0x4ba: 0x0208, 0x4bb: 0x0208, | ||
784 | 0x4bc: 0x0208, 0x4bd: 0x0008, 0x4be: 0x0008, 0x4bf: 0x0208, | ||
785 | // Block 0x13, offset 0x4c0 | ||
786 | 0x4c0: 0x0018, 0x4c1: 0x0018, 0x4c2: 0x0018, 0x4c3: 0x0018, 0x4c4: 0x0018, 0x4c5: 0x0018, | ||
787 | 0x4c6: 0x0018, 0x4c7: 0x0018, 0x4c8: 0x0018, 0x4c9: 0x0018, 0x4ca: 0x0018, 0x4cb: 0x0018, | ||
788 | 0x4cc: 0x0018, 0x4cd: 0x0018, 0x4ce: 0x0040, 0x4cf: 0x0340, 0x4d0: 0x0408, 0x4d1: 0x1308, | ||
789 | 0x4d2: 0x0208, 0x4d3: 0x0208, 0x4d4: 0x0208, 0x4d5: 0x0408, 0x4d6: 0x0408, 0x4d7: 0x0408, | ||
790 | 0x4d8: 0x0408, 0x4d9: 0x0408, 0x4da: 0x0208, 0x4db: 0x0208, 0x4dc: 0x0208, 0x4dd: 0x0208, | ||
791 | 0x4de: 0x0408, 0x4df: 0x0208, 0x4e0: 0x0208, 0x4e1: 0x0208, 0x4e2: 0x0208, 0x4e3: 0x0208, | ||
792 | 0x4e4: 0x0208, 0x4e5: 0x0208, 0x4e6: 0x0208, 0x4e7: 0x0208, 0x4e8: 0x0408, 0x4e9: 0x0208, | ||
793 | 0x4ea: 0x0408, 0x4eb: 0x0208, 0x4ec: 0x0408, 0x4ed: 0x0208, 0x4ee: 0x0208, 0x4ef: 0x0408, | ||
794 | 0x4f0: 0x1308, 0x4f1: 0x1308, 0x4f2: 0x1308, 0x4f3: 0x1308, 0x4f4: 0x1308, 0x4f5: 0x1308, | ||
795 | 0x4f6: 0x1308, 0x4f7: 0x1308, 0x4f8: 0x1308, 0x4f9: 0x1308, 0x4fa: 0x1308, 0x4fb: 0x1308, | ||
796 | 0x4fc: 0x1308, 0x4fd: 0x1308, 0x4fe: 0x1308, 0x4ff: 0x1308, | ||
797 | // Block 0x14, offset 0x500 | ||
798 | 0x500: 0x1008, 0x501: 0x1308, 0x502: 0x1308, 0x503: 0x1308, 0x504: 0x1308, 0x505: 0x1308, | ||
799 | 0x506: 0x1308, 0x507: 0x1308, 0x508: 0x1308, 0x509: 0x1008, 0x50a: 0x1008, 0x50b: 0x1008, | ||
800 | 0x50c: 0x1008, 0x50d: 0x1b08, 0x50e: 0x1008, 0x50f: 0x1008, 0x510: 0x0008, 0x511: 0x1308, | ||
801 | 0x512: 0x1308, 0x513: 0x1308, 0x514: 0x1308, 0x515: 0x1308, 0x516: 0x1308, 0x517: 0x1308, | ||
802 | 0x518: 0x04c9, 0x519: 0x0501, 0x51a: 0x0539, 0x51b: 0x0571, 0x51c: 0x05a9, 0x51d: 0x05e1, | ||
803 | 0x51e: 0x0619, 0x51f: 0x0651, 0x520: 0x0008, 0x521: 0x0008, 0x522: 0x1308, 0x523: 0x1308, | ||
804 | 0x524: 0x0018, 0x525: 0x0018, 0x526: 0x0008, 0x527: 0x0008, 0x528: 0x0008, 0x529: 0x0008, | ||
805 | 0x52a: 0x0008, 0x52b: 0x0008, 0x52c: 0x0008, 0x52d: 0x0008, 0x52e: 0x0008, 0x52f: 0x0008, | ||
806 | 0x530: 0x0018, 0x531: 0x0008, 0x532: 0x0008, 0x533: 0x0008, 0x534: 0x0008, 0x535: 0x0008, | ||
807 | 0x536: 0x0008, 0x537: 0x0008, 0x538: 0x0008, 0x539: 0x0008, 0x53a: 0x0008, 0x53b: 0x0008, | ||
808 | 0x53c: 0x0008, 0x53d: 0x0008, 0x53e: 0x0008, 0x53f: 0x0008, | ||
809 | // Block 0x15, offset 0x540 | ||
810 | 0x540: 0x0008, 0x541: 0x1308, 0x542: 0x1008, 0x543: 0x1008, 0x544: 0x0040, 0x545: 0x0008, | ||
811 | 0x546: 0x0008, 0x547: 0x0008, 0x548: 0x0008, 0x549: 0x0008, 0x54a: 0x0008, 0x54b: 0x0008, | ||
812 | 0x54c: 0x0008, 0x54d: 0x0040, 0x54e: 0x0040, 0x54f: 0x0008, 0x550: 0x0008, 0x551: 0x0040, | ||
813 | 0x552: 0x0040, 0x553: 0x0008, 0x554: 0x0008, 0x555: 0x0008, 0x556: 0x0008, 0x557: 0x0008, | ||
814 | 0x558: 0x0008, 0x559: 0x0008, 0x55a: 0x0008, 0x55b: 0x0008, 0x55c: 0x0008, 0x55d: 0x0008, | ||
815 | 0x55e: 0x0008, 0x55f: 0x0008, 0x560: 0x0008, 0x561: 0x0008, 0x562: 0x0008, 0x563: 0x0008, | ||
816 | 0x564: 0x0008, 0x565: 0x0008, 0x566: 0x0008, 0x567: 0x0008, 0x568: 0x0008, 0x569: 0x0040, | ||
817 | 0x56a: 0x0008, 0x56b: 0x0008, 0x56c: 0x0008, 0x56d: 0x0008, 0x56e: 0x0008, 0x56f: 0x0008, | ||
818 | 0x570: 0x0008, 0x571: 0x0040, 0x572: 0x0008, 0x573: 0x0040, 0x574: 0x0040, 0x575: 0x0040, | ||
819 | 0x576: 0x0008, 0x577: 0x0008, 0x578: 0x0008, 0x579: 0x0008, 0x57a: 0x0040, 0x57b: 0x0040, | ||
820 | 0x57c: 0x1308, 0x57d: 0x0008, 0x57e: 0x1008, 0x57f: 0x1008, | ||
821 | // Block 0x16, offset 0x580 | ||
822 | 0x580: 0x1008, 0x581: 0x1308, 0x582: 0x1308, 0x583: 0x1308, 0x584: 0x1308, 0x585: 0x0040, | ||
823 | 0x586: 0x0040, 0x587: 0x1008, 0x588: 0x1008, 0x589: 0x0040, 0x58a: 0x0040, 0x58b: 0x1008, | ||
824 | 0x58c: 0x1008, 0x58d: 0x1b08, 0x58e: 0x0008, 0x58f: 0x0040, 0x590: 0x0040, 0x591: 0x0040, | ||
825 | 0x592: 0x0040, 0x593: 0x0040, 0x594: 0x0040, 0x595: 0x0040, 0x596: 0x0040, 0x597: 0x1008, | ||
826 | 0x598: 0x0040, 0x599: 0x0040, 0x59a: 0x0040, 0x59b: 0x0040, 0x59c: 0x0689, 0x59d: 0x06c1, | ||
827 | 0x59e: 0x0040, 0x59f: 0x06f9, 0x5a0: 0x0008, 0x5a1: 0x0008, 0x5a2: 0x1308, 0x5a3: 0x1308, | ||
828 | 0x5a4: 0x0040, 0x5a5: 0x0040, 0x5a6: 0x0008, 0x5a7: 0x0008, 0x5a8: 0x0008, 0x5a9: 0x0008, | ||
829 | 0x5aa: 0x0008, 0x5ab: 0x0008, 0x5ac: 0x0008, 0x5ad: 0x0008, 0x5ae: 0x0008, 0x5af: 0x0008, | ||
830 | 0x5b0: 0x0008, 0x5b1: 0x0008, 0x5b2: 0x0018, 0x5b3: 0x0018, 0x5b4: 0x0018, 0x5b5: 0x0018, | ||
831 | 0x5b6: 0x0018, 0x5b7: 0x0018, 0x5b8: 0x0018, 0x5b9: 0x0018, 0x5ba: 0x0018, 0x5bb: 0x0018, | ||
832 | 0x5bc: 0x0040, 0x5bd: 0x0040, 0x5be: 0x0040, 0x5bf: 0x0040, | ||
833 | // Block 0x17, offset 0x5c0 | ||
834 | 0x5c0: 0x0040, 0x5c1: 0x1308, 0x5c2: 0x1308, 0x5c3: 0x1008, 0x5c4: 0x0040, 0x5c5: 0x0008, | ||
835 | 0x5c6: 0x0008, 0x5c7: 0x0008, 0x5c8: 0x0008, 0x5c9: 0x0008, 0x5ca: 0x0008, 0x5cb: 0x0040, | ||
836 | 0x5cc: 0x0040, 0x5cd: 0x0040, 0x5ce: 0x0040, 0x5cf: 0x0008, 0x5d0: 0x0008, 0x5d1: 0x0040, | ||
837 | 0x5d2: 0x0040, 0x5d3: 0x0008, 0x5d4: 0x0008, 0x5d5: 0x0008, 0x5d6: 0x0008, 0x5d7: 0x0008, | ||
838 | 0x5d8: 0x0008, 0x5d9: 0x0008, 0x5da: 0x0008, 0x5db: 0x0008, 0x5dc: 0x0008, 0x5dd: 0x0008, | ||
839 | 0x5de: 0x0008, 0x5df: 0x0008, 0x5e0: 0x0008, 0x5e1: 0x0008, 0x5e2: 0x0008, 0x5e3: 0x0008, | ||
840 | 0x5e4: 0x0008, 0x5e5: 0x0008, 0x5e6: 0x0008, 0x5e7: 0x0008, 0x5e8: 0x0008, 0x5e9: 0x0040, | ||
841 | 0x5ea: 0x0008, 0x5eb: 0x0008, 0x5ec: 0x0008, 0x5ed: 0x0008, 0x5ee: 0x0008, 0x5ef: 0x0008, | ||
842 | 0x5f0: 0x0008, 0x5f1: 0x0040, 0x5f2: 0x0008, 0x5f3: 0x0731, 0x5f4: 0x0040, 0x5f5: 0x0008, | ||
843 | 0x5f6: 0x0769, 0x5f7: 0x0040, 0x5f8: 0x0008, 0x5f9: 0x0008, 0x5fa: 0x0040, 0x5fb: 0x0040, | ||
844 | 0x5fc: 0x1308, 0x5fd: 0x0040, 0x5fe: 0x1008, 0x5ff: 0x1008, | ||
845 | // Block 0x18, offset 0x600 | ||
846 | 0x600: 0x1008, 0x601: 0x1308, 0x602: 0x1308, 0x603: 0x0040, 0x604: 0x0040, 0x605: 0x0040, | ||
847 | 0x606: 0x0040, 0x607: 0x1308, 0x608: 0x1308, 0x609: 0x0040, 0x60a: 0x0040, 0x60b: 0x1308, | ||
848 | 0x60c: 0x1308, 0x60d: 0x1b08, 0x60e: 0x0040, 0x60f: 0x0040, 0x610: 0x0040, 0x611: 0x1308, | ||
849 | 0x612: 0x0040, 0x613: 0x0040, 0x614: 0x0040, 0x615: 0x0040, 0x616: 0x0040, 0x617: 0x0040, | ||
850 | 0x618: 0x0040, 0x619: 0x07a1, 0x61a: 0x07d9, 0x61b: 0x0811, 0x61c: 0x0008, 0x61d: 0x0040, | ||
851 | 0x61e: 0x0849, 0x61f: 0x0040, 0x620: 0x0040, 0x621: 0x0040, 0x622: 0x0040, 0x623: 0x0040, | ||
852 | 0x624: 0x0040, 0x625: 0x0040, 0x626: 0x0008, 0x627: 0x0008, 0x628: 0x0008, 0x629: 0x0008, | ||
853 | 0x62a: 0x0008, 0x62b: 0x0008, 0x62c: 0x0008, 0x62d: 0x0008, 0x62e: 0x0008, 0x62f: 0x0008, | ||
854 | 0x630: 0x1308, 0x631: 0x1308, 0x632: 0x0008, 0x633: 0x0008, 0x634: 0x0008, 0x635: 0x1308, | ||
855 | 0x636: 0x0040, 0x637: 0x0040, 0x638: 0x0040, 0x639: 0x0040, 0x63a: 0x0040, 0x63b: 0x0040, | ||
856 | 0x63c: 0x0040, 0x63d: 0x0040, 0x63e: 0x0040, 0x63f: 0x0040, | ||
857 | // Block 0x19, offset 0x640 | ||
858 | 0x640: 0x0040, 0x641: 0x1308, 0x642: 0x1308, 0x643: 0x1008, 0x644: 0x0040, 0x645: 0x0008, | ||
859 | 0x646: 0x0008, 0x647: 0x0008, 0x648: 0x0008, 0x649: 0x0008, 0x64a: 0x0008, 0x64b: 0x0008, | ||
860 | 0x64c: 0x0008, 0x64d: 0x0008, 0x64e: 0x0040, 0x64f: 0x0008, 0x650: 0x0008, 0x651: 0x0008, | ||
861 | 0x652: 0x0040, 0x653: 0x0008, 0x654: 0x0008, 0x655: 0x0008, 0x656: 0x0008, 0x657: 0x0008, | ||
862 | 0x658: 0x0008, 0x659: 0x0008, 0x65a: 0x0008, 0x65b: 0x0008, 0x65c: 0x0008, 0x65d: 0x0008, | ||
863 | 0x65e: 0x0008, 0x65f: 0x0008, 0x660: 0x0008, 0x661: 0x0008, 0x662: 0x0008, 0x663: 0x0008, | ||
864 | 0x664: 0x0008, 0x665: 0x0008, 0x666: 0x0008, 0x667: 0x0008, 0x668: 0x0008, 0x669: 0x0040, | ||
865 | 0x66a: 0x0008, 0x66b: 0x0008, 0x66c: 0x0008, 0x66d: 0x0008, 0x66e: 0x0008, 0x66f: 0x0008, | ||
866 | 0x670: 0x0008, 0x671: 0x0040, 0x672: 0x0008, 0x673: 0x0008, 0x674: 0x0040, 0x675: 0x0008, | ||
867 | 0x676: 0x0008, 0x677: 0x0008, 0x678: 0x0008, 0x679: 0x0008, 0x67a: 0x0040, 0x67b: 0x0040, | ||
868 | 0x67c: 0x1308, 0x67d: 0x0008, 0x67e: 0x1008, 0x67f: 0x1008, | ||
869 | // Block 0x1a, offset 0x680 | ||
870 | 0x680: 0x1008, 0x681: 0x1308, 0x682: 0x1308, 0x683: 0x1308, 0x684: 0x1308, 0x685: 0x1308, | ||
871 | 0x686: 0x0040, 0x687: 0x1308, 0x688: 0x1308, 0x689: 0x1008, 0x68a: 0x0040, 0x68b: 0x1008, | ||
872 | 0x68c: 0x1008, 0x68d: 0x1b08, 0x68e: 0x0040, 0x68f: 0x0040, 0x690: 0x0008, 0x691: 0x0040, | ||
873 | 0x692: 0x0040, 0x693: 0x0040, 0x694: 0x0040, 0x695: 0x0040, 0x696: 0x0040, 0x697: 0x0040, | ||
874 | 0x698: 0x0040, 0x699: 0x0040, 0x69a: 0x0040, 0x69b: 0x0040, 0x69c: 0x0040, 0x69d: 0x0040, | ||
875 | 0x69e: 0x0040, 0x69f: 0x0040, 0x6a0: 0x0008, 0x6a1: 0x0008, 0x6a2: 0x1308, 0x6a3: 0x1308, | ||
876 | 0x6a4: 0x0040, 0x6a5: 0x0040, 0x6a6: 0x0008, 0x6a7: 0x0008, 0x6a8: 0x0008, 0x6a9: 0x0008, | ||
877 | 0x6aa: 0x0008, 0x6ab: 0x0008, 0x6ac: 0x0008, 0x6ad: 0x0008, 0x6ae: 0x0008, 0x6af: 0x0008, | ||
878 | 0x6b0: 0x0018, 0x6b1: 0x0018, 0x6b2: 0x0040, 0x6b3: 0x0040, 0x6b4: 0x0040, 0x6b5: 0x0040, | ||
879 | 0x6b6: 0x0040, 0x6b7: 0x0040, 0x6b8: 0x0040, 0x6b9: 0x0008, 0x6ba: 0x0040, 0x6bb: 0x0040, | ||
880 | 0x6bc: 0x0040, 0x6bd: 0x0040, 0x6be: 0x0040, 0x6bf: 0x0040, | ||
881 | // Block 0x1b, offset 0x6c0 | ||
882 | 0x6c0: 0x0040, 0x6c1: 0x1308, 0x6c2: 0x1008, 0x6c3: 0x1008, 0x6c4: 0x0040, 0x6c5: 0x0008, | ||
883 | 0x6c6: 0x0008, 0x6c7: 0x0008, 0x6c8: 0x0008, 0x6c9: 0x0008, 0x6ca: 0x0008, 0x6cb: 0x0008, | ||
884 | 0x6cc: 0x0008, 0x6cd: 0x0040, 0x6ce: 0x0040, 0x6cf: 0x0008, 0x6d0: 0x0008, 0x6d1: 0x0040, | ||
885 | 0x6d2: 0x0040, 0x6d3: 0x0008, 0x6d4: 0x0008, 0x6d5: 0x0008, 0x6d6: 0x0008, 0x6d7: 0x0008, | ||
886 | 0x6d8: 0x0008, 0x6d9: 0x0008, 0x6da: 0x0008, 0x6db: 0x0008, 0x6dc: 0x0008, 0x6dd: 0x0008, | ||
887 | 0x6de: 0x0008, 0x6df: 0x0008, 0x6e0: 0x0008, 0x6e1: 0x0008, 0x6e2: 0x0008, 0x6e3: 0x0008, | ||
888 | 0x6e4: 0x0008, 0x6e5: 0x0008, 0x6e6: 0x0008, 0x6e7: 0x0008, 0x6e8: 0x0008, 0x6e9: 0x0040, | ||
889 | 0x6ea: 0x0008, 0x6eb: 0x0008, 0x6ec: 0x0008, 0x6ed: 0x0008, 0x6ee: 0x0008, 0x6ef: 0x0008, | ||
890 | 0x6f0: 0x0008, 0x6f1: 0x0040, 0x6f2: 0x0008, 0x6f3: 0x0008, 0x6f4: 0x0040, 0x6f5: 0x0008, | ||
891 | 0x6f6: 0x0008, 0x6f7: 0x0008, 0x6f8: 0x0008, 0x6f9: 0x0008, 0x6fa: 0x0040, 0x6fb: 0x0040, | ||
892 | 0x6fc: 0x1308, 0x6fd: 0x0008, 0x6fe: 0x1008, 0x6ff: 0x1308, | ||
893 | // Block 0x1c, offset 0x700 | ||
894 | 0x700: 0x1008, 0x701: 0x1308, 0x702: 0x1308, 0x703: 0x1308, 0x704: 0x1308, 0x705: 0x0040, | ||
895 | 0x706: 0x0040, 0x707: 0x1008, 0x708: 0x1008, 0x709: 0x0040, 0x70a: 0x0040, 0x70b: 0x1008, | ||
896 | 0x70c: 0x1008, 0x70d: 0x1b08, 0x70e: 0x0040, 0x70f: 0x0040, 0x710: 0x0040, 0x711: 0x0040, | ||
897 | 0x712: 0x0040, 0x713: 0x0040, 0x714: 0x0040, 0x715: 0x0040, 0x716: 0x1308, 0x717: 0x1008, | ||
898 | 0x718: 0x0040, 0x719: 0x0040, 0x71a: 0x0040, 0x71b: 0x0040, 0x71c: 0x0881, 0x71d: 0x08b9, | ||
899 | 0x71e: 0x0040, 0x71f: 0x0008, 0x720: 0x0008, 0x721: 0x0008, 0x722: 0x1308, 0x723: 0x1308, | ||
900 | 0x724: 0x0040, 0x725: 0x0040, 0x726: 0x0008, 0x727: 0x0008, 0x728: 0x0008, 0x729: 0x0008, | ||
901 | 0x72a: 0x0008, 0x72b: 0x0008, 0x72c: 0x0008, 0x72d: 0x0008, 0x72e: 0x0008, 0x72f: 0x0008, | ||
902 | 0x730: 0x0018, 0x731: 0x0008, 0x732: 0x0018, 0x733: 0x0018, 0x734: 0x0018, 0x735: 0x0018, | ||
903 | 0x736: 0x0018, 0x737: 0x0018, 0x738: 0x0040, 0x739: 0x0040, 0x73a: 0x0040, 0x73b: 0x0040, | ||
904 | 0x73c: 0x0040, 0x73d: 0x0040, 0x73e: 0x0040, 0x73f: 0x0040, | ||
905 | // Block 0x1d, offset 0x740 | ||
906 | 0x740: 0x0040, 0x741: 0x0040, 0x742: 0x1308, 0x743: 0x0008, 0x744: 0x0040, 0x745: 0x0008, | ||
907 | 0x746: 0x0008, 0x747: 0x0008, 0x748: 0x0008, 0x749: 0x0008, 0x74a: 0x0008, 0x74b: 0x0040, | ||
908 | 0x74c: 0x0040, 0x74d: 0x0040, 0x74e: 0x0008, 0x74f: 0x0008, 0x750: 0x0008, 0x751: 0x0040, | ||
909 | 0x752: 0x0008, 0x753: 0x0008, 0x754: 0x0008, 0x755: 0x0008, 0x756: 0x0040, 0x757: 0x0040, | ||
910 | 0x758: 0x0040, 0x759: 0x0008, 0x75a: 0x0008, 0x75b: 0x0040, 0x75c: 0x0008, 0x75d: 0x0040, | ||
911 | 0x75e: 0x0008, 0x75f: 0x0008, 0x760: 0x0040, 0x761: 0x0040, 0x762: 0x0040, 0x763: 0x0008, | ||
912 | 0x764: 0x0008, 0x765: 0x0040, 0x766: 0x0040, 0x767: 0x0040, 0x768: 0x0008, 0x769: 0x0008, | ||
913 | 0x76a: 0x0008, 0x76b: 0x0040, 0x76c: 0x0040, 0x76d: 0x0040, 0x76e: 0x0008, 0x76f: 0x0008, | ||
914 | 0x770: 0x0008, 0x771: 0x0008, 0x772: 0x0008, 0x773: 0x0008, 0x774: 0x0008, 0x775: 0x0008, | ||
915 | 0x776: 0x0008, 0x777: 0x0008, 0x778: 0x0008, 0x779: 0x0008, 0x77a: 0x0040, 0x77b: 0x0040, | ||
916 | 0x77c: 0x0040, 0x77d: 0x0040, 0x77e: 0x1008, 0x77f: 0x1008, | ||
917 | // Block 0x1e, offset 0x780 | ||
918 | 0x780: 0x1308, 0x781: 0x1008, 0x782: 0x1008, 0x783: 0x1008, 0x784: 0x1008, 0x785: 0x0040, | ||
919 | 0x786: 0x1308, 0x787: 0x1308, 0x788: 0x1308, 0x789: 0x0040, 0x78a: 0x1308, 0x78b: 0x1308, | ||
920 | 0x78c: 0x1308, 0x78d: 0x1b08, 0x78e: 0x0040, 0x78f: 0x0040, 0x790: 0x0040, 0x791: 0x0040, | ||
921 | 0x792: 0x0040, 0x793: 0x0040, 0x794: 0x0040, 0x795: 0x1308, 0x796: 0x1308, 0x797: 0x0040, | ||
922 | 0x798: 0x0008, 0x799: 0x0008, 0x79a: 0x0008, 0x79b: 0x0040, 0x79c: 0x0040, 0x79d: 0x0040, | ||
923 | 0x79e: 0x0040, 0x79f: 0x0040, 0x7a0: 0x0008, 0x7a1: 0x0008, 0x7a2: 0x1308, 0x7a3: 0x1308, | ||
924 | 0x7a4: 0x0040, 0x7a5: 0x0040, 0x7a6: 0x0008, 0x7a7: 0x0008, 0x7a8: 0x0008, 0x7a9: 0x0008, | ||
925 | 0x7aa: 0x0008, 0x7ab: 0x0008, 0x7ac: 0x0008, 0x7ad: 0x0008, 0x7ae: 0x0008, 0x7af: 0x0008, | ||
926 | 0x7b0: 0x0040, 0x7b1: 0x0040, 0x7b2: 0x0040, 0x7b3: 0x0040, 0x7b4: 0x0040, 0x7b5: 0x0040, | ||
927 | 0x7b6: 0x0040, 0x7b7: 0x0040, 0x7b8: 0x0018, 0x7b9: 0x0018, 0x7ba: 0x0018, 0x7bb: 0x0018, | ||
928 | 0x7bc: 0x0018, 0x7bd: 0x0018, 0x7be: 0x0018, 0x7bf: 0x0018, | ||
929 | // Block 0x1f, offset 0x7c0 | ||
930 | 0x7c0: 0x0008, 0x7c1: 0x1308, 0x7c2: 0x1008, 0x7c3: 0x1008, 0x7c4: 0x0040, 0x7c5: 0x0008, | ||
931 | 0x7c6: 0x0008, 0x7c7: 0x0008, 0x7c8: 0x0008, 0x7c9: 0x0008, 0x7ca: 0x0008, 0x7cb: 0x0008, | ||
932 | 0x7cc: 0x0008, 0x7cd: 0x0040, 0x7ce: 0x0008, 0x7cf: 0x0008, 0x7d0: 0x0008, 0x7d1: 0x0040, | ||
933 | 0x7d2: 0x0008, 0x7d3: 0x0008, 0x7d4: 0x0008, 0x7d5: 0x0008, 0x7d6: 0x0008, 0x7d7: 0x0008, | ||
934 | 0x7d8: 0x0008, 0x7d9: 0x0008, 0x7da: 0x0008, 0x7db: 0x0008, 0x7dc: 0x0008, 0x7dd: 0x0008, | ||
935 | 0x7de: 0x0008, 0x7df: 0x0008, 0x7e0: 0x0008, 0x7e1: 0x0008, 0x7e2: 0x0008, 0x7e3: 0x0008, | ||
936 | 0x7e4: 0x0008, 0x7e5: 0x0008, 0x7e6: 0x0008, 0x7e7: 0x0008, 0x7e8: 0x0008, 0x7e9: 0x0040, | ||
937 | 0x7ea: 0x0008, 0x7eb: 0x0008, 0x7ec: 0x0008, 0x7ed: 0x0008, 0x7ee: 0x0008, 0x7ef: 0x0008, | ||
938 | 0x7f0: 0x0008, 0x7f1: 0x0008, 0x7f2: 0x0008, 0x7f3: 0x0008, 0x7f4: 0x0040, 0x7f5: 0x0008, | ||
939 | 0x7f6: 0x0008, 0x7f7: 0x0008, 0x7f8: 0x0008, 0x7f9: 0x0008, 0x7fa: 0x0040, 0x7fb: 0x0040, | ||
940 | 0x7fc: 0x1308, 0x7fd: 0x0008, 0x7fe: 0x1008, 0x7ff: 0x1308, | ||
941 | // Block 0x20, offset 0x800 | ||
942 | 0x800: 0x1008, 0x801: 0x1008, 0x802: 0x1008, 0x803: 0x1008, 0x804: 0x1008, 0x805: 0x0040, | ||
943 | 0x806: 0x1308, 0x807: 0x1008, 0x808: 0x1008, 0x809: 0x0040, 0x80a: 0x1008, 0x80b: 0x1008, | ||
944 | 0x80c: 0x1308, 0x80d: 0x1b08, 0x80e: 0x0040, 0x80f: 0x0040, 0x810: 0x0040, 0x811: 0x0040, | ||
945 | 0x812: 0x0040, 0x813: 0x0040, 0x814: 0x0040, 0x815: 0x1008, 0x816: 0x1008, 0x817: 0x0040, | ||
946 | 0x818: 0x0040, 0x819: 0x0040, 0x81a: 0x0040, 0x81b: 0x0040, 0x81c: 0x0040, 0x81d: 0x0040, | ||
947 | 0x81e: 0x0008, 0x81f: 0x0040, 0x820: 0x0008, 0x821: 0x0008, 0x822: 0x1308, 0x823: 0x1308, | ||
948 | 0x824: 0x0040, 0x825: 0x0040, 0x826: 0x0008, 0x827: 0x0008, 0x828: 0x0008, 0x829: 0x0008, | ||
949 | 0x82a: 0x0008, 0x82b: 0x0008, 0x82c: 0x0008, 0x82d: 0x0008, 0x82e: 0x0008, 0x82f: 0x0008, | ||
950 | 0x830: 0x0040, 0x831: 0x0008, 0x832: 0x0008, 0x833: 0x0040, 0x834: 0x0040, 0x835: 0x0040, | ||
951 | 0x836: 0x0040, 0x837: 0x0040, 0x838: 0x0040, 0x839: 0x0040, 0x83a: 0x0040, 0x83b: 0x0040, | ||
952 | 0x83c: 0x0040, 0x83d: 0x0040, 0x83e: 0x0040, 0x83f: 0x0040, | ||
953 | // Block 0x21, offset 0x840 | ||
954 | 0x840: 0x1008, 0x841: 0x1308, 0x842: 0x1308, 0x843: 0x1308, 0x844: 0x1308, 0x845: 0x0040, | ||
955 | 0x846: 0x1008, 0x847: 0x1008, 0x848: 0x1008, 0x849: 0x0040, 0x84a: 0x1008, 0x84b: 0x1008, | ||
956 | 0x84c: 0x1008, 0x84d: 0x1b08, 0x84e: 0x0008, 0x84f: 0x0018, 0x850: 0x0040, 0x851: 0x0040, | ||
957 | 0x852: 0x0040, 0x853: 0x0040, 0x854: 0x0008, 0x855: 0x0008, 0x856: 0x0008, 0x857: 0x1008, | ||
958 | 0x858: 0x0018, 0x859: 0x0018, 0x85a: 0x0018, 0x85b: 0x0018, 0x85c: 0x0018, 0x85d: 0x0018, | ||
959 | 0x85e: 0x0018, 0x85f: 0x0008, 0x860: 0x0008, 0x861: 0x0008, 0x862: 0x1308, 0x863: 0x1308, | ||
960 | 0x864: 0x0040, 0x865: 0x0040, 0x866: 0x0008, 0x867: 0x0008, 0x868: 0x0008, 0x869: 0x0008, | ||
961 | 0x86a: 0x0008, 0x86b: 0x0008, 0x86c: 0x0008, 0x86d: 0x0008, 0x86e: 0x0008, 0x86f: 0x0008, | ||
962 | 0x870: 0x0018, 0x871: 0x0018, 0x872: 0x0018, 0x873: 0x0018, 0x874: 0x0018, 0x875: 0x0018, | ||
963 | 0x876: 0x0018, 0x877: 0x0018, 0x878: 0x0018, 0x879: 0x0018, 0x87a: 0x0008, 0x87b: 0x0008, | ||
964 | 0x87c: 0x0008, 0x87d: 0x0008, 0x87e: 0x0008, 0x87f: 0x0008, | ||
965 | // Block 0x22, offset 0x880 | ||
966 | 0x880: 0x0040, 0x881: 0x0008, 0x882: 0x0008, 0x883: 0x0040, 0x884: 0x0008, 0x885: 0x0040, | ||
967 | 0x886: 0x0040, 0x887: 0x0008, 0x888: 0x0008, 0x889: 0x0040, 0x88a: 0x0008, 0x88b: 0x0040, | ||
968 | 0x88c: 0x0040, 0x88d: 0x0008, 0x88e: 0x0040, 0x88f: 0x0040, 0x890: 0x0040, 0x891: 0x0040, | ||
969 | 0x892: 0x0040, 0x893: 0x0040, 0x894: 0x0008, 0x895: 0x0008, 0x896: 0x0008, 0x897: 0x0008, | ||
970 | 0x898: 0x0040, 0x899: 0x0008, 0x89a: 0x0008, 0x89b: 0x0008, 0x89c: 0x0008, 0x89d: 0x0008, | ||
971 | 0x89e: 0x0008, 0x89f: 0x0008, 0x8a0: 0x0040, 0x8a1: 0x0008, 0x8a2: 0x0008, 0x8a3: 0x0008, | ||
972 | 0x8a4: 0x0040, 0x8a5: 0x0008, 0x8a6: 0x0040, 0x8a7: 0x0008, 0x8a8: 0x0040, 0x8a9: 0x0040, | ||
973 | 0x8aa: 0x0008, 0x8ab: 0x0008, 0x8ac: 0x0040, 0x8ad: 0x0008, 0x8ae: 0x0008, 0x8af: 0x0008, | ||
974 | 0x8b0: 0x0008, 0x8b1: 0x1308, 0x8b2: 0x0008, 0x8b3: 0x0929, 0x8b4: 0x1308, 0x8b5: 0x1308, | ||
975 | 0x8b6: 0x1308, 0x8b7: 0x1308, 0x8b8: 0x1308, 0x8b9: 0x1308, 0x8ba: 0x0040, 0x8bb: 0x1308, | ||
976 | 0x8bc: 0x1308, 0x8bd: 0x0008, 0x8be: 0x0040, 0x8bf: 0x0040, | ||
977 | // Block 0x23, offset 0x8c0 | ||
978 | 0x8c0: 0x0008, 0x8c1: 0x0008, 0x8c2: 0x0008, 0x8c3: 0x09d1, 0x8c4: 0x0008, 0x8c5: 0x0008, | ||
979 | 0x8c6: 0x0008, 0x8c7: 0x0008, 0x8c8: 0x0040, 0x8c9: 0x0008, 0x8ca: 0x0008, 0x8cb: 0x0008, | ||
980 | 0x8cc: 0x0008, 0x8cd: 0x0a09, 0x8ce: 0x0008, 0x8cf: 0x0008, 0x8d0: 0x0008, 0x8d1: 0x0008, | ||
981 | 0x8d2: 0x0a41, 0x8d3: 0x0008, 0x8d4: 0x0008, 0x8d5: 0x0008, 0x8d6: 0x0008, 0x8d7: 0x0a79, | ||
982 | 0x8d8: 0x0008, 0x8d9: 0x0008, 0x8da: 0x0008, 0x8db: 0x0008, 0x8dc: 0x0ab1, 0x8dd: 0x0008, | ||
983 | 0x8de: 0x0008, 0x8df: 0x0008, 0x8e0: 0x0008, 0x8e1: 0x0008, 0x8e2: 0x0008, 0x8e3: 0x0008, | ||
984 | 0x8e4: 0x0008, 0x8e5: 0x0008, 0x8e6: 0x0008, 0x8e7: 0x0008, 0x8e8: 0x0008, 0x8e9: 0x0ae9, | ||
985 | 0x8ea: 0x0008, 0x8eb: 0x0008, 0x8ec: 0x0008, 0x8ed: 0x0040, 0x8ee: 0x0040, 0x8ef: 0x0040, | ||
986 | 0x8f0: 0x0040, 0x8f1: 0x1308, 0x8f2: 0x1308, 0x8f3: 0x0b21, 0x8f4: 0x1308, 0x8f5: 0x0b59, | ||
987 | 0x8f6: 0x0b91, 0x8f7: 0x0bc9, 0x8f8: 0x0c19, 0x8f9: 0x0c51, 0x8fa: 0x1308, 0x8fb: 0x1308, | ||
988 | 0x8fc: 0x1308, 0x8fd: 0x1308, 0x8fe: 0x1308, 0x8ff: 0x1008, | ||
989 | // Block 0x24, offset 0x900 | ||
990 | 0x900: 0x1308, 0x901: 0x0ca1, 0x902: 0x1308, 0x903: 0x1308, 0x904: 0x1b08, 0x905: 0x0018, | ||
991 | 0x906: 0x1308, 0x907: 0x1308, 0x908: 0x0008, 0x909: 0x0008, 0x90a: 0x0008, 0x90b: 0x0008, | ||
992 | 0x90c: 0x0008, 0x90d: 0x1308, 0x90e: 0x1308, 0x90f: 0x1308, 0x910: 0x1308, 0x911: 0x1308, | ||
993 | 0x912: 0x1308, 0x913: 0x0cd9, 0x914: 0x1308, 0x915: 0x1308, 0x916: 0x1308, 0x917: 0x1308, | ||
994 | 0x918: 0x0040, 0x919: 0x1308, 0x91a: 0x1308, 0x91b: 0x1308, 0x91c: 0x1308, 0x91d: 0x0d11, | ||
995 | 0x91e: 0x1308, 0x91f: 0x1308, 0x920: 0x1308, 0x921: 0x1308, 0x922: 0x0d49, 0x923: 0x1308, | ||
996 | 0x924: 0x1308, 0x925: 0x1308, 0x926: 0x1308, 0x927: 0x0d81, 0x928: 0x1308, 0x929: 0x1308, | ||
997 | 0x92a: 0x1308, 0x92b: 0x1308, 0x92c: 0x0db9, 0x92d: 0x1308, 0x92e: 0x1308, 0x92f: 0x1308, | ||
998 | 0x930: 0x1308, 0x931: 0x1308, 0x932: 0x1308, 0x933: 0x1308, 0x934: 0x1308, 0x935: 0x1308, | ||
999 | 0x936: 0x1308, 0x937: 0x1308, 0x938: 0x1308, 0x939: 0x0df1, 0x93a: 0x1308, 0x93b: 0x1308, | ||
1000 | 0x93c: 0x1308, 0x93d: 0x0040, 0x93e: 0x0018, 0x93f: 0x0018, | ||
1001 | // Block 0x25, offset 0x940 | ||
1002 | 0x940: 0x0008, 0x941: 0x0008, 0x942: 0x0008, 0x943: 0x0008, 0x944: 0x0008, 0x945: 0x0008, | ||
1003 | 0x946: 0x0008, 0x947: 0x0008, 0x948: 0x0008, 0x949: 0x0008, 0x94a: 0x0008, 0x94b: 0x0008, | ||
1004 | 0x94c: 0x0008, 0x94d: 0x0008, 0x94e: 0x0008, 0x94f: 0x0008, 0x950: 0x0008, 0x951: 0x0008, | ||
1005 | 0x952: 0x0008, 0x953: 0x0008, 0x954: 0x0008, 0x955: 0x0008, 0x956: 0x0008, 0x957: 0x0008, | ||
1006 | 0x958: 0x0008, 0x959: 0x0008, 0x95a: 0x0008, 0x95b: 0x0008, 0x95c: 0x0008, 0x95d: 0x0008, | ||
1007 | 0x95e: 0x0008, 0x95f: 0x0008, 0x960: 0x0008, 0x961: 0x0008, 0x962: 0x0008, 0x963: 0x0008, | ||
1008 | 0x964: 0x0008, 0x965: 0x0008, 0x966: 0x0008, 0x967: 0x0008, 0x968: 0x0008, 0x969: 0x0008, | ||
1009 | 0x96a: 0x0008, 0x96b: 0x0008, 0x96c: 0x0039, 0x96d: 0x0ed1, 0x96e: 0x0ee9, 0x96f: 0x0008, | ||
1010 | 0x970: 0x0ef9, 0x971: 0x0f09, 0x972: 0x0f19, 0x973: 0x0f31, 0x974: 0x0249, 0x975: 0x0f41, | ||
1011 | 0x976: 0x0259, 0x977: 0x0f51, 0x978: 0x0359, 0x979: 0x0f61, 0x97a: 0x0f71, 0x97b: 0x0008, | ||
1012 | 0x97c: 0x00d9, 0x97d: 0x0f81, 0x97e: 0x0f99, 0x97f: 0x0269, | ||
1013 | // Block 0x26, offset 0x980 | ||
1014 | 0x980: 0x0fa9, 0x981: 0x0fb9, 0x982: 0x0279, 0x983: 0x0039, 0x984: 0x0fc9, 0x985: 0x0fe1, | ||
1015 | 0x986: 0x059d, 0x987: 0x0ee9, 0x988: 0x0ef9, 0x989: 0x0f09, 0x98a: 0x0ff9, 0x98b: 0x1011, | ||
1016 | 0x98c: 0x1029, 0x98d: 0x0f31, 0x98e: 0x0008, 0x98f: 0x0f51, 0x990: 0x0f61, 0x991: 0x1041, | ||
1017 | 0x992: 0x00d9, 0x993: 0x1059, 0x994: 0x05b5, 0x995: 0x05b5, 0x996: 0x0f99, 0x997: 0x0fa9, | ||
1018 | 0x998: 0x0fb9, 0x999: 0x059d, 0x99a: 0x1071, 0x99b: 0x1089, 0x99c: 0x05cd, 0x99d: 0x1099, | ||
1019 | 0x99e: 0x10b1, 0x99f: 0x10c9, 0x9a0: 0x10e1, 0x9a1: 0x10f9, 0x9a2: 0x0f41, 0x9a3: 0x0269, | ||
1020 | 0x9a4: 0x0fb9, 0x9a5: 0x1089, 0x9a6: 0x1099, 0x9a7: 0x10b1, 0x9a8: 0x1111, 0x9a9: 0x10e1, | ||
1021 | 0x9aa: 0x10f9, 0x9ab: 0x0008, 0x9ac: 0x0008, 0x9ad: 0x0008, 0x9ae: 0x0008, 0x9af: 0x0008, | ||
1022 | 0x9b0: 0x0008, 0x9b1: 0x0008, 0x9b2: 0x0008, 0x9b3: 0x0008, 0x9b4: 0x0008, 0x9b5: 0x0008, | ||
1023 | 0x9b6: 0x0008, 0x9b7: 0x0008, 0x9b8: 0x1129, 0x9b9: 0x0008, 0x9ba: 0x0008, 0x9bb: 0x0008, | ||
1024 | 0x9bc: 0x0008, 0x9bd: 0x0008, 0x9be: 0x0008, 0x9bf: 0x0008, | ||
1025 | // Block 0x27, offset 0x9c0 | ||
1026 | 0x9c0: 0x0008, 0x9c1: 0x0008, 0x9c2: 0x0008, 0x9c3: 0x0008, 0x9c4: 0x0008, 0x9c5: 0x0008, | ||
1027 | 0x9c6: 0x0008, 0x9c7: 0x0008, 0x9c8: 0x0008, 0x9c9: 0x0008, 0x9ca: 0x0008, 0x9cb: 0x0008, | ||
1028 | 0x9cc: 0x0008, 0x9cd: 0x0008, 0x9ce: 0x0008, 0x9cf: 0x0008, 0x9d0: 0x0008, 0x9d1: 0x0008, | ||
1029 | 0x9d2: 0x0008, 0x9d3: 0x0008, 0x9d4: 0x0008, 0x9d5: 0x0008, 0x9d6: 0x0008, 0x9d7: 0x0008, | ||
1030 | 0x9d8: 0x0008, 0x9d9: 0x0008, 0x9da: 0x0008, 0x9db: 0x1141, 0x9dc: 0x1159, 0x9dd: 0x1169, | ||
1031 | 0x9de: 0x1181, 0x9df: 0x1029, 0x9e0: 0x1199, 0x9e1: 0x11a9, 0x9e2: 0x11c1, 0x9e3: 0x11d9, | ||
1032 | 0x9e4: 0x11f1, 0x9e5: 0x1209, 0x9e6: 0x1221, 0x9e7: 0x05e5, 0x9e8: 0x1239, 0x9e9: 0x1251, | ||
1033 | 0x9ea: 0xe17d, 0x9eb: 0x1269, 0x9ec: 0x1281, 0x9ed: 0x1299, 0x9ee: 0x12b1, 0x9ef: 0x12c9, | ||
1034 | 0x9f0: 0x12e1, 0x9f1: 0x12f9, 0x9f2: 0x1311, 0x9f3: 0x1329, 0x9f4: 0x1341, 0x9f5: 0x1359, | ||
1035 | 0x9f6: 0x1371, 0x9f7: 0x1389, 0x9f8: 0x05fd, 0x9f9: 0x13a1, 0x9fa: 0x13b9, 0x9fb: 0x13d1, | ||
1036 | 0x9fc: 0x13e1, 0x9fd: 0x13f9, 0x9fe: 0x1411, 0x9ff: 0x1429, | ||
1037 | // Block 0x28, offset 0xa00 | ||
1038 | 0xa00: 0xe00d, 0xa01: 0x0008, 0xa02: 0xe00d, 0xa03: 0x0008, 0xa04: 0xe00d, 0xa05: 0x0008, | ||
1039 | 0xa06: 0xe00d, 0xa07: 0x0008, 0xa08: 0xe00d, 0xa09: 0x0008, 0xa0a: 0xe00d, 0xa0b: 0x0008, | ||
1040 | 0xa0c: 0xe00d, 0xa0d: 0x0008, 0xa0e: 0xe00d, 0xa0f: 0x0008, 0xa10: 0xe00d, 0xa11: 0x0008, | ||
1041 | 0xa12: 0xe00d, 0xa13: 0x0008, 0xa14: 0xe00d, 0xa15: 0x0008, 0xa16: 0xe00d, 0xa17: 0x0008, | ||
1042 | 0xa18: 0xe00d, 0xa19: 0x0008, 0xa1a: 0xe00d, 0xa1b: 0x0008, 0xa1c: 0xe00d, 0xa1d: 0x0008, | ||
1043 | 0xa1e: 0xe00d, 0xa1f: 0x0008, 0xa20: 0xe00d, 0xa21: 0x0008, 0xa22: 0xe00d, 0xa23: 0x0008, | ||
1044 | 0xa24: 0xe00d, 0xa25: 0x0008, 0xa26: 0xe00d, 0xa27: 0x0008, 0xa28: 0xe00d, 0xa29: 0x0008, | ||
1045 | 0xa2a: 0xe00d, 0xa2b: 0x0008, 0xa2c: 0xe00d, 0xa2d: 0x0008, 0xa2e: 0xe00d, 0xa2f: 0x0008, | ||
1046 | 0xa30: 0xe00d, 0xa31: 0x0008, 0xa32: 0xe00d, 0xa33: 0x0008, 0xa34: 0xe00d, 0xa35: 0x0008, | ||
1047 | 0xa36: 0xe00d, 0xa37: 0x0008, 0xa38: 0xe00d, 0xa39: 0x0008, 0xa3a: 0xe00d, 0xa3b: 0x0008, | ||
1048 | 0xa3c: 0xe00d, 0xa3d: 0x0008, 0xa3e: 0xe00d, 0xa3f: 0x0008, | ||
1049 | // Block 0x29, offset 0xa40 | ||
1050 | 0xa40: 0xe00d, 0xa41: 0x0008, 0xa42: 0xe00d, 0xa43: 0x0008, 0xa44: 0xe00d, 0xa45: 0x0008, | ||
1051 | 0xa46: 0xe00d, 0xa47: 0x0008, 0xa48: 0xe00d, 0xa49: 0x0008, 0xa4a: 0xe00d, 0xa4b: 0x0008, | ||
1052 | 0xa4c: 0xe00d, 0xa4d: 0x0008, 0xa4e: 0xe00d, 0xa4f: 0x0008, 0xa50: 0xe00d, 0xa51: 0x0008, | ||
1053 | 0xa52: 0xe00d, 0xa53: 0x0008, 0xa54: 0xe00d, 0xa55: 0x0008, 0xa56: 0x0008, 0xa57: 0x0008, | ||
1054 | 0xa58: 0x0008, 0xa59: 0x0008, 0xa5a: 0x0615, 0xa5b: 0x0635, 0xa5c: 0x0008, 0xa5d: 0x0008, | ||
1055 | 0xa5e: 0x1441, 0xa5f: 0x0008, 0xa60: 0xe00d, 0xa61: 0x0008, 0xa62: 0xe00d, 0xa63: 0x0008, | ||
1056 | 0xa64: 0xe00d, 0xa65: 0x0008, 0xa66: 0xe00d, 0xa67: 0x0008, 0xa68: 0xe00d, 0xa69: 0x0008, | ||
1057 | 0xa6a: 0xe00d, 0xa6b: 0x0008, 0xa6c: 0xe00d, 0xa6d: 0x0008, 0xa6e: 0xe00d, 0xa6f: 0x0008, | ||
1058 | 0xa70: 0xe00d, 0xa71: 0x0008, 0xa72: 0xe00d, 0xa73: 0x0008, 0xa74: 0xe00d, 0xa75: 0x0008, | ||
1059 | 0xa76: 0xe00d, 0xa77: 0x0008, 0xa78: 0xe00d, 0xa79: 0x0008, 0xa7a: 0xe00d, 0xa7b: 0x0008, | ||
1060 | 0xa7c: 0xe00d, 0xa7d: 0x0008, 0xa7e: 0xe00d, 0xa7f: 0x0008, | ||
1061 | // Block 0x2a, offset 0xa80 | ||
1062 | 0xa80: 0x0008, 0xa81: 0x0008, 0xa82: 0x0008, 0xa83: 0x0008, 0xa84: 0x0008, 0xa85: 0x0008, | ||
1063 | 0xa86: 0x0040, 0xa87: 0x0040, 0xa88: 0xe045, 0xa89: 0xe045, 0xa8a: 0xe045, 0xa8b: 0xe045, | ||
1064 | 0xa8c: 0xe045, 0xa8d: 0xe045, 0xa8e: 0x0040, 0xa8f: 0x0040, 0xa90: 0x0008, 0xa91: 0x0008, | ||
1065 | 0xa92: 0x0008, 0xa93: 0x0008, 0xa94: 0x0008, 0xa95: 0x0008, 0xa96: 0x0008, 0xa97: 0x0008, | ||
1066 | 0xa98: 0x0040, 0xa99: 0xe045, 0xa9a: 0x0040, 0xa9b: 0xe045, 0xa9c: 0x0040, 0xa9d: 0xe045, | ||
1067 | 0xa9e: 0x0040, 0xa9f: 0xe045, 0xaa0: 0x0008, 0xaa1: 0x0008, 0xaa2: 0x0008, 0xaa3: 0x0008, | ||
1068 | 0xaa4: 0x0008, 0xaa5: 0x0008, 0xaa6: 0x0008, 0xaa7: 0x0008, 0xaa8: 0xe045, 0xaa9: 0xe045, | ||
1069 | 0xaaa: 0xe045, 0xaab: 0xe045, 0xaac: 0xe045, 0xaad: 0xe045, 0xaae: 0xe045, 0xaaf: 0xe045, | ||
1070 | 0xab0: 0x0008, 0xab1: 0x1459, 0xab2: 0x0008, 0xab3: 0x1471, 0xab4: 0x0008, 0xab5: 0x1489, | ||
1071 | 0xab6: 0x0008, 0xab7: 0x14a1, 0xab8: 0x0008, 0xab9: 0x14b9, 0xaba: 0x0008, 0xabb: 0x14d1, | ||
1072 | 0xabc: 0x0008, 0xabd: 0x14e9, 0xabe: 0x0040, 0xabf: 0x0040, | ||
1073 | // Block 0x2b, offset 0xac0 | ||
1074 | 0xac0: 0x1501, 0xac1: 0x1531, 0xac2: 0x1561, 0xac3: 0x1591, 0xac4: 0x15c1, 0xac5: 0x15f1, | ||
1075 | 0xac6: 0x1621, 0xac7: 0x1651, 0xac8: 0x1501, 0xac9: 0x1531, 0xaca: 0x1561, 0xacb: 0x1591, | ||
1076 | 0xacc: 0x15c1, 0xacd: 0x15f1, 0xace: 0x1621, 0xacf: 0x1651, 0xad0: 0x1681, 0xad1: 0x16b1, | ||
1077 | 0xad2: 0x16e1, 0xad3: 0x1711, 0xad4: 0x1741, 0xad5: 0x1771, 0xad6: 0x17a1, 0xad7: 0x17d1, | ||
1078 | 0xad8: 0x1681, 0xad9: 0x16b1, 0xada: 0x16e1, 0xadb: 0x1711, 0xadc: 0x1741, 0xadd: 0x1771, | ||
1079 | 0xade: 0x17a1, 0xadf: 0x17d1, 0xae0: 0x1801, 0xae1: 0x1831, 0xae2: 0x1861, 0xae3: 0x1891, | ||
1080 | 0xae4: 0x18c1, 0xae5: 0x18f1, 0xae6: 0x1921, 0xae7: 0x1951, 0xae8: 0x1801, 0xae9: 0x1831, | ||
1081 | 0xaea: 0x1861, 0xaeb: 0x1891, 0xaec: 0x18c1, 0xaed: 0x18f1, 0xaee: 0x1921, 0xaef: 0x1951, | ||
1082 | 0xaf0: 0x0008, 0xaf1: 0x0008, 0xaf2: 0x1981, 0xaf3: 0x19b1, 0xaf4: 0x19d9, 0xaf5: 0x0040, | ||
1083 | 0xaf6: 0x0008, 0xaf7: 0x1a01, 0xaf8: 0xe045, 0xaf9: 0xe045, 0xafa: 0x064d, 0xafb: 0x1459, | ||
1084 | 0xafc: 0x19b1, 0xafd: 0x0666, 0xafe: 0x1a31, 0xaff: 0x0686, | ||
1085 | // Block 0x2c, offset 0xb00 | ||
1086 | 0xb00: 0x06a6, 0xb01: 0x1a4a, 0xb02: 0x1a79, 0xb03: 0x1aa9, 0xb04: 0x1ad1, 0xb05: 0x0040, | ||
1087 | 0xb06: 0x0008, 0xb07: 0x1af9, 0xb08: 0x06c5, 0xb09: 0x1471, 0xb0a: 0x06dd, 0xb0b: 0x1489, | ||
1088 | 0xb0c: 0x1aa9, 0xb0d: 0x1b2a, 0xb0e: 0x1b5a, 0xb0f: 0x1b8a, 0xb10: 0x0008, 0xb11: 0x0008, | ||
1089 | 0xb12: 0x0008, 0xb13: 0x1bb9, 0xb14: 0x0040, 0xb15: 0x0040, 0xb16: 0x0008, 0xb17: 0x0008, | ||
1090 | 0xb18: 0xe045, 0xb19: 0xe045, 0xb1a: 0x06f5, 0xb1b: 0x14a1, 0xb1c: 0x0040, 0xb1d: 0x1bd2, | ||
1091 | 0xb1e: 0x1c02, 0xb1f: 0x1c32, 0xb20: 0x0008, 0xb21: 0x0008, 0xb22: 0x0008, 0xb23: 0x1c61, | ||
1092 | 0xb24: 0x0008, 0xb25: 0x0008, 0xb26: 0x0008, 0xb27: 0x0008, 0xb28: 0xe045, 0xb29: 0xe045, | ||
1093 | 0xb2a: 0x070d, 0xb2b: 0x14d1, 0xb2c: 0xe04d, 0xb2d: 0x1c7a, 0xb2e: 0x03d2, 0xb2f: 0x1caa, | ||
1094 | 0xb30: 0x0040, 0xb31: 0x0040, 0xb32: 0x1cb9, 0xb33: 0x1ce9, 0xb34: 0x1d11, 0xb35: 0x0040, | ||
1095 | 0xb36: 0x0008, 0xb37: 0x1d39, 0xb38: 0x0725, 0xb39: 0x14b9, 0xb3a: 0x0515, 0xb3b: 0x14e9, | ||
1096 | 0xb3c: 0x1ce9, 0xb3d: 0x073e, 0xb3e: 0x075e, 0xb3f: 0x0040, | ||
1097 | // Block 0x2d, offset 0xb40 | ||
1098 | 0xb40: 0x000a, 0xb41: 0x000a, 0xb42: 0x000a, 0xb43: 0x000a, 0xb44: 0x000a, 0xb45: 0x000a, | ||
1099 | 0xb46: 0x000a, 0xb47: 0x000a, 0xb48: 0x000a, 0xb49: 0x000a, 0xb4a: 0x000a, 0xb4b: 0x03c0, | ||
1100 | 0xb4c: 0x0003, 0xb4d: 0x0003, 0xb4e: 0x0340, 0xb4f: 0x0340, 0xb50: 0x0018, 0xb51: 0xe00d, | ||
1101 | 0xb52: 0x0018, 0xb53: 0x0018, 0xb54: 0x0018, 0xb55: 0x0018, 0xb56: 0x0018, 0xb57: 0x077e, | ||
1102 | 0xb58: 0x0018, 0xb59: 0x0018, 0xb5a: 0x0018, 0xb5b: 0x0018, 0xb5c: 0x0018, 0xb5d: 0x0018, | ||
1103 | 0xb5e: 0x0018, 0xb5f: 0x0018, 0xb60: 0x0018, 0xb61: 0x0018, 0xb62: 0x0018, 0xb63: 0x0018, | ||
1104 | 0xb64: 0x0040, 0xb65: 0x0040, 0xb66: 0x0040, 0xb67: 0x0018, 0xb68: 0x0040, 0xb69: 0x0040, | ||
1105 | 0xb6a: 0x0340, 0xb6b: 0x0340, 0xb6c: 0x0340, 0xb6d: 0x0340, 0xb6e: 0x0340, 0xb6f: 0x000a, | ||
1106 | 0xb70: 0x0018, 0xb71: 0x0018, 0xb72: 0x0018, 0xb73: 0x1d69, 0xb74: 0x1da1, 0xb75: 0x0018, | ||
1107 | 0xb76: 0x1df1, 0xb77: 0x1e29, 0xb78: 0x0018, 0xb79: 0x0018, 0xb7a: 0x0018, 0xb7b: 0x0018, | ||
1108 | 0xb7c: 0x1e7a, 0xb7d: 0x0018, 0xb7e: 0x079e, 0xb7f: 0x0018, | ||
1109 | // Block 0x2e, offset 0xb80 | ||
1110 | 0xb80: 0x0018, 0xb81: 0x0018, 0xb82: 0x0018, 0xb83: 0x0018, 0xb84: 0x0018, 0xb85: 0x0018, | ||
1111 | 0xb86: 0x0018, 0xb87: 0x1e92, 0xb88: 0x1eaa, 0xb89: 0x1ec2, 0xb8a: 0x0018, 0xb8b: 0x0018, | ||
1112 | 0xb8c: 0x0018, 0xb8d: 0x0018, 0xb8e: 0x0018, 0xb8f: 0x0018, 0xb90: 0x0018, 0xb91: 0x0018, | ||
1113 | 0xb92: 0x0018, 0xb93: 0x0018, 0xb94: 0x0018, 0xb95: 0x0018, 0xb96: 0x0018, 0xb97: 0x1ed9, | ||
1114 | 0xb98: 0x0018, 0xb99: 0x0018, 0xb9a: 0x0018, 0xb9b: 0x0018, 0xb9c: 0x0018, 0xb9d: 0x0018, | ||
1115 | 0xb9e: 0x0018, 0xb9f: 0x000a, 0xba0: 0x03c0, 0xba1: 0x0340, 0xba2: 0x0340, 0xba3: 0x0340, | ||
1116 | 0xba4: 0x03c0, 0xba5: 0x0040, 0xba6: 0x0040, 0xba7: 0x0040, 0xba8: 0x0040, 0xba9: 0x0040, | ||
1117 | 0xbaa: 0x0340, 0xbab: 0x0340, 0xbac: 0x0340, 0xbad: 0x0340, 0xbae: 0x0340, 0xbaf: 0x0340, | ||
1118 | 0xbb0: 0x1f41, 0xbb1: 0x0f41, 0xbb2: 0x0040, 0xbb3: 0x0040, 0xbb4: 0x1f51, 0xbb5: 0x1f61, | ||
1119 | 0xbb6: 0x1f71, 0xbb7: 0x1f81, 0xbb8: 0x1f91, 0xbb9: 0x1fa1, 0xbba: 0x1fb2, 0xbbb: 0x07bd, | ||
1120 | 0xbbc: 0x1fc2, 0xbbd: 0x1fd2, 0xbbe: 0x1fe2, 0xbbf: 0x0f71, | ||
1121 | // Block 0x2f, offset 0xbc0 | ||
1122 | 0xbc0: 0x1f41, 0xbc1: 0x00c9, 0xbc2: 0x0069, 0xbc3: 0x0079, 0xbc4: 0x1f51, 0xbc5: 0x1f61, | ||
1123 | 0xbc6: 0x1f71, 0xbc7: 0x1f81, 0xbc8: 0x1f91, 0xbc9: 0x1fa1, 0xbca: 0x1fb2, 0xbcb: 0x07d5, | ||
1124 | 0xbcc: 0x1fc2, 0xbcd: 0x1fd2, 0xbce: 0x1fe2, 0xbcf: 0x0040, 0xbd0: 0x0039, 0xbd1: 0x0f09, | ||
1125 | 0xbd2: 0x00d9, 0xbd3: 0x0369, 0xbd4: 0x0ff9, 0xbd5: 0x0249, 0xbd6: 0x0f51, 0xbd7: 0x0359, | ||
1126 | 0xbd8: 0x0f61, 0xbd9: 0x0f71, 0xbda: 0x0f99, 0xbdb: 0x01d9, 0xbdc: 0x0fa9, 0xbdd: 0x0040, | ||
1127 | 0xbde: 0x0040, 0xbdf: 0x0040, 0xbe0: 0x0018, 0xbe1: 0x0018, 0xbe2: 0x0018, 0xbe3: 0x0018, | ||
1128 | 0xbe4: 0x0018, 0xbe5: 0x0018, 0xbe6: 0x0018, 0xbe7: 0x0018, 0xbe8: 0x1ff1, 0xbe9: 0x0018, | ||
1129 | 0xbea: 0x0018, 0xbeb: 0x0018, 0xbec: 0x0018, 0xbed: 0x0018, 0xbee: 0x0018, 0xbef: 0x0018, | ||
1130 | 0xbf0: 0x0018, 0xbf1: 0x0018, 0xbf2: 0x0018, 0xbf3: 0x0018, 0xbf4: 0x0018, 0xbf5: 0x0018, | ||
1131 | 0xbf6: 0x0018, 0xbf7: 0x0018, 0xbf8: 0x0018, 0xbf9: 0x0018, 0xbfa: 0x0018, 0xbfb: 0x0018, | ||
1132 | 0xbfc: 0x0018, 0xbfd: 0x0018, 0xbfe: 0x0018, 0xbff: 0x0040, | ||
1133 | // Block 0x30, offset 0xc00 | ||
1134 | 0xc00: 0x07ee, 0xc01: 0x080e, 0xc02: 0x1159, 0xc03: 0x082d, 0xc04: 0x0018, 0xc05: 0x084e, | ||
1135 | 0xc06: 0x086e, 0xc07: 0x1011, 0xc08: 0x0018, 0xc09: 0x088d, 0xc0a: 0x0f31, 0xc0b: 0x0249, | ||
1136 | 0xc0c: 0x0249, 0xc0d: 0x0249, 0xc0e: 0x0249, 0xc0f: 0x2009, 0xc10: 0x0f41, 0xc11: 0x0f41, | ||
1137 | 0xc12: 0x0359, 0xc13: 0x0359, 0xc14: 0x0018, 0xc15: 0x0f71, 0xc16: 0x2021, 0xc17: 0x0018, | ||
1138 | 0xc18: 0x0018, 0xc19: 0x0f99, 0xc1a: 0x2039, 0xc1b: 0x0269, 0xc1c: 0x0269, 0xc1d: 0x0269, | ||
1139 | 0xc1e: 0x0018, 0xc1f: 0x0018, 0xc20: 0x2049, 0xc21: 0x08ad, 0xc22: 0x2061, 0xc23: 0x0018, | ||
1140 | 0xc24: 0x13d1, 0xc25: 0x0018, 0xc26: 0x2079, 0xc27: 0x0018, 0xc28: 0x13d1, 0xc29: 0x0018, | ||
1141 | 0xc2a: 0x0f51, 0xc2b: 0x2091, 0xc2c: 0x0ee9, 0xc2d: 0x1159, 0xc2e: 0x0018, 0xc2f: 0x0f09, | ||
1142 | 0xc30: 0x0f09, 0xc31: 0x1199, 0xc32: 0x0040, 0xc33: 0x0f61, 0xc34: 0x00d9, 0xc35: 0x20a9, | ||
1143 | 0xc36: 0x20c1, 0xc37: 0x20d9, 0xc38: 0x20f1, 0xc39: 0x0f41, 0xc3a: 0x0018, 0xc3b: 0x08cd, | ||
1144 | 0xc3c: 0x2109, 0xc3d: 0x10b1, 0xc3e: 0x10b1, 0xc3f: 0x2109, | ||
1145 | // Block 0x31, offset 0xc40 | ||
1146 | 0xc40: 0x08ed, 0xc41: 0x0018, 0xc42: 0x0018, 0xc43: 0x0018, 0xc44: 0x0018, 0xc45: 0x0ef9, | ||
1147 | 0xc46: 0x0ef9, 0xc47: 0x0f09, 0xc48: 0x0f41, 0xc49: 0x0259, 0xc4a: 0x0018, 0xc4b: 0x0018, | ||
1148 | 0xc4c: 0x0018, 0xc4d: 0x0018, 0xc4e: 0x0008, 0xc4f: 0x0018, 0xc50: 0x2121, 0xc51: 0x2151, | ||
1149 | 0xc52: 0x2181, 0xc53: 0x21b9, 0xc54: 0x21e9, 0xc55: 0x2219, 0xc56: 0x2249, 0xc57: 0x2279, | ||
1150 | 0xc58: 0x22a9, 0xc59: 0x22d9, 0xc5a: 0x2309, 0xc5b: 0x2339, 0xc5c: 0x2369, 0xc5d: 0x2399, | ||
1151 | 0xc5e: 0x23c9, 0xc5f: 0x23f9, 0xc60: 0x0f41, 0xc61: 0x2421, 0xc62: 0x0905, 0xc63: 0x2439, | ||
1152 | 0xc64: 0x1089, 0xc65: 0x2451, 0xc66: 0x0925, 0xc67: 0x2469, 0xc68: 0x2491, 0xc69: 0x0369, | ||
1153 | 0xc6a: 0x24a9, 0xc6b: 0x0945, 0xc6c: 0x0359, 0xc6d: 0x1159, 0xc6e: 0x0ef9, 0xc6f: 0x0f61, | ||
1154 | 0xc70: 0x0f41, 0xc71: 0x2421, 0xc72: 0x0965, 0xc73: 0x2439, 0xc74: 0x1089, 0xc75: 0x2451, | ||
1155 | 0xc76: 0x0985, 0xc77: 0x2469, 0xc78: 0x2491, 0xc79: 0x0369, 0xc7a: 0x24a9, 0xc7b: 0x09a5, | ||
1156 | 0xc7c: 0x0359, 0xc7d: 0x1159, 0xc7e: 0x0ef9, 0xc7f: 0x0f61, | ||
1157 | // Block 0x32, offset 0xc80 | ||
1158 | 0xc80: 0x0018, 0xc81: 0x0018, 0xc82: 0x0018, 0xc83: 0x0018, 0xc84: 0x0018, 0xc85: 0x0018, | ||
1159 | 0xc86: 0x0018, 0xc87: 0x0018, 0xc88: 0x0018, 0xc89: 0x0018, 0xc8a: 0x0018, 0xc8b: 0x0040, | ||
1160 | 0xc8c: 0x0040, 0xc8d: 0x0040, 0xc8e: 0x0040, 0xc8f: 0x0040, 0xc90: 0x0040, 0xc91: 0x0040, | ||
1161 | 0xc92: 0x0040, 0xc93: 0x0040, 0xc94: 0x0040, 0xc95: 0x0040, 0xc96: 0x0040, 0xc97: 0x0040, | ||
1162 | 0xc98: 0x0040, 0xc99: 0x0040, 0xc9a: 0x0040, 0xc9b: 0x0040, 0xc9c: 0x0040, 0xc9d: 0x0040, | ||
1163 | 0xc9e: 0x0040, 0xc9f: 0x0040, 0xca0: 0x00c9, 0xca1: 0x0069, 0xca2: 0x0079, 0xca3: 0x1f51, | ||
1164 | 0xca4: 0x1f61, 0xca5: 0x1f71, 0xca6: 0x1f81, 0xca7: 0x1f91, 0xca8: 0x1fa1, 0xca9: 0x2601, | ||
1165 | 0xcaa: 0x2619, 0xcab: 0x2631, 0xcac: 0x2649, 0xcad: 0x2661, 0xcae: 0x2679, 0xcaf: 0x2691, | ||
1166 | 0xcb0: 0x26a9, 0xcb1: 0x26c1, 0xcb2: 0x26d9, 0xcb3: 0x26f1, 0xcb4: 0x0a06, 0xcb5: 0x0a26, | ||
1167 | 0xcb6: 0x0a46, 0xcb7: 0x0a66, 0xcb8: 0x0a86, 0xcb9: 0x0aa6, 0xcba: 0x0ac6, 0xcbb: 0x0ae6, | ||
1168 | 0xcbc: 0x0b06, 0xcbd: 0x270a, 0xcbe: 0x2732, 0xcbf: 0x275a, | ||
1169 | // Block 0x33, offset 0xcc0 | ||
1170 | 0xcc0: 0x2782, 0xcc1: 0x27aa, 0xcc2: 0x27d2, 0xcc3: 0x27fa, 0xcc4: 0x2822, 0xcc5: 0x284a, | ||
1171 | 0xcc6: 0x2872, 0xcc7: 0x289a, 0xcc8: 0x0040, 0xcc9: 0x0040, 0xcca: 0x0040, 0xccb: 0x0040, | ||
1172 | 0xccc: 0x0040, 0xccd: 0x0040, 0xcce: 0x0040, 0xccf: 0x0040, 0xcd0: 0x0040, 0xcd1: 0x0040, | ||
1173 | 0xcd2: 0x0040, 0xcd3: 0x0040, 0xcd4: 0x0040, 0xcd5: 0x0040, 0xcd6: 0x0040, 0xcd7: 0x0040, | ||
1174 | 0xcd8: 0x0040, 0xcd9: 0x0040, 0xcda: 0x0040, 0xcdb: 0x0040, 0xcdc: 0x0b26, 0xcdd: 0x0b46, | ||
1175 | 0xcde: 0x0b66, 0xcdf: 0x0b86, 0xce0: 0x0ba6, 0xce1: 0x0bc6, 0xce2: 0x0be6, 0xce3: 0x0c06, | ||
1176 | 0xce4: 0x0c26, 0xce5: 0x0c46, 0xce6: 0x0c66, 0xce7: 0x0c86, 0xce8: 0x0ca6, 0xce9: 0x0cc6, | ||
1177 | 0xcea: 0x0ce6, 0xceb: 0x0d06, 0xcec: 0x0d26, 0xced: 0x0d46, 0xcee: 0x0d66, 0xcef: 0x0d86, | ||
1178 | 0xcf0: 0x0da6, 0xcf1: 0x0dc6, 0xcf2: 0x0de6, 0xcf3: 0x0e06, 0xcf4: 0x0e26, 0xcf5: 0x0e46, | ||
1179 | 0xcf6: 0x0039, 0xcf7: 0x0ee9, 0xcf8: 0x1159, 0xcf9: 0x0ef9, 0xcfa: 0x0f09, 0xcfb: 0x1199, | ||
1180 | 0xcfc: 0x0f31, 0xcfd: 0x0249, 0xcfe: 0x0f41, 0xcff: 0x0259, | ||
1181 | // Block 0x34, offset 0xd00 | ||
1182 | 0xd00: 0x0f51, 0xd01: 0x0359, 0xd02: 0x0f61, 0xd03: 0x0f71, 0xd04: 0x00d9, 0xd05: 0x0f99, | ||
1183 | 0xd06: 0x2039, 0xd07: 0x0269, 0xd08: 0x01d9, 0xd09: 0x0fa9, 0xd0a: 0x0fb9, 0xd0b: 0x1089, | ||
1184 | 0xd0c: 0x0279, 0xd0d: 0x0369, 0xd0e: 0x0289, 0xd0f: 0x13d1, 0xd10: 0x0039, 0xd11: 0x0ee9, | ||
1185 | 0xd12: 0x1159, 0xd13: 0x0ef9, 0xd14: 0x0f09, 0xd15: 0x1199, 0xd16: 0x0f31, 0xd17: 0x0249, | ||
1186 | 0xd18: 0x0f41, 0xd19: 0x0259, 0xd1a: 0x0f51, 0xd1b: 0x0359, 0xd1c: 0x0f61, 0xd1d: 0x0f71, | ||
1187 | 0xd1e: 0x00d9, 0xd1f: 0x0f99, 0xd20: 0x2039, 0xd21: 0x0269, 0xd22: 0x01d9, 0xd23: 0x0fa9, | ||
1188 | 0xd24: 0x0fb9, 0xd25: 0x1089, 0xd26: 0x0279, 0xd27: 0x0369, 0xd28: 0x0289, 0xd29: 0x13d1, | ||
1189 | 0xd2a: 0x1f41, 0xd2b: 0x0018, 0xd2c: 0x0018, 0xd2d: 0x0018, 0xd2e: 0x0018, 0xd2f: 0x0018, | ||
1190 | 0xd30: 0x0018, 0xd31: 0x0018, 0xd32: 0x0018, 0xd33: 0x0018, 0xd34: 0x0018, 0xd35: 0x0018, | ||
1191 | 0xd36: 0x0018, 0xd37: 0x0018, 0xd38: 0x0018, 0xd39: 0x0018, 0xd3a: 0x0018, 0xd3b: 0x0018, | ||
1192 | 0xd3c: 0x0018, 0xd3d: 0x0018, 0xd3e: 0x0018, 0xd3f: 0x0018, | ||
1193 | // Block 0x35, offset 0xd40 | ||
1194 | 0xd40: 0x0008, 0xd41: 0x0008, 0xd42: 0x0008, 0xd43: 0x0008, 0xd44: 0x0008, 0xd45: 0x0008, | ||
1195 | 0xd46: 0x0008, 0xd47: 0x0008, 0xd48: 0x0008, 0xd49: 0x0008, 0xd4a: 0x0008, 0xd4b: 0x0008, | ||
1196 | 0xd4c: 0x0008, 0xd4d: 0x0008, 0xd4e: 0x0008, 0xd4f: 0x0008, 0xd50: 0x0008, 0xd51: 0x0008, | ||
1197 | 0xd52: 0x0008, 0xd53: 0x0008, 0xd54: 0x0008, 0xd55: 0x0008, 0xd56: 0x0008, 0xd57: 0x0008, | ||
1198 | 0xd58: 0x0008, 0xd59: 0x0008, 0xd5a: 0x0008, 0xd5b: 0x0008, 0xd5c: 0x0008, 0xd5d: 0x0008, | ||
1199 | 0xd5e: 0x0008, 0xd5f: 0x0040, 0xd60: 0xe00d, 0xd61: 0x0008, 0xd62: 0x2971, 0xd63: 0x0ebd, | ||
1200 | 0xd64: 0x2989, 0xd65: 0x0008, 0xd66: 0x0008, 0xd67: 0xe07d, 0xd68: 0x0008, 0xd69: 0xe01d, | ||
1201 | 0xd6a: 0x0008, 0xd6b: 0xe03d, 0xd6c: 0x0008, 0xd6d: 0x0fe1, 0xd6e: 0x1281, 0xd6f: 0x0fc9, | ||
1202 | 0xd70: 0x1141, 0xd71: 0x0008, 0xd72: 0xe00d, 0xd73: 0x0008, 0xd74: 0x0008, 0xd75: 0xe01d, | ||
1203 | 0xd76: 0x0008, 0xd77: 0x0008, 0xd78: 0x0008, 0xd79: 0x0008, 0xd7a: 0x0008, 0xd7b: 0x0008, | ||
1204 | 0xd7c: 0x0259, 0xd7d: 0x1089, 0xd7e: 0x29a1, 0xd7f: 0x29b9, | ||
1205 | // Block 0x36, offset 0xd80 | ||
1206 | 0xd80: 0xe00d, 0xd81: 0x0008, 0xd82: 0xe00d, 0xd83: 0x0008, 0xd84: 0xe00d, 0xd85: 0x0008, | ||
1207 | 0xd86: 0xe00d, 0xd87: 0x0008, 0xd88: 0xe00d, 0xd89: 0x0008, 0xd8a: 0xe00d, 0xd8b: 0x0008, | ||
1208 | 0xd8c: 0xe00d, 0xd8d: 0x0008, 0xd8e: 0xe00d, 0xd8f: 0x0008, 0xd90: 0xe00d, 0xd91: 0x0008, | ||
1209 | 0xd92: 0xe00d, 0xd93: 0x0008, 0xd94: 0xe00d, 0xd95: 0x0008, 0xd96: 0xe00d, 0xd97: 0x0008, | ||
1210 | 0xd98: 0xe00d, 0xd99: 0x0008, 0xd9a: 0xe00d, 0xd9b: 0x0008, 0xd9c: 0xe00d, 0xd9d: 0x0008, | ||
1211 | 0xd9e: 0xe00d, 0xd9f: 0x0008, 0xda0: 0xe00d, 0xda1: 0x0008, 0xda2: 0xe00d, 0xda3: 0x0008, | ||
1212 | 0xda4: 0x0008, 0xda5: 0x0018, 0xda6: 0x0018, 0xda7: 0x0018, 0xda8: 0x0018, 0xda9: 0x0018, | ||
1213 | 0xdaa: 0x0018, 0xdab: 0xe03d, 0xdac: 0x0008, 0xdad: 0xe01d, 0xdae: 0x0008, 0xdaf: 0x1308, | ||
1214 | 0xdb0: 0x1308, 0xdb1: 0x1308, 0xdb2: 0xe00d, 0xdb3: 0x0008, 0xdb4: 0x0040, 0xdb5: 0x0040, | ||
1215 | 0xdb6: 0x0040, 0xdb7: 0x0040, 0xdb8: 0x0040, 0xdb9: 0x0018, 0xdba: 0x0018, 0xdbb: 0x0018, | ||
1216 | 0xdbc: 0x0018, 0xdbd: 0x0018, 0xdbe: 0x0018, 0xdbf: 0x0018, | ||
1217 | // Block 0x37, offset 0xdc0 | ||
1218 | 0xdc0: 0x26fd, 0xdc1: 0x271d, 0xdc2: 0x273d, 0xdc3: 0x275d, 0xdc4: 0x277d, 0xdc5: 0x279d, | ||
1219 | 0xdc6: 0x27bd, 0xdc7: 0x27dd, 0xdc8: 0x27fd, 0xdc9: 0x281d, 0xdca: 0x283d, 0xdcb: 0x285d, | ||
1220 | 0xdcc: 0x287d, 0xdcd: 0x289d, 0xdce: 0x28bd, 0xdcf: 0x28dd, 0xdd0: 0x28fd, 0xdd1: 0x291d, | ||
1221 | 0xdd2: 0x293d, 0xdd3: 0x295d, 0xdd4: 0x297d, 0xdd5: 0x299d, 0xdd6: 0x0040, 0xdd7: 0x0040, | ||
1222 | 0xdd8: 0x0040, 0xdd9: 0x0040, 0xdda: 0x0040, 0xddb: 0x0040, 0xddc: 0x0040, 0xddd: 0x0040, | ||
1223 | 0xdde: 0x0040, 0xddf: 0x0040, 0xde0: 0x0040, 0xde1: 0x0040, 0xde2: 0x0040, 0xde3: 0x0040, | ||
1224 | 0xde4: 0x0040, 0xde5: 0x0040, 0xde6: 0x0040, 0xde7: 0x0040, 0xde8: 0x0040, 0xde9: 0x0040, | ||
1225 | 0xdea: 0x0040, 0xdeb: 0x0040, 0xdec: 0x0040, 0xded: 0x0040, 0xdee: 0x0040, 0xdef: 0x0040, | ||
1226 | 0xdf0: 0x0040, 0xdf1: 0x0040, 0xdf2: 0x0040, 0xdf3: 0x0040, 0xdf4: 0x0040, 0xdf5: 0x0040, | ||
1227 | 0xdf6: 0x0040, 0xdf7: 0x0040, 0xdf8: 0x0040, 0xdf9: 0x0040, 0xdfa: 0x0040, 0xdfb: 0x0040, | ||
1228 | 0xdfc: 0x0040, 0xdfd: 0x0040, 0xdfe: 0x0040, 0xdff: 0x0040, | ||
1229 | // Block 0x38, offset 0xe00 | ||
1230 | 0xe00: 0x000a, 0xe01: 0x0018, 0xe02: 0x29d1, 0xe03: 0x0018, 0xe04: 0x0018, 0xe05: 0x0008, | ||
1231 | 0xe06: 0x0008, 0xe07: 0x0008, 0xe08: 0x0018, 0xe09: 0x0018, 0xe0a: 0x0018, 0xe0b: 0x0018, | ||
1232 | 0xe0c: 0x0018, 0xe0d: 0x0018, 0xe0e: 0x0018, 0xe0f: 0x0018, 0xe10: 0x0018, 0xe11: 0x0018, | ||
1233 | 0xe12: 0x0018, 0xe13: 0x0018, 0xe14: 0x0018, 0xe15: 0x0018, 0xe16: 0x0018, 0xe17: 0x0018, | ||
1234 | 0xe18: 0x0018, 0xe19: 0x0018, 0xe1a: 0x0018, 0xe1b: 0x0018, 0xe1c: 0x0018, 0xe1d: 0x0018, | ||
1235 | 0xe1e: 0x0018, 0xe1f: 0x0018, 0xe20: 0x0018, 0xe21: 0x0018, 0xe22: 0x0018, 0xe23: 0x0018, | ||
1236 | 0xe24: 0x0018, 0xe25: 0x0018, 0xe26: 0x0018, 0xe27: 0x0018, 0xe28: 0x0018, 0xe29: 0x0018, | ||
1237 | 0xe2a: 0x1308, 0xe2b: 0x1308, 0xe2c: 0x1308, 0xe2d: 0x1308, 0xe2e: 0x1018, 0xe2f: 0x1018, | ||
1238 | 0xe30: 0x0018, 0xe31: 0x0018, 0xe32: 0x0018, 0xe33: 0x0018, 0xe34: 0x0018, 0xe35: 0x0018, | ||
1239 | 0xe36: 0xe125, 0xe37: 0x0018, 0xe38: 0x29bd, 0xe39: 0x29dd, 0xe3a: 0x29fd, 0xe3b: 0x0018, | ||
1240 | 0xe3c: 0x0008, 0xe3d: 0x0018, 0xe3e: 0x0018, 0xe3f: 0x0018, | ||
1241 | // Block 0x39, offset 0xe40 | ||
1242 | 0xe40: 0x2b3d, 0xe41: 0x2b5d, 0xe42: 0x2b7d, 0xe43: 0x2b9d, 0xe44: 0x2bbd, 0xe45: 0x2bdd, | ||
1243 | 0xe46: 0x2bdd, 0xe47: 0x2bdd, 0xe48: 0x2bfd, 0xe49: 0x2bfd, 0xe4a: 0x2bfd, 0xe4b: 0x2bfd, | ||
1244 | 0xe4c: 0x2c1d, 0xe4d: 0x2c1d, 0xe4e: 0x2c1d, 0xe4f: 0x2c3d, 0xe50: 0x2c5d, 0xe51: 0x2c5d, | ||
1245 | 0xe52: 0x2a7d, 0xe53: 0x2a7d, 0xe54: 0x2c5d, 0xe55: 0x2c5d, 0xe56: 0x2c7d, 0xe57: 0x2c7d, | ||
1246 | 0xe58: 0x2c5d, 0xe59: 0x2c5d, 0xe5a: 0x2a7d, 0xe5b: 0x2a7d, 0xe5c: 0x2c5d, 0xe5d: 0x2c5d, | ||
1247 | 0xe5e: 0x2c3d, 0xe5f: 0x2c3d, 0xe60: 0x2c9d, 0xe61: 0x2c9d, 0xe62: 0x2cbd, 0xe63: 0x2cbd, | ||
1248 | 0xe64: 0x0040, 0xe65: 0x2cdd, 0xe66: 0x2cfd, 0xe67: 0x2d1d, 0xe68: 0x2d1d, 0xe69: 0x2d3d, | ||
1249 | 0xe6a: 0x2d5d, 0xe6b: 0x2d7d, 0xe6c: 0x2d9d, 0xe6d: 0x2dbd, 0xe6e: 0x2ddd, 0xe6f: 0x2dfd, | ||
1250 | 0xe70: 0x2e1d, 0xe71: 0x2e3d, 0xe72: 0x2e3d, 0xe73: 0x2e5d, 0xe74: 0x2e7d, 0xe75: 0x2e7d, | ||
1251 | 0xe76: 0x2e9d, 0xe77: 0x2ebd, 0xe78: 0x2e5d, 0xe79: 0x2edd, 0xe7a: 0x2efd, 0xe7b: 0x2edd, | ||
1252 | 0xe7c: 0x2e5d, 0xe7d: 0x2f1d, 0xe7e: 0x2f3d, 0xe7f: 0x2f5d, | ||
1253 | // Block 0x3a, offset 0xe80 | ||
1254 | 0xe80: 0x2f7d, 0xe81: 0x2f9d, 0xe82: 0x2cfd, 0xe83: 0x2cdd, 0xe84: 0x2fbd, 0xe85: 0x2fdd, | ||
1255 | 0xe86: 0x2ffd, 0xe87: 0x301d, 0xe88: 0x303d, 0xe89: 0x305d, 0xe8a: 0x307d, 0xe8b: 0x309d, | ||
1256 | 0xe8c: 0x30bd, 0xe8d: 0x30dd, 0xe8e: 0x30fd, 0xe8f: 0x0040, 0xe90: 0x0018, 0xe91: 0x0018, | ||
1257 | 0xe92: 0x311d, 0xe93: 0x313d, 0xe94: 0x315d, 0xe95: 0x317d, 0xe96: 0x319d, 0xe97: 0x31bd, | ||
1258 | 0xe98: 0x31dd, 0xe99: 0x31fd, 0xe9a: 0x321d, 0xe9b: 0x323d, 0xe9c: 0x315d, 0xe9d: 0x325d, | ||
1259 | 0xe9e: 0x327d, 0xe9f: 0x329d, 0xea0: 0x0008, 0xea1: 0x0008, 0xea2: 0x0008, 0xea3: 0x0008, | ||
1260 | 0xea4: 0x0008, 0xea5: 0x0008, 0xea6: 0x0008, 0xea7: 0x0008, 0xea8: 0x0008, 0xea9: 0x0008, | ||
1261 | 0xeaa: 0x0008, 0xeab: 0x0008, 0xeac: 0x0008, 0xead: 0x0008, 0xeae: 0x0008, 0xeaf: 0x0008, | ||
1262 | 0xeb0: 0x0008, 0xeb1: 0x0008, 0xeb2: 0x0008, 0xeb3: 0x0008, 0xeb4: 0x0008, 0xeb5: 0x0008, | ||
1263 | 0xeb6: 0x0008, 0xeb7: 0x0008, 0xeb8: 0x0008, 0xeb9: 0x0008, 0xeba: 0x0008, 0xebb: 0x0040, | ||
1264 | 0xebc: 0x0040, 0xebd: 0x0040, 0xebe: 0x0040, 0xebf: 0x0040, | ||
1265 | // Block 0x3b, offset 0xec0 | ||
1266 | 0xec0: 0x36a2, 0xec1: 0x36d2, 0xec2: 0x3702, 0xec3: 0x3732, 0xec4: 0x32bd, 0xec5: 0x32dd, | ||
1267 | 0xec6: 0x32fd, 0xec7: 0x331d, 0xec8: 0x0018, 0xec9: 0x0018, 0xeca: 0x0018, 0xecb: 0x0018, | ||
1268 | 0xecc: 0x0018, 0xecd: 0x0018, 0xece: 0x0018, 0xecf: 0x0018, 0xed0: 0x333d, 0xed1: 0x3761, | ||
1269 | 0xed2: 0x3779, 0xed3: 0x3791, 0xed4: 0x37a9, 0xed5: 0x37c1, 0xed6: 0x37d9, 0xed7: 0x37f1, | ||
1270 | 0xed8: 0x3809, 0xed9: 0x3821, 0xeda: 0x3839, 0xedb: 0x3851, 0xedc: 0x3869, 0xedd: 0x3881, | ||
1271 | 0xede: 0x3899, 0xedf: 0x38b1, 0xee0: 0x335d, 0xee1: 0x337d, 0xee2: 0x339d, 0xee3: 0x33bd, | ||
1272 | 0xee4: 0x33dd, 0xee5: 0x33dd, 0xee6: 0x33fd, 0xee7: 0x341d, 0xee8: 0x343d, 0xee9: 0x345d, | ||
1273 | 0xeea: 0x347d, 0xeeb: 0x349d, 0xeec: 0x34bd, 0xeed: 0x34dd, 0xeee: 0x34fd, 0xeef: 0x351d, | ||
1274 | 0xef0: 0x353d, 0xef1: 0x355d, 0xef2: 0x357d, 0xef3: 0x359d, 0xef4: 0x35bd, 0xef5: 0x35dd, | ||
1275 | 0xef6: 0x35fd, 0xef7: 0x361d, 0xef8: 0x363d, 0xef9: 0x365d, 0xefa: 0x367d, 0xefb: 0x369d, | ||
1276 | 0xefc: 0x38c9, 0xefd: 0x3901, 0xefe: 0x36bd, 0xeff: 0x0018, | ||
1277 | // Block 0x3c, offset 0xf00 | ||
1278 | 0xf00: 0x36dd, 0xf01: 0x36fd, 0xf02: 0x371d, 0xf03: 0x373d, 0xf04: 0x375d, 0xf05: 0x377d, | ||
1279 | 0xf06: 0x379d, 0xf07: 0x37bd, 0xf08: 0x37dd, 0xf09: 0x37fd, 0xf0a: 0x381d, 0xf0b: 0x383d, | ||
1280 | 0xf0c: 0x385d, 0xf0d: 0x387d, 0xf0e: 0x389d, 0xf0f: 0x38bd, 0xf10: 0x38dd, 0xf11: 0x38fd, | ||
1281 | 0xf12: 0x391d, 0xf13: 0x393d, 0xf14: 0x395d, 0xf15: 0x397d, 0xf16: 0x399d, 0xf17: 0x39bd, | ||
1282 | 0xf18: 0x39dd, 0xf19: 0x39fd, 0xf1a: 0x3a1d, 0xf1b: 0x3a3d, 0xf1c: 0x3a5d, 0xf1d: 0x3a7d, | ||
1283 | 0xf1e: 0x3a9d, 0xf1f: 0x3abd, 0xf20: 0x3add, 0xf21: 0x3afd, 0xf22: 0x3b1d, 0xf23: 0x3b3d, | ||
1284 | 0xf24: 0x3b5d, 0xf25: 0x3b7d, 0xf26: 0x127d, 0xf27: 0x3b9d, 0xf28: 0x3bbd, 0xf29: 0x3bdd, | ||
1285 | 0xf2a: 0x3bfd, 0xf2b: 0x3c1d, 0xf2c: 0x3c3d, 0xf2d: 0x3c5d, 0xf2e: 0x239d, 0xf2f: 0x3c7d, | ||
1286 | 0xf30: 0x3c9d, 0xf31: 0x3939, 0xf32: 0x3951, 0xf33: 0x3969, 0xf34: 0x3981, 0xf35: 0x3999, | ||
1287 | 0xf36: 0x39b1, 0xf37: 0x39c9, 0xf38: 0x39e1, 0xf39: 0x39f9, 0xf3a: 0x3a11, 0xf3b: 0x3a29, | ||
1288 | 0xf3c: 0x3a41, 0xf3d: 0x3a59, 0xf3e: 0x3a71, 0xf3f: 0x3a89, | ||
1289 | // Block 0x3d, offset 0xf40 | ||
1290 | 0xf40: 0x3aa1, 0xf41: 0x3ac9, 0xf42: 0x3af1, 0xf43: 0x3b19, 0xf44: 0x3b41, 0xf45: 0x3b69, | ||
1291 | 0xf46: 0x3b91, 0xf47: 0x3bb9, 0xf48: 0x3be1, 0xf49: 0x3c09, 0xf4a: 0x3c39, 0xf4b: 0x3c69, | ||
1292 | 0xf4c: 0x3c99, 0xf4d: 0x3cbd, 0xf4e: 0x3cb1, 0xf4f: 0x3cdd, 0xf50: 0x3cfd, 0xf51: 0x3d15, | ||
1293 | 0xf52: 0x3d2d, 0xf53: 0x3d45, 0xf54: 0x3d5d, 0xf55: 0x3d5d, 0xf56: 0x3d45, 0xf57: 0x3d75, | ||
1294 | 0xf58: 0x07bd, 0xf59: 0x3d8d, 0xf5a: 0x3da5, 0xf5b: 0x3dbd, 0xf5c: 0x3dd5, 0xf5d: 0x3ded, | ||
1295 | 0xf5e: 0x3e05, 0xf5f: 0x3e1d, 0xf60: 0x3e35, 0xf61: 0x3e4d, 0xf62: 0x3e65, 0xf63: 0x3e7d, | ||
1296 | 0xf64: 0x3e95, 0xf65: 0x3e95, 0xf66: 0x3ead, 0xf67: 0x3ead, 0xf68: 0x3ec5, 0xf69: 0x3ec5, | ||
1297 | 0xf6a: 0x3edd, 0xf6b: 0x3ef5, 0xf6c: 0x3f0d, 0xf6d: 0x3f25, 0xf6e: 0x3f3d, 0xf6f: 0x3f3d, | ||
1298 | 0xf70: 0x3f55, 0xf71: 0x3f55, 0xf72: 0x3f55, 0xf73: 0x3f6d, 0xf74: 0x3f85, 0xf75: 0x3f9d, | ||
1299 | 0xf76: 0x3fb5, 0xf77: 0x3f9d, 0xf78: 0x3fcd, 0xf79: 0x3fe5, 0xf7a: 0x3f6d, 0xf7b: 0x3ffd, | ||
1300 | 0xf7c: 0x4015, 0xf7d: 0x4015, 0xf7e: 0x4015, 0xf7f: 0x0040, | ||
1301 | // Block 0x3e, offset 0xf80 | ||
1302 | 0xf80: 0x3cc9, 0xf81: 0x3d31, 0xf82: 0x3d99, 0xf83: 0x3e01, 0xf84: 0x3e51, 0xf85: 0x3eb9, | ||
1303 | 0xf86: 0x3f09, 0xf87: 0x3f59, 0xf88: 0x3fd9, 0xf89: 0x4041, 0xf8a: 0x4091, 0xf8b: 0x40e1, | ||
1304 | 0xf8c: 0x4131, 0xf8d: 0x4199, 0xf8e: 0x4201, 0xf8f: 0x4251, 0xf90: 0x42a1, 0xf91: 0x42d9, | ||
1305 | 0xf92: 0x4329, 0xf93: 0x4391, 0xf94: 0x43f9, 0xf95: 0x4431, 0xf96: 0x44b1, 0xf97: 0x4549, | ||
1306 | 0xf98: 0x45c9, 0xf99: 0x4619, 0xf9a: 0x4699, 0xf9b: 0x4719, 0xf9c: 0x4781, 0xf9d: 0x47d1, | ||
1307 | 0xf9e: 0x4821, 0xf9f: 0x4871, 0xfa0: 0x48d9, 0xfa1: 0x4959, 0xfa2: 0x49c1, 0xfa3: 0x4a11, | ||
1308 | 0xfa4: 0x4a61, 0xfa5: 0x4ab1, 0xfa6: 0x4ae9, 0xfa7: 0x4b21, 0xfa8: 0x4b59, 0xfa9: 0x4b91, | ||
1309 | 0xfaa: 0x4be1, 0xfab: 0x4c31, 0xfac: 0x4cb1, 0xfad: 0x4d01, 0xfae: 0x4d69, 0xfaf: 0x4de9, | ||
1310 | 0xfb0: 0x4e39, 0xfb1: 0x4e71, 0xfb2: 0x4ea9, 0xfb3: 0x4f29, 0xfb4: 0x4f91, 0xfb5: 0x5011, | ||
1311 | 0xfb6: 0x5061, 0xfb7: 0x50e1, 0xfb8: 0x5119, 0xfb9: 0x5169, 0xfba: 0x51b9, 0xfbb: 0x5209, | ||
1312 | 0xfbc: 0x5259, 0xfbd: 0x52a9, 0xfbe: 0x5311, 0xfbf: 0x5361, | ||
1313 | // Block 0x3f, offset 0xfc0 | ||
1314 | 0xfc0: 0x5399, 0xfc1: 0x53e9, 0xfc2: 0x5439, 0xfc3: 0x5489, 0xfc4: 0x54f1, 0xfc5: 0x5541, | ||
1315 | 0xfc6: 0x5591, 0xfc7: 0x55e1, 0xfc8: 0x5661, 0xfc9: 0x56c9, 0xfca: 0x5701, 0xfcb: 0x5781, | ||
1316 | 0xfcc: 0x57b9, 0xfcd: 0x5821, 0xfce: 0x5889, 0xfcf: 0x58d9, 0xfd0: 0x5929, 0xfd1: 0x5979, | ||
1317 | 0xfd2: 0x59e1, 0xfd3: 0x5a19, 0xfd4: 0x5a69, 0xfd5: 0x5ad1, 0xfd6: 0x5b09, 0xfd7: 0x5b89, | ||
1318 | 0xfd8: 0x5bd9, 0xfd9: 0x5c01, 0xfda: 0x5c29, 0xfdb: 0x5c51, 0xfdc: 0x5c79, 0xfdd: 0x5ca1, | ||
1319 | 0xfde: 0x5cc9, 0xfdf: 0x5cf1, 0xfe0: 0x5d19, 0xfe1: 0x5d41, 0xfe2: 0x5d69, 0xfe3: 0x5d99, | ||
1320 | 0xfe4: 0x5dc9, 0xfe5: 0x5df9, 0xfe6: 0x5e29, 0xfe7: 0x5e59, 0xfe8: 0x5e89, 0xfe9: 0x5eb9, | ||
1321 | 0xfea: 0x5ee9, 0xfeb: 0x5f19, 0xfec: 0x5f49, 0xfed: 0x5f79, 0xfee: 0x5fa9, 0xfef: 0x5fd9, | ||
1322 | 0xff0: 0x6009, 0xff1: 0x402d, 0xff2: 0x6039, 0xff3: 0x6051, 0xff4: 0x404d, 0xff5: 0x6069, | ||
1323 | 0xff6: 0x6081, 0xff7: 0x6099, 0xff8: 0x406d, 0xff9: 0x406d, 0xffa: 0x60b1, 0xffb: 0x60c9, | ||
1324 | 0xffc: 0x6101, 0xffd: 0x6139, 0xffe: 0x6171, 0xfff: 0x61a9, | ||
1325 | // Block 0x40, offset 0x1000 | ||
1326 | 0x1000: 0x6211, 0x1001: 0x6229, 0x1002: 0x408d, 0x1003: 0x6241, 0x1004: 0x6259, 0x1005: 0x6271, | ||
1327 | 0x1006: 0x6289, 0x1007: 0x62a1, 0x1008: 0x40ad, 0x1009: 0x62b9, 0x100a: 0x62e1, 0x100b: 0x62f9, | ||
1328 | 0x100c: 0x40cd, 0x100d: 0x40cd, 0x100e: 0x6311, 0x100f: 0x6329, 0x1010: 0x6341, 0x1011: 0x40ed, | ||
1329 | 0x1012: 0x410d, 0x1013: 0x412d, 0x1014: 0x414d, 0x1015: 0x416d, 0x1016: 0x6359, 0x1017: 0x6371, | ||
1330 | 0x1018: 0x6389, 0x1019: 0x63a1, 0x101a: 0x63b9, 0x101b: 0x418d, 0x101c: 0x63d1, 0x101d: 0x63e9, | ||
1331 | 0x101e: 0x6401, 0x101f: 0x41ad, 0x1020: 0x41cd, 0x1021: 0x6419, 0x1022: 0x41ed, 0x1023: 0x420d, | ||
1332 | 0x1024: 0x422d, 0x1025: 0x6431, 0x1026: 0x424d, 0x1027: 0x6449, 0x1028: 0x6479, 0x1029: 0x6211, | ||
1333 | 0x102a: 0x426d, 0x102b: 0x428d, 0x102c: 0x42ad, 0x102d: 0x42cd, 0x102e: 0x64b1, 0x102f: 0x64f1, | ||
1334 | 0x1030: 0x6539, 0x1031: 0x6551, 0x1032: 0x42ed, 0x1033: 0x6569, 0x1034: 0x6581, 0x1035: 0x6599, | ||
1335 | 0x1036: 0x430d, 0x1037: 0x65b1, 0x1038: 0x65c9, 0x1039: 0x65b1, 0x103a: 0x65e1, 0x103b: 0x65f9, | ||
1336 | 0x103c: 0x432d, 0x103d: 0x6611, 0x103e: 0x6629, 0x103f: 0x6611, | ||
1337 | // Block 0x41, offset 0x1040 | ||
1338 | 0x1040: 0x434d, 0x1041: 0x436d, 0x1042: 0x0040, 0x1043: 0x6641, 0x1044: 0x6659, 0x1045: 0x6671, | ||
1339 | 0x1046: 0x6689, 0x1047: 0x0040, 0x1048: 0x66c1, 0x1049: 0x66d9, 0x104a: 0x66f1, 0x104b: 0x6709, | ||
1340 | 0x104c: 0x6721, 0x104d: 0x6739, 0x104e: 0x6401, 0x104f: 0x6751, 0x1050: 0x6769, 0x1051: 0x6781, | ||
1341 | 0x1052: 0x438d, 0x1053: 0x6799, 0x1054: 0x6289, 0x1055: 0x43ad, 0x1056: 0x43cd, 0x1057: 0x67b1, | ||
1342 | 0x1058: 0x0040, 0x1059: 0x43ed, 0x105a: 0x67c9, 0x105b: 0x67e1, 0x105c: 0x67f9, 0x105d: 0x6811, | ||
1343 | 0x105e: 0x6829, 0x105f: 0x6859, 0x1060: 0x6889, 0x1061: 0x68b1, 0x1062: 0x68d9, 0x1063: 0x6901, | ||
1344 | 0x1064: 0x6929, 0x1065: 0x6951, 0x1066: 0x6979, 0x1067: 0x69a1, 0x1068: 0x69c9, 0x1069: 0x69f1, | ||
1345 | 0x106a: 0x6a21, 0x106b: 0x6a51, 0x106c: 0x6a81, 0x106d: 0x6ab1, 0x106e: 0x6ae1, 0x106f: 0x6b11, | ||
1346 | 0x1070: 0x6b41, 0x1071: 0x6b71, 0x1072: 0x6ba1, 0x1073: 0x6bd1, 0x1074: 0x6c01, 0x1075: 0x6c31, | ||
1347 | 0x1076: 0x6c61, 0x1077: 0x6c91, 0x1078: 0x6cc1, 0x1079: 0x6cf1, 0x107a: 0x6d21, 0x107b: 0x6d51, | ||
1348 | 0x107c: 0x6d81, 0x107d: 0x6db1, 0x107e: 0x6de1, 0x107f: 0x440d, | ||
1349 | // Block 0x42, offset 0x1080 | ||
1350 | 0x1080: 0xe00d, 0x1081: 0x0008, 0x1082: 0xe00d, 0x1083: 0x0008, 0x1084: 0xe00d, 0x1085: 0x0008, | ||
1351 | 0x1086: 0xe00d, 0x1087: 0x0008, 0x1088: 0xe00d, 0x1089: 0x0008, 0x108a: 0xe00d, 0x108b: 0x0008, | ||
1352 | 0x108c: 0xe00d, 0x108d: 0x0008, 0x108e: 0xe00d, 0x108f: 0x0008, 0x1090: 0xe00d, 0x1091: 0x0008, | ||
1353 | 0x1092: 0xe00d, 0x1093: 0x0008, 0x1094: 0xe00d, 0x1095: 0x0008, 0x1096: 0xe00d, 0x1097: 0x0008, | ||
1354 | 0x1098: 0xe00d, 0x1099: 0x0008, 0x109a: 0xe00d, 0x109b: 0x0008, 0x109c: 0xe00d, 0x109d: 0x0008, | ||
1355 | 0x109e: 0xe00d, 0x109f: 0x0008, 0x10a0: 0xe00d, 0x10a1: 0x0008, 0x10a2: 0xe00d, 0x10a3: 0x0008, | ||
1356 | 0x10a4: 0xe00d, 0x10a5: 0x0008, 0x10a6: 0xe00d, 0x10a7: 0x0008, 0x10a8: 0xe00d, 0x10a9: 0x0008, | ||
1357 | 0x10aa: 0xe00d, 0x10ab: 0x0008, 0x10ac: 0xe00d, 0x10ad: 0x0008, 0x10ae: 0x0008, 0x10af: 0x1308, | ||
1358 | 0x10b0: 0x1318, 0x10b1: 0x1318, 0x10b2: 0x1318, 0x10b3: 0x0018, 0x10b4: 0x1308, 0x10b5: 0x1308, | ||
1359 | 0x10b6: 0x1308, 0x10b7: 0x1308, 0x10b8: 0x1308, 0x10b9: 0x1308, 0x10ba: 0x1308, 0x10bb: 0x1308, | ||
1360 | 0x10bc: 0x1308, 0x10bd: 0x1308, 0x10be: 0x0018, 0x10bf: 0x0008, | ||
1361 | // Block 0x43, offset 0x10c0 | ||
1362 | 0x10c0: 0xe00d, 0x10c1: 0x0008, 0x10c2: 0xe00d, 0x10c3: 0x0008, 0x10c4: 0xe00d, 0x10c5: 0x0008, | ||
1363 | 0x10c6: 0xe00d, 0x10c7: 0x0008, 0x10c8: 0xe00d, 0x10c9: 0x0008, 0x10ca: 0xe00d, 0x10cb: 0x0008, | ||
1364 | 0x10cc: 0xe00d, 0x10cd: 0x0008, 0x10ce: 0xe00d, 0x10cf: 0x0008, 0x10d0: 0xe00d, 0x10d1: 0x0008, | ||
1365 | 0x10d2: 0xe00d, 0x10d3: 0x0008, 0x10d4: 0xe00d, 0x10d5: 0x0008, 0x10d6: 0xe00d, 0x10d7: 0x0008, | ||
1366 | 0x10d8: 0xe00d, 0x10d9: 0x0008, 0x10da: 0xe00d, 0x10db: 0x0008, 0x10dc: 0x0ea1, 0x10dd: 0x6e11, | ||
1367 | 0x10de: 0x1308, 0x10df: 0x1308, 0x10e0: 0x0008, 0x10e1: 0x0008, 0x10e2: 0x0008, 0x10e3: 0x0008, | ||
1368 | 0x10e4: 0x0008, 0x10e5: 0x0008, 0x10e6: 0x0008, 0x10e7: 0x0008, 0x10e8: 0x0008, 0x10e9: 0x0008, | ||
1369 | 0x10ea: 0x0008, 0x10eb: 0x0008, 0x10ec: 0x0008, 0x10ed: 0x0008, 0x10ee: 0x0008, 0x10ef: 0x0008, | ||
1370 | 0x10f0: 0x0008, 0x10f1: 0x0008, 0x10f2: 0x0008, 0x10f3: 0x0008, 0x10f4: 0x0008, 0x10f5: 0x0008, | ||
1371 | 0x10f6: 0x0008, 0x10f7: 0x0008, 0x10f8: 0x0008, 0x10f9: 0x0008, 0x10fa: 0x0008, 0x10fb: 0x0008, | ||
1372 | 0x10fc: 0x0008, 0x10fd: 0x0008, 0x10fe: 0x0008, 0x10ff: 0x0008, | ||
1373 | // Block 0x44, offset 0x1100 | ||
1374 | 0x1100: 0x0018, 0x1101: 0x0018, 0x1102: 0x0018, 0x1103: 0x0018, 0x1104: 0x0018, 0x1105: 0x0018, | ||
1375 | 0x1106: 0x0018, 0x1107: 0x0018, 0x1108: 0x0018, 0x1109: 0x0018, 0x110a: 0x0018, 0x110b: 0x0018, | ||
1376 | 0x110c: 0x0018, 0x110d: 0x0018, 0x110e: 0x0018, 0x110f: 0x0018, 0x1110: 0x0018, 0x1111: 0x0018, | ||
1377 | 0x1112: 0x0018, 0x1113: 0x0018, 0x1114: 0x0018, 0x1115: 0x0018, 0x1116: 0x0018, 0x1117: 0x0008, | ||
1378 | 0x1118: 0x0008, 0x1119: 0x0008, 0x111a: 0x0008, 0x111b: 0x0008, 0x111c: 0x0008, 0x111d: 0x0008, | ||
1379 | 0x111e: 0x0008, 0x111f: 0x0008, 0x1120: 0x0018, 0x1121: 0x0018, 0x1122: 0xe00d, 0x1123: 0x0008, | ||
1380 | 0x1124: 0xe00d, 0x1125: 0x0008, 0x1126: 0xe00d, 0x1127: 0x0008, 0x1128: 0xe00d, 0x1129: 0x0008, | ||
1381 | 0x112a: 0xe00d, 0x112b: 0x0008, 0x112c: 0xe00d, 0x112d: 0x0008, 0x112e: 0xe00d, 0x112f: 0x0008, | ||
1382 | 0x1130: 0x0008, 0x1131: 0x0008, 0x1132: 0xe00d, 0x1133: 0x0008, 0x1134: 0xe00d, 0x1135: 0x0008, | ||
1383 | 0x1136: 0xe00d, 0x1137: 0x0008, 0x1138: 0xe00d, 0x1139: 0x0008, 0x113a: 0xe00d, 0x113b: 0x0008, | ||
1384 | 0x113c: 0xe00d, 0x113d: 0x0008, 0x113e: 0xe00d, 0x113f: 0x0008, | ||
1385 | // Block 0x45, offset 0x1140 | ||
1386 | 0x1140: 0xe00d, 0x1141: 0x0008, 0x1142: 0xe00d, 0x1143: 0x0008, 0x1144: 0xe00d, 0x1145: 0x0008, | ||
1387 | 0x1146: 0xe00d, 0x1147: 0x0008, 0x1148: 0xe00d, 0x1149: 0x0008, 0x114a: 0xe00d, 0x114b: 0x0008, | ||
1388 | 0x114c: 0xe00d, 0x114d: 0x0008, 0x114e: 0xe00d, 0x114f: 0x0008, 0x1150: 0xe00d, 0x1151: 0x0008, | ||
1389 | 0x1152: 0xe00d, 0x1153: 0x0008, 0x1154: 0xe00d, 0x1155: 0x0008, 0x1156: 0xe00d, 0x1157: 0x0008, | ||
1390 | 0x1158: 0xe00d, 0x1159: 0x0008, 0x115a: 0xe00d, 0x115b: 0x0008, 0x115c: 0xe00d, 0x115d: 0x0008, | ||
1391 | 0x115e: 0xe00d, 0x115f: 0x0008, 0x1160: 0xe00d, 0x1161: 0x0008, 0x1162: 0xe00d, 0x1163: 0x0008, | ||
1392 | 0x1164: 0xe00d, 0x1165: 0x0008, 0x1166: 0xe00d, 0x1167: 0x0008, 0x1168: 0xe00d, 0x1169: 0x0008, | ||
1393 | 0x116a: 0xe00d, 0x116b: 0x0008, 0x116c: 0xe00d, 0x116d: 0x0008, 0x116e: 0xe00d, 0x116f: 0x0008, | ||
1394 | 0x1170: 0xe0fd, 0x1171: 0x0008, 0x1172: 0x0008, 0x1173: 0x0008, 0x1174: 0x0008, 0x1175: 0x0008, | ||
1395 | 0x1176: 0x0008, 0x1177: 0x0008, 0x1178: 0x0008, 0x1179: 0xe01d, 0x117a: 0x0008, 0x117b: 0xe03d, | ||
1396 | 0x117c: 0x0008, 0x117d: 0x442d, 0x117e: 0xe00d, 0x117f: 0x0008, | ||
1397 | // Block 0x46, offset 0x1180 | ||
1398 | 0x1180: 0xe00d, 0x1181: 0x0008, 0x1182: 0xe00d, 0x1183: 0x0008, 0x1184: 0xe00d, 0x1185: 0x0008, | ||
1399 | 0x1186: 0xe00d, 0x1187: 0x0008, 0x1188: 0x0008, 0x1189: 0x0018, 0x118a: 0x0018, 0x118b: 0xe03d, | ||
1400 | 0x118c: 0x0008, 0x118d: 0x11d9, 0x118e: 0x0008, 0x118f: 0x0008, 0x1190: 0xe00d, 0x1191: 0x0008, | ||
1401 | 0x1192: 0xe00d, 0x1193: 0x0008, 0x1194: 0x0008, 0x1195: 0x0008, 0x1196: 0xe00d, 0x1197: 0x0008, | ||
1402 | 0x1198: 0xe00d, 0x1199: 0x0008, 0x119a: 0xe00d, 0x119b: 0x0008, 0x119c: 0xe00d, 0x119d: 0x0008, | ||
1403 | 0x119e: 0xe00d, 0x119f: 0x0008, 0x11a0: 0xe00d, 0x11a1: 0x0008, 0x11a2: 0xe00d, 0x11a3: 0x0008, | ||
1404 | 0x11a4: 0xe00d, 0x11a5: 0x0008, 0x11a6: 0xe00d, 0x11a7: 0x0008, 0x11a8: 0xe00d, 0x11a9: 0x0008, | ||
1405 | 0x11aa: 0x6e29, 0x11ab: 0x1029, 0x11ac: 0x11c1, 0x11ad: 0x6e41, 0x11ae: 0x1221, 0x11af: 0x0040, | ||
1406 | 0x11b0: 0x6e59, 0x11b1: 0x6e71, 0x11b2: 0x1239, 0x11b3: 0x444d, 0x11b4: 0xe00d, 0x11b5: 0x0008, | ||
1407 | 0x11b6: 0xe00d, 0x11b7: 0x0008, 0x11b8: 0x0040, 0x11b9: 0x0040, 0x11ba: 0x0040, 0x11bb: 0x0040, | ||
1408 | 0x11bc: 0x0040, 0x11bd: 0x0040, 0x11be: 0x0040, 0x11bf: 0x0040, | ||
1409 | // Block 0x47, offset 0x11c0 | ||
1410 | 0x11c0: 0x64d5, 0x11c1: 0x64f5, 0x11c2: 0x6515, 0x11c3: 0x6535, 0x11c4: 0x6555, 0x11c5: 0x6575, | ||
1411 | 0x11c6: 0x6595, 0x11c7: 0x65b5, 0x11c8: 0x65d5, 0x11c9: 0x65f5, 0x11ca: 0x6615, 0x11cb: 0x6635, | ||
1412 | 0x11cc: 0x6655, 0x11cd: 0x6675, 0x11ce: 0x0008, 0x11cf: 0x0008, 0x11d0: 0x6695, 0x11d1: 0x0008, | ||
1413 | 0x11d2: 0x66b5, 0x11d3: 0x0008, 0x11d4: 0x0008, 0x11d5: 0x66d5, 0x11d6: 0x66f5, 0x11d7: 0x6715, | ||
1414 | 0x11d8: 0x6735, 0x11d9: 0x6755, 0x11da: 0x6775, 0x11db: 0x6795, 0x11dc: 0x67b5, 0x11dd: 0x67d5, | ||
1415 | 0x11de: 0x67f5, 0x11df: 0x0008, 0x11e0: 0x6815, 0x11e1: 0x0008, 0x11e2: 0x6835, 0x11e3: 0x0008, | ||
1416 | 0x11e4: 0x0008, 0x11e5: 0x6855, 0x11e6: 0x6875, 0x11e7: 0x0008, 0x11e8: 0x0008, 0x11e9: 0x0008, | ||
1417 | 0x11ea: 0x6895, 0x11eb: 0x68b5, 0x11ec: 0x68d5, 0x11ed: 0x68f5, 0x11ee: 0x6915, 0x11ef: 0x6935, | ||
1418 | 0x11f0: 0x6955, 0x11f1: 0x6975, 0x11f2: 0x6995, 0x11f3: 0x69b5, 0x11f4: 0x69d5, 0x11f5: 0x69f5, | ||
1419 | 0x11f6: 0x6a15, 0x11f7: 0x6a35, 0x11f8: 0x6a55, 0x11f9: 0x6a75, 0x11fa: 0x6a95, 0x11fb: 0x6ab5, | ||
1420 | 0x11fc: 0x6ad5, 0x11fd: 0x6af5, 0x11fe: 0x6b15, 0x11ff: 0x6b35, | ||
1421 | // Block 0x48, offset 0x1200 | ||
1422 | 0x1200: 0x7a95, 0x1201: 0x7ab5, 0x1202: 0x7ad5, 0x1203: 0x7af5, 0x1204: 0x7b15, 0x1205: 0x7b35, | ||
1423 | 0x1206: 0x7b55, 0x1207: 0x7b75, 0x1208: 0x7b95, 0x1209: 0x7bb5, 0x120a: 0x7bd5, 0x120b: 0x7bf5, | ||
1424 | 0x120c: 0x7c15, 0x120d: 0x7c35, 0x120e: 0x7c55, 0x120f: 0x6ec9, 0x1210: 0x6ef1, 0x1211: 0x6f19, | ||
1425 | 0x1212: 0x7c75, 0x1213: 0x7c95, 0x1214: 0x7cb5, 0x1215: 0x6f41, 0x1216: 0x6f69, 0x1217: 0x6f91, | ||
1426 | 0x1218: 0x7cd5, 0x1219: 0x7cf5, 0x121a: 0x0040, 0x121b: 0x0040, 0x121c: 0x0040, 0x121d: 0x0040, | ||
1427 | 0x121e: 0x0040, 0x121f: 0x0040, 0x1220: 0x0040, 0x1221: 0x0040, 0x1222: 0x0040, 0x1223: 0x0040, | ||
1428 | 0x1224: 0x0040, 0x1225: 0x0040, 0x1226: 0x0040, 0x1227: 0x0040, 0x1228: 0x0040, 0x1229: 0x0040, | ||
1429 | 0x122a: 0x0040, 0x122b: 0x0040, 0x122c: 0x0040, 0x122d: 0x0040, 0x122e: 0x0040, 0x122f: 0x0040, | ||
1430 | 0x1230: 0x0040, 0x1231: 0x0040, 0x1232: 0x0040, 0x1233: 0x0040, 0x1234: 0x0040, 0x1235: 0x0040, | ||
1431 | 0x1236: 0x0040, 0x1237: 0x0040, 0x1238: 0x0040, 0x1239: 0x0040, 0x123a: 0x0040, 0x123b: 0x0040, | ||
1432 | 0x123c: 0x0040, 0x123d: 0x0040, 0x123e: 0x0040, 0x123f: 0x0040, | ||
1433 | // Block 0x49, offset 0x1240 | ||
1434 | 0x1240: 0x6fb9, 0x1241: 0x6fd1, 0x1242: 0x6fe9, 0x1243: 0x7d15, 0x1244: 0x7d35, 0x1245: 0x7001, | ||
1435 | 0x1246: 0x7001, 0x1247: 0x0040, 0x1248: 0x0040, 0x1249: 0x0040, 0x124a: 0x0040, 0x124b: 0x0040, | ||
1436 | 0x124c: 0x0040, 0x124d: 0x0040, 0x124e: 0x0040, 0x124f: 0x0040, 0x1250: 0x0040, 0x1251: 0x0040, | ||
1437 | 0x1252: 0x0040, 0x1253: 0x7019, 0x1254: 0x7041, 0x1255: 0x7069, 0x1256: 0x7091, 0x1257: 0x70b9, | ||
1438 | 0x1258: 0x0040, 0x1259: 0x0040, 0x125a: 0x0040, 0x125b: 0x0040, 0x125c: 0x0040, 0x125d: 0x70e1, | ||
1439 | 0x125e: 0x1308, 0x125f: 0x7109, 0x1260: 0x7131, 0x1261: 0x20a9, 0x1262: 0x20f1, 0x1263: 0x7149, | ||
1440 | 0x1264: 0x7161, 0x1265: 0x7179, 0x1266: 0x7191, 0x1267: 0x71a9, 0x1268: 0x71c1, 0x1269: 0x1fb2, | ||
1441 | 0x126a: 0x71d9, 0x126b: 0x7201, 0x126c: 0x7229, 0x126d: 0x7261, 0x126e: 0x7299, 0x126f: 0x72c1, | ||
1442 | 0x1270: 0x72e9, 0x1271: 0x7311, 0x1272: 0x7339, 0x1273: 0x7361, 0x1274: 0x7389, 0x1275: 0x73b1, | ||
1443 | 0x1276: 0x73d9, 0x1277: 0x0040, 0x1278: 0x7401, 0x1279: 0x7429, 0x127a: 0x7451, 0x127b: 0x7479, | ||
1444 | 0x127c: 0x74a1, 0x127d: 0x0040, 0x127e: 0x74c9, 0x127f: 0x0040, | ||
1445 | // Block 0x4a, offset 0x1280 | ||
1446 | 0x1280: 0x74f1, 0x1281: 0x7519, 0x1282: 0x0040, 0x1283: 0x7541, 0x1284: 0x7569, 0x1285: 0x0040, | ||
1447 | 0x1286: 0x7591, 0x1287: 0x75b9, 0x1288: 0x75e1, 0x1289: 0x7609, 0x128a: 0x7631, 0x128b: 0x7659, | ||
1448 | 0x128c: 0x7681, 0x128d: 0x76a9, 0x128e: 0x76d1, 0x128f: 0x76f9, 0x1290: 0x7721, 0x1291: 0x7721, | ||
1449 | 0x1292: 0x7739, 0x1293: 0x7739, 0x1294: 0x7739, 0x1295: 0x7739, 0x1296: 0x7751, 0x1297: 0x7751, | ||
1450 | 0x1298: 0x7751, 0x1299: 0x7751, 0x129a: 0x7769, 0x129b: 0x7769, 0x129c: 0x7769, 0x129d: 0x7769, | ||
1451 | 0x129e: 0x7781, 0x129f: 0x7781, 0x12a0: 0x7781, 0x12a1: 0x7781, 0x12a2: 0x7799, 0x12a3: 0x7799, | ||
1452 | 0x12a4: 0x7799, 0x12a5: 0x7799, 0x12a6: 0x77b1, 0x12a7: 0x77b1, 0x12a8: 0x77b1, 0x12a9: 0x77b1, | ||
1453 | 0x12aa: 0x77c9, 0x12ab: 0x77c9, 0x12ac: 0x77c9, 0x12ad: 0x77c9, 0x12ae: 0x77e1, 0x12af: 0x77e1, | ||
1454 | 0x12b0: 0x77e1, 0x12b1: 0x77e1, 0x12b2: 0x77f9, 0x12b3: 0x77f9, 0x12b4: 0x77f9, 0x12b5: 0x77f9, | ||
1455 | 0x12b6: 0x7811, 0x12b7: 0x7811, 0x12b8: 0x7811, 0x12b9: 0x7811, 0x12ba: 0x7829, 0x12bb: 0x7829, | ||
1456 | 0x12bc: 0x7829, 0x12bd: 0x7829, 0x12be: 0x7841, 0x12bf: 0x7841, | ||
1457 | // Block 0x4b, offset 0x12c0 | ||
1458 | 0x12c0: 0x7841, 0x12c1: 0x7841, 0x12c2: 0x7859, 0x12c3: 0x7859, 0x12c4: 0x7871, 0x12c5: 0x7871, | ||
1459 | 0x12c6: 0x7889, 0x12c7: 0x7889, 0x12c8: 0x78a1, 0x12c9: 0x78a1, 0x12ca: 0x78b9, 0x12cb: 0x78b9, | ||
1460 | 0x12cc: 0x78d1, 0x12cd: 0x78d1, 0x12ce: 0x78e9, 0x12cf: 0x78e9, 0x12d0: 0x78e9, 0x12d1: 0x78e9, | ||
1461 | 0x12d2: 0x7901, 0x12d3: 0x7901, 0x12d4: 0x7901, 0x12d5: 0x7901, 0x12d6: 0x7919, 0x12d7: 0x7919, | ||
1462 | 0x12d8: 0x7919, 0x12d9: 0x7919, 0x12da: 0x7931, 0x12db: 0x7931, 0x12dc: 0x7931, 0x12dd: 0x7931, | ||
1463 | 0x12de: 0x7949, 0x12df: 0x7949, 0x12e0: 0x7961, 0x12e1: 0x7961, 0x12e2: 0x7961, 0x12e3: 0x7961, | ||
1464 | 0x12e4: 0x7979, 0x12e5: 0x7979, 0x12e6: 0x7991, 0x12e7: 0x7991, 0x12e8: 0x7991, 0x12e9: 0x7991, | ||
1465 | 0x12ea: 0x79a9, 0x12eb: 0x79a9, 0x12ec: 0x79a9, 0x12ed: 0x79a9, 0x12ee: 0x79c1, 0x12ef: 0x79c1, | ||
1466 | 0x12f0: 0x79d9, 0x12f1: 0x79d9, 0x12f2: 0x0018, 0x12f3: 0x0018, 0x12f4: 0x0018, 0x12f5: 0x0018, | ||
1467 | 0x12f6: 0x0018, 0x12f7: 0x0018, 0x12f8: 0x0018, 0x12f9: 0x0018, 0x12fa: 0x0018, 0x12fb: 0x0018, | ||
1468 | 0x12fc: 0x0018, 0x12fd: 0x0018, 0x12fe: 0x0018, 0x12ff: 0x0018, | ||
1469 | // Block 0x4c, offset 0x1300 | ||
1470 | 0x1300: 0x0018, 0x1301: 0x0018, 0x1302: 0x0040, 0x1303: 0x0040, 0x1304: 0x0040, 0x1305: 0x0040, | ||
1471 | 0x1306: 0x0040, 0x1307: 0x0040, 0x1308: 0x0040, 0x1309: 0x0040, 0x130a: 0x0040, 0x130b: 0x0040, | ||
1472 | 0x130c: 0x0040, 0x130d: 0x0040, 0x130e: 0x0040, 0x130f: 0x0040, 0x1310: 0x0040, 0x1311: 0x0040, | ||
1473 | 0x1312: 0x0040, 0x1313: 0x79f1, 0x1314: 0x79f1, 0x1315: 0x79f1, 0x1316: 0x79f1, 0x1317: 0x7a09, | ||
1474 | 0x1318: 0x7a09, 0x1319: 0x7a21, 0x131a: 0x7a21, 0x131b: 0x7a39, 0x131c: 0x7a39, 0x131d: 0x0479, | ||
1475 | 0x131e: 0x7a51, 0x131f: 0x7a51, 0x1320: 0x7a69, 0x1321: 0x7a69, 0x1322: 0x7a81, 0x1323: 0x7a81, | ||
1476 | 0x1324: 0x7a99, 0x1325: 0x7a99, 0x1326: 0x7a99, 0x1327: 0x7a99, 0x1328: 0x7ab1, 0x1329: 0x7ab1, | ||
1477 | 0x132a: 0x7ac9, 0x132b: 0x7ac9, 0x132c: 0x7af1, 0x132d: 0x7af1, 0x132e: 0x7b19, 0x132f: 0x7b19, | ||
1478 | 0x1330: 0x7b41, 0x1331: 0x7b41, 0x1332: 0x7b69, 0x1333: 0x7b69, 0x1334: 0x7b91, 0x1335: 0x7b91, | ||
1479 | 0x1336: 0x7bb9, 0x1337: 0x7bb9, 0x1338: 0x7bb9, 0x1339: 0x7be1, 0x133a: 0x7be1, 0x133b: 0x7be1, | ||
1480 | 0x133c: 0x7c09, 0x133d: 0x7c09, 0x133e: 0x7c09, 0x133f: 0x7c09, | ||
1481 | // Block 0x4d, offset 0x1340 | ||
1482 | 0x1340: 0x85f9, 0x1341: 0x8621, 0x1342: 0x8649, 0x1343: 0x8671, 0x1344: 0x8699, 0x1345: 0x86c1, | ||
1483 | 0x1346: 0x86e9, 0x1347: 0x8711, 0x1348: 0x8739, 0x1349: 0x8761, 0x134a: 0x8789, 0x134b: 0x87b1, | ||
1484 | 0x134c: 0x87d9, 0x134d: 0x8801, 0x134e: 0x8829, 0x134f: 0x8851, 0x1350: 0x8879, 0x1351: 0x88a1, | ||
1485 | 0x1352: 0x88c9, 0x1353: 0x88f1, 0x1354: 0x8919, 0x1355: 0x8941, 0x1356: 0x8969, 0x1357: 0x8991, | ||
1486 | 0x1358: 0x89b9, 0x1359: 0x89e1, 0x135a: 0x8a09, 0x135b: 0x8a31, 0x135c: 0x8a59, 0x135d: 0x8a81, | ||
1487 | 0x135e: 0x8aaa, 0x135f: 0x8ada, 0x1360: 0x8b0a, 0x1361: 0x8b3a, 0x1362: 0x8b6a, 0x1363: 0x8b9a, | ||
1488 | 0x1364: 0x8bc9, 0x1365: 0x8bf1, 0x1366: 0x7c71, 0x1367: 0x8c19, 0x1368: 0x7be1, 0x1369: 0x7c99, | ||
1489 | 0x136a: 0x8c41, 0x136b: 0x8c69, 0x136c: 0x7d39, 0x136d: 0x8c91, 0x136e: 0x7d61, 0x136f: 0x7d89, | ||
1490 | 0x1370: 0x8cb9, 0x1371: 0x8ce1, 0x1372: 0x7e29, 0x1373: 0x8d09, 0x1374: 0x7e51, 0x1375: 0x7e79, | ||
1491 | 0x1376: 0x8d31, 0x1377: 0x8d59, 0x1378: 0x7ec9, 0x1379: 0x8d81, 0x137a: 0x7ef1, 0x137b: 0x7f19, | ||
1492 | 0x137c: 0x83a1, 0x137d: 0x83c9, 0x137e: 0x8441, 0x137f: 0x8469, | ||
1493 | // Block 0x4e, offset 0x1380 | ||
1494 | 0x1380: 0x8491, 0x1381: 0x8531, 0x1382: 0x8559, 0x1383: 0x8581, 0x1384: 0x85a9, 0x1385: 0x8649, | ||
1495 | 0x1386: 0x8671, 0x1387: 0x8699, 0x1388: 0x8da9, 0x1389: 0x8739, 0x138a: 0x8dd1, 0x138b: 0x8df9, | ||
1496 | 0x138c: 0x8829, 0x138d: 0x8e21, 0x138e: 0x8851, 0x138f: 0x8879, 0x1390: 0x8a81, 0x1391: 0x8e49, | ||
1497 | 0x1392: 0x8e71, 0x1393: 0x89b9, 0x1394: 0x8e99, 0x1395: 0x89e1, 0x1396: 0x8a09, 0x1397: 0x7c21, | ||
1498 | 0x1398: 0x7c49, 0x1399: 0x8ec1, 0x139a: 0x7c71, 0x139b: 0x8ee9, 0x139c: 0x7cc1, 0x139d: 0x7ce9, | ||
1499 | 0x139e: 0x7d11, 0x139f: 0x7d39, 0x13a0: 0x8f11, 0x13a1: 0x7db1, 0x13a2: 0x7dd9, 0x13a3: 0x7e01, | ||
1500 | 0x13a4: 0x7e29, 0x13a5: 0x8f39, 0x13a6: 0x7ec9, 0x13a7: 0x7f41, 0x13a8: 0x7f69, 0x13a9: 0x7f91, | ||
1501 | 0x13aa: 0x7fb9, 0x13ab: 0x7fe1, 0x13ac: 0x8031, 0x13ad: 0x8059, 0x13ae: 0x8081, 0x13af: 0x80a9, | ||
1502 | 0x13b0: 0x80d1, 0x13b1: 0x80f9, 0x13b2: 0x8f61, 0x13b3: 0x8121, 0x13b4: 0x8149, 0x13b5: 0x8171, | ||
1503 | 0x13b6: 0x8199, 0x13b7: 0x81c1, 0x13b8: 0x81e9, 0x13b9: 0x8239, 0x13ba: 0x8261, 0x13bb: 0x8289, | ||
1504 | 0x13bc: 0x82b1, 0x13bd: 0x82d9, 0x13be: 0x8301, 0x13bf: 0x8329, | ||
1505 | // Block 0x4f, offset 0x13c0 | ||
1506 | 0x13c0: 0x8351, 0x13c1: 0x8379, 0x13c2: 0x83f1, 0x13c3: 0x8419, 0x13c4: 0x84b9, 0x13c5: 0x84e1, | ||
1507 | 0x13c6: 0x8509, 0x13c7: 0x8531, 0x13c8: 0x8559, 0x13c9: 0x85d1, 0x13ca: 0x85f9, 0x13cb: 0x8621, | ||
1508 | 0x13cc: 0x8649, 0x13cd: 0x8f89, 0x13ce: 0x86c1, 0x13cf: 0x86e9, 0x13d0: 0x8711, 0x13d1: 0x8739, | ||
1509 | 0x13d2: 0x87b1, 0x13d3: 0x87d9, 0x13d4: 0x8801, 0x13d5: 0x8829, 0x13d6: 0x8fb1, 0x13d7: 0x88a1, | ||
1510 | 0x13d8: 0x88c9, 0x13d9: 0x8fd9, 0x13da: 0x8941, 0x13db: 0x8969, 0x13dc: 0x8991, 0x13dd: 0x89b9, | ||
1511 | 0x13de: 0x9001, 0x13df: 0x7c71, 0x13e0: 0x8ee9, 0x13e1: 0x7d39, 0x13e2: 0x8f11, 0x13e3: 0x7e29, | ||
1512 | 0x13e4: 0x8f39, 0x13e5: 0x7ec9, 0x13e6: 0x9029, 0x13e7: 0x80d1, 0x13e8: 0x9051, 0x13e9: 0x9079, | ||
1513 | 0x13ea: 0x90a1, 0x13eb: 0x8531, 0x13ec: 0x8559, 0x13ed: 0x8649, 0x13ee: 0x8829, 0x13ef: 0x8fb1, | ||
1514 | 0x13f0: 0x89b9, 0x13f1: 0x9001, 0x13f2: 0x90c9, 0x13f3: 0x9101, 0x13f4: 0x9139, 0x13f5: 0x9171, | ||
1515 | 0x13f6: 0x9199, 0x13f7: 0x91c1, 0x13f8: 0x91e9, 0x13f9: 0x9211, 0x13fa: 0x9239, 0x13fb: 0x9261, | ||
1516 | 0x13fc: 0x9289, 0x13fd: 0x92b1, 0x13fe: 0x92d9, 0x13ff: 0x9301, | ||
1517 | // Block 0x50, offset 0x1400 | ||
1518 | 0x1400: 0x9329, 0x1401: 0x9351, 0x1402: 0x9379, 0x1403: 0x93a1, 0x1404: 0x93c9, 0x1405: 0x93f1, | ||
1519 | 0x1406: 0x9419, 0x1407: 0x9441, 0x1408: 0x9469, 0x1409: 0x9491, 0x140a: 0x94b9, 0x140b: 0x94e1, | ||
1520 | 0x140c: 0x9079, 0x140d: 0x9509, 0x140e: 0x9531, 0x140f: 0x9559, 0x1410: 0x9581, 0x1411: 0x9171, | ||
1521 | 0x1412: 0x9199, 0x1413: 0x91c1, 0x1414: 0x91e9, 0x1415: 0x9211, 0x1416: 0x9239, 0x1417: 0x9261, | ||
1522 | 0x1418: 0x9289, 0x1419: 0x92b1, 0x141a: 0x92d9, 0x141b: 0x9301, 0x141c: 0x9329, 0x141d: 0x9351, | ||
1523 | 0x141e: 0x9379, 0x141f: 0x93a1, 0x1420: 0x93c9, 0x1421: 0x93f1, 0x1422: 0x9419, 0x1423: 0x9441, | ||
1524 | 0x1424: 0x9469, 0x1425: 0x9491, 0x1426: 0x94b9, 0x1427: 0x94e1, 0x1428: 0x9079, 0x1429: 0x9509, | ||
1525 | 0x142a: 0x9531, 0x142b: 0x9559, 0x142c: 0x9581, 0x142d: 0x9491, 0x142e: 0x94b9, 0x142f: 0x94e1, | ||
1526 | 0x1430: 0x9079, 0x1431: 0x9051, 0x1432: 0x90a1, 0x1433: 0x8211, 0x1434: 0x8059, 0x1435: 0x8081, | ||
1527 | 0x1436: 0x80a9, 0x1437: 0x9491, 0x1438: 0x94b9, 0x1439: 0x94e1, 0x143a: 0x8211, 0x143b: 0x8239, | ||
1528 | 0x143c: 0x95a9, 0x143d: 0x95a9, 0x143e: 0x0018, 0x143f: 0x0018, | ||
1529 | // Block 0x51, offset 0x1440 | ||
1530 | 0x1440: 0x0040, 0x1441: 0x0040, 0x1442: 0x0040, 0x1443: 0x0040, 0x1444: 0x0040, 0x1445: 0x0040, | ||
1531 | 0x1446: 0x0040, 0x1447: 0x0040, 0x1448: 0x0040, 0x1449: 0x0040, 0x144a: 0x0040, 0x144b: 0x0040, | ||
1532 | 0x144c: 0x0040, 0x144d: 0x0040, 0x144e: 0x0040, 0x144f: 0x0040, 0x1450: 0x95d1, 0x1451: 0x9609, | ||
1533 | 0x1452: 0x9609, 0x1453: 0x9641, 0x1454: 0x9679, 0x1455: 0x96b1, 0x1456: 0x96e9, 0x1457: 0x9721, | ||
1534 | 0x1458: 0x9759, 0x1459: 0x9759, 0x145a: 0x9791, 0x145b: 0x97c9, 0x145c: 0x9801, 0x145d: 0x9839, | ||
1535 | 0x145e: 0x9871, 0x145f: 0x98a9, 0x1460: 0x98a9, 0x1461: 0x98e1, 0x1462: 0x9919, 0x1463: 0x9919, | ||
1536 | 0x1464: 0x9951, 0x1465: 0x9951, 0x1466: 0x9989, 0x1467: 0x99c1, 0x1468: 0x99c1, 0x1469: 0x99f9, | ||
1537 | 0x146a: 0x9a31, 0x146b: 0x9a31, 0x146c: 0x9a69, 0x146d: 0x9a69, 0x146e: 0x9aa1, 0x146f: 0x9ad9, | ||
1538 | 0x1470: 0x9ad9, 0x1471: 0x9b11, 0x1472: 0x9b11, 0x1473: 0x9b49, 0x1474: 0x9b81, 0x1475: 0x9bb9, | ||
1539 | 0x1476: 0x9bf1, 0x1477: 0x9bf1, 0x1478: 0x9c29, 0x1479: 0x9c61, 0x147a: 0x9c99, 0x147b: 0x9cd1, | ||
1540 | 0x147c: 0x9d09, 0x147d: 0x9d09, 0x147e: 0x9d41, 0x147f: 0x9d79, | ||
1541 | // Block 0x52, offset 0x1480 | ||
1542 | 0x1480: 0xa949, 0x1481: 0xa981, 0x1482: 0xa9b9, 0x1483: 0xa8a1, 0x1484: 0x9bb9, 0x1485: 0x9989, | ||
1543 | 0x1486: 0xa9f1, 0x1487: 0xaa29, 0x1488: 0x0040, 0x1489: 0x0040, 0x148a: 0x0040, 0x148b: 0x0040, | ||
1544 | 0x148c: 0x0040, 0x148d: 0x0040, 0x148e: 0x0040, 0x148f: 0x0040, 0x1490: 0x0040, 0x1491: 0x0040, | ||
1545 | 0x1492: 0x0040, 0x1493: 0x0040, 0x1494: 0x0040, 0x1495: 0x0040, 0x1496: 0x0040, 0x1497: 0x0040, | ||
1546 | 0x1498: 0x0040, 0x1499: 0x0040, 0x149a: 0x0040, 0x149b: 0x0040, 0x149c: 0x0040, 0x149d: 0x0040, | ||
1547 | 0x149e: 0x0040, 0x149f: 0x0040, 0x14a0: 0x0040, 0x14a1: 0x0040, 0x14a2: 0x0040, 0x14a3: 0x0040, | ||
1548 | 0x14a4: 0x0040, 0x14a5: 0x0040, 0x14a6: 0x0040, 0x14a7: 0x0040, 0x14a8: 0x0040, 0x14a9: 0x0040, | ||
1549 | 0x14aa: 0x0040, 0x14ab: 0x0040, 0x14ac: 0x0040, 0x14ad: 0x0040, 0x14ae: 0x0040, 0x14af: 0x0040, | ||
1550 | 0x14b0: 0xaa61, 0x14b1: 0xaa99, 0x14b2: 0xaad1, 0x14b3: 0xab19, 0x14b4: 0xab61, 0x14b5: 0xaba9, | ||
1551 | 0x14b6: 0xabf1, 0x14b7: 0xac39, 0x14b8: 0xac81, 0x14b9: 0xacc9, 0x14ba: 0xad02, 0x14bb: 0xae12, | ||
1552 | 0x14bc: 0xae91, 0x14bd: 0x0018, 0x14be: 0x0040, 0x14bf: 0x0040, | ||
1553 | // Block 0x53, offset 0x14c0 | ||
1554 | 0x14c0: 0x13c0, 0x14c1: 0x13c0, 0x14c2: 0x13c0, 0x14c3: 0x13c0, 0x14c4: 0x13c0, 0x14c5: 0x13c0, | ||
1555 | 0x14c6: 0x13c0, 0x14c7: 0x13c0, 0x14c8: 0x13c0, 0x14c9: 0x13c0, 0x14ca: 0x13c0, 0x14cb: 0x13c0, | ||
1556 | 0x14cc: 0x13c0, 0x14cd: 0x13c0, 0x14ce: 0x13c0, 0x14cf: 0x13c0, 0x14d0: 0xaeda, 0x14d1: 0x7d55, | ||
1557 | 0x14d2: 0x0040, 0x14d3: 0xaeea, 0x14d4: 0x03c2, 0x14d5: 0xaefa, 0x14d6: 0xaf0a, 0x14d7: 0x7d75, | ||
1558 | 0x14d8: 0x7d95, 0x14d9: 0x0040, 0x14da: 0x0040, 0x14db: 0x0040, 0x14dc: 0x0040, 0x14dd: 0x0040, | ||
1559 | 0x14de: 0x0040, 0x14df: 0x0040, 0x14e0: 0x1308, 0x14e1: 0x1308, 0x14e2: 0x1308, 0x14e3: 0x1308, | ||
1560 | 0x14e4: 0x1308, 0x14e5: 0x1308, 0x14e6: 0x1308, 0x14e7: 0x1308, 0x14e8: 0x1308, 0x14e9: 0x1308, | ||
1561 | 0x14ea: 0x1308, 0x14eb: 0x1308, 0x14ec: 0x1308, 0x14ed: 0x1308, 0x14ee: 0x1308, 0x14ef: 0x1308, | ||
1562 | 0x14f0: 0x0040, 0x14f1: 0x7db5, 0x14f2: 0x7dd5, 0x14f3: 0xaf1a, 0x14f4: 0xaf1a, 0x14f5: 0x1fd2, | ||
1563 | 0x14f6: 0x1fe2, 0x14f7: 0xaf2a, 0x14f8: 0xaf3a, 0x14f9: 0x7df5, 0x14fa: 0x7e15, 0x14fb: 0x7e35, | ||
1564 | 0x14fc: 0x7df5, 0x14fd: 0x7e55, 0x14fe: 0x7e75, 0x14ff: 0x7e55, | ||
1565 | // Block 0x54, offset 0x1500 | ||
1566 | 0x1500: 0x7e95, 0x1501: 0x7eb5, 0x1502: 0x7ed5, 0x1503: 0x7eb5, 0x1504: 0x7ef5, 0x1505: 0x0018, | ||
1567 | 0x1506: 0x0018, 0x1507: 0xaf4a, 0x1508: 0xaf5a, 0x1509: 0x7f16, 0x150a: 0x7f36, 0x150b: 0x7f56, | ||
1568 | 0x150c: 0x7f76, 0x150d: 0xaf1a, 0x150e: 0xaf1a, 0x150f: 0xaf1a, 0x1510: 0xaeda, 0x1511: 0x7f95, | ||
1569 | 0x1512: 0x0040, 0x1513: 0x0040, 0x1514: 0x03c2, 0x1515: 0xaeea, 0x1516: 0xaf0a, 0x1517: 0xaefa, | ||
1570 | 0x1518: 0x7fb5, 0x1519: 0x1fd2, 0x151a: 0x1fe2, 0x151b: 0xaf2a, 0x151c: 0xaf3a, 0x151d: 0x7e95, | ||
1571 | 0x151e: 0x7ef5, 0x151f: 0xaf6a, 0x1520: 0xaf7a, 0x1521: 0xaf8a, 0x1522: 0x1fb2, 0x1523: 0xaf99, | ||
1572 | 0x1524: 0xafaa, 0x1525: 0xafba, 0x1526: 0x1fc2, 0x1527: 0x0040, 0x1528: 0xafca, 0x1529: 0xafda, | ||
1573 | 0x152a: 0xafea, 0x152b: 0xaffa, 0x152c: 0x0040, 0x152d: 0x0040, 0x152e: 0x0040, 0x152f: 0x0040, | ||
1574 | 0x1530: 0x7fd6, 0x1531: 0xb009, 0x1532: 0x7ff6, 0x1533: 0x0008, 0x1534: 0x8016, 0x1535: 0x0040, | ||
1575 | 0x1536: 0x8036, 0x1537: 0xb031, 0x1538: 0x8056, 0x1539: 0xb059, 0x153a: 0x8076, 0x153b: 0xb081, | ||
1576 | 0x153c: 0x8096, 0x153d: 0xb0a9, 0x153e: 0x80b6, 0x153f: 0xb0d1, | ||
1577 | // Block 0x55, offset 0x1540 | ||
1578 | 0x1540: 0xb0f9, 0x1541: 0xb111, 0x1542: 0xb111, 0x1543: 0xb129, 0x1544: 0xb129, 0x1545: 0xb141, | ||
1579 | 0x1546: 0xb141, 0x1547: 0xb159, 0x1548: 0xb159, 0x1549: 0xb171, 0x154a: 0xb171, 0x154b: 0xb171, | ||
1580 | 0x154c: 0xb171, 0x154d: 0xb189, 0x154e: 0xb189, 0x154f: 0xb1a1, 0x1550: 0xb1a1, 0x1551: 0xb1a1, | ||
1581 | 0x1552: 0xb1a1, 0x1553: 0xb1b9, 0x1554: 0xb1b9, 0x1555: 0xb1d1, 0x1556: 0xb1d1, 0x1557: 0xb1d1, | ||
1582 | 0x1558: 0xb1d1, 0x1559: 0xb1e9, 0x155a: 0xb1e9, 0x155b: 0xb1e9, 0x155c: 0xb1e9, 0x155d: 0xb201, | ||
1583 | 0x155e: 0xb201, 0x155f: 0xb201, 0x1560: 0xb201, 0x1561: 0xb219, 0x1562: 0xb219, 0x1563: 0xb219, | ||
1584 | 0x1564: 0xb219, 0x1565: 0xb231, 0x1566: 0xb231, 0x1567: 0xb231, 0x1568: 0xb231, 0x1569: 0xb249, | ||
1585 | 0x156a: 0xb249, 0x156b: 0xb261, 0x156c: 0xb261, 0x156d: 0xb279, 0x156e: 0xb279, 0x156f: 0xb291, | ||
1586 | 0x1570: 0xb291, 0x1571: 0xb2a9, 0x1572: 0xb2a9, 0x1573: 0xb2a9, 0x1574: 0xb2a9, 0x1575: 0xb2c1, | ||
1587 | 0x1576: 0xb2c1, 0x1577: 0xb2c1, 0x1578: 0xb2c1, 0x1579: 0xb2d9, 0x157a: 0xb2d9, 0x157b: 0xb2d9, | ||
1588 | 0x157c: 0xb2d9, 0x157d: 0xb2f1, 0x157e: 0xb2f1, 0x157f: 0xb2f1, | ||
1589 | // Block 0x56, offset 0x1580 | ||
1590 | 0x1580: 0xb2f1, 0x1581: 0xb309, 0x1582: 0xb309, 0x1583: 0xb309, 0x1584: 0xb309, 0x1585: 0xb321, | ||
1591 | 0x1586: 0xb321, 0x1587: 0xb321, 0x1588: 0xb321, 0x1589: 0xb339, 0x158a: 0xb339, 0x158b: 0xb339, | ||
1592 | 0x158c: 0xb339, 0x158d: 0xb351, 0x158e: 0xb351, 0x158f: 0xb351, 0x1590: 0xb351, 0x1591: 0xb369, | ||
1593 | 0x1592: 0xb369, 0x1593: 0xb369, 0x1594: 0xb369, 0x1595: 0xb381, 0x1596: 0xb381, 0x1597: 0xb381, | ||
1594 | 0x1598: 0xb381, 0x1599: 0xb399, 0x159a: 0xb399, 0x159b: 0xb399, 0x159c: 0xb399, 0x159d: 0xb3b1, | ||
1595 | 0x159e: 0xb3b1, 0x159f: 0xb3b1, 0x15a0: 0xb3b1, 0x15a1: 0xb3c9, 0x15a2: 0xb3c9, 0x15a3: 0xb3c9, | ||
1596 | 0x15a4: 0xb3c9, 0x15a5: 0xb3e1, 0x15a6: 0xb3e1, 0x15a7: 0xb3e1, 0x15a8: 0xb3e1, 0x15a9: 0xb3f9, | ||
1597 | 0x15aa: 0xb3f9, 0x15ab: 0xb3f9, 0x15ac: 0xb3f9, 0x15ad: 0xb411, 0x15ae: 0xb411, 0x15af: 0x7ab1, | ||
1598 | 0x15b0: 0x7ab1, 0x15b1: 0xb429, 0x15b2: 0xb429, 0x15b3: 0xb429, 0x15b4: 0xb429, 0x15b5: 0xb441, | ||
1599 | 0x15b6: 0xb441, 0x15b7: 0xb469, 0x15b8: 0xb469, 0x15b9: 0xb491, 0x15ba: 0xb491, 0x15bb: 0xb4b9, | ||
1600 | 0x15bc: 0xb4b9, 0x15bd: 0x0040, 0x15be: 0x0040, 0x15bf: 0x03c0, | ||
1601 | // Block 0x57, offset 0x15c0 | ||
1602 | 0x15c0: 0x0040, 0x15c1: 0xaefa, 0x15c2: 0xb4e2, 0x15c3: 0xaf6a, 0x15c4: 0xafda, 0x15c5: 0xafea, | ||
1603 | 0x15c6: 0xaf7a, 0x15c7: 0xb4f2, 0x15c8: 0x1fd2, 0x15c9: 0x1fe2, 0x15ca: 0xaf8a, 0x15cb: 0x1fb2, | ||
1604 | 0x15cc: 0xaeda, 0x15cd: 0xaf99, 0x15ce: 0x29d1, 0x15cf: 0xb502, 0x15d0: 0x1f41, 0x15d1: 0x00c9, | ||
1605 | 0x15d2: 0x0069, 0x15d3: 0x0079, 0x15d4: 0x1f51, 0x15d5: 0x1f61, 0x15d6: 0x1f71, 0x15d7: 0x1f81, | ||
1606 | 0x15d8: 0x1f91, 0x15d9: 0x1fa1, 0x15da: 0xaeea, 0x15db: 0x03c2, 0x15dc: 0xafaa, 0x15dd: 0x1fc2, | ||
1607 | 0x15de: 0xafba, 0x15df: 0xaf0a, 0x15e0: 0xaffa, 0x15e1: 0x0039, 0x15e2: 0x0ee9, 0x15e3: 0x1159, | ||
1608 | 0x15e4: 0x0ef9, 0x15e5: 0x0f09, 0x15e6: 0x1199, 0x15e7: 0x0f31, 0x15e8: 0x0249, 0x15e9: 0x0f41, | ||
1609 | 0x15ea: 0x0259, 0x15eb: 0x0f51, 0x15ec: 0x0359, 0x15ed: 0x0f61, 0x15ee: 0x0f71, 0x15ef: 0x00d9, | ||
1610 | 0x15f0: 0x0f99, 0x15f1: 0x2039, 0x15f2: 0x0269, 0x15f3: 0x01d9, 0x15f4: 0x0fa9, 0x15f5: 0x0fb9, | ||
1611 | 0x15f6: 0x1089, 0x15f7: 0x0279, 0x15f8: 0x0369, 0x15f9: 0x0289, 0x15fa: 0x13d1, 0x15fb: 0xaf4a, | ||
1612 | 0x15fc: 0xafca, 0x15fd: 0xaf5a, 0x15fe: 0xb512, 0x15ff: 0xaf1a, | ||
1613 | // Block 0x58, offset 0x1600 | ||
1614 | 0x1600: 0x1caa, 0x1601: 0x0039, 0x1602: 0x0ee9, 0x1603: 0x1159, 0x1604: 0x0ef9, 0x1605: 0x0f09, | ||
1615 | 0x1606: 0x1199, 0x1607: 0x0f31, 0x1608: 0x0249, 0x1609: 0x0f41, 0x160a: 0x0259, 0x160b: 0x0f51, | ||
1616 | 0x160c: 0x0359, 0x160d: 0x0f61, 0x160e: 0x0f71, 0x160f: 0x00d9, 0x1610: 0x0f99, 0x1611: 0x2039, | ||
1617 | 0x1612: 0x0269, 0x1613: 0x01d9, 0x1614: 0x0fa9, 0x1615: 0x0fb9, 0x1616: 0x1089, 0x1617: 0x0279, | ||
1618 | 0x1618: 0x0369, 0x1619: 0x0289, 0x161a: 0x13d1, 0x161b: 0xaf2a, 0x161c: 0xb522, 0x161d: 0xaf3a, | ||
1619 | 0x161e: 0xb532, 0x161f: 0x80d5, 0x1620: 0x80f5, 0x1621: 0x29d1, 0x1622: 0x8115, 0x1623: 0x8115, | ||
1620 | 0x1624: 0x8135, 0x1625: 0x8155, 0x1626: 0x8175, 0x1627: 0x8195, 0x1628: 0x81b5, 0x1629: 0x81d5, | ||
1621 | 0x162a: 0x81f5, 0x162b: 0x8215, 0x162c: 0x8235, 0x162d: 0x8255, 0x162e: 0x8275, 0x162f: 0x8295, | ||
1622 | 0x1630: 0x82b5, 0x1631: 0x82d5, 0x1632: 0x82f5, 0x1633: 0x8315, 0x1634: 0x8335, 0x1635: 0x8355, | ||
1623 | 0x1636: 0x8375, 0x1637: 0x8395, 0x1638: 0x83b5, 0x1639: 0x83d5, 0x163a: 0x83f5, 0x163b: 0x8415, | ||
1624 | 0x163c: 0x81b5, 0x163d: 0x8435, 0x163e: 0x8455, 0x163f: 0x8215, | ||
1625 | // Block 0x59, offset 0x1640 | ||
1626 | 0x1640: 0x8475, 0x1641: 0x8495, 0x1642: 0x84b5, 0x1643: 0x84d5, 0x1644: 0x84f5, 0x1645: 0x8515, | ||
1627 | 0x1646: 0x8535, 0x1647: 0x8555, 0x1648: 0x84d5, 0x1649: 0x8575, 0x164a: 0x84d5, 0x164b: 0x8595, | ||
1628 | 0x164c: 0x8595, 0x164d: 0x85b5, 0x164e: 0x85b5, 0x164f: 0x85d5, 0x1650: 0x8515, 0x1651: 0x85f5, | ||
1629 | 0x1652: 0x8615, 0x1653: 0x85f5, 0x1654: 0x8635, 0x1655: 0x8615, 0x1656: 0x8655, 0x1657: 0x8655, | ||
1630 | 0x1658: 0x8675, 0x1659: 0x8675, 0x165a: 0x8695, 0x165b: 0x8695, 0x165c: 0x8615, 0x165d: 0x8115, | ||
1631 | 0x165e: 0x86b5, 0x165f: 0x86d5, 0x1660: 0x0040, 0x1661: 0x86f5, 0x1662: 0x8715, 0x1663: 0x8735, | ||
1632 | 0x1664: 0x8755, 0x1665: 0x8735, 0x1666: 0x8775, 0x1667: 0x8795, 0x1668: 0x87b5, 0x1669: 0x87b5, | ||
1633 | 0x166a: 0x87d5, 0x166b: 0x87d5, 0x166c: 0x87f5, 0x166d: 0x87f5, 0x166e: 0x87d5, 0x166f: 0x87d5, | ||
1634 | 0x1670: 0x8815, 0x1671: 0x8835, 0x1672: 0x8855, 0x1673: 0x8875, 0x1674: 0x8895, 0x1675: 0x88b5, | ||
1635 | 0x1676: 0x88b5, 0x1677: 0x88b5, 0x1678: 0x88d5, 0x1679: 0x88d5, 0x167a: 0x88d5, 0x167b: 0x88d5, | ||
1636 | 0x167c: 0x87b5, 0x167d: 0x87b5, 0x167e: 0x87b5, 0x167f: 0x0040, | ||
1637 | // Block 0x5a, offset 0x1680 | ||
1638 | 0x1680: 0x0040, 0x1681: 0x0040, 0x1682: 0x8715, 0x1683: 0x86f5, 0x1684: 0x88f5, 0x1685: 0x86f5, | ||
1639 | 0x1686: 0x8715, 0x1687: 0x86f5, 0x1688: 0x0040, 0x1689: 0x0040, 0x168a: 0x8915, 0x168b: 0x8715, | ||
1640 | 0x168c: 0x8935, 0x168d: 0x88f5, 0x168e: 0x8935, 0x168f: 0x8715, 0x1690: 0x0040, 0x1691: 0x0040, | ||
1641 | 0x1692: 0x8955, 0x1693: 0x8975, 0x1694: 0x8875, 0x1695: 0x8935, 0x1696: 0x88f5, 0x1697: 0x8935, | ||
1642 | 0x1698: 0x0040, 0x1699: 0x0040, 0x169a: 0x8995, 0x169b: 0x89b5, 0x169c: 0x8995, 0x169d: 0x0040, | ||
1643 | 0x169e: 0x0040, 0x169f: 0x0040, 0x16a0: 0xb541, 0x16a1: 0xb559, 0x16a2: 0xb571, 0x16a3: 0x89d6, | ||
1644 | 0x16a4: 0xb589, 0x16a5: 0xb5a1, 0x16a6: 0x89f5, 0x16a7: 0x0040, 0x16a8: 0x8a15, 0x16a9: 0x8a35, | ||
1645 | 0x16aa: 0x8a55, 0x16ab: 0x8a35, 0x16ac: 0x8a75, 0x16ad: 0x8a95, 0x16ae: 0x8ab5, 0x16af: 0x0040, | ||
1646 | 0x16b0: 0x0040, 0x16b1: 0x0040, 0x16b2: 0x0040, 0x16b3: 0x0040, 0x16b4: 0x0040, 0x16b5: 0x0040, | ||
1647 | 0x16b6: 0x0040, 0x16b7: 0x0040, 0x16b8: 0x0040, 0x16b9: 0x0340, 0x16ba: 0x0340, 0x16bb: 0x0340, | ||
1648 | 0x16bc: 0x0040, 0x16bd: 0x0040, 0x16be: 0x0040, 0x16bf: 0x0040, | ||
1649 | // Block 0x5b, offset 0x16c0 | ||
1650 | 0x16c0: 0x0208, 0x16c1: 0x0208, 0x16c2: 0x0208, 0x16c3: 0x0208, 0x16c4: 0x0208, 0x16c5: 0x0408, | ||
1651 | 0x16c6: 0x0008, 0x16c7: 0x0408, 0x16c8: 0x0018, 0x16c9: 0x0408, 0x16ca: 0x0408, 0x16cb: 0x0008, | ||
1652 | 0x16cc: 0x0008, 0x16cd: 0x0108, 0x16ce: 0x0408, 0x16cf: 0x0408, 0x16d0: 0x0408, 0x16d1: 0x0408, | ||
1653 | 0x16d2: 0x0408, 0x16d3: 0x0208, 0x16d4: 0x0208, 0x16d5: 0x0208, 0x16d6: 0x0208, 0x16d7: 0x0108, | ||
1654 | 0x16d8: 0x0208, 0x16d9: 0x0208, 0x16da: 0x0208, 0x16db: 0x0208, 0x16dc: 0x0208, 0x16dd: 0x0408, | ||
1655 | 0x16de: 0x0208, 0x16df: 0x0208, 0x16e0: 0x0208, 0x16e1: 0x0408, 0x16e2: 0x0008, 0x16e3: 0x0008, | ||
1656 | 0x16e4: 0x0408, 0x16e5: 0x1308, 0x16e6: 0x1308, 0x16e7: 0x0040, 0x16e8: 0x0040, 0x16e9: 0x0040, | ||
1657 | 0x16ea: 0x0040, 0x16eb: 0x0218, 0x16ec: 0x0218, 0x16ed: 0x0218, 0x16ee: 0x0218, 0x16ef: 0x0418, | ||
1658 | 0x16f0: 0x0018, 0x16f1: 0x0018, 0x16f2: 0x0018, 0x16f3: 0x0018, 0x16f4: 0x0018, 0x16f5: 0x0018, | ||
1659 | 0x16f6: 0x0018, 0x16f7: 0x0040, 0x16f8: 0x0040, 0x16f9: 0x0040, 0x16fa: 0x0040, 0x16fb: 0x0040, | ||
1660 | 0x16fc: 0x0040, 0x16fd: 0x0040, 0x16fe: 0x0040, 0x16ff: 0x0040, | ||
1661 | // Block 0x5c, offset 0x1700 | ||
1662 | 0x1700: 0x0208, 0x1701: 0x0408, 0x1702: 0x0208, 0x1703: 0x0408, 0x1704: 0x0408, 0x1705: 0x0408, | ||
1663 | 0x1706: 0x0208, 0x1707: 0x0208, 0x1708: 0x0208, 0x1709: 0x0408, 0x170a: 0x0208, 0x170b: 0x0208, | ||
1664 | 0x170c: 0x0408, 0x170d: 0x0208, 0x170e: 0x0408, 0x170f: 0x0408, 0x1710: 0x0208, 0x1711: 0x0408, | ||
1665 | 0x1712: 0x0040, 0x1713: 0x0040, 0x1714: 0x0040, 0x1715: 0x0040, 0x1716: 0x0040, 0x1717: 0x0040, | ||
1666 | 0x1718: 0x0040, 0x1719: 0x0018, 0x171a: 0x0018, 0x171b: 0x0018, 0x171c: 0x0018, 0x171d: 0x0040, | ||
1667 | 0x171e: 0x0040, 0x171f: 0x0040, 0x1720: 0x0040, 0x1721: 0x0040, 0x1722: 0x0040, 0x1723: 0x0040, | ||
1668 | 0x1724: 0x0040, 0x1725: 0x0040, 0x1726: 0x0040, 0x1727: 0x0040, 0x1728: 0x0040, 0x1729: 0x0418, | ||
1669 | 0x172a: 0x0418, 0x172b: 0x0418, 0x172c: 0x0418, 0x172d: 0x0218, 0x172e: 0x0218, 0x172f: 0x0018, | ||
1670 | 0x1730: 0x0040, 0x1731: 0x0040, 0x1732: 0x0040, 0x1733: 0x0040, 0x1734: 0x0040, 0x1735: 0x0040, | ||
1671 | 0x1736: 0x0040, 0x1737: 0x0040, 0x1738: 0x0040, 0x1739: 0x0040, 0x173a: 0x0040, 0x173b: 0x0040, | ||
1672 | 0x173c: 0x0040, 0x173d: 0x0040, 0x173e: 0x0040, 0x173f: 0x0040, | ||
1673 | // Block 0x5d, offset 0x1740 | ||
1674 | 0x1740: 0x1308, 0x1741: 0x1308, 0x1742: 0x1008, 0x1743: 0x1008, 0x1744: 0x0040, 0x1745: 0x0008, | ||
1675 | 0x1746: 0x0008, 0x1747: 0x0008, 0x1748: 0x0008, 0x1749: 0x0008, 0x174a: 0x0008, 0x174b: 0x0008, | ||
1676 | 0x174c: 0x0008, 0x174d: 0x0040, 0x174e: 0x0040, 0x174f: 0x0008, 0x1750: 0x0008, 0x1751: 0x0040, | ||
1677 | 0x1752: 0x0040, 0x1753: 0x0008, 0x1754: 0x0008, 0x1755: 0x0008, 0x1756: 0x0008, 0x1757: 0x0008, | ||
1678 | 0x1758: 0x0008, 0x1759: 0x0008, 0x175a: 0x0008, 0x175b: 0x0008, 0x175c: 0x0008, 0x175d: 0x0008, | ||
1679 | 0x175e: 0x0008, 0x175f: 0x0008, 0x1760: 0x0008, 0x1761: 0x0008, 0x1762: 0x0008, 0x1763: 0x0008, | ||
1680 | 0x1764: 0x0008, 0x1765: 0x0008, 0x1766: 0x0008, 0x1767: 0x0008, 0x1768: 0x0008, 0x1769: 0x0040, | ||
1681 | 0x176a: 0x0008, 0x176b: 0x0008, 0x176c: 0x0008, 0x176d: 0x0008, 0x176e: 0x0008, 0x176f: 0x0008, | ||
1682 | 0x1770: 0x0008, 0x1771: 0x0040, 0x1772: 0x0008, 0x1773: 0x0008, 0x1774: 0x0040, 0x1775: 0x0008, | ||
1683 | 0x1776: 0x0008, 0x1777: 0x0008, 0x1778: 0x0008, 0x1779: 0x0008, 0x177a: 0x0040, 0x177b: 0x0040, | ||
1684 | 0x177c: 0x1308, 0x177d: 0x0008, 0x177e: 0x1008, 0x177f: 0x1008, | ||
1685 | // Block 0x5e, offset 0x1780 | ||
1686 | 0x1780: 0x1308, 0x1781: 0x1008, 0x1782: 0x1008, 0x1783: 0x1008, 0x1784: 0x1008, 0x1785: 0x0040, | ||
1687 | 0x1786: 0x0040, 0x1787: 0x1008, 0x1788: 0x1008, 0x1789: 0x0040, 0x178a: 0x0040, 0x178b: 0x1008, | ||
1688 | 0x178c: 0x1008, 0x178d: 0x1808, 0x178e: 0x0040, 0x178f: 0x0040, 0x1790: 0x0008, 0x1791: 0x0040, | ||
1689 | 0x1792: 0x0040, 0x1793: 0x0040, 0x1794: 0x0040, 0x1795: 0x0040, 0x1796: 0x0040, 0x1797: 0x1008, | ||
1690 | 0x1798: 0x0040, 0x1799: 0x0040, 0x179a: 0x0040, 0x179b: 0x0040, 0x179c: 0x0040, 0x179d: 0x0008, | ||
1691 | 0x179e: 0x0008, 0x179f: 0x0008, 0x17a0: 0x0008, 0x17a1: 0x0008, 0x17a2: 0x1008, 0x17a3: 0x1008, | ||
1692 | 0x17a4: 0x0040, 0x17a5: 0x0040, 0x17a6: 0x1308, 0x17a7: 0x1308, 0x17a8: 0x1308, 0x17a9: 0x1308, | ||
1693 | 0x17aa: 0x1308, 0x17ab: 0x1308, 0x17ac: 0x1308, 0x17ad: 0x0040, 0x17ae: 0x0040, 0x17af: 0x0040, | ||
1694 | 0x17b0: 0x1308, 0x17b1: 0x1308, 0x17b2: 0x1308, 0x17b3: 0x1308, 0x17b4: 0x1308, 0x17b5: 0x0040, | ||
1695 | 0x17b6: 0x0040, 0x17b7: 0x0040, 0x17b8: 0x0040, 0x17b9: 0x0040, 0x17ba: 0x0040, 0x17bb: 0x0040, | ||
1696 | 0x17bc: 0x0040, 0x17bd: 0x0040, 0x17be: 0x0040, 0x17bf: 0x0040, | ||
1697 | // Block 0x5f, offset 0x17c0 | ||
1698 | 0x17c0: 0x0039, 0x17c1: 0x0ee9, 0x17c2: 0x1159, 0x17c3: 0x0ef9, 0x17c4: 0x0f09, 0x17c5: 0x1199, | ||
1699 | 0x17c6: 0x0f31, 0x17c7: 0x0249, 0x17c8: 0x0f41, 0x17c9: 0x0259, 0x17ca: 0x0f51, 0x17cb: 0x0359, | ||
1700 | 0x17cc: 0x0f61, 0x17cd: 0x0f71, 0x17ce: 0x00d9, 0x17cf: 0x0f99, 0x17d0: 0x2039, 0x17d1: 0x0269, | ||
1701 | 0x17d2: 0x01d9, 0x17d3: 0x0fa9, 0x17d4: 0x0fb9, 0x17d5: 0x1089, 0x17d6: 0x0279, 0x17d7: 0x0369, | ||
1702 | 0x17d8: 0x0289, 0x17d9: 0x13d1, 0x17da: 0x0039, 0x17db: 0x0ee9, 0x17dc: 0x1159, 0x17dd: 0x0ef9, | ||
1703 | 0x17de: 0x0f09, 0x17df: 0x1199, 0x17e0: 0x0f31, 0x17e1: 0x0249, 0x17e2: 0x0f41, 0x17e3: 0x0259, | ||
1704 | 0x17e4: 0x0f51, 0x17e5: 0x0359, 0x17e6: 0x0f61, 0x17e7: 0x0f71, 0x17e8: 0x00d9, 0x17e9: 0x0f99, | ||
1705 | 0x17ea: 0x2039, 0x17eb: 0x0269, 0x17ec: 0x01d9, 0x17ed: 0x0fa9, 0x17ee: 0x0fb9, 0x17ef: 0x1089, | ||
1706 | 0x17f0: 0x0279, 0x17f1: 0x0369, 0x17f2: 0x0289, 0x17f3: 0x13d1, 0x17f4: 0x0039, 0x17f5: 0x0ee9, | ||
1707 | 0x17f6: 0x1159, 0x17f7: 0x0ef9, 0x17f8: 0x0f09, 0x17f9: 0x1199, 0x17fa: 0x0f31, 0x17fb: 0x0249, | ||
1708 | 0x17fc: 0x0f41, 0x17fd: 0x0259, 0x17fe: 0x0f51, 0x17ff: 0x0359, | ||
1709 | // Block 0x60, offset 0x1800 | ||
1710 | 0x1800: 0x0f61, 0x1801: 0x0f71, 0x1802: 0x00d9, 0x1803: 0x0f99, 0x1804: 0x2039, 0x1805: 0x0269, | ||
1711 | 0x1806: 0x01d9, 0x1807: 0x0fa9, 0x1808: 0x0fb9, 0x1809: 0x1089, 0x180a: 0x0279, 0x180b: 0x0369, | ||
1712 | 0x180c: 0x0289, 0x180d: 0x13d1, 0x180e: 0x0039, 0x180f: 0x0ee9, 0x1810: 0x1159, 0x1811: 0x0ef9, | ||
1713 | 0x1812: 0x0f09, 0x1813: 0x1199, 0x1814: 0x0f31, 0x1815: 0x0040, 0x1816: 0x0f41, 0x1817: 0x0259, | ||
1714 | 0x1818: 0x0f51, 0x1819: 0x0359, 0x181a: 0x0f61, 0x181b: 0x0f71, 0x181c: 0x00d9, 0x181d: 0x0f99, | ||
1715 | 0x181e: 0x2039, 0x181f: 0x0269, 0x1820: 0x01d9, 0x1821: 0x0fa9, 0x1822: 0x0fb9, 0x1823: 0x1089, | ||
1716 | 0x1824: 0x0279, 0x1825: 0x0369, 0x1826: 0x0289, 0x1827: 0x13d1, 0x1828: 0x0039, 0x1829: 0x0ee9, | ||
1717 | 0x182a: 0x1159, 0x182b: 0x0ef9, 0x182c: 0x0f09, 0x182d: 0x1199, 0x182e: 0x0f31, 0x182f: 0x0249, | ||
1718 | 0x1830: 0x0f41, 0x1831: 0x0259, 0x1832: 0x0f51, 0x1833: 0x0359, 0x1834: 0x0f61, 0x1835: 0x0f71, | ||
1719 | 0x1836: 0x00d9, 0x1837: 0x0f99, 0x1838: 0x2039, 0x1839: 0x0269, 0x183a: 0x01d9, 0x183b: 0x0fa9, | ||
1720 | 0x183c: 0x0fb9, 0x183d: 0x1089, 0x183e: 0x0279, 0x183f: 0x0369, | ||
1721 | // Block 0x61, offset 0x1840 | ||
1722 | 0x1840: 0x0289, 0x1841: 0x13d1, 0x1842: 0x0039, 0x1843: 0x0ee9, 0x1844: 0x1159, 0x1845: 0x0ef9, | ||
1723 | 0x1846: 0x0f09, 0x1847: 0x1199, 0x1848: 0x0f31, 0x1849: 0x0249, 0x184a: 0x0f41, 0x184b: 0x0259, | ||
1724 | 0x184c: 0x0f51, 0x184d: 0x0359, 0x184e: 0x0f61, 0x184f: 0x0f71, 0x1850: 0x00d9, 0x1851: 0x0f99, | ||
1725 | 0x1852: 0x2039, 0x1853: 0x0269, 0x1854: 0x01d9, 0x1855: 0x0fa9, 0x1856: 0x0fb9, 0x1857: 0x1089, | ||
1726 | 0x1858: 0x0279, 0x1859: 0x0369, 0x185a: 0x0289, 0x185b: 0x13d1, 0x185c: 0x0039, 0x185d: 0x0040, | ||
1727 | 0x185e: 0x1159, 0x185f: 0x0ef9, 0x1860: 0x0040, 0x1861: 0x0040, 0x1862: 0x0f31, 0x1863: 0x0040, | ||
1728 | 0x1864: 0x0040, 0x1865: 0x0259, 0x1866: 0x0f51, 0x1867: 0x0040, 0x1868: 0x0040, 0x1869: 0x0f71, | ||
1729 | 0x186a: 0x00d9, 0x186b: 0x0f99, 0x186c: 0x2039, 0x186d: 0x0040, 0x186e: 0x01d9, 0x186f: 0x0fa9, | ||
1730 | 0x1870: 0x0fb9, 0x1871: 0x1089, 0x1872: 0x0279, 0x1873: 0x0369, 0x1874: 0x0289, 0x1875: 0x13d1, | ||
1731 | 0x1876: 0x0039, 0x1877: 0x0ee9, 0x1878: 0x1159, 0x1879: 0x0ef9, 0x187a: 0x0040, 0x187b: 0x1199, | ||
1732 | 0x187c: 0x0040, 0x187d: 0x0249, 0x187e: 0x0f41, 0x187f: 0x0259, | ||
1733 | // Block 0x62, offset 0x1880 | ||
1734 | 0x1880: 0x0f51, 0x1881: 0x0359, 0x1882: 0x0f61, 0x1883: 0x0f71, 0x1884: 0x0040, 0x1885: 0x0f99, | ||
1735 | 0x1886: 0x2039, 0x1887: 0x0269, 0x1888: 0x01d9, 0x1889: 0x0fa9, 0x188a: 0x0fb9, 0x188b: 0x1089, | ||
1736 | 0x188c: 0x0279, 0x188d: 0x0369, 0x188e: 0x0289, 0x188f: 0x13d1, 0x1890: 0x0039, 0x1891: 0x0ee9, | ||
1737 | 0x1892: 0x1159, 0x1893: 0x0ef9, 0x1894: 0x0f09, 0x1895: 0x1199, 0x1896: 0x0f31, 0x1897: 0x0249, | ||
1738 | 0x1898: 0x0f41, 0x1899: 0x0259, 0x189a: 0x0f51, 0x189b: 0x0359, 0x189c: 0x0f61, 0x189d: 0x0f71, | ||
1739 | 0x189e: 0x00d9, 0x189f: 0x0f99, 0x18a0: 0x2039, 0x18a1: 0x0269, 0x18a2: 0x01d9, 0x18a3: 0x0fa9, | ||
1740 | 0x18a4: 0x0fb9, 0x18a5: 0x1089, 0x18a6: 0x0279, 0x18a7: 0x0369, 0x18a8: 0x0289, 0x18a9: 0x13d1, | ||
1741 | 0x18aa: 0x0039, 0x18ab: 0x0ee9, 0x18ac: 0x1159, 0x18ad: 0x0ef9, 0x18ae: 0x0f09, 0x18af: 0x1199, | ||
1742 | 0x18b0: 0x0f31, 0x18b1: 0x0249, 0x18b2: 0x0f41, 0x18b3: 0x0259, 0x18b4: 0x0f51, 0x18b5: 0x0359, | ||
1743 | 0x18b6: 0x0f61, 0x18b7: 0x0f71, 0x18b8: 0x00d9, 0x18b9: 0x0f99, 0x18ba: 0x2039, 0x18bb: 0x0269, | ||
1744 | 0x18bc: 0x01d9, 0x18bd: 0x0fa9, 0x18be: 0x0fb9, 0x18bf: 0x1089, | ||
1745 | // Block 0x63, offset 0x18c0 | ||
1746 | 0x18c0: 0x0279, 0x18c1: 0x0369, 0x18c2: 0x0289, 0x18c3: 0x13d1, 0x18c4: 0x0039, 0x18c5: 0x0ee9, | ||
1747 | 0x18c6: 0x0040, 0x18c7: 0x0ef9, 0x18c8: 0x0f09, 0x18c9: 0x1199, 0x18ca: 0x0f31, 0x18cb: 0x0040, | ||
1748 | 0x18cc: 0x0040, 0x18cd: 0x0259, 0x18ce: 0x0f51, 0x18cf: 0x0359, 0x18d0: 0x0f61, 0x18d1: 0x0f71, | ||
1749 | 0x18d2: 0x00d9, 0x18d3: 0x0f99, 0x18d4: 0x2039, 0x18d5: 0x0040, 0x18d6: 0x01d9, 0x18d7: 0x0fa9, | ||
1750 | 0x18d8: 0x0fb9, 0x18d9: 0x1089, 0x18da: 0x0279, 0x18db: 0x0369, 0x18dc: 0x0289, 0x18dd: 0x0040, | ||
1751 | 0x18de: 0x0039, 0x18df: 0x0ee9, 0x18e0: 0x1159, 0x18e1: 0x0ef9, 0x18e2: 0x0f09, 0x18e3: 0x1199, | ||
1752 | 0x18e4: 0x0f31, 0x18e5: 0x0249, 0x18e6: 0x0f41, 0x18e7: 0x0259, 0x18e8: 0x0f51, 0x18e9: 0x0359, | ||
1753 | 0x18ea: 0x0f61, 0x18eb: 0x0f71, 0x18ec: 0x00d9, 0x18ed: 0x0f99, 0x18ee: 0x2039, 0x18ef: 0x0269, | ||
1754 | 0x18f0: 0x01d9, 0x18f1: 0x0fa9, 0x18f2: 0x0fb9, 0x18f3: 0x1089, 0x18f4: 0x0279, 0x18f5: 0x0369, | ||
1755 | 0x18f6: 0x0289, 0x18f7: 0x13d1, 0x18f8: 0x0039, 0x18f9: 0x0ee9, 0x18fa: 0x0040, 0x18fb: 0x0ef9, | ||
1756 | 0x18fc: 0x0f09, 0x18fd: 0x1199, 0x18fe: 0x0f31, 0x18ff: 0x0040, | ||
1757 | // Block 0x64, offset 0x1900 | ||
1758 | 0x1900: 0x0f41, 0x1901: 0x0259, 0x1902: 0x0f51, 0x1903: 0x0359, 0x1904: 0x0f61, 0x1905: 0x0040, | ||
1759 | 0x1906: 0x00d9, 0x1907: 0x0040, 0x1908: 0x0040, 0x1909: 0x0040, 0x190a: 0x01d9, 0x190b: 0x0fa9, | ||
1760 | 0x190c: 0x0fb9, 0x190d: 0x1089, 0x190e: 0x0279, 0x190f: 0x0369, 0x1910: 0x0289, 0x1911: 0x0040, | ||
1761 | 0x1912: 0x0039, 0x1913: 0x0ee9, 0x1914: 0x1159, 0x1915: 0x0ef9, 0x1916: 0x0f09, 0x1917: 0x1199, | ||
1762 | 0x1918: 0x0f31, 0x1919: 0x0249, 0x191a: 0x0f41, 0x191b: 0x0259, 0x191c: 0x0f51, 0x191d: 0x0359, | ||
1763 | 0x191e: 0x0f61, 0x191f: 0x0f71, 0x1920: 0x00d9, 0x1921: 0x0f99, 0x1922: 0x2039, 0x1923: 0x0269, | ||
1764 | 0x1924: 0x01d9, 0x1925: 0x0fa9, 0x1926: 0x0fb9, 0x1927: 0x1089, 0x1928: 0x0279, 0x1929: 0x0369, | ||
1765 | 0x192a: 0x0289, 0x192b: 0x13d1, 0x192c: 0x0039, 0x192d: 0x0ee9, 0x192e: 0x1159, 0x192f: 0x0ef9, | ||
1766 | 0x1930: 0x0f09, 0x1931: 0x1199, 0x1932: 0x0f31, 0x1933: 0x0249, 0x1934: 0x0f41, 0x1935: 0x0259, | ||
1767 | 0x1936: 0x0f51, 0x1937: 0x0359, 0x1938: 0x0f61, 0x1939: 0x0f71, 0x193a: 0x00d9, 0x193b: 0x0f99, | ||
1768 | 0x193c: 0x2039, 0x193d: 0x0269, 0x193e: 0x01d9, 0x193f: 0x0fa9, | ||
1769 | // Block 0x65, offset 0x1940 | ||
1770 | 0x1940: 0x0fb9, 0x1941: 0x1089, 0x1942: 0x0279, 0x1943: 0x0369, 0x1944: 0x0289, 0x1945: 0x13d1, | ||
1771 | 0x1946: 0x0039, 0x1947: 0x0ee9, 0x1948: 0x1159, 0x1949: 0x0ef9, 0x194a: 0x0f09, 0x194b: 0x1199, | ||
1772 | 0x194c: 0x0f31, 0x194d: 0x0249, 0x194e: 0x0f41, 0x194f: 0x0259, 0x1950: 0x0f51, 0x1951: 0x0359, | ||
1773 | 0x1952: 0x0f61, 0x1953: 0x0f71, 0x1954: 0x00d9, 0x1955: 0x0f99, 0x1956: 0x2039, 0x1957: 0x0269, | ||
1774 | 0x1958: 0x01d9, 0x1959: 0x0fa9, 0x195a: 0x0fb9, 0x195b: 0x1089, 0x195c: 0x0279, 0x195d: 0x0369, | ||
1775 | 0x195e: 0x0289, 0x195f: 0x13d1, 0x1960: 0x0039, 0x1961: 0x0ee9, 0x1962: 0x1159, 0x1963: 0x0ef9, | ||
1776 | 0x1964: 0x0f09, 0x1965: 0x1199, 0x1966: 0x0f31, 0x1967: 0x0249, 0x1968: 0x0f41, 0x1969: 0x0259, | ||
1777 | 0x196a: 0x0f51, 0x196b: 0x0359, 0x196c: 0x0f61, 0x196d: 0x0f71, 0x196e: 0x00d9, 0x196f: 0x0f99, | ||
1778 | 0x1970: 0x2039, 0x1971: 0x0269, 0x1972: 0x01d9, 0x1973: 0x0fa9, 0x1974: 0x0fb9, 0x1975: 0x1089, | ||
1779 | 0x1976: 0x0279, 0x1977: 0x0369, 0x1978: 0x0289, 0x1979: 0x13d1, 0x197a: 0x0039, 0x197b: 0x0ee9, | ||
1780 | 0x197c: 0x1159, 0x197d: 0x0ef9, 0x197e: 0x0f09, 0x197f: 0x1199, | ||
1781 | // Block 0x66, offset 0x1980 | ||
1782 | 0x1980: 0x0f31, 0x1981: 0x0249, 0x1982: 0x0f41, 0x1983: 0x0259, 0x1984: 0x0f51, 0x1985: 0x0359, | ||
1783 | 0x1986: 0x0f61, 0x1987: 0x0f71, 0x1988: 0x00d9, 0x1989: 0x0f99, 0x198a: 0x2039, 0x198b: 0x0269, | ||
1784 | 0x198c: 0x01d9, 0x198d: 0x0fa9, 0x198e: 0x0fb9, 0x198f: 0x1089, 0x1990: 0x0279, 0x1991: 0x0369, | ||
1785 | 0x1992: 0x0289, 0x1993: 0x13d1, 0x1994: 0x0039, 0x1995: 0x0ee9, 0x1996: 0x1159, 0x1997: 0x0ef9, | ||
1786 | 0x1998: 0x0f09, 0x1999: 0x1199, 0x199a: 0x0f31, 0x199b: 0x0249, 0x199c: 0x0f41, 0x199d: 0x0259, | ||
1787 | 0x199e: 0x0f51, 0x199f: 0x0359, 0x19a0: 0x0f61, 0x19a1: 0x0f71, 0x19a2: 0x00d9, 0x19a3: 0x0f99, | ||
1788 | 0x19a4: 0x2039, 0x19a5: 0x0269, 0x19a6: 0x01d9, 0x19a7: 0x0fa9, 0x19a8: 0x0fb9, 0x19a9: 0x1089, | ||
1789 | 0x19aa: 0x0279, 0x19ab: 0x0369, 0x19ac: 0x0289, 0x19ad: 0x13d1, 0x19ae: 0x0039, 0x19af: 0x0ee9, | ||
1790 | 0x19b0: 0x1159, 0x19b1: 0x0ef9, 0x19b2: 0x0f09, 0x19b3: 0x1199, 0x19b4: 0x0f31, 0x19b5: 0x0249, | ||
1791 | 0x19b6: 0x0f41, 0x19b7: 0x0259, 0x19b8: 0x0f51, 0x19b9: 0x0359, 0x19ba: 0x0f61, 0x19bb: 0x0f71, | ||
1792 | 0x19bc: 0x00d9, 0x19bd: 0x0f99, 0x19be: 0x2039, 0x19bf: 0x0269, | ||
1793 | // Block 0x67, offset 0x19c0 | ||
1794 | 0x19c0: 0x01d9, 0x19c1: 0x0fa9, 0x19c2: 0x0fb9, 0x19c3: 0x1089, 0x19c4: 0x0279, 0x19c5: 0x0369, | ||
1795 | 0x19c6: 0x0289, 0x19c7: 0x13d1, 0x19c8: 0x0039, 0x19c9: 0x0ee9, 0x19ca: 0x1159, 0x19cb: 0x0ef9, | ||
1796 | 0x19cc: 0x0f09, 0x19cd: 0x1199, 0x19ce: 0x0f31, 0x19cf: 0x0249, 0x19d0: 0x0f41, 0x19d1: 0x0259, | ||
1797 | 0x19d2: 0x0f51, 0x19d3: 0x0359, 0x19d4: 0x0f61, 0x19d5: 0x0f71, 0x19d6: 0x00d9, 0x19d7: 0x0f99, | ||
1798 | 0x19d8: 0x2039, 0x19d9: 0x0269, 0x19da: 0x01d9, 0x19db: 0x0fa9, 0x19dc: 0x0fb9, 0x19dd: 0x1089, | ||
1799 | 0x19de: 0x0279, 0x19df: 0x0369, 0x19e0: 0x0289, 0x19e1: 0x13d1, 0x19e2: 0x0039, 0x19e3: 0x0ee9, | ||
1800 | 0x19e4: 0x1159, 0x19e5: 0x0ef9, 0x19e6: 0x0f09, 0x19e7: 0x1199, 0x19e8: 0x0f31, 0x19e9: 0x0249, | ||
1801 | 0x19ea: 0x0f41, 0x19eb: 0x0259, 0x19ec: 0x0f51, 0x19ed: 0x0359, 0x19ee: 0x0f61, 0x19ef: 0x0f71, | ||
1802 | 0x19f0: 0x00d9, 0x19f1: 0x0f99, 0x19f2: 0x2039, 0x19f3: 0x0269, 0x19f4: 0x01d9, 0x19f5: 0x0fa9, | ||
1803 | 0x19f6: 0x0fb9, 0x19f7: 0x1089, 0x19f8: 0x0279, 0x19f9: 0x0369, 0x19fa: 0x0289, 0x19fb: 0x13d1, | ||
1804 | 0x19fc: 0x0039, 0x19fd: 0x0ee9, 0x19fe: 0x1159, 0x19ff: 0x0ef9, | ||
1805 | // Block 0x68, offset 0x1a00 | ||
1806 | 0x1a00: 0x0f09, 0x1a01: 0x1199, 0x1a02: 0x0f31, 0x1a03: 0x0249, 0x1a04: 0x0f41, 0x1a05: 0x0259, | ||
1807 | 0x1a06: 0x0f51, 0x1a07: 0x0359, 0x1a08: 0x0f61, 0x1a09: 0x0f71, 0x1a0a: 0x00d9, 0x1a0b: 0x0f99, | ||
1808 | 0x1a0c: 0x2039, 0x1a0d: 0x0269, 0x1a0e: 0x01d9, 0x1a0f: 0x0fa9, 0x1a10: 0x0fb9, 0x1a11: 0x1089, | ||
1809 | 0x1a12: 0x0279, 0x1a13: 0x0369, 0x1a14: 0x0289, 0x1a15: 0x13d1, 0x1a16: 0x0039, 0x1a17: 0x0ee9, | ||
1810 | 0x1a18: 0x1159, 0x1a19: 0x0ef9, 0x1a1a: 0x0f09, 0x1a1b: 0x1199, 0x1a1c: 0x0f31, 0x1a1d: 0x0249, | ||
1811 | 0x1a1e: 0x0f41, 0x1a1f: 0x0259, 0x1a20: 0x0f51, 0x1a21: 0x0359, 0x1a22: 0x0f61, 0x1a23: 0x0f71, | ||
1812 | 0x1a24: 0x00d9, 0x1a25: 0x0f99, 0x1a26: 0x2039, 0x1a27: 0x0269, 0x1a28: 0x01d9, 0x1a29: 0x0fa9, | ||
1813 | 0x1a2a: 0x0fb9, 0x1a2b: 0x1089, 0x1a2c: 0x0279, 0x1a2d: 0x0369, 0x1a2e: 0x0289, 0x1a2f: 0x13d1, | ||
1814 | 0x1a30: 0x0039, 0x1a31: 0x0ee9, 0x1a32: 0x1159, 0x1a33: 0x0ef9, 0x1a34: 0x0f09, 0x1a35: 0x1199, | ||
1815 | 0x1a36: 0x0f31, 0x1a37: 0x0249, 0x1a38: 0x0f41, 0x1a39: 0x0259, 0x1a3a: 0x0f51, 0x1a3b: 0x0359, | ||
1816 | 0x1a3c: 0x0f61, 0x1a3d: 0x0f71, 0x1a3e: 0x00d9, 0x1a3f: 0x0f99, | ||
1817 | // Block 0x69, offset 0x1a40 | ||
1818 | 0x1a40: 0x2039, 0x1a41: 0x0269, 0x1a42: 0x01d9, 0x1a43: 0x0fa9, 0x1a44: 0x0fb9, 0x1a45: 0x1089, | ||
1819 | 0x1a46: 0x0279, 0x1a47: 0x0369, 0x1a48: 0x0289, 0x1a49: 0x13d1, 0x1a4a: 0x0039, 0x1a4b: 0x0ee9, | ||
1820 | 0x1a4c: 0x1159, 0x1a4d: 0x0ef9, 0x1a4e: 0x0f09, 0x1a4f: 0x1199, 0x1a50: 0x0f31, 0x1a51: 0x0249, | ||
1821 | 0x1a52: 0x0f41, 0x1a53: 0x0259, 0x1a54: 0x0f51, 0x1a55: 0x0359, 0x1a56: 0x0f61, 0x1a57: 0x0f71, | ||
1822 | 0x1a58: 0x00d9, 0x1a59: 0x0f99, 0x1a5a: 0x2039, 0x1a5b: 0x0269, 0x1a5c: 0x01d9, 0x1a5d: 0x0fa9, | ||
1823 | 0x1a5e: 0x0fb9, 0x1a5f: 0x1089, 0x1a60: 0x0279, 0x1a61: 0x0369, 0x1a62: 0x0289, 0x1a63: 0x13d1, | ||
1824 | 0x1a64: 0xba81, 0x1a65: 0xba99, 0x1a66: 0x0040, 0x1a67: 0x0040, 0x1a68: 0xbab1, 0x1a69: 0x1099, | ||
1825 | 0x1a6a: 0x10b1, 0x1a6b: 0x10c9, 0x1a6c: 0xbac9, 0x1a6d: 0xbae1, 0x1a6e: 0xbaf9, 0x1a6f: 0x1429, | ||
1826 | 0x1a70: 0x1a31, 0x1a71: 0xbb11, 0x1a72: 0xbb29, 0x1a73: 0xbb41, 0x1a74: 0xbb59, 0x1a75: 0xbb71, | ||
1827 | 0x1a76: 0xbb89, 0x1a77: 0x2109, 0x1a78: 0x1111, 0x1a79: 0x1429, 0x1a7a: 0xbba1, 0x1a7b: 0xbbb9, | ||
1828 | 0x1a7c: 0xbbd1, 0x1a7d: 0x10e1, 0x1a7e: 0x10f9, 0x1a7f: 0xbbe9, | ||
1829 | // Block 0x6a, offset 0x1a80 | ||
1830 | 0x1a80: 0x2079, 0x1a81: 0xbc01, 0x1a82: 0xbab1, 0x1a83: 0x1099, 0x1a84: 0x10b1, 0x1a85: 0x10c9, | ||
1831 | 0x1a86: 0xbac9, 0x1a87: 0xbae1, 0x1a88: 0xbaf9, 0x1a89: 0x1429, 0x1a8a: 0x1a31, 0x1a8b: 0xbb11, | ||
1832 | 0x1a8c: 0xbb29, 0x1a8d: 0xbb41, 0x1a8e: 0xbb59, 0x1a8f: 0xbb71, 0x1a90: 0xbb89, 0x1a91: 0x2109, | ||
1833 | 0x1a92: 0x1111, 0x1a93: 0xbba1, 0x1a94: 0xbba1, 0x1a95: 0xbbb9, 0x1a96: 0xbbd1, 0x1a97: 0x10e1, | ||
1834 | 0x1a98: 0x10f9, 0x1a99: 0xbbe9, 0x1a9a: 0x2079, 0x1a9b: 0xbc21, 0x1a9c: 0xbac9, 0x1a9d: 0x1429, | ||
1835 | 0x1a9e: 0xbb11, 0x1a9f: 0x10e1, 0x1aa0: 0x1111, 0x1aa1: 0x2109, 0x1aa2: 0xbab1, 0x1aa3: 0x1099, | ||
1836 | 0x1aa4: 0x10b1, 0x1aa5: 0x10c9, 0x1aa6: 0xbac9, 0x1aa7: 0xbae1, 0x1aa8: 0xbaf9, 0x1aa9: 0x1429, | ||
1837 | 0x1aaa: 0x1a31, 0x1aab: 0xbb11, 0x1aac: 0xbb29, 0x1aad: 0xbb41, 0x1aae: 0xbb59, 0x1aaf: 0xbb71, | ||
1838 | 0x1ab0: 0xbb89, 0x1ab1: 0x2109, 0x1ab2: 0x1111, 0x1ab3: 0x1429, 0x1ab4: 0xbba1, 0x1ab5: 0xbbb9, | ||
1839 | 0x1ab6: 0xbbd1, 0x1ab7: 0x10e1, 0x1ab8: 0x10f9, 0x1ab9: 0xbbe9, 0x1aba: 0x2079, 0x1abb: 0xbc01, | ||
1840 | 0x1abc: 0xbab1, 0x1abd: 0x1099, 0x1abe: 0x10b1, 0x1abf: 0x10c9, | ||
1841 | // Block 0x6b, offset 0x1ac0 | ||
1842 | 0x1ac0: 0xbac9, 0x1ac1: 0xbae1, 0x1ac2: 0xbaf9, 0x1ac3: 0x1429, 0x1ac4: 0x1a31, 0x1ac5: 0xbb11, | ||
1843 | 0x1ac6: 0xbb29, 0x1ac7: 0xbb41, 0x1ac8: 0xbb59, 0x1ac9: 0xbb71, 0x1aca: 0xbb89, 0x1acb: 0x2109, | ||
1844 | 0x1acc: 0x1111, 0x1acd: 0xbba1, 0x1ace: 0xbba1, 0x1acf: 0xbbb9, 0x1ad0: 0xbbd1, 0x1ad1: 0x10e1, | ||
1845 | 0x1ad2: 0x10f9, 0x1ad3: 0xbbe9, 0x1ad4: 0x2079, 0x1ad5: 0xbc21, 0x1ad6: 0xbac9, 0x1ad7: 0x1429, | ||
1846 | 0x1ad8: 0xbb11, 0x1ad9: 0x10e1, 0x1ada: 0x1111, 0x1adb: 0x2109, 0x1adc: 0xbab1, 0x1add: 0x1099, | ||
1847 | 0x1ade: 0x10b1, 0x1adf: 0x10c9, 0x1ae0: 0xbac9, 0x1ae1: 0xbae1, 0x1ae2: 0xbaf9, 0x1ae3: 0x1429, | ||
1848 | 0x1ae4: 0x1a31, 0x1ae5: 0xbb11, 0x1ae6: 0xbb29, 0x1ae7: 0xbb41, 0x1ae8: 0xbb59, 0x1ae9: 0xbb71, | ||
1849 | 0x1aea: 0xbb89, 0x1aeb: 0x2109, 0x1aec: 0x1111, 0x1aed: 0x1429, 0x1aee: 0xbba1, 0x1aef: 0xbbb9, | ||
1850 | 0x1af0: 0xbbd1, 0x1af1: 0x10e1, 0x1af2: 0x10f9, 0x1af3: 0xbbe9, 0x1af4: 0x2079, 0x1af5: 0xbc01, | ||
1851 | 0x1af6: 0xbab1, 0x1af7: 0x1099, 0x1af8: 0x10b1, 0x1af9: 0x10c9, 0x1afa: 0xbac9, 0x1afb: 0xbae1, | ||
1852 | 0x1afc: 0xbaf9, 0x1afd: 0x1429, 0x1afe: 0x1a31, 0x1aff: 0xbb11, | ||
1853 | // Block 0x6c, offset 0x1b00 | ||
1854 | 0x1b00: 0xbb29, 0x1b01: 0xbb41, 0x1b02: 0xbb59, 0x1b03: 0xbb71, 0x1b04: 0xbb89, 0x1b05: 0x2109, | ||
1855 | 0x1b06: 0x1111, 0x1b07: 0xbba1, 0x1b08: 0xbba1, 0x1b09: 0xbbb9, 0x1b0a: 0xbbd1, 0x1b0b: 0x10e1, | ||
1856 | 0x1b0c: 0x10f9, 0x1b0d: 0xbbe9, 0x1b0e: 0x2079, 0x1b0f: 0xbc21, 0x1b10: 0xbac9, 0x1b11: 0x1429, | ||
1857 | 0x1b12: 0xbb11, 0x1b13: 0x10e1, 0x1b14: 0x1111, 0x1b15: 0x2109, 0x1b16: 0xbab1, 0x1b17: 0x1099, | ||
1858 | 0x1b18: 0x10b1, 0x1b19: 0x10c9, 0x1b1a: 0xbac9, 0x1b1b: 0xbae1, 0x1b1c: 0xbaf9, 0x1b1d: 0x1429, | ||
1859 | 0x1b1e: 0x1a31, 0x1b1f: 0xbb11, 0x1b20: 0xbb29, 0x1b21: 0xbb41, 0x1b22: 0xbb59, 0x1b23: 0xbb71, | ||
1860 | 0x1b24: 0xbb89, 0x1b25: 0x2109, 0x1b26: 0x1111, 0x1b27: 0x1429, 0x1b28: 0xbba1, 0x1b29: 0xbbb9, | ||
1861 | 0x1b2a: 0xbbd1, 0x1b2b: 0x10e1, 0x1b2c: 0x10f9, 0x1b2d: 0xbbe9, 0x1b2e: 0x2079, 0x1b2f: 0xbc01, | ||
1862 | 0x1b30: 0xbab1, 0x1b31: 0x1099, 0x1b32: 0x10b1, 0x1b33: 0x10c9, 0x1b34: 0xbac9, 0x1b35: 0xbae1, | ||
1863 | 0x1b36: 0xbaf9, 0x1b37: 0x1429, 0x1b38: 0x1a31, 0x1b39: 0xbb11, 0x1b3a: 0xbb29, 0x1b3b: 0xbb41, | ||
1864 | 0x1b3c: 0xbb59, 0x1b3d: 0xbb71, 0x1b3e: 0xbb89, 0x1b3f: 0x2109, | ||
1865 | // Block 0x6d, offset 0x1b40 | ||
1866 | 0x1b40: 0x1111, 0x1b41: 0xbba1, 0x1b42: 0xbba1, 0x1b43: 0xbbb9, 0x1b44: 0xbbd1, 0x1b45: 0x10e1, | ||
1867 | 0x1b46: 0x10f9, 0x1b47: 0xbbe9, 0x1b48: 0x2079, 0x1b49: 0xbc21, 0x1b4a: 0xbac9, 0x1b4b: 0x1429, | ||
1868 | 0x1b4c: 0xbb11, 0x1b4d: 0x10e1, 0x1b4e: 0x1111, 0x1b4f: 0x2109, 0x1b50: 0xbab1, 0x1b51: 0x1099, | ||
1869 | 0x1b52: 0x10b1, 0x1b53: 0x10c9, 0x1b54: 0xbac9, 0x1b55: 0xbae1, 0x1b56: 0xbaf9, 0x1b57: 0x1429, | ||
1870 | 0x1b58: 0x1a31, 0x1b59: 0xbb11, 0x1b5a: 0xbb29, 0x1b5b: 0xbb41, 0x1b5c: 0xbb59, 0x1b5d: 0xbb71, | ||
1871 | 0x1b5e: 0xbb89, 0x1b5f: 0x2109, 0x1b60: 0x1111, 0x1b61: 0x1429, 0x1b62: 0xbba1, 0x1b63: 0xbbb9, | ||
1872 | 0x1b64: 0xbbd1, 0x1b65: 0x10e1, 0x1b66: 0x10f9, 0x1b67: 0xbbe9, 0x1b68: 0x2079, 0x1b69: 0xbc01, | ||
1873 | 0x1b6a: 0xbab1, 0x1b6b: 0x1099, 0x1b6c: 0x10b1, 0x1b6d: 0x10c9, 0x1b6e: 0xbac9, 0x1b6f: 0xbae1, | ||
1874 | 0x1b70: 0xbaf9, 0x1b71: 0x1429, 0x1b72: 0x1a31, 0x1b73: 0xbb11, 0x1b74: 0xbb29, 0x1b75: 0xbb41, | ||
1875 | 0x1b76: 0xbb59, 0x1b77: 0xbb71, 0x1b78: 0xbb89, 0x1b79: 0x2109, 0x1b7a: 0x1111, 0x1b7b: 0xbba1, | ||
1876 | 0x1b7c: 0xbba1, 0x1b7d: 0xbbb9, 0x1b7e: 0xbbd1, 0x1b7f: 0x10e1, | ||
1877 | // Block 0x6e, offset 0x1b80 | ||
1878 | 0x1b80: 0x10f9, 0x1b81: 0xbbe9, 0x1b82: 0x2079, 0x1b83: 0xbc21, 0x1b84: 0xbac9, 0x1b85: 0x1429, | ||
1879 | 0x1b86: 0xbb11, 0x1b87: 0x10e1, 0x1b88: 0x1111, 0x1b89: 0x2109, 0x1b8a: 0xbc41, 0x1b8b: 0xbc41, | ||
1880 | 0x1b8c: 0x0040, 0x1b8d: 0x0040, 0x1b8e: 0x1f41, 0x1b8f: 0x00c9, 0x1b90: 0x0069, 0x1b91: 0x0079, | ||
1881 | 0x1b92: 0x1f51, 0x1b93: 0x1f61, 0x1b94: 0x1f71, 0x1b95: 0x1f81, 0x1b96: 0x1f91, 0x1b97: 0x1fa1, | ||
1882 | 0x1b98: 0x1f41, 0x1b99: 0x00c9, 0x1b9a: 0x0069, 0x1b9b: 0x0079, 0x1b9c: 0x1f51, 0x1b9d: 0x1f61, | ||
1883 | 0x1b9e: 0x1f71, 0x1b9f: 0x1f81, 0x1ba0: 0x1f91, 0x1ba1: 0x1fa1, 0x1ba2: 0x1f41, 0x1ba3: 0x00c9, | ||
1884 | 0x1ba4: 0x0069, 0x1ba5: 0x0079, 0x1ba6: 0x1f51, 0x1ba7: 0x1f61, 0x1ba8: 0x1f71, 0x1ba9: 0x1f81, | ||
1885 | 0x1baa: 0x1f91, 0x1bab: 0x1fa1, 0x1bac: 0x1f41, 0x1bad: 0x00c9, 0x1bae: 0x0069, 0x1baf: 0x0079, | ||
1886 | 0x1bb0: 0x1f51, 0x1bb1: 0x1f61, 0x1bb2: 0x1f71, 0x1bb3: 0x1f81, 0x1bb4: 0x1f91, 0x1bb5: 0x1fa1, | ||
1887 | 0x1bb6: 0x1f41, 0x1bb7: 0x00c9, 0x1bb8: 0x0069, 0x1bb9: 0x0079, 0x1bba: 0x1f51, 0x1bbb: 0x1f61, | ||
1888 | 0x1bbc: 0x1f71, 0x1bbd: 0x1f81, 0x1bbe: 0x1f91, 0x1bbf: 0x1fa1, | ||
1889 | // Block 0x6f, offset 0x1bc0 | ||
1890 | 0x1bc0: 0xe115, 0x1bc1: 0xe115, 0x1bc2: 0xe135, 0x1bc3: 0xe135, 0x1bc4: 0xe115, 0x1bc5: 0xe115, | ||
1891 | 0x1bc6: 0xe175, 0x1bc7: 0xe175, 0x1bc8: 0xe115, 0x1bc9: 0xe115, 0x1bca: 0xe135, 0x1bcb: 0xe135, | ||
1892 | 0x1bcc: 0xe115, 0x1bcd: 0xe115, 0x1bce: 0xe1f5, 0x1bcf: 0xe1f5, 0x1bd0: 0xe115, 0x1bd1: 0xe115, | ||
1893 | 0x1bd2: 0xe135, 0x1bd3: 0xe135, 0x1bd4: 0xe115, 0x1bd5: 0xe115, 0x1bd6: 0xe175, 0x1bd7: 0xe175, | ||
1894 | 0x1bd8: 0xe115, 0x1bd9: 0xe115, 0x1bda: 0xe135, 0x1bdb: 0xe135, 0x1bdc: 0xe115, 0x1bdd: 0xe115, | ||
1895 | 0x1bde: 0x8b05, 0x1bdf: 0x8b05, 0x1be0: 0x04b5, 0x1be1: 0x04b5, 0x1be2: 0x0208, 0x1be3: 0x0208, | ||
1896 | 0x1be4: 0x0208, 0x1be5: 0x0208, 0x1be6: 0x0208, 0x1be7: 0x0208, 0x1be8: 0x0208, 0x1be9: 0x0208, | ||
1897 | 0x1bea: 0x0208, 0x1beb: 0x0208, 0x1bec: 0x0208, 0x1bed: 0x0208, 0x1bee: 0x0208, 0x1bef: 0x0208, | ||
1898 | 0x1bf0: 0x0208, 0x1bf1: 0x0208, 0x1bf2: 0x0208, 0x1bf3: 0x0208, 0x1bf4: 0x0208, 0x1bf5: 0x0208, | ||
1899 | 0x1bf6: 0x0208, 0x1bf7: 0x0208, 0x1bf8: 0x0208, 0x1bf9: 0x0208, 0x1bfa: 0x0208, 0x1bfb: 0x0208, | ||
1900 | 0x1bfc: 0x0208, 0x1bfd: 0x0208, 0x1bfe: 0x0208, 0x1bff: 0x0208, | ||
1901 | // Block 0x70, offset 0x1c00 | ||
1902 | 0x1c00: 0xb189, 0x1c01: 0xb1a1, 0x1c02: 0xb201, 0x1c03: 0xb249, 0x1c04: 0x0040, 0x1c05: 0xb411, | ||
1903 | 0x1c06: 0xb291, 0x1c07: 0xb219, 0x1c08: 0xb309, 0x1c09: 0xb429, 0x1c0a: 0xb399, 0x1c0b: 0xb3b1, | ||
1904 | 0x1c0c: 0xb3c9, 0x1c0d: 0xb3e1, 0x1c0e: 0xb2a9, 0x1c0f: 0xb339, 0x1c10: 0xb369, 0x1c11: 0xb2d9, | ||
1905 | 0x1c12: 0xb381, 0x1c13: 0xb279, 0x1c14: 0xb2c1, 0x1c15: 0xb1d1, 0x1c16: 0xb1e9, 0x1c17: 0xb231, | ||
1906 | 0x1c18: 0xb261, 0x1c19: 0xb2f1, 0x1c1a: 0xb321, 0x1c1b: 0xb351, 0x1c1c: 0xbc59, 0x1c1d: 0x7949, | ||
1907 | 0x1c1e: 0xbc71, 0x1c1f: 0xbc89, 0x1c20: 0x0040, 0x1c21: 0xb1a1, 0x1c22: 0xb201, 0x1c23: 0x0040, | ||
1908 | 0x1c24: 0xb3f9, 0x1c25: 0x0040, 0x1c26: 0x0040, 0x1c27: 0xb219, 0x1c28: 0x0040, 0x1c29: 0xb429, | ||
1909 | 0x1c2a: 0xb399, 0x1c2b: 0xb3b1, 0x1c2c: 0xb3c9, 0x1c2d: 0xb3e1, 0x1c2e: 0xb2a9, 0x1c2f: 0xb339, | ||
1910 | 0x1c30: 0xb369, 0x1c31: 0xb2d9, 0x1c32: 0xb381, 0x1c33: 0x0040, 0x1c34: 0xb2c1, 0x1c35: 0xb1d1, | ||
1911 | 0x1c36: 0xb1e9, 0x1c37: 0xb231, 0x1c38: 0x0040, 0x1c39: 0xb2f1, 0x1c3a: 0x0040, 0x1c3b: 0xb351, | ||
1912 | 0x1c3c: 0x0040, 0x1c3d: 0x0040, 0x1c3e: 0x0040, 0x1c3f: 0x0040, | ||
1913 | // Block 0x71, offset 0x1c40 | ||
1914 | 0x1c40: 0x0040, 0x1c41: 0x0040, 0x1c42: 0xb201, 0x1c43: 0x0040, 0x1c44: 0x0040, 0x1c45: 0x0040, | ||
1915 | 0x1c46: 0x0040, 0x1c47: 0xb219, 0x1c48: 0x0040, 0x1c49: 0xb429, 0x1c4a: 0x0040, 0x1c4b: 0xb3b1, | ||
1916 | 0x1c4c: 0x0040, 0x1c4d: 0xb3e1, 0x1c4e: 0xb2a9, 0x1c4f: 0xb339, 0x1c50: 0x0040, 0x1c51: 0xb2d9, | ||
1917 | 0x1c52: 0xb381, 0x1c53: 0x0040, 0x1c54: 0xb2c1, 0x1c55: 0x0040, 0x1c56: 0x0040, 0x1c57: 0xb231, | ||
1918 | 0x1c58: 0x0040, 0x1c59: 0xb2f1, 0x1c5a: 0x0040, 0x1c5b: 0xb351, 0x1c5c: 0x0040, 0x1c5d: 0x7949, | ||
1919 | 0x1c5e: 0x0040, 0x1c5f: 0xbc89, 0x1c60: 0x0040, 0x1c61: 0xb1a1, 0x1c62: 0xb201, 0x1c63: 0x0040, | ||
1920 | 0x1c64: 0xb3f9, 0x1c65: 0x0040, 0x1c66: 0x0040, 0x1c67: 0xb219, 0x1c68: 0xb309, 0x1c69: 0xb429, | ||
1921 | 0x1c6a: 0xb399, 0x1c6b: 0x0040, 0x1c6c: 0xb3c9, 0x1c6d: 0xb3e1, 0x1c6e: 0xb2a9, 0x1c6f: 0xb339, | ||
1922 | 0x1c70: 0xb369, 0x1c71: 0xb2d9, 0x1c72: 0xb381, 0x1c73: 0x0040, 0x1c74: 0xb2c1, 0x1c75: 0xb1d1, | ||
1923 | 0x1c76: 0xb1e9, 0x1c77: 0xb231, 0x1c78: 0x0040, 0x1c79: 0xb2f1, 0x1c7a: 0xb321, 0x1c7b: 0xb351, | ||
1924 | 0x1c7c: 0xbc59, 0x1c7d: 0x0040, 0x1c7e: 0xbc71, 0x1c7f: 0x0040, | ||
1925 | // Block 0x72, offset 0x1c80 | ||
1926 | 0x1c80: 0xb189, 0x1c81: 0xb1a1, 0x1c82: 0xb201, 0x1c83: 0xb249, 0x1c84: 0xb3f9, 0x1c85: 0xb411, | ||
1927 | 0x1c86: 0xb291, 0x1c87: 0xb219, 0x1c88: 0xb309, 0x1c89: 0xb429, 0x1c8a: 0x0040, 0x1c8b: 0xb3b1, | ||
1928 | 0x1c8c: 0xb3c9, 0x1c8d: 0xb3e1, 0x1c8e: 0xb2a9, 0x1c8f: 0xb339, 0x1c90: 0xb369, 0x1c91: 0xb2d9, | ||
1929 | 0x1c92: 0xb381, 0x1c93: 0xb279, 0x1c94: 0xb2c1, 0x1c95: 0xb1d1, 0x1c96: 0xb1e9, 0x1c97: 0xb231, | ||
1930 | 0x1c98: 0xb261, 0x1c99: 0xb2f1, 0x1c9a: 0xb321, 0x1c9b: 0xb351, 0x1c9c: 0x0040, 0x1c9d: 0x0040, | ||
1931 | 0x1c9e: 0x0040, 0x1c9f: 0x0040, 0x1ca0: 0x0040, 0x1ca1: 0xb1a1, 0x1ca2: 0xb201, 0x1ca3: 0xb249, | ||
1932 | 0x1ca4: 0x0040, 0x1ca5: 0xb411, 0x1ca6: 0xb291, 0x1ca7: 0xb219, 0x1ca8: 0xb309, 0x1ca9: 0xb429, | ||
1933 | 0x1caa: 0x0040, 0x1cab: 0xb3b1, 0x1cac: 0xb3c9, 0x1cad: 0xb3e1, 0x1cae: 0xb2a9, 0x1caf: 0xb339, | ||
1934 | 0x1cb0: 0xb369, 0x1cb1: 0xb2d9, 0x1cb2: 0xb381, 0x1cb3: 0xb279, 0x1cb4: 0xb2c1, 0x1cb5: 0xb1d1, | ||
1935 | 0x1cb6: 0xb1e9, 0x1cb7: 0xb231, 0x1cb8: 0xb261, 0x1cb9: 0xb2f1, 0x1cba: 0xb321, 0x1cbb: 0xb351, | ||
1936 | 0x1cbc: 0x0040, 0x1cbd: 0x0040, 0x1cbe: 0x0040, 0x1cbf: 0x0040, | ||
1937 | // Block 0x73, offset 0x1cc0 | ||
1938 | 0x1cc0: 0x0040, 0x1cc1: 0xbca2, 0x1cc2: 0xbcba, 0x1cc3: 0xbcd2, 0x1cc4: 0xbcea, 0x1cc5: 0xbd02, | ||
1939 | 0x1cc6: 0xbd1a, 0x1cc7: 0xbd32, 0x1cc8: 0xbd4a, 0x1cc9: 0xbd62, 0x1cca: 0xbd7a, 0x1ccb: 0x0018, | ||
1940 | 0x1ccc: 0x0018, 0x1ccd: 0x0040, 0x1cce: 0x0040, 0x1ccf: 0x0040, 0x1cd0: 0xbd92, 0x1cd1: 0xbdb2, | ||
1941 | 0x1cd2: 0xbdd2, 0x1cd3: 0xbdf2, 0x1cd4: 0xbe12, 0x1cd5: 0xbe32, 0x1cd6: 0xbe52, 0x1cd7: 0xbe72, | ||
1942 | 0x1cd8: 0xbe92, 0x1cd9: 0xbeb2, 0x1cda: 0xbed2, 0x1cdb: 0xbef2, 0x1cdc: 0xbf12, 0x1cdd: 0xbf32, | ||
1943 | 0x1cde: 0xbf52, 0x1cdf: 0xbf72, 0x1ce0: 0xbf92, 0x1ce1: 0xbfb2, 0x1ce2: 0xbfd2, 0x1ce3: 0xbff2, | ||
1944 | 0x1ce4: 0xc012, 0x1ce5: 0xc032, 0x1ce6: 0xc052, 0x1ce7: 0xc072, 0x1ce8: 0xc092, 0x1ce9: 0xc0b2, | ||
1945 | 0x1cea: 0xc0d1, 0x1ceb: 0x1159, 0x1cec: 0x0269, 0x1ced: 0x6671, 0x1cee: 0xc111, 0x1cef: 0x0040, | ||
1946 | 0x1cf0: 0x0039, 0x1cf1: 0x0ee9, 0x1cf2: 0x1159, 0x1cf3: 0x0ef9, 0x1cf4: 0x0f09, 0x1cf5: 0x1199, | ||
1947 | 0x1cf6: 0x0f31, 0x1cf7: 0x0249, 0x1cf8: 0x0f41, 0x1cf9: 0x0259, 0x1cfa: 0x0f51, 0x1cfb: 0x0359, | ||
1948 | 0x1cfc: 0x0f61, 0x1cfd: 0x0f71, 0x1cfe: 0x00d9, 0x1cff: 0x0f99, | ||
1949 | // Block 0x74, offset 0x1d00 | ||
1950 | 0x1d00: 0x2039, 0x1d01: 0x0269, 0x1d02: 0x01d9, 0x1d03: 0x0fa9, 0x1d04: 0x0fb9, 0x1d05: 0x1089, | ||
1951 | 0x1d06: 0x0279, 0x1d07: 0x0369, 0x1d08: 0x0289, 0x1d09: 0x13d1, 0x1d0a: 0xc129, 0x1d0b: 0x65b1, | ||
1952 | 0x1d0c: 0xc141, 0x1d0d: 0x1441, 0x1d0e: 0xc159, 0x1d0f: 0xc179, 0x1d10: 0x0018, 0x1d11: 0x0018, | ||
1953 | 0x1d12: 0x0018, 0x1d13: 0x0018, 0x1d14: 0x0018, 0x1d15: 0x0018, 0x1d16: 0x0018, 0x1d17: 0x0018, | ||
1954 | 0x1d18: 0x0018, 0x1d19: 0x0018, 0x1d1a: 0x0018, 0x1d1b: 0x0018, 0x1d1c: 0x0018, 0x1d1d: 0x0018, | ||
1955 | 0x1d1e: 0x0018, 0x1d1f: 0x0018, 0x1d20: 0x0018, 0x1d21: 0x0018, 0x1d22: 0x0018, 0x1d23: 0x0018, | ||
1956 | 0x1d24: 0x0018, 0x1d25: 0x0018, 0x1d26: 0x0018, 0x1d27: 0x0018, 0x1d28: 0x0018, 0x1d29: 0x0018, | ||
1957 | 0x1d2a: 0xc191, 0x1d2b: 0xc1a9, 0x1d2c: 0x0040, 0x1d2d: 0x0040, 0x1d2e: 0x0040, 0x1d2f: 0x0040, | ||
1958 | 0x1d30: 0x0018, 0x1d31: 0x0018, 0x1d32: 0x0018, 0x1d33: 0x0018, 0x1d34: 0x0018, 0x1d35: 0x0018, | ||
1959 | 0x1d36: 0x0018, 0x1d37: 0x0018, 0x1d38: 0x0018, 0x1d39: 0x0018, 0x1d3a: 0x0018, 0x1d3b: 0x0018, | ||
1960 | 0x1d3c: 0x0018, 0x1d3d: 0x0018, 0x1d3e: 0x0018, 0x1d3f: 0x0018, | ||
1961 | // Block 0x75, offset 0x1d40 | ||
1962 | 0x1d40: 0xc1d9, 0x1d41: 0xc211, 0x1d42: 0xc249, 0x1d43: 0x0040, 0x1d44: 0x0040, 0x1d45: 0x0040, | ||
1963 | 0x1d46: 0x0040, 0x1d47: 0x0040, 0x1d48: 0x0040, 0x1d49: 0x0040, 0x1d4a: 0x0040, 0x1d4b: 0x0040, | ||
1964 | 0x1d4c: 0x0040, 0x1d4d: 0x0040, 0x1d4e: 0x0040, 0x1d4f: 0x0040, 0x1d50: 0xc269, 0x1d51: 0xc289, | ||
1965 | 0x1d52: 0xc2a9, 0x1d53: 0xc2c9, 0x1d54: 0xc2e9, 0x1d55: 0xc309, 0x1d56: 0xc329, 0x1d57: 0xc349, | ||
1966 | 0x1d58: 0xc369, 0x1d59: 0xc389, 0x1d5a: 0xc3a9, 0x1d5b: 0xc3c9, 0x1d5c: 0xc3e9, 0x1d5d: 0xc409, | ||
1967 | 0x1d5e: 0xc429, 0x1d5f: 0xc449, 0x1d60: 0xc469, 0x1d61: 0xc489, 0x1d62: 0xc4a9, 0x1d63: 0xc4c9, | ||
1968 | 0x1d64: 0xc4e9, 0x1d65: 0xc509, 0x1d66: 0xc529, 0x1d67: 0xc549, 0x1d68: 0xc569, 0x1d69: 0xc589, | ||
1969 | 0x1d6a: 0xc5a9, 0x1d6b: 0xc5c9, 0x1d6c: 0xc5e9, 0x1d6d: 0xc609, 0x1d6e: 0xc629, 0x1d6f: 0xc649, | ||
1970 | 0x1d70: 0xc669, 0x1d71: 0xc689, 0x1d72: 0xc6a9, 0x1d73: 0xc6c9, 0x1d74: 0xc6e9, 0x1d75: 0xc709, | ||
1971 | 0x1d76: 0xc729, 0x1d77: 0xc749, 0x1d78: 0xc769, 0x1d79: 0xc789, 0x1d7a: 0xc7a9, 0x1d7b: 0xc7c9, | ||
1972 | 0x1d7c: 0x0040, 0x1d7d: 0x0040, 0x1d7e: 0x0040, 0x1d7f: 0x0040, | ||
1973 | // Block 0x76, offset 0x1d80 | ||
1974 | 0x1d80: 0xcaf9, 0x1d81: 0xcb19, 0x1d82: 0xcb39, 0x1d83: 0x8b1d, 0x1d84: 0xcb59, 0x1d85: 0xcb79, | ||
1975 | 0x1d86: 0xcb99, 0x1d87: 0xcbb9, 0x1d88: 0xcbd9, 0x1d89: 0xcbf9, 0x1d8a: 0xcc19, 0x1d8b: 0xcc39, | ||
1976 | 0x1d8c: 0xcc59, 0x1d8d: 0x8b3d, 0x1d8e: 0xcc79, 0x1d8f: 0xcc99, 0x1d90: 0xccb9, 0x1d91: 0xccd9, | ||
1977 | 0x1d92: 0x8b5d, 0x1d93: 0xccf9, 0x1d94: 0xcd19, 0x1d95: 0xc429, 0x1d96: 0x8b7d, 0x1d97: 0xcd39, | ||
1978 | 0x1d98: 0xcd59, 0x1d99: 0xcd79, 0x1d9a: 0xcd99, 0x1d9b: 0xcdb9, 0x1d9c: 0x8b9d, 0x1d9d: 0xcdd9, | ||
1979 | 0x1d9e: 0xcdf9, 0x1d9f: 0xce19, 0x1da0: 0xce39, 0x1da1: 0xce59, 0x1da2: 0xc789, 0x1da3: 0xce79, | ||
1980 | 0x1da4: 0xce99, 0x1da5: 0xceb9, 0x1da6: 0xced9, 0x1da7: 0xcef9, 0x1da8: 0xcf19, 0x1da9: 0xcf39, | ||
1981 | 0x1daa: 0xcf59, 0x1dab: 0xcf79, 0x1dac: 0xcf99, 0x1dad: 0xcfb9, 0x1dae: 0xcfd9, 0x1daf: 0xcff9, | ||
1982 | 0x1db0: 0xd019, 0x1db1: 0xd039, 0x1db2: 0xd039, 0x1db3: 0xd039, 0x1db4: 0x8bbd, 0x1db5: 0xd059, | ||
1983 | 0x1db6: 0xd079, 0x1db7: 0xd099, 0x1db8: 0x8bdd, 0x1db9: 0xd0b9, 0x1dba: 0xd0d9, 0x1dbb: 0xd0f9, | ||
1984 | 0x1dbc: 0xd119, 0x1dbd: 0xd139, 0x1dbe: 0xd159, 0x1dbf: 0xd179, | ||
1985 | // Block 0x77, offset 0x1dc0 | ||
1986 | 0x1dc0: 0xd199, 0x1dc1: 0xd1b9, 0x1dc2: 0xd1d9, 0x1dc3: 0xd1f9, 0x1dc4: 0xd219, 0x1dc5: 0xd239, | ||
1987 | 0x1dc6: 0xd239, 0x1dc7: 0xd259, 0x1dc8: 0xd279, 0x1dc9: 0xd299, 0x1dca: 0xd2b9, 0x1dcb: 0xd2d9, | ||
1988 | 0x1dcc: 0xd2f9, 0x1dcd: 0xd319, 0x1dce: 0xd339, 0x1dcf: 0xd359, 0x1dd0: 0xd379, 0x1dd1: 0xd399, | ||
1989 | 0x1dd2: 0xd3b9, 0x1dd3: 0xd3d9, 0x1dd4: 0xd3f9, 0x1dd5: 0xd419, 0x1dd6: 0xd439, 0x1dd7: 0xd459, | ||
1990 | 0x1dd8: 0xd479, 0x1dd9: 0x8bfd, 0x1dda: 0xd499, 0x1ddb: 0xd4b9, 0x1ddc: 0xd4d9, 0x1ddd: 0xc309, | ||
1991 | 0x1dde: 0xd4f9, 0x1ddf: 0xd519, 0x1de0: 0x8c1d, 0x1de1: 0x8c3d, 0x1de2: 0xd539, 0x1de3: 0xd559, | ||
1992 | 0x1de4: 0xd579, 0x1de5: 0xd599, 0x1de6: 0xd5b9, 0x1de7: 0xd5d9, 0x1de8: 0x0040, 0x1de9: 0xd5f9, | ||
1993 | 0x1dea: 0xd619, 0x1deb: 0xd619, 0x1dec: 0x8c5d, 0x1ded: 0xd639, 0x1dee: 0xd659, 0x1def: 0xd679, | ||
1994 | 0x1df0: 0xd699, 0x1df1: 0x8c7d, 0x1df2: 0xd6b9, 0x1df3: 0xd6d9, 0x1df4: 0x0040, 0x1df5: 0xd6f9, | ||
1995 | 0x1df6: 0xd719, 0x1df7: 0xd739, 0x1df8: 0xd759, 0x1df9: 0xd779, 0x1dfa: 0xd799, 0x1dfb: 0x8c9d, | ||
1996 | 0x1dfc: 0xd7b9, 0x1dfd: 0x8cbd, 0x1dfe: 0xd7d9, 0x1dff: 0xd7f9, | ||
1997 | // Block 0x78, offset 0x1e00 | ||
1998 | 0x1e00: 0xd819, 0x1e01: 0xd839, 0x1e02: 0xd859, 0x1e03: 0xd879, 0x1e04: 0xd899, 0x1e05: 0xd8b9, | ||
1999 | 0x1e06: 0xd8d9, 0x1e07: 0xd8f9, 0x1e08: 0xd919, 0x1e09: 0x8cdd, 0x1e0a: 0xd939, 0x1e0b: 0xd959, | ||
2000 | 0x1e0c: 0xd979, 0x1e0d: 0xd999, 0x1e0e: 0xd9b9, 0x1e0f: 0x8cfd, 0x1e10: 0xd9d9, 0x1e11: 0x8d1d, | ||
2001 | 0x1e12: 0x8d3d, 0x1e13: 0xd9f9, 0x1e14: 0xda19, 0x1e15: 0xda19, 0x1e16: 0xda39, 0x1e17: 0x8d5d, | ||
2002 | 0x1e18: 0x8d7d, 0x1e19: 0xda59, 0x1e1a: 0xda79, 0x1e1b: 0xda99, 0x1e1c: 0xdab9, 0x1e1d: 0xdad9, | ||
2003 | 0x1e1e: 0xdaf9, 0x1e1f: 0xdb19, 0x1e20: 0xdb39, 0x1e21: 0xdb59, 0x1e22: 0xdb79, 0x1e23: 0xdb99, | ||
2004 | 0x1e24: 0x8d9d, 0x1e25: 0xdbb9, 0x1e26: 0xdbd9, 0x1e27: 0xdbf9, 0x1e28: 0xdc19, 0x1e29: 0xdbf9, | ||
2005 | 0x1e2a: 0xdc39, 0x1e2b: 0xdc59, 0x1e2c: 0xdc79, 0x1e2d: 0xdc99, 0x1e2e: 0xdcb9, 0x1e2f: 0xdcd9, | ||
2006 | 0x1e30: 0xdcf9, 0x1e31: 0xdd19, 0x1e32: 0xdd39, 0x1e33: 0xdd59, 0x1e34: 0xdd79, 0x1e35: 0xdd99, | ||
2007 | 0x1e36: 0xddb9, 0x1e37: 0xddd9, 0x1e38: 0x8dbd, 0x1e39: 0xddf9, 0x1e3a: 0xde19, 0x1e3b: 0xde39, | ||
2008 | 0x1e3c: 0xde59, 0x1e3d: 0xde79, 0x1e3e: 0x8ddd, 0x1e3f: 0xde99, | ||
2009 | // Block 0x79, offset 0x1e40 | ||
2010 | 0x1e40: 0xe599, 0x1e41: 0xe5b9, 0x1e42: 0xe5d9, 0x1e43: 0xe5f9, 0x1e44: 0xe619, 0x1e45: 0xe639, | ||
2011 | 0x1e46: 0x8efd, 0x1e47: 0xe659, 0x1e48: 0xe679, 0x1e49: 0xe699, 0x1e4a: 0xe6b9, 0x1e4b: 0xe6d9, | ||
2012 | 0x1e4c: 0xe6f9, 0x1e4d: 0x8f1d, 0x1e4e: 0xe719, 0x1e4f: 0xe739, 0x1e50: 0x8f3d, 0x1e51: 0x8f5d, | ||
2013 | 0x1e52: 0xe759, 0x1e53: 0xe779, 0x1e54: 0xe799, 0x1e55: 0xe7b9, 0x1e56: 0xe7d9, 0x1e57: 0xe7f9, | ||
2014 | 0x1e58: 0xe819, 0x1e59: 0xe839, 0x1e5a: 0xe859, 0x1e5b: 0x8f7d, 0x1e5c: 0xe879, 0x1e5d: 0x8f9d, | ||
2015 | 0x1e5e: 0xe899, 0x1e5f: 0x0040, 0x1e60: 0xe8b9, 0x1e61: 0xe8d9, 0x1e62: 0xe8f9, 0x1e63: 0x8fbd, | ||
2016 | 0x1e64: 0xe919, 0x1e65: 0xe939, 0x1e66: 0x8fdd, 0x1e67: 0x8ffd, 0x1e68: 0xe959, 0x1e69: 0xe979, | ||
2017 | 0x1e6a: 0xe999, 0x1e6b: 0xe9b9, 0x1e6c: 0xe9d9, 0x1e6d: 0xe9d9, 0x1e6e: 0xe9f9, 0x1e6f: 0xea19, | ||
2018 | 0x1e70: 0xea39, 0x1e71: 0xea59, 0x1e72: 0xea79, 0x1e73: 0xea99, 0x1e74: 0xeab9, 0x1e75: 0x901d, | ||
2019 | 0x1e76: 0xead9, 0x1e77: 0x903d, 0x1e78: 0xeaf9, 0x1e79: 0x905d, 0x1e7a: 0xeb19, 0x1e7b: 0x907d, | ||
2020 | 0x1e7c: 0x909d, 0x1e7d: 0x90bd, 0x1e7e: 0xeb39, 0x1e7f: 0xeb59, | ||
2021 | // Block 0x7a, offset 0x1e80 | ||
2022 | 0x1e80: 0xeb79, 0x1e81: 0x90dd, 0x1e82: 0x90fd, 0x1e83: 0x911d, 0x1e84: 0x913d, 0x1e85: 0xeb99, | ||
2023 | 0x1e86: 0xebb9, 0x1e87: 0xebb9, 0x1e88: 0xebd9, 0x1e89: 0xebf9, 0x1e8a: 0xec19, 0x1e8b: 0xec39, | ||
2024 | 0x1e8c: 0xec59, 0x1e8d: 0x915d, 0x1e8e: 0xec79, 0x1e8f: 0xec99, 0x1e90: 0xecb9, 0x1e91: 0xecd9, | ||
2025 | 0x1e92: 0x917d, 0x1e93: 0xecf9, 0x1e94: 0x919d, 0x1e95: 0x91bd, 0x1e96: 0xed19, 0x1e97: 0xed39, | ||
2026 | 0x1e98: 0xed59, 0x1e99: 0xed79, 0x1e9a: 0xed99, 0x1e9b: 0xedb9, 0x1e9c: 0x91dd, 0x1e9d: 0x91fd, | ||
2027 | 0x1e9e: 0x921d, 0x1e9f: 0x0040, 0x1ea0: 0xedd9, 0x1ea1: 0x923d, 0x1ea2: 0xedf9, 0x1ea3: 0xee19, | ||
2028 | 0x1ea4: 0xee39, 0x1ea5: 0x925d, 0x1ea6: 0xee59, 0x1ea7: 0xee79, 0x1ea8: 0xee99, 0x1ea9: 0xeeb9, | ||
2029 | 0x1eaa: 0xeed9, 0x1eab: 0x927d, 0x1eac: 0xeef9, 0x1ead: 0xef19, 0x1eae: 0xef39, 0x1eaf: 0xef59, | ||
2030 | 0x1eb0: 0xef79, 0x1eb1: 0xef99, 0x1eb2: 0x929d, 0x1eb3: 0x92bd, 0x1eb4: 0xefb9, 0x1eb5: 0x92dd, | ||
2031 | 0x1eb6: 0xefd9, 0x1eb7: 0x92fd, 0x1eb8: 0xeff9, 0x1eb9: 0xf019, 0x1eba: 0xf039, 0x1ebb: 0x931d, | ||
2032 | 0x1ebc: 0x933d, 0x1ebd: 0xf059, 0x1ebe: 0x935d, 0x1ebf: 0xf079, | ||
2033 | // Block 0x7b, offset 0x1ec0 | ||
2034 | 0x1ec0: 0xf6b9, 0x1ec1: 0xf6d9, 0x1ec2: 0xf6f9, 0x1ec3: 0xf719, 0x1ec4: 0xf739, 0x1ec5: 0x951d, | ||
2035 | 0x1ec6: 0xf759, 0x1ec7: 0xf779, 0x1ec8: 0xf799, 0x1ec9: 0xf7b9, 0x1eca: 0xf7d9, 0x1ecb: 0x953d, | ||
2036 | 0x1ecc: 0x955d, 0x1ecd: 0xf7f9, 0x1ece: 0xf819, 0x1ecf: 0xf839, 0x1ed0: 0xf859, 0x1ed1: 0xf879, | ||
2037 | 0x1ed2: 0xf899, 0x1ed3: 0x957d, 0x1ed4: 0xf8b9, 0x1ed5: 0xf8d9, 0x1ed6: 0xf8f9, 0x1ed7: 0xf919, | ||
2038 | 0x1ed8: 0x959d, 0x1ed9: 0x95bd, 0x1eda: 0xf939, 0x1edb: 0xf959, 0x1edc: 0xf979, 0x1edd: 0x95dd, | ||
2039 | 0x1ede: 0xf999, 0x1edf: 0xf9b9, 0x1ee0: 0x6815, 0x1ee1: 0x95fd, 0x1ee2: 0xf9d9, 0x1ee3: 0xf9f9, | ||
2040 | 0x1ee4: 0xfa19, 0x1ee5: 0x961d, 0x1ee6: 0xfa39, 0x1ee7: 0xfa59, 0x1ee8: 0xfa79, 0x1ee9: 0xfa99, | ||
2041 | 0x1eea: 0xfab9, 0x1eeb: 0xfad9, 0x1eec: 0xfaf9, 0x1eed: 0x963d, 0x1eee: 0xfb19, 0x1eef: 0xfb39, | ||
2042 | 0x1ef0: 0xfb59, 0x1ef1: 0x965d, 0x1ef2: 0xfb79, 0x1ef3: 0xfb99, 0x1ef4: 0xfbb9, 0x1ef5: 0xfbd9, | ||
2043 | 0x1ef6: 0x7b35, 0x1ef7: 0x967d, 0x1ef8: 0xfbf9, 0x1ef9: 0xfc19, 0x1efa: 0xfc39, 0x1efb: 0x969d, | ||
2044 | 0x1efc: 0xfc59, 0x1efd: 0x96bd, 0x1efe: 0xfc79, 0x1eff: 0xfc79, | ||
2045 | // Block 0x7c, offset 0x1f00 | ||
2046 | 0x1f00: 0xfc99, 0x1f01: 0x96dd, 0x1f02: 0xfcb9, 0x1f03: 0xfcd9, 0x1f04: 0xfcf9, 0x1f05: 0xfd19, | ||
2047 | 0x1f06: 0xfd39, 0x1f07: 0xfd59, 0x1f08: 0xfd79, 0x1f09: 0x96fd, 0x1f0a: 0xfd99, 0x1f0b: 0xfdb9, | ||
2048 | 0x1f0c: 0xfdd9, 0x1f0d: 0xfdf9, 0x1f0e: 0xfe19, 0x1f0f: 0xfe39, 0x1f10: 0x971d, 0x1f11: 0xfe59, | ||
2049 | 0x1f12: 0x973d, 0x1f13: 0x975d, 0x1f14: 0x977d, 0x1f15: 0xfe79, 0x1f16: 0xfe99, 0x1f17: 0xfeb9, | ||
2050 | 0x1f18: 0xfed9, 0x1f19: 0xfef9, 0x1f1a: 0xff19, 0x1f1b: 0xff39, 0x1f1c: 0xff59, 0x1f1d: 0x979d, | ||
2051 | 0x1f1e: 0x0040, 0x1f1f: 0x0040, 0x1f20: 0x0040, 0x1f21: 0x0040, 0x1f22: 0x0040, 0x1f23: 0x0040, | ||
2052 | 0x1f24: 0x0040, 0x1f25: 0x0040, 0x1f26: 0x0040, 0x1f27: 0x0040, 0x1f28: 0x0040, 0x1f29: 0x0040, | ||
2053 | 0x1f2a: 0x0040, 0x1f2b: 0x0040, 0x1f2c: 0x0040, 0x1f2d: 0x0040, 0x1f2e: 0x0040, 0x1f2f: 0x0040, | ||
2054 | 0x1f30: 0x0040, 0x1f31: 0x0040, 0x1f32: 0x0040, 0x1f33: 0x0040, 0x1f34: 0x0040, 0x1f35: 0x0040, | ||
2055 | 0x1f36: 0x0040, 0x1f37: 0x0040, 0x1f38: 0x0040, 0x1f39: 0x0040, 0x1f3a: 0x0040, 0x1f3b: 0x0040, | ||
2056 | 0x1f3c: 0x0040, 0x1f3d: 0x0040, 0x1f3e: 0x0040, 0x1f3f: 0x0040, | ||
2057 | } | ||
2058 | |||
2059 | // idnaIndex: 35 blocks, 2240 entries, 4480 bytes | ||
2060 | // Block 0 is the zero block. | ||
2061 | var idnaIndex = [2240]uint16{ | ||
2062 | // Block 0x0, offset 0x0 | ||
2063 | // Block 0x1, offset 0x40 | ||
2064 | // Block 0x2, offset 0x80 | ||
2065 | // Block 0x3, offset 0xc0 | ||
2066 | 0xc2: 0x01, 0xc3: 0x7b, 0xc4: 0x02, 0xc5: 0x03, 0xc6: 0x04, 0xc7: 0x05, | ||
2067 | 0xc8: 0x06, 0xc9: 0x7c, 0xca: 0x7d, 0xcb: 0x07, 0xcc: 0x7e, 0xcd: 0x08, 0xce: 0x09, 0xcf: 0x0a, | ||
2068 | 0xd0: 0x7f, 0xd1: 0x0b, 0xd2: 0x0c, 0xd3: 0x0d, 0xd4: 0x0e, 0xd5: 0x80, 0xd6: 0x81, 0xd7: 0x82, | ||
2069 | 0xd8: 0x0f, 0xd9: 0x83, 0xda: 0x84, 0xdb: 0x10, 0xdc: 0x11, 0xdd: 0x85, 0xde: 0x86, 0xdf: 0x87, | ||
2070 | 0xe0: 0x02, 0xe1: 0x03, 0xe2: 0x04, 0xe3: 0x05, 0xe4: 0x06, 0xe5: 0x07, 0xe6: 0x07, 0xe7: 0x07, | ||
2071 | 0xe8: 0x07, 0xe9: 0x08, 0xea: 0x09, 0xeb: 0x07, 0xec: 0x07, 0xed: 0x0a, 0xee: 0x0b, 0xef: 0x0c, | ||
2072 | 0xf0: 0x1c, 0xf1: 0x1d, 0xf2: 0x1d, 0xf3: 0x1f, 0xf4: 0x20, | ||
2073 | // Block 0x4, offset 0x100 | ||
2074 | 0x120: 0x88, 0x121: 0x89, 0x122: 0x8a, 0x123: 0x8b, 0x124: 0x8c, 0x125: 0x12, 0x126: 0x13, 0x127: 0x14, | ||
2075 | 0x128: 0x15, 0x129: 0x16, 0x12a: 0x17, 0x12b: 0x18, 0x12c: 0x19, 0x12d: 0x1a, 0x12e: 0x1b, 0x12f: 0x8d, | ||
2076 | 0x130: 0x8e, 0x131: 0x1c, 0x132: 0x1d, 0x133: 0x1e, 0x134: 0x8f, 0x135: 0x1f, 0x136: 0x90, 0x137: 0x91, | ||
2077 | 0x138: 0x92, 0x139: 0x93, 0x13a: 0x20, 0x13b: 0x94, 0x13c: 0x95, 0x13d: 0x21, 0x13e: 0x22, 0x13f: 0x96, | ||
2078 | // Block 0x5, offset 0x140 | ||
2079 | 0x140: 0x97, 0x141: 0x98, 0x142: 0x99, 0x143: 0x9a, 0x144: 0x9b, 0x145: 0x9c, 0x146: 0x9b, 0x147: 0x9b, | ||
2080 | 0x148: 0x9d, 0x149: 0x9e, 0x14a: 0x9f, 0x14b: 0xa0, 0x14c: 0xa1, 0x14d: 0xa2, 0x14e: 0xa3, 0x14f: 0xa4, | ||
2081 | 0x150: 0xa5, 0x151: 0x9d, 0x152: 0x9d, 0x153: 0x9d, 0x154: 0x9d, 0x155: 0x9d, 0x156: 0x9d, 0x157: 0x9d, | ||
2082 | 0x158: 0x9d, 0x159: 0xa6, 0x15a: 0xa7, 0x15b: 0xa8, 0x15c: 0xa9, 0x15d: 0xaa, 0x15e: 0xab, 0x15f: 0xac, | ||
2083 | 0x160: 0xad, 0x161: 0xae, 0x162: 0xaf, 0x163: 0xb0, 0x164: 0xb1, 0x165: 0xb2, 0x166: 0xb3, 0x167: 0xb4, | ||
2084 | 0x168: 0xb5, 0x169: 0xb6, 0x16a: 0xb7, 0x16b: 0xb8, 0x16c: 0xb9, 0x16d: 0xba, 0x16e: 0xbb, 0x16f: 0xbc, | ||
2085 | 0x170: 0xbd, 0x171: 0xbe, 0x172: 0xbf, 0x173: 0xc0, 0x174: 0x23, 0x175: 0x24, 0x176: 0x25, 0x177: 0xc1, | ||
2086 | 0x178: 0x26, 0x179: 0x26, 0x17a: 0x27, 0x17b: 0x26, 0x17c: 0xc2, 0x17d: 0x28, 0x17e: 0x29, 0x17f: 0x2a, | ||
2087 | // Block 0x6, offset 0x180 | ||
2088 | 0x180: 0x2b, 0x181: 0x2c, 0x182: 0x2d, 0x183: 0xc3, 0x184: 0x2e, 0x185: 0x2f, 0x186: 0xc4, 0x187: 0x9b, | ||
2089 | 0x188: 0xc5, 0x189: 0xc6, 0x18a: 0x9b, 0x18b: 0x9b, 0x18c: 0xc7, 0x18d: 0x9b, 0x18e: 0x9b, 0x18f: 0xc8, | ||
2090 | 0x190: 0xc9, 0x191: 0x30, 0x192: 0x31, 0x193: 0x32, 0x194: 0x9b, 0x195: 0x9b, 0x196: 0x9b, 0x197: 0x9b, | ||
2091 | 0x198: 0x9b, 0x199: 0x9b, 0x19a: 0x9b, 0x19b: 0x9b, 0x19c: 0x9b, 0x19d: 0x9b, 0x19e: 0x9b, 0x19f: 0x9b, | ||
2092 | 0x1a0: 0x9b, 0x1a1: 0x9b, 0x1a2: 0x9b, 0x1a3: 0x9b, 0x1a4: 0x9b, 0x1a5: 0x9b, 0x1a6: 0x9b, 0x1a7: 0x9b, | ||
2093 | 0x1a8: 0xca, 0x1a9: 0xcb, 0x1aa: 0x9b, 0x1ab: 0xcc, 0x1ac: 0x9b, 0x1ad: 0xcd, 0x1ae: 0xce, 0x1af: 0xcf, | ||
2094 | 0x1b0: 0xd0, 0x1b1: 0x33, 0x1b2: 0x26, 0x1b3: 0x34, 0x1b4: 0xd1, 0x1b5: 0xd2, 0x1b6: 0xd3, 0x1b7: 0xd4, | ||
2095 | 0x1b8: 0xd5, 0x1b9: 0xd6, 0x1ba: 0xd7, 0x1bb: 0xd8, 0x1bc: 0xd9, 0x1bd: 0xda, 0x1be: 0xdb, 0x1bf: 0x35, | ||
2096 | // Block 0x7, offset 0x1c0 | ||
2097 | 0x1c0: 0x36, 0x1c1: 0xdc, 0x1c2: 0xdd, 0x1c3: 0xde, 0x1c4: 0xdf, 0x1c5: 0x37, 0x1c6: 0x38, 0x1c7: 0xe0, | ||
2098 | 0x1c8: 0xe1, 0x1c9: 0x39, 0x1ca: 0x3a, 0x1cb: 0x3b, 0x1cc: 0x3c, 0x1cd: 0x3d, 0x1ce: 0x3e, 0x1cf: 0x3f, | ||
2099 | 0x1d0: 0x9d, 0x1d1: 0x9d, 0x1d2: 0x9d, 0x1d3: 0x9d, 0x1d4: 0x9d, 0x1d5: 0x9d, 0x1d6: 0x9d, 0x1d7: 0x9d, | ||
2100 | 0x1d8: 0x9d, 0x1d9: 0x9d, 0x1da: 0x9d, 0x1db: 0x9d, 0x1dc: 0x9d, 0x1dd: 0x9d, 0x1de: 0x9d, 0x1df: 0x9d, | ||
2101 | 0x1e0: 0x9d, 0x1e1: 0x9d, 0x1e2: 0x9d, 0x1e3: 0x9d, 0x1e4: 0x9d, 0x1e5: 0x9d, 0x1e6: 0x9d, 0x1e7: 0x9d, | ||
2102 | 0x1e8: 0x9d, 0x1e9: 0x9d, 0x1ea: 0x9d, 0x1eb: 0x9d, 0x1ec: 0x9d, 0x1ed: 0x9d, 0x1ee: 0x9d, 0x1ef: 0x9d, | ||
2103 | 0x1f0: 0x9d, 0x1f1: 0x9d, 0x1f2: 0x9d, 0x1f3: 0x9d, 0x1f4: 0x9d, 0x1f5: 0x9d, 0x1f6: 0x9d, 0x1f7: 0x9d, | ||
2104 | 0x1f8: 0x9d, 0x1f9: 0x9d, 0x1fa: 0x9d, 0x1fb: 0x9d, 0x1fc: 0x9d, 0x1fd: 0x9d, 0x1fe: 0x9d, 0x1ff: 0x9d, | ||
2105 | // Block 0x8, offset 0x200 | ||
2106 | 0x200: 0x9d, 0x201: 0x9d, 0x202: 0x9d, 0x203: 0x9d, 0x204: 0x9d, 0x205: 0x9d, 0x206: 0x9d, 0x207: 0x9d, | ||
2107 | 0x208: 0x9d, 0x209: 0x9d, 0x20a: 0x9d, 0x20b: 0x9d, 0x20c: 0x9d, 0x20d: 0x9d, 0x20e: 0x9d, 0x20f: 0x9d, | ||
2108 | 0x210: 0x9d, 0x211: 0x9d, 0x212: 0x9d, 0x213: 0x9d, 0x214: 0x9d, 0x215: 0x9d, 0x216: 0x9d, 0x217: 0x9d, | ||
2109 | 0x218: 0x9d, 0x219: 0x9d, 0x21a: 0x9d, 0x21b: 0x9d, 0x21c: 0x9d, 0x21d: 0x9d, 0x21e: 0x9d, 0x21f: 0x9d, | ||
2110 | 0x220: 0x9d, 0x221: 0x9d, 0x222: 0x9d, 0x223: 0x9d, 0x224: 0x9d, 0x225: 0x9d, 0x226: 0x9d, 0x227: 0x9d, | ||
2111 | 0x228: 0x9d, 0x229: 0x9d, 0x22a: 0x9d, 0x22b: 0x9d, 0x22c: 0x9d, 0x22d: 0x9d, 0x22e: 0x9d, 0x22f: 0x9d, | ||
2112 | 0x230: 0x9d, 0x231: 0x9d, 0x232: 0x9d, 0x233: 0x9d, 0x234: 0x9d, 0x235: 0x9d, 0x236: 0xb0, 0x237: 0x9b, | ||
2113 | 0x238: 0x9d, 0x239: 0x9d, 0x23a: 0x9d, 0x23b: 0x9d, 0x23c: 0x9d, 0x23d: 0x9d, 0x23e: 0x9d, 0x23f: 0x9d, | ||
2114 | // Block 0x9, offset 0x240 | ||
2115 | 0x240: 0x9d, 0x241: 0x9d, 0x242: 0x9d, 0x243: 0x9d, 0x244: 0x9d, 0x245: 0x9d, 0x246: 0x9d, 0x247: 0x9d, | ||
2116 | 0x248: 0x9d, 0x249: 0x9d, 0x24a: 0x9d, 0x24b: 0x9d, 0x24c: 0x9d, 0x24d: 0x9d, 0x24e: 0x9d, 0x24f: 0x9d, | ||
2117 | 0x250: 0x9d, 0x251: 0x9d, 0x252: 0x9d, 0x253: 0x9d, 0x254: 0x9d, 0x255: 0x9d, 0x256: 0x9d, 0x257: 0x9d, | ||
2118 | 0x258: 0x9d, 0x259: 0x9d, 0x25a: 0x9d, 0x25b: 0x9d, 0x25c: 0x9d, 0x25d: 0x9d, 0x25e: 0x9d, 0x25f: 0x9d, | ||
2119 | 0x260: 0x9d, 0x261: 0x9d, 0x262: 0x9d, 0x263: 0x9d, 0x264: 0x9d, 0x265: 0x9d, 0x266: 0x9d, 0x267: 0x9d, | ||
2120 | 0x268: 0x9d, 0x269: 0x9d, 0x26a: 0x9d, 0x26b: 0x9d, 0x26c: 0x9d, 0x26d: 0x9d, 0x26e: 0x9d, 0x26f: 0x9d, | ||
2121 | 0x270: 0x9d, 0x271: 0x9d, 0x272: 0x9d, 0x273: 0x9d, 0x274: 0x9d, 0x275: 0x9d, 0x276: 0x9d, 0x277: 0x9d, | ||
2122 | 0x278: 0x9d, 0x279: 0x9d, 0x27a: 0x9d, 0x27b: 0x9d, 0x27c: 0x9d, 0x27d: 0x9d, 0x27e: 0x9d, 0x27f: 0x9d, | ||
2123 | // Block 0xa, offset 0x280 | ||
2124 | 0x280: 0x9d, 0x281: 0x9d, 0x282: 0x9d, 0x283: 0x9d, 0x284: 0x9d, 0x285: 0x9d, 0x286: 0x9d, 0x287: 0x9d, | ||
2125 | 0x288: 0x9d, 0x289: 0x9d, 0x28a: 0x9d, 0x28b: 0x9d, 0x28c: 0x9d, 0x28d: 0x9d, 0x28e: 0x9d, 0x28f: 0x9d, | ||
2126 | 0x290: 0x9d, 0x291: 0x9d, 0x292: 0x9d, 0x293: 0x9d, 0x294: 0x9d, 0x295: 0x9d, 0x296: 0x9d, 0x297: 0x9d, | ||
2127 | 0x298: 0x9d, 0x299: 0x9d, 0x29a: 0x9d, 0x29b: 0x9d, 0x29c: 0x9d, 0x29d: 0x9d, 0x29e: 0x9d, 0x29f: 0x9d, | ||
2128 | 0x2a0: 0x9d, 0x2a1: 0x9d, 0x2a2: 0x9d, 0x2a3: 0x9d, 0x2a4: 0x9d, 0x2a5: 0x9d, 0x2a6: 0x9d, 0x2a7: 0x9d, | ||
2129 | 0x2a8: 0x9d, 0x2a9: 0x9d, 0x2aa: 0x9d, 0x2ab: 0x9d, 0x2ac: 0x9d, 0x2ad: 0x9d, 0x2ae: 0x9d, 0x2af: 0x9d, | ||
2130 | 0x2b0: 0x9d, 0x2b1: 0x9d, 0x2b2: 0x9d, 0x2b3: 0x9d, 0x2b4: 0x9d, 0x2b5: 0x9d, 0x2b6: 0x9d, 0x2b7: 0x9d, | ||
2131 | 0x2b8: 0x9d, 0x2b9: 0x9d, 0x2ba: 0x9d, 0x2bb: 0x9d, 0x2bc: 0x9d, 0x2bd: 0x9d, 0x2be: 0x9d, 0x2bf: 0xe2, | ||
2132 | // Block 0xb, offset 0x2c0 | ||
2133 | 0x2c0: 0x9d, 0x2c1: 0x9d, 0x2c2: 0x9d, 0x2c3: 0x9d, 0x2c4: 0x9d, 0x2c5: 0x9d, 0x2c6: 0x9d, 0x2c7: 0x9d, | ||
2134 | 0x2c8: 0x9d, 0x2c9: 0x9d, 0x2ca: 0x9d, 0x2cb: 0x9d, 0x2cc: 0x9d, 0x2cd: 0x9d, 0x2ce: 0x9d, 0x2cf: 0x9d, | ||
2135 | 0x2d0: 0x9d, 0x2d1: 0x9d, 0x2d2: 0xe3, 0x2d3: 0xe4, 0x2d4: 0x9d, 0x2d5: 0x9d, 0x2d6: 0x9d, 0x2d7: 0x9d, | ||
2136 | 0x2d8: 0xe5, 0x2d9: 0x40, 0x2da: 0x41, 0x2db: 0xe6, 0x2dc: 0x42, 0x2dd: 0x43, 0x2de: 0x44, 0x2df: 0xe7, | ||
2137 | 0x2e0: 0xe8, 0x2e1: 0xe9, 0x2e2: 0xea, 0x2e3: 0xeb, 0x2e4: 0xec, 0x2e5: 0xed, 0x2e6: 0xee, 0x2e7: 0xef, | ||
2138 | 0x2e8: 0xf0, 0x2e9: 0xf1, 0x2ea: 0xf2, 0x2eb: 0xf3, 0x2ec: 0xf4, 0x2ed: 0xf5, 0x2ee: 0xf6, 0x2ef: 0xf7, | ||
2139 | 0x2f0: 0x9d, 0x2f1: 0x9d, 0x2f2: 0x9d, 0x2f3: 0x9d, 0x2f4: 0x9d, 0x2f5: 0x9d, 0x2f6: 0x9d, 0x2f7: 0x9d, | ||
2140 | 0x2f8: 0x9d, 0x2f9: 0x9d, 0x2fa: 0x9d, 0x2fb: 0x9d, 0x2fc: 0x9d, 0x2fd: 0x9d, 0x2fe: 0x9d, 0x2ff: 0x9d, | ||
2141 | // Block 0xc, offset 0x300 | ||
2142 | 0x300: 0x9d, 0x301: 0x9d, 0x302: 0x9d, 0x303: 0x9d, 0x304: 0x9d, 0x305: 0x9d, 0x306: 0x9d, 0x307: 0x9d, | ||
2143 | 0x308: 0x9d, 0x309: 0x9d, 0x30a: 0x9d, 0x30b: 0x9d, 0x30c: 0x9d, 0x30d: 0x9d, 0x30e: 0x9d, 0x30f: 0x9d, | ||
2144 | 0x310: 0x9d, 0x311: 0x9d, 0x312: 0x9d, 0x313: 0x9d, 0x314: 0x9d, 0x315: 0x9d, 0x316: 0x9d, 0x317: 0x9d, | ||
2145 | 0x318: 0x9d, 0x319: 0x9d, 0x31a: 0x9d, 0x31b: 0x9d, 0x31c: 0x9d, 0x31d: 0x9d, 0x31e: 0xf8, 0x31f: 0xf9, | ||
2146 | // Block 0xd, offset 0x340 | ||
2147 | 0x340: 0xb8, 0x341: 0xb8, 0x342: 0xb8, 0x343: 0xb8, 0x344: 0xb8, 0x345: 0xb8, 0x346: 0xb8, 0x347: 0xb8, | ||
2148 | 0x348: 0xb8, 0x349: 0xb8, 0x34a: 0xb8, 0x34b: 0xb8, 0x34c: 0xb8, 0x34d: 0xb8, 0x34e: 0xb8, 0x34f: 0xb8, | ||
2149 | 0x350: 0xb8, 0x351: 0xb8, 0x352: 0xb8, 0x353: 0xb8, 0x354: 0xb8, 0x355: 0xb8, 0x356: 0xb8, 0x357: 0xb8, | ||
2150 | 0x358: 0xb8, 0x359: 0xb8, 0x35a: 0xb8, 0x35b: 0xb8, 0x35c: 0xb8, 0x35d: 0xb8, 0x35e: 0xb8, 0x35f: 0xb8, | ||
2151 | 0x360: 0xb8, 0x361: 0xb8, 0x362: 0xb8, 0x363: 0xb8, 0x364: 0xb8, 0x365: 0xb8, 0x366: 0xb8, 0x367: 0xb8, | ||
2152 | 0x368: 0xb8, 0x369: 0xb8, 0x36a: 0xb8, 0x36b: 0xb8, 0x36c: 0xb8, 0x36d: 0xb8, 0x36e: 0xb8, 0x36f: 0xb8, | ||
2153 | 0x370: 0xb8, 0x371: 0xb8, 0x372: 0xb8, 0x373: 0xb8, 0x374: 0xb8, 0x375: 0xb8, 0x376: 0xb8, 0x377: 0xb8, | ||
2154 | 0x378: 0xb8, 0x379: 0xb8, 0x37a: 0xb8, 0x37b: 0xb8, 0x37c: 0xb8, 0x37d: 0xb8, 0x37e: 0xb8, 0x37f: 0xb8, | ||
2155 | // Block 0xe, offset 0x380 | ||
2156 | 0x380: 0xb8, 0x381: 0xb8, 0x382: 0xb8, 0x383: 0xb8, 0x384: 0xb8, 0x385: 0xb8, 0x386: 0xb8, 0x387: 0xb8, | ||
2157 | 0x388: 0xb8, 0x389: 0xb8, 0x38a: 0xb8, 0x38b: 0xb8, 0x38c: 0xb8, 0x38d: 0xb8, 0x38e: 0xb8, 0x38f: 0xb8, | ||
2158 | 0x390: 0xb8, 0x391: 0xb8, 0x392: 0xb8, 0x393: 0xb8, 0x394: 0xb8, 0x395: 0xb8, 0x396: 0xb8, 0x397: 0xb8, | ||
2159 | 0x398: 0xb8, 0x399: 0xb8, 0x39a: 0xb8, 0x39b: 0xb8, 0x39c: 0xb8, 0x39d: 0xb8, 0x39e: 0xb8, 0x39f: 0xb8, | ||
2160 | 0x3a0: 0xb8, 0x3a1: 0xb8, 0x3a2: 0xb8, 0x3a3: 0xb8, 0x3a4: 0xfa, 0x3a5: 0xfb, 0x3a6: 0xfc, 0x3a7: 0xfd, | ||
2161 | 0x3a8: 0x45, 0x3a9: 0xfe, 0x3aa: 0xff, 0x3ab: 0x46, 0x3ac: 0x47, 0x3ad: 0x48, 0x3ae: 0x49, 0x3af: 0x4a, | ||
2162 | 0x3b0: 0x100, 0x3b1: 0x4b, 0x3b2: 0x4c, 0x3b3: 0x4d, 0x3b4: 0x4e, 0x3b5: 0x4f, 0x3b6: 0x101, 0x3b7: 0x50, | ||
2163 | 0x3b8: 0x51, 0x3b9: 0x52, 0x3ba: 0x53, 0x3bb: 0x54, 0x3bc: 0x55, 0x3bd: 0x56, 0x3be: 0x57, 0x3bf: 0x58, | ||
2164 | // Block 0xf, offset 0x3c0 | ||
2165 | 0x3c0: 0x102, 0x3c1: 0x103, 0x3c2: 0x9d, 0x3c3: 0x104, 0x3c4: 0x105, 0x3c5: 0x9b, 0x3c6: 0x106, 0x3c7: 0x107, | ||
2166 | 0x3c8: 0xb8, 0x3c9: 0xb8, 0x3ca: 0x108, 0x3cb: 0x109, 0x3cc: 0x10a, 0x3cd: 0x10b, 0x3ce: 0x10c, 0x3cf: 0x10d, | ||
2167 | 0x3d0: 0x10e, 0x3d1: 0x9d, 0x3d2: 0x10f, 0x3d3: 0x110, 0x3d4: 0x111, 0x3d5: 0x112, 0x3d6: 0xb8, 0x3d7: 0xb8, | ||
2168 | 0x3d8: 0x9d, 0x3d9: 0x9d, 0x3da: 0x9d, 0x3db: 0x9d, 0x3dc: 0x113, 0x3dd: 0x114, 0x3de: 0xb8, 0x3df: 0xb8, | ||
2169 | 0x3e0: 0x115, 0x3e1: 0x116, 0x3e2: 0x117, 0x3e3: 0x118, 0x3e4: 0x119, 0x3e5: 0xb8, 0x3e6: 0x11a, 0x3e7: 0x11b, | ||
2170 | 0x3e8: 0x11c, 0x3e9: 0x11d, 0x3ea: 0x11e, 0x3eb: 0x59, 0x3ec: 0x11f, 0x3ed: 0x120, 0x3ee: 0x5a, 0x3ef: 0xb8, | ||
2171 | 0x3f0: 0x9d, 0x3f1: 0x121, 0x3f2: 0x122, 0x3f3: 0x123, 0x3f4: 0xb8, 0x3f5: 0xb8, 0x3f6: 0xb8, 0x3f7: 0xb8, | ||
2172 | 0x3f8: 0xb8, 0x3f9: 0x124, 0x3fa: 0xb8, 0x3fb: 0xb8, 0x3fc: 0xb8, 0x3fd: 0xb8, 0x3fe: 0xb8, 0x3ff: 0xb8, | ||
2173 | // Block 0x10, offset 0x400 | ||
2174 | 0x400: 0x125, 0x401: 0x126, 0x402: 0x127, 0x403: 0x128, 0x404: 0x129, 0x405: 0x12a, 0x406: 0x12b, 0x407: 0x12c, | ||
2175 | 0x408: 0x12d, 0x409: 0xb8, 0x40a: 0x12e, 0x40b: 0x12f, 0x40c: 0x5b, 0x40d: 0x5c, 0x40e: 0xb8, 0x40f: 0xb8, | ||
2176 | 0x410: 0x130, 0x411: 0x131, 0x412: 0x132, 0x413: 0x133, 0x414: 0xb8, 0x415: 0xb8, 0x416: 0x134, 0x417: 0x135, | ||
2177 | 0x418: 0x136, 0x419: 0x137, 0x41a: 0x138, 0x41b: 0x139, 0x41c: 0x13a, 0x41d: 0xb8, 0x41e: 0xb8, 0x41f: 0xb8, | ||
2178 | 0x420: 0xb8, 0x421: 0xb8, 0x422: 0x13b, 0x423: 0x13c, 0x424: 0xb8, 0x425: 0xb8, 0x426: 0xb8, 0x427: 0xb8, | ||
2179 | 0x428: 0xb8, 0x429: 0xb8, 0x42a: 0xb8, 0x42b: 0x13d, 0x42c: 0xb8, 0x42d: 0xb8, 0x42e: 0xb8, 0x42f: 0xb8, | ||
2180 | 0x430: 0x13e, 0x431: 0x13f, 0x432: 0x140, 0x433: 0xb8, 0x434: 0xb8, 0x435: 0xb8, 0x436: 0xb8, 0x437: 0xb8, | ||
2181 | 0x438: 0xb8, 0x439: 0xb8, 0x43a: 0xb8, 0x43b: 0xb8, 0x43c: 0xb8, 0x43d: 0xb8, 0x43e: 0xb8, 0x43f: 0xb8, | ||
2182 | // Block 0x11, offset 0x440 | ||
2183 | 0x440: 0x9d, 0x441: 0x9d, 0x442: 0x9d, 0x443: 0x9d, 0x444: 0x9d, 0x445: 0x9d, 0x446: 0x9d, 0x447: 0x9d, | ||
2184 | 0x448: 0x9d, 0x449: 0x9d, 0x44a: 0x9d, 0x44b: 0x9d, 0x44c: 0x9d, 0x44d: 0x9d, 0x44e: 0x141, 0x44f: 0xb8, | ||
2185 | 0x450: 0x9b, 0x451: 0x142, 0x452: 0x9d, 0x453: 0x9d, 0x454: 0x9d, 0x455: 0x143, 0x456: 0xb8, 0x457: 0xb8, | ||
2186 | 0x458: 0xb8, 0x459: 0xb8, 0x45a: 0xb8, 0x45b: 0xb8, 0x45c: 0xb8, 0x45d: 0xb8, 0x45e: 0xb8, 0x45f: 0xb8, | ||
2187 | 0x460: 0xb8, 0x461: 0xb8, 0x462: 0xb8, 0x463: 0xb8, 0x464: 0xb8, 0x465: 0xb8, 0x466: 0xb8, 0x467: 0xb8, | ||
2188 | 0x468: 0xb8, 0x469: 0xb8, 0x46a: 0xb8, 0x46b: 0xb8, 0x46c: 0xb8, 0x46d: 0xb8, 0x46e: 0xb8, 0x46f: 0xb8, | ||
2189 | 0x470: 0xb8, 0x471: 0xb8, 0x472: 0xb8, 0x473: 0xb8, 0x474: 0xb8, 0x475: 0xb8, 0x476: 0xb8, 0x477: 0xb8, | ||
2190 | 0x478: 0xb8, 0x479: 0xb8, 0x47a: 0xb8, 0x47b: 0xb8, 0x47c: 0xb8, 0x47d: 0xb8, 0x47e: 0xb8, 0x47f: 0xb8, | ||
2191 | // Block 0x12, offset 0x480 | ||
2192 | 0x480: 0x9d, 0x481: 0x9d, 0x482: 0x9d, 0x483: 0x9d, 0x484: 0x9d, 0x485: 0x9d, 0x486: 0x9d, 0x487: 0x9d, | ||
2193 | 0x488: 0x9d, 0x489: 0x9d, 0x48a: 0x9d, 0x48b: 0x9d, 0x48c: 0x9d, 0x48d: 0x9d, 0x48e: 0x9d, 0x48f: 0x9d, | ||
2194 | 0x490: 0x144, 0x491: 0xb8, 0x492: 0xb8, 0x493: 0xb8, 0x494: 0xb8, 0x495: 0xb8, 0x496: 0xb8, 0x497: 0xb8, | ||
2195 | 0x498: 0xb8, 0x499: 0xb8, 0x49a: 0xb8, 0x49b: 0xb8, 0x49c: 0xb8, 0x49d: 0xb8, 0x49e: 0xb8, 0x49f: 0xb8, | ||
2196 | 0x4a0: 0xb8, 0x4a1: 0xb8, 0x4a2: 0xb8, 0x4a3: 0xb8, 0x4a4: 0xb8, 0x4a5: 0xb8, 0x4a6: 0xb8, 0x4a7: 0xb8, | ||
2197 | 0x4a8: 0xb8, 0x4a9: 0xb8, 0x4aa: 0xb8, 0x4ab: 0xb8, 0x4ac: 0xb8, 0x4ad: 0xb8, 0x4ae: 0xb8, 0x4af: 0xb8, | ||
2198 | 0x4b0: 0xb8, 0x4b1: 0xb8, 0x4b2: 0xb8, 0x4b3: 0xb8, 0x4b4: 0xb8, 0x4b5: 0xb8, 0x4b6: 0xb8, 0x4b7: 0xb8, | ||
2199 | 0x4b8: 0xb8, 0x4b9: 0xb8, 0x4ba: 0xb8, 0x4bb: 0xb8, 0x4bc: 0xb8, 0x4bd: 0xb8, 0x4be: 0xb8, 0x4bf: 0xb8, | ||
2200 | // Block 0x13, offset 0x4c0 | ||
2201 | 0x4c0: 0xb8, 0x4c1: 0xb8, 0x4c2: 0xb8, 0x4c3: 0xb8, 0x4c4: 0xb8, 0x4c5: 0xb8, 0x4c6: 0xb8, 0x4c7: 0xb8, | ||
2202 | 0x4c8: 0xb8, 0x4c9: 0xb8, 0x4ca: 0xb8, 0x4cb: 0xb8, 0x4cc: 0xb8, 0x4cd: 0xb8, 0x4ce: 0xb8, 0x4cf: 0xb8, | ||
2203 | 0x4d0: 0x9d, 0x4d1: 0x9d, 0x4d2: 0x9d, 0x4d3: 0x9d, 0x4d4: 0x9d, 0x4d5: 0x9d, 0x4d6: 0x9d, 0x4d7: 0x9d, | ||
2204 | 0x4d8: 0x9d, 0x4d9: 0x145, 0x4da: 0xb8, 0x4db: 0xb8, 0x4dc: 0xb8, 0x4dd: 0xb8, 0x4de: 0xb8, 0x4df: 0xb8, | ||
2205 | 0x4e0: 0xb8, 0x4e1: 0xb8, 0x4e2: 0xb8, 0x4e3: 0xb8, 0x4e4: 0xb8, 0x4e5: 0xb8, 0x4e6: 0xb8, 0x4e7: 0xb8, | ||
2206 | 0x4e8: 0xb8, 0x4e9: 0xb8, 0x4ea: 0xb8, 0x4eb: 0xb8, 0x4ec: 0xb8, 0x4ed: 0xb8, 0x4ee: 0xb8, 0x4ef: 0xb8, | ||
2207 | 0x4f0: 0xb8, 0x4f1: 0xb8, 0x4f2: 0xb8, 0x4f3: 0xb8, 0x4f4: 0xb8, 0x4f5: 0xb8, 0x4f6: 0xb8, 0x4f7: 0xb8, | ||
2208 | 0x4f8: 0xb8, 0x4f9: 0xb8, 0x4fa: 0xb8, 0x4fb: 0xb8, 0x4fc: 0xb8, 0x4fd: 0xb8, 0x4fe: 0xb8, 0x4ff: 0xb8, | ||
2209 | // Block 0x14, offset 0x500 | ||
2210 | 0x500: 0xb8, 0x501: 0xb8, 0x502: 0xb8, 0x503: 0xb8, 0x504: 0xb8, 0x505: 0xb8, 0x506: 0xb8, 0x507: 0xb8, | ||
2211 | 0x508: 0xb8, 0x509: 0xb8, 0x50a: 0xb8, 0x50b: 0xb8, 0x50c: 0xb8, 0x50d: 0xb8, 0x50e: 0xb8, 0x50f: 0xb8, | ||
2212 | 0x510: 0xb8, 0x511: 0xb8, 0x512: 0xb8, 0x513: 0xb8, 0x514: 0xb8, 0x515: 0xb8, 0x516: 0xb8, 0x517: 0xb8, | ||
2213 | 0x518: 0xb8, 0x519: 0xb8, 0x51a: 0xb8, 0x51b: 0xb8, 0x51c: 0xb8, 0x51d: 0xb8, 0x51e: 0xb8, 0x51f: 0xb8, | ||
2214 | 0x520: 0x9d, 0x521: 0x9d, 0x522: 0x9d, 0x523: 0x9d, 0x524: 0x9d, 0x525: 0x9d, 0x526: 0x9d, 0x527: 0x9d, | ||
2215 | 0x528: 0x13d, 0x529: 0x146, 0x52a: 0xb8, 0x52b: 0x147, 0x52c: 0x148, 0x52d: 0x149, 0x52e: 0x14a, 0x52f: 0xb8, | ||
2216 | 0x530: 0xb8, 0x531: 0xb8, 0x532: 0xb8, 0x533: 0xb8, 0x534: 0xb8, 0x535: 0xb8, 0x536: 0xb8, 0x537: 0xb8, | ||
2217 | 0x538: 0xb8, 0x539: 0xb8, 0x53a: 0xb8, 0x53b: 0xb8, 0x53c: 0x9d, 0x53d: 0x14b, 0x53e: 0x14c, 0x53f: 0x14d, | ||
2218 | // Block 0x15, offset 0x540 | ||
2219 | 0x540: 0x9d, 0x541: 0x9d, 0x542: 0x9d, 0x543: 0x9d, 0x544: 0x9d, 0x545: 0x9d, 0x546: 0x9d, 0x547: 0x9d, | ||
2220 | 0x548: 0x9d, 0x549: 0x9d, 0x54a: 0x9d, 0x54b: 0x9d, 0x54c: 0x9d, 0x54d: 0x9d, 0x54e: 0x9d, 0x54f: 0x9d, | ||
2221 | 0x550: 0x9d, 0x551: 0x9d, 0x552: 0x9d, 0x553: 0x9d, 0x554: 0x9d, 0x555: 0x9d, 0x556: 0x9d, 0x557: 0x9d, | ||
2222 | 0x558: 0x9d, 0x559: 0x9d, 0x55a: 0x9d, 0x55b: 0x9d, 0x55c: 0x9d, 0x55d: 0x9d, 0x55e: 0x9d, 0x55f: 0x14e, | ||
2223 | 0x560: 0x9d, 0x561: 0x9d, 0x562: 0x9d, 0x563: 0x9d, 0x564: 0x9d, 0x565: 0x9d, 0x566: 0x9d, 0x567: 0x9d, | ||
2224 | 0x568: 0x9d, 0x569: 0x9d, 0x56a: 0x9d, 0x56b: 0x14f, 0x56c: 0xb8, 0x56d: 0xb8, 0x56e: 0xb8, 0x56f: 0xb8, | ||
2225 | 0x570: 0xb8, 0x571: 0xb8, 0x572: 0xb8, 0x573: 0xb8, 0x574: 0xb8, 0x575: 0xb8, 0x576: 0xb8, 0x577: 0xb8, | ||
2226 | 0x578: 0xb8, 0x579: 0xb8, 0x57a: 0xb8, 0x57b: 0xb8, 0x57c: 0xb8, 0x57d: 0xb8, 0x57e: 0xb8, 0x57f: 0xb8, | ||
2227 | // Block 0x16, offset 0x580 | ||
2228 | 0x580: 0x150, 0x581: 0xb8, 0x582: 0xb8, 0x583: 0xb8, 0x584: 0xb8, 0x585: 0xb8, 0x586: 0xb8, 0x587: 0xb8, | ||
2229 | 0x588: 0xb8, 0x589: 0xb8, 0x58a: 0xb8, 0x58b: 0xb8, 0x58c: 0xb8, 0x58d: 0xb8, 0x58e: 0xb8, 0x58f: 0xb8, | ||
2230 | 0x590: 0xb8, 0x591: 0xb8, 0x592: 0xb8, 0x593: 0xb8, 0x594: 0xb8, 0x595: 0xb8, 0x596: 0xb8, 0x597: 0xb8, | ||
2231 | 0x598: 0xb8, 0x599: 0xb8, 0x59a: 0xb8, 0x59b: 0xb8, 0x59c: 0xb8, 0x59d: 0xb8, 0x59e: 0xb8, 0x59f: 0xb8, | ||
2232 | 0x5a0: 0xb8, 0x5a1: 0xb8, 0x5a2: 0xb8, 0x5a3: 0xb8, 0x5a4: 0xb8, 0x5a5: 0xb8, 0x5a6: 0xb8, 0x5a7: 0xb8, | ||
2233 | 0x5a8: 0xb8, 0x5a9: 0xb8, 0x5aa: 0xb8, 0x5ab: 0xb8, 0x5ac: 0xb8, 0x5ad: 0xb8, 0x5ae: 0xb8, 0x5af: 0xb8, | ||
2234 | 0x5b0: 0x9d, 0x5b1: 0x151, 0x5b2: 0x152, 0x5b3: 0xb8, 0x5b4: 0xb8, 0x5b5: 0xb8, 0x5b6: 0xb8, 0x5b7: 0xb8, | ||
2235 | 0x5b8: 0xb8, 0x5b9: 0xb8, 0x5ba: 0xb8, 0x5bb: 0xb8, 0x5bc: 0xb8, 0x5bd: 0xb8, 0x5be: 0xb8, 0x5bf: 0xb8, | ||
2236 | // Block 0x17, offset 0x5c0 | ||
2237 | 0x5c0: 0x9b, 0x5c1: 0x9b, 0x5c2: 0x9b, 0x5c3: 0x153, 0x5c4: 0x154, 0x5c5: 0x155, 0x5c6: 0x156, 0x5c7: 0x157, | ||
2238 | 0x5c8: 0x9b, 0x5c9: 0x158, 0x5ca: 0xb8, 0x5cb: 0xb8, 0x5cc: 0x9b, 0x5cd: 0x159, 0x5ce: 0xb8, 0x5cf: 0xb8, | ||
2239 | 0x5d0: 0x5d, 0x5d1: 0x5e, 0x5d2: 0x5f, 0x5d3: 0x60, 0x5d4: 0x61, 0x5d5: 0x62, 0x5d6: 0x63, 0x5d7: 0x64, | ||
2240 | 0x5d8: 0x65, 0x5d9: 0x66, 0x5da: 0x67, 0x5db: 0x68, 0x5dc: 0x69, 0x5dd: 0x6a, 0x5de: 0x6b, 0x5df: 0x6c, | ||
2241 | 0x5e0: 0x9b, 0x5e1: 0x9b, 0x5e2: 0x9b, 0x5e3: 0x9b, 0x5e4: 0x9b, 0x5e5: 0x9b, 0x5e6: 0x9b, 0x5e7: 0x9b, | ||
2242 | 0x5e8: 0x15a, 0x5e9: 0x15b, 0x5ea: 0x15c, 0x5eb: 0xb8, 0x5ec: 0xb8, 0x5ed: 0xb8, 0x5ee: 0xb8, 0x5ef: 0xb8, | ||
2243 | 0x5f0: 0xb8, 0x5f1: 0xb8, 0x5f2: 0xb8, 0x5f3: 0xb8, 0x5f4: 0xb8, 0x5f5: 0xb8, 0x5f6: 0xb8, 0x5f7: 0xb8, | ||
2244 | 0x5f8: 0xb8, 0x5f9: 0xb8, 0x5fa: 0xb8, 0x5fb: 0xb8, 0x5fc: 0xb8, 0x5fd: 0xb8, 0x5fe: 0xb8, 0x5ff: 0xb8, | ||
2245 | // Block 0x18, offset 0x600 | ||
2246 | 0x600: 0x15d, 0x601: 0xb8, 0x602: 0xb8, 0x603: 0xb8, 0x604: 0xb8, 0x605: 0xb8, 0x606: 0xb8, 0x607: 0xb8, | ||
2247 | 0x608: 0xb8, 0x609: 0xb8, 0x60a: 0xb8, 0x60b: 0xb8, 0x60c: 0xb8, 0x60d: 0xb8, 0x60e: 0xb8, 0x60f: 0xb8, | ||
2248 | 0x610: 0xb8, 0x611: 0xb8, 0x612: 0xb8, 0x613: 0xb8, 0x614: 0xb8, 0x615: 0xb8, 0x616: 0xb8, 0x617: 0xb8, | ||
2249 | 0x618: 0xb8, 0x619: 0xb8, 0x61a: 0xb8, 0x61b: 0xb8, 0x61c: 0xb8, 0x61d: 0xb8, 0x61e: 0xb8, 0x61f: 0xb8, | ||
2250 | 0x620: 0x9d, 0x621: 0x9d, 0x622: 0x9d, 0x623: 0x15e, 0x624: 0x6d, 0x625: 0x15f, 0x626: 0xb8, 0x627: 0xb8, | ||
2251 | 0x628: 0xb8, 0x629: 0xb8, 0x62a: 0xb8, 0x62b: 0xb8, 0x62c: 0xb8, 0x62d: 0xb8, 0x62e: 0xb8, 0x62f: 0xb8, | ||
2252 | 0x630: 0xb8, 0x631: 0xb8, 0x632: 0xb8, 0x633: 0xb8, 0x634: 0xb8, 0x635: 0xb8, 0x636: 0xb8, 0x637: 0xb8, | ||
2253 | 0x638: 0x6e, 0x639: 0x6f, 0x63a: 0x70, 0x63b: 0x160, 0x63c: 0xb8, 0x63d: 0xb8, 0x63e: 0xb8, 0x63f: 0xb8, | ||
2254 | // Block 0x19, offset 0x640 | ||
2255 | 0x640: 0x161, 0x641: 0x9b, 0x642: 0x162, 0x643: 0x163, 0x644: 0x71, 0x645: 0x72, 0x646: 0x164, 0x647: 0x165, | ||
2256 | 0x648: 0x73, 0x649: 0x166, 0x64a: 0xb8, 0x64b: 0xb8, 0x64c: 0x9b, 0x64d: 0x9b, 0x64e: 0x9b, 0x64f: 0x9b, | ||
2257 | 0x650: 0x9b, 0x651: 0x9b, 0x652: 0x9b, 0x653: 0x9b, 0x654: 0x9b, 0x655: 0x9b, 0x656: 0x9b, 0x657: 0x9b, | ||
2258 | 0x658: 0x9b, 0x659: 0x9b, 0x65a: 0x9b, 0x65b: 0x167, 0x65c: 0x9b, 0x65d: 0x168, 0x65e: 0x9b, 0x65f: 0x169, | ||
2259 | 0x660: 0x16a, 0x661: 0x16b, 0x662: 0x16c, 0x663: 0xb8, 0x664: 0x16d, 0x665: 0x16e, 0x666: 0x16f, 0x667: 0x170, | ||
2260 | 0x668: 0xb8, 0x669: 0xb8, 0x66a: 0xb8, 0x66b: 0xb8, 0x66c: 0xb8, 0x66d: 0xb8, 0x66e: 0xb8, 0x66f: 0xb8, | ||
2261 | 0x670: 0xb8, 0x671: 0xb8, 0x672: 0xb8, 0x673: 0xb8, 0x674: 0xb8, 0x675: 0xb8, 0x676: 0xb8, 0x677: 0xb8, | ||
2262 | 0x678: 0xb8, 0x679: 0xb8, 0x67a: 0xb8, 0x67b: 0xb8, 0x67c: 0xb8, 0x67d: 0xb8, 0x67e: 0xb8, 0x67f: 0xb8, | ||
2263 | // Block 0x1a, offset 0x680 | ||
2264 | 0x680: 0x9d, 0x681: 0x9d, 0x682: 0x9d, 0x683: 0x9d, 0x684: 0x9d, 0x685: 0x9d, 0x686: 0x9d, 0x687: 0x9d, | ||
2265 | 0x688: 0x9d, 0x689: 0x9d, 0x68a: 0x9d, 0x68b: 0x9d, 0x68c: 0x9d, 0x68d: 0x9d, 0x68e: 0x9d, 0x68f: 0x9d, | ||
2266 | 0x690: 0x9d, 0x691: 0x9d, 0x692: 0x9d, 0x693: 0x9d, 0x694: 0x9d, 0x695: 0x9d, 0x696: 0x9d, 0x697: 0x9d, | ||
2267 | 0x698: 0x9d, 0x699: 0x9d, 0x69a: 0x9d, 0x69b: 0x171, 0x69c: 0x9d, 0x69d: 0x9d, 0x69e: 0x9d, 0x69f: 0x9d, | ||
2268 | 0x6a0: 0x9d, 0x6a1: 0x9d, 0x6a2: 0x9d, 0x6a3: 0x9d, 0x6a4: 0x9d, 0x6a5: 0x9d, 0x6a6: 0x9d, 0x6a7: 0x9d, | ||
2269 | 0x6a8: 0x9d, 0x6a9: 0x9d, 0x6aa: 0x9d, 0x6ab: 0x9d, 0x6ac: 0x9d, 0x6ad: 0x9d, 0x6ae: 0x9d, 0x6af: 0x9d, | ||
2270 | 0x6b0: 0x9d, 0x6b1: 0x9d, 0x6b2: 0x9d, 0x6b3: 0x9d, 0x6b4: 0x9d, 0x6b5: 0x9d, 0x6b6: 0x9d, 0x6b7: 0x9d, | ||
2271 | 0x6b8: 0x9d, 0x6b9: 0x9d, 0x6ba: 0x9d, 0x6bb: 0x9d, 0x6bc: 0x9d, 0x6bd: 0x9d, 0x6be: 0x9d, 0x6bf: 0x9d, | ||
2272 | // Block 0x1b, offset 0x6c0 | ||
2273 | 0x6c0: 0x9d, 0x6c1: 0x9d, 0x6c2: 0x9d, 0x6c3: 0x9d, 0x6c4: 0x9d, 0x6c5: 0x9d, 0x6c6: 0x9d, 0x6c7: 0x9d, | ||
2274 | 0x6c8: 0x9d, 0x6c9: 0x9d, 0x6ca: 0x9d, 0x6cb: 0x9d, 0x6cc: 0x9d, 0x6cd: 0x9d, 0x6ce: 0x9d, 0x6cf: 0x9d, | ||
2275 | 0x6d0: 0x9d, 0x6d1: 0x9d, 0x6d2: 0x9d, 0x6d3: 0x9d, 0x6d4: 0x9d, 0x6d5: 0x9d, 0x6d6: 0x9d, 0x6d7: 0x9d, | ||
2276 | 0x6d8: 0x9d, 0x6d9: 0x9d, 0x6da: 0x9d, 0x6db: 0x9d, 0x6dc: 0x172, 0x6dd: 0x9d, 0x6de: 0x9d, 0x6df: 0x9d, | ||
2277 | 0x6e0: 0x173, 0x6e1: 0x9d, 0x6e2: 0x9d, 0x6e3: 0x9d, 0x6e4: 0x9d, 0x6e5: 0x9d, 0x6e6: 0x9d, 0x6e7: 0x9d, | ||
2278 | 0x6e8: 0x9d, 0x6e9: 0x9d, 0x6ea: 0x9d, 0x6eb: 0x9d, 0x6ec: 0x9d, 0x6ed: 0x9d, 0x6ee: 0x9d, 0x6ef: 0x9d, | ||
2279 | 0x6f0: 0x9d, 0x6f1: 0x9d, 0x6f2: 0x9d, 0x6f3: 0x9d, 0x6f4: 0x9d, 0x6f5: 0x9d, 0x6f6: 0x9d, 0x6f7: 0x9d, | ||
2280 | 0x6f8: 0x9d, 0x6f9: 0x9d, 0x6fa: 0x9d, 0x6fb: 0x9d, 0x6fc: 0x9d, 0x6fd: 0x9d, 0x6fe: 0x9d, 0x6ff: 0x9d, | ||
2281 | // Block 0x1c, offset 0x700 | ||
2282 | 0x700: 0x9d, 0x701: 0x9d, 0x702: 0x9d, 0x703: 0x9d, 0x704: 0x9d, 0x705: 0x9d, 0x706: 0x9d, 0x707: 0x9d, | ||
2283 | 0x708: 0x9d, 0x709: 0x9d, 0x70a: 0x9d, 0x70b: 0x9d, 0x70c: 0x9d, 0x70d: 0x9d, 0x70e: 0x9d, 0x70f: 0x9d, | ||
2284 | 0x710: 0x9d, 0x711: 0x9d, 0x712: 0x9d, 0x713: 0x9d, 0x714: 0x9d, 0x715: 0x9d, 0x716: 0x9d, 0x717: 0x9d, | ||
2285 | 0x718: 0x9d, 0x719: 0x9d, 0x71a: 0x9d, 0x71b: 0x9d, 0x71c: 0x9d, 0x71d: 0x9d, 0x71e: 0x9d, 0x71f: 0x9d, | ||
2286 | 0x720: 0x9d, 0x721: 0x9d, 0x722: 0x9d, 0x723: 0x9d, 0x724: 0x9d, 0x725: 0x9d, 0x726: 0x9d, 0x727: 0x9d, | ||
2287 | 0x728: 0x9d, 0x729: 0x9d, 0x72a: 0x9d, 0x72b: 0x9d, 0x72c: 0x9d, 0x72d: 0x9d, 0x72e: 0x9d, 0x72f: 0x9d, | ||
2288 | 0x730: 0x9d, 0x731: 0x9d, 0x732: 0x9d, 0x733: 0x9d, 0x734: 0x9d, 0x735: 0x9d, 0x736: 0x9d, 0x737: 0x9d, | ||
2289 | 0x738: 0x9d, 0x739: 0x9d, 0x73a: 0x174, 0x73b: 0xb8, 0x73c: 0xb8, 0x73d: 0xb8, 0x73e: 0xb8, 0x73f: 0xb8, | ||
2290 | // Block 0x1d, offset 0x740 | ||
2291 | 0x740: 0xb8, 0x741: 0xb8, 0x742: 0xb8, 0x743: 0xb8, 0x744: 0xb8, 0x745: 0xb8, 0x746: 0xb8, 0x747: 0xb8, | ||
2292 | 0x748: 0xb8, 0x749: 0xb8, 0x74a: 0xb8, 0x74b: 0xb8, 0x74c: 0xb8, 0x74d: 0xb8, 0x74e: 0xb8, 0x74f: 0xb8, | ||
2293 | 0x750: 0xb8, 0x751: 0xb8, 0x752: 0xb8, 0x753: 0xb8, 0x754: 0xb8, 0x755: 0xb8, 0x756: 0xb8, 0x757: 0xb8, | ||
2294 | 0x758: 0xb8, 0x759: 0xb8, 0x75a: 0xb8, 0x75b: 0xb8, 0x75c: 0xb8, 0x75d: 0xb8, 0x75e: 0xb8, 0x75f: 0xb8, | ||
2295 | 0x760: 0x74, 0x761: 0x75, 0x762: 0x76, 0x763: 0x175, 0x764: 0x77, 0x765: 0x78, 0x766: 0x176, 0x767: 0x79, | ||
2296 | 0x768: 0x7a, 0x769: 0xb8, 0x76a: 0xb8, 0x76b: 0xb8, 0x76c: 0xb8, 0x76d: 0xb8, 0x76e: 0xb8, 0x76f: 0xb8, | ||
2297 | 0x770: 0xb8, 0x771: 0xb8, 0x772: 0xb8, 0x773: 0xb8, 0x774: 0xb8, 0x775: 0xb8, 0x776: 0xb8, 0x777: 0xb8, | ||
2298 | 0x778: 0xb8, 0x779: 0xb8, 0x77a: 0xb8, 0x77b: 0xb8, 0x77c: 0xb8, 0x77d: 0xb8, 0x77e: 0xb8, 0x77f: 0xb8, | ||
2299 | // Block 0x1e, offset 0x780 | ||
2300 | 0x790: 0x0d, 0x791: 0x0e, 0x792: 0x0f, 0x793: 0x10, 0x794: 0x11, 0x795: 0x0b, 0x796: 0x12, 0x797: 0x07, | ||
2301 | 0x798: 0x13, 0x799: 0x0b, 0x79a: 0x0b, 0x79b: 0x14, 0x79c: 0x0b, 0x79d: 0x15, 0x79e: 0x16, 0x79f: 0x17, | ||
2302 | 0x7a0: 0x07, 0x7a1: 0x07, 0x7a2: 0x07, 0x7a3: 0x07, 0x7a4: 0x07, 0x7a5: 0x07, 0x7a6: 0x07, 0x7a7: 0x07, | ||
2303 | 0x7a8: 0x07, 0x7a9: 0x07, 0x7aa: 0x18, 0x7ab: 0x19, 0x7ac: 0x1a, 0x7ad: 0x0b, 0x7ae: 0x0b, 0x7af: 0x1b, | ||
2304 | 0x7b0: 0x0b, 0x7b1: 0x0b, 0x7b2: 0x0b, 0x7b3: 0x0b, 0x7b4: 0x0b, 0x7b5: 0x0b, 0x7b6: 0x0b, 0x7b7: 0x0b, | ||
2305 | 0x7b8: 0x0b, 0x7b9: 0x0b, 0x7ba: 0x0b, 0x7bb: 0x0b, 0x7bc: 0x0b, 0x7bd: 0x0b, 0x7be: 0x0b, 0x7bf: 0x0b, | ||
2306 | // Block 0x1f, offset 0x7c0 | ||
2307 | 0x7c0: 0x0b, 0x7c1: 0x0b, 0x7c2: 0x0b, 0x7c3: 0x0b, 0x7c4: 0x0b, 0x7c5: 0x0b, 0x7c6: 0x0b, 0x7c7: 0x0b, | ||
2308 | 0x7c8: 0x0b, 0x7c9: 0x0b, 0x7ca: 0x0b, 0x7cb: 0x0b, 0x7cc: 0x0b, 0x7cd: 0x0b, 0x7ce: 0x0b, 0x7cf: 0x0b, | ||
2309 | 0x7d0: 0x0b, 0x7d1: 0x0b, 0x7d2: 0x0b, 0x7d3: 0x0b, 0x7d4: 0x0b, 0x7d5: 0x0b, 0x7d6: 0x0b, 0x7d7: 0x0b, | ||
2310 | 0x7d8: 0x0b, 0x7d9: 0x0b, 0x7da: 0x0b, 0x7db: 0x0b, 0x7dc: 0x0b, 0x7dd: 0x0b, 0x7de: 0x0b, 0x7df: 0x0b, | ||
2311 | 0x7e0: 0x0b, 0x7e1: 0x0b, 0x7e2: 0x0b, 0x7e3: 0x0b, 0x7e4: 0x0b, 0x7e5: 0x0b, 0x7e6: 0x0b, 0x7e7: 0x0b, | ||
2312 | 0x7e8: 0x0b, 0x7e9: 0x0b, 0x7ea: 0x0b, 0x7eb: 0x0b, 0x7ec: 0x0b, 0x7ed: 0x0b, 0x7ee: 0x0b, 0x7ef: 0x0b, | ||
2313 | 0x7f0: 0x0b, 0x7f1: 0x0b, 0x7f2: 0x0b, 0x7f3: 0x0b, 0x7f4: 0x0b, 0x7f5: 0x0b, 0x7f6: 0x0b, 0x7f7: 0x0b, | ||
2314 | 0x7f8: 0x0b, 0x7f9: 0x0b, 0x7fa: 0x0b, 0x7fb: 0x0b, 0x7fc: 0x0b, 0x7fd: 0x0b, 0x7fe: 0x0b, 0x7ff: 0x0b, | ||
2315 | // Block 0x20, offset 0x800 | ||
2316 | 0x800: 0x177, 0x801: 0x178, 0x802: 0xb8, 0x803: 0xb8, 0x804: 0x179, 0x805: 0x179, 0x806: 0x179, 0x807: 0x17a, | ||
2317 | 0x808: 0xb8, 0x809: 0xb8, 0x80a: 0xb8, 0x80b: 0xb8, 0x80c: 0xb8, 0x80d: 0xb8, 0x80e: 0xb8, 0x80f: 0xb8, | ||
2318 | 0x810: 0xb8, 0x811: 0xb8, 0x812: 0xb8, 0x813: 0xb8, 0x814: 0xb8, 0x815: 0xb8, 0x816: 0xb8, 0x817: 0xb8, | ||
2319 | 0x818: 0xb8, 0x819: 0xb8, 0x81a: 0xb8, 0x81b: 0xb8, 0x81c: 0xb8, 0x81d: 0xb8, 0x81e: 0xb8, 0x81f: 0xb8, | ||
2320 | 0x820: 0xb8, 0x821: 0xb8, 0x822: 0xb8, 0x823: 0xb8, 0x824: 0xb8, 0x825: 0xb8, 0x826: 0xb8, 0x827: 0xb8, | ||
2321 | 0x828: 0xb8, 0x829: 0xb8, 0x82a: 0xb8, 0x82b: 0xb8, 0x82c: 0xb8, 0x82d: 0xb8, 0x82e: 0xb8, 0x82f: 0xb8, | ||
2322 | 0x830: 0xb8, 0x831: 0xb8, 0x832: 0xb8, 0x833: 0xb8, 0x834: 0xb8, 0x835: 0xb8, 0x836: 0xb8, 0x837: 0xb8, | ||
2323 | 0x838: 0xb8, 0x839: 0xb8, 0x83a: 0xb8, 0x83b: 0xb8, 0x83c: 0xb8, 0x83d: 0xb8, 0x83e: 0xb8, 0x83f: 0xb8, | ||
2324 | // Block 0x21, offset 0x840 | ||
2325 | 0x840: 0x0b, 0x841: 0x0b, 0x842: 0x0b, 0x843: 0x0b, 0x844: 0x0b, 0x845: 0x0b, 0x846: 0x0b, 0x847: 0x0b, | ||
2326 | 0x848: 0x0b, 0x849: 0x0b, 0x84a: 0x0b, 0x84b: 0x0b, 0x84c: 0x0b, 0x84d: 0x0b, 0x84e: 0x0b, 0x84f: 0x0b, | ||
2327 | 0x850: 0x0b, 0x851: 0x0b, 0x852: 0x0b, 0x853: 0x0b, 0x854: 0x0b, 0x855: 0x0b, 0x856: 0x0b, 0x857: 0x0b, | ||
2328 | 0x858: 0x0b, 0x859: 0x0b, 0x85a: 0x0b, 0x85b: 0x0b, 0x85c: 0x0b, 0x85d: 0x0b, 0x85e: 0x0b, 0x85f: 0x0b, | ||
2329 | 0x860: 0x1e, 0x861: 0x0b, 0x862: 0x0b, 0x863: 0x0b, 0x864: 0x0b, 0x865: 0x0b, 0x866: 0x0b, 0x867: 0x0b, | ||
2330 | 0x868: 0x0b, 0x869: 0x0b, 0x86a: 0x0b, 0x86b: 0x0b, 0x86c: 0x0b, 0x86d: 0x0b, 0x86e: 0x0b, 0x86f: 0x0b, | ||
2331 | 0x870: 0x0b, 0x871: 0x0b, 0x872: 0x0b, 0x873: 0x0b, 0x874: 0x0b, 0x875: 0x0b, 0x876: 0x0b, 0x877: 0x0b, | ||
2332 | 0x878: 0x0b, 0x879: 0x0b, 0x87a: 0x0b, 0x87b: 0x0b, 0x87c: 0x0b, 0x87d: 0x0b, 0x87e: 0x0b, 0x87f: 0x0b, | ||
2333 | // Block 0x22, offset 0x880 | ||
2334 | 0x880: 0x0b, 0x881: 0x0b, 0x882: 0x0b, 0x883: 0x0b, 0x884: 0x0b, 0x885: 0x0b, 0x886: 0x0b, 0x887: 0x0b, | ||
2335 | 0x888: 0x0b, 0x889: 0x0b, 0x88a: 0x0b, 0x88b: 0x0b, 0x88c: 0x0b, 0x88d: 0x0b, 0x88e: 0x0b, 0x88f: 0x0b, | ||
2336 | } | ||
2337 | |||
2338 | // idnaSparseOffset: 256 entries, 512 bytes | ||
2339 | var idnaSparseOffset = []uint16{0x0, 0x8, 0x19, 0x25, 0x27, 0x2c, 0x34, 0x3f, 0x4b, 0x5c, 0x60, 0x6f, 0x74, 0x7b, 0x87, 0x95, 0xa3, 0xa8, 0xb1, 0xc1, 0xcf, 0xdc, 0xe8, 0xf9, 0x103, 0x10a, 0x117, 0x128, 0x12f, 0x13a, 0x149, 0x157, 0x161, 0x163, 0x167, 0x169, 0x175, 0x180, 0x188, 0x18e, 0x194, 0x199, 0x19e, 0x1a1, 0x1a5, 0x1ab, 0x1b0, 0x1bc, 0x1c6, 0x1cc, 0x1dd, 0x1e7, 0x1ea, 0x1f2, 0x1f5, 0x202, 0x20a, 0x20e, 0x215, 0x21d, 0x22d, 0x239, 0x23b, 0x245, 0x251, 0x25d, 0x269, 0x271, 0x276, 0x280, 0x291, 0x295, 0x2a0, 0x2a4, 0x2ad, 0x2b5, 0x2bb, 0x2c0, 0x2c3, 0x2c6, 0x2ca, 0x2d0, 0x2d4, 0x2d8, 0x2de, 0x2e5, 0x2eb, 0x2f3, 0x2fa, 0x305, 0x30f, 0x313, 0x316, 0x31c, 0x320, 0x322, 0x325, 0x327, 0x32a, 0x334, 0x337, 0x346, 0x34a, 0x34f, 0x352, 0x356, 0x35b, 0x360, 0x366, 0x36c, 0x37b, 0x381, 0x385, 0x394, 0x399, 0x3a1, 0x3ab, 0x3b6, 0x3be, 0x3cf, 0x3d8, 0x3e8, 0x3f5, 0x3ff, 0x404, 0x411, 0x415, 0x41a, 0x41c, 0x420, 0x422, 0x426, 0x42f, 0x435, 0x439, 0x449, 0x453, 0x458, 0x45b, 0x461, 0x468, 0x46d, 0x471, 0x477, 0x47c, 0x485, 0x48a, 0x490, 0x497, 0x49e, 0x4a5, 0x4a9, 0x4ae, 0x4b1, 0x4b6, 0x4c2, 0x4c8, 0x4cd, 0x4d4, 0x4dc, 0x4e1, 0x4e5, 0x4f5, 0x4fc, 0x500, 0x504, 0x50b, 0x50e, 0x511, 0x515, 0x519, 0x51f, 0x528, 0x534, 0x53b, 0x544, 0x54c, 0x553, 0x561, 0x56e, 0x57b, 0x584, 0x588, 0x596, 0x59e, 0x5a9, 0x5b2, 0x5b8, 0x5c0, 0x5c9, 0x5d3, 0x5d6, 0x5e2, 0x5e5, 0x5ea, 0x5ed, 0x5f7, 0x600, 0x60c, 0x60f, 0x614, 0x617, 0x61a, 0x61d, 0x624, 0x62b, 0x62f, 0x63a, 0x63d, 0x643, 0x648, 0x64c, 0x64f, 0x652, 0x655, 0x65a, 0x664, 0x667, 0x66b, 0x67a, 0x686, 0x68a, 0x68f, 0x694, 0x698, 0x69d, 0x6a6, 0x6b1, 0x6b7, 0x6bf, 0x6c3, 0x6c7, 0x6cd, 0x6d3, 0x6d8, 0x6db, 0x6e9, 0x6f0, 0x6f3, 0x6f6, 0x6fa, 0x700, 0x705, 0x70f, 0x714, 0x717, 0x71a, 0x71d, 0x720, 0x724, 0x727, 0x737, 0x748, 0x74d, 0x74f, 0x751} | ||
2340 | |||
2341 | // idnaSparseValues: 1876 entries, 7504 bytes | ||
2342 | var idnaSparseValues = [1876]valueRange{ | ||
2343 | // Block 0x0, offset 0x0 | ||
2344 | {value: 0x0000, lo: 0x07}, | ||
2345 | {value: 0xe105, lo: 0x80, hi: 0x96}, | ||
2346 | {value: 0x0018, lo: 0x97, hi: 0x97}, | ||
2347 | {value: 0xe105, lo: 0x98, hi: 0x9e}, | ||
2348 | {value: 0x001f, lo: 0x9f, hi: 0x9f}, | ||
2349 | {value: 0x0008, lo: 0xa0, hi: 0xb6}, | ||
2350 | {value: 0x0018, lo: 0xb7, hi: 0xb7}, | ||
2351 | {value: 0x0008, lo: 0xb8, hi: 0xbf}, | ||
2352 | // Block 0x1, offset 0x8 | ||
2353 | {value: 0x0000, lo: 0x10}, | ||
2354 | {value: 0x0008, lo: 0x80, hi: 0x80}, | ||
2355 | {value: 0xe01d, lo: 0x81, hi: 0x81}, | ||
2356 | {value: 0x0008, lo: 0x82, hi: 0x82}, | ||
2357 | {value: 0x0335, lo: 0x83, hi: 0x83}, | ||
2358 | {value: 0x034d, lo: 0x84, hi: 0x84}, | ||
2359 | {value: 0x0365, lo: 0x85, hi: 0x85}, | ||
2360 | {value: 0xe00d, lo: 0x86, hi: 0x86}, | ||
2361 | {value: 0x0008, lo: 0x87, hi: 0x87}, | ||
2362 | {value: 0xe00d, lo: 0x88, hi: 0x88}, | ||
2363 | {value: 0x0008, lo: 0x89, hi: 0x89}, | ||
2364 | {value: 0xe00d, lo: 0x8a, hi: 0x8a}, | ||
2365 | {value: 0x0008, lo: 0x8b, hi: 0x8b}, | ||
2366 | {value: 0xe00d, lo: 0x8c, hi: 0x8c}, | ||
2367 | {value: 0x0008, lo: 0x8d, hi: 0x8d}, | ||
2368 | {value: 0xe00d, lo: 0x8e, hi: 0x8e}, | ||
2369 | {value: 0x0008, lo: 0x8f, hi: 0xbf}, | ||
2370 | // Block 0x2, offset 0x19 | ||
2371 | {value: 0x0000, lo: 0x0b}, | ||
2372 | {value: 0x0008, lo: 0x80, hi: 0xaf}, | ||
2373 | {value: 0x0249, lo: 0xb0, hi: 0xb0}, | ||
2374 | {value: 0x037d, lo: 0xb1, hi: 0xb1}, | ||
2375 | {value: 0x0259, lo: 0xb2, hi: 0xb2}, | ||
2376 | {value: 0x0269, lo: 0xb3, hi: 0xb3}, | ||
2377 | {value: 0x034d, lo: 0xb4, hi: 0xb4}, | ||
2378 | {value: 0x0395, lo: 0xb5, hi: 0xb5}, | ||
2379 | {value: 0xe1bd, lo: 0xb6, hi: 0xb6}, | ||
2380 | {value: 0x0279, lo: 0xb7, hi: 0xb7}, | ||
2381 | {value: 0x0289, lo: 0xb8, hi: 0xb8}, | ||
2382 | {value: 0x0008, lo: 0xb9, hi: 0xbf}, | ||
2383 | // Block 0x3, offset 0x25 | ||
2384 | {value: 0x0000, lo: 0x01}, | ||
2385 | {value: 0x1308, lo: 0x80, hi: 0xbf}, | ||
2386 | // Block 0x4, offset 0x27 | ||
2387 | {value: 0x0000, lo: 0x04}, | ||
2388 | {value: 0x03f5, lo: 0x80, hi: 0x8f}, | ||
2389 | {value: 0xe105, lo: 0x90, hi: 0x9f}, | ||
2390 | {value: 0x049d, lo: 0xa0, hi: 0xaf}, | ||
2391 | {value: 0x0008, lo: 0xb0, hi: 0xbf}, | ||
2392 | // Block 0x5, offset 0x2c | ||
2393 | {value: 0x0000, lo: 0x07}, | ||
2394 | {value: 0xe185, lo: 0x80, hi: 0x8f}, | ||
2395 | {value: 0x0545, lo: 0x90, hi: 0x96}, | ||
2396 | {value: 0x0040, lo: 0x97, hi: 0x98}, | ||
2397 | {value: 0x0008, lo: 0x99, hi: 0x99}, | ||
2398 | {value: 0x0018, lo: 0x9a, hi: 0x9f}, | ||
2399 | {value: 0x0040, lo: 0xa0, hi: 0xa0}, | ||
2400 | {value: 0x0008, lo: 0xa1, hi: 0xbf}, | ||
2401 | // Block 0x6, offset 0x34 | ||
2402 | {value: 0x0000, lo: 0x0a}, | ||
2403 | {value: 0x0008, lo: 0x80, hi: 0x86}, | ||
2404 | {value: 0x0401, lo: 0x87, hi: 0x87}, | ||
2405 | {value: 0x0040, lo: 0x88, hi: 0x88}, | ||
2406 | {value: 0x0018, lo: 0x89, hi: 0x8a}, | ||
2407 | {value: 0x0040, lo: 0x8b, hi: 0x8c}, | ||
2408 | {value: 0x0018, lo: 0x8d, hi: 0x8f}, | ||
2409 | {value: 0x0040, lo: 0x90, hi: 0x90}, | ||
2410 | {value: 0x1308, lo: 0x91, hi: 0xbd}, | ||
2411 | {value: 0x0018, lo: 0xbe, hi: 0xbe}, | ||
2412 | {value: 0x1308, lo: 0xbf, hi: 0xbf}, | ||
2413 | // Block 0x7, offset 0x3f | ||
2414 | {value: 0x0000, lo: 0x0b}, | ||
2415 | {value: 0x0018, lo: 0x80, hi: 0x80}, | ||
2416 | {value: 0x1308, lo: 0x81, hi: 0x82}, | ||
2417 | {value: 0x0018, lo: 0x83, hi: 0x83}, | ||
2418 | {value: 0x1308, lo: 0x84, hi: 0x85}, | ||
2419 | {value: 0x0018, lo: 0x86, hi: 0x86}, | ||
2420 | {value: 0x1308, lo: 0x87, hi: 0x87}, | ||
2421 | {value: 0x0040, lo: 0x88, hi: 0x8f}, | ||
2422 | {value: 0x0008, lo: 0x90, hi: 0xaa}, | ||
2423 | {value: 0x0040, lo: 0xab, hi: 0xaf}, | ||
2424 | {value: 0x0008, lo: 0xb0, hi: 0xb4}, | ||
2425 | {value: 0x0040, lo: 0xb5, hi: 0xbf}, | ||
2426 | // Block 0x8, offset 0x4b | ||
2427 | {value: 0x0000, lo: 0x10}, | ||
2428 | {value: 0x0018, lo: 0x80, hi: 0x80}, | ||
2429 | {value: 0x0208, lo: 0x81, hi: 0x87}, | ||
2430 | {value: 0x0408, lo: 0x88, hi: 0x88}, | ||
2431 | {value: 0x0208, lo: 0x89, hi: 0x8a}, | ||
2432 | {value: 0x1308, lo: 0x8b, hi: 0x9f}, | ||
2433 | {value: 0x0008, lo: 0xa0, hi: 0xa9}, | ||
2434 | {value: 0x0018, lo: 0xaa, hi: 0xad}, | ||
2435 | {value: 0x0208, lo: 0xae, hi: 0xaf}, | ||
2436 | {value: 0x1308, lo: 0xb0, hi: 0xb0}, | ||
2437 | {value: 0x0408, lo: 0xb1, hi: 0xb3}, | ||
2438 | {value: 0x0008, lo: 0xb4, hi: 0xb4}, | ||
2439 | {value: 0x0429, lo: 0xb5, hi: 0xb5}, | ||
2440 | {value: 0x0451, lo: 0xb6, hi: 0xb6}, | ||
2441 | {value: 0x0479, lo: 0xb7, hi: 0xb7}, | ||
2442 | {value: 0x04a1, lo: 0xb8, hi: 0xb8}, | ||
2443 | {value: 0x0208, lo: 0xb9, hi: 0xbf}, | ||
2444 | // Block 0x9, offset 0x5c | ||
2445 | {value: 0x0000, lo: 0x03}, | ||
2446 | {value: 0x0208, lo: 0x80, hi: 0x87}, | ||
2447 | {value: 0x0408, lo: 0x88, hi: 0x99}, | ||
2448 | {value: 0x0208, lo: 0x9a, hi: 0xbf}, | ||
2449 | // Block 0xa, offset 0x60 | ||
2450 | {value: 0x0000, lo: 0x0e}, | ||
2451 | {value: 0x1308, lo: 0x80, hi: 0x8a}, | ||
2452 | {value: 0x0040, lo: 0x8b, hi: 0x8c}, | ||
2453 | {value: 0x0408, lo: 0x8d, hi: 0x8d}, | ||
2454 | {value: 0x0208, lo: 0x8e, hi: 0x98}, | ||
2455 | {value: 0x0408, lo: 0x99, hi: 0x9b}, | ||
2456 | {value: 0x0208, lo: 0x9c, hi: 0xaa}, | ||
2457 | {value: 0x0408, lo: 0xab, hi: 0xac}, | ||
2458 | {value: 0x0208, lo: 0xad, hi: 0xb0}, | ||
2459 | {value: 0x0408, lo: 0xb1, hi: 0xb1}, | ||
2460 | {value: 0x0208, lo: 0xb2, hi: 0xb2}, | ||
2461 | {value: 0x0408, lo: 0xb3, hi: 0xb4}, | ||
2462 | {value: 0x0208, lo: 0xb5, hi: 0xb7}, | ||
2463 | {value: 0x0408, lo: 0xb8, hi: 0xb9}, | ||
2464 | {value: 0x0208, lo: 0xba, hi: 0xbf}, | ||
2465 | // Block 0xb, offset 0x6f | ||
2466 | {value: 0x0000, lo: 0x04}, | ||
2467 | {value: 0x0008, lo: 0x80, hi: 0xa5}, | ||
2468 | {value: 0x1308, lo: 0xa6, hi: 0xb0}, | ||
2469 | {value: 0x0008, lo: 0xb1, hi: 0xb1}, | ||
2470 | {value: 0x0040, lo: 0xb2, hi: 0xbf}, | ||
2471 | // Block 0xc, offset 0x74 | ||
2472 | {value: 0x0000, lo: 0x06}, | ||
2473 | {value: 0x0008, lo: 0x80, hi: 0x89}, | ||
2474 | {value: 0x0208, lo: 0x8a, hi: 0xaa}, | ||
2475 | {value: 0x1308, lo: 0xab, hi: 0xb3}, | ||
2476 | {value: 0x0008, lo: 0xb4, hi: 0xb5}, | ||
2477 | {value: 0x0018, lo: 0xb6, hi: 0xba}, | ||
2478 | {value: 0x0040, lo: 0xbb, hi: 0xbf}, | ||
2479 | // Block 0xd, offset 0x7b | ||
2480 | {value: 0x0000, lo: 0x0b}, | ||
2481 | {value: 0x0008, lo: 0x80, hi: 0x95}, | ||
2482 | {value: 0x1308, lo: 0x96, hi: 0x99}, | ||
2483 | {value: 0x0008, lo: 0x9a, hi: 0x9a}, | ||
2484 | {value: 0x1308, lo: 0x9b, hi: 0xa3}, | ||
2485 | {value: 0x0008, lo: 0xa4, hi: 0xa4}, | ||
2486 | {value: 0x1308, lo: 0xa5, hi: 0xa7}, | ||
2487 | {value: 0x0008, lo: 0xa8, hi: 0xa8}, | ||
2488 | {value: 0x1308, lo: 0xa9, hi: 0xad}, | ||
2489 | {value: 0x0040, lo: 0xae, hi: 0xaf}, | ||
2490 | {value: 0x0018, lo: 0xb0, hi: 0xbe}, | ||
2491 | {value: 0x0040, lo: 0xbf, hi: 0xbf}, | ||
2492 | // Block 0xe, offset 0x87 | ||
2493 | {value: 0x0000, lo: 0x0d}, | ||
2494 | {value: 0x0408, lo: 0x80, hi: 0x80}, | ||
2495 | {value: 0x0208, lo: 0x81, hi: 0x85}, | ||
2496 | {value: 0x0408, lo: 0x86, hi: 0x87}, | ||
2497 | {value: 0x0208, lo: 0x88, hi: 0x88}, | ||
2498 | {value: 0x0408, lo: 0x89, hi: 0x89}, | ||
2499 | {value: 0x0208, lo: 0x8a, hi: 0x93}, | ||
2500 | {value: 0x0408, lo: 0x94, hi: 0x94}, | ||
2501 | {value: 0x0208, lo: 0x95, hi: 0x95}, | ||
2502 | {value: 0x0008, lo: 0x96, hi: 0x98}, | ||
2503 | {value: 0x1308, lo: 0x99, hi: 0x9b}, | ||
2504 | {value: 0x0040, lo: 0x9c, hi: 0x9d}, | ||
2505 | {value: 0x0018, lo: 0x9e, hi: 0x9e}, | ||
2506 | {value: 0x0040, lo: 0x9f, hi: 0xbf}, | ||
2507 | // Block 0xf, offset 0x95 | ||
2508 | {value: 0x0000, lo: 0x0d}, | ||
2509 | {value: 0x0040, lo: 0x80, hi: 0x9f}, | ||
2510 | {value: 0x0208, lo: 0xa0, hi: 0xa9}, | ||
2511 | {value: 0x0408, lo: 0xaa, hi: 0xac}, | ||
2512 | {value: 0x0008, lo: 0xad, hi: 0xad}, | ||
2513 | {value: 0x0408, lo: 0xae, hi: 0xae}, | ||
2514 | {value: 0x0208, lo: 0xaf, hi: 0xb0}, | ||
2515 | {value: 0x0408, lo: 0xb1, hi: 0xb2}, | ||
2516 | {value: 0x0208, lo: 0xb3, hi: 0xb4}, | ||
2517 | {value: 0x0040, lo: 0xb5, hi: 0xb5}, | ||
2518 | {value: 0x0208, lo: 0xb6, hi: 0xb8}, | ||
2519 | {value: 0x0408, lo: 0xb9, hi: 0xb9}, | ||
2520 | {value: 0x0208, lo: 0xba, hi: 0xbd}, | ||
2521 | {value: 0x0040, lo: 0xbe, hi: 0xbf}, | ||
2522 | // Block 0x10, offset 0xa3 | ||
2523 | {value: 0x0000, lo: 0x04}, | ||
2524 | {value: 0x0040, lo: 0x80, hi: 0x93}, | ||
2525 | {value: 0x1308, lo: 0x94, hi: 0xa1}, | ||
2526 | {value: 0x0040, lo: 0xa2, hi: 0xa2}, | ||
2527 | {value: 0x1308, lo: 0xa3, hi: 0xbf}, | ||
2528 | // Block 0x11, offset 0xa8 | ||
2529 | {value: 0x0000, lo: 0x08}, | ||
2530 | {value: 0x1308, lo: 0x80, hi: 0x82}, | ||
2531 | {value: 0x1008, lo: 0x83, hi: 0x83}, | ||
2532 | {value: 0x0008, lo: 0x84, hi: 0xb9}, | ||
2533 | {value: 0x1308, lo: 0xba, hi: 0xba}, | ||
2534 | {value: 0x1008, lo: 0xbb, hi: 0xbb}, | ||
2535 | {value: 0x1308, lo: 0xbc, hi: 0xbc}, | ||
2536 | {value: 0x0008, lo: 0xbd, hi: 0xbd}, | ||
2537 | {value: 0x1008, lo: 0xbe, hi: 0xbf}, | ||
2538 | // Block 0x12, offset 0xb1 | ||
2539 | {value: 0x0000, lo: 0x0f}, | ||
2540 | {value: 0x1308, lo: 0x80, hi: 0x80}, | ||
2541 | {value: 0x1008, lo: 0x81, hi: 0x82}, | ||
2542 | {value: 0x0040, lo: 0x83, hi: 0x85}, | ||
2543 | {value: 0x1008, lo: 0x86, hi: 0x88}, | ||
2544 | {value: 0x0040, lo: 0x89, hi: 0x89}, | ||
2545 | {value: 0x1008, lo: 0x8a, hi: 0x8c}, | ||
2546 | {value: 0x1b08, lo: 0x8d, hi: 0x8d}, | ||
2547 | {value: 0x0040, lo: 0x8e, hi: 0x8f}, | ||
2548 | {value: 0x0008, lo: 0x90, hi: 0x90}, | ||
2549 | {value: 0x0040, lo: 0x91, hi: 0x96}, | ||
2550 | {value: 0x1008, lo: 0x97, hi: 0x97}, | ||
2551 | {value: 0x0040, lo: 0x98, hi: 0xa5}, | ||
2552 | {value: 0x0008, lo: 0xa6, hi: 0xaf}, | ||
2553 | {value: 0x0018, lo: 0xb0, hi: 0xba}, | ||
2554 | {value: 0x0040, lo: 0xbb, hi: 0xbf}, | ||
2555 | // Block 0x13, offset 0xc1 | ||
2556 | {value: 0x0000, lo: 0x0d}, | ||
2557 | {value: 0x1308, lo: 0x80, hi: 0x80}, | ||
2558 | {value: 0x1008, lo: 0x81, hi: 0x83}, | ||
2559 | {value: 0x0040, lo: 0x84, hi: 0x84}, | ||
2560 | {value: 0x0008, lo: 0x85, hi: 0x8c}, | ||
2561 | {value: 0x0040, lo: 0x8d, hi: 0x8d}, | ||
2562 | {value: 0x0008, lo: 0x8e, hi: 0x90}, | ||
2563 | {value: 0x0040, lo: 0x91, hi: 0x91}, | ||
2564 | {value: 0x0008, lo: 0x92, hi: 0xa8}, | ||
2565 | {value: 0x0040, lo: 0xa9, hi: 0xa9}, | ||
2566 | {value: 0x0008, lo: 0xaa, hi: 0xb9}, | ||
2567 | {value: 0x0040, lo: 0xba, hi: 0xbc}, | ||
2568 | {value: 0x0008, lo: 0xbd, hi: 0xbd}, | ||
2569 | {value: 0x1308, lo: 0xbe, hi: 0xbf}, | ||
2570 | // Block 0x14, offset 0xcf | ||
2571 | {value: 0x0000, lo: 0x0c}, | ||
2572 | {value: 0x0040, lo: 0x80, hi: 0x80}, | ||
2573 | {value: 0x1308, lo: 0x81, hi: 0x81}, | ||
2574 | {value: 0x1008, lo: 0x82, hi: 0x83}, | ||
2575 | {value: 0x0040, lo: 0x84, hi: 0x84}, | ||
2576 | {value: 0x0008, lo: 0x85, hi: 0x8c}, | ||
2577 | {value: 0x0040, lo: 0x8d, hi: 0x8d}, | ||
2578 | {value: 0x0008, lo: 0x8e, hi: 0x90}, | ||
2579 | {value: 0x0040, lo: 0x91, hi: 0x91}, | ||
2580 | {value: 0x0008, lo: 0x92, hi: 0xba}, | ||
2581 | {value: 0x0040, lo: 0xbb, hi: 0xbc}, | ||
2582 | {value: 0x0008, lo: 0xbd, hi: 0xbd}, | ||
2583 | {value: 0x1008, lo: 0xbe, hi: 0xbf}, | ||
2584 | // Block 0x15, offset 0xdc | ||
2585 | {value: 0x0000, lo: 0x0b}, | ||
2586 | {value: 0x0040, lo: 0x80, hi: 0x81}, | ||
2587 | {value: 0x1008, lo: 0x82, hi: 0x83}, | ||
2588 | {value: 0x0040, lo: 0x84, hi: 0x84}, | ||
2589 | {value: 0x0008, lo: 0x85, hi: 0x96}, | ||
2590 | {value: 0x0040, lo: 0x97, hi: 0x99}, | ||
2591 | {value: 0x0008, lo: 0x9a, hi: 0xb1}, | ||
2592 | {value: 0x0040, lo: 0xb2, hi: 0xb2}, | ||
2593 | {value: 0x0008, lo: 0xb3, hi: 0xbb}, | ||
2594 | {value: 0x0040, lo: 0xbc, hi: 0xbc}, | ||
2595 | {value: 0x0008, lo: 0xbd, hi: 0xbd}, | ||
2596 | {value: 0x0040, lo: 0xbe, hi: 0xbf}, | ||
2597 | // Block 0x16, offset 0xe8 | ||
2598 | {value: 0x0000, lo: 0x10}, | ||
2599 | {value: 0x0008, lo: 0x80, hi: 0x86}, | ||
2600 | {value: 0x0040, lo: 0x87, hi: 0x89}, | ||
2601 | {value: 0x1b08, lo: 0x8a, hi: 0x8a}, | ||
2602 | {value: 0x0040, lo: 0x8b, hi: 0x8e}, | ||
2603 | {value: 0x1008, lo: 0x8f, hi: 0x91}, | ||
2604 | {value: 0x1308, lo: 0x92, hi: 0x94}, | ||
2605 | {value: 0x0040, lo: 0x95, hi: 0x95}, | ||
2606 | {value: 0x1308, lo: 0x96, hi: 0x96}, | ||
2607 | {value: 0x0040, lo: 0x97, hi: 0x97}, | ||
2608 | {value: 0x1008, lo: 0x98, hi: 0x9f}, | ||
2609 | {value: 0x0040, lo: 0xa0, hi: 0xa5}, | ||
2610 | {value: 0x0008, lo: 0xa6, hi: 0xaf}, | ||
2611 | {value: 0x0040, lo: 0xb0, hi: 0xb1}, | ||
2612 | {value: 0x1008, lo: 0xb2, hi: 0xb3}, | ||
2613 | {value: 0x0018, lo: 0xb4, hi: 0xb4}, | ||
2614 | {value: 0x0040, lo: 0xb5, hi: 0xbf}, | ||
2615 | // Block 0x17, offset 0xf9 | ||
2616 | {value: 0x0000, lo: 0x09}, | ||
2617 | {value: 0x0040, lo: 0x80, hi: 0x80}, | ||
2618 | {value: 0x0008, lo: 0x81, hi: 0xb0}, | ||
2619 | {value: 0x1308, lo: 0xb1, hi: 0xb1}, | ||
2620 | {value: 0x0008, lo: 0xb2, hi: 0xb2}, | ||
2621 | {value: 0x08f1, lo: 0xb3, hi: 0xb3}, | ||
2622 | {value: 0x1308, lo: 0xb4, hi: 0xb9}, | ||
2623 | {value: 0x1b08, lo: 0xba, hi: 0xba}, | ||
2624 | {value: 0x0040, lo: 0xbb, hi: 0xbe}, | ||
2625 | {value: 0x0018, lo: 0xbf, hi: 0xbf}, | ||
2626 | // Block 0x18, offset 0x103 | ||
2627 | {value: 0x0000, lo: 0x06}, | ||
2628 | {value: 0x0008, lo: 0x80, hi: 0x86}, | ||
2629 | {value: 0x1308, lo: 0x87, hi: 0x8e}, | ||
2630 | {value: 0x0018, lo: 0x8f, hi: 0x8f}, | ||
2631 | {value: 0x0008, lo: 0x90, hi: 0x99}, | ||
2632 | {value: 0x0018, lo: 0x9a, hi: 0x9b}, | ||
2633 | {value: 0x0040, lo: 0x9c, hi: 0xbf}, | ||
2634 | // Block 0x19, offset 0x10a | ||
2635 | {value: 0x0000, lo: 0x0c}, | ||
2636 | {value: 0x0008, lo: 0x80, hi: 0x84}, | ||
2637 | {value: 0x0040, lo: 0x85, hi: 0x85}, | ||
2638 | {value: 0x0008, lo: 0x86, hi: 0x86}, | ||
2639 | {value: 0x0040, lo: 0x87, hi: 0x87}, | ||
2640 | {value: 0x1308, lo: 0x88, hi: 0x8d}, | ||
2641 | {value: 0x0040, lo: 0x8e, hi: 0x8f}, | ||
2642 | {value: 0x0008, lo: 0x90, hi: 0x99}, | ||
2643 | {value: 0x0040, lo: 0x9a, hi: 0x9b}, | ||
2644 | {value: 0x0961, lo: 0x9c, hi: 0x9c}, | ||
2645 | {value: 0x0999, lo: 0x9d, hi: 0x9d}, | ||
2646 | {value: 0x0008, lo: 0x9e, hi: 0x9f}, | ||
2647 | {value: 0x0040, lo: 0xa0, hi: 0xbf}, | ||
2648 | // Block 0x1a, offset 0x117 | ||
2649 | {value: 0x0000, lo: 0x10}, | ||
2650 | {value: 0x0008, lo: 0x80, hi: 0x80}, | ||
2651 | {value: 0x0018, lo: 0x81, hi: 0x8a}, | ||
2652 | {value: 0x0008, lo: 0x8b, hi: 0x8b}, | ||
2653 | {value: 0xe03d, lo: 0x8c, hi: 0x8c}, | ||
2654 | {value: 0x0018, lo: 0x8d, hi: 0x97}, | ||
2655 | {value: 0x1308, lo: 0x98, hi: 0x99}, | ||
2656 | {value: 0x0018, lo: 0x9a, hi: 0x9f}, | ||
2657 | {value: 0x0008, lo: 0xa0, hi: 0xa9}, | ||
2658 | {value: 0x0018, lo: 0xaa, hi: 0xb4}, | ||
2659 | {value: 0x1308, lo: 0xb5, hi: 0xb5}, | ||
2660 | {value: 0x0018, lo: 0xb6, hi: 0xb6}, | ||
2661 | {value: 0x1308, lo: 0xb7, hi: 0xb7}, | ||
2662 | {value: 0x0018, lo: 0xb8, hi: 0xb8}, | ||
2663 | {value: 0x1308, lo: 0xb9, hi: 0xb9}, | ||
2664 | {value: 0x0018, lo: 0xba, hi: 0xbd}, | ||
2665 | {value: 0x1008, lo: 0xbe, hi: 0xbf}, | ||
2666 | // Block 0x1b, offset 0x128 | ||
2667 | {value: 0x0000, lo: 0x06}, | ||
2668 | {value: 0x0018, lo: 0x80, hi: 0x85}, | ||
2669 | {value: 0x1308, lo: 0x86, hi: 0x86}, | ||
2670 | {value: 0x0018, lo: 0x87, hi: 0x8c}, | ||
2671 | {value: 0x0040, lo: 0x8d, hi: 0x8d}, | ||
2672 | {value: 0x0018, lo: 0x8e, hi: 0x9a}, | ||
2673 | {value: 0x0040, lo: 0x9b, hi: 0xbf}, | ||
2674 | // Block 0x1c, offset 0x12f | ||
2675 | {value: 0x0000, lo: 0x0a}, | ||
2676 | {value: 0x0008, lo: 0x80, hi: 0xaa}, | ||
2677 | {value: 0x1008, lo: 0xab, hi: 0xac}, | ||
2678 | {value: 0x1308, lo: 0xad, hi: 0xb0}, | ||
2679 | {value: 0x1008, lo: 0xb1, hi: 0xb1}, | ||
2680 | {value: 0x1308, lo: 0xb2, hi: 0xb7}, | ||
2681 | {value: 0x1008, lo: 0xb8, hi: 0xb8}, | ||
2682 | {value: 0x1b08, lo: 0xb9, hi: 0xba}, | ||
2683 | {value: 0x1008, lo: 0xbb, hi: 0xbc}, | ||
2684 | {value: 0x1308, lo: 0xbd, hi: 0xbe}, | ||
2685 | {value: 0x0008, lo: 0xbf, hi: 0xbf}, | ||
2686 | // Block 0x1d, offset 0x13a | ||
2687 | {value: 0x0000, lo: 0x0e}, | ||
2688 | {value: 0x0008, lo: 0x80, hi: 0x89}, | ||
2689 | {value: 0x0018, lo: 0x8a, hi: 0x8f}, | ||
2690 | {value: 0x0008, lo: 0x90, hi: 0x95}, | ||
2691 | {value: 0x1008, lo: 0x96, hi: 0x97}, | ||
2692 | {value: 0x1308, lo: 0x98, hi: 0x99}, | ||
2693 | {value: 0x0008, lo: 0x9a, hi: 0x9d}, | ||
2694 | {value: 0x1308, lo: 0x9e, hi: 0xa0}, | ||
2695 | {value: 0x0008, lo: 0xa1, hi: 0xa1}, | ||
2696 | {value: 0x1008, lo: 0xa2, hi: 0xa4}, | ||
2697 | {value: 0x0008, lo: 0xa5, hi: 0xa6}, | ||
2698 | {value: 0x1008, lo: 0xa7, hi: 0xad}, | ||
2699 | {value: 0x0008, lo: 0xae, hi: 0xb0}, | ||
2700 | {value: 0x1308, lo: 0xb1, hi: 0xb4}, | ||
2701 | {value: 0x0008, lo: 0xb5, hi: 0xbf}, | ||
2702 | // Block 0x1e, offset 0x149 | ||
2703 | {value: 0x0000, lo: 0x0d}, | ||
2704 | {value: 0x0008, lo: 0x80, hi: 0x81}, | ||
2705 | {value: 0x1308, lo: 0x82, hi: 0x82}, | ||
2706 | {value: 0x1008, lo: 0x83, hi: 0x84}, | ||
2707 | {value: 0x1308, lo: 0x85, hi: 0x86}, | ||
2708 | {value: 0x1008, lo: 0x87, hi: 0x8c}, | ||
2709 | {value: 0x1308, lo: 0x8d, hi: 0x8d}, | ||
2710 | {value: 0x0008, lo: 0x8e, hi: 0x8e}, | ||
2711 | {value: 0x1008, lo: 0x8f, hi: 0x8f}, | ||
2712 | {value: 0x0008, lo: 0x90, hi: 0x99}, | ||
2713 | {value: 0x1008, lo: 0x9a, hi: 0x9c}, | ||
2714 | {value: 0x1308, lo: 0x9d, hi: 0x9d}, | ||
2715 | {value: 0x0018, lo: 0x9e, hi: 0x9f}, | ||
2716 | {value: 0x0040, lo: 0xa0, hi: 0xbf}, | ||
2717 | // Block 0x1f, offset 0x157 | ||
2718 | {value: 0x0000, lo: 0x09}, | ||
2719 | {value: 0x0040, lo: 0x80, hi: 0x86}, | ||
2720 | {value: 0x055d, lo: 0x87, hi: 0x87}, | ||
2721 | {value: 0x0040, lo: 0x88, hi: 0x8c}, | ||
2722 | {value: 0x055d, lo: 0x8d, hi: 0x8d}, | ||
2723 | {value: 0x0040, lo: 0x8e, hi: 0x8f}, | ||
2724 | {value: 0x0008, lo: 0x90, hi: 0xba}, | ||
2725 | {value: 0x0018, lo: 0xbb, hi: 0xbb}, | ||
2726 | {value: 0xe105, lo: 0xbc, hi: 0xbc}, | ||
2727 | {value: 0x0008, lo: 0xbd, hi: 0xbf}, | ||
2728 | // Block 0x20, offset 0x161 | ||
2729 | {value: 0x0000, lo: 0x01}, | ||
2730 | {value: 0x0018, lo: 0x80, hi: 0xbf}, | ||
2731 | // Block 0x21, offset 0x163 | ||
2732 | {value: 0x0000, lo: 0x03}, | ||
2733 | {value: 0x0018, lo: 0x80, hi: 0x9e}, | ||
2734 | {value: 0x0040, lo: 0x9f, hi: 0xa0}, | ||
2735 | {value: 0x0018, lo: 0xa1, hi: 0xbf}, | ||
2736 | // Block 0x22, offset 0x167 | ||
2737 | {value: 0x0000, lo: 0x01}, | ||
2738 | {value: 0x0008, lo: 0x80, hi: 0xbf}, | ||
2739 | // Block 0x23, offset 0x169 | ||
2740 | {value: 0x0000, lo: 0x0b}, | ||
2741 | {value: 0x0008, lo: 0x80, hi: 0x88}, | ||
2742 | {value: 0x0040, lo: 0x89, hi: 0x89}, | ||
2743 | {value: 0x0008, lo: 0x8a, hi: 0x8d}, | ||
2744 | {value: 0x0040, lo: 0x8e, hi: 0x8f}, | ||
2745 | {value: 0x0008, lo: 0x90, hi: 0x96}, | ||
2746 | {value: 0x0040, lo: 0x97, hi: 0x97}, | ||
2747 | {value: 0x0008, lo: 0x98, hi: 0x98}, | ||
2748 | {value: 0x0040, lo: 0x99, hi: 0x99}, | ||
2749 | {value: 0x0008, lo: 0x9a, hi: 0x9d}, | ||
2750 | {value: 0x0040, lo: 0x9e, hi: 0x9f}, | ||
2751 | {value: 0x0008, lo: 0xa0, hi: 0xbf}, | ||
2752 | // Block 0x24, offset 0x175 | ||
2753 | {value: 0x0000, lo: 0x0a}, | ||
2754 | {value: 0x0008, lo: 0x80, hi: 0x88}, | ||
2755 | {value: 0x0040, lo: 0x89, hi: 0x89}, | ||
2756 | {value: 0x0008, lo: 0x8a, hi: 0x8d}, | ||
2757 | {value: 0x0040, lo: 0x8e, hi: 0x8f}, | ||
2758 | {value: 0x0008, lo: 0x90, hi: 0xb0}, | ||
2759 | {value: 0x0040, lo: 0xb1, hi: 0xb1}, | ||
2760 | {value: 0x0008, lo: 0xb2, hi: 0xb5}, | ||
2761 | {value: 0x0040, lo: 0xb6, hi: 0xb7}, | ||
2762 | {value: 0x0008, lo: 0xb8, hi: 0xbe}, | ||
2763 | {value: 0x0040, lo: 0xbf, hi: 0xbf}, | ||
2764 | // Block 0x25, offset 0x180 | ||
2765 | {value: 0x0000, lo: 0x07}, | ||
2766 | {value: 0x0008, lo: 0x80, hi: 0x80}, | ||
2767 | {value: 0x0040, lo: 0x81, hi: 0x81}, | ||
2768 | {value: 0x0008, lo: 0x82, hi: 0x85}, | ||
2769 | {value: 0x0040, lo: 0x86, hi: 0x87}, | ||
2770 | {value: 0x0008, lo: 0x88, hi: 0x96}, | ||
2771 | {value: 0x0040, lo: 0x97, hi: 0x97}, | ||
2772 | {value: 0x0008, lo: 0x98, hi: 0xbf}, | ||
2773 | // Block 0x26, offset 0x188 | ||
2774 | {value: 0x0000, lo: 0x05}, | ||
2775 | {value: 0x0008, lo: 0x80, hi: 0x90}, | ||
2776 | {value: 0x0040, lo: 0x91, hi: 0x91}, | ||
2777 | {value: 0x0008, lo: 0x92, hi: 0x95}, | ||
2778 | {value: 0x0040, lo: 0x96, hi: 0x97}, | ||
2779 | {value: 0x0008, lo: 0x98, hi: 0xbf}, | ||
2780 | // Block 0x27, offset 0x18e | ||
2781 | {value: 0x0000, lo: 0x05}, | ||
2782 | {value: 0x0008, lo: 0x80, hi: 0x9a}, | ||
2783 | {value: 0x0040, lo: 0x9b, hi: 0x9c}, | ||
2784 | {value: 0x1308, lo: 0x9d, hi: 0x9f}, | ||
2785 | {value: 0x0018, lo: 0xa0, hi: 0xbc}, | ||
2786 | {value: 0x0040, lo: 0xbd, hi: 0xbf}, | ||
2787 | // Block 0x28, offset 0x194 | ||
2788 | {value: 0x0000, lo: 0x04}, | ||
2789 | {value: 0x0008, lo: 0x80, hi: 0x8f}, | ||
2790 | {value: 0x0018, lo: 0x90, hi: 0x99}, | ||
2791 | {value: 0x0040, lo: 0x9a, hi: 0x9f}, | ||
2792 | {value: 0x0008, lo: 0xa0, hi: 0xbf}, | ||
2793 | // Block 0x29, offset 0x199 | ||
2794 | {value: 0x0000, lo: 0x04}, | ||
2795 | {value: 0x0008, lo: 0x80, hi: 0xb5}, | ||
2796 | {value: 0x0040, lo: 0xb6, hi: 0xb7}, | ||
2797 | {value: 0xe045, lo: 0xb8, hi: 0xbd}, | ||
2798 | {value: 0x0040, lo: 0xbe, hi: 0xbf}, | ||
2799 | // Block 0x2a, offset 0x19e | ||
2800 | {value: 0x0000, lo: 0x02}, | ||
2801 | {value: 0x0018, lo: 0x80, hi: 0x80}, | ||
2802 | {value: 0x0008, lo: 0x81, hi: 0xbf}, | ||
2803 | // Block 0x2b, offset 0x1a1 | ||
2804 | {value: 0x0000, lo: 0x03}, | ||
2805 | {value: 0x0008, lo: 0x80, hi: 0xac}, | ||
2806 | {value: 0x0018, lo: 0xad, hi: 0xae}, | ||
2807 | {value: 0x0008, lo: 0xaf, hi: 0xbf}, | ||
2808 | // Block 0x2c, offset 0x1a5 | ||
2809 | {value: 0x0000, lo: 0x05}, | ||
2810 | {value: 0x0040, lo: 0x80, hi: 0x80}, | ||
2811 | {value: 0x0008, lo: 0x81, hi: 0x9a}, | ||
2812 | {value: 0x0018, lo: 0x9b, hi: 0x9c}, | ||
2813 | {value: 0x0040, lo: 0x9d, hi: 0x9f}, | ||
2814 | {value: 0x0008, lo: 0xa0, hi: 0xbf}, | ||
2815 | // Block 0x2d, offset 0x1ab | ||
2816 | {value: 0x0000, lo: 0x04}, | ||
2817 | {value: 0x0008, lo: 0x80, hi: 0xaa}, | ||
2818 | {value: 0x0018, lo: 0xab, hi: 0xb0}, | ||
2819 | {value: 0x0008, lo: 0xb1, hi: 0xb8}, | ||
2820 | {value: 0x0040, lo: 0xb9, hi: 0xbf}, | ||
2821 | // Block 0x2e, offset 0x1b0 | ||
2822 | {value: 0x0000, lo: 0x0b}, | ||
2823 | {value: 0x0008, lo: 0x80, hi: 0x8c}, | ||
2824 | {value: 0x0040, lo: 0x8d, hi: 0x8d}, | ||
2825 | {value: 0x0008, lo: 0x8e, hi: 0x91}, | ||
2826 | {value: 0x1308, lo: 0x92, hi: 0x93}, | ||
2827 | {value: 0x1b08, lo: 0x94, hi: 0x94}, | ||
2828 | {value: 0x0040, lo: 0x95, hi: 0x9f}, | ||
2829 | {value: 0x0008, lo: 0xa0, hi: 0xb1}, | ||
2830 | {value: 0x1308, lo: 0xb2, hi: 0xb3}, | ||
2831 | {value: 0x1b08, lo: 0xb4, hi: 0xb4}, | ||
2832 | {value: 0x0018, lo: 0xb5, hi: 0xb6}, | ||
2833 | {value: 0x0040, lo: 0xb7, hi: 0xbf}, | ||
2834 | // Block 0x2f, offset 0x1bc | ||
2835 | {value: 0x0000, lo: 0x09}, | ||
2836 | {value: 0x0008, lo: 0x80, hi: 0x91}, | ||
2837 | {value: 0x1308, lo: 0x92, hi: 0x93}, | ||
2838 | {value: 0x0040, lo: 0x94, hi: 0x9f}, | ||
2839 | {value: 0x0008, lo: 0xa0, hi: 0xac}, | ||
2840 | {value: 0x0040, lo: 0xad, hi: 0xad}, | ||
2841 | {value: 0x0008, lo: 0xae, hi: 0xb0}, | ||
2842 | {value: 0x0040, lo: 0xb1, hi: 0xb1}, | ||
2843 | {value: 0x1308, lo: 0xb2, hi: 0xb3}, | ||
2844 | {value: 0x0040, lo: 0xb4, hi: 0xbf}, | ||
2845 | // Block 0x30, offset 0x1c6 | ||
2846 | {value: 0x0000, lo: 0x05}, | ||
2847 | {value: 0x0008, lo: 0x80, hi: 0xb3}, | ||
2848 | {value: 0x1340, lo: 0xb4, hi: 0xb5}, | ||
2849 | {value: 0x1008, lo: 0xb6, hi: 0xb6}, | ||
2850 | {value: 0x1308, lo: 0xb7, hi: 0xbd}, | ||
2851 | {value: 0x1008, lo: 0xbe, hi: 0xbf}, | ||
2852 | // Block 0x31, offset 0x1cc | ||
2853 | {value: 0x0000, lo: 0x10}, | ||
2854 | {value: 0x1008, lo: 0x80, hi: 0x85}, | ||
2855 | {value: 0x1308, lo: 0x86, hi: 0x86}, | ||
2856 | {value: 0x1008, lo: 0x87, hi: 0x88}, | ||
2857 | {value: 0x1308, lo: 0x89, hi: 0x91}, | ||
2858 | {value: 0x1b08, lo: 0x92, hi: 0x92}, | ||
2859 | {value: 0x1308, lo: 0x93, hi: 0x93}, | ||
2860 | {value: 0x0018, lo: 0x94, hi: 0x96}, | ||
2861 | {value: 0x0008, lo: 0x97, hi: 0x97}, | ||
2862 | {value: 0x0018, lo: 0x98, hi: 0x9b}, | ||
2863 | {value: 0x0008, lo: 0x9c, hi: 0x9c}, | ||
2864 | {value: 0x1308, lo: 0x9d, hi: 0x9d}, | ||
2865 | {value: 0x0040, lo: 0x9e, hi: 0x9f}, | ||
2866 | {value: 0x0008, lo: 0xa0, hi: 0xa9}, | ||
2867 | {value: 0x0040, lo: 0xaa, hi: 0xaf}, | ||
2868 | {value: 0x0018, lo: 0xb0, hi: 0xb9}, | ||
2869 | {value: 0x0040, lo: 0xba, hi: 0xbf}, | ||
2870 | // Block 0x32, offset 0x1dd | ||
2871 | {value: 0x0000, lo: 0x09}, | ||
2872 | {value: 0x0018, lo: 0x80, hi: 0x85}, | ||
2873 | {value: 0x0040, lo: 0x86, hi: 0x86}, | ||
2874 | {value: 0x0218, lo: 0x87, hi: 0x87}, | ||
2875 | {value: 0x0018, lo: 0x88, hi: 0x8a}, | ||
2876 | {value: 0x13c0, lo: 0x8b, hi: 0x8d}, | ||
2877 | {value: 0x0040, lo: 0x8e, hi: 0x8f}, | ||
2878 | {value: 0x0008, lo: 0x90, hi: 0x99}, | ||
2879 | {value: 0x0040, lo: 0x9a, hi: 0x9f}, | ||
2880 | {value: 0x0208, lo: 0xa0, hi: 0xbf}, | ||
2881 | // Block 0x33, offset 0x1e7 | ||
2882 | {value: 0x0000, lo: 0x02}, | ||
2883 | {value: 0x0208, lo: 0x80, hi: 0xb7}, | ||
2884 | {value: 0x0040, lo: 0xb8, hi: 0xbf}, | ||
2885 | // Block 0x34, offset 0x1ea | ||
2886 | {value: 0x0000, lo: 0x07}, | ||
2887 | {value: 0x0008, lo: 0x80, hi: 0x84}, | ||
2888 | {value: 0x1308, lo: 0x85, hi: 0x86}, | ||
2889 | {value: 0x0208, lo: 0x87, hi: 0xa8}, | ||
2890 | {value: 0x1308, lo: 0xa9, hi: 0xa9}, | ||
2891 | {value: 0x0208, lo: 0xaa, hi: 0xaa}, | ||
2892 | {value: 0x0040, lo: 0xab, hi: 0xaf}, | ||
2893 | {value: 0x0008, lo: 0xb0, hi: 0xbf}, | ||
2894 | // Block 0x35, offset 0x1f2 | ||
2895 | {value: 0x0000, lo: 0x02}, | ||
2896 | {value: 0x0008, lo: 0x80, hi: 0xb5}, | ||
2897 | {value: 0x0040, lo: 0xb6, hi: 0xbf}, | ||
2898 | // Block 0x36, offset 0x1f5 | ||
2899 | {value: 0x0000, lo: 0x0c}, | ||
2900 | {value: 0x0008, lo: 0x80, hi: 0x9e}, | ||
2901 | {value: 0x0040, lo: 0x9f, hi: 0x9f}, | ||
2902 | {value: 0x1308, lo: 0xa0, hi: 0xa2}, | ||
2903 | {value: 0x1008, lo: 0xa3, hi: 0xa6}, | ||
2904 | {value: 0x1308, lo: 0xa7, hi: 0xa8}, | ||
2905 | {value: 0x1008, lo: 0xa9, hi: 0xab}, | ||
2906 | {value: 0x0040, lo: 0xac, hi: 0xaf}, | ||
2907 | {value: 0x1008, lo: 0xb0, hi: 0xb1}, | ||
2908 | {value: 0x1308, lo: 0xb2, hi: 0xb2}, | ||
2909 | {value: 0x1008, lo: 0xb3, hi: 0xb8}, | ||
2910 | {value: 0x1308, lo: 0xb9, hi: 0xbb}, | ||
2911 | {value: 0x0040, lo: 0xbc, hi: 0xbf}, | ||
2912 | // Block 0x37, offset 0x202 | ||
2913 | {value: 0x0000, lo: 0x07}, | ||
2914 | {value: 0x0018, lo: 0x80, hi: 0x80}, | ||
2915 | {value: 0x0040, lo: 0x81, hi: 0x83}, | ||
2916 | {value: 0x0018, lo: 0x84, hi: 0x85}, | ||
2917 | {value: 0x0008, lo: 0x86, hi: 0xad}, | ||
2918 | {value: 0x0040, lo: 0xae, hi: 0xaf}, | ||
2919 | {value: 0x0008, lo: 0xb0, hi: 0xb4}, | ||
2920 | {value: 0x0040, lo: 0xb5, hi: 0xbf}, | ||
2921 | // Block 0x38, offset 0x20a | ||
2922 | {value: 0x0000, lo: 0x03}, | ||
2923 | {value: 0x0008, lo: 0x80, hi: 0xab}, | ||
2924 | {value: 0x0040, lo: 0xac, hi: 0xaf}, | ||
2925 | {value: 0x0008, lo: 0xb0, hi: 0xbf}, | ||
2926 | // Block 0x39, offset 0x20e | ||
2927 | {value: 0x0000, lo: 0x06}, | ||
2928 | {value: 0x0008, lo: 0x80, hi: 0x89}, | ||
2929 | {value: 0x0040, lo: 0x8a, hi: 0x8f}, | ||
2930 | {value: 0x0008, lo: 0x90, hi: 0x99}, | ||
2931 | {value: 0x0028, lo: 0x9a, hi: 0x9a}, | ||
2932 | {value: 0x0040, lo: 0x9b, hi: 0x9d}, | ||
2933 | {value: 0x0018, lo: 0x9e, hi: 0xbf}, | ||
2934 | // Block 0x3a, offset 0x215 | ||
2935 | {value: 0x0000, lo: 0x07}, | ||
2936 | {value: 0x0008, lo: 0x80, hi: 0x96}, | ||
2937 | {value: 0x1308, lo: 0x97, hi: 0x98}, | ||
2938 | {value: 0x1008, lo: 0x99, hi: 0x9a}, | ||
2939 | {value: 0x1308, lo: 0x9b, hi: 0x9b}, | ||
2940 | {value: 0x0040, lo: 0x9c, hi: 0x9d}, | ||
2941 | {value: 0x0018, lo: 0x9e, hi: 0x9f}, | ||
2942 | {value: 0x0008, lo: 0xa0, hi: 0xbf}, | ||
2943 | // Block 0x3b, offset 0x21d | ||
2944 | {value: 0x0000, lo: 0x0f}, | ||
2945 | {value: 0x0008, lo: 0x80, hi: 0x94}, | ||
2946 | {value: 0x1008, lo: 0x95, hi: 0x95}, | ||
2947 | {value: 0x1308, lo: 0x96, hi: 0x96}, | ||
2948 | {value: 0x1008, lo: 0x97, hi: 0x97}, | ||
2949 | {value: 0x1308, lo: 0x98, hi: 0x9e}, | ||
2950 | {value: 0x0040, lo: 0x9f, hi: 0x9f}, | ||
2951 | {value: 0x1b08, lo: 0xa0, hi: 0xa0}, | ||
2952 | {value: 0x1008, lo: 0xa1, hi: 0xa1}, | ||
2953 | {value: 0x1308, lo: 0xa2, hi: 0xa2}, | ||
2954 | {value: 0x1008, lo: 0xa3, hi: 0xa4}, | ||
2955 | {value: 0x1308, lo: 0xa5, hi: 0xac}, | ||
2956 | {value: 0x1008, lo: 0xad, hi: 0xb2}, | ||
2957 | {value: 0x1308, lo: 0xb3, hi: 0xbc}, | ||
2958 | {value: 0x0040, lo: 0xbd, hi: 0xbe}, | ||
2959 | {value: 0x1308, lo: 0xbf, hi: 0xbf}, | ||
2960 | // Block 0x3c, offset 0x22d | ||
2961 | {value: 0x0000, lo: 0x0b}, | ||
2962 | {value: 0x0008, lo: 0x80, hi: 0x89}, | ||
2963 | {value: 0x0040, lo: 0x8a, hi: 0x8f}, | ||
2964 | {value: 0x0008, lo: 0x90, hi: 0x99}, | ||
2965 | {value: 0x0040, lo: 0x9a, hi: 0x9f}, | ||
2966 | {value: 0x0018, lo: 0xa0, hi: 0xa6}, | ||
2967 | {value: 0x0008, lo: 0xa7, hi: 0xa7}, | ||
2968 | {value: 0x0018, lo: 0xa8, hi: 0xad}, | ||
2969 | {value: 0x0040, lo: 0xae, hi: 0xaf}, | ||
2970 | {value: 0x1308, lo: 0xb0, hi: 0xbd}, | ||
2971 | {value: 0x1318, lo: 0xbe, hi: 0xbe}, | ||
2972 | {value: 0x0040, lo: 0xbf, hi: 0xbf}, | ||
2973 | // Block 0x3d, offset 0x239 | ||
2974 | {value: 0x0000, lo: 0x01}, | ||
2975 | {value: 0x0040, lo: 0x80, hi: 0xbf}, | ||
2976 | // Block 0x3e, offset 0x23b | ||
2977 | {value: 0x0000, lo: 0x09}, | ||
2978 | {value: 0x1308, lo: 0x80, hi: 0x83}, | ||
2979 | {value: 0x1008, lo: 0x84, hi: 0x84}, | ||
2980 | {value: 0x0008, lo: 0x85, hi: 0xb3}, | ||
2981 | {value: 0x1308, lo: 0xb4, hi: 0xb4}, | ||
2982 | {value: 0x1008, lo: 0xb5, hi: 0xb5}, | ||
2983 | {value: 0x1308, lo: 0xb6, hi: 0xba}, | ||
2984 | {value: 0x1008, lo: 0xbb, hi: 0xbb}, | ||
2985 | {value: 0x1308, lo: 0xbc, hi: 0xbc}, | ||
2986 | {value: 0x1008, lo: 0xbd, hi: 0xbf}, | ||
2987 | // Block 0x3f, offset 0x245 | ||
2988 | {value: 0x0000, lo: 0x0b}, | ||
2989 | {value: 0x1008, lo: 0x80, hi: 0x81}, | ||
2990 | {value: 0x1308, lo: 0x82, hi: 0x82}, | ||
2991 | {value: 0x1008, lo: 0x83, hi: 0x83}, | ||
2992 | {value: 0x1808, lo: 0x84, hi: 0x84}, | ||
2993 | {value: 0x0008, lo: 0x85, hi: 0x8b}, | ||
2994 | {value: 0x0040, lo: 0x8c, hi: 0x8f}, | ||
2995 | {value: 0x0008, lo: 0x90, hi: 0x99}, | ||
2996 | {value: 0x0018, lo: 0x9a, hi: 0xaa}, | ||
2997 | {value: 0x1308, lo: 0xab, hi: 0xb3}, | ||
2998 | {value: 0x0018, lo: 0xb4, hi: 0xbc}, | ||
2999 | {value: 0x0040, lo: 0xbd, hi: 0xbf}, | ||
3000 | // Block 0x40, offset 0x251 | ||
3001 | {value: 0x0000, lo: 0x0b}, | ||
3002 | {value: 0x1308, lo: 0x80, hi: 0x81}, | ||
3003 | {value: 0x1008, lo: 0x82, hi: 0x82}, | ||
3004 | {value: 0x0008, lo: 0x83, hi: 0xa0}, | ||
3005 | {value: 0x1008, lo: 0xa1, hi: 0xa1}, | ||
3006 | {value: 0x1308, lo: 0xa2, hi: 0xa5}, | ||
3007 | {value: 0x1008, lo: 0xa6, hi: 0xa7}, | ||
3008 | {value: 0x1308, lo: 0xa8, hi: 0xa9}, | ||
3009 | {value: 0x1808, lo: 0xaa, hi: 0xaa}, | ||
3010 | {value: 0x1b08, lo: 0xab, hi: 0xab}, | ||
3011 | {value: 0x1308, lo: 0xac, hi: 0xad}, | ||
3012 | {value: 0x0008, lo: 0xae, hi: 0xbf}, | ||
3013 | // Block 0x41, offset 0x25d | ||
3014 | {value: 0x0000, lo: 0x0b}, | ||
3015 | {value: 0x0008, lo: 0x80, hi: 0xa5}, | ||
3016 | {value: 0x1308, lo: 0xa6, hi: 0xa6}, | ||
3017 | {value: 0x1008, lo: 0xa7, hi: 0xa7}, | ||
3018 | {value: 0x1308, lo: 0xa8, hi: 0xa9}, | ||
3019 | {value: 0x1008, lo: 0xaa, hi: 0xac}, | ||
3020 | {value: 0x1308, lo: 0xad, hi: 0xad}, | ||
3021 | {value: 0x1008, lo: 0xae, hi: 0xae}, | ||
3022 | {value: 0x1308, lo: 0xaf, hi: 0xb1}, | ||
3023 | {value: 0x1808, lo: 0xb2, hi: 0xb3}, | ||
3024 | {value: 0x0040, lo: 0xb4, hi: 0xbb}, | ||
3025 | {value: 0x0018, lo: 0xbc, hi: 0xbf}, | ||
3026 | // Block 0x42, offset 0x269 | ||
3027 | {value: 0x0000, lo: 0x07}, | ||
3028 | {value: 0x0008, lo: 0x80, hi: 0xa3}, | ||
3029 | {value: 0x1008, lo: 0xa4, hi: 0xab}, | ||
3030 | {value: 0x1308, lo: 0xac, hi: 0xb3}, | ||
3031 | {value: 0x1008, lo: 0xb4, hi: 0xb5}, | ||
3032 | {value: 0x1308, lo: 0xb6, hi: 0xb7}, | ||
3033 | {value: 0x0040, lo: 0xb8, hi: 0xba}, | ||
3034 | {value: 0x0018, lo: 0xbb, hi: 0xbf}, | ||
3035 | // Block 0x43, offset 0x271 | ||
3036 | {value: 0x0000, lo: 0x04}, | ||
3037 | {value: 0x0008, lo: 0x80, hi: 0x89}, | ||
3038 | {value: 0x0040, lo: 0x8a, hi: 0x8c}, | ||
3039 | {value: 0x0008, lo: 0x8d, hi: 0xbd}, | ||
3040 | {value: 0x0018, lo: 0xbe, hi: 0xbf}, | ||
3041 | // Block 0x44, offset 0x276 | ||
3042 | {value: 0x0000, lo: 0x09}, | ||
3043 | {value: 0x0e29, lo: 0x80, hi: 0x80}, | ||
3044 | {value: 0x0e41, lo: 0x81, hi: 0x81}, | ||
3045 | {value: 0x0e59, lo: 0x82, hi: 0x82}, | ||
3046 | {value: 0x0e71, lo: 0x83, hi: 0x83}, | ||
3047 | {value: 0x0e89, lo: 0x84, hi: 0x85}, | ||
3048 | {value: 0x0ea1, lo: 0x86, hi: 0x86}, | ||
3049 | {value: 0x0eb9, lo: 0x87, hi: 0x87}, | ||
3050 | {value: 0x057d, lo: 0x88, hi: 0x88}, | ||
3051 | {value: 0x0040, lo: 0x89, hi: 0xbf}, | ||
3052 | // Block 0x45, offset 0x280 | ||
3053 | {value: 0x0000, lo: 0x10}, | ||
3054 | {value: 0x0018, lo: 0x80, hi: 0x87}, | ||
3055 | {value: 0x0040, lo: 0x88, hi: 0x8f}, | ||
3056 | {value: 0x1308, lo: 0x90, hi: 0x92}, | ||
3057 | {value: 0x0018, lo: 0x93, hi: 0x93}, | ||
3058 | {value: 0x1308, lo: 0x94, hi: 0xa0}, | ||
3059 | {value: 0x1008, lo: 0xa1, hi: 0xa1}, | ||
3060 | {value: 0x1308, lo: 0xa2, hi: 0xa8}, | ||
3061 | {value: 0x0008, lo: 0xa9, hi: 0xac}, | ||
3062 | {value: 0x1308, lo: 0xad, hi: 0xad}, | ||
3063 | {value: 0x0008, lo: 0xae, hi: 0xb1}, | ||
3064 | {value: 0x1008, lo: 0xb2, hi: 0xb3}, | ||
3065 | {value: 0x1308, lo: 0xb4, hi: 0xb4}, | ||
3066 | {value: 0x0008, lo: 0xb5, hi: 0xb6}, | ||
3067 | {value: 0x0040, lo: 0xb7, hi: 0xb7}, | ||
3068 | {value: 0x1308, lo: 0xb8, hi: 0xb9}, | ||
3069 | {value: 0x0040, lo: 0xba, hi: 0xbf}, | ||
3070 | // Block 0x46, offset 0x291 | ||
3071 | {value: 0x0000, lo: 0x03}, | ||
3072 | {value: 0x1308, lo: 0x80, hi: 0xb5}, | ||
3073 | {value: 0x0040, lo: 0xb6, hi: 0xba}, | ||
3074 | {value: 0x1308, lo: 0xbb, hi: 0xbf}, | ||
3075 | // Block 0x47, offset 0x295 | ||
3076 | {value: 0x0000, lo: 0x0a}, | ||
3077 | {value: 0x0008, lo: 0x80, hi: 0x87}, | ||
3078 | {value: 0xe045, lo: 0x88, hi: 0x8f}, | ||
3079 | {value: 0x0008, lo: 0x90, hi: 0x95}, | ||
3080 | {value: 0x0040, lo: 0x96, hi: 0x97}, | ||
3081 | {value: 0xe045, lo: 0x98, hi: 0x9d}, | ||
3082 | {value: 0x0040, lo: 0x9e, hi: 0x9f}, | ||
3083 | {value: 0x0008, lo: 0xa0, hi: 0xa7}, | ||
3084 | {value: 0xe045, lo: 0xa8, hi: 0xaf}, | ||
3085 | {value: 0x0008, lo: 0xb0, hi: 0xb7}, | ||
3086 | {value: 0xe045, lo: 0xb8, hi: 0xbf}, | ||
3087 | // Block 0x48, offset 0x2a0 | ||
3088 | {value: 0x0000, lo: 0x03}, | ||
3089 | {value: 0x0040, lo: 0x80, hi: 0x8f}, | ||
3090 | {value: 0x1318, lo: 0x90, hi: 0xb0}, | ||
3091 | {value: 0x0040, lo: 0xb1, hi: 0xbf}, | ||
3092 | // Block 0x49, offset 0x2a4 | ||
3093 | {value: 0x0000, lo: 0x08}, | ||
3094 | {value: 0x0018, lo: 0x80, hi: 0x82}, | ||
3095 | {value: 0x0040, lo: 0x83, hi: 0x83}, | ||
3096 | {value: 0x0008, lo: 0x84, hi: 0x84}, | ||
3097 | {value: 0x0018, lo: 0x85, hi: 0x88}, | ||
3098 | {value: 0x24c1, lo: 0x89, hi: 0x89}, | ||
3099 | {value: 0x0018, lo: 0x8a, hi: 0x8b}, | ||
3100 | {value: 0x0040, lo: 0x8c, hi: 0x8f}, | ||
3101 | {value: 0x0018, lo: 0x90, hi: 0xbf}, | ||
3102 | // Block 0x4a, offset 0x2ad | ||
3103 | {value: 0x0000, lo: 0x07}, | ||
3104 | {value: 0x0018, lo: 0x80, hi: 0xab}, | ||
3105 | {value: 0x24f1, lo: 0xac, hi: 0xac}, | ||
3106 | {value: 0x2529, lo: 0xad, hi: 0xad}, | ||
3107 | {value: 0x0018, lo: 0xae, hi: 0xae}, | ||
3108 | {value: 0x2579, lo: 0xaf, hi: 0xaf}, | ||
3109 | {value: 0x25b1, lo: 0xb0, hi: 0xb0}, | ||
3110 | {value: 0x0018, lo: 0xb1, hi: 0xbf}, | ||
3111 | // Block 0x4b, offset 0x2b5 | ||
3112 | {value: 0x0000, lo: 0x05}, | ||
3113 | {value: 0x0018, lo: 0x80, hi: 0x9f}, | ||
3114 | {value: 0x0080, lo: 0xa0, hi: 0xa0}, | ||
3115 | {value: 0x0018, lo: 0xa1, hi: 0xad}, | ||
3116 | {value: 0x0080, lo: 0xae, hi: 0xaf}, | ||
3117 | {value: 0x0018, lo: 0xb0, hi: 0xbf}, | ||
3118 | // Block 0x4c, offset 0x2bb | ||
3119 | {value: 0x0000, lo: 0x04}, | ||
3120 | {value: 0x0018, lo: 0x80, hi: 0xa8}, | ||
3121 | {value: 0x09c5, lo: 0xa9, hi: 0xa9}, | ||
3122 | {value: 0x09e5, lo: 0xaa, hi: 0xaa}, | ||
3123 | {value: 0x0018, lo: 0xab, hi: 0xbf}, | ||
3124 | // Block 0x4d, offset 0x2c0 | ||
3125 | {value: 0x0000, lo: 0x02}, | ||
3126 | {value: 0x0018, lo: 0x80, hi: 0xbe}, | ||
3127 | {value: 0x0040, lo: 0xbf, hi: 0xbf}, | ||
3128 | // Block 0x4e, offset 0x2c3 | ||
3129 | {value: 0x0000, lo: 0x02}, | ||
3130 | {value: 0x0018, lo: 0x80, hi: 0xa6}, | ||
3131 | {value: 0x0040, lo: 0xa7, hi: 0xbf}, | ||
3132 | // Block 0x4f, offset 0x2c6 | ||
3133 | {value: 0x0000, lo: 0x03}, | ||
3134 | {value: 0x0018, lo: 0x80, hi: 0x8b}, | ||
3135 | {value: 0x28c1, lo: 0x8c, hi: 0x8c}, | ||
3136 | {value: 0x0018, lo: 0x8d, hi: 0xbf}, | ||
3137 | // Block 0x50, offset 0x2ca | ||
3138 | {value: 0x0000, lo: 0x05}, | ||
3139 | {value: 0x0018, lo: 0x80, hi: 0xb3}, | ||
3140 | {value: 0x0e66, lo: 0xb4, hi: 0xb4}, | ||
3141 | {value: 0x292a, lo: 0xb5, hi: 0xb5}, | ||
3142 | {value: 0x0e86, lo: 0xb6, hi: 0xb6}, | ||
3143 | {value: 0x0018, lo: 0xb7, hi: 0xbf}, | ||
3144 | // Block 0x51, offset 0x2d0 | ||
3145 | {value: 0x0000, lo: 0x03}, | ||
3146 | {value: 0x0018, lo: 0x80, hi: 0x9b}, | ||
3147 | {value: 0x2941, lo: 0x9c, hi: 0x9c}, | ||
3148 | {value: 0x0018, lo: 0x9d, hi: 0xbf}, | ||
3149 | // Block 0x52, offset 0x2d4 | ||
3150 | {value: 0x0000, lo: 0x03}, | ||
3151 | {value: 0x0018, lo: 0x80, hi: 0xb3}, | ||
3152 | {value: 0x0040, lo: 0xb4, hi: 0xb5}, | ||
3153 | {value: 0x0018, lo: 0xb6, hi: 0xbf}, | ||
3154 | // Block 0x53, offset 0x2d8 | ||
3155 | {value: 0x0000, lo: 0x05}, | ||
3156 | {value: 0x0018, lo: 0x80, hi: 0x95}, | ||
3157 | {value: 0x0040, lo: 0x96, hi: 0x97}, | ||
3158 | {value: 0x0018, lo: 0x98, hi: 0xb9}, | ||
3159 | {value: 0x0040, lo: 0xba, hi: 0xbc}, | ||
3160 | {value: 0x0018, lo: 0xbd, hi: 0xbf}, | ||
3161 | // Block 0x54, offset 0x2de | ||
3162 | {value: 0x0000, lo: 0x06}, | ||
3163 | {value: 0x0018, lo: 0x80, hi: 0x88}, | ||
3164 | {value: 0x0040, lo: 0x89, hi: 0x89}, | ||
3165 | {value: 0x0018, lo: 0x8a, hi: 0x91}, | ||
3166 | {value: 0x0040, lo: 0x92, hi: 0xab}, | ||
3167 | {value: 0x0018, lo: 0xac, hi: 0xaf}, | ||
3168 | {value: 0x0040, lo: 0xb0, hi: 0xbf}, | ||
3169 | // Block 0x55, offset 0x2e5 | ||
3170 | {value: 0x0000, lo: 0x05}, | ||
3171 | {value: 0xe185, lo: 0x80, hi: 0x8f}, | ||
3172 | {value: 0x03f5, lo: 0x90, hi: 0x9f}, | ||
3173 | {value: 0x0ea5, lo: 0xa0, hi: 0xae}, | ||
3174 | {value: 0x0040, lo: 0xaf, hi: 0xaf}, | ||
3175 | {value: 0x0008, lo: 0xb0, hi: 0xbf}, | ||
3176 | // Block 0x56, offset 0x2eb | ||
3177 | {value: 0x0000, lo: 0x07}, | ||
3178 | {value: 0x0008, lo: 0x80, hi: 0xa5}, | ||
3179 | {value: 0x0040, lo: 0xa6, hi: 0xa6}, | ||
3180 | {value: 0x0008, lo: 0xa7, hi: 0xa7}, | ||
3181 | {value: 0x0040, lo: 0xa8, hi: 0xac}, | ||
3182 | {value: 0x0008, lo: 0xad, hi: 0xad}, | ||
3183 | {value: 0x0040, lo: 0xae, hi: 0xaf}, | ||
3184 | {value: 0x0008, lo: 0xb0, hi: 0xbf}, | ||
3185 | // Block 0x57, offset 0x2f3 | ||
3186 | {value: 0x0000, lo: 0x06}, | ||
3187 | {value: 0x0008, lo: 0x80, hi: 0xa7}, | ||
3188 | {value: 0x0040, lo: 0xa8, hi: 0xae}, | ||
3189 | {value: 0xe075, lo: 0xaf, hi: 0xaf}, | ||
3190 | {value: 0x0018, lo: 0xb0, hi: 0xb0}, | ||
3191 | {value: 0x0040, lo: 0xb1, hi: 0xbe}, | ||
3192 | {value: 0x1b08, lo: 0xbf, hi: 0xbf}, | ||
3193 | // Block 0x58, offset 0x2fa | ||
3194 | {value: 0x0000, lo: 0x0a}, | ||
3195 | {value: 0x0008, lo: 0x80, hi: 0x96}, | ||
3196 | {value: 0x0040, lo: 0x97, hi: 0x9f}, | ||
3197 | {value: 0x0008, lo: 0xa0, hi: 0xa6}, | ||
3198 | {value: 0x0040, lo: 0xa7, hi: 0xa7}, | ||
3199 | {value: 0x0008, lo: 0xa8, hi: 0xae}, | ||
3200 | {value: 0x0040, lo: 0xaf, hi: 0xaf}, | ||
3201 | {value: 0x0008, lo: 0xb0, hi: 0xb6}, | ||
3202 | {value: 0x0040, lo: 0xb7, hi: 0xb7}, | ||
3203 | {value: 0x0008, lo: 0xb8, hi: 0xbe}, | ||
3204 | {value: 0x0040, lo: 0xbf, hi: 0xbf}, | ||
3205 | // Block 0x59, offset 0x305 | ||
3206 | {value: 0x0000, lo: 0x09}, | ||
3207 | {value: 0x0008, lo: 0x80, hi: 0x86}, | ||
3208 | {value: 0x0040, lo: 0x87, hi: 0x87}, | ||
3209 | {value: 0x0008, lo: 0x88, hi: 0x8e}, | ||
3210 | {value: 0x0040, lo: 0x8f, hi: 0x8f}, | ||
3211 | {value: 0x0008, lo: 0x90, hi: 0x96}, | ||
3212 | {value: 0x0040, lo: 0x97, hi: 0x97}, | ||
3213 | {value: 0x0008, lo: 0x98, hi: 0x9e}, | ||
3214 | {value: 0x0040, lo: 0x9f, hi: 0x9f}, | ||
3215 | {value: 0x1308, lo: 0xa0, hi: 0xbf}, | ||
3216 | // Block 0x5a, offset 0x30f | ||
3217 | {value: 0x0000, lo: 0x03}, | ||
3218 | {value: 0x0018, lo: 0x80, hi: 0xae}, | ||
3219 | {value: 0x0008, lo: 0xaf, hi: 0xaf}, | ||
3220 | {value: 0x0018, lo: 0xb0, hi: 0xbf}, | ||
3221 | // Block 0x5b, offset 0x313 | ||
3222 | {value: 0x0000, lo: 0x02}, | ||
3223 | {value: 0x0018, lo: 0x80, hi: 0x84}, | ||
3224 | {value: 0x0040, lo: 0x85, hi: 0xbf}, | ||
3225 | // Block 0x5c, offset 0x316 | ||
3226 | {value: 0x0000, lo: 0x05}, | ||
3227 | {value: 0x0018, lo: 0x80, hi: 0x99}, | ||
3228 | {value: 0x0040, lo: 0x9a, hi: 0x9a}, | ||
3229 | {value: 0x0018, lo: 0x9b, hi: 0x9e}, | ||
3230 | {value: 0x0edd, lo: 0x9f, hi: 0x9f}, | ||
3231 | {value: 0x0018, lo: 0xa0, hi: 0xbf}, | ||
3232 | // Block 0x5d, offset 0x31c | ||
3233 | {value: 0x0000, lo: 0x03}, | ||
3234 | {value: 0x0018, lo: 0x80, hi: 0xb2}, | ||
3235 | {value: 0x0efd, lo: 0xb3, hi: 0xb3}, | ||
3236 | {value: 0x0040, lo: 0xb4, hi: 0xbf}, | ||
3237 | // Block 0x5e, offset 0x320 | ||
3238 | {value: 0x0020, lo: 0x01}, | ||
3239 | {value: 0x0f1d, lo: 0x80, hi: 0xbf}, | ||
3240 | // Block 0x5f, offset 0x322 | ||
3241 | {value: 0x0020, lo: 0x02}, | ||
3242 | {value: 0x171d, lo: 0x80, hi: 0x8f}, | ||
3243 | {value: 0x18fd, lo: 0x90, hi: 0xbf}, | ||
3244 | // Block 0x60, offset 0x325 | ||
3245 | {value: 0x0020, lo: 0x01}, | ||
3246 | {value: 0x1efd, lo: 0x80, hi: 0xbf}, | ||
3247 | // Block 0x61, offset 0x327 | ||
3248 | {value: 0x0000, lo: 0x02}, | ||
3249 | {value: 0x0040, lo: 0x80, hi: 0x80}, | ||
3250 | {value: 0x0008, lo: 0x81, hi: 0xbf}, | ||
3251 | // Block 0x62, offset 0x32a | ||
3252 | {value: 0x0000, lo: 0x09}, | ||
3253 | {value: 0x0008, lo: 0x80, hi: 0x96}, | ||
3254 | {value: 0x0040, lo: 0x97, hi: 0x98}, | ||
3255 | {value: 0x1308, lo: 0x99, hi: 0x9a}, | ||
3256 | {value: 0x29e2, lo: 0x9b, hi: 0x9b}, | ||
3257 | {value: 0x2a0a, lo: 0x9c, hi: 0x9c}, | ||
3258 | {value: 0x0008, lo: 0x9d, hi: 0x9e}, | ||
3259 | {value: 0x2a31, lo: 0x9f, hi: 0x9f}, | ||
3260 | {value: 0x0018, lo: 0xa0, hi: 0xa0}, | ||
3261 | {value: 0x0008, lo: 0xa1, hi: 0xbf}, | ||
3262 | // Block 0x63, offset 0x334 | ||
3263 | {value: 0x0000, lo: 0x02}, | ||
3264 | {value: 0x0008, lo: 0x80, hi: 0xbe}, | ||
3265 | {value: 0x2a69, lo: 0xbf, hi: 0xbf}, | ||
3266 | // Block 0x64, offset 0x337 | ||
3267 | {value: 0x0000, lo: 0x0e}, | ||
3268 | {value: 0x0040, lo: 0x80, hi: 0x84}, | ||
3269 | {value: 0x0008, lo: 0x85, hi: 0xad}, | ||
3270 | {value: 0x0040, lo: 0xae, hi: 0xb0}, | ||
3271 | {value: 0x2a1d, lo: 0xb1, hi: 0xb1}, | ||
3272 | {value: 0x2a3d, lo: 0xb2, hi: 0xb2}, | ||
3273 | {value: 0x2a5d, lo: 0xb3, hi: 0xb3}, | ||
3274 | {value: 0x2a7d, lo: 0xb4, hi: 0xb4}, | ||
3275 | {value: 0x2a5d, lo: 0xb5, hi: 0xb5}, | ||
3276 | {value: 0x2a9d, lo: 0xb6, hi: 0xb6}, | ||
3277 | {value: 0x2abd, lo: 0xb7, hi: 0xb7}, | ||
3278 | {value: 0x2add, lo: 0xb8, hi: 0xb9}, | ||
3279 | {value: 0x2afd, lo: 0xba, hi: 0xbb}, | ||
3280 | {value: 0x2b1d, lo: 0xbc, hi: 0xbd}, | ||
3281 | {value: 0x2afd, lo: 0xbe, hi: 0xbf}, | ||
3282 | // Block 0x65, offset 0x346 | ||
3283 | {value: 0x0000, lo: 0x03}, | ||
3284 | {value: 0x0018, lo: 0x80, hi: 0xa3}, | ||
3285 | {value: 0x0040, lo: 0xa4, hi: 0xaf}, | ||
3286 | {value: 0x0008, lo: 0xb0, hi: 0xbf}, | ||
3287 | // Block 0x66, offset 0x34a | ||
3288 | {value: 0x0030, lo: 0x04}, | ||
3289 | {value: 0x2aa2, lo: 0x80, hi: 0x9d}, | ||
3290 | {value: 0x305a, lo: 0x9e, hi: 0x9e}, | ||
3291 | {value: 0x0040, lo: 0x9f, hi: 0x9f}, | ||
3292 | {value: 0x30a2, lo: 0xa0, hi: 0xbf}, | ||
3293 | // Block 0x67, offset 0x34f | ||
3294 | {value: 0x0000, lo: 0x02}, | ||
3295 | {value: 0x0008, lo: 0x80, hi: 0x95}, | ||
3296 | {value: 0x0040, lo: 0x96, hi: 0xbf}, | ||
3297 | // Block 0x68, offset 0x352 | ||
3298 | {value: 0x0000, lo: 0x03}, | ||
3299 | {value: 0x0008, lo: 0x80, hi: 0x8c}, | ||
3300 | {value: 0x0040, lo: 0x8d, hi: 0x8f}, | ||
3301 | {value: 0x0018, lo: 0x90, hi: 0xbf}, | ||
3302 | // Block 0x69, offset 0x356 | ||
3303 | {value: 0x0000, lo: 0x04}, | ||
3304 | {value: 0x0018, lo: 0x80, hi: 0x86}, | ||
3305 | {value: 0x0040, lo: 0x87, hi: 0x8f}, | ||
3306 | {value: 0x0008, lo: 0x90, hi: 0xbd}, | ||
3307 | {value: 0x0018, lo: 0xbe, hi: 0xbf}, | ||
3308 | // Block 0x6a, offset 0x35b | ||
3309 | {value: 0x0000, lo: 0x04}, | ||
3310 | {value: 0x0008, lo: 0x80, hi: 0x8c}, | ||
3311 | {value: 0x0018, lo: 0x8d, hi: 0x8f}, | ||
3312 | {value: 0x0008, lo: 0x90, hi: 0xab}, | ||
3313 | {value: 0x0040, lo: 0xac, hi: 0xbf}, | ||
3314 | // Block 0x6b, offset 0x360 | ||
3315 | {value: 0x0000, lo: 0x05}, | ||
3316 | {value: 0x0008, lo: 0x80, hi: 0xa5}, | ||
3317 | {value: 0x0018, lo: 0xa6, hi: 0xaf}, | ||
3318 | {value: 0x1308, lo: 0xb0, hi: 0xb1}, | ||
3319 | {value: 0x0018, lo: 0xb2, hi: 0xb7}, | ||
3320 | {value: 0x0040, lo: 0xb8, hi: 0xbf}, | ||
3321 | // Block 0x6c, offset 0x366 | ||
3322 | {value: 0x0000, lo: 0x05}, | ||
3323 | {value: 0x0040, lo: 0x80, hi: 0xb6}, | ||
3324 | {value: 0x0008, lo: 0xb7, hi: 0xb7}, | ||
3325 | {value: 0x2009, lo: 0xb8, hi: 0xb8}, | ||
3326 | {value: 0x6e89, lo: 0xb9, hi: 0xb9}, | ||
3327 | {value: 0x0008, lo: 0xba, hi: 0xbf}, | ||
3328 | // Block 0x6d, offset 0x36c | ||
3329 | {value: 0x0000, lo: 0x0e}, | ||
3330 | {value: 0x0008, lo: 0x80, hi: 0x81}, | ||
3331 | {value: 0x1308, lo: 0x82, hi: 0x82}, | ||
3332 | {value: 0x0008, lo: 0x83, hi: 0x85}, | ||
3333 | {value: 0x1b08, lo: 0x86, hi: 0x86}, | ||
3334 | {value: 0x0008, lo: 0x87, hi: 0x8a}, | ||
3335 | {value: 0x1308, lo: 0x8b, hi: 0x8b}, | ||
3336 | {value: 0x0008, lo: 0x8c, hi: 0xa2}, | ||
3337 | {value: 0x1008, lo: 0xa3, hi: 0xa4}, | ||
3338 | {value: 0x1308, lo: 0xa5, hi: 0xa6}, | ||
3339 | {value: 0x1008, lo: 0xa7, hi: 0xa7}, | ||
3340 | {value: 0x0018, lo: 0xa8, hi: 0xab}, | ||
3341 | {value: 0x0040, lo: 0xac, hi: 0xaf}, | ||
3342 | {value: 0x0018, lo: 0xb0, hi: 0xb9}, | ||
3343 | {value: 0x0040, lo: 0xba, hi: 0xbf}, | ||
3344 | // Block 0x6e, offset 0x37b | ||
3345 | {value: 0x0000, lo: 0x05}, | ||
3346 | {value: 0x0208, lo: 0x80, hi: 0xb1}, | ||
3347 | {value: 0x0108, lo: 0xb2, hi: 0xb2}, | ||
3348 | {value: 0x0008, lo: 0xb3, hi: 0xb3}, | ||
3349 | {value: 0x0018, lo: 0xb4, hi: 0xb7}, | ||
3350 | {value: 0x0040, lo: 0xb8, hi: 0xbf}, | ||
3351 | // Block 0x6f, offset 0x381 | ||
3352 | {value: 0x0000, lo: 0x03}, | ||
3353 | {value: 0x1008, lo: 0x80, hi: 0x81}, | ||
3354 | {value: 0x0008, lo: 0x82, hi: 0xb3}, | ||
3355 | {value: 0x1008, lo: 0xb4, hi: 0xbf}, | ||
3356 | // Block 0x70, offset 0x385 | ||
3357 | {value: 0x0000, lo: 0x0e}, | ||
3358 | {value: 0x1008, lo: 0x80, hi: 0x83}, | ||
3359 | {value: 0x1b08, lo: 0x84, hi: 0x84}, | ||
3360 | {value: 0x1308, lo: 0x85, hi: 0x85}, | ||
3361 | {value: 0x0040, lo: 0x86, hi: 0x8d}, | ||
3362 | {value: 0x0018, lo: 0x8e, hi: 0x8f}, | ||
3363 | {value: 0x0008, lo: 0x90, hi: 0x99}, | ||
3364 | {value: 0x0040, lo: 0x9a, hi: 0x9f}, | ||
3365 | {value: 0x1308, lo: 0xa0, hi: 0xb1}, | ||
3366 | {value: 0x0008, lo: 0xb2, hi: 0xb7}, | ||
3367 | {value: 0x0018, lo: 0xb8, hi: 0xba}, | ||
3368 | {value: 0x0008, lo: 0xbb, hi: 0xbb}, | ||
3369 | {value: 0x0018, lo: 0xbc, hi: 0xbc}, | ||
3370 | {value: 0x0008, lo: 0xbd, hi: 0xbd}, | ||
3371 | {value: 0x0040, lo: 0xbe, hi: 0xbf}, | ||
3372 | // Block 0x71, offset 0x394 | ||
3373 | {value: 0x0000, lo: 0x04}, | ||
3374 | {value: 0x0008, lo: 0x80, hi: 0xa5}, | ||
3375 | {value: 0x1308, lo: 0xa6, hi: 0xad}, | ||
3376 | {value: 0x0018, lo: 0xae, hi: 0xaf}, | ||
3377 | {value: 0x0008, lo: 0xb0, hi: 0xbf}, | ||
3378 | // Block 0x72, offset 0x399 | ||
3379 | {value: 0x0000, lo: 0x07}, | ||
3380 | {value: 0x0008, lo: 0x80, hi: 0x86}, | ||
3381 | {value: 0x1308, lo: 0x87, hi: 0x91}, | ||
3382 | {value: 0x1008, lo: 0x92, hi: 0x92}, | ||
3383 | {value: 0x1808, lo: 0x93, hi: 0x93}, | ||
3384 | {value: 0x0040, lo: 0x94, hi: 0x9e}, | ||
3385 | {value: 0x0018, lo: 0x9f, hi: 0xbc}, | ||
3386 | {value: 0x0040, lo: 0xbd, hi: 0xbf}, | ||
3387 | // Block 0x73, offset 0x3a1 | ||
3388 | {value: 0x0000, lo: 0x09}, | ||
3389 | {value: 0x1308, lo: 0x80, hi: 0x82}, | ||
3390 | {value: 0x1008, lo: 0x83, hi: 0x83}, | ||
3391 | {value: 0x0008, lo: 0x84, hi: 0xb2}, | ||
3392 | {value: 0x1308, lo: 0xb3, hi: 0xb3}, | ||
3393 | {value: 0x1008, lo: 0xb4, hi: 0xb5}, | ||
3394 | {value: 0x1308, lo: 0xb6, hi: 0xb9}, | ||
3395 | {value: 0x1008, lo: 0xba, hi: 0xbb}, | ||
3396 | {value: 0x1308, lo: 0xbc, hi: 0xbc}, | ||
3397 | {value: 0x1008, lo: 0xbd, hi: 0xbf}, | ||
3398 | // Block 0x74, offset 0x3ab | ||
3399 | {value: 0x0000, lo: 0x0a}, | ||
3400 | {value: 0x1808, lo: 0x80, hi: 0x80}, | ||
3401 | {value: 0x0018, lo: 0x81, hi: 0x8d}, | ||
3402 | {value: 0x0040, lo: 0x8e, hi: 0x8e}, | ||
3403 | {value: 0x0008, lo: 0x8f, hi: 0x99}, | ||
3404 | {value: 0x0040, lo: 0x9a, hi: 0x9d}, | ||
3405 | {value: 0x0018, lo: 0x9e, hi: 0x9f}, | ||
3406 | {value: 0x0008, lo: 0xa0, hi: 0xa4}, | ||
3407 | {value: 0x1308, lo: 0xa5, hi: 0xa5}, | ||
3408 | {value: 0x0008, lo: 0xa6, hi: 0xbe}, | ||
3409 | {value: 0x0040, lo: 0xbf, hi: 0xbf}, | ||
3410 | // Block 0x75, offset 0x3b6 | ||
3411 | {value: 0x0000, lo: 0x07}, | ||
3412 | {value: 0x0008, lo: 0x80, hi: 0xa8}, | ||
3413 | {value: 0x1308, lo: 0xa9, hi: 0xae}, | ||
3414 | {value: 0x1008, lo: 0xaf, hi: 0xb0}, | ||
3415 | {value: 0x1308, lo: 0xb1, hi: 0xb2}, | ||
3416 | {value: 0x1008, lo: 0xb3, hi: 0xb4}, | ||
3417 | {value: 0x1308, lo: 0xb5, hi: 0xb6}, | ||
3418 | {value: 0x0040, lo: 0xb7, hi: 0xbf}, | ||
3419 | // Block 0x76, offset 0x3be | ||
3420 | {value: 0x0000, lo: 0x10}, | ||
3421 | {value: 0x0008, lo: 0x80, hi: 0x82}, | ||
3422 | {value: 0x1308, lo: 0x83, hi: 0x83}, | ||
3423 | {value: 0x0008, lo: 0x84, hi: 0x8b}, | ||
3424 | {value: 0x1308, lo: 0x8c, hi: 0x8c}, | ||
3425 | {value: 0x1008, lo: 0x8d, hi: 0x8d}, | ||
3426 | {value: 0x0040, lo: 0x8e, hi: 0x8f}, | ||
3427 | {value: 0x0008, lo: 0x90, hi: 0x99}, | ||
3428 | {value: 0x0040, lo: 0x9a, hi: 0x9b}, | ||
3429 | {value: 0x0018, lo: 0x9c, hi: 0x9f}, | ||
3430 | {value: 0x0008, lo: 0xa0, hi: 0xb6}, | ||
3431 | {value: 0x0018, lo: 0xb7, hi: 0xb9}, | ||
3432 | {value: 0x0008, lo: 0xba, hi: 0xba}, | ||
3433 | {value: 0x1008, lo: 0xbb, hi: 0xbb}, | ||
3434 | {value: 0x1308, lo: 0xbc, hi: 0xbc}, | ||
3435 | {value: 0x1008, lo: 0xbd, hi: 0xbd}, | ||
3436 | {value: 0x0008, lo: 0xbe, hi: 0xbf}, | ||
3437 | // Block 0x77, offset 0x3cf | ||
3438 | {value: 0x0000, lo: 0x08}, | ||
3439 | {value: 0x0008, lo: 0x80, hi: 0xaf}, | ||
3440 | {value: 0x1308, lo: 0xb0, hi: 0xb0}, | ||
3441 | {value: 0x0008, lo: 0xb1, hi: 0xb1}, | ||
3442 | {value: 0x1308, lo: 0xb2, hi: 0xb4}, | ||
3443 | {value: 0x0008, lo: 0xb5, hi: 0xb6}, | ||
3444 | {value: 0x1308, lo: 0xb7, hi: 0xb8}, | ||
3445 | {value: 0x0008, lo: 0xb9, hi: 0xbd}, | ||
3446 | {value: 0x1308, lo: 0xbe, hi: 0xbf}, | ||
3447 | // Block 0x78, offset 0x3d8 | ||
3448 | {value: 0x0000, lo: 0x0f}, | ||
3449 | {value: 0x0008, lo: 0x80, hi: 0x80}, | ||
3450 | {value: 0x1308, lo: 0x81, hi: 0x81}, | ||
3451 | {value: 0x0008, lo: 0x82, hi: 0x82}, | ||
3452 | {value: 0x0040, lo: 0x83, hi: 0x9a}, | ||
3453 | {value: 0x0008, lo: 0x9b, hi: 0x9d}, | ||
3454 | {value: 0x0018, lo: 0x9e, hi: 0x9f}, | ||
3455 | {value: 0x0008, lo: 0xa0, hi: 0xaa}, | ||
3456 | {value: 0x1008, lo: 0xab, hi: 0xab}, | ||
3457 | {value: 0x1308, lo: 0xac, hi: 0xad}, | ||
3458 | {value: 0x1008, lo: 0xae, hi: 0xaf}, | ||
3459 | {value: 0x0018, lo: 0xb0, hi: 0xb1}, | ||
3460 | {value: 0x0008, lo: 0xb2, hi: 0xb4}, | ||
3461 | {value: 0x1008, lo: 0xb5, hi: 0xb5}, | ||
3462 | {value: 0x1b08, lo: 0xb6, hi: 0xb6}, | ||
3463 | {value: 0x0040, lo: 0xb7, hi: 0xbf}, | ||
3464 | // Block 0x79, offset 0x3e8 | ||
3465 | {value: 0x0000, lo: 0x0c}, | ||
3466 | {value: 0x0040, lo: 0x80, hi: 0x80}, | ||
3467 | {value: 0x0008, lo: 0x81, hi: 0x86}, | ||
3468 | {value: 0x0040, lo: 0x87, hi: 0x88}, | ||
3469 | {value: 0x0008, lo: 0x89, hi: 0x8e}, | ||
3470 | {value: 0x0040, lo: 0x8f, hi: 0x90}, | ||
3471 | {value: 0x0008, lo: 0x91, hi: 0x96}, | ||
3472 | {value: 0x0040, lo: 0x97, hi: 0x9f}, | ||
3473 | {value: 0x0008, lo: 0xa0, hi: 0xa6}, | ||
3474 | {value: 0x0040, lo: 0xa7, hi: 0xa7}, | ||
3475 | {value: 0x0008, lo: 0xa8, hi: 0xae}, | ||
3476 | {value: 0x0040, lo: 0xaf, hi: 0xaf}, | ||
3477 | {value: 0x0008, lo: 0xb0, hi: 0xbf}, | ||
3478 | // Block 0x7a, offset 0x3f5 | ||
3479 | {value: 0x0000, lo: 0x09}, | ||
3480 | {value: 0x0008, lo: 0x80, hi: 0x9a}, | ||
3481 | {value: 0x0018, lo: 0x9b, hi: 0x9b}, | ||
3482 | {value: 0x4465, lo: 0x9c, hi: 0x9c}, | ||
3483 | {value: 0x447d, lo: 0x9d, hi: 0x9d}, | ||
3484 | {value: 0x2971, lo: 0x9e, hi: 0x9e}, | ||
3485 | {value: 0xe06d, lo: 0x9f, hi: 0x9f}, | ||
3486 | {value: 0x0008, lo: 0xa0, hi: 0xa5}, | ||
3487 | {value: 0x0040, lo: 0xa6, hi: 0xaf}, | ||
3488 | {value: 0x4495, lo: 0xb0, hi: 0xbf}, | ||
3489 | // Block 0x7b, offset 0x3ff | ||
3490 | {value: 0x0000, lo: 0x04}, | ||
3491 | {value: 0x44b5, lo: 0x80, hi: 0x8f}, | ||
3492 | {value: 0x44d5, lo: 0x90, hi: 0x9f}, | ||
3493 | {value: 0x44f5, lo: 0xa0, hi: 0xaf}, | ||
3494 | {value: 0x44d5, lo: 0xb0, hi: 0xbf}, | ||
3495 | // Block 0x7c, offset 0x404 | ||
3496 | {value: 0x0000, lo: 0x0c}, | ||
3497 | {value: 0x0008, lo: 0x80, hi: 0xa2}, | ||
3498 | {value: 0x1008, lo: 0xa3, hi: 0xa4}, | ||
3499 | {value: 0x1308, lo: 0xa5, hi: 0xa5}, | ||
3500 | {value: 0x1008, lo: 0xa6, hi: 0xa7}, | ||
3501 | {value: 0x1308, lo: 0xa8, hi: 0xa8}, | ||
3502 | {value: 0x1008, lo: 0xa9, hi: 0xaa}, | ||
3503 | {value: 0x0018, lo: 0xab, hi: 0xab}, | ||
3504 | {value: 0x1008, lo: 0xac, hi: 0xac}, | ||
3505 | {value: 0x1b08, lo: 0xad, hi: 0xad}, | ||
3506 | {value: 0x0040, lo: 0xae, hi: 0xaf}, | ||
3507 | {value: 0x0008, lo: 0xb0, hi: 0xb9}, | ||
3508 | {value: 0x0040, lo: 0xba, hi: 0xbf}, | ||
3509 | // Block 0x7d, offset 0x411 | ||
3510 | {value: 0x0000, lo: 0x03}, | ||
3511 | {value: 0x0008, lo: 0x80, hi: 0xa3}, | ||
3512 | {value: 0x0040, lo: 0xa4, hi: 0xaf}, | ||
3513 | {value: 0x0018, lo: 0xb0, hi: 0xbf}, | ||
3514 | // Block 0x7e, offset 0x415 | ||
3515 | {value: 0x0000, lo: 0x04}, | ||
3516 | {value: 0x0018, lo: 0x80, hi: 0x86}, | ||
3517 | {value: 0x0040, lo: 0x87, hi: 0x8a}, | ||
3518 | {value: 0x0018, lo: 0x8b, hi: 0xbb}, | ||
3519 | {value: 0x0040, lo: 0xbc, hi: 0xbf}, | ||
3520 | // Block 0x7f, offset 0x41a | ||
3521 | {value: 0x0020, lo: 0x01}, | ||
3522 | {value: 0x4515, lo: 0x80, hi: 0xbf}, | ||
3523 | // Block 0x80, offset 0x41c | ||
3524 | {value: 0x0020, lo: 0x03}, | ||
3525 | {value: 0x4d15, lo: 0x80, hi: 0x94}, | ||
3526 | {value: 0x4ad5, lo: 0x95, hi: 0x95}, | ||
3527 | {value: 0x4fb5, lo: 0x96, hi: 0xbf}, | ||
3528 | // Block 0x81, offset 0x420 | ||
3529 | {value: 0x0020, lo: 0x01}, | ||
3530 | {value: 0x54f5, lo: 0x80, hi: 0xbf}, | ||
3531 | // Block 0x82, offset 0x422 | ||
3532 | {value: 0x0020, lo: 0x03}, | ||
3533 | {value: 0x5cf5, lo: 0x80, hi: 0x84}, | ||
3534 | {value: 0x5655, lo: 0x85, hi: 0x85}, | ||
3535 | {value: 0x5d95, lo: 0x86, hi: 0xbf}, | ||
3536 | // Block 0x83, offset 0x426 | ||
3537 | {value: 0x0020, lo: 0x08}, | ||
3538 | {value: 0x6b55, lo: 0x80, hi: 0x8f}, | ||
3539 | {value: 0x6d15, lo: 0x90, hi: 0x90}, | ||
3540 | {value: 0x6d55, lo: 0x91, hi: 0xab}, | ||
3541 | {value: 0x6ea1, lo: 0xac, hi: 0xac}, | ||
3542 | {value: 0x70b5, lo: 0xad, hi: 0xad}, | ||
3543 | {value: 0x0040, lo: 0xae, hi: 0xae}, | ||
3544 | {value: 0x0040, lo: 0xaf, hi: 0xaf}, | ||
3545 | {value: 0x70d5, lo: 0xb0, hi: 0xbf}, | ||
3546 | // Block 0x84, offset 0x42f | ||
3547 | {value: 0x0020, lo: 0x05}, | ||
3548 | {value: 0x72d5, lo: 0x80, hi: 0xad}, | ||
3549 | {value: 0x6535, lo: 0xae, hi: 0xae}, | ||
3550 | {value: 0x7895, lo: 0xaf, hi: 0xb5}, | ||
3551 | {value: 0x6f55, lo: 0xb6, hi: 0xb6}, | ||
3552 | {value: 0x7975, lo: 0xb7, hi: 0xbf}, | ||
3553 | // Block 0x85, offset 0x435 | ||
3554 | {value: 0x0028, lo: 0x03}, | ||
3555 | {value: 0x7c21, lo: 0x80, hi: 0x82}, | ||
3556 | {value: 0x7be1, lo: 0x83, hi: 0x83}, | ||
3557 | {value: 0x7c99, lo: 0x84, hi: 0xbf}, | ||
3558 | // Block 0x86, offset 0x439 | ||
3559 | {value: 0x0038, lo: 0x0f}, | ||
3560 | {value: 0x9db1, lo: 0x80, hi: 0x83}, | ||
3561 | {value: 0x9e59, lo: 0x84, hi: 0x85}, | ||
3562 | {value: 0x9e91, lo: 0x86, hi: 0x87}, | ||
3563 | {value: 0x9ec9, lo: 0x88, hi: 0x8f}, | ||
3564 | {value: 0x0040, lo: 0x90, hi: 0x90}, | ||
3565 | {value: 0x0040, lo: 0x91, hi: 0x91}, | ||
3566 | {value: 0xa089, lo: 0x92, hi: 0x97}, | ||
3567 | {value: 0xa1a1, lo: 0x98, hi: 0x9c}, | ||
3568 | {value: 0xa281, lo: 0x9d, hi: 0xb3}, | ||
3569 | {value: 0x9d41, lo: 0xb4, hi: 0xb4}, | ||
3570 | {value: 0x9db1, lo: 0xb5, hi: 0xb5}, | ||
3571 | {value: 0xa789, lo: 0xb6, hi: 0xbb}, | ||
3572 | {value: 0xa869, lo: 0xbc, hi: 0xbc}, | ||
3573 | {value: 0xa7f9, lo: 0xbd, hi: 0xbd}, | ||
3574 | {value: 0xa8d9, lo: 0xbe, hi: 0xbf}, | ||
3575 | // Block 0x87, offset 0x449 | ||
3576 | {value: 0x0000, lo: 0x09}, | ||
3577 | {value: 0x0008, lo: 0x80, hi: 0x8b}, | ||
3578 | {value: 0x0040, lo: 0x8c, hi: 0x8c}, | ||
3579 | {value: 0x0008, lo: 0x8d, hi: 0xa6}, | ||
3580 | {value: 0x0040, lo: 0xa7, hi: 0xa7}, | ||
3581 | {value: 0x0008, lo: 0xa8, hi: 0xba}, | ||
3582 | {value: 0x0040, lo: 0xbb, hi: 0xbb}, | ||
3583 | {value: 0x0008, lo: 0xbc, hi: 0xbd}, | ||
3584 | {value: 0x0040, lo: 0xbe, hi: 0xbe}, | ||
3585 | {value: 0x0008, lo: 0xbf, hi: 0xbf}, | ||
3586 | // Block 0x88, offset 0x453 | ||
3587 | {value: 0x0000, lo: 0x04}, | ||
3588 | {value: 0x0008, lo: 0x80, hi: 0x8d}, | ||
3589 | {value: 0x0040, lo: 0x8e, hi: 0x8f}, | ||
3590 | {value: 0x0008, lo: 0x90, hi: 0x9d}, | ||
3591 | {value: 0x0040, lo: 0x9e, hi: 0xbf}, | ||
3592 | // Block 0x89, offset 0x458 | ||
3593 | {value: 0x0000, lo: 0x02}, | ||
3594 | {value: 0x0008, lo: 0x80, hi: 0xba}, | ||
3595 | {value: 0x0040, lo: 0xbb, hi: 0xbf}, | ||
3596 | // Block 0x8a, offset 0x45b | ||
3597 | {value: 0x0000, lo: 0x05}, | ||
3598 | {value: 0x0018, lo: 0x80, hi: 0x82}, | ||
3599 | {value: 0x0040, lo: 0x83, hi: 0x86}, | ||
3600 | {value: 0x0018, lo: 0x87, hi: 0xb3}, | ||
3601 | {value: 0x0040, lo: 0xb4, hi: 0xb6}, | ||
3602 | {value: 0x0018, lo: 0xb7, hi: 0xbf}, | ||
3603 | // Block 0x8b, offset 0x461 | ||
3604 | {value: 0x0000, lo: 0x06}, | ||
3605 | {value: 0x0018, lo: 0x80, hi: 0x8e}, | ||
3606 | {value: 0x0040, lo: 0x8f, hi: 0x8f}, | ||
3607 | {value: 0x0018, lo: 0x90, hi: 0x9b}, | ||
3608 | {value: 0x0040, lo: 0x9c, hi: 0x9f}, | ||
3609 | {value: 0x0018, lo: 0xa0, hi: 0xa0}, | ||
3610 | {value: 0x0040, lo: 0xa1, hi: 0xbf}, | ||
3611 | // Block 0x8c, offset 0x468 | ||
3612 | {value: 0x0000, lo: 0x04}, | ||
3613 | {value: 0x0040, lo: 0x80, hi: 0x8f}, | ||
3614 | {value: 0x0018, lo: 0x90, hi: 0xbc}, | ||
3615 | {value: 0x1308, lo: 0xbd, hi: 0xbd}, | ||
3616 | {value: 0x0040, lo: 0xbe, hi: 0xbf}, | ||
3617 | // Block 0x8d, offset 0x46d | ||
3618 | {value: 0x0000, lo: 0x03}, | ||
3619 | {value: 0x0008, lo: 0x80, hi: 0x9c}, | ||
3620 | {value: 0x0040, lo: 0x9d, hi: 0x9f}, | ||
3621 | {value: 0x0008, lo: 0xa0, hi: 0xbf}, | ||
3622 | // Block 0x8e, offset 0x471 | ||
3623 | {value: 0x0000, lo: 0x05}, | ||
3624 | {value: 0x0008, lo: 0x80, hi: 0x90}, | ||
3625 | {value: 0x0040, lo: 0x91, hi: 0x9f}, | ||
3626 | {value: 0x1308, lo: 0xa0, hi: 0xa0}, | ||
3627 | {value: 0x0018, lo: 0xa1, hi: 0xbb}, | ||
3628 | {value: 0x0040, lo: 0xbc, hi: 0xbf}, | ||
3629 | // Block 0x8f, offset 0x477 | ||
3630 | {value: 0x0000, lo: 0x04}, | ||
3631 | {value: 0x0008, lo: 0x80, hi: 0x9f}, | ||
3632 | {value: 0x0018, lo: 0xa0, hi: 0xa3}, | ||
3633 | {value: 0x0040, lo: 0xa4, hi: 0xaf}, | ||
3634 | {value: 0x0008, lo: 0xb0, hi: 0xbf}, | ||
3635 | // Block 0x90, offset 0x47c | ||
3636 | {value: 0x0000, lo: 0x08}, | ||
3637 | {value: 0x0008, lo: 0x80, hi: 0x80}, | ||
3638 | {value: 0x0018, lo: 0x81, hi: 0x81}, | ||
3639 | {value: 0x0008, lo: 0x82, hi: 0x89}, | ||
3640 | {value: 0x0018, lo: 0x8a, hi: 0x8a}, | ||
3641 | {value: 0x0040, lo: 0x8b, hi: 0x8f}, | ||
3642 | {value: 0x0008, lo: 0x90, hi: 0xb5}, | ||
3643 | {value: 0x1308, lo: 0xb6, hi: 0xba}, | ||
3644 | {value: 0x0040, lo: 0xbb, hi: 0xbf}, | ||
3645 | // Block 0x91, offset 0x485 | ||
3646 | {value: 0x0000, lo: 0x04}, | ||
3647 | {value: 0x0008, lo: 0x80, hi: 0x9d}, | ||
3648 | {value: 0x0040, lo: 0x9e, hi: 0x9e}, | ||
3649 | {value: 0x0018, lo: 0x9f, hi: 0x9f}, | ||
3650 | {value: 0x0008, lo: 0xa0, hi: 0xbf}, | ||
3651 | // Block 0x92, offset 0x48a | ||
3652 | {value: 0x0000, lo: 0x05}, | ||
3653 | {value: 0x0008, lo: 0x80, hi: 0x83}, | ||
3654 | {value: 0x0040, lo: 0x84, hi: 0x87}, | ||
3655 | {value: 0x0008, lo: 0x88, hi: 0x8f}, | ||
3656 | {value: 0x0018, lo: 0x90, hi: 0x95}, | ||
3657 | {value: 0x0040, lo: 0x96, hi: 0xbf}, | ||
3658 | // Block 0x93, offset 0x490 | ||
3659 | {value: 0x0000, lo: 0x06}, | ||
3660 | {value: 0xe145, lo: 0x80, hi: 0x87}, | ||
3661 | {value: 0xe1c5, lo: 0x88, hi: 0x8f}, | ||
3662 | {value: 0xe145, lo: 0x90, hi: 0x97}, | ||
3663 | {value: 0x8ad5, lo: 0x98, hi: 0x9f}, | ||
3664 | {value: 0x8aed, lo: 0xa0, hi: 0xa7}, | ||
3665 | {value: 0x0008, lo: 0xa8, hi: 0xbf}, | ||
3666 | // Block 0x94, offset 0x497 | ||
3667 | {value: 0x0000, lo: 0x06}, | ||
3668 | {value: 0x0008, lo: 0x80, hi: 0x9d}, | ||
3669 | {value: 0x0040, lo: 0x9e, hi: 0x9f}, | ||
3670 | {value: 0x0008, lo: 0xa0, hi: 0xa9}, | ||
3671 | {value: 0x0040, lo: 0xaa, hi: 0xaf}, | ||
3672 | {value: 0x8aed, lo: 0xb0, hi: 0xb7}, | ||
3673 | {value: 0x8ad5, lo: 0xb8, hi: 0xbf}, | ||
3674 | // Block 0x95, offset 0x49e | ||
3675 | {value: 0x0000, lo: 0x06}, | ||
3676 | {value: 0xe145, lo: 0x80, hi: 0x87}, | ||
3677 | {value: 0xe1c5, lo: 0x88, hi: 0x8f}, | ||
3678 | {value: 0xe145, lo: 0x90, hi: 0x93}, | ||
3679 | {value: 0x0040, lo: 0x94, hi: 0x97}, | ||
3680 | {value: 0x0008, lo: 0x98, hi: 0xbb}, | ||
3681 | {value: 0x0040, lo: 0xbc, hi: 0xbf}, | ||
3682 | // Block 0x96, offset 0x4a5 | ||
3683 | {value: 0x0000, lo: 0x03}, | ||
3684 | {value: 0x0008, lo: 0x80, hi: 0xa7}, | ||
3685 | {value: 0x0040, lo: 0xa8, hi: 0xaf}, | ||
3686 | {value: 0x0008, lo: 0xb0, hi: 0xbf}, | ||
3687 | // Block 0x97, offset 0x4a9 | ||
3688 | {value: 0x0000, lo: 0x04}, | ||
3689 | {value: 0x0008, lo: 0x80, hi: 0xa3}, | ||
3690 | {value: 0x0040, lo: 0xa4, hi: 0xae}, | ||
3691 | {value: 0x0018, lo: 0xaf, hi: 0xaf}, | ||
3692 | {value: 0x0040, lo: 0xb0, hi: 0xbf}, | ||
3693 | // Block 0x98, offset 0x4ae | ||
3694 | {value: 0x0000, lo: 0x02}, | ||
3695 | {value: 0x0008, lo: 0x80, hi: 0xb6}, | ||
3696 | {value: 0x0040, lo: 0xb7, hi: 0xbf}, | ||
3697 | // Block 0x99, offset 0x4b1 | ||
3698 | {value: 0x0000, lo: 0x04}, | ||
3699 | {value: 0x0008, lo: 0x80, hi: 0x95}, | ||
3700 | {value: 0x0040, lo: 0x96, hi: 0x9f}, | ||
3701 | {value: 0x0008, lo: 0xa0, hi: 0xa7}, | ||
3702 | {value: 0x0040, lo: 0xa8, hi: 0xbf}, | ||
3703 | // Block 0x9a, offset 0x4b6 | ||
3704 | {value: 0x0000, lo: 0x0b}, | ||
3705 | {value: 0x0008, lo: 0x80, hi: 0x85}, | ||
3706 | {value: 0x0040, lo: 0x86, hi: 0x87}, | ||
3707 | {value: 0x0008, lo: 0x88, hi: 0x88}, | ||
3708 | {value: 0x0040, lo: 0x89, hi: 0x89}, | ||
3709 | {value: 0x0008, lo: 0x8a, hi: 0xb5}, | ||
3710 | {value: 0x0040, lo: 0xb6, hi: 0xb6}, | ||
3711 | {value: 0x0008, lo: 0xb7, hi: 0xb8}, | ||
3712 | {value: 0x0040, lo: 0xb9, hi: 0xbb}, | ||
3713 | {value: 0x0008, lo: 0xbc, hi: 0xbc}, | ||
3714 | {value: 0x0040, lo: 0xbd, hi: 0xbe}, | ||
3715 | {value: 0x0008, lo: 0xbf, hi: 0xbf}, | ||
3716 | // Block 0x9b, offset 0x4c2 | ||
3717 | {value: 0x0000, lo: 0x05}, | ||
3718 | {value: 0x0008, lo: 0x80, hi: 0x95}, | ||
3719 | {value: 0x0040, lo: 0x96, hi: 0x96}, | ||
3720 | {value: 0x0018, lo: 0x97, hi: 0x9f}, | ||
3721 | {value: 0x0008, lo: 0xa0, hi: 0xb6}, | ||
3722 | {value: 0x0018, lo: 0xb7, hi: 0xbf}, | ||
3723 | // Block 0x9c, offset 0x4c8 | ||
3724 | {value: 0x0000, lo: 0x04}, | ||
3725 | {value: 0x0008, lo: 0x80, hi: 0x9e}, | ||
3726 | {value: 0x0040, lo: 0x9f, hi: 0xa6}, | ||
3727 | {value: 0x0018, lo: 0xa7, hi: 0xaf}, | ||
3728 | {value: 0x0040, lo: 0xb0, hi: 0xbf}, | ||
3729 | // Block 0x9d, offset 0x4cd | ||
3730 | {value: 0x0000, lo: 0x06}, | ||
3731 | {value: 0x0040, lo: 0x80, hi: 0x9f}, | ||
3732 | {value: 0x0008, lo: 0xa0, hi: 0xb2}, | ||
3733 | {value: 0x0040, lo: 0xb3, hi: 0xb3}, | ||
3734 | {value: 0x0008, lo: 0xb4, hi: 0xb5}, | ||
3735 | {value: 0x0040, lo: 0xb6, hi: 0xba}, | ||
3736 | {value: 0x0018, lo: 0xbb, hi: 0xbf}, | ||
3737 | // Block 0x9e, offset 0x4d4 | ||
3738 | {value: 0x0000, lo: 0x07}, | ||
3739 | {value: 0x0008, lo: 0x80, hi: 0x95}, | ||
3740 | {value: 0x0018, lo: 0x96, hi: 0x9b}, | ||
3741 | {value: 0x0040, lo: 0x9c, hi: 0x9e}, | ||
3742 | {value: 0x0018, lo: 0x9f, hi: 0x9f}, | ||
3743 | {value: 0x0008, lo: 0xa0, hi: 0xb9}, | ||
3744 | {value: 0x0040, lo: 0xba, hi: 0xbe}, | ||
3745 | {value: 0x0018, lo: 0xbf, hi: 0xbf}, | ||
3746 | // Block 0x9f, offset 0x4dc | ||
3747 | {value: 0x0000, lo: 0x04}, | ||
3748 | {value: 0x0008, lo: 0x80, hi: 0xb7}, | ||
3749 | {value: 0x0040, lo: 0xb8, hi: 0xbb}, | ||
3750 | {value: 0x0018, lo: 0xbc, hi: 0xbd}, | ||
3751 | {value: 0x0008, lo: 0xbe, hi: 0xbf}, | ||
3752 | // Block 0xa0, offset 0x4e1 | ||
3753 | {value: 0x0000, lo: 0x03}, | ||
3754 | {value: 0x0018, lo: 0x80, hi: 0x8f}, | ||
3755 | {value: 0x0040, lo: 0x90, hi: 0x91}, | ||
3756 | {value: 0x0018, lo: 0x92, hi: 0xbf}, | ||
3757 | // Block 0xa1, offset 0x4e5 | ||
3758 | {value: 0x0000, lo: 0x0f}, | ||
3759 | {value: 0x0008, lo: 0x80, hi: 0x80}, | ||
3760 | {value: 0x1308, lo: 0x81, hi: 0x83}, | ||
3761 | {value: 0x0040, lo: 0x84, hi: 0x84}, | ||
3762 | {value: 0x1308, lo: 0x85, hi: 0x86}, | ||
3763 | {value: 0x0040, lo: 0x87, hi: 0x8b}, | ||
3764 | {value: 0x1308, lo: 0x8c, hi: 0x8f}, | ||
3765 | {value: 0x0008, lo: 0x90, hi: 0x93}, | ||
3766 | {value: 0x0040, lo: 0x94, hi: 0x94}, | ||
3767 | {value: 0x0008, lo: 0x95, hi: 0x97}, | ||
3768 | {value: 0x0040, lo: 0x98, hi: 0x98}, | ||
3769 | {value: 0x0008, lo: 0x99, hi: 0xb3}, | ||
3770 | {value: 0x0040, lo: 0xb4, hi: 0xb7}, | ||
3771 | {value: 0x1308, lo: 0xb8, hi: 0xba}, | ||
3772 | {value: 0x0040, lo: 0xbb, hi: 0xbe}, | ||
3773 | {value: 0x1b08, lo: 0xbf, hi: 0xbf}, | ||
3774 | // Block 0xa2, offset 0x4f5 | ||
3775 | {value: 0x0000, lo: 0x06}, | ||
3776 | {value: 0x0018, lo: 0x80, hi: 0x87}, | ||
3777 | {value: 0x0040, lo: 0x88, hi: 0x8f}, | ||
3778 | {value: 0x0018, lo: 0x90, hi: 0x98}, | ||
3779 | {value: 0x0040, lo: 0x99, hi: 0x9f}, | ||
3780 | {value: 0x0008, lo: 0xa0, hi: 0xbc}, | ||
3781 | {value: 0x0018, lo: 0xbd, hi: 0xbf}, | ||
3782 | // Block 0xa3, offset 0x4fc | ||
3783 | {value: 0x0000, lo: 0x03}, | ||
3784 | {value: 0x0008, lo: 0x80, hi: 0x9c}, | ||
3785 | {value: 0x0018, lo: 0x9d, hi: 0x9f}, | ||
3786 | {value: 0x0040, lo: 0xa0, hi: 0xbf}, | ||
3787 | // Block 0xa4, offset 0x500 | ||
3788 | {value: 0x0000, lo: 0x03}, | ||
3789 | {value: 0x0008, lo: 0x80, hi: 0xb5}, | ||
3790 | {value: 0x0040, lo: 0xb6, hi: 0xb8}, | ||
3791 | {value: 0x0018, lo: 0xb9, hi: 0xbf}, | ||
3792 | // Block 0xa5, offset 0x504 | ||
3793 | {value: 0x0000, lo: 0x06}, | ||
3794 | {value: 0x0008, lo: 0x80, hi: 0x95}, | ||
3795 | {value: 0x0040, lo: 0x96, hi: 0x97}, | ||
3796 | {value: 0x0018, lo: 0x98, hi: 0x9f}, | ||
3797 | {value: 0x0008, lo: 0xa0, hi: 0xb2}, | ||
3798 | {value: 0x0040, lo: 0xb3, hi: 0xb7}, | ||
3799 | {value: 0x0018, lo: 0xb8, hi: 0xbf}, | ||
3800 | // Block 0xa6, offset 0x50b | ||
3801 | {value: 0x0000, lo: 0x02}, | ||
3802 | {value: 0x0008, lo: 0x80, hi: 0x88}, | ||
3803 | {value: 0x0040, lo: 0x89, hi: 0xbf}, | ||
3804 | // Block 0xa7, offset 0x50e | ||
3805 | {value: 0x0000, lo: 0x02}, | ||
3806 | {value: 0x03dd, lo: 0x80, hi: 0xb2}, | ||
3807 | {value: 0x0040, lo: 0xb3, hi: 0xbf}, | ||
3808 | // Block 0xa8, offset 0x511 | ||
3809 | {value: 0x0000, lo: 0x03}, | ||
3810 | {value: 0x0008, lo: 0x80, hi: 0xb2}, | ||
3811 | {value: 0x0040, lo: 0xb3, hi: 0xb9}, | ||
3812 | {value: 0x0018, lo: 0xba, hi: 0xbf}, | ||
3813 | // Block 0xa9, offset 0x515 | ||
3814 | {value: 0x0000, lo: 0x03}, | ||
3815 | {value: 0x0040, lo: 0x80, hi: 0x9f}, | ||
3816 | {value: 0x0018, lo: 0xa0, hi: 0xbe}, | ||
3817 | {value: 0x0040, lo: 0xbf, hi: 0xbf}, | ||
3818 | // Block 0xaa, offset 0x519 | ||
3819 | {value: 0x0000, lo: 0x05}, | ||
3820 | {value: 0x1008, lo: 0x80, hi: 0x80}, | ||
3821 | {value: 0x1308, lo: 0x81, hi: 0x81}, | ||
3822 | {value: 0x1008, lo: 0x82, hi: 0x82}, | ||
3823 | {value: 0x0008, lo: 0x83, hi: 0xb7}, | ||
3824 | {value: 0x1308, lo: 0xb8, hi: 0xbf}, | ||
3825 | // Block 0xab, offset 0x51f | ||
3826 | {value: 0x0000, lo: 0x08}, | ||
3827 | {value: 0x1308, lo: 0x80, hi: 0x85}, | ||
3828 | {value: 0x1b08, lo: 0x86, hi: 0x86}, | ||
3829 | {value: 0x0018, lo: 0x87, hi: 0x8d}, | ||
3830 | {value: 0x0040, lo: 0x8e, hi: 0x91}, | ||
3831 | {value: 0x0018, lo: 0x92, hi: 0xa5}, | ||
3832 | {value: 0x0008, lo: 0xa6, hi: 0xaf}, | ||
3833 | {value: 0x0040, lo: 0xb0, hi: 0xbe}, | ||
3834 | {value: 0x1b08, lo: 0xbf, hi: 0xbf}, | ||
3835 | // Block 0xac, offset 0x528 | ||
3836 | {value: 0x0000, lo: 0x0b}, | ||
3837 | {value: 0x1308, lo: 0x80, hi: 0x81}, | ||
3838 | {value: 0x1008, lo: 0x82, hi: 0x82}, | ||
3839 | {value: 0x0008, lo: 0x83, hi: 0xaf}, | ||
3840 | {value: 0x1008, lo: 0xb0, hi: 0xb2}, | ||
3841 | {value: 0x1308, lo: 0xb3, hi: 0xb6}, | ||
3842 | {value: 0x1008, lo: 0xb7, hi: 0xb8}, | ||
3843 | {value: 0x1b08, lo: 0xb9, hi: 0xb9}, | ||
3844 | {value: 0x1308, lo: 0xba, hi: 0xba}, | ||
3845 | {value: 0x0018, lo: 0xbb, hi: 0xbc}, | ||
3846 | {value: 0x0340, lo: 0xbd, hi: 0xbd}, | ||
3847 | {value: 0x0018, lo: 0xbe, hi: 0xbf}, | ||
3848 | // Block 0xad, offset 0x534 | ||
3849 | {value: 0x0000, lo: 0x06}, | ||
3850 | {value: 0x0018, lo: 0x80, hi: 0x81}, | ||
3851 | {value: 0x0040, lo: 0x82, hi: 0x8f}, | ||
3852 | {value: 0x0008, lo: 0x90, hi: 0xa8}, | ||
3853 | {value: 0x0040, lo: 0xa9, hi: 0xaf}, | ||
3854 | {value: 0x0008, lo: 0xb0, hi: 0xb9}, | ||
3855 | {value: 0x0040, lo: 0xba, hi: 0xbf}, | ||
3856 | // Block 0xae, offset 0x53b | ||
3857 | {value: 0x0000, lo: 0x08}, | ||
3858 | {value: 0x1308, lo: 0x80, hi: 0x82}, | ||
3859 | {value: 0x0008, lo: 0x83, hi: 0xa6}, | ||
3860 | {value: 0x1308, lo: 0xa7, hi: 0xab}, | ||
3861 | {value: 0x1008, lo: 0xac, hi: 0xac}, | ||
3862 | {value: 0x1308, lo: 0xad, hi: 0xb2}, | ||
3863 | {value: 0x1b08, lo: 0xb3, hi: 0xb4}, | ||
3864 | {value: 0x0040, lo: 0xb5, hi: 0xb5}, | ||
3865 | {value: 0x0008, lo: 0xb6, hi: 0xbf}, | ||
3866 | // Block 0xaf, offset 0x544 | ||
3867 | {value: 0x0000, lo: 0x07}, | ||
3868 | {value: 0x0018, lo: 0x80, hi: 0x83}, | ||
3869 | {value: 0x0040, lo: 0x84, hi: 0x8f}, | ||
3870 | {value: 0x0008, lo: 0x90, hi: 0xb2}, | ||
3871 | {value: 0x1308, lo: 0xb3, hi: 0xb3}, | ||
3872 | {value: 0x0018, lo: 0xb4, hi: 0xb5}, | ||
3873 | {value: 0x0008, lo: 0xb6, hi: 0xb6}, | ||
3874 | {value: 0x0040, lo: 0xb7, hi: 0xbf}, | ||
3875 | // Block 0xb0, offset 0x54c | ||
3876 | {value: 0x0000, lo: 0x06}, | ||
3877 | {value: 0x1308, lo: 0x80, hi: 0x81}, | ||
3878 | {value: 0x1008, lo: 0x82, hi: 0x82}, | ||
3879 | {value: 0x0008, lo: 0x83, hi: 0xb2}, | ||
3880 | {value: 0x1008, lo: 0xb3, hi: 0xb5}, | ||
3881 | {value: 0x1308, lo: 0xb6, hi: 0xbe}, | ||
3882 | {value: 0x1008, lo: 0xbf, hi: 0xbf}, | ||
3883 | // Block 0xb1, offset 0x553 | ||
3884 | {value: 0x0000, lo: 0x0d}, | ||
3885 | {value: 0x1808, lo: 0x80, hi: 0x80}, | ||
3886 | {value: 0x0008, lo: 0x81, hi: 0x84}, | ||
3887 | {value: 0x0018, lo: 0x85, hi: 0x89}, | ||
3888 | {value: 0x1308, lo: 0x8a, hi: 0x8c}, | ||
3889 | {value: 0x0018, lo: 0x8d, hi: 0x8d}, | ||
3890 | {value: 0x0040, lo: 0x8e, hi: 0x8f}, | ||
3891 | {value: 0x0008, lo: 0x90, hi: 0x9a}, | ||
3892 | {value: 0x0018, lo: 0x9b, hi: 0x9b}, | ||
3893 | {value: 0x0008, lo: 0x9c, hi: 0x9c}, | ||
3894 | {value: 0x0018, lo: 0x9d, hi: 0x9f}, | ||
3895 | {value: 0x0040, lo: 0xa0, hi: 0xa0}, | ||
3896 | {value: 0x0018, lo: 0xa1, hi: 0xb4}, | ||
3897 | {value: 0x0040, lo: 0xb5, hi: 0xbf}, | ||
3898 | // Block 0xb2, offset 0x561 | ||
3899 | {value: 0x0000, lo: 0x0c}, | ||
3900 | {value: 0x0008, lo: 0x80, hi: 0x91}, | ||
3901 | {value: 0x0040, lo: 0x92, hi: 0x92}, | ||
3902 | {value: 0x0008, lo: 0x93, hi: 0xab}, | ||
3903 | {value: 0x1008, lo: 0xac, hi: 0xae}, | ||
3904 | {value: 0x1308, lo: 0xaf, hi: 0xb1}, | ||
3905 | {value: 0x1008, lo: 0xb2, hi: 0xb3}, | ||
3906 | {value: 0x1308, lo: 0xb4, hi: 0xb4}, | ||
3907 | {value: 0x1808, lo: 0xb5, hi: 0xb5}, | ||
3908 | {value: 0x1308, lo: 0xb6, hi: 0xb7}, | ||
3909 | {value: 0x0018, lo: 0xb8, hi: 0xbd}, | ||
3910 | {value: 0x1308, lo: 0xbe, hi: 0xbe}, | ||
3911 | {value: 0x0040, lo: 0xbf, hi: 0xbf}, | ||
3912 | // Block 0xb3, offset 0x56e | ||
3913 | {value: 0x0000, lo: 0x0c}, | ||
3914 | {value: 0x0008, lo: 0x80, hi: 0x86}, | ||
3915 | {value: 0x0040, lo: 0x87, hi: 0x87}, | ||
3916 | {value: 0x0008, lo: 0x88, hi: 0x88}, | ||
3917 | {value: 0x0040, lo: 0x89, hi: 0x89}, | ||
3918 | {value: 0x0008, lo: 0x8a, hi: 0x8d}, | ||
3919 | {value: 0x0040, lo: 0x8e, hi: 0x8e}, | ||
3920 | {value: 0x0008, lo: 0x8f, hi: 0x9d}, | ||
3921 | {value: 0x0040, lo: 0x9e, hi: 0x9e}, | ||
3922 | {value: 0x0008, lo: 0x9f, hi: 0xa8}, | ||
3923 | {value: 0x0018, lo: 0xa9, hi: 0xa9}, | ||
3924 | {value: 0x0040, lo: 0xaa, hi: 0xaf}, | ||
3925 | {value: 0x0008, lo: 0xb0, hi: 0xbf}, | ||
3926 | // Block 0xb4, offset 0x57b | ||
3927 | {value: 0x0000, lo: 0x08}, | ||
3928 | {value: 0x0008, lo: 0x80, hi: 0x9e}, | ||
3929 | {value: 0x1308, lo: 0x9f, hi: 0x9f}, | ||
3930 | {value: 0x1008, lo: 0xa0, hi: 0xa2}, | ||
3931 | {value: 0x1308, lo: 0xa3, hi: 0xa9}, | ||
3932 | {value: 0x1b08, lo: 0xaa, hi: 0xaa}, | ||
3933 | {value: 0x0040, lo: 0xab, hi: 0xaf}, | ||
3934 | {value: 0x0008, lo: 0xb0, hi: 0xb9}, | ||
3935 | {value: 0x0040, lo: 0xba, hi: 0xbf}, | ||
3936 | // Block 0xb5, offset 0x584 | ||
3937 | {value: 0x0000, lo: 0x03}, | ||
3938 | {value: 0x0008, lo: 0x80, hi: 0xb4}, | ||
3939 | {value: 0x1008, lo: 0xb5, hi: 0xb7}, | ||
3940 | {value: 0x1308, lo: 0xb8, hi: 0xbf}, | ||
3941 | // Block 0xb6, offset 0x588 | ||
3942 | {value: 0x0000, lo: 0x0d}, | ||
3943 | {value: 0x1008, lo: 0x80, hi: 0x81}, | ||
3944 | {value: 0x1b08, lo: 0x82, hi: 0x82}, | ||
3945 | {value: 0x1308, lo: 0x83, hi: 0x84}, | ||
3946 | {value: 0x1008, lo: 0x85, hi: 0x85}, | ||
3947 | {value: 0x1308, lo: 0x86, hi: 0x86}, | ||
3948 | {value: 0x0008, lo: 0x87, hi: 0x8a}, | ||
3949 | {value: 0x0018, lo: 0x8b, hi: 0x8f}, | ||
3950 | {value: 0x0008, lo: 0x90, hi: 0x99}, | ||
3951 | {value: 0x0040, lo: 0x9a, hi: 0x9a}, | ||
3952 | {value: 0x0018, lo: 0x9b, hi: 0x9b}, | ||
3953 | {value: 0x0040, lo: 0x9c, hi: 0x9c}, | ||
3954 | {value: 0x0018, lo: 0x9d, hi: 0x9d}, | ||
3955 | {value: 0x0040, lo: 0x9e, hi: 0xbf}, | ||
3956 | // Block 0xb7, offset 0x596 | ||
3957 | {value: 0x0000, lo: 0x07}, | ||
3958 | {value: 0x0008, lo: 0x80, hi: 0xaf}, | ||
3959 | {value: 0x1008, lo: 0xb0, hi: 0xb2}, | ||
3960 | {value: 0x1308, lo: 0xb3, hi: 0xb8}, | ||
3961 | {value: 0x1008, lo: 0xb9, hi: 0xb9}, | ||
3962 | {value: 0x1308, lo: 0xba, hi: 0xba}, | ||
3963 | {value: 0x1008, lo: 0xbb, hi: 0xbe}, | ||
3964 | {value: 0x1308, lo: 0xbf, hi: 0xbf}, | ||
3965 | // Block 0xb8, offset 0x59e | ||
3966 | {value: 0x0000, lo: 0x0a}, | ||
3967 | {value: 0x1308, lo: 0x80, hi: 0x80}, | ||
3968 | {value: 0x1008, lo: 0x81, hi: 0x81}, | ||
3969 | {value: 0x1b08, lo: 0x82, hi: 0x82}, | ||
3970 | {value: 0x1308, lo: 0x83, hi: 0x83}, | ||
3971 | {value: 0x0008, lo: 0x84, hi: 0x85}, | ||
3972 | {value: 0x0018, lo: 0x86, hi: 0x86}, | ||
3973 | {value: 0x0008, lo: 0x87, hi: 0x87}, | ||
3974 | {value: 0x0040, lo: 0x88, hi: 0x8f}, | ||
3975 | {value: 0x0008, lo: 0x90, hi: 0x99}, | ||
3976 | {value: 0x0040, lo: 0x9a, hi: 0xbf}, | ||
3977 | // Block 0xb9, offset 0x5a9 | ||
3978 | {value: 0x0000, lo: 0x08}, | ||
3979 | {value: 0x0008, lo: 0x80, hi: 0xae}, | ||
3980 | {value: 0x1008, lo: 0xaf, hi: 0xb1}, | ||
3981 | {value: 0x1308, lo: 0xb2, hi: 0xb5}, | ||
3982 | {value: 0x0040, lo: 0xb6, hi: 0xb7}, | ||
3983 | {value: 0x1008, lo: 0xb8, hi: 0xbb}, | ||
3984 | {value: 0x1308, lo: 0xbc, hi: 0xbd}, | ||
3985 | {value: 0x1008, lo: 0xbe, hi: 0xbe}, | ||
3986 | {value: 0x1b08, lo: 0xbf, hi: 0xbf}, | ||
3987 | // Block 0xba, offset 0x5b2 | ||
3988 | {value: 0x0000, lo: 0x05}, | ||
3989 | {value: 0x1308, lo: 0x80, hi: 0x80}, | ||
3990 | {value: 0x0018, lo: 0x81, hi: 0x97}, | ||
3991 | {value: 0x0008, lo: 0x98, hi: 0x9b}, | ||
3992 | {value: 0x1308, lo: 0x9c, hi: 0x9d}, | ||
3993 | {value: 0x0040, lo: 0x9e, hi: 0xbf}, | ||
3994 | // Block 0xbb, offset 0x5b8 | ||
3995 | {value: 0x0000, lo: 0x07}, | ||
3996 | {value: 0x0008, lo: 0x80, hi: 0xaf}, | ||
3997 | {value: 0x1008, lo: 0xb0, hi: 0xb2}, | ||
3998 | {value: 0x1308, lo: 0xb3, hi: 0xba}, | ||
3999 | {value: 0x1008, lo: 0xbb, hi: 0xbc}, | ||
4000 | {value: 0x1308, lo: 0xbd, hi: 0xbd}, | ||
4001 | {value: 0x1008, lo: 0xbe, hi: 0xbe}, | ||
4002 | {value: 0x1b08, lo: 0xbf, hi: 0xbf}, | ||
4003 | // Block 0xbc, offset 0x5c0 | ||
4004 | {value: 0x0000, lo: 0x08}, | ||
4005 | {value: 0x1308, lo: 0x80, hi: 0x80}, | ||
4006 | {value: 0x0018, lo: 0x81, hi: 0x83}, | ||
4007 | {value: 0x0008, lo: 0x84, hi: 0x84}, | ||
4008 | {value: 0x0040, lo: 0x85, hi: 0x8f}, | ||
4009 | {value: 0x0008, lo: 0x90, hi: 0x99}, | ||
4010 | {value: 0x0040, lo: 0x9a, hi: 0x9f}, | ||
4011 | {value: 0x0018, lo: 0xa0, hi: 0xac}, | ||
4012 | {value: 0x0040, lo: 0xad, hi: 0xbf}, | ||
4013 | // Block 0xbd, offset 0x5c9 | ||
4014 | {value: 0x0000, lo: 0x09}, | ||
4015 | {value: 0x0008, lo: 0x80, hi: 0xaa}, | ||
4016 | {value: 0x1308, lo: 0xab, hi: 0xab}, | ||
4017 | {value: 0x1008, lo: 0xac, hi: 0xac}, | ||
4018 | {value: 0x1308, lo: 0xad, hi: 0xad}, | ||
4019 | {value: 0x1008, lo: 0xae, hi: 0xaf}, | ||
4020 | {value: 0x1308, lo: 0xb0, hi: 0xb5}, | ||
4021 | {value: 0x1808, lo: 0xb6, hi: 0xb6}, | ||
4022 | {value: 0x1308, lo: 0xb7, hi: 0xb7}, | ||
4023 | {value: 0x0040, lo: 0xb8, hi: 0xbf}, | ||
4024 | // Block 0xbe, offset 0x5d3 | ||
4025 | {value: 0x0000, lo: 0x02}, | ||
4026 | {value: 0x0008, lo: 0x80, hi: 0x89}, | ||
4027 | {value: 0x0040, lo: 0x8a, hi: 0xbf}, | ||
4028 | // Block 0xbf, offset 0x5d6 | ||
4029 | {value: 0x0000, lo: 0x0b}, | ||
4030 | {value: 0x0008, lo: 0x80, hi: 0x99}, | ||
4031 | {value: 0x0040, lo: 0x9a, hi: 0x9c}, | ||
4032 | {value: 0x1308, lo: 0x9d, hi: 0x9f}, | ||
4033 | {value: 0x1008, lo: 0xa0, hi: 0xa1}, | ||
4034 | {value: 0x1308, lo: 0xa2, hi: 0xa5}, | ||
4035 | {value: 0x1008, lo: 0xa6, hi: 0xa6}, | ||
4036 | {value: 0x1308, lo: 0xa7, hi: 0xaa}, | ||
4037 | {value: 0x1b08, lo: 0xab, hi: 0xab}, | ||
4038 | {value: 0x0040, lo: 0xac, hi: 0xaf}, | ||
4039 | {value: 0x0008, lo: 0xb0, hi: 0xb9}, | ||
4040 | {value: 0x0018, lo: 0xba, hi: 0xbf}, | ||
4041 | // Block 0xc0, offset 0x5e2 | ||
4042 | {value: 0x0000, lo: 0x02}, | ||
4043 | {value: 0x0040, lo: 0x80, hi: 0x9f}, | ||
4044 | {value: 0x049d, lo: 0xa0, hi: 0xbf}, | ||
4045 | // Block 0xc1, offset 0x5e5 | ||
4046 | {value: 0x0000, lo: 0x04}, | ||
4047 | {value: 0x0008, lo: 0x80, hi: 0xa9}, | ||
4048 | {value: 0x0018, lo: 0xaa, hi: 0xb2}, | ||
4049 | {value: 0x0040, lo: 0xb3, hi: 0xbe}, | ||
4050 | {value: 0x0008, lo: 0xbf, hi: 0xbf}, | ||
4051 | // Block 0xc2, offset 0x5ea | ||
4052 | {value: 0x0000, lo: 0x02}, | ||
4053 | {value: 0x0008, lo: 0x80, hi: 0xb8}, | ||
4054 | {value: 0x0040, lo: 0xb9, hi: 0xbf}, | ||
4055 | // Block 0xc3, offset 0x5ed | ||
4056 | {value: 0x0000, lo: 0x09}, | ||
4057 | {value: 0x0008, lo: 0x80, hi: 0x88}, | ||
4058 | {value: 0x0040, lo: 0x89, hi: 0x89}, | ||
4059 | {value: 0x0008, lo: 0x8a, hi: 0xae}, | ||
4060 | {value: 0x1008, lo: 0xaf, hi: 0xaf}, | ||
4061 | {value: 0x1308, lo: 0xb0, hi: 0xb6}, | ||
4062 | {value: 0x0040, lo: 0xb7, hi: 0xb7}, | ||
4063 | {value: 0x1308, lo: 0xb8, hi: 0xbd}, | ||
4064 | {value: 0x1008, lo: 0xbe, hi: 0xbe}, | ||
4065 | {value: 0x1b08, lo: 0xbf, hi: 0xbf}, | ||
4066 | // Block 0xc4, offset 0x5f7 | ||
4067 | {value: 0x0000, lo: 0x08}, | ||
4068 | {value: 0x0008, lo: 0x80, hi: 0x80}, | ||
4069 | {value: 0x0018, lo: 0x81, hi: 0x85}, | ||
4070 | {value: 0x0040, lo: 0x86, hi: 0x8f}, | ||
4071 | {value: 0x0008, lo: 0x90, hi: 0x99}, | ||
4072 | {value: 0x0018, lo: 0x9a, hi: 0xac}, | ||
4073 | {value: 0x0040, lo: 0xad, hi: 0xaf}, | ||
4074 | {value: 0x0018, lo: 0xb0, hi: 0xb1}, | ||
4075 | {value: 0x0008, lo: 0xb2, hi: 0xbf}, | ||
4076 | // Block 0xc5, offset 0x600 | ||
4077 | {value: 0x0000, lo: 0x0b}, | ||
4078 | {value: 0x0008, lo: 0x80, hi: 0x8f}, | ||
4079 | {value: 0x0040, lo: 0x90, hi: 0x91}, | ||
4080 | {value: 0x1308, lo: 0x92, hi: 0xa7}, | ||
4081 | {value: 0x0040, lo: 0xa8, hi: 0xa8}, | ||
4082 | {value: 0x1008, lo: 0xa9, hi: 0xa9}, | ||
4083 | {value: 0x1308, lo: 0xaa, hi: 0xb0}, | ||
4084 | {value: 0x1008, lo: 0xb1, hi: 0xb1}, | ||
4085 | {value: 0x1308, lo: 0xb2, hi: 0xb3}, | ||
4086 | {value: 0x1008, lo: 0xb4, hi: 0xb4}, | ||
4087 | {value: 0x1308, lo: 0xb5, hi: 0xb6}, | ||
4088 | {value: 0x0040, lo: 0xb7, hi: 0xbf}, | ||
4089 | // Block 0xc6, offset 0x60c | ||
4090 | {value: 0x0000, lo: 0x02}, | ||
4091 | {value: 0x0008, lo: 0x80, hi: 0x99}, | ||
4092 | {value: 0x0040, lo: 0x9a, hi: 0xbf}, | ||
4093 | // Block 0xc7, offset 0x60f | ||
4094 | {value: 0x0000, lo: 0x04}, | ||
4095 | {value: 0x0018, lo: 0x80, hi: 0xae}, | ||
4096 | {value: 0x0040, lo: 0xaf, hi: 0xaf}, | ||
4097 | {value: 0x0018, lo: 0xb0, hi: 0xb4}, | ||
4098 | {value: 0x0040, lo: 0xb5, hi: 0xbf}, | ||
4099 | // Block 0xc8, offset 0x614 | ||
4100 | {value: 0x0000, lo: 0x02}, | ||
4101 | {value: 0x0008, lo: 0x80, hi: 0x83}, | ||
4102 | {value: 0x0040, lo: 0x84, hi: 0xbf}, | ||
4103 | // Block 0xc9, offset 0x617 | ||
4104 | {value: 0x0000, lo: 0x02}, | ||
4105 | {value: 0x0008, lo: 0x80, hi: 0xae}, | ||
4106 | {value: 0x0040, lo: 0xaf, hi: 0xbf}, | ||
4107 | // Block 0xca, offset 0x61a | ||
4108 | {value: 0x0000, lo: 0x02}, | ||
4109 | {value: 0x0008, lo: 0x80, hi: 0x86}, | ||
4110 | {value: 0x0040, lo: 0x87, hi: 0xbf}, | ||
4111 | // Block 0xcb, offset 0x61d | ||
4112 | {value: 0x0000, lo: 0x06}, | ||
4113 | {value: 0x0008, lo: 0x80, hi: 0x9e}, | ||
4114 | {value: 0x0040, lo: 0x9f, hi: 0x9f}, | ||
4115 | {value: 0x0008, lo: 0xa0, hi: 0xa9}, | ||
4116 | {value: 0x0040, lo: 0xaa, hi: 0xad}, | ||
4117 | {value: 0x0018, lo: 0xae, hi: 0xaf}, | ||
4118 | {value: 0x0040, lo: 0xb0, hi: 0xbf}, | ||
4119 | // Block 0xcc, offset 0x624 | ||
4120 | {value: 0x0000, lo: 0x06}, | ||
4121 | {value: 0x0040, lo: 0x80, hi: 0x8f}, | ||
4122 | {value: 0x0008, lo: 0x90, hi: 0xad}, | ||
4123 | {value: 0x0040, lo: 0xae, hi: 0xaf}, | ||
4124 | {value: 0x1308, lo: 0xb0, hi: 0xb4}, | ||
4125 | {value: 0x0018, lo: 0xb5, hi: 0xb5}, | ||
4126 | {value: 0x0040, lo: 0xb6, hi: 0xbf}, | ||
4127 | // Block 0xcd, offset 0x62b | ||
4128 | {value: 0x0000, lo: 0x03}, | ||
4129 | {value: 0x0008, lo: 0x80, hi: 0xaf}, | ||
4130 | {value: 0x1308, lo: 0xb0, hi: 0xb6}, | ||
4131 | {value: 0x0018, lo: 0xb7, hi: 0xbf}, | ||
4132 | // Block 0xce, offset 0x62f | ||
4133 | {value: 0x0000, lo: 0x0a}, | ||
4134 | {value: 0x0008, lo: 0x80, hi: 0x83}, | ||
4135 | {value: 0x0018, lo: 0x84, hi: 0x85}, | ||
4136 | {value: 0x0040, lo: 0x86, hi: 0x8f}, | ||
4137 | {value: 0x0008, lo: 0x90, hi: 0x99}, | ||
4138 | {value: 0x0040, lo: 0x9a, hi: 0x9a}, | ||
4139 | {value: 0x0018, lo: 0x9b, hi: 0xa1}, | ||
4140 | {value: 0x0040, lo: 0xa2, hi: 0xa2}, | ||
4141 | {value: 0x0008, lo: 0xa3, hi: 0xb7}, | ||
4142 | {value: 0x0040, lo: 0xb8, hi: 0xbc}, | ||
4143 | {value: 0x0008, lo: 0xbd, hi: 0xbf}, | ||
4144 | // Block 0xcf, offset 0x63a | ||
4145 | {value: 0x0000, lo: 0x02}, | ||
4146 | {value: 0x0008, lo: 0x80, hi: 0x8f}, | ||
4147 | {value: 0x0040, lo: 0x90, hi: 0xbf}, | ||
4148 | // Block 0xd0, offset 0x63d | ||
4149 | {value: 0x0000, lo: 0x05}, | ||
4150 | {value: 0x0008, lo: 0x80, hi: 0x84}, | ||
4151 | {value: 0x0040, lo: 0x85, hi: 0x8f}, | ||
4152 | {value: 0x0008, lo: 0x90, hi: 0x90}, | ||
4153 | {value: 0x1008, lo: 0x91, hi: 0xbe}, | ||
4154 | {value: 0x0040, lo: 0xbf, hi: 0xbf}, | ||
4155 | // Block 0xd1, offset 0x643 | ||
4156 | {value: 0x0000, lo: 0x04}, | ||
4157 | {value: 0x0040, lo: 0x80, hi: 0x8e}, | ||
4158 | {value: 0x1308, lo: 0x8f, hi: 0x92}, | ||
4159 | {value: 0x0008, lo: 0x93, hi: 0x9f}, | ||
4160 | {value: 0x0040, lo: 0xa0, hi: 0xbf}, | ||
4161 | // Block 0xd2, offset 0x648 | ||
4162 | {value: 0x0000, lo: 0x03}, | ||
4163 | {value: 0x0040, lo: 0x80, hi: 0x9f}, | ||
4164 | {value: 0x0008, lo: 0xa0, hi: 0xa0}, | ||
4165 | {value: 0x0040, lo: 0xa1, hi: 0xbf}, | ||
4166 | // Block 0xd3, offset 0x64c | ||
4167 | {value: 0x0000, lo: 0x02}, | ||
4168 | {value: 0x0008, lo: 0x80, hi: 0xac}, | ||
4169 | {value: 0x0040, lo: 0xad, hi: 0xbf}, | ||
4170 | // Block 0xd4, offset 0x64f | ||
4171 | {value: 0x0000, lo: 0x02}, | ||
4172 | {value: 0x0008, lo: 0x80, hi: 0xb2}, | ||
4173 | {value: 0x0040, lo: 0xb3, hi: 0xbf}, | ||
4174 | // Block 0xd5, offset 0x652 | ||
4175 | {value: 0x0000, lo: 0x02}, | ||
4176 | {value: 0x0008, lo: 0x80, hi: 0x81}, | ||
4177 | {value: 0x0040, lo: 0x82, hi: 0xbf}, | ||
4178 | // Block 0xd6, offset 0x655 | ||
4179 | {value: 0x0000, lo: 0x04}, | ||
4180 | {value: 0x0008, lo: 0x80, hi: 0xaa}, | ||
4181 | {value: 0x0040, lo: 0xab, hi: 0xaf}, | ||
4182 | {value: 0x0008, lo: 0xb0, hi: 0xbc}, | ||
4183 | {value: 0x0040, lo: 0xbd, hi: 0xbf}, | ||
4184 | // Block 0xd7, offset 0x65a | ||
4185 | {value: 0x0000, lo: 0x09}, | ||
4186 | {value: 0x0008, lo: 0x80, hi: 0x88}, | ||
4187 | {value: 0x0040, lo: 0x89, hi: 0x8f}, | ||
4188 | {value: 0x0008, lo: 0x90, hi: 0x99}, | ||
4189 | {value: 0x0040, lo: 0x9a, hi: 0x9b}, | ||
4190 | {value: 0x0018, lo: 0x9c, hi: 0x9c}, | ||
4191 | {value: 0x1308, lo: 0x9d, hi: 0x9e}, | ||
4192 | {value: 0x0018, lo: 0x9f, hi: 0x9f}, | ||
4193 | {value: 0x03c0, lo: 0xa0, hi: 0xa3}, | ||
4194 | {value: 0x0040, lo: 0xa4, hi: 0xbf}, | ||
4195 | // Block 0xd8, offset 0x664 | ||
4196 | {value: 0x0000, lo: 0x02}, | ||
4197 | {value: 0x0018, lo: 0x80, hi: 0xb5}, | ||
4198 | {value: 0x0040, lo: 0xb6, hi: 0xbf}, | ||
4199 | // Block 0xd9, offset 0x667 | ||
4200 | {value: 0x0000, lo: 0x03}, | ||
4201 | {value: 0x0018, lo: 0x80, hi: 0xa6}, | ||
4202 | {value: 0x0040, lo: 0xa7, hi: 0xa8}, | ||
4203 | {value: 0x0018, lo: 0xa9, hi: 0xbf}, | ||
4204 | // Block 0xda, offset 0x66b | ||
4205 | {value: 0x0000, lo: 0x0e}, | ||
4206 | {value: 0x0018, lo: 0x80, hi: 0x9d}, | ||
4207 | {value: 0xb5b9, lo: 0x9e, hi: 0x9e}, | ||
4208 | {value: 0xb601, lo: 0x9f, hi: 0x9f}, | ||
4209 | {value: 0xb649, lo: 0xa0, hi: 0xa0}, | ||
4210 | {value: 0xb6b1, lo: 0xa1, hi: 0xa1}, | ||
4211 | {value: 0xb719, lo: 0xa2, hi: 0xa2}, | ||
4212 | {value: 0xb781, lo: 0xa3, hi: 0xa3}, | ||
4213 | {value: 0xb7e9, lo: 0xa4, hi: 0xa4}, | ||
4214 | {value: 0x1018, lo: 0xa5, hi: 0xa6}, | ||
4215 | {value: 0x1318, lo: 0xa7, hi: 0xa9}, | ||
4216 | {value: 0x0018, lo: 0xaa, hi: 0xac}, | ||
4217 | {value: 0x1018, lo: 0xad, hi: 0xb2}, | ||
4218 | {value: 0x0340, lo: 0xb3, hi: 0xba}, | ||
4219 | {value: 0x1318, lo: 0xbb, hi: 0xbf}, | ||
4220 | // Block 0xdb, offset 0x67a | ||
4221 | {value: 0x0000, lo: 0x0b}, | ||
4222 | {value: 0x1318, lo: 0x80, hi: 0x82}, | ||
4223 | {value: 0x0018, lo: 0x83, hi: 0x84}, | ||
4224 | {value: 0x1318, lo: 0x85, hi: 0x8b}, | ||
4225 | {value: 0x0018, lo: 0x8c, hi: 0xa9}, | ||
4226 | {value: 0x1318, lo: 0xaa, hi: 0xad}, | ||
4227 | {value: 0x0018, lo: 0xae, hi: 0xba}, | ||
4228 | {value: 0xb851, lo: 0xbb, hi: 0xbb}, | ||
4229 | {value: 0xb899, lo: 0xbc, hi: 0xbc}, | ||
4230 | {value: 0xb8e1, lo: 0xbd, hi: 0xbd}, | ||
4231 | {value: 0xb949, lo: 0xbe, hi: 0xbe}, | ||
4232 | {value: 0xb9b1, lo: 0xbf, hi: 0xbf}, | ||
4233 | // Block 0xdc, offset 0x686 | ||
4234 | {value: 0x0000, lo: 0x03}, | ||
4235 | {value: 0xba19, lo: 0x80, hi: 0x80}, | ||
4236 | {value: 0x0018, lo: 0x81, hi: 0xa8}, | ||
4237 | {value: 0x0040, lo: 0xa9, hi: 0xbf}, | ||
4238 | // Block 0xdd, offset 0x68a | ||
4239 | {value: 0x0000, lo: 0x04}, | ||
4240 | {value: 0x0018, lo: 0x80, hi: 0x81}, | ||
4241 | {value: 0x1318, lo: 0x82, hi: 0x84}, | ||
4242 | {value: 0x0018, lo: 0x85, hi: 0x85}, | ||
4243 | {value: 0x0040, lo: 0x86, hi: 0xbf}, | ||
4244 | // Block 0xde, offset 0x68f | ||
4245 | {value: 0x0000, lo: 0x04}, | ||
4246 | {value: 0x0018, lo: 0x80, hi: 0x96}, | ||
4247 | {value: 0x0040, lo: 0x97, hi: 0x9f}, | ||
4248 | {value: 0x0018, lo: 0xa0, hi: 0xb1}, | ||
4249 | {value: 0x0040, lo: 0xb2, hi: 0xbf}, | ||
4250 | // Block 0xdf, offset 0x694 | ||
4251 | {value: 0x0000, lo: 0x03}, | ||
4252 | {value: 0x1308, lo: 0x80, hi: 0xb6}, | ||
4253 | {value: 0x0018, lo: 0xb7, hi: 0xba}, | ||
4254 | {value: 0x1308, lo: 0xbb, hi: 0xbf}, | ||
4255 | // Block 0xe0, offset 0x698 | ||
4256 | {value: 0x0000, lo: 0x04}, | ||
4257 | {value: 0x1308, lo: 0x80, hi: 0xac}, | ||
4258 | {value: 0x0018, lo: 0xad, hi: 0xb4}, | ||
4259 | {value: 0x1308, lo: 0xb5, hi: 0xb5}, | ||
4260 | {value: 0x0018, lo: 0xb6, hi: 0xbf}, | ||
4261 | // Block 0xe1, offset 0x69d | ||
4262 | {value: 0x0000, lo: 0x08}, | ||
4263 | {value: 0x0018, lo: 0x80, hi: 0x83}, | ||
4264 | {value: 0x1308, lo: 0x84, hi: 0x84}, | ||
4265 | {value: 0x0018, lo: 0x85, hi: 0x8b}, | ||
4266 | {value: 0x0040, lo: 0x8c, hi: 0x9a}, | ||
4267 | {value: 0x1308, lo: 0x9b, hi: 0x9f}, | ||
4268 | {value: 0x0040, lo: 0xa0, hi: 0xa0}, | ||
4269 | {value: 0x1308, lo: 0xa1, hi: 0xaf}, | ||
4270 | {value: 0x0040, lo: 0xb0, hi: 0xbf}, | ||
4271 | // Block 0xe2, offset 0x6a6 | ||
4272 | {value: 0x0000, lo: 0x0a}, | ||
4273 | {value: 0x1308, lo: 0x80, hi: 0x86}, | ||
4274 | {value: 0x0040, lo: 0x87, hi: 0x87}, | ||
4275 | {value: 0x1308, lo: 0x88, hi: 0x98}, | ||
4276 | {value: 0x0040, lo: 0x99, hi: 0x9a}, | ||
4277 | {value: 0x1308, lo: 0x9b, hi: 0xa1}, | ||
4278 | {value: 0x0040, lo: 0xa2, hi: 0xa2}, | ||
4279 | {value: 0x1308, lo: 0xa3, hi: 0xa4}, | ||
4280 | {value: 0x0040, lo: 0xa5, hi: 0xa5}, | ||
4281 | {value: 0x1308, lo: 0xa6, hi: 0xaa}, | ||
4282 | {value: 0x0040, lo: 0xab, hi: 0xbf}, | ||
4283 | // Block 0xe3, offset 0x6b1 | ||
4284 | {value: 0x0000, lo: 0x05}, | ||
4285 | {value: 0x0008, lo: 0x80, hi: 0x84}, | ||
4286 | {value: 0x0040, lo: 0x85, hi: 0x86}, | ||
4287 | {value: 0x0018, lo: 0x87, hi: 0x8f}, | ||
4288 | {value: 0x1308, lo: 0x90, hi: 0x96}, | ||
4289 | {value: 0x0040, lo: 0x97, hi: 0xbf}, | ||
4290 | // Block 0xe4, offset 0x6b7 | ||
4291 | {value: 0x0000, lo: 0x07}, | ||
4292 | {value: 0x0208, lo: 0x80, hi: 0x83}, | ||
4293 | {value: 0x1308, lo: 0x84, hi: 0x8a}, | ||
4294 | {value: 0x0040, lo: 0x8b, hi: 0x8f}, | ||
4295 | {value: 0x0008, lo: 0x90, hi: 0x99}, | ||
4296 | {value: 0x0040, lo: 0x9a, hi: 0x9d}, | ||
4297 | {value: 0x0018, lo: 0x9e, hi: 0x9f}, | ||
4298 | {value: 0x0040, lo: 0xa0, hi: 0xbf}, | ||
4299 | // Block 0xe5, offset 0x6bf | ||
4300 | {value: 0x0000, lo: 0x03}, | ||
4301 | {value: 0x0040, lo: 0x80, hi: 0xaf}, | ||
4302 | {value: 0x0018, lo: 0xb0, hi: 0xb1}, | ||
4303 | {value: 0x0040, lo: 0xb2, hi: 0xbf}, | ||
4304 | // Block 0xe6, offset 0x6c3 | ||
4305 | {value: 0x0000, lo: 0x03}, | ||
4306 | {value: 0x0018, lo: 0x80, hi: 0xab}, | ||
4307 | {value: 0x0040, lo: 0xac, hi: 0xaf}, | ||
4308 | {value: 0x0018, lo: 0xb0, hi: 0xbf}, | ||
4309 | // Block 0xe7, offset 0x6c7 | ||
4310 | {value: 0x0000, lo: 0x05}, | ||
4311 | {value: 0x0018, lo: 0x80, hi: 0x93}, | ||
4312 | {value: 0x0040, lo: 0x94, hi: 0x9f}, | ||
4313 | {value: 0x0018, lo: 0xa0, hi: 0xae}, | ||
4314 | {value: 0x0040, lo: 0xaf, hi: 0xb0}, | ||
4315 | {value: 0x0018, lo: 0xb1, hi: 0xbf}, | ||
4316 | // Block 0xe8, offset 0x6cd | ||
4317 | {value: 0x0000, lo: 0x05}, | ||
4318 | {value: 0x0040, lo: 0x80, hi: 0x80}, | ||
4319 | {value: 0x0018, lo: 0x81, hi: 0x8f}, | ||
4320 | {value: 0x0040, lo: 0x90, hi: 0x90}, | ||
4321 | {value: 0x0018, lo: 0x91, hi: 0xb5}, | ||
4322 | {value: 0x0040, lo: 0xb6, hi: 0xbf}, | ||
4323 | // Block 0xe9, offset 0x6d3 | ||
4324 | {value: 0x0000, lo: 0x04}, | ||
4325 | {value: 0x0018, lo: 0x80, hi: 0x8f}, | ||
4326 | {value: 0xc1c1, lo: 0x90, hi: 0x90}, | ||
4327 | {value: 0x0018, lo: 0x91, hi: 0xac}, | ||
4328 | {value: 0x0040, lo: 0xad, hi: 0xbf}, | ||
4329 | // Block 0xea, offset 0x6d8 | ||
4330 | {value: 0x0000, lo: 0x02}, | ||
4331 | {value: 0x0040, lo: 0x80, hi: 0xa5}, | ||
4332 | {value: 0x0018, lo: 0xa6, hi: 0xbf}, | ||
4333 | // Block 0xeb, offset 0x6db | ||
4334 | {value: 0x0000, lo: 0x0d}, | ||
4335 | {value: 0xc7e9, lo: 0x80, hi: 0x80}, | ||
4336 | {value: 0xc839, lo: 0x81, hi: 0x81}, | ||
4337 | {value: 0xc889, lo: 0x82, hi: 0x82}, | ||
4338 | {value: 0xc8d9, lo: 0x83, hi: 0x83}, | ||
4339 | {value: 0xc929, lo: 0x84, hi: 0x84}, | ||
4340 | {value: 0xc979, lo: 0x85, hi: 0x85}, | ||
4341 | {value: 0xc9c9, lo: 0x86, hi: 0x86}, | ||
4342 | {value: 0xca19, lo: 0x87, hi: 0x87}, | ||
4343 | {value: 0xca69, lo: 0x88, hi: 0x88}, | ||
4344 | {value: 0x0040, lo: 0x89, hi: 0x8f}, | ||
4345 | {value: 0xcab9, lo: 0x90, hi: 0x90}, | ||
4346 | {value: 0xcad9, lo: 0x91, hi: 0x91}, | ||
4347 | {value: 0x0040, lo: 0x92, hi: 0xbf}, | ||
4348 | // Block 0xec, offset 0x6e9 | ||
4349 | {value: 0x0000, lo: 0x06}, | ||
4350 | {value: 0x0018, lo: 0x80, hi: 0x92}, | ||
4351 | {value: 0x0040, lo: 0x93, hi: 0x9f}, | ||
4352 | {value: 0x0018, lo: 0xa0, hi: 0xac}, | ||
4353 | {value: 0x0040, lo: 0xad, hi: 0xaf}, | ||
4354 | {value: 0x0018, lo: 0xb0, hi: 0xb6}, | ||
4355 | {value: 0x0040, lo: 0xb7, hi: 0xbf}, | ||
4356 | // Block 0xed, offset 0x6f0 | ||
4357 | {value: 0x0000, lo: 0x02}, | ||
4358 | {value: 0x0018, lo: 0x80, hi: 0xb3}, | ||
4359 | {value: 0x0040, lo: 0xb4, hi: 0xbf}, | ||
4360 | // Block 0xee, offset 0x6f3 | ||
4361 | {value: 0x0000, lo: 0x02}, | ||
4362 | {value: 0x0018, lo: 0x80, hi: 0x94}, | ||
4363 | {value: 0x0040, lo: 0x95, hi: 0xbf}, | ||
4364 | // Block 0xef, offset 0x6f6 | ||
4365 | {value: 0x0000, lo: 0x03}, | ||
4366 | {value: 0x0018, lo: 0x80, hi: 0x8b}, | ||
4367 | {value: 0x0040, lo: 0x8c, hi: 0x8f}, | ||
4368 | {value: 0x0018, lo: 0x90, hi: 0xbf}, | ||
4369 | // Block 0xf0, offset 0x6fa | ||
4370 | {value: 0x0000, lo: 0x05}, | ||
4371 | {value: 0x0018, lo: 0x80, hi: 0x87}, | ||
4372 | {value: 0x0040, lo: 0x88, hi: 0x8f}, | ||
4373 | {value: 0x0018, lo: 0x90, hi: 0x99}, | ||
4374 | {value: 0x0040, lo: 0x9a, hi: 0x9f}, | ||
4375 | {value: 0x0018, lo: 0xa0, hi: 0xbf}, | ||
4376 | // Block 0xf1, offset 0x700 | ||
4377 | {value: 0x0000, lo: 0x04}, | ||
4378 | {value: 0x0018, lo: 0x80, hi: 0x87}, | ||
4379 | {value: 0x0040, lo: 0x88, hi: 0x8f}, | ||
4380 | {value: 0x0018, lo: 0x90, hi: 0xad}, | ||
4381 | {value: 0x0040, lo: 0xae, hi: 0xbf}, | ||
4382 | // Block 0xf2, offset 0x705 | ||
4383 | {value: 0x0000, lo: 0x09}, | ||
4384 | {value: 0x0040, lo: 0x80, hi: 0x8f}, | ||
4385 | {value: 0x0018, lo: 0x90, hi: 0x9e}, | ||
4386 | {value: 0x0040, lo: 0x9f, hi: 0x9f}, | ||
4387 | {value: 0x0018, lo: 0xa0, hi: 0xa7}, | ||
4388 | {value: 0x0040, lo: 0xa8, hi: 0xaf}, | ||
4389 | {value: 0x0018, lo: 0xb0, hi: 0xb0}, | ||
4390 | {value: 0x0040, lo: 0xb1, hi: 0xb2}, | ||
4391 | {value: 0x0018, lo: 0xb3, hi: 0xbe}, | ||
4392 | {value: 0x0040, lo: 0xbf, hi: 0xbf}, | ||
4393 | // Block 0xf3, offset 0x70f | ||
4394 | {value: 0x0000, lo: 0x04}, | ||
4395 | {value: 0x0018, lo: 0x80, hi: 0x8b}, | ||
4396 | {value: 0x0040, lo: 0x8c, hi: 0x8f}, | ||
4397 | {value: 0x0018, lo: 0x90, hi: 0x9e}, | ||
4398 | {value: 0x0040, lo: 0x9f, hi: 0xbf}, | ||
4399 | // Block 0xf4, offset 0x714 | ||
4400 | {value: 0x0000, lo: 0x02}, | ||
4401 | {value: 0x0018, lo: 0x80, hi: 0x91}, | ||
4402 | {value: 0x0040, lo: 0x92, hi: 0xbf}, | ||
4403 | // Block 0xf5, offset 0x717 | ||
4404 | {value: 0x0000, lo: 0x02}, | ||
4405 | {value: 0x0018, lo: 0x80, hi: 0x80}, | ||
4406 | {value: 0x0040, lo: 0x81, hi: 0xbf}, | ||
4407 | // Block 0xf6, offset 0x71a | ||
4408 | {value: 0x0000, lo: 0x02}, | ||
4409 | {value: 0x0008, lo: 0x80, hi: 0x96}, | ||
4410 | {value: 0x0040, lo: 0x97, hi: 0xbf}, | ||
4411 | // Block 0xf7, offset 0x71d | ||
4412 | {value: 0x0000, lo: 0x02}, | ||
4413 | {value: 0x0008, lo: 0x80, hi: 0xb4}, | ||
4414 | {value: 0x0040, lo: 0xb5, hi: 0xbf}, | ||
4415 | // Block 0xf8, offset 0x720 | ||
4416 | {value: 0x0000, lo: 0x03}, | ||
4417 | {value: 0x0008, lo: 0x80, hi: 0x9d}, | ||
4418 | {value: 0x0040, lo: 0x9e, hi: 0x9f}, | ||
4419 | {value: 0x0008, lo: 0xa0, hi: 0xbf}, | ||
4420 | // Block 0xf9, offset 0x724 | ||
4421 | {value: 0x0000, lo: 0x02}, | ||
4422 | {value: 0x0008, lo: 0x80, hi: 0xa1}, | ||
4423 | {value: 0x0040, lo: 0xa2, hi: 0xbf}, | ||
4424 | // Block 0xfa, offset 0x727 | ||
4425 | {value: 0x0020, lo: 0x0f}, | ||
4426 | {value: 0xdeb9, lo: 0x80, hi: 0x89}, | ||
4427 | {value: 0x8dfd, lo: 0x8a, hi: 0x8a}, | ||
4428 | {value: 0xdff9, lo: 0x8b, hi: 0x9c}, | ||
4429 | {value: 0x8e1d, lo: 0x9d, hi: 0x9d}, | ||
4430 | {value: 0xe239, lo: 0x9e, hi: 0xa2}, | ||
4431 | {value: 0x8e3d, lo: 0xa3, hi: 0xa3}, | ||
4432 | {value: 0xe2d9, lo: 0xa4, hi: 0xab}, | ||
4433 | {value: 0x7ed5, lo: 0xac, hi: 0xac}, | ||
4434 | {value: 0xe3d9, lo: 0xad, hi: 0xaf}, | ||
4435 | {value: 0x8e5d, lo: 0xb0, hi: 0xb0}, | ||
4436 | {value: 0xe439, lo: 0xb1, hi: 0xb6}, | ||
4437 | {value: 0x8e7d, lo: 0xb7, hi: 0xb9}, | ||
4438 | {value: 0xe4f9, lo: 0xba, hi: 0xba}, | ||
4439 | {value: 0x8edd, lo: 0xbb, hi: 0xbb}, | ||
4440 | {value: 0xe519, lo: 0xbc, hi: 0xbf}, | ||
4441 | // Block 0xfb, offset 0x737 | ||
4442 | {value: 0x0020, lo: 0x10}, | ||
4443 | {value: 0x937d, lo: 0x80, hi: 0x80}, | ||
4444 | {value: 0xf099, lo: 0x81, hi: 0x86}, | ||
4445 | {value: 0x939d, lo: 0x87, hi: 0x8a}, | ||
4446 | {value: 0xd9f9, lo: 0x8b, hi: 0x8b}, | ||
4447 | {value: 0xf159, lo: 0x8c, hi: 0x96}, | ||
4448 | {value: 0x941d, lo: 0x97, hi: 0x97}, | ||
4449 | {value: 0xf2b9, lo: 0x98, hi: 0xa3}, | ||
4450 | {value: 0x943d, lo: 0xa4, hi: 0xa6}, | ||
4451 | {value: 0xf439, lo: 0xa7, hi: 0xaa}, | ||
4452 | {value: 0x949d, lo: 0xab, hi: 0xab}, | ||
4453 | {value: 0xf4b9, lo: 0xac, hi: 0xac}, | ||
4454 | {value: 0x94bd, lo: 0xad, hi: 0xad}, | ||
4455 | {value: 0xf4d9, lo: 0xae, hi: 0xaf}, | ||
4456 | {value: 0x94dd, lo: 0xb0, hi: 0xb1}, | ||
4457 | {value: 0xf519, lo: 0xb2, hi: 0xbe}, | ||
4458 | {value: 0x0040, lo: 0xbf, hi: 0xbf}, | ||
4459 | // Block 0xfc, offset 0x748 | ||
4460 | {value: 0x0000, lo: 0x04}, | ||
4461 | {value: 0x0040, lo: 0x80, hi: 0x80}, | ||
4462 | {value: 0x0340, lo: 0x81, hi: 0x81}, | ||
4463 | {value: 0x0040, lo: 0x82, hi: 0x9f}, | ||
4464 | {value: 0x0340, lo: 0xa0, hi: 0xbf}, | ||
4465 | // Block 0xfd, offset 0x74d | ||
4466 | {value: 0x0000, lo: 0x01}, | ||
4467 | {value: 0x0340, lo: 0x80, hi: 0xbf}, | ||
4468 | // Block 0xfe, offset 0x74f | ||
4469 | {value: 0x0000, lo: 0x01}, | ||
4470 | {value: 0x13c0, lo: 0x80, hi: 0xbf}, | ||
4471 | // Block 0xff, offset 0x751 | ||
4472 | {value: 0x0000, lo: 0x02}, | ||
4473 | {value: 0x13c0, lo: 0x80, hi: 0xaf}, | ||
4474 | {value: 0x0040, lo: 0xb0, hi: 0xbf}, | ||
4475 | } | ||
4476 | |||
4477 | // Total table size 41559 bytes (40KiB); checksum: F4A1FA4E | ||
diff --git a/vendor/golang.org/x/net/idna/trie.go b/vendor/golang.org/x/net/idna/trie.go new file mode 100644 index 0000000..c4ef847 --- /dev/null +++ b/vendor/golang.org/x/net/idna/trie.go | |||
@@ -0,0 +1,72 @@ | |||
1 | // Code generated by running "go generate" in golang.org/x/text. DO NOT EDIT. | ||
2 | |||
3 | // Copyright 2016 The Go Authors. All rights reserved. | ||
4 | // Use of this source code is governed by a BSD-style | ||
5 | // license that can be found in the LICENSE file. | ||
6 | |||
7 | package idna | ||
8 | |||
9 | // appendMapping appends the mapping for the respective rune. isMapped must be | ||
10 | // true. A mapping is a categorization of a rune as defined in UTS #46. | ||
11 | func (c info) appendMapping(b []byte, s string) []byte { | ||
12 | index := int(c >> indexShift) | ||
13 | if c&xorBit == 0 { | ||
14 | s := mappings[index:] | ||
15 | return append(b, s[1:s[0]+1]...) | ||
16 | } | ||
17 | b = append(b, s...) | ||
18 | if c&inlineXOR == inlineXOR { | ||
19 | // TODO: support and handle two-byte inline masks | ||
20 | b[len(b)-1] ^= byte(index) | ||
21 | } else { | ||
22 | for p := len(b) - int(xorData[index]); p < len(b); p++ { | ||
23 | index++ | ||
24 | b[p] ^= xorData[index] | ||
25 | } | ||
26 | } | ||
27 | return b | ||
28 | } | ||
29 | |||
30 | // Sparse block handling code. | ||
31 | |||
32 | type valueRange struct { | ||
33 | value uint16 // header: value:stride | ||
34 | lo, hi byte // header: lo:n | ||
35 | } | ||
36 | |||
37 | type sparseBlocks struct { | ||
38 | values []valueRange | ||
39 | offset []uint16 | ||
40 | } | ||
41 | |||
42 | var idnaSparse = sparseBlocks{ | ||
43 | values: idnaSparseValues[:], | ||
44 | offset: idnaSparseOffset[:], | ||
45 | } | ||
46 | |||
47 | // Don't use newIdnaTrie to avoid unconditional linking in of the table. | ||
48 | var trie = &idnaTrie{} | ||
49 | |||
50 | // lookup determines the type of block n and looks up the value for b. | ||
51 | // For n < t.cutoff, the block is a simple lookup table. Otherwise, the block | ||
52 | // is a list of ranges with an accompanying value. Given a matching range r, | ||
53 | // the value for b is by r.value + (b - r.lo) * stride. | ||
54 | func (t *sparseBlocks) lookup(n uint32, b byte) uint16 { | ||
55 | offset := t.offset[n] | ||
56 | header := t.values[offset] | ||
57 | lo := offset + 1 | ||
58 | hi := lo + uint16(header.lo) | ||
59 | for lo < hi { | ||
60 | m := lo + (hi-lo)/2 | ||
61 | r := t.values[m] | ||
62 | if r.lo <= b && b <= r.hi { | ||
63 | return r.value + uint16(b-r.lo)*header.value | ||
64 | } | ||
65 | if b < r.lo { | ||
66 | hi = m | ||
67 | } else { | ||
68 | lo = m + 1 | ||
69 | } | ||
70 | } | ||
71 | return 0 | ||
72 | } | ||
diff --git a/vendor/golang.org/x/net/idna/trieval.go b/vendor/golang.org/x/net/idna/trieval.go new file mode 100644 index 0000000..63cb03b --- /dev/null +++ b/vendor/golang.org/x/net/idna/trieval.go | |||
@@ -0,0 +1,114 @@ | |||
1 | // Code generated by running "go generate" in golang.org/x/text. DO NOT EDIT. | ||
2 | |||
3 | package idna | ||
4 | |||
5 | // This file contains definitions for interpreting the trie value of the idna | ||
6 | // trie generated by "go run gen*.go". It is shared by both the generator | ||
7 | // program and the resultant package. Sharing is achieved by the generator | ||
8 | // copying gen_trieval.go to trieval.go and changing what's above this comment. | ||
9 | |||
10 | // info holds information from the IDNA mapping table for a single rune. It is | ||
11 | // the value returned by a trie lookup. In most cases, all information fits in | ||
12 | // a 16-bit value. For mappings, this value may contain an index into a slice | ||
13 | // with the mapped string. Such mappings can consist of the actual mapped value | ||
14 | // or an XOR pattern to be applied to the bytes of the UTF8 encoding of the | ||
15 | // input rune. This technique is used by the cases packages and reduces the | ||
16 | // table size significantly. | ||
17 | // | ||
18 | // The per-rune values have the following format: | ||
19 | // | ||
20 | // if mapped { | ||
21 | // if inlinedXOR { | ||
22 | // 15..13 inline XOR marker | ||
23 | // 12..11 unused | ||
24 | // 10..3 inline XOR mask | ||
25 | // } else { | ||
26 | // 15..3 index into xor or mapping table | ||
27 | // } | ||
28 | // } else { | ||
29 | // 15..13 unused | ||
30 | // 12 modifier (including virama) | ||
31 | // 11 virama modifier | ||
32 | // 10..8 joining type | ||
33 | // 7..3 category type | ||
34 | // } | ||
35 | // 2 use xor pattern | ||
36 | // 1..0 mapped category | ||
37 | // | ||
38 | // See the definitions below for a more detailed description of the various | ||
39 | // bits. | ||
40 | type info uint16 | ||
41 | |||
42 | const ( | ||
43 | catSmallMask = 0x3 | ||
44 | catBigMask = 0xF8 | ||
45 | indexShift = 3 | ||
46 | xorBit = 0x4 // interpret the index as an xor pattern | ||
47 | inlineXOR = 0xE000 // These bits are set if the XOR pattern is inlined. | ||
48 | |||
49 | joinShift = 8 | ||
50 | joinMask = 0x07 | ||
51 | |||
52 | viramaModifier = 0x0800 | ||
53 | modifier = 0x1000 | ||
54 | ) | ||
55 | |||
56 | // A category corresponds to a category defined in the IDNA mapping table. | ||
57 | type category uint16 | ||
58 | |||
59 | const ( | ||
60 | unknown category = 0 // not defined currently in unicode. | ||
61 | mapped category = 1 | ||
62 | disallowedSTD3Mapped category = 2 | ||
63 | deviation category = 3 | ||
64 | ) | ||
65 | |||
66 | const ( | ||
67 | valid category = 0x08 | ||
68 | validNV8 category = 0x18 | ||
69 | validXV8 category = 0x28 | ||
70 | disallowed category = 0x40 | ||
71 | disallowedSTD3Valid category = 0x80 | ||
72 | ignored category = 0xC0 | ||
73 | ) | ||
74 | |||
75 | // join types and additional rune information | ||
76 | const ( | ||
77 | joiningL = (iota + 1) | ||
78 | joiningD | ||
79 | joiningT | ||
80 | joiningR | ||
81 | |||
82 | //the following types are derived during processing | ||
83 | joinZWJ | ||
84 | joinZWNJ | ||
85 | joinVirama | ||
86 | numJoinTypes | ||
87 | ) | ||
88 | |||
89 | func (c info) isMapped() bool { | ||
90 | return c&0x3 != 0 | ||
91 | } | ||
92 | |||
93 | func (c info) category() category { | ||
94 | small := c & catSmallMask | ||
95 | if small != 0 { | ||
96 | return category(small) | ||
97 | } | ||
98 | return category(c & catBigMask) | ||
99 | } | ||
100 | |||
101 | func (c info) joinType() info { | ||
102 | if c.isMapped() { | ||
103 | return 0 | ||
104 | } | ||
105 | return (c >> joinShift) & joinMask | ||
106 | } | ||
107 | |||
108 | func (c info) isModifier() bool { | ||
109 | return c&(modifier|catSmallMask) == modifier | ||
110 | } | ||
111 | |||
112 | func (c info) isViramaModifier() bool { | ||
113 | return c&(viramaModifier|catSmallMask) == viramaModifier | ||
114 | } | ||
diff --git a/vendor/golang.org/x/net/internal/timeseries/timeseries.go b/vendor/golang.org/x/net/internal/timeseries/timeseries.go new file mode 100644 index 0000000..685f0e7 --- /dev/null +++ b/vendor/golang.org/x/net/internal/timeseries/timeseries.go | |||
@@ -0,0 +1,525 @@ | |||
1 | // Copyright 2015 The Go Authors. All rights reserved. | ||
2 | // Use of this source code is governed by a BSD-style | ||
3 | // license that can be found in the LICENSE file. | ||
4 | |||
5 | // Package timeseries implements a time series structure for stats collection. | ||
6 | package timeseries // import "golang.org/x/net/internal/timeseries" | ||
7 | |||
8 | import ( | ||
9 | "fmt" | ||
10 | "log" | ||
11 | "time" | ||
12 | ) | ||
13 | |||
14 | const ( | ||
15 | timeSeriesNumBuckets = 64 | ||
16 | minuteHourSeriesNumBuckets = 60 | ||
17 | ) | ||
18 | |||
19 | var timeSeriesResolutions = []time.Duration{ | ||
20 | 1 * time.Second, | ||
21 | 10 * time.Second, | ||
22 | 1 * time.Minute, | ||
23 | 10 * time.Minute, | ||
24 | 1 * time.Hour, | ||
25 | 6 * time.Hour, | ||
26 | 24 * time.Hour, // 1 day | ||
27 | 7 * 24 * time.Hour, // 1 week | ||
28 | 4 * 7 * 24 * time.Hour, // 4 weeks | ||
29 | 16 * 7 * 24 * time.Hour, // 16 weeks | ||
30 | } | ||
31 | |||
32 | var minuteHourSeriesResolutions = []time.Duration{ | ||
33 | 1 * time.Second, | ||
34 | 1 * time.Minute, | ||
35 | } | ||
36 | |||
37 | // An Observable is a kind of data that can be aggregated in a time series. | ||
38 | type Observable interface { | ||
39 | Multiply(ratio float64) // Multiplies the data in self by a given ratio | ||
40 | Add(other Observable) // Adds the data from a different observation to self | ||
41 | Clear() // Clears the observation so it can be reused. | ||
42 | CopyFrom(other Observable) // Copies the contents of a given observation to self | ||
43 | } | ||
44 | |||
45 | // Float attaches the methods of Observable to a float64. | ||
46 | type Float float64 | ||
47 | |||
48 | // NewFloat returns a Float. | ||
49 | func NewFloat() Observable { | ||
50 | f := Float(0) | ||
51 | return &f | ||
52 | } | ||
53 | |||
54 | // String returns the float as a string. | ||
55 | func (f *Float) String() string { return fmt.Sprintf("%g", f.Value()) } | ||
56 | |||
57 | // Value returns the float's value. | ||
58 | func (f *Float) Value() float64 { return float64(*f) } | ||
59 | |||
60 | func (f *Float) Multiply(ratio float64) { *f *= Float(ratio) } | ||
61 | |||
62 | func (f *Float) Add(other Observable) { | ||
63 | o := other.(*Float) | ||
64 | *f += *o | ||
65 | } | ||
66 | |||
67 | func (f *Float) Clear() { *f = 0 } | ||
68 | |||
69 | func (f *Float) CopyFrom(other Observable) { | ||
70 | o := other.(*Float) | ||
71 | *f = *o | ||
72 | } | ||
73 | |||
74 | // A Clock tells the current time. | ||
75 | type Clock interface { | ||
76 | Time() time.Time | ||
77 | } | ||
78 | |||
79 | type defaultClock int | ||
80 | |||
81 | var defaultClockInstance defaultClock | ||
82 | |||
83 | func (defaultClock) Time() time.Time { return time.Now() } | ||
84 | |||
85 | // Information kept per level. Each level consists of a circular list of | ||
86 | // observations. The start of the level may be derived from end and the | ||
87 | // len(buckets) * sizeInMillis. | ||
88 | type tsLevel struct { | ||
89 | oldest int // index to oldest bucketed Observable | ||
90 | newest int // index to newest bucketed Observable | ||
91 | end time.Time // end timestamp for this level | ||
92 | size time.Duration // duration of the bucketed Observable | ||
93 | buckets []Observable // collections of observations | ||
94 | provider func() Observable // used for creating new Observable | ||
95 | } | ||
96 | |||
97 | func (l *tsLevel) Clear() { | ||
98 | l.oldest = 0 | ||
99 | l.newest = len(l.buckets) - 1 | ||
100 | l.end = time.Time{} | ||
101 | for i := range l.buckets { | ||
102 | if l.buckets[i] != nil { | ||
103 | l.buckets[i].Clear() | ||
104 | l.buckets[i] = nil | ||
105 | } | ||
106 | } | ||
107 | } | ||
108 | |||
109 | func (l *tsLevel) InitLevel(size time.Duration, numBuckets int, f func() Observable) { | ||
110 | l.size = size | ||
111 | l.provider = f | ||
112 | l.buckets = make([]Observable, numBuckets) | ||
113 | } | ||
114 | |||
115 | // Keeps a sequence of levels. Each level is responsible for storing data at | ||
116 | // a given resolution. For example, the first level stores data at a one | ||
117 | // minute resolution while the second level stores data at a one hour | ||
118 | // resolution. | ||
119 | |||
120 | // Each level is represented by a sequence of buckets. Each bucket spans an | ||
121 | // interval equal to the resolution of the level. New observations are added | ||
122 | // to the last bucket. | ||
123 | type timeSeries struct { | ||
124 | provider func() Observable // make more Observable | ||
125 | numBuckets int // number of buckets in each level | ||
126 | levels []*tsLevel // levels of bucketed Observable | ||
127 | lastAdd time.Time // time of last Observable tracked | ||
128 | total Observable // convenient aggregation of all Observable | ||
129 | clock Clock // Clock for getting current time | ||
130 | pending Observable // observations not yet bucketed | ||
131 | pendingTime time.Time // what time are we keeping in pending | ||
132 | dirty bool // if there are pending observations | ||
133 | } | ||
134 | |||
135 | // init initializes a level according to the supplied criteria. | ||
136 | func (ts *timeSeries) init(resolutions []time.Duration, f func() Observable, numBuckets int, clock Clock) { | ||
137 | ts.provider = f | ||
138 | ts.numBuckets = numBuckets | ||
139 | ts.clock = clock | ||
140 | ts.levels = make([]*tsLevel, len(resolutions)) | ||
141 | |||
142 | for i := range resolutions { | ||
143 | if i > 0 && resolutions[i-1] >= resolutions[i] { | ||
144 | log.Print("timeseries: resolutions must be monotonically increasing") | ||
145 | break | ||
146 | } | ||
147 | newLevel := new(tsLevel) | ||
148 | newLevel.InitLevel(resolutions[i], ts.numBuckets, ts.provider) | ||
149 | ts.levels[i] = newLevel | ||
150 | } | ||
151 | |||
152 | ts.Clear() | ||
153 | } | ||
154 | |||
155 | // Clear removes all observations from the time series. | ||
156 | func (ts *timeSeries) Clear() { | ||
157 | ts.lastAdd = time.Time{} | ||
158 | ts.total = ts.resetObservation(ts.total) | ||
159 | ts.pending = ts.resetObservation(ts.pending) | ||
160 | ts.pendingTime = time.Time{} | ||
161 | ts.dirty = false | ||
162 | |||
163 | for i := range ts.levels { | ||
164 | ts.levels[i].Clear() | ||
165 | } | ||
166 | } | ||
167 | |||
168 | // Add records an observation at the current time. | ||
169 | func (ts *timeSeries) Add(observation Observable) { | ||
170 | ts.AddWithTime(observation, ts.clock.Time()) | ||
171 | } | ||
172 | |||
173 | // AddWithTime records an observation at the specified time. | ||
174 | func (ts *timeSeries) AddWithTime(observation Observable, t time.Time) { | ||
175 | |||
176 | smallBucketDuration := ts.levels[0].size | ||
177 | |||
178 | if t.After(ts.lastAdd) { | ||
179 | ts.lastAdd = t | ||
180 | } | ||
181 | |||
182 | if t.After(ts.pendingTime) { | ||
183 | ts.advance(t) | ||
184 | ts.mergePendingUpdates() | ||
185 | ts.pendingTime = ts.levels[0].end | ||
186 | ts.pending.CopyFrom(observation) | ||
187 | ts.dirty = true | ||
188 | } else if t.After(ts.pendingTime.Add(-1 * smallBucketDuration)) { | ||
189 | // The observation is close enough to go into the pending bucket. | ||
190 | // This compensates for clock skewing and small scheduling delays | ||
191 | // by letting the update stay in the fast path. | ||
192 | ts.pending.Add(observation) | ||
193 | ts.dirty = true | ||
194 | } else { | ||
195 | ts.mergeValue(observation, t) | ||
196 | } | ||
197 | } | ||
198 | |||
199 | // mergeValue inserts the observation at the specified time in the past into all levels. | ||
200 | func (ts *timeSeries) mergeValue(observation Observable, t time.Time) { | ||
201 | for _, level := range ts.levels { | ||
202 | index := (ts.numBuckets - 1) - int(level.end.Sub(t)/level.size) | ||
203 | if 0 <= index && index < ts.numBuckets { | ||
204 | bucketNumber := (level.oldest + index) % ts.numBuckets | ||
205 | if level.buckets[bucketNumber] == nil { | ||
206 | level.buckets[bucketNumber] = level.provider() | ||
207 | } | ||
208 | level.buckets[bucketNumber].Add(observation) | ||
209 | } | ||
210 | } | ||
211 | ts.total.Add(observation) | ||
212 | } | ||
213 | |||
214 | // mergePendingUpdates applies the pending updates into all levels. | ||
215 | func (ts *timeSeries) mergePendingUpdates() { | ||
216 | if ts.dirty { | ||
217 | ts.mergeValue(ts.pending, ts.pendingTime) | ||
218 | ts.pending = ts.resetObservation(ts.pending) | ||
219 | ts.dirty = false | ||
220 | } | ||
221 | } | ||
222 | |||
223 | // advance cycles the buckets at each level until the latest bucket in | ||
224 | // each level can hold the time specified. | ||
225 | func (ts *timeSeries) advance(t time.Time) { | ||
226 | if !t.After(ts.levels[0].end) { | ||
227 | return | ||
228 | } | ||
229 | for i := 0; i < len(ts.levels); i++ { | ||
230 | level := ts.levels[i] | ||
231 | if !level.end.Before(t) { | ||
232 | break | ||
233 | } | ||
234 | |||
235 | // If the time is sufficiently far, just clear the level and advance | ||
236 | // directly. | ||
237 | if !t.Before(level.end.Add(level.size * time.Duration(ts.numBuckets))) { | ||
238 | for _, b := range level.buckets { | ||
239 | ts.resetObservation(b) | ||
240 | } | ||
241 | level.end = time.Unix(0, (t.UnixNano()/level.size.Nanoseconds())*level.size.Nanoseconds()) | ||
242 | } | ||
243 | |||
244 | for t.After(level.end) { | ||
245 | level.end = level.end.Add(level.size) | ||
246 | level.newest = level.oldest | ||
247 | level.oldest = (level.oldest + 1) % ts.numBuckets | ||
248 | ts.resetObservation(level.buckets[level.newest]) | ||
249 | } | ||
250 | |||
251 | t = level.end | ||
252 | } | ||
253 | } | ||
254 | |||
255 | // Latest returns the sum of the num latest buckets from the level. | ||
256 | func (ts *timeSeries) Latest(level, num int) Observable { | ||
257 | now := ts.clock.Time() | ||
258 | if ts.levels[0].end.Before(now) { | ||
259 | ts.advance(now) | ||
260 | } | ||
261 | |||
262 | ts.mergePendingUpdates() | ||
263 | |||
264 | result := ts.provider() | ||
265 | l := ts.levels[level] | ||
266 | index := l.newest | ||
267 | |||
268 | for i := 0; i < num; i++ { | ||
269 | if l.buckets[index] != nil { | ||
270 | result.Add(l.buckets[index]) | ||
271 | } | ||
272 | if index == 0 { | ||
273 | index = ts.numBuckets | ||
274 | } | ||
275 | index-- | ||
276 | } | ||
277 | |||
278 | return result | ||
279 | } | ||
280 | |||
281 | // LatestBuckets returns a copy of the num latest buckets from level. | ||
282 | func (ts *timeSeries) LatestBuckets(level, num int) []Observable { | ||
283 | if level < 0 || level > len(ts.levels) { | ||
284 | log.Print("timeseries: bad level argument: ", level) | ||
285 | return nil | ||
286 | } | ||
287 | if num < 0 || num >= ts.numBuckets { | ||
288 | log.Print("timeseries: bad num argument: ", num) | ||
289 | return nil | ||
290 | } | ||
291 | |||
292 | results := make([]Observable, num) | ||
293 | now := ts.clock.Time() | ||
294 | if ts.levels[0].end.Before(now) { | ||
295 | ts.advance(now) | ||
296 | } | ||
297 | |||
298 | ts.mergePendingUpdates() | ||
299 | |||
300 | l := ts.levels[level] | ||
301 | index := l.newest | ||
302 | |||
303 | for i := 0; i < num; i++ { | ||
304 | result := ts.provider() | ||
305 | results[i] = result | ||
306 | if l.buckets[index] != nil { | ||
307 | result.CopyFrom(l.buckets[index]) | ||
308 | } | ||
309 | |||
310 | if index == 0 { | ||
311 | index = ts.numBuckets | ||
312 | } | ||
313 | index -= 1 | ||
314 | } | ||
315 | return results | ||
316 | } | ||
317 | |||
318 | // ScaleBy updates observations by scaling by factor. | ||
319 | func (ts *timeSeries) ScaleBy(factor float64) { | ||
320 | for _, l := range ts.levels { | ||
321 | for i := 0; i < ts.numBuckets; i++ { | ||
322 | l.buckets[i].Multiply(factor) | ||
323 | } | ||
324 | } | ||
325 | |||
326 | ts.total.Multiply(factor) | ||
327 | ts.pending.Multiply(factor) | ||
328 | } | ||
329 | |||
330 | // Range returns the sum of observations added over the specified time range. | ||
331 | // If start or finish times don't fall on bucket boundaries of the same | ||
332 | // level, then return values are approximate answers. | ||
333 | func (ts *timeSeries) Range(start, finish time.Time) Observable { | ||
334 | return ts.ComputeRange(start, finish, 1)[0] | ||
335 | } | ||
336 | |||
337 | // Recent returns the sum of observations from the last delta. | ||
338 | func (ts *timeSeries) Recent(delta time.Duration) Observable { | ||
339 | now := ts.clock.Time() | ||
340 | return ts.Range(now.Add(-delta), now) | ||
341 | } | ||
342 | |||
343 | // Total returns the total of all observations. | ||
344 | func (ts *timeSeries) Total() Observable { | ||
345 | ts.mergePendingUpdates() | ||
346 | return ts.total | ||
347 | } | ||
348 | |||
349 | // ComputeRange computes a specified number of values into a slice using | ||
350 | // the observations recorded over the specified time period. The return | ||
351 | // values are approximate if the start or finish times don't fall on the | ||
352 | // bucket boundaries at the same level or if the number of buckets spanning | ||
353 | // the range is not an integral multiple of num. | ||
354 | func (ts *timeSeries) ComputeRange(start, finish time.Time, num int) []Observable { | ||
355 | if start.After(finish) { | ||
356 | log.Printf("timeseries: start > finish, %v>%v", start, finish) | ||
357 | return nil | ||
358 | } | ||
359 | |||
360 | if num < 0 { | ||
361 | log.Printf("timeseries: num < 0, %v", num) | ||
362 | return nil | ||
363 | } | ||
364 | |||
365 | results := make([]Observable, num) | ||
366 | |||
367 | for _, l := range ts.levels { | ||
368 | if !start.Before(l.end.Add(-l.size * time.Duration(ts.numBuckets))) { | ||
369 | ts.extract(l, start, finish, num, results) | ||
370 | return results | ||
371 | } | ||
372 | } | ||
373 | |||
374 | // Failed to find a level that covers the desired range. So just | ||
375 | // extract from the last level, even if it doesn't cover the entire | ||
376 | // desired range. | ||
377 | ts.extract(ts.levels[len(ts.levels)-1], start, finish, num, results) | ||
378 | |||
379 | return results | ||
380 | } | ||
381 | |||
382 | // RecentList returns the specified number of values in slice over the most | ||
383 | // recent time period of the specified range. | ||
384 | func (ts *timeSeries) RecentList(delta time.Duration, num int) []Observable { | ||
385 | if delta < 0 { | ||
386 | return nil | ||
387 | } | ||
388 | now := ts.clock.Time() | ||
389 | return ts.ComputeRange(now.Add(-delta), now, num) | ||
390 | } | ||
391 | |||
392 | // extract returns a slice of specified number of observations from a given | ||
393 | // level over a given range. | ||
394 | func (ts *timeSeries) extract(l *tsLevel, start, finish time.Time, num int, results []Observable) { | ||
395 | ts.mergePendingUpdates() | ||
396 | |||
397 | srcInterval := l.size | ||
398 | dstInterval := finish.Sub(start) / time.Duration(num) | ||
399 | dstStart := start | ||
400 | srcStart := l.end.Add(-srcInterval * time.Duration(ts.numBuckets)) | ||
401 | |||
402 | srcIndex := 0 | ||
403 | |||
404 | // Where should scanning start? | ||
405 | if dstStart.After(srcStart) { | ||
406 | advance := dstStart.Sub(srcStart) / srcInterval | ||
407 | srcIndex += int(advance) | ||
408 | srcStart = srcStart.Add(advance * srcInterval) | ||
409 | } | ||
410 | |||
411 | // The i'th value is computed as show below. | ||
412 | // interval = (finish/start)/num | ||
413 | // i'th value = sum of observation in range | ||
414 | // [ start + i * interval, | ||
415 | // start + (i + 1) * interval ) | ||
416 | for i := 0; i < num; i++ { | ||
417 | results[i] = ts.resetObservation(results[i]) | ||
418 | dstEnd := dstStart.Add(dstInterval) | ||
419 | for srcIndex < ts.numBuckets && srcStart.Before(dstEnd) { | ||
420 | srcEnd := srcStart.Add(srcInterval) | ||
421 | if srcEnd.After(ts.lastAdd) { | ||
422 | srcEnd = ts.lastAdd | ||
423 | } | ||
424 | |||
425 | if !srcEnd.Before(dstStart) { | ||
426 | srcValue := l.buckets[(srcIndex+l.oldest)%ts.numBuckets] | ||
427 | if !srcStart.Before(dstStart) && !srcEnd.After(dstEnd) { | ||
428 | // dst completely contains src. | ||
429 | if srcValue != nil { | ||
430 | results[i].Add(srcValue) | ||
431 | } | ||
432 | } else { | ||
433 | // dst partially overlaps src. | ||
434 | overlapStart := maxTime(srcStart, dstStart) | ||
435 | overlapEnd := minTime(srcEnd, dstEnd) | ||
436 | base := srcEnd.Sub(srcStart) | ||
437 | fraction := overlapEnd.Sub(overlapStart).Seconds() / base.Seconds() | ||
438 | |||
439 | used := ts.provider() | ||
440 | if srcValue != nil { | ||
441 | used.CopyFrom(srcValue) | ||
442 | } | ||
443 | used.Multiply(fraction) | ||
444 | results[i].Add(used) | ||
445 | } | ||
446 | |||
447 | if srcEnd.After(dstEnd) { | ||
448 | break | ||
449 | } | ||
450 | } | ||
451 | srcIndex++ | ||
452 | srcStart = srcStart.Add(srcInterval) | ||
453 | } | ||
454 | dstStart = dstStart.Add(dstInterval) | ||
455 | } | ||
456 | } | ||
457 | |||
458 | // resetObservation clears the content so the struct may be reused. | ||
459 | func (ts *timeSeries) resetObservation(observation Observable) Observable { | ||
460 | if observation == nil { | ||
461 | observation = ts.provider() | ||
462 | } else { | ||
463 | observation.Clear() | ||
464 | } | ||
465 | return observation | ||
466 | } | ||
467 | |||
468 | // TimeSeries tracks data at granularities from 1 second to 16 weeks. | ||
469 | type TimeSeries struct { | ||
470 | timeSeries | ||
471 | } | ||
472 | |||
473 | // NewTimeSeries creates a new TimeSeries using the function provided for creating new Observable. | ||
474 | func NewTimeSeries(f func() Observable) *TimeSeries { | ||
475 | return NewTimeSeriesWithClock(f, defaultClockInstance) | ||
476 | } | ||
477 | |||
478 | // NewTimeSeriesWithClock creates a new TimeSeries using the function provided for creating new Observable and the clock for | ||
479 | // assigning timestamps. | ||
480 | func NewTimeSeriesWithClock(f func() Observable, clock Clock) *TimeSeries { | ||
481 | ts := new(TimeSeries) | ||
482 | ts.timeSeries.init(timeSeriesResolutions, f, timeSeriesNumBuckets, clock) | ||
483 | return ts | ||
484 | } | ||
485 | |||
486 | // MinuteHourSeries tracks data at granularities of 1 minute and 1 hour. | ||
487 | type MinuteHourSeries struct { | ||
488 | timeSeries | ||
489 | } | ||
490 | |||
491 | // NewMinuteHourSeries creates a new MinuteHourSeries using the function provided for creating new Observable. | ||
492 | func NewMinuteHourSeries(f func() Observable) *MinuteHourSeries { | ||
493 | return NewMinuteHourSeriesWithClock(f, defaultClockInstance) | ||
494 | } | ||
495 | |||
496 | // NewMinuteHourSeriesWithClock creates a new MinuteHourSeries using the function provided for creating new Observable and the clock for | ||
497 | // assigning timestamps. | ||
498 | func NewMinuteHourSeriesWithClock(f func() Observable, clock Clock) *MinuteHourSeries { | ||
499 | ts := new(MinuteHourSeries) | ||
500 | ts.timeSeries.init(minuteHourSeriesResolutions, f, | ||
501 | minuteHourSeriesNumBuckets, clock) | ||
502 | return ts | ||
503 | } | ||
504 | |||
505 | func (ts *MinuteHourSeries) Minute() Observable { | ||
506 | return ts.timeSeries.Latest(0, 60) | ||
507 | } | ||
508 | |||
509 | func (ts *MinuteHourSeries) Hour() Observable { | ||
510 | return ts.timeSeries.Latest(1, 60) | ||
511 | } | ||
512 | |||
513 | func minTime(a, b time.Time) time.Time { | ||
514 | if a.Before(b) { | ||
515 | return a | ||
516 | } | ||
517 | return b | ||
518 | } | ||
519 | |||
520 | func maxTime(a, b time.Time) time.Time { | ||
521 | if a.After(b) { | ||
522 | return a | ||
523 | } | ||
524 | return b | ||
525 | } | ||
diff --git a/vendor/golang.org/x/net/lex/httplex/httplex.go b/vendor/golang.org/x/net/lex/httplex/httplex.go new file mode 100644 index 0000000..20f2b89 --- /dev/null +++ b/vendor/golang.org/x/net/lex/httplex/httplex.go | |||
@@ -0,0 +1,351 @@ | |||
1 | // Copyright 2016 The Go Authors. All rights reserved. | ||
2 | // Use of this source code is governed by a BSD-style | ||
3 | // license that can be found in the LICENSE file. | ||
4 | |||
5 | // Package httplex contains rules around lexical matters of various | ||
6 | // HTTP-related specifications. | ||
7 | // | ||
8 | // This package is shared by the standard library (which vendors it) | ||
9 | // and x/net/http2. It comes with no API stability promise. | ||
10 | package httplex | ||
11 | |||
12 | import ( | ||
13 | "net" | ||
14 | "strings" | ||
15 | "unicode/utf8" | ||
16 | |||
17 | "golang.org/x/net/idna" | ||
18 | ) | ||
19 | |||
20 | var isTokenTable = [127]bool{ | ||
21 | '!': true, | ||
22 | '#': true, | ||
23 | '$': true, | ||
24 | '%': true, | ||
25 | '&': true, | ||
26 | '\'': true, | ||
27 | '*': true, | ||
28 | '+': true, | ||
29 | '-': true, | ||
30 | '.': true, | ||
31 | '0': true, | ||
32 | '1': true, | ||
33 | '2': true, | ||
34 | '3': true, | ||
35 | '4': true, | ||
36 | '5': true, | ||
37 | '6': true, | ||
38 | '7': true, | ||
39 | '8': true, | ||
40 | '9': true, | ||
41 | 'A': true, | ||
42 | 'B': true, | ||
43 | 'C': true, | ||
44 | 'D': true, | ||
45 | 'E': true, | ||
46 | 'F': true, | ||
47 | 'G': true, | ||
48 | 'H': true, | ||
49 | 'I': true, | ||
50 | 'J': true, | ||
51 | 'K': true, | ||
52 | 'L': true, | ||
53 | 'M': true, | ||
54 | 'N': true, | ||
55 | 'O': true, | ||
56 | 'P': true, | ||
57 | 'Q': true, | ||
58 | 'R': true, | ||
59 | 'S': true, | ||
60 | 'T': true, | ||
61 | 'U': true, | ||
62 | 'W': true, | ||
63 | 'V': true, | ||
64 | 'X': true, | ||
65 | 'Y': true, | ||
66 | 'Z': true, | ||
67 | '^': true, | ||
68 | '_': true, | ||
69 | '`': true, | ||
70 | 'a': true, | ||
71 | 'b': true, | ||
72 | 'c': true, | ||
73 | 'd': true, | ||
74 | 'e': true, | ||
75 | 'f': true, | ||
76 | 'g': true, | ||
77 | 'h': true, | ||
78 | 'i': true, | ||
79 | 'j': true, | ||
80 | 'k': true, | ||
81 | 'l': true, | ||
82 | 'm': true, | ||
83 | 'n': true, | ||
84 | 'o': true, | ||
85 | 'p': true, | ||
86 | 'q': true, | ||
87 | 'r': true, | ||
88 | 's': true, | ||
89 | 't': true, | ||
90 | 'u': true, | ||
91 | 'v': true, | ||
92 | 'w': true, | ||
93 | 'x': true, | ||
94 | 'y': true, | ||
95 | 'z': true, | ||
96 | '|': true, | ||
97 | '~': true, | ||
98 | } | ||
99 | |||
100 | func IsTokenRune(r rune) bool { | ||
101 | i := int(r) | ||
102 | return i < len(isTokenTable) && isTokenTable[i] | ||
103 | } | ||
104 | |||
105 | func isNotToken(r rune) bool { | ||
106 | return !IsTokenRune(r) | ||
107 | } | ||
108 | |||
109 | // HeaderValuesContainsToken reports whether any string in values | ||
110 | // contains the provided token, ASCII case-insensitively. | ||
111 | func HeaderValuesContainsToken(values []string, token string) bool { | ||
112 | for _, v := range values { | ||
113 | if headerValueContainsToken(v, token) { | ||
114 | return true | ||
115 | } | ||
116 | } | ||
117 | return false | ||
118 | } | ||
119 | |||
120 | // isOWS reports whether b is an optional whitespace byte, as defined | ||
121 | // by RFC 7230 section 3.2.3. | ||
122 | func isOWS(b byte) bool { return b == ' ' || b == '\t' } | ||
123 | |||
124 | // trimOWS returns x with all optional whitespace removes from the | ||
125 | // beginning and end. | ||
126 | func trimOWS(x string) string { | ||
127 | // TODO: consider using strings.Trim(x, " \t") instead, | ||
128 | // if and when it's fast enough. See issue 10292. | ||
129 | // But this ASCII-only code will probably always beat UTF-8 | ||
130 | // aware code. | ||
131 | for len(x) > 0 && isOWS(x[0]) { | ||
132 | x = x[1:] | ||
133 | } | ||
134 | for len(x) > 0 && isOWS(x[len(x)-1]) { | ||
135 | x = x[:len(x)-1] | ||
136 | } | ||
137 | return x | ||
138 | } | ||
139 | |||
140 | // headerValueContainsToken reports whether v (assumed to be a | ||
141 | // 0#element, in the ABNF extension described in RFC 7230 section 7) | ||
142 | // contains token amongst its comma-separated tokens, ASCII | ||
143 | // case-insensitively. | ||
144 | func headerValueContainsToken(v string, token string) bool { | ||
145 | v = trimOWS(v) | ||
146 | if comma := strings.IndexByte(v, ','); comma != -1 { | ||
147 | return tokenEqual(trimOWS(v[:comma]), token) || headerValueContainsToken(v[comma+1:], token) | ||
148 | } | ||
149 | return tokenEqual(v, token) | ||
150 | } | ||
151 | |||
152 | // lowerASCII returns the ASCII lowercase version of b. | ||
153 | func lowerASCII(b byte) byte { | ||
154 | if 'A' <= b && b <= 'Z' { | ||
155 | return b + ('a' - 'A') | ||
156 | } | ||
157 | return b | ||
158 | } | ||
159 | |||
160 | // tokenEqual reports whether t1 and t2 are equal, ASCII case-insensitively. | ||
161 | func tokenEqual(t1, t2 string) bool { | ||
162 | if len(t1) != len(t2) { | ||
163 | return false | ||
164 | } | ||
165 | for i, b := range t1 { | ||
166 | if b >= utf8.RuneSelf { | ||
167 | // No UTF-8 or non-ASCII allowed in tokens. | ||
168 | return false | ||
169 | } | ||
170 | if lowerASCII(byte(b)) != lowerASCII(t2[i]) { | ||
171 | return false | ||
172 | } | ||
173 | } | ||
174 | return true | ||
175 | } | ||
176 | |||
177 | // isLWS reports whether b is linear white space, according | ||
178 | // to http://www.w3.org/Protocols/rfc2616/rfc2616-sec2.html#sec2.2 | ||
179 | // LWS = [CRLF] 1*( SP | HT ) | ||
180 | func isLWS(b byte) bool { return b == ' ' || b == '\t' } | ||
181 | |||
182 | // isCTL reports whether b is a control byte, according | ||
183 | // to http://www.w3.org/Protocols/rfc2616/rfc2616-sec2.html#sec2.2 | ||
184 | // CTL = <any US-ASCII control character | ||
185 | // (octets 0 - 31) and DEL (127)> | ||
186 | func isCTL(b byte) bool { | ||
187 | const del = 0x7f // a CTL | ||
188 | return b < ' ' || b == del | ||
189 | } | ||
190 | |||
191 | // ValidHeaderFieldName reports whether v is a valid HTTP/1.x header name. | ||
192 | // HTTP/2 imposes the additional restriction that uppercase ASCII | ||
193 | // letters are not allowed. | ||
194 | // | ||
195 | // RFC 7230 says: | ||
196 | // header-field = field-name ":" OWS field-value OWS | ||
197 | // field-name = token | ||
198 | // token = 1*tchar | ||
199 | // tchar = "!" / "#" / "$" / "%" / "&" / "'" / "*" / "+" / "-" / "." / | ||
200 | // "^" / "_" / "`" / "|" / "~" / DIGIT / ALPHA | ||
201 | func ValidHeaderFieldName(v string) bool { | ||
202 | if len(v) == 0 { | ||
203 | return false | ||
204 | } | ||
205 | for _, r := range v { | ||
206 | if !IsTokenRune(r) { | ||
207 | return false | ||
208 | } | ||
209 | } | ||
210 | return true | ||
211 | } | ||
212 | |||
213 | // ValidHostHeader reports whether h is a valid host header. | ||
214 | func ValidHostHeader(h string) bool { | ||
215 | // The latest spec is actually this: | ||
216 | // | ||
217 | // http://tools.ietf.org/html/rfc7230#section-5.4 | ||
218 | // Host = uri-host [ ":" port ] | ||
219 | // | ||
220 | // Where uri-host is: | ||
221 | // http://tools.ietf.org/html/rfc3986#section-3.2.2 | ||
222 | // | ||
223 | // But we're going to be much more lenient for now and just | ||
224 | // search for any byte that's not a valid byte in any of those | ||
225 | // expressions. | ||
226 | for i := 0; i < len(h); i++ { | ||
227 | if !validHostByte[h[i]] { | ||
228 | return false | ||
229 | } | ||
230 | } | ||
231 | return true | ||
232 | } | ||
233 | |||
234 | // See the validHostHeader comment. | ||
235 | var validHostByte = [256]bool{ | ||
236 | '0': true, '1': true, '2': true, '3': true, '4': true, '5': true, '6': true, '7': true, | ||
237 | '8': true, '9': true, | ||
238 | |||
239 | 'a': true, 'b': true, 'c': true, 'd': true, 'e': true, 'f': true, 'g': true, 'h': true, | ||
240 | 'i': true, 'j': true, 'k': true, 'l': true, 'm': true, 'n': true, 'o': true, 'p': true, | ||
241 | 'q': true, 'r': true, 's': true, 't': true, 'u': true, 'v': true, 'w': true, 'x': true, | ||
242 | 'y': true, 'z': true, | ||
243 | |||
244 | 'A': true, 'B': true, 'C': true, 'D': true, 'E': true, 'F': true, 'G': true, 'H': true, | ||
245 | 'I': true, 'J': true, 'K': true, 'L': true, 'M': true, 'N': true, 'O': true, 'P': true, | ||
246 | 'Q': true, 'R': true, 'S': true, 'T': true, 'U': true, 'V': true, 'W': true, 'X': true, | ||
247 | 'Y': true, 'Z': true, | ||
248 | |||
249 | '!': true, // sub-delims | ||
250 | '$': true, // sub-delims | ||
251 | '%': true, // pct-encoded (and used in IPv6 zones) | ||
252 | '&': true, // sub-delims | ||
253 | '(': true, // sub-delims | ||
254 | ')': true, // sub-delims | ||
255 | '*': true, // sub-delims | ||
256 | '+': true, // sub-delims | ||
257 | ',': true, // sub-delims | ||
258 | '-': true, // unreserved | ||
259 | '.': true, // unreserved | ||
260 | ':': true, // IPv6address + Host expression's optional port | ||
261 | ';': true, // sub-delims | ||
262 | '=': true, // sub-delims | ||
263 | '[': true, | ||
264 | '\'': true, // sub-delims | ||
265 | ']': true, | ||
266 | '_': true, // unreserved | ||
267 | '~': true, // unreserved | ||
268 | } | ||
269 | |||
270 | // ValidHeaderFieldValue reports whether v is a valid "field-value" according to | ||
271 | // http://www.w3.org/Protocols/rfc2616/rfc2616-sec4.html#sec4.2 : | ||
272 | // | ||
273 | // message-header = field-name ":" [ field-value ] | ||
274 | // field-value = *( field-content | LWS ) | ||
275 | // field-content = <the OCTETs making up the field-value | ||
276 | // and consisting of either *TEXT or combinations | ||
277 | // of token, separators, and quoted-string> | ||
278 | // | ||
279 | // http://www.w3.org/Protocols/rfc2616/rfc2616-sec2.html#sec2.2 : | ||
280 | // | ||
281 | // TEXT = <any OCTET except CTLs, | ||
282 | // but including LWS> | ||
283 | // LWS = [CRLF] 1*( SP | HT ) | ||
284 | // CTL = <any US-ASCII control character | ||
285 | // (octets 0 - 31) and DEL (127)> | ||
286 | // | ||
287 | // RFC 7230 says: | ||
288 | // field-value = *( field-content / obs-fold ) | ||
289 | // obj-fold = N/A to http2, and deprecated | ||
290 | // field-content = field-vchar [ 1*( SP / HTAB ) field-vchar ] | ||
291 | // field-vchar = VCHAR / obs-text | ||
292 | // obs-text = %x80-FF | ||
293 | // VCHAR = "any visible [USASCII] character" | ||
294 | // | ||
295 | // http2 further says: "Similarly, HTTP/2 allows header field values | ||
296 | // that are not valid. While most of the values that can be encoded | ||
297 | // will not alter header field parsing, carriage return (CR, ASCII | ||
298 | // 0xd), line feed (LF, ASCII 0xa), and the zero character (NUL, ASCII | ||
299 | // 0x0) might be exploited by an attacker if they are translated | ||
300 | // verbatim. Any request or response that contains a character not | ||
301 | // permitted in a header field value MUST be treated as malformed | ||
302 | // (Section 8.1.2.6). Valid characters are defined by the | ||
303 | // field-content ABNF rule in Section 3.2 of [RFC7230]." | ||
304 | // | ||
305 | // This function does not (yet?) properly handle the rejection of | ||
306 | // strings that begin or end with SP or HTAB. | ||
307 | func ValidHeaderFieldValue(v string) bool { | ||
308 | for i := 0; i < len(v); i++ { | ||
309 | b := v[i] | ||
310 | if isCTL(b) && !isLWS(b) { | ||
311 | return false | ||
312 | } | ||
313 | } | ||
314 | return true | ||
315 | } | ||
316 | |||
317 | func isASCII(s string) bool { | ||
318 | for i := 0; i < len(s); i++ { | ||
319 | if s[i] >= utf8.RuneSelf { | ||
320 | return false | ||
321 | } | ||
322 | } | ||
323 | return true | ||
324 | } | ||
325 | |||
326 | // PunycodeHostPort returns the IDNA Punycode version | ||
327 | // of the provided "host" or "host:port" string. | ||
328 | func PunycodeHostPort(v string) (string, error) { | ||
329 | if isASCII(v) { | ||
330 | return v, nil | ||
331 | } | ||
332 | |||
333 | host, port, err := net.SplitHostPort(v) | ||
334 | if err != nil { | ||
335 | // The input 'v' argument was just a "host" argument, | ||
336 | // without a port. This error should not be returned | ||
337 | // to the caller. | ||
338 | host = v | ||
339 | port = "" | ||
340 | } | ||
341 | host, err = idna.ToASCII(host) | ||
342 | if err != nil { | ||
343 | // Non-UTF-8? Not representable in Punycode, in any | ||
344 | // case. | ||
345 | return "", err | ||
346 | } | ||
347 | if port == "" { | ||
348 | return host, nil | ||
349 | } | ||
350 | return net.JoinHostPort(host, port), nil | ||
351 | } | ||
diff --git a/vendor/golang.org/x/net/trace/events.go b/vendor/golang.org/x/net/trace/events.go new file mode 100644 index 0000000..c646a69 --- /dev/null +++ b/vendor/golang.org/x/net/trace/events.go | |||
@@ -0,0 +1,532 @@ | |||
1 | // Copyright 2015 The Go Authors. All rights reserved. | ||
2 | // Use of this source code is governed by a BSD-style | ||
3 | // license that can be found in the LICENSE file. | ||
4 | |||
5 | package trace | ||
6 | |||
7 | import ( | ||
8 | "bytes" | ||
9 | "fmt" | ||
10 | "html/template" | ||
11 | "io" | ||
12 | "log" | ||
13 | "net/http" | ||
14 | "runtime" | ||
15 | "sort" | ||
16 | "strconv" | ||
17 | "strings" | ||
18 | "sync" | ||
19 | "sync/atomic" | ||
20 | "text/tabwriter" | ||
21 | "time" | ||
22 | ) | ||
23 | |||
24 | const maxEventsPerLog = 100 | ||
25 | |||
26 | type bucket struct { | ||
27 | MaxErrAge time.Duration | ||
28 | String string | ||
29 | } | ||
30 | |||
31 | var buckets = []bucket{ | ||
32 | {0, "total"}, | ||
33 | {10 * time.Second, "errs<10s"}, | ||
34 | {1 * time.Minute, "errs<1m"}, | ||
35 | {10 * time.Minute, "errs<10m"}, | ||
36 | {1 * time.Hour, "errs<1h"}, | ||
37 | {10 * time.Hour, "errs<10h"}, | ||
38 | {24000 * time.Hour, "errors"}, | ||
39 | } | ||
40 | |||
41 | // RenderEvents renders the HTML page typically served at /debug/events. | ||
42 | // It does not do any auth checking. The request may be nil. | ||
43 | // | ||
44 | // Most users will use the Events handler. | ||
45 | func RenderEvents(w http.ResponseWriter, req *http.Request, sensitive bool) { | ||
46 | now := time.Now() | ||
47 | data := &struct { | ||
48 | Families []string // family names | ||
49 | Buckets []bucket | ||
50 | Counts [][]int // eventLog count per family/bucket | ||
51 | |||
52 | // Set when a bucket has been selected. | ||
53 | Family string | ||
54 | Bucket int | ||
55 | EventLogs eventLogs | ||
56 | Expanded bool | ||
57 | }{ | ||
58 | Buckets: buckets, | ||
59 | } | ||
60 | |||
61 | data.Families = make([]string, 0, len(families)) | ||
62 | famMu.RLock() | ||
63 | for name := range families { | ||
64 | data.Families = append(data.Families, name) | ||
65 | } | ||
66 | famMu.RUnlock() | ||
67 | sort.Strings(data.Families) | ||
68 | |||
69 | // Count the number of eventLogs in each family for each error age. | ||
70 | data.Counts = make([][]int, len(data.Families)) | ||
71 | for i, name := range data.Families { | ||
72 | // TODO(sameer): move this loop under the family lock. | ||
73 | f := getEventFamily(name) | ||
74 | data.Counts[i] = make([]int, len(data.Buckets)) | ||
75 | for j, b := range data.Buckets { | ||
76 | data.Counts[i][j] = f.Count(now, b.MaxErrAge) | ||
77 | } | ||
78 | } | ||
79 | |||
80 | if req != nil { | ||
81 | var ok bool | ||
82 | data.Family, data.Bucket, ok = parseEventsArgs(req) | ||
83 | if !ok { | ||
84 | // No-op | ||
85 | } else { | ||
86 | data.EventLogs = getEventFamily(data.Family).Copy(now, buckets[data.Bucket].MaxErrAge) | ||
87 | } | ||
88 | if data.EventLogs != nil { | ||
89 | defer data.EventLogs.Free() | ||
90 | sort.Sort(data.EventLogs) | ||
91 | } | ||
92 | if exp, err := strconv.ParseBool(req.FormValue("exp")); err == nil { | ||
93 | data.Expanded = exp | ||
94 | } | ||
95 | } | ||
96 | |||
97 | famMu.RLock() | ||
98 | defer famMu.RUnlock() | ||
99 | if err := eventsTmpl().Execute(w, data); err != nil { | ||
100 | log.Printf("net/trace: Failed executing template: %v", err) | ||
101 | } | ||
102 | } | ||
103 | |||
104 | func parseEventsArgs(req *http.Request) (fam string, b int, ok bool) { | ||
105 | fam, bStr := req.FormValue("fam"), req.FormValue("b") | ||
106 | if fam == "" || bStr == "" { | ||
107 | return "", 0, false | ||
108 | } | ||
109 | b, err := strconv.Atoi(bStr) | ||
110 | if err != nil || b < 0 || b >= len(buckets) { | ||
111 | return "", 0, false | ||
112 | } | ||
113 | return fam, b, true | ||
114 | } | ||
115 | |||
116 | // An EventLog provides a log of events associated with a specific object. | ||
117 | type EventLog interface { | ||
118 | // Printf formats its arguments with fmt.Sprintf and adds the | ||
119 | // result to the event log. | ||
120 | Printf(format string, a ...interface{}) | ||
121 | |||
122 | // Errorf is like Printf, but it marks this event as an error. | ||
123 | Errorf(format string, a ...interface{}) | ||
124 | |||
125 | // Finish declares that this event log is complete. | ||
126 | // The event log should not be used after calling this method. | ||
127 | Finish() | ||
128 | } | ||
129 | |||
130 | // NewEventLog returns a new EventLog with the specified family name | ||
131 | // and title. | ||
132 | func NewEventLog(family, title string) EventLog { | ||
133 | el := newEventLog() | ||
134 | el.ref() | ||
135 | el.Family, el.Title = family, title | ||
136 | el.Start = time.Now() | ||
137 | el.events = make([]logEntry, 0, maxEventsPerLog) | ||
138 | el.stack = make([]uintptr, 32) | ||
139 | n := runtime.Callers(2, el.stack) | ||
140 | el.stack = el.stack[:n] | ||
141 | |||
142 | getEventFamily(family).add(el) | ||
143 | return el | ||
144 | } | ||
145 | |||
146 | func (el *eventLog) Finish() { | ||
147 | getEventFamily(el.Family).remove(el) | ||
148 | el.unref() // matches ref in New | ||
149 | } | ||
150 | |||
151 | var ( | ||
152 | famMu sync.RWMutex | ||
153 | families = make(map[string]*eventFamily) // family name => family | ||
154 | ) | ||
155 | |||
156 | func getEventFamily(fam string) *eventFamily { | ||
157 | famMu.Lock() | ||
158 | defer famMu.Unlock() | ||
159 | f := families[fam] | ||
160 | if f == nil { | ||
161 | f = &eventFamily{} | ||
162 | families[fam] = f | ||
163 | } | ||
164 | return f | ||
165 | } | ||
166 | |||
167 | type eventFamily struct { | ||
168 | mu sync.RWMutex | ||
169 | eventLogs eventLogs | ||
170 | } | ||
171 | |||
172 | func (f *eventFamily) add(el *eventLog) { | ||
173 | f.mu.Lock() | ||
174 | f.eventLogs = append(f.eventLogs, el) | ||
175 | f.mu.Unlock() | ||
176 | } | ||
177 | |||
178 | func (f *eventFamily) remove(el *eventLog) { | ||
179 | f.mu.Lock() | ||
180 | defer f.mu.Unlock() | ||
181 | for i, el0 := range f.eventLogs { | ||
182 | if el == el0 { | ||
183 | copy(f.eventLogs[i:], f.eventLogs[i+1:]) | ||
184 | f.eventLogs = f.eventLogs[:len(f.eventLogs)-1] | ||
185 | return | ||
186 | } | ||
187 | } | ||
188 | } | ||
189 | |||
190 | func (f *eventFamily) Count(now time.Time, maxErrAge time.Duration) (n int) { | ||
191 | f.mu.RLock() | ||
192 | defer f.mu.RUnlock() | ||
193 | for _, el := range f.eventLogs { | ||
194 | if el.hasRecentError(now, maxErrAge) { | ||
195 | n++ | ||
196 | } | ||
197 | } | ||
198 | return | ||
199 | } | ||
200 | |||
201 | func (f *eventFamily) Copy(now time.Time, maxErrAge time.Duration) (els eventLogs) { | ||
202 | f.mu.RLock() | ||
203 | defer f.mu.RUnlock() | ||
204 | els = make(eventLogs, 0, len(f.eventLogs)) | ||
205 | for _, el := range f.eventLogs { | ||
206 | if el.hasRecentError(now, maxErrAge) { | ||
207 | el.ref() | ||
208 | els = append(els, el) | ||
209 | } | ||
210 | } | ||
211 | return | ||
212 | } | ||
213 | |||
214 | type eventLogs []*eventLog | ||
215 | |||
216 | // Free calls unref on each element of the list. | ||
217 | func (els eventLogs) Free() { | ||
218 | for _, el := range els { | ||
219 | el.unref() | ||
220 | } | ||
221 | } | ||
222 | |||
223 | // eventLogs may be sorted in reverse chronological order. | ||
224 | func (els eventLogs) Len() int { return len(els) } | ||
225 | func (els eventLogs) Less(i, j int) bool { return els[i].Start.After(els[j].Start) } | ||
226 | func (els eventLogs) Swap(i, j int) { els[i], els[j] = els[j], els[i] } | ||
227 | |||
228 | // A logEntry is a timestamped log entry in an event log. | ||
229 | type logEntry struct { | ||
230 | When time.Time | ||
231 | Elapsed time.Duration // since previous event in log | ||
232 | NewDay bool // whether this event is on a different day to the previous event | ||
233 | What string | ||
234 | IsErr bool | ||
235 | } | ||
236 | |||
237 | // WhenString returns a string representation of the elapsed time of the event. | ||
238 | // It will include the date if midnight was crossed. | ||
239 | func (e logEntry) WhenString() string { | ||
240 | if e.NewDay { | ||
241 | return e.When.Format("2006/01/02 15:04:05.000000") | ||
242 | } | ||
243 | return e.When.Format("15:04:05.000000") | ||
244 | } | ||
245 | |||
246 | // An eventLog represents an active event log. | ||
247 | type eventLog struct { | ||
248 | // Family is the top-level grouping of event logs to which this belongs. | ||
249 | Family string | ||
250 | |||
251 | // Title is the title of this event log. | ||
252 | Title string | ||
253 | |||
254 | // Timing information. | ||
255 | Start time.Time | ||
256 | |||
257 | // Call stack where this event log was created. | ||
258 | stack []uintptr | ||
259 | |||
260 | // Append-only sequence of events. | ||
261 | // | ||
262 | // TODO(sameer): change this to a ring buffer to avoid the array copy | ||
263 | // when we hit maxEventsPerLog. | ||
264 | mu sync.RWMutex | ||
265 | events []logEntry | ||
266 | LastErrorTime time.Time | ||
267 | discarded int | ||
268 | |||
269 | refs int32 // how many buckets this is in | ||
270 | } | ||
271 | |||
272 | func (el *eventLog) reset() { | ||
273 | // Clear all but the mutex. Mutexes may not be copied, even when unlocked. | ||
274 | el.Family = "" | ||
275 | el.Title = "" | ||
276 | el.Start = time.Time{} | ||
277 | el.stack = nil | ||
278 | el.events = nil | ||
279 | el.LastErrorTime = time.Time{} | ||
280 | el.discarded = 0 | ||
281 | el.refs = 0 | ||
282 | } | ||
283 | |||
284 | func (el *eventLog) hasRecentError(now time.Time, maxErrAge time.Duration) bool { | ||
285 | if maxErrAge == 0 { | ||
286 | return true | ||
287 | } | ||
288 | el.mu.RLock() | ||
289 | defer el.mu.RUnlock() | ||
290 | return now.Sub(el.LastErrorTime) < maxErrAge | ||
291 | } | ||
292 | |||
293 | // delta returns the elapsed time since the last event or the log start, | ||
294 | // and whether it spans midnight. | ||
295 | // L >= el.mu | ||
296 | func (el *eventLog) delta(t time.Time) (time.Duration, bool) { | ||
297 | if len(el.events) == 0 { | ||
298 | return t.Sub(el.Start), false | ||
299 | } | ||
300 | prev := el.events[len(el.events)-1].When | ||
301 | return t.Sub(prev), prev.Day() != t.Day() | ||
302 | |||
303 | } | ||
304 | |||
305 | func (el *eventLog) Printf(format string, a ...interface{}) { | ||
306 | el.printf(false, format, a...) | ||
307 | } | ||
308 | |||
309 | func (el *eventLog) Errorf(format string, a ...interface{}) { | ||
310 | el.printf(true, format, a...) | ||
311 | } | ||
312 | |||
313 | func (el *eventLog) printf(isErr bool, format string, a ...interface{}) { | ||
314 | e := logEntry{When: time.Now(), IsErr: isErr, What: fmt.Sprintf(format, a...)} | ||
315 | el.mu.Lock() | ||
316 | e.Elapsed, e.NewDay = el.delta(e.When) | ||
317 | if len(el.events) < maxEventsPerLog { | ||
318 | el.events = append(el.events, e) | ||
319 | } else { | ||
320 | // Discard the oldest event. | ||
321 | if el.discarded == 0 { | ||
322 | // el.discarded starts at two to count for the event it | ||
323 | // is replacing, plus the next one that we are about to | ||
324 | // drop. | ||
325 | el.discarded = 2 | ||
326 | } else { | ||
327 | el.discarded++ | ||
328 | } | ||
329 | // TODO(sameer): if this causes allocations on a critical path, | ||
330 | // change eventLog.What to be a fmt.Stringer, as in trace.go. | ||
331 | el.events[0].What = fmt.Sprintf("(%d events discarded)", el.discarded) | ||
332 | // The timestamp of the discarded meta-event should be | ||
333 | // the time of the last event it is representing. | ||
334 | el.events[0].When = el.events[1].When | ||
335 | copy(el.events[1:], el.events[2:]) | ||
336 | el.events[maxEventsPerLog-1] = e | ||
337 | } | ||
338 | if e.IsErr { | ||
339 | el.LastErrorTime = e.When | ||
340 | } | ||
341 | el.mu.Unlock() | ||
342 | } | ||
343 | |||
344 | func (el *eventLog) ref() { | ||
345 | atomic.AddInt32(&el.refs, 1) | ||
346 | } | ||
347 | |||
348 | func (el *eventLog) unref() { | ||
349 | if atomic.AddInt32(&el.refs, -1) == 0 { | ||
350 | freeEventLog(el) | ||
351 | } | ||
352 | } | ||
353 | |||
354 | func (el *eventLog) When() string { | ||
355 | return el.Start.Format("2006/01/02 15:04:05.000000") | ||
356 | } | ||
357 | |||
358 | func (el *eventLog) ElapsedTime() string { | ||
359 | elapsed := time.Since(el.Start) | ||
360 | return fmt.Sprintf("%.6f", elapsed.Seconds()) | ||
361 | } | ||
362 | |||
363 | func (el *eventLog) Stack() string { | ||
364 | buf := new(bytes.Buffer) | ||
365 | tw := tabwriter.NewWriter(buf, 1, 8, 1, '\t', 0) | ||
366 | printStackRecord(tw, el.stack) | ||
367 | tw.Flush() | ||
368 | return buf.String() | ||
369 | } | ||
370 | |||
371 | // printStackRecord prints the function + source line information | ||
372 | // for a single stack trace. | ||
373 | // Adapted from runtime/pprof/pprof.go. | ||
374 | func printStackRecord(w io.Writer, stk []uintptr) { | ||
375 | for _, pc := range stk { | ||
376 | f := runtime.FuncForPC(pc) | ||
377 | if f == nil { | ||
378 | continue | ||
379 | } | ||
380 | file, line := f.FileLine(pc) | ||
381 | name := f.Name() | ||
382 | // Hide runtime.goexit and any runtime functions at the beginning. | ||
383 | if strings.HasPrefix(name, "runtime.") { | ||
384 | continue | ||
385 | } | ||
386 | fmt.Fprintf(w, "# %s\t%s:%d\n", name, file, line) | ||
387 | } | ||
388 | } | ||
389 | |||
390 | func (el *eventLog) Events() []logEntry { | ||
391 | el.mu.RLock() | ||
392 | defer el.mu.RUnlock() | ||
393 | return el.events | ||
394 | } | ||
395 | |||
396 | // freeEventLogs is a freelist of *eventLog | ||
397 | var freeEventLogs = make(chan *eventLog, 1000) | ||
398 | |||
399 | // newEventLog returns a event log ready to use. | ||
400 | func newEventLog() *eventLog { | ||
401 | select { | ||
402 | case el := <-freeEventLogs: | ||
403 | return el | ||
404 | default: | ||
405 | return new(eventLog) | ||
406 | } | ||
407 | } | ||
408 | |||
409 | // freeEventLog adds el to freeEventLogs if there's room. | ||
410 | // This is non-blocking. | ||
411 | func freeEventLog(el *eventLog) { | ||
412 | el.reset() | ||
413 | select { | ||
414 | case freeEventLogs <- el: | ||
415 | default: | ||
416 | } | ||
417 | } | ||
418 | |||
419 | var eventsTmplCache *template.Template | ||
420 | var eventsTmplOnce sync.Once | ||
421 | |||
422 | func eventsTmpl() *template.Template { | ||
423 | eventsTmplOnce.Do(func() { | ||
424 | eventsTmplCache = template.Must(template.New("events").Funcs(template.FuncMap{ | ||
425 | "elapsed": elapsed, | ||
426 | "trimSpace": strings.TrimSpace, | ||
427 | }).Parse(eventsHTML)) | ||
428 | }) | ||
429 | return eventsTmplCache | ||
430 | } | ||
431 | |||
432 | const eventsHTML = ` | ||
433 | <html> | ||
434 | <head> | ||
435 | <title>events</title> | ||
436 | </head> | ||
437 | <style type="text/css"> | ||
438 | body { | ||
439 | font-family: sans-serif; | ||
440 | } | ||
441 | table#req-status td.family { | ||
442 | padding-right: 2em; | ||
443 | } | ||
444 | table#req-status td.active { | ||
445 | padding-right: 1em; | ||
446 | } | ||
447 | table#req-status td.empty { | ||
448 | color: #aaa; | ||
449 | } | ||
450 | table#reqs { | ||
451 | margin-top: 1em; | ||
452 | } | ||
453 | table#reqs tr.first { | ||
454 | {{if $.Expanded}}font-weight: bold;{{end}} | ||
455 | } | ||
456 | table#reqs td { | ||
457 | font-family: monospace; | ||
458 | } | ||
459 | table#reqs td.when { | ||
460 | text-align: right; | ||
461 | white-space: nowrap; | ||
462 | } | ||
463 | table#reqs td.elapsed { | ||
464 | padding: 0 0.5em; | ||
465 | text-align: right; | ||
466 | white-space: pre; | ||
467 | width: 10em; | ||
468 | } | ||
469 | address { | ||
470 | font-size: smaller; | ||
471 | margin-top: 5em; | ||
472 | } | ||
473 | </style> | ||
474 | <body> | ||
475 | |||
476 | <h1>/debug/events</h1> | ||
477 | |||
478 | <table id="req-status"> | ||
479 | {{range $i, $fam := .Families}} | ||
480 | <tr> | ||
481 | <td class="family">{{$fam}}</td> | ||
482 | |||
483 | {{range $j, $bucket := $.Buckets}} | ||
484 | {{$n := index $.Counts $i $j}} | ||
485 | <td class="{{if not $bucket.MaxErrAge}}active{{end}}{{if not $n}}empty{{end}}"> | ||
486 | {{if $n}}<a href="?fam={{$fam}}&b={{$j}}{{if $.Expanded}}&exp=1{{end}}">{{end}} | ||
487 | [{{$n}} {{$bucket.String}}] | ||
488 | {{if $n}}</a>{{end}} | ||
489 | </td> | ||
490 | {{end}} | ||
491 | |||
492 | </tr>{{end}} | ||
493 | </table> | ||
494 | |||
495 | {{if $.EventLogs}} | ||
496 | <hr /> | ||
497 | <h3>Family: {{$.Family}}</h3> | ||
498 | |||
499 | {{if $.Expanded}}<a href="?fam={{$.Family}}&b={{$.Bucket}}">{{end}} | ||
500 | [Summary]{{if $.Expanded}}</a>{{end}} | ||
501 | |||
502 | {{if not $.Expanded}}<a href="?fam={{$.Family}}&b={{$.Bucket}}&exp=1">{{end}} | ||
503 | [Expanded]{{if not $.Expanded}}</a>{{end}} | ||
504 | |||
505 | <table id="reqs"> | ||
506 | <tr><th>When</th><th>Elapsed</th></tr> | ||
507 | {{range $el := $.EventLogs}} | ||
508 | <tr class="first"> | ||
509 | <td class="when">{{$el.When}}</td> | ||
510 | <td class="elapsed">{{$el.ElapsedTime}}</td> | ||
511 | <td>{{$el.Title}} | ||
512 | </tr> | ||
513 | {{if $.Expanded}} | ||
514 | <tr> | ||
515 | <td class="when"></td> | ||
516 | <td class="elapsed"></td> | ||
517 | <td><pre>{{$el.Stack|trimSpace}}</pre></td> | ||
518 | </tr> | ||
519 | {{range $el.Events}} | ||
520 | <tr> | ||
521 | <td class="when">{{.WhenString}}</td> | ||
522 | <td class="elapsed">{{elapsed .Elapsed}}</td> | ||
523 | <td>.{{if .IsErr}}E{{else}}.{{end}}. {{.What}}</td> | ||
524 | </tr> | ||
525 | {{end}} | ||
526 | {{end}} | ||
527 | {{end}} | ||
528 | </table> | ||
529 | {{end}} | ||
530 | </body> | ||
531 | </html> | ||
532 | ` | ||
diff --git a/vendor/golang.org/x/net/trace/histogram.go b/vendor/golang.org/x/net/trace/histogram.go new file mode 100644 index 0000000..9bf4286 --- /dev/null +++ b/vendor/golang.org/x/net/trace/histogram.go | |||
@@ -0,0 +1,365 @@ | |||
1 | // Copyright 2015 The Go Authors. All rights reserved. | ||
2 | // Use of this source code is governed by a BSD-style | ||
3 | // license that can be found in the LICENSE file. | ||
4 | |||
5 | package trace | ||
6 | |||
7 | // This file implements histogramming for RPC statistics collection. | ||
8 | |||
9 | import ( | ||
10 | "bytes" | ||
11 | "fmt" | ||
12 | "html/template" | ||
13 | "log" | ||
14 | "math" | ||
15 | "sync" | ||
16 | |||
17 | "golang.org/x/net/internal/timeseries" | ||
18 | ) | ||
19 | |||
20 | const ( | ||
21 | bucketCount = 38 | ||
22 | ) | ||
23 | |||
24 | // histogram keeps counts of values in buckets that are spaced | ||
25 | // out in powers of 2: 0-1, 2-3, 4-7... | ||
26 | // histogram implements timeseries.Observable | ||
27 | type histogram struct { | ||
28 | sum int64 // running total of measurements | ||
29 | sumOfSquares float64 // square of running total | ||
30 | buckets []int64 // bucketed values for histogram | ||
31 | value int // holds a single value as an optimization | ||
32 | valueCount int64 // number of values recorded for single value | ||
33 | } | ||
34 | |||
35 | // AddMeasurement records a value measurement observation to the histogram. | ||
36 | func (h *histogram) addMeasurement(value int64) { | ||
37 | // TODO: assert invariant | ||
38 | h.sum += value | ||
39 | h.sumOfSquares += float64(value) * float64(value) | ||
40 | |||
41 | bucketIndex := getBucket(value) | ||
42 | |||
43 | if h.valueCount == 0 || (h.valueCount > 0 && h.value == bucketIndex) { | ||
44 | h.value = bucketIndex | ||
45 | h.valueCount++ | ||
46 | } else { | ||
47 | h.allocateBuckets() | ||
48 | h.buckets[bucketIndex]++ | ||
49 | } | ||
50 | } | ||
51 | |||
52 | func (h *histogram) allocateBuckets() { | ||
53 | if h.buckets == nil { | ||
54 | h.buckets = make([]int64, bucketCount) | ||
55 | h.buckets[h.value] = h.valueCount | ||
56 | h.value = 0 | ||
57 | h.valueCount = -1 | ||
58 | } | ||
59 | } | ||
60 | |||
61 | func log2(i int64) int { | ||
62 | n := 0 | ||
63 | for ; i >= 0x100; i >>= 8 { | ||
64 | n += 8 | ||
65 | } | ||
66 | for ; i > 0; i >>= 1 { | ||
67 | n += 1 | ||
68 | } | ||
69 | return n | ||
70 | } | ||
71 | |||
72 | func getBucket(i int64) (index int) { | ||
73 | index = log2(i) - 1 | ||
74 | if index < 0 { | ||
75 | index = 0 | ||
76 | } | ||
77 | if index >= bucketCount { | ||
78 | index = bucketCount - 1 | ||
79 | } | ||
80 | return | ||
81 | } | ||
82 | |||
83 | // Total returns the number of recorded observations. | ||
84 | func (h *histogram) total() (total int64) { | ||
85 | if h.valueCount >= 0 { | ||
86 | total = h.valueCount | ||
87 | } | ||
88 | for _, val := range h.buckets { | ||
89 | total += int64(val) | ||
90 | } | ||
91 | return | ||
92 | } | ||
93 | |||
94 | // Average returns the average value of recorded observations. | ||
95 | func (h *histogram) average() float64 { | ||
96 | t := h.total() | ||
97 | if t == 0 { | ||
98 | return 0 | ||
99 | } | ||
100 | return float64(h.sum) / float64(t) | ||
101 | } | ||
102 | |||
103 | // Variance returns the variance of recorded observations. | ||
104 | func (h *histogram) variance() float64 { | ||
105 | t := float64(h.total()) | ||
106 | if t == 0 { | ||
107 | return 0 | ||
108 | } | ||
109 | s := float64(h.sum) / t | ||
110 | return h.sumOfSquares/t - s*s | ||
111 | } | ||
112 | |||
113 | // StandardDeviation returns the standard deviation of recorded observations. | ||
114 | func (h *histogram) standardDeviation() float64 { | ||
115 | return math.Sqrt(h.variance()) | ||
116 | } | ||
117 | |||
118 | // PercentileBoundary estimates the value that the given fraction of recorded | ||
119 | // observations are less than. | ||
120 | func (h *histogram) percentileBoundary(percentile float64) int64 { | ||
121 | total := h.total() | ||
122 | |||
123 | // Corner cases (make sure result is strictly less than Total()) | ||
124 | if total == 0 { | ||
125 | return 0 | ||
126 | } else if total == 1 { | ||
127 | return int64(h.average()) | ||
128 | } | ||
129 | |||
130 | percentOfTotal := round(float64(total) * percentile) | ||
131 | var runningTotal int64 | ||
132 | |||
133 | for i := range h.buckets { | ||
134 | value := h.buckets[i] | ||
135 | runningTotal += value | ||
136 | if runningTotal == percentOfTotal { | ||
137 | // We hit an exact bucket boundary. If the next bucket has data, it is a | ||
138 | // good estimate of the value. If the bucket is empty, we interpolate the | ||
139 | // midpoint between the next bucket's boundary and the next non-zero | ||
140 | // bucket. If the remaining buckets are all empty, then we use the | ||
141 | // boundary for the next bucket as the estimate. | ||
142 | j := uint8(i + 1) | ||
143 | min := bucketBoundary(j) | ||
144 | if runningTotal < total { | ||
145 | for h.buckets[j] == 0 { | ||
146 | j++ | ||
147 | } | ||
148 | } | ||
149 | max := bucketBoundary(j) | ||
150 | return min + round(float64(max-min)/2) | ||
151 | } else if runningTotal > percentOfTotal { | ||
152 | // The value is in this bucket. Interpolate the value. | ||
153 | delta := runningTotal - percentOfTotal | ||
154 | percentBucket := float64(value-delta) / float64(value) | ||
155 | bucketMin := bucketBoundary(uint8(i)) | ||
156 | nextBucketMin := bucketBoundary(uint8(i + 1)) | ||
157 | bucketSize := nextBucketMin - bucketMin | ||
158 | return bucketMin + round(percentBucket*float64(bucketSize)) | ||
159 | } | ||
160 | } | ||
161 | return bucketBoundary(bucketCount - 1) | ||
162 | } | ||
163 | |||
164 | // Median returns the estimated median of the observed values. | ||
165 | func (h *histogram) median() int64 { | ||
166 | return h.percentileBoundary(0.5) | ||
167 | } | ||
168 | |||
169 | // Add adds other to h. | ||
170 | func (h *histogram) Add(other timeseries.Observable) { | ||
171 | o := other.(*histogram) | ||
172 | if o.valueCount == 0 { | ||
173 | // Other histogram is empty | ||
174 | } else if h.valueCount >= 0 && o.valueCount > 0 && h.value == o.value { | ||
175 | // Both have a single bucketed value, aggregate them | ||
176 | h.valueCount += o.valueCount | ||
177 | } else { | ||
178 | // Two different values necessitate buckets in this histogram | ||
179 | h.allocateBuckets() | ||
180 | if o.valueCount >= 0 { | ||
181 | h.buckets[o.value] += o.valueCount | ||
182 | } else { | ||
183 | for i := range h.buckets { | ||
184 | h.buckets[i] += o.buckets[i] | ||
185 | } | ||
186 | } | ||
187 | } | ||
188 | h.sumOfSquares += o.sumOfSquares | ||
189 | h.sum += o.sum | ||
190 | } | ||
191 | |||
192 | // Clear resets the histogram to an empty state, removing all observed values. | ||
193 | func (h *histogram) Clear() { | ||
194 | h.buckets = nil | ||
195 | h.value = 0 | ||
196 | h.valueCount = 0 | ||
197 | h.sum = 0 | ||
198 | h.sumOfSquares = 0 | ||
199 | } | ||
200 | |||
201 | // CopyFrom copies from other, which must be a *histogram, into h. | ||
202 | func (h *histogram) CopyFrom(other timeseries.Observable) { | ||
203 | o := other.(*histogram) | ||
204 | if o.valueCount == -1 { | ||
205 | h.allocateBuckets() | ||
206 | copy(h.buckets, o.buckets) | ||
207 | } | ||
208 | h.sum = o.sum | ||
209 | h.sumOfSquares = o.sumOfSquares | ||
210 | h.value = o.value | ||
211 | h.valueCount = o.valueCount | ||
212 | } | ||
213 | |||
214 | // Multiply scales the histogram by the specified ratio. | ||
215 | func (h *histogram) Multiply(ratio float64) { | ||
216 | if h.valueCount == -1 { | ||
217 | for i := range h.buckets { | ||
218 | h.buckets[i] = int64(float64(h.buckets[i]) * ratio) | ||
219 | } | ||
220 | } else { | ||
221 | h.valueCount = int64(float64(h.valueCount) * ratio) | ||
222 | } | ||
223 | h.sum = int64(float64(h.sum) * ratio) | ||
224 | h.sumOfSquares = h.sumOfSquares * ratio | ||
225 | } | ||
226 | |||
227 | // New creates a new histogram. | ||
228 | func (h *histogram) New() timeseries.Observable { | ||
229 | r := new(histogram) | ||
230 | r.Clear() | ||
231 | return r | ||
232 | } | ||
233 | |||
234 | func (h *histogram) String() string { | ||
235 | return fmt.Sprintf("%d, %f, %d, %d, %v", | ||
236 | h.sum, h.sumOfSquares, h.value, h.valueCount, h.buckets) | ||
237 | } | ||
238 | |||
239 | // round returns the closest int64 to the argument | ||
240 | func round(in float64) int64 { | ||
241 | return int64(math.Floor(in + 0.5)) | ||
242 | } | ||
243 | |||
244 | // bucketBoundary returns the first value in the bucket. | ||
245 | func bucketBoundary(bucket uint8) int64 { | ||
246 | if bucket == 0 { | ||
247 | return 0 | ||
248 | } | ||
249 | return 1 << bucket | ||
250 | } | ||
251 | |||
252 | // bucketData holds data about a specific bucket for use in distTmpl. | ||
253 | type bucketData struct { | ||
254 | Lower, Upper int64 | ||
255 | N int64 | ||
256 | Pct, CumulativePct float64 | ||
257 | GraphWidth int | ||
258 | } | ||
259 | |||
260 | // data holds data about a Distribution for use in distTmpl. | ||
261 | type data struct { | ||
262 | Buckets []*bucketData | ||
263 | Count, Median int64 | ||
264 | Mean, StandardDeviation float64 | ||
265 | } | ||
266 | |||
267 | // maxHTMLBarWidth is the maximum width of the HTML bar for visualizing buckets. | ||
268 | const maxHTMLBarWidth = 350.0 | ||
269 | |||
270 | // newData returns data representing h for use in distTmpl. | ||
271 | func (h *histogram) newData() *data { | ||
272 | // Force the allocation of buckets to simplify the rendering implementation | ||
273 | h.allocateBuckets() | ||
274 | // We scale the bars on the right so that the largest bar is | ||
275 | // maxHTMLBarWidth pixels in width. | ||
276 | maxBucket := int64(0) | ||
277 | for _, n := range h.buckets { | ||
278 | if n > maxBucket { | ||
279 | maxBucket = n | ||
280 | } | ||
281 | } | ||
282 | total := h.total() | ||
283 | barsizeMult := maxHTMLBarWidth / float64(maxBucket) | ||
284 | var pctMult float64 | ||
285 | if total == 0 { | ||
286 | pctMult = 1.0 | ||
287 | } else { | ||
288 | pctMult = 100.0 / float64(total) | ||
289 | } | ||
290 | |||
291 | buckets := make([]*bucketData, len(h.buckets)) | ||
292 | runningTotal := int64(0) | ||
293 | for i, n := range h.buckets { | ||
294 | if n == 0 { | ||
295 | continue | ||
296 | } | ||
297 | runningTotal += n | ||
298 | var upperBound int64 | ||
299 | if i < bucketCount-1 { | ||
300 | upperBound = bucketBoundary(uint8(i + 1)) | ||
301 | } else { | ||
302 | upperBound = math.MaxInt64 | ||
303 | } | ||
304 | buckets[i] = &bucketData{ | ||
305 | Lower: bucketBoundary(uint8(i)), | ||
306 | Upper: upperBound, | ||
307 | N: n, | ||
308 | Pct: float64(n) * pctMult, | ||
309 | CumulativePct: float64(runningTotal) * pctMult, | ||
310 | GraphWidth: int(float64(n) * barsizeMult), | ||
311 | } | ||
312 | } | ||
313 | return &data{ | ||
314 | Buckets: buckets, | ||
315 | Count: total, | ||
316 | Median: h.median(), | ||
317 | Mean: h.average(), | ||
318 | StandardDeviation: h.standardDeviation(), | ||
319 | } | ||
320 | } | ||
321 | |||
322 | func (h *histogram) html() template.HTML { | ||
323 | buf := new(bytes.Buffer) | ||
324 | if err := distTmpl().Execute(buf, h.newData()); err != nil { | ||
325 | buf.Reset() | ||
326 | log.Printf("net/trace: couldn't execute template: %v", err) | ||
327 | } | ||
328 | return template.HTML(buf.String()) | ||
329 | } | ||
330 | |||
331 | var distTmplCache *template.Template | ||
332 | var distTmplOnce sync.Once | ||
333 | |||
334 | func distTmpl() *template.Template { | ||
335 | distTmplOnce.Do(func() { | ||
336 | // Input: data | ||
337 | distTmplCache = template.Must(template.New("distTmpl").Parse(` | ||
338 | <table> | ||
339 | <tr> | ||
340 | <td style="padding:0.25em">Count: {{.Count}}</td> | ||
341 | <td style="padding:0.25em">Mean: {{printf "%.0f" .Mean}}</td> | ||
342 | <td style="padding:0.25em">StdDev: {{printf "%.0f" .StandardDeviation}}</td> | ||
343 | <td style="padding:0.25em">Median: {{.Median}}</td> | ||
344 | </tr> | ||
345 | </table> | ||
346 | <hr> | ||
347 | <table> | ||
348 | {{range $b := .Buckets}} | ||
349 | {{if $b}} | ||
350 | <tr> | ||
351 | <td style="padding:0 0 0 0.25em">[</td> | ||
352 | <td style="text-align:right;padding:0 0.25em">{{.Lower}},</td> | ||
353 | <td style="text-align:right;padding:0 0.25em">{{.Upper}})</td> | ||
354 | <td style="text-align:right;padding:0 0.25em">{{.N}}</td> | ||
355 | <td style="text-align:right;padding:0 0.25em">{{printf "%#.3f" .Pct}}%</td> | ||
356 | <td style="text-align:right;padding:0 0.25em">{{printf "%#.3f" .CumulativePct}}%</td> | ||
357 | <td><div style="background-color: blue; height: 1em; width: {{.GraphWidth}};"></div></td> | ||
358 | </tr> | ||
359 | {{end}} | ||
360 | {{end}} | ||
361 | </table> | ||
362 | `)) | ||
363 | }) | ||
364 | return distTmplCache | ||
365 | } | ||
diff --git a/vendor/golang.org/x/net/trace/trace.go b/vendor/golang.org/x/net/trace/trace.go new file mode 100644 index 0000000..bb72a52 --- /dev/null +++ b/vendor/golang.org/x/net/trace/trace.go | |||
@@ -0,0 +1,1082 @@ | |||
1 | // Copyright 2015 The Go Authors. All rights reserved. | ||
2 | // Use of this source code is governed by a BSD-style | ||
3 | // license that can be found in the LICENSE file. | ||
4 | |||
5 | /* | ||
6 | Package trace implements tracing of requests and long-lived objects. | ||
7 | It exports HTTP interfaces on /debug/requests and /debug/events. | ||
8 | |||
9 | A trace.Trace provides tracing for short-lived objects, usually requests. | ||
10 | A request handler might be implemented like this: | ||
11 | |||
12 | func fooHandler(w http.ResponseWriter, req *http.Request) { | ||
13 | tr := trace.New("mypkg.Foo", req.URL.Path) | ||
14 | defer tr.Finish() | ||
15 | ... | ||
16 | tr.LazyPrintf("some event %q happened", str) | ||
17 | ... | ||
18 | if err := somethingImportant(); err != nil { | ||
19 | tr.LazyPrintf("somethingImportant failed: %v", err) | ||
20 | tr.SetError() | ||
21 | } | ||
22 | } | ||
23 | |||
24 | The /debug/requests HTTP endpoint organizes the traces by family, | ||
25 | errors, and duration. It also provides histogram of request duration | ||
26 | for each family. | ||
27 | |||
28 | A trace.EventLog provides tracing for long-lived objects, such as RPC | ||
29 | connections. | ||
30 | |||
31 | // A Fetcher fetches URL paths for a single domain. | ||
32 | type Fetcher struct { | ||
33 | domain string | ||
34 | events trace.EventLog | ||
35 | } | ||
36 | |||
37 | func NewFetcher(domain string) *Fetcher { | ||
38 | return &Fetcher{ | ||
39 | domain, | ||
40 | trace.NewEventLog("mypkg.Fetcher", domain), | ||
41 | } | ||
42 | } | ||
43 | |||
44 | func (f *Fetcher) Fetch(path string) (string, error) { | ||
45 | resp, err := http.Get("http://" + f.domain + "/" + path) | ||
46 | if err != nil { | ||
47 | f.events.Errorf("Get(%q) = %v", path, err) | ||
48 | return "", err | ||
49 | } | ||
50 | f.events.Printf("Get(%q) = %s", path, resp.Status) | ||
51 | ... | ||
52 | } | ||
53 | |||
54 | func (f *Fetcher) Close() error { | ||
55 | f.events.Finish() | ||
56 | return nil | ||
57 | } | ||
58 | |||
59 | The /debug/events HTTP endpoint organizes the event logs by family and | ||
60 | by time since the last error. The expanded view displays recent log | ||
61 | entries and the log's call stack. | ||
62 | */ | ||
63 | package trace // import "golang.org/x/net/trace" | ||
64 | |||
65 | import ( | ||
66 | "bytes" | ||
67 | "fmt" | ||
68 | "html/template" | ||
69 | "io" | ||
70 | "log" | ||
71 | "net" | ||
72 | "net/http" | ||
73 | "runtime" | ||
74 | "sort" | ||
75 | "strconv" | ||
76 | "sync" | ||
77 | "sync/atomic" | ||
78 | "time" | ||
79 | |||
80 | "golang.org/x/net/internal/timeseries" | ||
81 | ) | ||
82 | |||
83 | // DebugUseAfterFinish controls whether to debug uses of Trace values after finishing. | ||
84 | // FOR DEBUGGING ONLY. This will slow down the program. | ||
85 | var DebugUseAfterFinish = false | ||
86 | |||
87 | // AuthRequest determines whether a specific request is permitted to load the | ||
88 | // /debug/requests or /debug/events pages. | ||
89 | // | ||
90 | // It returns two bools; the first indicates whether the page may be viewed at all, | ||
91 | // and the second indicates whether sensitive events will be shown. | ||
92 | // | ||
93 | // AuthRequest may be replaced by a program to customize its authorization requirements. | ||
94 | // | ||
95 | // The default AuthRequest function returns (true, true) if and only if the request | ||
96 | // comes from localhost/127.0.0.1/[::1]. | ||
97 | var AuthRequest = func(req *http.Request) (any, sensitive bool) { | ||
98 | // RemoteAddr is commonly in the form "IP" or "IP:port". | ||
99 | // If it is in the form "IP:port", split off the port. | ||
100 | host, _, err := net.SplitHostPort(req.RemoteAddr) | ||
101 | if err != nil { | ||
102 | host = req.RemoteAddr | ||
103 | } | ||
104 | switch host { | ||
105 | case "localhost", "127.0.0.1", "::1": | ||
106 | return true, true | ||
107 | default: | ||
108 | return false, false | ||
109 | } | ||
110 | } | ||
111 | |||
112 | func init() { | ||
113 | // TODO(jbd): Serve Traces from /debug/traces in the future? | ||
114 | // There is no requirement for a request to be present to have traces. | ||
115 | http.HandleFunc("/debug/requests", Traces) | ||
116 | http.HandleFunc("/debug/events", Events) | ||
117 | } | ||
118 | |||
119 | // Traces responds with traces from the program. | ||
120 | // The package initialization registers it in http.DefaultServeMux | ||
121 | // at /debug/requests. | ||
122 | // | ||
123 | // It performs authorization by running AuthRequest. | ||
124 | func Traces(w http.ResponseWriter, req *http.Request) { | ||
125 | any, sensitive := AuthRequest(req) | ||
126 | if !any { | ||
127 | http.Error(w, "not allowed", http.StatusUnauthorized) | ||
128 | return | ||
129 | } | ||
130 | w.Header().Set("Content-Type", "text/html; charset=utf-8") | ||
131 | Render(w, req, sensitive) | ||
132 | } | ||
133 | |||
134 | // Events responds with a page of events collected by EventLogs. | ||
135 | // The package initialization registers it in http.DefaultServeMux | ||
136 | // at /debug/events. | ||
137 | // | ||
138 | // It performs authorization by running AuthRequest. | ||
139 | func Events(w http.ResponseWriter, req *http.Request) { | ||
140 | any, sensitive := AuthRequest(req) | ||
141 | if !any { | ||
142 | http.Error(w, "not allowed", http.StatusUnauthorized) | ||
143 | return | ||
144 | } | ||
145 | w.Header().Set("Content-Type", "text/html; charset=utf-8") | ||
146 | RenderEvents(w, req, sensitive) | ||
147 | } | ||
148 | |||
149 | // Render renders the HTML page typically served at /debug/requests. | ||
150 | // It does not do any auth checking. The request may be nil. | ||
151 | // | ||
152 | // Most users will use the Traces handler. | ||
153 | func Render(w io.Writer, req *http.Request, sensitive bool) { | ||
154 | data := &struct { | ||
155 | Families []string | ||
156 | ActiveTraceCount map[string]int | ||
157 | CompletedTraces map[string]*family | ||
158 | |||
159 | // Set when a bucket has been selected. | ||
160 | Traces traceList | ||
161 | Family string | ||
162 | Bucket int | ||
163 | Expanded bool | ||
164 | Traced bool | ||
165 | Active bool | ||
166 | ShowSensitive bool // whether to show sensitive events | ||
167 | |||
168 | Histogram template.HTML | ||
169 | HistogramWindow string // e.g. "last minute", "last hour", "all time" | ||
170 | |||
171 | // If non-zero, the set of traces is a partial set, | ||
172 | // and this is the total number. | ||
173 | Total int | ||
174 | }{ | ||
175 | CompletedTraces: completedTraces, | ||
176 | } | ||
177 | |||
178 | data.ShowSensitive = sensitive | ||
179 | if req != nil { | ||
180 | // Allow show_sensitive=0 to force hiding of sensitive data for testing. | ||
181 | // This only goes one way; you can't use show_sensitive=1 to see things. | ||
182 | if req.FormValue("show_sensitive") == "0" { | ||
183 | data.ShowSensitive = false | ||
184 | } | ||
185 | |||
186 | if exp, err := strconv.ParseBool(req.FormValue("exp")); err == nil { | ||
187 | data.Expanded = exp | ||
188 | } | ||
189 | if exp, err := strconv.ParseBool(req.FormValue("rtraced")); err == nil { | ||
190 | data.Traced = exp | ||
191 | } | ||
192 | } | ||
193 | |||
194 | completedMu.RLock() | ||
195 | data.Families = make([]string, 0, len(completedTraces)) | ||
196 | for fam := range completedTraces { | ||
197 | data.Families = append(data.Families, fam) | ||
198 | } | ||
199 | completedMu.RUnlock() | ||
200 | sort.Strings(data.Families) | ||
201 | |||
202 | // We are careful here to minimize the time spent locking activeMu, | ||
203 | // since that lock is required every time an RPC starts and finishes. | ||
204 | data.ActiveTraceCount = make(map[string]int, len(data.Families)) | ||
205 | activeMu.RLock() | ||
206 | for fam, s := range activeTraces { | ||
207 | data.ActiveTraceCount[fam] = s.Len() | ||
208 | } | ||
209 | activeMu.RUnlock() | ||
210 | |||
211 | var ok bool | ||
212 | data.Family, data.Bucket, ok = parseArgs(req) | ||
213 | switch { | ||
214 | case !ok: | ||
215 | // No-op | ||
216 | case data.Bucket == -1: | ||
217 | data.Active = true | ||
218 | n := data.ActiveTraceCount[data.Family] | ||
219 | data.Traces = getActiveTraces(data.Family) | ||
220 | if len(data.Traces) < n { | ||
221 | data.Total = n | ||
222 | } | ||
223 | case data.Bucket < bucketsPerFamily: | ||
224 | if b := lookupBucket(data.Family, data.Bucket); b != nil { | ||
225 | data.Traces = b.Copy(data.Traced) | ||
226 | } | ||
227 | default: | ||
228 | if f := getFamily(data.Family, false); f != nil { | ||
229 | var obs timeseries.Observable | ||
230 | f.LatencyMu.RLock() | ||
231 | switch o := data.Bucket - bucketsPerFamily; o { | ||
232 | case 0: | ||
233 | obs = f.Latency.Minute() | ||
234 | data.HistogramWindow = "last minute" | ||
235 | case 1: | ||
236 | obs = f.Latency.Hour() | ||
237 | data.HistogramWindow = "last hour" | ||
238 | case 2: | ||
239 | obs = f.Latency.Total() | ||
240 | data.HistogramWindow = "all time" | ||
241 | } | ||
242 | f.LatencyMu.RUnlock() | ||
243 | if obs != nil { | ||
244 | data.Histogram = obs.(*histogram).html() | ||
245 | } | ||
246 | } | ||
247 | } | ||
248 | |||
249 | if data.Traces != nil { | ||
250 | defer data.Traces.Free() | ||
251 | sort.Sort(data.Traces) | ||
252 | } | ||
253 | |||
254 | completedMu.RLock() | ||
255 | defer completedMu.RUnlock() | ||
256 | if err := pageTmpl().ExecuteTemplate(w, "Page", data); err != nil { | ||
257 | log.Printf("net/trace: Failed executing template: %v", err) | ||
258 | } | ||
259 | } | ||
260 | |||
261 | func parseArgs(req *http.Request) (fam string, b int, ok bool) { | ||
262 | if req == nil { | ||
263 | return "", 0, false | ||
264 | } | ||
265 | fam, bStr := req.FormValue("fam"), req.FormValue("b") | ||
266 | if fam == "" || bStr == "" { | ||
267 | return "", 0, false | ||
268 | } | ||
269 | b, err := strconv.Atoi(bStr) | ||
270 | if err != nil || b < -1 { | ||
271 | return "", 0, false | ||
272 | } | ||
273 | |||
274 | return fam, b, true | ||
275 | } | ||
276 | |||
277 | func lookupBucket(fam string, b int) *traceBucket { | ||
278 | f := getFamily(fam, false) | ||
279 | if f == nil || b < 0 || b >= len(f.Buckets) { | ||
280 | return nil | ||
281 | } | ||
282 | return f.Buckets[b] | ||
283 | } | ||
284 | |||
285 | type contextKeyT string | ||
286 | |||
287 | var contextKey = contextKeyT("golang.org/x/net/trace.Trace") | ||
288 | |||
289 | // Trace represents an active request. | ||
290 | type Trace interface { | ||
291 | // LazyLog adds x to the event log. It will be evaluated each time the | ||
292 | // /debug/requests page is rendered. Any memory referenced by x will be | ||
293 | // pinned until the trace is finished and later discarded. | ||
294 | LazyLog(x fmt.Stringer, sensitive bool) | ||
295 | |||
296 | // LazyPrintf evaluates its arguments with fmt.Sprintf each time the | ||
297 | // /debug/requests page is rendered. Any memory referenced by a will be | ||
298 | // pinned until the trace is finished and later discarded. | ||
299 | LazyPrintf(format string, a ...interface{}) | ||
300 | |||
301 | // SetError declares that this trace resulted in an error. | ||
302 | SetError() | ||
303 | |||
304 | // SetRecycler sets a recycler for the trace. | ||
305 | // f will be called for each event passed to LazyLog at a time when | ||
306 | // it is no longer required, whether while the trace is still active | ||
307 | // and the event is discarded, or when a completed trace is discarded. | ||
308 | SetRecycler(f func(interface{})) | ||
309 | |||
310 | // SetTraceInfo sets the trace info for the trace. | ||
311 | // This is currently unused. | ||
312 | SetTraceInfo(traceID, spanID uint64) | ||
313 | |||
314 | // SetMaxEvents sets the maximum number of events that will be stored | ||
315 | // in the trace. This has no effect if any events have already been | ||
316 | // added to the trace. | ||
317 | SetMaxEvents(m int) | ||
318 | |||
319 | // Finish declares that this trace is complete. | ||
320 | // The trace should not be used after calling this method. | ||
321 | Finish() | ||
322 | } | ||
323 | |||
324 | type lazySprintf struct { | ||
325 | format string | ||
326 | a []interface{} | ||
327 | } | ||
328 | |||
329 | func (l *lazySprintf) String() string { | ||
330 | return fmt.Sprintf(l.format, l.a...) | ||
331 | } | ||
332 | |||
333 | // New returns a new Trace with the specified family and title. | ||
334 | func New(family, title string) Trace { | ||
335 | tr := newTrace() | ||
336 | tr.ref() | ||
337 | tr.Family, tr.Title = family, title | ||
338 | tr.Start = time.Now() | ||
339 | tr.maxEvents = maxEventsPerTrace | ||
340 | tr.events = tr.eventsBuf[:0] | ||
341 | |||
342 | activeMu.RLock() | ||
343 | s := activeTraces[tr.Family] | ||
344 | activeMu.RUnlock() | ||
345 | if s == nil { | ||
346 | activeMu.Lock() | ||
347 | s = activeTraces[tr.Family] // check again | ||
348 | if s == nil { | ||
349 | s = new(traceSet) | ||
350 | activeTraces[tr.Family] = s | ||
351 | } | ||
352 | activeMu.Unlock() | ||
353 | } | ||
354 | s.Add(tr) | ||
355 | |||
356 | // Trigger allocation of the completed trace structure for this family. | ||
357 | // This will cause the family to be present in the request page during | ||
358 | // the first trace of this family. We don't care about the return value, | ||
359 | // nor is there any need for this to run inline, so we execute it in its | ||
360 | // own goroutine, but only if the family isn't allocated yet. | ||
361 | completedMu.RLock() | ||
362 | if _, ok := completedTraces[tr.Family]; !ok { | ||
363 | go allocFamily(tr.Family) | ||
364 | } | ||
365 | completedMu.RUnlock() | ||
366 | |||
367 | return tr | ||
368 | } | ||
369 | |||
370 | func (tr *trace) Finish() { | ||
371 | tr.Elapsed = time.Now().Sub(tr.Start) | ||
372 | if DebugUseAfterFinish { | ||
373 | buf := make([]byte, 4<<10) // 4 KB should be enough | ||
374 | n := runtime.Stack(buf, false) | ||
375 | tr.finishStack = buf[:n] | ||
376 | } | ||
377 | |||
378 | activeMu.RLock() | ||
379 | m := activeTraces[tr.Family] | ||
380 | activeMu.RUnlock() | ||
381 | m.Remove(tr) | ||
382 | |||
383 | f := getFamily(tr.Family, true) | ||
384 | for _, b := range f.Buckets { | ||
385 | if b.Cond.match(tr) { | ||
386 | b.Add(tr) | ||
387 | } | ||
388 | } | ||
389 | // Add a sample of elapsed time as microseconds to the family's timeseries | ||
390 | h := new(histogram) | ||
391 | h.addMeasurement(tr.Elapsed.Nanoseconds() / 1e3) | ||
392 | f.LatencyMu.Lock() | ||
393 | f.Latency.Add(h) | ||
394 | f.LatencyMu.Unlock() | ||
395 | |||
396 | tr.unref() // matches ref in New | ||
397 | } | ||
398 | |||
399 | const ( | ||
400 | bucketsPerFamily = 9 | ||
401 | tracesPerBucket = 10 | ||
402 | maxActiveTraces = 20 // Maximum number of active traces to show. | ||
403 | maxEventsPerTrace = 10 | ||
404 | numHistogramBuckets = 38 | ||
405 | ) | ||
406 | |||
407 | var ( | ||
408 | // The active traces. | ||
409 | activeMu sync.RWMutex | ||
410 | activeTraces = make(map[string]*traceSet) // family -> traces | ||
411 | |||
412 | // Families of completed traces. | ||
413 | completedMu sync.RWMutex | ||
414 | completedTraces = make(map[string]*family) // family -> traces | ||
415 | ) | ||
416 | |||
417 | type traceSet struct { | ||
418 | mu sync.RWMutex | ||
419 | m map[*trace]bool | ||
420 | |||
421 | // We could avoid the entire map scan in FirstN by having a slice of all the traces | ||
422 | // ordered by start time, and an index into that from the trace struct, with a periodic | ||
423 | // repack of the slice after enough traces finish; we could also use a skip list or similar. | ||
424 | // However, that would shift some of the expense from /debug/requests time to RPC time, | ||
425 | // which is probably the wrong trade-off. | ||
426 | } | ||
427 | |||
428 | func (ts *traceSet) Len() int { | ||
429 | ts.mu.RLock() | ||
430 | defer ts.mu.RUnlock() | ||
431 | return len(ts.m) | ||
432 | } | ||
433 | |||
434 | func (ts *traceSet) Add(tr *trace) { | ||
435 | ts.mu.Lock() | ||
436 | if ts.m == nil { | ||
437 | ts.m = make(map[*trace]bool) | ||
438 | } | ||
439 | ts.m[tr] = true | ||
440 | ts.mu.Unlock() | ||
441 | } | ||
442 | |||
443 | func (ts *traceSet) Remove(tr *trace) { | ||
444 | ts.mu.Lock() | ||
445 | delete(ts.m, tr) | ||
446 | ts.mu.Unlock() | ||
447 | } | ||
448 | |||
449 | // FirstN returns the first n traces ordered by time. | ||
450 | func (ts *traceSet) FirstN(n int) traceList { | ||
451 | ts.mu.RLock() | ||
452 | defer ts.mu.RUnlock() | ||
453 | |||
454 | if n > len(ts.m) { | ||
455 | n = len(ts.m) | ||
456 | } | ||
457 | trl := make(traceList, 0, n) | ||
458 | |||
459 | // Fast path for when no selectivity is needed. | ||
460 | if n == len(ts.m) { | ||
461 | for tr := range ts.m { | ||
462 | tr.ref() | ||
463 | trl = append(trl, tr) | ||
464 | } | ||
465 | sort.Sort(trl) | ||
466 | return trl | ||
467 | } | ||
468 | |||
469 | // Pick the oldest n traces. | ||
470 | // This is inefficient. See the comment in the traceSet struct. | ||
471 | for tr := range ts.m { | ||
472 | // Put the first n traces into trl in the order they occur. | ||
473 | // When we have n, sort trl, and thereafter maintain its order. | ||
474 | if len(trl) < n { | ||
475 | tr.ref() | ||
476 | trl = append(trl, tr) | ||
477 | if len(trl) == n { | ||
478 | // This is guaranteed to happen exactly once during this loop. | ||
479 | sort.Sort(trl) | ||
480 | } | ||
481 | continue | ||
482 | } | ||
483 | if tr.Start.After(trl[n-1].Start) { | ||
484 | continue | ||
485 | } | ||
486 | |||
487 | // Find where to insert this one. | ||
488 | tr.ref() | ||
489 | i := sort.Search(n, func(i int) bool { return trl[i].Start.After(tr.Start) }) | ||
490 | trl[n-1].unref() | ||
491 | copy(trl[i+1:], trl[i:]) | ||
492 | trl[i] = tr | ||
493 | } | ||
494 | |||
495 | return trl | ||
496 | } | ||
497 | |||
498 | func getActiveTraces(fam string) traceList { | ||
499 | activeMu.RLock() | ||
500 | s := activeTraces[fam] | ||
501 | activeMu.RUnlock() | ||
502 | if s == nil { | ||
503 | return nil | ||
504 | } | ||
505 | return s.FirstN(maxActiveTraces) | ||
506 | } | ||
507 | |||
508 | func getFamily(fam string, allocNew bool) *family { | ||
509 | completedMu.RLock() | ||
510 | f := completedTraces[fam] | ||
511 | completedMu.RUnlock() | ||
512 | if f == nil && allocNew { | ||
513 | f = allocFamily(fam) | ||
514 | } | ||
515 | return f | ||
516 | } | ||
517 | |||
518 | func allocFamily(fam string) *family { | ||
519 | completedMu.Lock() | ||
520 | defer completedMu.Unlock() | ||
521 | f := completedTraces[fam] | ||
522 | if f == nil { | ||
523 | f = newFamily() | ||
524 | completedTraces[fam] = f | ||
525 | } | ||
526 | return f | ||
527 | } | ||
528 | |||
529 | // family represents a set of trace buckets and associated latency information. | ||
530 | type family struct { | ||
531 | // traces may occur in multiple buckets. | ||
532 | Buckets [bucketsPerFamily]*traceBucket | ||
533 | |||
534 | // latency time series | ||
535 | LatencyMu sync.RWMutex | ||
536 | Latency *timeseries.MinuteHourSeries | ||
537 | } | ||
538 | |||
539 | func newFamily() *family { | ||
540 | return &family{ | ||
541 | Buckets: [bucketsPerFamily]*traceBucket{ | ||
542 | {Cond: minCond(0)}, | ||
543 | {Cond: minCond(50 * time.Millisecond)}, | ||
544 | {Cond: minCond(100 * time.Millisecond)}, | ||
545 | {Cond: minCond(200 * time.Millisecond)}, | ||
546 | {Cond: minCond(500 * time.Millisecond)}, | ||
547 | {Cond: minCond(1 * time.Second)}, | ||
548 | {Cond: minCond(10 * time.Second)}, | ||
549 | {Cond: minCond(100 * time.Second)}, | ||
550 | {Cond: errorCond{}}, | ||
551 | }, | ||
552 | Latency: timeseries.NewMinuteHourSeries(func() timeseries.Observable { return new(histogram) }), | ||
553 | } | ||
554 | } | ||
555 | |||
556 | // traceBucket represents a size-capped bucket of historic traces, | ||
557 | // along with a condition for a trace to belong to the bucket. | ||
558 | type traceBucket struct { | ||
559 | Cond cond | ||
560 | |||
561 | // Ring buffer implementation of a fixed-size FIFO queue. | ||
562 | mu sync.RWMutex | ||
563 | buf [tracesPerBucket]*trace | ||
564 | start int // < tracesPerBucket | ||
565 | length int // <= tracesPerBucket | ||
566 | } | ||
567 | |||
568 | func (b *traceBucket) Add(tr *trace) { | ||
569 | b.mu.Lock() | ||
570 | defer b.mu.Unlock() | ||
571 | |||
572 | i := b.start + b.length | ||
573 | if i >= tracesPerBucket { | ||
574 | i -= tracesPerBucket | ||
575 | } | ||
576 | if b.length == tracesPerBucket { | ||
577 | // "Remove" an element from the bucket. | ||
578 | b.buf[i].unref() | ||
579 | b.start++ | ||
580 | if b.start == tracesPerBucket { | ||
581 | b.start = 0 | ||
582 | } | ||
583 | } | ||
584 | b.buf[i] = tr | ||
585 | if b.length < tracesPerBucket { | ||
586 | b.length++ | ||
587 | } | ||
588 | tr.ref() | ||
589 | } | ||
590 | |||
591 | // Copy returns a copy of the traces in the bucket. | ||
592 | // If tracedOnly is true, only the traces with trace information will be returned. | ||
593 | // The logs will be ref'd before returning; the caller should call | ||
594 | // the Free method when it is done with them. | ||
595 | // TODO(dsymonds): keep track of traced requests in separate buckets. | ||
596 | func (b *traceBucket) Copy(tracedOnly bool) traceList { | ||
597 | b.mu.RLock() | ||
598 | defer b.mu.RUnlock() | ||
599 | |||
600 | trl := make(traceList, 0, b.length) | ||
601 | for i, x := 0, b.start; i < b.length; i++ { | ||
602 | tr := b.buf[x] | ||
603 | if !tracedOnly || tr.spanID != 0 { | ||
604 | tr.ref() | ||
605 | trl = append(trl, tr) | ||
606 | } | ||
607 | x++ | ||
608 | if x == b.length { | ||
609 | x = 0 | ||
610 | } | ||
611 | } | ||
612 | return trl | ||
613 | } | ||
614 | |||
615 | func (b *traceBucket) Empty() bool { | ||
616 | b.mu.RLock() | ||
617 | defer b.mu.RUnlock() | ||
618 | return b.length == 0 | ||
619 | } | ||
620 | |||
621 | // cond represents a condition on a trace. | ||
622 | type cond interface { | ||
623 | match(t *trace) bool | ||
624 | String() string | ||
625 | } | ||
626 | |||
627 | type minCond time.Duration | ||
628 | |||
629 | func (m minCond) match(t *trace) bool { return t.Elapsed >= time.Duration(m) } | ||
630 | func (m minCond) String() string { return fmt.Sprintf("≥%gs", time.Duration(m).Seconds()) } | ||
631 | |||
632 | type errorCond struct{} | ||
633 | |||
634 | func (e errorCond) match(t *trace) bool { return t.IsError } | ||
635 | func (e errorCond) String() string { return "errors" } | ||
636 | |||
637 | type traceList []*trace | ||
638 | |||
639 | // Free calls unref on each element of the list. | ||
640 | func (trl traceList) Free() { | ||
641 | for _, t := range trl { | ||
642 | t.unref() | ||
643 | } | ||
644 | } | ||
645 | |||
646 | // traceList may be sorted in reverse chronological order. | ||
647 | func (trl traceList) Len() int { return len(trl) } | ||
648 | func (trl traceList) Less(i, j int) bool { return trl[i].Start.After(trl[j].Start) } | ||
649 | func (trl traceList) Swap(i, j int) { trl[i], trl[j] = trl[j], trl[i] } | ||
650 | |||
651 | // An event is a timestamped log entry in a trace. | ||
652 | type event struct { | ||
653 | When time.Time | ||
654 | Elapsed time.Duration // since previous event in trace | ||
655 | NewDay bool // whether this event is on a different day to the previous event | ||
656 | Recyclable bool // whether this event was passed via LazyLog | ||
657 | Sensitive bool // whether this event contains sensitive information | ||
658 | What interface{} // string or fmt.Stringer | ||
659 | } | ||
660 | |||
661 | // WhenString returns a string representation of the elapsed time of the event. | ||
662 | // It will include the date if midnight was crossed. | ||
663 | func (e event) WhenString() string { | ||
664 | if e.NewDay { | ||
665 | return e.When.Format("2006/01/02 15:04:05.000000") | ||
666 | } | ||
667 | return e.When.Format("15:04:05.000000") | ||
668 | } | ||
669 | |||
670 | // discarded represents a number of discarded events. | ||
671 | // It is stored as *discarded to make it easier to update in-place. | ||
672 | type discarded int | ||
673 | |||
674 | func (d *discarded) String() string { | ||
675 | return fmt.Sprintf("(%d events discarded)", int(*d)) | ||
676 | } | ||
677 | |||
678 | // trace represents an active or complete request, | ||
679 | // either sent or received by this program. | ||
680 | type trace struct { | ||
681 | // Family is the top-level grouping of traces to which this belongs. | ||
682 | Family string | ||
683 | |||
684 | // Title is the title of this trace. | ||
685 | Title string | ||
686 | |||
687 | // Timing information. | ||
688 | Start time.Time | ||
689 | Elapsed time.Duration // zero while active | ||
690 | |||
691 | // Trace information if non-zero. | ||
692 | traceID uint64 | ||
693 | spanID uint64 | ||
694 | |||
695 | // Whether this trace resulted in an error. | ||
696 | IsError bool | ||
697 | |||
698 | // Append-only sequence of events (modulo discards). | ||
699 | mu sync.RWMutex | ||
700 | events []event | ||
701 | maxEvents int | ||
702 | |||
703 | refs int32 // how many buckets this is in | ||
704 | recycler func(interface{}) | ||
705 | disc discarded // scratch space to avoid allocation | ||
706 | |||
707 | finishStack []byte // where finish was called, if DebugUseAfterFinish is set | ||
708 | |||
709 | eventsBuf [4]event // preallocated buffer in case we only log a few events | ||
710 | } | ||
711 | |||
712 | func (tr *trace) reset() { | ||
713 | // Clear all but the mutex. Mutexes may not be copied, even when unlocked. | ||
714 | tr.Family = "" | ||
715 | tr.Title = "" | ||
716 | tr.Start = time.Time{} | ||
717 | tr.Elapsed = 0 | ||
718 | tr.traceID = 0 | ||
719 | tr.spanID = 0 | ||
720 | tr.IsError = false | ||
721 | tr.maxEvents = 0 | ||
722 | tr.events = nil | ||
723 | tr.refs = 0 | ||
724 | tr.recycler = nil | ||
725 | tr.disc = 0 | ||
726 | tr.finishStack = nil | ||
727 | for i := range tr.eventsBuf { | ||
728 | tr.eventsBuf[i] = event{} | ||
729 | } | ||
730 | } | ||
731 | |||
732 | // delta returns the elapsed time since the last event or the trace start, | ||
733 | // and whether it spans midnight. | ||
734 | // L >= tr.mu | ||
735 | func (tr *trace) delta(t time.Time) (time.Duration, bool) { | ||
736 | if len(tr.events) == 0 { | ||
737 | return t.Sub(tr.Start), false | ||
738 | } | ||
739 | prev := tr.events[len(tr.events)-1].When | ||
740 | return t.Sub(prev), prev.Day() != t.Day() | ||
741 | } | ||
742 | |||
743 | func (tr *trace) addEvent(x interface{}, recyclable, sensitive bool) { | ||
744 | if DebugUseAfterFinish && tr.finishStack != nil { | ||
745 | buf := make([]byte, 4<<10) // 4 KB should be enough | ||
746 | n := runtime.Stack(buf, false) | ||
747 | log.Printf("net/trace: trace used after finish:\nFinished at:\n%s\nUsed at:\n%s", tr.finishStack, buf[:n]) | ||
748 | } | ||
749 | |||
750 | /* | ||
751 | NOTE TO DEBUGGERS | ||
752 | |||
753 | If you are here because your program panicked in this code, | ||
754 | it is almost definitely the fault of code using this package, | ||
755 | and very unlikely to be the fault of this code. | ||
756 | |||
757 | The most likely scenario is that some code elsewhere is using | ||
758 | a trace.Trace after its Finish method is called. | ||
759 | You can temporarily set the DebugUseAfterFinish var | ||
760 | to help discover where that is; do not leave that var set, | ||
761 | since it makes this package much less efficient. | ||
762 | */ | ||
763 | |||
764 | e := event{When: time.Now(), What: x, Recyclable: recyclable, Sensitive: sensitive} | ||
765 | tr.mu.Lock() | ||
766 | e.Elapsed, e.NewDay = tr.delta(e.When) | ||
767 | if len(tr.events) < tr.maxEvents { | ||
768 | tr.events = append(tr.events, e) | ||
769 | } else { | ||
770 | // Discard the middle events. | ||
771 | di := int((tr.maxEvents - 1) / 2) | ||
772 | if d, ok := tr.events[di].What.(*discarded); ok { | ||
773 | (*d)++ | ||
774 | } else { | ||
775 | // disc starts at two to count for the event it is replacing, | ||
776 | // plus the next one that we are about to drop. | ||
777 | tr.disc = 2 | ||
778 | if tr.recycler != nil && tr.events[di].Recyclable { | ||
779 | go tr.recycler(tr.events[di].What) | ||
780 | } | ||
781 | tr.events[di].What = &tr.disc | ||
782 | } | ||
783 | // The timestamp of the discarded meta-event should be | ||
784 | // the time of the last event it is representing. | ||
785 | tr.events[di].When = tr.events[di+1].When | ||
786 | |||
787 | if tr.recycler != nil && tr.events[di+1].Recyclable { | ||
788 | go tr.recycler(tr.events[di+1].What) | ||
789 | } | ||
790 | copy(tr.events[di+1:], tr.events[di+2:]) | ||
791 | tr.events[tr.maxEvents-1] = e | ||
792 | } | ||
793 | tr.mu.Unlock() | ||
794 | } | ||
795 | |||
796 | func (tr *trace) LazyLog(x fmt.Stringer, sensitive bool) { | ||
797 | tr.addEvent(x, true, sensitive) | ||
798 | } | ||
799 | |||
800 | func (tr *trace) LazyPrintf(format string, a ...interface{}) { | ||
801 | tr.addEvent(&lazySprintf{format, a}, false, false) | ||
802 | } | ||
803 | |||
804 | func (tr *trace) SetError() { tr.IsError = true } | ||
805 | |||
806 | func (tr *trace) SetRecycler(f func(interface{})) { | ||
807 | tr.recycler = f | ||
808 | } | ||
809 | |||
810 | func (tr *trace) SetTraceInfo(traceID, spanID uint64) { | ||
811 | tr.traceID, tr.spanID = traceID, spanID | ||
812 | } | ||
813 | |||
814 | func (tr *trace) SetMaxEvents(m int) { | ||
815 | // Always keep at least three events: first, discarded count, last. | ||
816 | if len(tr.events) == 0 && m > 3 { | ||
817 | tr.maxEvents = m | ||
818 | } | ||
819 | } | ||
820 | |||
821 | func (tr *trace) ref() { | ||
822 | atomic.AddInt32(&tr.refs, 1) | ||
823 | } | ||
824 | |||
825 | func (tr *trace) unref() { | ||
826 | if atomic.AddInt32(&tr.refs, -1) == 0 { | ||
827 | if tr.recycler != nil { | ||
828 | // freeTrace clears tr, so we hold tr.recycler and tr.events here. | ||
829 | go func(f func(interface{}), es []event) { | ||
830 | for _, e := range es { | ||
831 | if e.Recyclable { | ||
832 | f(e.What) | ||
833 | } | ||
834 | } | ||
835 | }(tr.recycler, tr.events) | ||
836 | } | ||
837 | |||
838 | freeTrace(tr) | ||
839 | } | ||
840 | } | ||
841 | |||
842 | func (tr *trace) When() string { | ||
843 | return tr.Start.Format("2006/01/02 15:04:05.000000") | ||
844 | } | ||
845 | |||
846 | func (tr *trace) ElapsedTime() string { | ||
847 | t := tr.Elapsed | ||
848 | if t == 0 { | ||
849 | // Active trace. | ||
850 | t = time.Since(tr.Start) | ||
851 | } | ||
852 | return fmt.Sprintf("%.6f", t.Seconds()) | ||
853 | } | ||
854 | |||
855 | func (tr *trace) Events() []event { | ||
856 | tr.mu.RLock() | ||
857 | defer tr.mu.RUnlock() | ||
858 | return tr.events | ||
859 | } | ||
860 | |||
861 | var traceFreeList = make(chan *trace, 1000) // TODO(dsymonds): Use sync.Pool? | ||
862 | |||
863 | // newTrace returns a trace ready to use. | ||
864 | func newTrace() *trace { | ||
865 | select { | ||
866 | case tr := <-traceFreeList: | ||
867 | return tr | ||
868 | default: | ||
869 | return new(trace) | ||
870 | } | ||
871 | } | ||
872 | |||
873 | // freeTrace adds tr to traceFreeList if there's room. | ||
874 | // This is non-blocking. | ||
875 | func freeTrace(tr *trace) { | ||
876 | if DebugUseAfterFinish { | ||
877 | return // never reuse | ||
878 | } | ||
879 | tr.reset() | ||
880 | select { | ||
881 | case traceFreeList <- tr: | ||
882 | default: | ||
883 | } | ||
884 | } | ||
885 | |||
886 | func elapsed(d time.Duration) string { | ||
887 | b := []byte(fmt.Sprintf("%.6f", d.Seconds())) | ||
888 | |||
889 | // For subsecond durations, blank all zeros before decimal point, | ||
890 | // and all zeros between the decimal point and the first non-zero digit. | ||
891 | if d < time.Second { | ||
892 | dot := bytes.IndexByte(b, '.') | ||
893 | for i := 0; i < dot; i++ { | ||
894 | b[i] = ' ' | ||
895 | } | ||
896 | for i := dot + 1; i < len(b); i++ { | ||
897 | if b[i] == '0' { | ||
898 | b[i] = ' ' | ||
899 | } else { | ||
900 | break | ||
901 | } | ||
902 | } | ||
903 | } | ||
904 | |||
905 | return string(b) | ||
906 | } | ||
907 | |||
908 | var pageTmplCache *template.Template | ||
909 | var pageTmplOnce sync.Once | ||
910 | |||
911 | func pageTmpl() *template.Template { | ||
912 | pageTmplOnce.Do(func() { | ||
913 | pageTmplCache = template.Must(template.New("Page").Funcs(template.FuncMap{ | ||
914 | "elapsed": elapsed, | ||
915 | "add": func(a, b int) int { return a + b }, | ||
916 | }).Parse(pageHTML)) | ||
917 | }) | ||
918 | return pageTmplCache | ||
919 | } | ||
920 | |||
921 | const pageHTML = ` | ||
922 | {{template "Prolog" .}} | ||
923 | {{template "StatusTable" .}} | ||
924 | {{template "Epilog" .}} | ||
925 | |||
926 | {{define "Prolog"}} | ||
927 | <html> | ||
928 | <head> | ||
929 | <title>/debug/requests</title> | ||
930 | <style type="text/css"> | ||
931 | body { | ||
932 | font-family: sans-serif; | ||
933 | } | ||
934 | table#tr-status td.family { | ||
935 | padding-right: 2em; | ||
936 | } | ||
937 | table#tr-status td.active { | ||
938 | padding-right: 1em; | ||
939 | } | ||
940 | table#tr-status td.latency-first { | ||
941 | padding-left: 1em; | ||
942 | } | ||
943 | table#tr-status td.empty { | ||
944 | color: #aaa; | ||
945 | } | ||
946 | table#reqs { | ||
947 | margin-top: 1em; | ||
948 | } | ||
949 | table#reqs tr.first { | ||
950 | {{if $.Expanded}}font-weight: bold;{{end}} | ||
951 | } | ||
952 | table#reqs td { | ||
953 | font-family: monospace; | ||
954 | } | ||
955 | table#reqs td.when { | ||
956 | text-align: right; | ||
957 | white-space: nowrap; | ||
958 | } | ||
959 | table#reqs td.elapsed { | ||
960 | padding: 0 0.5em; | ||
961 | text-align: right; | ||
962 | white-space: pre; | ||
963 | width: 10em; | ||
964 | } | ||
965 | address { | ||
966 | font-size: smaller; | ||
967 | margin-top: 5em; | ||
968 | } | ||
969 | </style> | ||
970 | </head> | ||
971 | <body> | ||
972 | |||
973 | <h1>/debug/requests</h1> | ||
974 | {{end}} {{/* end of Prolog */}} | ||
975 | |||
976 | {{define "StatusTable"}} | ||
977 | <table id="tr-status"> | ||
978 | {{range $fam := .Families}} | ||
979 | <tr> | ||
980 | <td class="family">{{$fam}}</td> | ||
981 | |||
982 | {{$n := index $.ActiveTraceCount $fam}} | ||
983 | <td class="active {{if not $n}}empty{{end}}"> | ||
984 | {{if $n}}<a href="?fam={{$fam}}&b=-1{{if $.Expanded}}&exp=1{{end}}">{{end}} | ||
985 | [{{$n}} active] | ||
986 | {{if $n}}</a>{{end}} | ||
987 | </td> | ||
988 | |||
989 | {{$f := index $.CompletedTraces $fam}} | ||
990 | {{range $i, $b := $f.Buckets}} | ||
991 | {{$empty := $b.Empty}} | ||
992 | <td {{if $empty}}class="empty"{{end}}> | ||
993 | {{if not $empty}}<a href="?fam={{$fam}}&b={{$i}}{{if $.Expanded}}&exp=1{{end}}">{{end}} | ||
994 | [{{.Cond}}] | ||
995 | {{if not $empty}}</a>{{end}} | ||
996 | </td> | ||
997 | {{end}} | ||
998 | |||
999 | {{$nb := len $f.Buckets}} | ||
1000 | <td class="latency-first"> | ||
1001 | <a href="?fam={{$fam}}&b={{$nb}}">[minute]</a> | ||
1002 | </td> | ||
1003 | <td> | ||
1004 | <a href="?fam={{$fam}}&b={{add $nb 1}}">[hour]</a> | ||
1005 | </td> | ||
1006 | <td> | ||
1007 | <a href="?fam={{$fam}}&b={{add $nb 2}}">[total]</a> | ||
1008 | </td> | ||
1009 | |||
1010 | </tr> | ||
1011 | {{end}} | ||
1012 | </table> | ||
1013 | {{end}} {{/* end of StatusTable */}} | ||
1014 | |||
1015 | {{define "Epilog"}} | ||
1016 | {{if $.Traces}} | ||
1017 | <hr /> | ||
1018 | <h3>Family: {{$.Family}}</h3> | ||
1019 | |||
1020 | {{if or $.Expanded $.Traced}} | ||
1021 | <a href="?fam={{$.Family}}&b={{$.Bucket}}">[Normal/Summary]</a> | ||
1022 | {{else}} | ||
1023 | [Normal/Summary] | ||
1024 | {{end}} | ||
1025 | |||
1026 | {{if or (not $.Expanded) $.Traced}} | ||
1027 | <a href="?fam={{$.Family}}&b={{$.Bucket}}&exp=1">[Normal/Expanded]</a> | ||
1028 | {{else}} | ||
1029 | [Normal/Expanded] | ||
1030 | {{end}} | ||
1031 | |||
1032 | {{if not $.Active}} | ||
1033 | {{if or $.Expanded (not $.Traced)}} | ||
1034 | <a href="?fam={{$.Family}}&b={{$.Bucket}}&rtraced=1">[Traced/Summary]</a> | ||
1035 | {{else}} | ||
1036 | [Traced/Summary] | ||
1037 | {{end}} | ||
1038 | {{if or (not $.Expanded) (not $.Traced)}} | ||
1039 | <a href="?fam={{$.Family}}&b={{$.Bucket}}&exp=1&rtraced=1">[Traced/Expanded]</a> | ||
1040 | {{else}} | ||
1041 | [Traced/Expanded] | ||
1042 | {{end}} | ||
1043 | {{end}} | ||
1044 | |||
1045 | {{if $.Total}} | ||
1046 | <p><em>Showing <b>{{len $.Traces}}</b> of <b>{{$.Total}}</b> traces.</em></p> | ||
1047 | {{end}} | ||
1048 | |||
1049 | <table id="reqs"> | ||
1050 | <caption> | ||
1051 | {{if $.Active}}Active{{else}}Completed{{end}} Requests | ||
1052 | </caption> | ||
1053 | <tr><th>When</th><th>Elapsed (s)</th></tr> | ||
1054 | {{range $tr := $.Traces}} | ||
1055 | <tr class="first"> | ||
1056 | <td class="when">{{$tr.When}}</td> | ||
1057 | <td class="elapsed">{{$tr.ElapsedTime}}</td> | ||
1058 | <td>{{$tr.Title}}</td> | ||
1059 | {{/* TODO: include traceID/spanID */}} | ||
1060 | </tr> | ||
1061 | {{if $.Expanded}} | ||
1062 | {{range $tr.Events}} | ||
1063 | <tr> | ||
1064 | <td class="when">{{.WhenString}}</td> | ||
1065 | <td class="elapsed">{{elapsed .Elapsed}}</td> | ||
1066 | <td>{{if or $.ShowSensitive (not .Sensitive)}}... {{.What}}{{else}}<em>[redacted]</em>{{end}}</td> | ||
1067 | </tr> | ||
1068 | {{end}} | ||
1069 | {{end}} | ||
1070 | {{end}} | ||
1071 | </table> | ||
1072 | {{end}} {{/* if $.Traces */}} | ||
1073 | |||
1074 | {{if $.Histogram}} | ||
1075 | <h4>Latency (µs) of {{$.Family}} over {{$.HistogramWindow}}</h4> | ||
1076 | {{$.Histogram}} | ||
1077 | {{end}} {{/* if $.Histogram */}} | ||
1078 | |||
1079 | </body> | ||
1080 | </html> | ||
1081 | {{end}} {{/* end of Epilog */}} | ||
1082 | ` | ||
diff --git a/vendor/golang.org/x/net/trace/trace_go16.go b/vendor/golang.org/x/net/trace/trace_go16.go new file mode 100644 index 0000000..d608191 --- /dev/null +++ b/vendor/golang.org/x/net/trace/trace_go16.go | |||
@@ -0,0 +1,21 @@ | |||
1 | // Copyright 2017 The Go Authors. All rights reserved. | ||
2 | // Use of this source code is governed by a BSD-style | ||
3 | // license that can be found in the LICENSE file. | ||
4 | |||
5 | // +build !go1.7 | ||
6 | |||
7 | package trace | ||
8 | |||
9 | import "golang.org/x/net/context" | ||
10 | |||
11 | // NewContext returns a copy of the parent context | ||
12 | // and associates it with a Trace. | ||
13 | func NewContext(ctx context.Context, tr Trace) context.Context { | ||
14 | return context.WithValue(ctx, contextKey, tr) | ||
15 | } | ||
16 | |||
17 | // FromContext returns the Trace bound to the context, if any. | ||
18 | func FromContext(ctx context.Context) (tr Trace, ok bool) { | ||
19 | tr, ok = ctx.Value(contextKey).(Trace) | ||
20 | return | ||
21 | } | ||
diff --git a/vendor/golang.org/x/net/trace/trace_go17.go b/vendor/golang.org/x/net/trace/trace_go17.go new file mode 100644 index 0000000..df6e1fb --- /dev/null +++ b/vendor/golang.org/x/net/trace/trace_go17.go | |||
@@ -0,0 +1,21 @@ | |||
1 | // Copyright 2017 The Go Authors. All rights reserved. | ||
2 | // Use of this source code is governed by a BSD-style | ||
3 | // license that can be found in the LICENSE file. | ||
4 | |||
5 | // +build go1.7 | ||
6 | |||
7 | package trace | ||
8 | |||
9 | import "context" | ||
10 | |||
11 | // NewContext returns a copy of the parent context | ||
12 | // and associates it with a Trace. | ||
13 | func NewContext(ctx context.Context, tr Trace) context.Context { | ||
14 | return context.WithValue(ctx, contextKey, tr) | ||
15 | } | ||
16 | |||
17 | // FromContext returns the Trace bound to the context, if any. | ||
18 | func FromContext(ctx context.Context) (tr Trace, ok bool) { | ||
19 | tr, ok = ctx.Value(contextKey).(Trace) | ||
20 | return | ||
21 | } | ||