mirror of
https://github.com/syncthing/syncthing.git
synced 2026-01-05 12:29:14 -05:00
Compare commits
451 Commits
v0.6.6
...
v0.9.0-bet
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
bc0a8fcc1d | ||
|
|
3b4fe19dfb | ||
|
|
d3085a4127 | ||
|
|
0fcc193197 | ||
|
|
75d4d2df8b | ||
|
|
28f2e8f24d | ||
|
|
f692e3ac73 | ||
|
|
bcb5f6f472 | ||
|
|
74fd4a3722 | ||
|
|
884bb638bc | ||
|
|
3388d5b49c | ||
|
|
4fe2992924 | ||
|
|
0a804e39a8 | ||
|
|
f88a7a8e6a | ||
|
|
ec212f73eb | ||
|
|
91cc0cd05e | ||
|
|
7943902d73 | ||
|
|
32a5e83612 | ||
|
|
8b349945de | ||
|
|
fccdd85cc1 | ||
|
|
bd2b5db8f3 | ||
|
|
44bc5fd784 | ||
|
|
45dfd616cb | ||
|
|
39a691a7e6 | ||
|
|
35b5999cba | ||
|
|
d812f559ef | ||
|
|
54a1f37bf5 | ||
|
|
b0f46beffb | ||
|
|
c844991cba | ||
|
|
b7cf8a471f | ||
|
|
864bb8bc34 | ||
|
|
2d4b89a8e9 | ||
|
|
a6d67d30f5 | ||
|
|
0a633c526f | ||
|
|
655acb4cb2 | ||
|
|
91b35118d9 | ||
|
|
c64321df47 | ||
|
|
3f791b57ce | ||
|
|
8de2a7f4c8 | ||
|
|
dbb4b67205 | ||
|
|
f510f5f205 | ||
|
|
620eeae4a7 | ||
|
|
4cf04a3e0d | ||
|
|
27cd6e60f4 | ||
|
|
2b9fc0fd43 | ||
|
|
d6c058c407 | ||
|
|
8fe5438b59 | ||
|
|
e937e51476 | ||
|
|
b7ea695caf | ||
|
|
31350b4352 | ||
|
|
4a88d1244d | ||
|
|
439049f672 | ||
|
|
ee10295d04 | ||
|
|
2d272a3cac | ||
|
|
2b26891062 | ||
|
|
3d7d4d845a | ||
|
|
c488179783 | ||
|
|
cfb33321b0 | ||
|
|
193cea95ce | ||
|
|
3c4002e149 | ||
|
|
a720f90a70 | ||
|
|
4a6b43bcae | ||
|
|
2f5a822ca4 | ||
|
|
bc1d04f0b9 | ||
|
|
381795d6d0 | ||
|
|
6ade27641d | ||
|
|
53898d2c60 | ||
|
|
91c4ff6009 | ||
|
|
0aa067a726 | ||
|
|
67445a6dda | ||
|
|
5353659f9f | ||
|
|
7ac00e189b | ||
|
|
071f4c0769 | ||
|
|
b57f4ed97e | ||
|
|
7633b9672f | ||
|
|
4f6ee7c8eb | ||
|
|
d7cc48eab2 | ||
|
|
8f3effed32 | ||
|
|
fee8289c0a | ||
|
|
a2da31056b | ||
|
|
f97dd9d8d3 | ||
|
|
2383579a64 | ||
|
|
68750211ef | ||
|
|
db3e3ade80 | ||
|
|
e6f04ed238 | ||
|
|
a6eb690e31 | ||
|
|
21518adfc8 | ||
|
|
77fe8449ba | ||
|
|
33e9a35f08 | ||
|
|
4ab4816556 | ||
|
|
8e8a579bb2 | ||
|
|
efbdf72d20 | ||
|
|
0e59b5678a | ||
|
|
de75550415 | ||
|
|
4dbce32738 | ||
|
|
b05fcbc9d7 | ||
|
|
d09c71b688 | ||
|
|
874d6760d4 | ||
|
|
26ebbee877 | ||
|
|
12eda0449a | ||
|
|
5a98f4e47c | ||
|
|
964c903a68 | ||
|
|
21b699826d | ||
|
|
5fa8f8e50c | ||
|
|
9ca87f5314 | ||
|
|
537c6b3b69 | ||
|
|
48a3fac2da | ||
|
|
fd73682806 | ||
|
|
34bd5b9dcf | ||
|
|
58c5e46206 | ||
|
|
4c61ab0f18 | ||
|
|
f241b63e0e | ||
|
|
2ffdb5a82a | ||
|
|
46e963443d | ||
|
|
66d4e9e5d7 | ||
|
|
de382e33a3 | ||
|
|
3c6738da73 | ||
|
|
18e5cb6793 | ||
|
|
9cd6b85c09 | ||
|
|
f40f3b3b7b | ||
|
|
7454670b0a | ||
|
|
e63596681d | ||
|
|
3dbaa76dcb | ||
|
|
8752003b50 | ||
|
|
8716ed5aa4 | ||
|
|
38ac4e8f79 | ||
|
|
70fc8a3064 | ||
|
|
7626c5d526 | ||
|
|
7e04c9d048 | ||
|
|
9eda8f2c7e | ||
|
|
456d9e870d | ||
|
|
a1533696a5 | ||
|
|
92499af323 | ||
|
|
b2988cdd35 | ||
|
|
82cfd37263 | ||
|
|
df381fd03f | ||
|
|
5a2328d9a5 | ||
|
|
b2f66cfb60 | ||
|
|
6d24e4f122 | ||
|
|
2e2185165c | ||
|
|
f0612e57c2 | ||
|
|
e5d16ed08a | ||
|
|
1cff9ccc63 | ||
|
|
20a018db2e | ||
|
|
80c2b32b92 | ||
|
|
028e9bc17a | ||
|
|
afc2d6fda4 | ||
|
|
bec5c76631 | ||
|
|
d87051ca99 | ||
|
|
3798cebad0 | ||
|
|
a477989950 | ||
|
|
5065d1d0b4 | ||
|
|
829990c9ef | ||
|
|
ac037e0fa3 | ||
|
|
da42d51008 | ||
|
|
99027813ef | ||
|
|
9112ba8f0b | ||
|
|
843fd9bdbd | ||
|
|
26c33c4a69 | ||
|
|
2db76ae786 | ||
|
|
a0b15d006d | ||
|
|
23b27fa24a | ||
|
|
b6f580cbc2 | ||
|
|
f2459ef331 | ||
|
|
0a37fac794 | ||
|
|
2d9a822ed7 | ||
|
|
98622ca4d0 | ||
|
|
f7a25adcbd | ||
|
|
9bf13b253c | ||
|
|
2e8b639a34 | ||
|
|
672f7a010f | ||
|
|
37e15c4368 | ||
|
|
4d7837ba96 | ||
|
|
a6c8423905 | ||
|
|
832ed556d9 | ||
|
|
7c6fb018ca | ||
|
|
9c5c06bf31 | ||
|
|
61e3daaead | ||
|
|
9c0fde795e | ||
|
|
ce4f565e2f | ||
|
|
5369a62fd5 | ||
|
|
b44016ff70 | ||
|
|
9f76c87880 | ||
|
|
42ae2898e1 | ||
|
|
dd649a6be4 | ||
|
|
593f098276 | ||
|
|
4a87221f16 | ||
|
|
7745ed34d3 | ||
|
|
8fe546c4a2 | ||
|
|
381f6aeaf6 | ||
|
|
9154bacced | ||
|
|
dc0dc8efb4 | ||
|
|
b062d5dd7f | ||
|
|
c519e582b5 | ||
|
|
6b9dce36bf | ||
|
|
8e0520887a | ||
|
|
cfd1fdb38e | ||
|
|
c6ba0208d0 | ||
|
|
3d055bbb79 | ||
|
|
dd971b56e5 | ||
|
|
4031f5e24b | ||
|
|
1cd7cc6869 | ||
|
|
9de2864db3 | ||
|
|
c27861cbaf | ||
|
|
c2f75d3689 | ||
|
|
5454ca1cf7 | ||
|
|
8644bf30a9 | ||
|
|
db3341a178 | ||
|
|
e2cb0219c7 | ||
|
|
217f29de76 | ||
|
|
8661afcb4f | ||
|
|
ed07fc0f2c | ||
|
|
4af3f77a9a | ||
|
|
8c4f07ef1b | ||
|
|
1a231d39a5 | ||
|
|
17e3d14272 | ||
|
|
03182c7714 | ||
|
|
963078f6ac | ||
|
|
8356b58b1d | ||
|
|
303ce02271 | ||
|
|
bcdc3ecdae | ||
|
|
b60d648e22 | ||
|
|
7bc36cbbd1 | ||
|
|
04130fcb15 | ||
|
|
52d8e4c691 | ||
|
|
ae0193b724 | ||
|
|
2e1c33206f | ||
|
|
0c642ec7cf | ||
|
|
b3ca96eeba | ||
|
|
ae0e033178 | ||
|
|
a97985b428 | ||
|
|
63c0f11458 | ||
|
|
5b0dd9d3b2 | ||
|
|
8bba82a08d | ||
|
|
51bf15728a | ||
|
|
b336b2c336 | ||
|
|
2331089854 | ||
|
|
8a5a573851 | ||
|
|
6fb05fc82a | ||
|
|
358862c7ad | ||
|
|
4235175966 | ||
|
|
cd433a4f52 | ||
|
|
f3b550744f | ||
|
|
f31e5eaba2 | ||
|
|
7c8652b600 | ||
|
|
30837a7d95 | ||
|
|
3c25a74f3b | ||
|
|
da3177dbe0 | ||
|
|
3ca8dce98b | ||
|
|
e17fa7b14e | ||
|
|
230f149b4b | ||
|
|
dd3d8a6c98 | ||
|
|
36bdd9cb4d | ||
|
|
95f5e5fa9a | ||
|
|
1aef03288a | ||
|
|
a8c510cc72 | ||
|
|
e359b146aa | ||
|
|
dba40eefb1 | ||
|
|
23b55f68b7 | ||
|
|
5c65e10875 | ||
|
|
d7df11e724 | ||
|
|
c08ce5c571 | ||
|
|
12a6682eaf | ||
|
|
bbefcef53b | ||
|
|
729b0143e1 | ||
|
|
84c4298cd5 | ||
|
|
7d672fd989 | ||
|
|
1442d6f4c2 | ||
|
|
13022817d4 | ||
|
|
e788a99c3e | ||
|
|
09d4b3f71e | ||
|
|
78f0f2b131 | ||
|
|
40c750141a | ||
|
|
b60251b960 | ||
|
|
958c39ef5f | ||
|
|
e22ddae3a8 | ||
|
|
68afc897d6 | ||
|
|
ba58e95f6b | ||
|
|
adbd0b1834 | ||
|
|
3e34fc66e6 | ||
|
|
f8e34c083e | ||
|
|
cba554d0fa | ||
|
|
8903825e02 | ||
|
|
81cd84add2 | ||
|
|
8229d47da5 | ||
|
|
8f14d11d66 | ||
|
|
76f82cbd1f | ||
|
|
dc2f83e522 | ||
|
|
8b4282fe28 | ||
|
|
c6416b235b | ||
|
|
79f2b3bd7e | ||
|
|
1f996afa21 | ||
|
|
21335d65c4 | ||
|
|
870ce57005 | ||
|
|
0d3caa2183 | ||
|
|
602d7e8d18 | ||
|
|
a2309f3119 | ||
|
|
9a51be8548 | ||
|
|
5ed319ea42 | ||
|
|
eb7a70a3c9 | ||
|
|
b61f418bf2 | ||
|
|
1338b0a2f8 | ||
|
|
587e1a4f4c | ||
|
|
85d5449b3c | ||
|
|
532b576fd5 | ||
|
|
dd1197236d | ||
|
|
e8a9abaf40 | ||
|
|
1bf07d6b58 | ||
|
|
30ea9cb37e | ||
|
|
bae9247d84 | ||
|
|
a105ad1391 | ||
|
|
abbb40abd2 | ||
|
|
20b23338f7 | ||
|
|
0fcbee6478 | ||
|
|
1d602b9efa | ||
|
|
b783169c72 | ||
|
|
e4f266883a | ||
|
|
7a41362d90 | ||
|
|
3ed783983f | ||
|
|
837f3a68ab | ||
|
|
59e45c5c68 | ||
|
|
94761d0472 | ||
|
|
a91eb701bf | ||
|
|
1a1f118f1a | ||
|
|
b115fca8a9 | ||
|
|
dfd239ac06 | ||
|
|
2ae218d069 | ||
|
|
1401d2ee9b | ||
|
|
f39e105101 | ||
|
|
482795bab0 | ||
|
|
10e8861f14 | ||
|
|
ecc6476308 | ||
|
|
28e347002a | ||
|
|
b3d19bd5cc | ||
|
|
647165ab89 | ||
|
|
6807d9bd4c | ||
|
|
699ecc7140 | ||
|
|
b374ec9355 | ||
|
|
9659d021cb | ||
|
|
a4ad9eb134 | ||
|
|
a455258a62 | ||
|
|
0ae342673a | ||
|
|
33d75a264d | ||
|
|
89dc5bb951 | ||
|
|
45403917de | ||
|
|
ed476271a6 | ||
|
|
1e92c47960 | ||
|
|
4f2fe07ae4 | ||
|
|
aff3cd01c5 | ||
|
|
ac74ee1468 | ||
|
|
0d55cf4be5 | ||
|
|
5399a25532 | ||
|
|
ae882c93c9 | ||
|
|
f398ca77c1 | ||
|
|
dcd7d278aa | ||
|
|
89f5f3bf9a | ||
|
|
76ef42ee07 | ||
|
|
92c1ce57a6 | ||
|
|
116f232f5a | ||
|
|
ef81a36654 | ||
|
|
9fd2724d73 | ||
|
|
07d49b61d0 | ||
|
|
0c4e6ae7de | ||
|
|
65ec129dfb | ||
|
|
3e4d628f54 | ||
|
|
71684bfa45 | ||
|
|
e73b7e0398 | ||
|
|
35ebdc76ff | ||
|
|
90d0896848 | ||
|
|
5528db9693 | ||
|
|
aa78fbb09d | ||
|
|
d53b193e09 | ||
|
|
e0e16c371f | ||
|
|
53cd877899 | ||
|
|
1207223f3d | ||
|
|
39be6932b5 | ||
|
|
44a194d226 | ||
|
|
9349eb77cd | ||
|
|
c64549471a | ||
|
|
264bcbc78c | ||
|
|
f76fe1ac7a | ||
|
|
6364c4ff3f | ||
|
|
292a50de04 | ||
|
|
a08cba9c85 | ||
|
|
9fb60d6935 | ||
|
|
f2ed2d98d8 | ||
|
|
b802cb1e36 | ||
|
|
31bfd8c039 | ||
|
|
f72ee7a69e | ||
|
|
a98d75edaa | ||
|
|
622568c327 | ||
|
|
1ca7e47fd6 | ||
|
|
116203aef8 | ||
|
|
1bf128612d | ||
|
|
935a8eb9a7 | ||
|
|
7e5b350096 | ||
|
|
5c75869e85 | ||
|
|
fbd5ddea72 | ||
|
|
bc8e033eb5 | ||
|
|
70fa5ffa06 | ||
|
|
fb162ff529 | ||
|
|
9d535b13cf | ||
|
|
48bfc2d9ed | ||
|
|
5064f846fc | ||
|
|
41c228cb56 | ||
|
|
e974c8f33e | ||
|
|
94f5d5b59e | ||
|
|
433a0cb9cc | ||
|
|
c42a6b511c | ||
|
|
346b6f4f11 | ||
|
|
07eb4020bd | ||
|
|
c2f0c2225a | ||
|
|
711587492c | ||
|
|
536613f008 | ||
|
|
c832fc7d1b | ||
|
|
0b654581b6 | ||
|
|
cbae64fc06 | ||
|
|
1443a1388e | ||
|
|
a203d99182 | ||
|
|
bc5ff6e1b6 | ||
|
|
3b3c0c5950 | ||
|
|
ee0ee0e39d | ||
|
|
8dee10ba9c | ||
|
|
d3915b8dbf | ||
|
|
671d5cace6 | ||
|
|
aa3d73d322 | ||
|
|
d30a286f38 | ||
|
|
15699a39cf | ||
|
|
a1f32095df | ||
|
|
76e0960a51 | ||
|
|
8e33288156 | ||
|
|
f4d3a9980f | ||
|
|
fc8ce7c6e0 | ||
|
|
aaf0604601 | ||
|
|
dddf563105 | ||
|
|
dbe12cca4b | ||
|
|
ddf0ddbd05 | ||
|
|
5eb5a056bf | ||
|
|
2a5c0646c0 | ||
|
|
7d3c51df9e | ||
|
|
a67bb5e720 | ||
|
|
6d314cdc04 | ||
|
|
1139ea2c81 | ||
|
|
f87b1520e8 | ||
|
|
3700eb1e61 | ||
|
|
17a21102b3 | ||
|
|
e37441627f | ||
|
|
f4c6cd1676 | ||
|
|
bcd3fd40e4 | ||
|
|
d3d1a79996 | ||
|
|
fb4a2c9b5a |
5
.gitignore
vendored
5
.gitignore
vendored
@@ -3,3 +3,8 @@ syncthing.exe
|
||||
*.tar.gz
|
||||
*.zip
|
||||
*.asc
|
||||
*.sublime*
|
||||
discosrv
|
||||
.jshintrc
|
||||
coverage.out
|
||||
files/pidx
|
||||
|
||||
20
.travis.yml
Normal file
20
.travis.yml
Normal file
@@ -0,0 +1,20 @@
|
||||
language: go
|
||||
|
||||
go:
|
||||
- tip
|
||||
|
||||
install:
|
||||
- export PATH=$PATH:$HOME/gopath/bin
|
||||
- ./build.sh setup
|
||||
- go get code.google.com/p/go.tools/cmd/cover
|
||||
- go get github.com/mattn/goveralls
|
||||
|
||||
script:
|
||||
- ./build.sh test-cov
|
||||
|
||||
after_success:
|
||||
- goveralls -coverprofile=coverage.out -service=travis-ci -package=calmh/syncthing -repotoken="$COVERALS_TOKEN"
|
||||
|
||||
env:
|
||||
global:
|
||||
secure: "zEV2h2XtKHNLVdXJjM4LA/VjMfLVydm6goF+ARit+nOSGxGoH7f7jIdzJzhxgh7shKG93q61eLO1Tug+WBMYB2EpBuYnTB5AIMYhCDwNI8C4uBV6c3brHfcrie7MASNao8TID2QScASKNFFWvjv/i1Ccn5ztxdcQuhSsNjGZp8A="
|
||||
@@ -1,8 +1,42 @@
|
||||
Please do contribute!
|
||||
Please do contribute! If you want to contribute but are unsure where to
|
||||
start, the [Contributions Needed
|
||||
topic](http://discourse.syncthing.net/t/contributions-needed/49)
|
||||
lists areas in need of attention.
|
||||
|
||||
## Licensing
|
||||
|
||||
All contributions are made under the same MIT License as the rest of the
|
||||
project, except documentation which is licensed under the Creative
|
||||
Commons Attribution 4.0 International License. You retain the copyright
|
||||
to code you have written.
|
||||
|
||||
When accepting your first contribution, the maintainer of the project
|
||||
will ensure that you are added to the CONTRIBUTORS file. You are welcome
|
||||
to add yourself as a separate commit in your first pull request.
|
||||
|
||||
## Building
|
||||
|
||||
[See the wiki](https://github.com/calmh/syncthing/wiki/Building)
|
||||
[See the
|
||||
documentation](http://discourse.syncthing.net/t/building-syncthing/44)
|
||||
|
||||
## Branches
|
||||
|
||||
- `master` is the main branch containing good code that will end up in
|
||||
the next release. You should base your work on it. It won't ever be
|
||||
rebased or force-pushed to.
|
||||
|
||||
- `vx.y` branches exist to make patch releases on otherwise obsolete
|
||||
minor releases. Should only contain fixes cherry picked from master.
|
||||
Don't base any work on them.
|
||||
|
||||
- Other branches are probably topic branches and may be subject to
|
||||
rebasing. Don't base any work on them unless you specifically know
|
||||
otherwise.
|
||||
|
||||
## Tags
|
||||
|
||||
All releases are tagged semver style as `vx.y.z`. Release tags are
|
||||
signed by GPG key BCE524C7.
|
||||
|
||||
## Tests
|
||||
|
||||
@@ -14,7 +48,7 @@ Yes please!
|
||||
|
||||
## Documentation
|
||||
|
||||
[Hack it here](https://github.com/calmh/syncthing/wiki)
|
||||
[Over here!](http://discourse.syncthing.net/category/documentation)
|
||||
|
||||
## License
|
||||
|
||||
|
||||
10
CONTRIBUTORS
Normal file
10
CONTRIBUTORS
Normal file
@@ -0,0 +1,10 @@
|
||||
Aaron Bieber <qbit@deftly.net>
|
||||
Andrew Dunham <andrew@du.nham.ca>
|
||||
Arthur Axel fREW Schmidt <frew@afoolishmanifesto.com>
|
||||
Ben Sidhom <bsidhom@gmail.com>
|
||||
Brandon Philips <brandon@ifup.org>
|
||||
James Patterson <jamespatterson@operamail.com>
|
||||
Jens Diemer <github.com@jensdiemer.de>
|
||||
Philippe Schommers <philippe@schommers.be>
|
||||
Ryan Sullivan <kayoticsully@gmail.com>
|
||||
Veeti Paananen <veeti.paananen@rojekti.fi>
|
||||
60
Godeps/Godeps.json
generated
60
Godeps/Godeps.json
generated
@@ -1,37 +1,65 @@
|
||||
{
|
||||
"ImportPath": "github.com/calmh/syncthing",
|
||||
"GoVersion": "devel +3ca54dd30864 Sat Mar 22 11:05:40 2014 -0700",
|
||||
"GoVersion": "go1.3",
|
||||
"Packages": [
|
||||
"./cmd/syncthing"
|
||||
"./cmd/syncthing",
|
||||
"./cmd/assets",
|
||||
"./discover/cmd/discosrv"
|
||||
],
|
||||
"Deps": [
|
||||
{
|
||||
"ImportPath": "code.google.com/p/go.net/ipv6",
|
||||
"Comment": "null-117",
|
||||
"Rev": "c17ad62118ea511e1051721b429779fa40bddc74"
|
||||
"ImportPath": "bitbucket.org/kardianos/osext",
|
||||
"Comment": "null-13",
|
||||
"Rev": "5d3ddcf53a508cc2f7404eaebf546ef2cb5cdb6e"
|
||||
},
|
||||
{
|
||||
"ImportPath": "code.google.com/p/go.crypto/bcrypt",
|
||||
"Comment": "null-212",
|
||||
"Rev": "1064b89a6fb591df0dd65422295b8498916b092f"
|
||||
},
|
||||
{
|
||||
"ImportPath": "code.google.com/p/go.crypto/blowfish",
|
||||
"Comment": "null-212",
|
||||
"Rev": "1064b89a6fb591df0dd65422295b8498916b092f"
|
||||
},
|
||||
{
|
||||
"ImportPath": "code.google.com/p/go.text/transform",
|
||||
"Comment": "null-81",
|
||||
"Rev": "9cbe983aed9b0dfc73954433fead5e00866342ac"
|
||||
"Comment": "null-87",
|
||||
"Rev": "c59e4f2f93824f81213799e64c3eead7be24660a"
|
||||
},
|
||||
{
|
||||
"ImportPath": "code.google.com/p/go.text/unicode/norm",
|
||||
"Comment": "null-81",
|
||||
"Rev": "9cbe983aed9b0dfc73954433fead5e00866342ac"
|
||||
"Comment": "null-87",
|
||||
"Rev": "c59e4f2f93824f81213799e64c3eead7be24660a"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/calmh/ini",
|
||||
"Rev": "386c4240a9684d91d9ec4d93651909b49c7269e1"
|
||||
"ImportPath": "code.google.com/p/snappy-go/snappy",
|
||||
"Comment": "null-15",
|
||||
"Rev": "12e4b4183793ac4b061921e7980845e750679fd0"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/codegangsta/inject",
|
||||
"Rev": "9aea7a2fa5b79ef7fc00f63a575e72df33b4e886"
|
||||
"ImportPath": "github.com/golang/groupcache/lru",
|
||||
"Rev": "a531d51b7f9f3dd13c1c2b50d42d739b70442dbb"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/codegangsta/martini",
|
||||
"Comment": "v0.1-142-g8659df7",
|
||||
"Rev": "8659df7a51aebe6c6120268cd5a8b4c34fa8441a"
|
||||
"ImportPath": "github.com/juju/ratelimit",
|
||||
"Rev": "f9f36d11773655c0485207f0ad30dc2655f69d56"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/syndtr/goleveldb/leveldb",
|
||||
"Rev": "e1f2d2bdccd7c62f4d4a29aaf081bf1fc4404f91"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/vitrun/qart/coding",
|
||||
"Rev": "ccb109cf25f0cd24474da73b9fee4e7a3e8a8ce0"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/vitrun/qart/gf256",
|
||||
"Rev": "ccb109cf25f0cd24474da73b9fee4e7a3e8a8ce0"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/vitrun/qart/qr",
|
||||
"Rev": "ccb109cf25f0cd24474da73b9fee4e7a3e8a8ce0"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
20
Godeps/_workspace/src/bitbucket.org/kardianos/osext/LICENSE
generated
vendored
Normal file
20
Godeps/_workspace/src/bitbucket.org/kardianos/osext/LICENSE
generated
vendored
Normal file
@@ -0,0 +1,20 @@
|
||||
Copyright (c) 2012 Daniel Theophanes
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
|
||||
3. This notice may not be removed or altered from any source
|
||||
distribution.
|
||||
32
Godeps/_workspace/src/bitbucket.org/kardianos/osext/osext.go
generated
vendored
Normal file
32
Godeps/_workspace/src/bitbucket.org/kardianos/osext/osext.go
generated
vendored
Normal file
@@ -0,0 +1,32 @@
|
||||
// Copyright 2012 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// Extensions to the standard "os" package.
|
||||
package osext
|
||||
|
||||
import "path/filepath"
|
||||
|
||||
// Executable returns an absolute path that can be used to
|
||||
// re-invoke the current program.
|
||||
// It may not be valid after the current program exits.
|
||||
func Executable() (string, error) {
|
||||
p, err := executable()
|
||||
return filepath.Clean(p), err
|
||||
}
|
||||
|
||||
// Returns same path as Executable, returns just the folder
|
||||
// path. Excludes the executable name.
|
||||
func ExecutableFolder() (string, error) {
|
||||
p, err := Executable()
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
folder, _ := filepath.Split(p)
|
||||
return folder, nil
|
||||
}
|
||||
|
||||
// Depricated. Same as Executable().
|
||||
func GetExePath() (exePath string, err error) {
|
||||
return Executable()
|
||||
}
|
||||
20
Godeps/_workspace/src/bitbucket.org/kardianos/osext/osext_plan9.go
generated
vendored
Normal file
20
Godeps/_workspace/src/bitbucket.org/kardianos/osext/osext_plan9.go
generated
vendored
Normal file
@@ -0,0 +1,20 @@
|
||||
// Copyright 2012 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package osext
|
||||
|
||||
import (
|
||||
"syscall"
|
||||
"os"
|
||||
"strconv"
|
||||
)
|
||||
|
||||
func executable() (string, error) {
|
||||
f, err := os.Open("/proc/" + strconv.Itoa(os.Getpid()) + "/text")
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
defer f.Close()
|
||||
return syscall.Fd2path(int(f.Fd()))
|
||||
}
|
||||
25
Godeps/_workspace/src/bitbucket.org/kardianos/osext/osext_procfs.go
generated
vendored
Normal file
25
Godeps/_workspace/src/bitbucket.org/kardianos/osext/osext_procfs.go
generated
vendored
Normal file
@@ -0,0 +1,25 @@
|
||||
// Copyright 2012 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build linux netbsd openbsd
|
||||
|
||||
package osext
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"os"
|
||||
"runtime"
|
||||
)
|
||||
|
||||
func executable() (string, error) {
|
||||
switch runtime.GOOS {
|
||||
case "linux":
|
||||
return os.Readlink("/proc/self/exe")
|
||||
case "netbsd":
|
||||
return os.Readlink("/proc/curproc/exe")
|
||||
case "openbsd":
|
||||
return os.Readlink("/proc/curproc/file")
|
||||
}
|
||||
return "", errors.New("ExecPath not implemented for " + runtime.GOOS)
|
||||
}
|
||||
79
Godeps/_workspace/src/bitbucket.org/kardianos/osext/osext_sysctl.go
generated
vendored
Normal file
79
Godeps/_workspace/src/bitbucket.org/kardianos/osext/osext_sysctl.go
generated
vendored
Normal file
@@ -0,0 +1,79 @@
|
||||
// Copyright 2012 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build darwin freebsd
|
||||
|
||||
package osext
|
||||
|
||||
import (
|
||||
"os"
|
||||
"path/filepath"
|
||||
"runtime"
|
||||
"syscall"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
var initCwd, initCwdErr = os.Getwd()
|
||||
|
||||
func executable() (string, error) {
|
||||
var mib [4]int32
|
||||
switch runtime.GOOS {
|
||||
case "freebsd":
|
||||
mib = [4]int32{1 /* CTL_KERN */, 14 /* KERN_PROC */, 12 /* KERN_PROC_PATHNAME */, -1}
|
||||
case "darwin":
|
||||
mib = [4]int32{1 /* CTL_KERN */, 38 /* KERN_PROCARGS */, int32(os.Getpid()), -1}
|
||||
}
|
||||
|
||||
n := uintptr(0)
|
||||
// Get length.
|
||||
_, _, errNum := syscall.Syscall6(syscall.SYS___SYSCTL, uintptr(unsafe.Pointer(&mib[0])), 4, 0, uintptr(unsafe.Pointer(&n)), 0, 0)
|
||||
if errNum != 0 {
|
||||
return "", errNum
|
||||
}
|
||||
if n == 0 { // This shouldn't happen.
|
||||
return "", nil
|
||||
}
|
||||
buf := make([]byte, n)
|
||||
_, _, errNum = syscall.Syscall6(syscall.SYS___SYSCTL, uintptr(unsafe.Pointer(&mib[0])), 4, uintptr(unsafe.Pointer(&buf[0])), uintptr(unsafe.Pointer(&n)), 0, 0)
|
||||
if errNum != 0 {
|
||||
return "", errNum
|
||||
}
|
||||
if n == 0 { // This shouldn't happen.
|
||||
return "", nil
|
||||
}
|
||||
for i, v := range buf {
|
||||
if v == 0 {
|
||||
buf = buf[:i]
|
||||
break
|
||||
}
|
||||
}
|
||||
var err error
|
||||
execPath := string(buf)
|
||||
// execPath will not be empty due to above checks.
|
||||
// Try to get the absolute path if the execPath is not rooted.
|
||||
if execPath[0] != '/' {
|
||||
execPath, err = getAbs(execPath)
|
||||
if err != nil {
|
||||
return execPath, err
|
||||
}
|
||||
}
|
||||
// For darwin KERN_PROCARGS may return the path to a symlink rather than the
|
||||
// actual executable.
|
||||
if runtime.GOOS == "darwin" {
|
||||
if execPath, err = filepath.EvalSymlinks(execPath); err != nil {
|
||||
return execPath, err
|
||||
}
|
||||
}
|
||||
return execPath, nil
|
||||
}
|
||||
|
||||
func getAbs(execPath string) (string, error) {
|
||||
if initCwdErr != nil {
|
||||
return execPath, initCwdErr
|
||||
}
|
||||
// The execPath may begin with a "../" or a "./" so clean it first.
|
||||
// Join the two paths, trailing and starting slashes undetermined, so use
|
||||
// the generic Join function.
|
||||
return filepath.Join(initCwd, filepath.Clean(execPath)), nil
|
||||
}
|
||||
79
Godeps/_workspace/src/bitbucket.org/kardianos/osext/osext_test.go
generated
vendored
Normal file
79
Godeps/_workspace/src/bitbucket.org/kardianos/osext/osext_test.go
generated
vendored
Normal file
@@ -0,0 +1,79 @@
|
||||
// Copyright 2012 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build darwin linux freebsd netbsd windows
|
||||
|
||||
package osext
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
oexec "os/exec"
|
||||
"path/filepath"
|
||||
"runtime"
|
||||
"testing"
|
||||
)
|
||||
|
||||
const execPath_EnvVar = "OSTEST_OUTPUT_EXECPATH"
|
||||
|
||||
func TestExecPath(t *testing.T) {
|
||||
ep, err := Executable()
|
||||
if err != nil {
|
||||
t.Fatalf("ExecPath failed: %v", err)
|
||||
}
|
||||
// we want fn to be of the form "dir/prog"
|
||||
dir := filepath.Dir(filepath.Dir(ep))
|
||||
fn, err := filepath.Rel(dir, ep)
|
||||
if err != nil {
|
||||
t.Fatalf("filepath.Rel: %v", err)
|
||||
}
|
||||
cmd := &oexec.Cmd{}
|
||||
// make child start with a relative program path
|
||||
cmd.Dir = dir
|
||||
cmd.Path = fn
|
||||
// forge argv[0] for child, so that we can verify we could correctly
|
||||
// get real path of the executable without influenced by argv[0].
|
||||
cmd.Args = []string{"-", "-test.run=XXXX"}
|
||||
cmd.Env = []string{fmt.Sprintf("%s=1", execPath_EnvVar)}
|
||||
out, err := cmd.CombinedOutput()
|
||||
if err != nil {
|
||||
t.Fatalf("exec(self) failed: %v", err)
|
||||
}
|
||||
outs := string(out)
|
||||
if !filepath.IsAbs(outs) {
|
||||
t.Fatalf("Child returned %q, want an absolute path", out)
|
||||
}
|
||||
if !sameFile(outs, ep) {
|
||||
t.Fatalf("Child returned %q, not the same file as %q", out, ep)
|
||||
}
|
||||
}
|
||||
|
||||
func sameFile(fn1, fn2 string) bool {
|
||||
fi1, err := os.Stat(fn1)
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
fi2, err := os.Stat(fn2)
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
return os.SameFile(fi1, fi2)
|
||||
}
|
||||
|
||||
func init() {
|
||||
if e := os.Getenv(execPath_EnvVar); e != "" {
|
||||
// first chdir to another path
|
||||
dir := "/"
|
||||
if runtime.GOOS == "windows" {
|
||||
dir = filepath.VolumeName(".")
|
||||
}
|
||||
os.Chdir(dir)
|
||||
if ep, err := Executable(); err != nil {
|
||||
fmt.Fprint(os.Stderr, "ERROR: ", err)
|
||||
} else {
|
||||
fmt.Fprint(os.Stderr, ep)
|
||||
}
|
||||
os.Exit(0)
|
||||
}
|
||||
}
|
||||
34
Godeps/_workspace/src/bitbucket.org/kardianos/osext/osext_windows.go
generated
vendored
Normal file
34
Godeps/_workspace/src/bitbucket.org/kardianos/osext/osext_windows.go
generated
vendored
Normal file
@@ -0,0 +1,34 @@
|
||||
// Copyright 2012 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package osext
|
||||
|
||||
import (
|
||||
"syscall"
|
||||
"unicode/utf16"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
var (
|
||||
kernel = syscall.MustLoadDLL("kernel32.dll")
|
||||
getModuleFileNameProc = kernel.MustFindProc("GetModuleFileNameW")
|
||||
)
|
||||
|
||||
// GetModuleFileName() with hModule = NULL
|
||||
func executable() (exePath string, err error) {
|
||||
return getModuleFileName()
|
||||
}
|
||||
|
||||
func getModuleFileName() (string, error) {
|
||||
var n uint32
|
||||
b := make([]uint16, syscall.MAX_PATH)
|
||||
size := uint32(len(b))
|
||||
|
||||
r0, _, e1 := getModuleFileNameProc.Call(0, uintptr(unsafe.Pointer(&b[0])), uintptr(size))
|
||||
n = uint32(r0)
|
||||
if n == 0 {
|
||||
return "", e1
|
||||
}
|
||||
return string(utf16.Decode(b[0:n])), nil
|
||||
}
|
||||
35
Godeps/_workspace/src/code.google.com/p/go.crypto/bcrypt/base64.go
generated
vendored
Normal file
35
Godeps/_workspace/src/code.google.com/p/go.crypto/bcrypt/base64.go
generated
vendored
Normal file
@@ -0,0 +1,35 @@
|
||||
// Copyright 2011 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package bcrypt
|
||||
|
||||
import "encoding/base64"
|
||||
|
||||
const alphabet = "./ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"
|
||||
|
||||
var bcEncoding = base64.NewEncoding(alphabet)
|
||||
|
||||
func base64Encode(src []byte) []byte {
|
||||
n := bcEncoding.EncodedLen(len(src))
|
||||
dst := make([]byte, n)
|
||||
bcEncoding.Encode(dst, src)
|
||||
for dst[n-1] == '=' {
|
||||
n--
|
||||
}
|
||||
return dst[:n]
|
||||
}
|
||||
|
||||
func base64Decode(src []byte) ([]byte, error) {
|
||||
numOfEquals := 4 - (len(src) % 4)
|
||||
for i := 0; i < numOfEquals; i++ {
|
||||
src = append(src, '=')
|
||||
}
|
||||
|
||||
dst := make([]byte, bcEncoding.DecodedLen(len(src)))
|
||||
n, err := bcEncoding.Decode(dst, src)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return dst[:n], nil
|
||||
}
|
||||
294
Godeps/_workspace/src/code.google.com/p/go.crypto/bcrypt/bcrypt.go
generated
vendored
Normal file
294
Godeps/_workspace/src/code.google.com/p/go.crypto/bcrypt/bcrypt.go
generated
vendored
Normal file
@@ -0,0 +1,294 @@
|
||||
// Copyright 2011 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// Package bcrypt implements Provos and Mazières's bcrypt adaptive hashing
|
||||
// algorithm. See http://www.usenix.org/event/usenix99/provos/provos.pdf
|
||||
package bcrypt
|
||||
|
||||
// The code is a port of Provos and Mazières's C implementation.
|
||||
import (
|
||||
"code.google.com/p/go.crypto/blowfish"
|
||||
"crypto/rand"
|
||||
"crypto/subtle"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"strconv"
|
||||
)
|
||||
|
||||
const (
|
||||
MinCost int = 4 // the minimum allowable cost as passed in to GenerateFromPassword
|
||||
MaxCost int = 31 // the maximum allowable cost as passed in to GenerateFromPassword
|
||||
DefaultCost int = 10 // the cost that will actually be set if a cost below MinCost is passed into GenerateFromPassword
|
||||
)
|
||||
|
||||
// The error returned from CompareHashAndPassword when a password and hash do
|
||||
// not match.
|
||||
var ErrMismatchedHashAndPassword = errors.New("crypto/bcrypt: hashedPassword is not the hash of the given password")
|
||||
|
||||
// The error returned from CompareHashAndPassword when a hash is too short to
|
||||
// be a bcrypt hash.
|
||||
var ErrHashTooShort = errors.New("crypto/bcrypt: hashedSecret too short to be a bcrypted password")
|
||||
|
||||
// The error returned from CompareHashAndPassword when a hash was created with
|
||||
// a bcrypt algorithm newer than this implementation.
|
||||
type HashVersionTooNewError byte
|
||||
|
||||
func (hv HashVersionTooNewError) Error() string {
|
||||
return fmt.Sprintf("crypto/bcrypt: bcrypt algorithm version '%c' requested is newer than current version '%c'", byte(hv), majorVersion)
|
||||
}
|
||||
|
||||
// The error returned from CompareHashAndPassword when a hash starts with something other than '$'
|
||||
type InvalidHashPrefixError byte
|
||||
|
||||
func (ih InvalidHashPrefixError) Error() string {
|
||||
return fmt.Sprintf("crypto/bcrypt: bcrypt hashes must start with '$', but hashedSecret started with '%c'", byte(ih))
|
||||
}
|
||||
|
||||
type InvalidCostError int
|
||||
|
||||
func (ic InvalidCostError) Error() string {
|
||||
return fmt.Sprintf("crypto/bcrypt: cost %d is outside allowed range (%d,%d)", int(ic), int(MinCost), int(MaxCost))
|
||||
}
|
||||
|
||||
const (
|
||||
majorVersion = '2'
|
||||
minorVersion = 'a'
|
||||
maxSaltSize = 16
|
||||
maxCryptedHashSize = 23
|
||||
encodedSaltSize = 22
|
||||
encodedHashSize = 31
|
||||
minHashSize = 59
|
||||
)
|
||||
|
||||
// magicCipherData is an IV for the 64 Blowfish encryption calls in
|
||||
// bcrypt(). It's the string "OrpheanBeholderScryDoubt" in big-endian bytes.
|
||||
var magicCipherData = []byte{
|
||||
0x4f, 0x72, 0x70, 0x68,
|
||||
0x65, 0x61, 0x6e, 0x42,
|
||||
0x65, 0x68, 0x6f, 0x6c,
|
||||
0x64, 0x65, 0x72, 0x53,
|
||||
0x63, 0x72, 0x79, 0x44,
|
||||
0x6f, 0x75, 0x62, 0x74,
|
||||
}
|
||||
|
||||
type hashed struct {
|
||||
hash []byte
|
||||
salt []byte
|
||||
cost int // allowed range is MinCost to MaxCost
|
||||
major byte
|
||||
minor byte
|
||||
}
|
||||
|
||||
// GenerateFromPassword returns the bcrypt hash of the password at the given
|
||||
// cost. If the cost given is less than MinCost, the cost will be set to
|
||||
// DefaultCost, instead. Use CompareHashAndPassword, as defined in this package,
|
||||
// to compare the returned hashed password with its cleartext version.
|
||||
func GenerateFromPassword(password []byte, cost int) ([]byte, error) {
|
||||
p, err := newFromPassword(password, cost)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return p.Hash(), nil
|
||||
}
|
||||
|
||||
// CompareHashAndPassword compares a bcrypt hashed password with its possible
|
||||
// plaintext equivalent. Returns nil on success, or an error on failure.
|
||||
func CompareHashAndPassword(hashedPassword, password []byte) error {
|
||||
p, err := newFromHash(hashedPassword)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
otherHash, err := bcrypt(password, p.cost, p.salt)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
otherP := &hashed{otherHash, p.salt, p.cost, p.major, p.minor}
|
||||
if subtle.ConstantTimeCompare(p.Hash(), otherP.Hash()) == 1 {
|
||||
return nil
|
||||
}
|
||||
|
||||
return ErrMismatchedHashAndPassword
|
||||
}
|
||||
|
||||
// Cost returns the hashing cost used to create the given hashed
|
||||
// password. When, in the future, the hashing cost of a password system needs
|
||||
// to be increased in order to adjust for greater computational power, this
|
||||
// function allows one to establish which passwords need to be updated.
|
||||
func Cost(hashedPassword []byte) (int, error) {
|
||||
p, err := newFromHash(hashedPassword)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return p.cost, nil
|
||||
}
|
||||
|
||||
func newFromPassword(password []byte, cost int) (*hashed, error) {
|
||||
if cost < MinCost {
|
||||
cost = DefaultCost
|
||||
}
|
||||
p := new(hashed)
|
||||
p.major = majorVersion
|
||||
p.minor = minorVersion
|
||||
|
||||
err := checkCost(cost)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
p.cost = cost
|
||||
|
||||
unencodedSalt := make([]byte, maxSaltSize)
|
||||
_, err = io.ReadFull(rand.Reader, unencodedSalt)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
p.salt = base64Encode(unencodedSalt)
|
||||
hash, err := bcrypt(password, p.cost, p.salt)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
p.hash = hash
|
||||
return p, err
|
||||
}
|
||||
|
||||
func newFromHash(hashedSecret []byte) (*hashed, error) {
|
||||
if len(hashedSecret) < minHashSize {
|
||||
return nil, ErrHashTooShort
|
||||
}
|
||||
p := new(hashed)
|
||||
n, err := p.decodeVersion(hashedSecret)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
hashedSecret = hashedSecret[n:]
|
||||
n, err = p.decodeCost(hashedSecret)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
hashedSecret = hashedSecret[n:]
|
||||
|
||||
// The "+2" is here because we'll have to append at most 2 '=' to the salt
|
||||
// when base64 decoding it in expensiveBlowfishSetup().
|
||||
p.salt = make([]byte, encodedSaltSize, encodedSaltSize+2)
|
||||
copy(p.salt, hashedSecret[:encodedSaltSize])
|
||||
|
||||
hashedSecret = hashedSecret[encodedSaltSize:]
|
||||
p.hash = make([]byte, len(hashedSecret))
|
||||
copy(p.hash, hashedSecret)
|
||||
|
||||
return p, nil
|
||||
}
|
||||
|
||||
func bcrypt(password []byte, cost int, salt []byte) ([]byte, error) {
|
||||
cipherData := make([]byte, len(magicCipherData))
|
||||
copy(cipherData, magicCipherData)
|
||||
|
||||
c, err := expensiveBlowfishSetup(password, uint32(cost), salt)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
for i := 0; i < 24; i += 8 {
|
||||
for j := 0; j < 64; j++ {
|
||||
c.Encrypt(cipherData[i:i+8], cipherData[i:i+8])
|
||||
}
|
||||
}
|
||||
|
||||
// Bug compatibility with C bcrypt implementations. We only encode 23 of
|
||||
// the 24 bytes encrypted.
|
||||
hsh := base64Encode(cipherData[:maxCryptedHashSize])
|
||||
return hsh, nil
|
||||
}
|
||||
|
||||
func expensiveBlowfishSetup(key []byte, cost uint32, salt []byte) (*blowfish.Cipher, error) {
|
||||
|
||||
csalt, err := base64Decode(salt)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Bug compatibility with C bcrypt implementations. They use the trailing
|
||||
// NULL in the key string during expansion.
|
||||
ckey := append(key, 0)
|
||||
|
||||
c, err := blowfish.NewSaltedCipher(ckey, csalt)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var i, rounds uint64
|
||||
rounds = 1 << cost
|
||||
for i = 0; i < rounds; i++ {
|
||||
blowfish.ExpandKey(ckey, c)
|
||||
blowfish.ExpandKey(csalt, c)
|
||||
}
|
||||
|
||||
return c, nil
|
||||
}
|
||||
|
||||
func (p *hashed) Hash() []byte {
|
||||
arr := make([]byte, 60)
|
||||
arr[0] = '$'
|
||||
arr[1] = p.major
|
||||
n := 2
|
||||
if p.minor != 0 {
|
||||
arr[2] = p.minor
|
||||
n = 3
|
||||
}
|
||||
arr[n] = '$'
|
||||
n += 1
|
||||
copy(arr[n:], []byte(fmt.Sprintf("%02d", p.cost)))
|
||||
n += 2
|
||||
arr[n] = '$'
|
||||
n += 1
|
||||
copy(arr[n:], p.salt)
|
||||
n += encodedSaltSize
|
||||
copy(arr[n:], p.hash)
|
||||
n += encodedHashSize
|
||||
return arr[:n]
|
||||
}
|
||||
|
||||
func (p *hashed) decodeVersion(sbytes []byte) (int, error) {
|
||||
if sbytes[0] != '$' {
|
||||
return -1, InvalidHashPrefixError(sbytes[0])
|
||||
}
|
||||
if sbytes[1] > majorVersion {
|
||||
return -1, HashVersionTooNewError(sbytes[1])
|
||||
}
|
||||
p.major = sbytes[1]
|
||||
n := 3
|
||||
if sbytes[2] != '$' {
|
||||
p.minor = sbytes[2]
|
||||
n++
|
||||
}
|
||||
return n, nil
|
||||
}
|
||||
|
||||
// sbytes should begin where decodeVersion left off.
|
||||
func (p *hashed) decodeCost(sbytes []byte) (int, error) {
|
||||
cost, err := strconv.Atoi(string(sbytes[0:2]))
|
||||
if err != nil {
|
||||
return -1, err
|
||||
}
|
||||
err = checkCost(cost)
|
||||
if err != nil {
|
||||
return -1, err
|
||||
}
|
||||
p.cost = cost
|
||||
return 3, nil
|
||||
}
|
||||
|
||||
func (p *hashed) String() string {
|
||||
return fmt.Sprintf("&{hash: %#v, salt: %#v, cost: %d, major: %c, minor: %c}", string(p.hash), p.salt, p.cost, p.major, p.minor)
|
||||
}
|
||||
|
||||
func checkCost(cost int) error {
|
||||
if cost < MinCost || cost > MaxCost {
|
||||
return InvalidCostError(cost)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
226
Godeps/_workspace/src/code.google.com/p/go.crypto/bcrypt/bcrypt_test.go
generated
vendored
Normal file
226
Godeps/_workspace/src/code.google.com/p/go.crypto/bcrypt/bcrypt_test.go
generated
vendored
Normal file
@@ -0,0 +1,226 @@
|
||||
// Copyright 2011 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package bcrypt
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestBcryptingIsEasy(t *testing.T) {
|
||||
pass := []byte("mypassword")
|
||||
hp, err := GenerateFromPassword(pass, 0)
|
||||
if err != nil {
|
||||
t.Fatalf("GenerateFromPassword error: %s", err)
|
||||
}
|
||||
|
||||
if CompareHashAndPassword(hp, pass) != nil {
|
||||
t.Errorf("%v should hash %s correctly", hp, pass)
|
||||
}
|
||||
|
||||
notPass := "notthepass"
|
||||
err = CompareHashAndPassword(hp, []byte(notPass))
|
||||
if err != ErrMismatchedHashAndPassword {
|
||||
t.Errorf("%v and %s should be mismatched", hp, notPass)
|
||||
}
|
||||
}
|
||||
|
||||
func TestBcryptingIsCorrect(t *testing.T) {
|
||||
pass := []byte("allmine")
|
||||
salt := []byte("XajjQvNhvvRt5GSeFk1xFe")
|
||||
expectedHash := []byte("$2a$10$XajjQvNhvvRt5GSeFk1xFeyqRrsxkhBkUiQeg0dt.wU1qD4aFDcga")
|
||||
|
||||
hash, err := bcrypt(pass, 10, salt)
|
||||
if err != nil {
|
||||
t.Fatalf("bcrypt blew up: %v", err)
|
||||
}
|
||||
if !bytes.HasSuffix(expectedHash, hash) {
|
||||
t.Errorf("%v should be the suffix of %v", hash, expectedHash)
|
||||
}
|
||||
|
||||
h, err := newFromHash(expectedHash)
|
||||
if err != nil {
|
||||
t.Errorf("Unable to parse %s: %v", string(expectedHash), err)
|
||||
}
|
||||
|
||||
// This is not the safe way to compare these hashes. We do this only for
|
||||
// testing clarity. Use bcrypt.CompareHashAndPassword()
|
||||
if err == nil && !bytes.Equal(expectedHash, h.Hash()) {
|
||||
t.Errorf("Parsed hash %v should equal %v", h.Hash(), expectedHash)
|
||||
}
|
||||
}
|
||||
|
||||
func TestVeryShortPasswords(t *testing.T) {
|
||||
key := []byte("k")
|
||||
salt := []byte("XajjQvNhvvRt5GSeFk1xFe")
|
||||
_, err := bcrypt(key, 10, salt)
|
||||
if err != nil {
|
||||
t.Errorf("One byte key resulted in error: %s", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestTooLongPasswordsWork(t *testing.T) {
|
||||
salt := []byte("XajjQvNhvvRt5GSeFk1xFe")
|
||||
// One byte over the usual 56 byte limit that blowfish has
|
||||
tooLongPass := []byte("012345678901234567890123456789012345678901234567890123456")
|
||||
tooLongExpected := []byte("$2a$10$XajjQvNhvvRt5GSeFk1xFe5l47dONXg781AmZtd869sO8zfsHuw7C")
|
||||
hash, err := bcrypt(tooLongPass, 10, salt)
|
||||
if err != nil {
|
||||
t.Fatalf("bcrypt blew up on long password: %v", err)
|
||||
}
|
||||
if !bytes.HasSuffix(tooLongExpected, hash) {
|
||||
t.Errorf("%v should be the suffix of %v", hash, tooLongExpected)
|
||||
}
|
||||
}
|
||||
|
||||
type InvalidHashTest struct {
|
||||
err error
|
||||
hash []byte
|
||||
}
|
||||
|
||||
var invalidTests = []InvalidHashTest{
|
||||
{ErrHashTooShort, []byte("$2a$10$fooo")},
|
||||
{ErrHashTooShort, []byte("$2a")},
|
||||
{HashVersionTooNewError('3'), []byte("$3a$10$sssssssssssssssssssssshhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh")},
|
||||
{InvalidHashPrefixError('%'), []byte("%2a$10$sssssssssssssssssssssshhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh")},
|
||||
{InvalidCostError(32), []byte("$2a$32$sssssssssssssssssssssshhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh")},
|
||||
}
|
||||
|
||||
func TestInvalidHashErrors(t *testing.T) {
|
||||
check := func(name string, expected, err error) {
|
||||
if err == nil {
|
||||
t.Errorf("%s: Should have returned an error", name)
|
||||
}
|
||||
if err != nil && err != expected {
|
||||
t.Errorf("%s gave err %v but should have given %v", name, err, expected)
|
||||
}
|
||||
}
|
||||
for _, iht := range invalidTests {
|
||||
_, err := newFromHash(iht.hash)
|
||||
check("newFromHash", iht.err, err)
|
||||
err = CompareHashAndPassword(iht.hash, []byte("anything"))
|
||||
check("CompareHashAndPassword", iht.err, err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestUnpaddedBase64Encoding(t *testing.T) {
|
||||
original := []byte{101, 201, 101, 75, 19, 227, 199, 20, 239, 236, 133, 32, 30, 109, 243, 30}
|
||||
encodedOriginal := []byte("XajjQvNhvvRt5GSeFk1xFe")
|
||||
|
||||
encoded := base64Encode(original)
|
||||
|
||||
if !bytes.Equal(encodedOriginal, encoded) {
|
||||
t.Errorf("Encoded %v should have equaled %v", encoded, encodedOriginal)
|
||||
}
|
||||
|
||||
decoded, err := base64Decode(encodedOriginal)
|
||||
if err != nil {
|
||||
t.Fatalf("base64Decode blew up: %s", err)
|
||||
}
|
||||
|
||||
if !bytes.Equal(decoded, original) {
|
||||
t.Errorf("Decoded %v should have equaled %v", decoded, original)
|
||||
}
|
||||
}
|
||||
|
||||
func TestCost(t *testing.T) {
|
||||
suffix := "XajjQvNhvvRt5GSeFk1xFe5l47dONXg781AmZtd869sO8zfsHuw7C"
|
||||
for _, vers := range []string{"2a", "2"} {
|
||||
for _, cost := range []int{4, 10} {
|
||||
s := fmt.Sprintf("$%s$%02d$%s", vers, cost, suffix)
|
||||
h := []byte(s)
|
||||
actual, err := Cost(h)
|
||||
if err != nil {
|
||||
t.Errorf("Cost, error: %s", err)
|
||||
continue
|
||||
}
|
||||
if actual != cost {
|
||||
t.Errorf("Cost, expected: %d, actual: %d", cost, actual)
|
||||
}
|
||||
}
|
||||
}
|
||||
_, err := Cost([]byte("$a$a$" + suffix))
|
||||
if err == nil {
|
||||
t.Errorf("Cost, malformed but no error returned")
|
||||
}
|
||||
}
|
||||
|
||||
func TestCostValidationInHash(t *testing.T) {
|
||||
if testing.Short() {
|
||||
return
|
||||
}
|
||||
|
||||
pass := []byte("mypassword")
|
||||
|
||||
for c := 0; c < MinCost; c++ {
|
||||
p, _ := newFromPassword(pass, c)
|
||||
if p.cost != DefaultCost {
|
||||
t.Errorf("newFromPassword should default costs below %d to %d, but was %d", MinCost, DefaultCost, p.cost)
|
||||
}
|
||||
}
|
||||
|
||||
p, _ := newFromPassword(pass, 14)
|
||||
if p.cost != 14 {
|
||||
t.Errorf("newFromPassword should default cost to 14, but was %d", p.cost)
|
||||
}
|
||||
|
||||
hp, _ := newFromHash(p.Hash())
|
||||
if p.cost != hp.cost {
|
||||
t.Errorf("newFromHash should maintain the cost at %d, but was %d", p.cost, hp.cost)
|
||||
}
|
||||
|
||||
_, err := newFromPassword(pass, 32)
|
||||
if err == nil {
|
||||
t.Fatalf("newFromPassword: should return a cost error")
|
||||
}
|
||||
if err != InvalidCostError(32) {
|
||||
t.Errorf("newFromPassword: should return cost error, got %#v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestCostReturnsWithLeadingZeroes(t *testing.T) {
|
||||
hp, _ := newFromPassword([]byte("abcdefgh"), 7)
|
||||
cost := hp.Hash()[4:7]
|
||||
expected := []byte("07$")
|
||||
|
||||
if !bytes.Equal(expected, cost) {
|
||||
t.Errorf("single digit costs in hash should have leading zeros: was %v instead of %v", cost, expected)
|
||||
}
|
||||
}
|
||||
|
||||
func TestMinorNotRequired(t *testing.T) {
|
||||
noMinorHash := []byte("$2$10$XajjQvNhvvRt5GSeFk1xFeyqRrsxkhBkUiQeg0dt.wU1qD4aFDcga")
|
||||
h, err := newFromHash(noMinorHash)
|
||||
if err != nil {
|
||||
t.Fatalf("No minor hash blew up: %s", err)
|
||||
}
|
||||
if h.minor != 0 {
|
||||
t.Errorf("Should leave minor version at 0, but was %d", h.minor)
|
||||
}
|
||||
|
||||
if !bytes.Equal(noMinorHash, h.Hash()) {
|
||||
t.Errorf("Should generate hash %v, but created %v", noMinorHash, h.Hash())
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkEqual(b *testing.B) {
|
||||
b.StopTimer()
|
||||
passwd := []byte("somepasswordyoulike")
|
||||
hash, _ := GenerateFromPassword(passwd, 10)
|
||||
b.StartTimer()
|
||||
for i := 0; i < b.N; i++ {
|
||||
CompareHashAndPassword(hash, passwd)
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkGeneration(b *testing.B) {
|
||||
b.StopTimer()
|
||||
passwd := []byte("mylongpassword1234")
|
||||
b.StartTimer()
|
||||
for i := 0; i < b.N; i++ {
|
||||
GenerateFromPassword(passwd, 10)
|
||||
}
|
||||
}
|
||||
190
Godeps/_workspace/src/code.google.com/p/go.crypto/blowfish/block.go
generated
vendored
Normal file
190
Godeps/_workspace/src/code.google.com/p/go.crypto/blowfish/block.go
generated
vendored
Normal file
@@ -0,0 +1,190 @@
|
||||
// Copyright 2010 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package blowfish
|
||||
|
||||
// ExpandKey performs a key expansion on the given *Cipher. Specifically, it
|
||||
// performs the Blowfish algorithm's key schedule which sets up the *Cipher's
|
||||
// pi and substitution tables for calls to Encrypt. This is used, primarily,
|
||||
// by the bcrypt package to reuse the Blowfish key schedule during its
|
||||
// set up. It's unlikely that you need to use this directly.
|
||||
func ExpandKey(key []byte, c *Cipher) {
|
||||
j := 0
|
||||
for i := 0; i < 18; i++ {
|
||||
var d uint32
|
||||
for k := 0; k < 4; k++ {
|
||||
d = d<<8 | uint32(key[j])
|
||||
j++
|
||||
if j >= len(key) {
|
||||
j = 0
|
||||
}
|
||||
}
|
||||
c.p[i] ^= d
|
||||
}
|
||||
|
||||
var l, r uint32
|
||||
for i := 0; i < 18; i += 2 {
|
||||
l, r = encryptBlock(l, r, c)
|
||||
c.p[i], c.p[i+1] = l, r
|
||||
}
|
||||
|
||||
for i := 0; i < 256; i += 2 {
|
||||
l, r = encryptBlock(l, r, c)
|
||||
c.s0[i], c.s0[i+1] = l, r
|
||||
}
|
||||
for i := 0; i < 256; i += 2 {
|
||||
l, r = encryptBlock(l, r, c)
|
||||
c.s1[i], c.s1[i+1] = l, r
|
||||
}
|
||||
for i := 0; i < 256; i += 2 {
|
||||
l, r = encryptBlock(l, r, c)
|
||||
c.s2[i], c.s2[i+1] = l, r
|
||||
}
|
||||
for i := 0; i < 256; i += 2 {
|
||||
l, r = encryptBlock(l, r, c)
|
||||
c.s3[i], c.s3[i+1] = l, r
|
||||
}
|
||||
}
|
||||
|
||||
// This is similar to ExpandKey, but folds the salt during the key
|
||||
// schedule. While ExpandKey is essentially expandKeyWithSalt with an all-zero
|
||||
// salt passed in, reusing ExpandKey turns out to be a place of inefficiency
|
||||
// and specializing it here is useful.
|
||||
func expandKeyWithSalt(key []byte, salt []byte, c *Cipher) {
|
||||
j := 0
|
||||
for i := 0; i < 18; i++ {
|
||||
var d uint32
|
||||
for k := 0; k < 4; k++ {
|
||||
d = d<<8 | uint32(key[j])
|
||||
j++
|
||||
if j >= len(key) {
|
||||
j = 0
|
||||
}
|
||||
}
|
||||
c.p[i] ^= d
|
||||
}
|
||||
|
||||
j = 0
|
||||
var expandedSalt [4]uint32
|
||||
for i := range expandedSalt {
|
||||
var d uint32
|
||||
for k := 0; k < 4; k++ {
|
||||
d = d<<8 | uint32(salt[j])
|
||||
j++
|
||||
if j >= len(salt) {
|
||||
j = 0
|
||||
}
|
||||
}
|
||||
expandedSalt[i] = d
|
||||
}
|
||||
|
||||
var l, r uint32
|
||||
for i := 0; i < 18; i += 2 {
|
||||
l ^= expandedSalt[i&2]
|
||||
r ^= expandedSalt[(i&2)+1]
|
||||
l, r = encryptBlock(l, r, c)
|
||||
c.p[i], c.p[i+1] = l, r
|
||||
}
|
||||
|
||||
for i := 0; i < 256; i += 4 {
|
||||
l ^= expandedSalt[2]
|
||||
r ^= expandedSalt[3]
|
||||
l, r = encryptBlock(l, r, c)
|
||||
c.s0[i], c.s0[i+1] = l, r
|
||||
|
||||
l ^= expandedSalt[0]
|
||||
r ^= expandedSalt[1]
|
||||
l, r = encryptBlock(l, r, c)
|
||||
c.s0[i+2], c.s0[i+3] = l, r
|
||||
|
||||
}
|
||||
|
||||
for i := 0; i < 256; i += 4 {
|
||||
l ^= expandedSalt[2]
|
||||
r ^= expandedSalt[3]
|
||||
l, r = encryptBlock(l, r, c)
|
||||
c.s1[i], c.s1[i+1] = l, r
|
||||
|
||||
l ^= expandedSalt[0]
|
||||
r ^= expandedSalt[1]
|
||||
l, r = encryptBlock(l, r, c)
|
||||
c.s1[i+2], c.s1[i+3] = l, r
|
||||
}
|
||||
|
||||
for i := 0; i < 256; i += 4 {
|
||||
l ^= expandedSalt[2]
|
||||
r ^= expandedSalt[3]
|
||||
l, r = encryptBlock(l, r, c)
|
||||
c.s2[i], c.s2[i+1] = l, r
|
||||
|
||||
l ^= expandedSalt[0]
|
||||
r ^= expandedSalt[1]
|
||||
l, r = encryptBlock(l, r, c)
|
||||
c.s2[i+2], c.s2[i+3] = l, r
|
||||
}
|
||||
|
||||
for i := 0; i < 256; i += 4 {
|
||||
l ^= expandedSalt[2]
|
||||
r ^= expandedSalt[3]
|
||||
l, r = encryptBlock(l, r, c)
|
||||
c.s3[i], c.s3[i+1] = l, r
|
||||
|
||||
l ^= expandedSalt[0]
|
||||
r ^= expandedSalt[1]
|
||||
l, r = encryptBlock(l, r, c)
|
||||
c.s3[i+2], c.s3[i+3] = l, r
|
||||
}
|
||||
}
|
||||
|
||||
func encryptBlock(l, r uint32, c *Cipher) (uint32, uint32) {
|
||||
xl, xr := l, r
|
||||
xl ^= c.p[0]
|
||||
xr ^= ((c.s0[byte(xl>>24)] + c.s1[byte(xl>>16)]) ^ c.s2[byte(xl>>8)]) + c.s3[byte(xl)] ^ c.p[1]
|
||||
xl ^= ((c.s0[byte(xr>>24)] + c.s1[byte(xr>>16)]) ^ c.s2[byte(xr>>8)]) + c.s3[byte(xr)] ^ c.p[2]
|
||||
xr ^= ((c.s0[byte(xl>>24)] + c.s1[byte(xl>>16)]) ^ c.s2[byte(xl>>8)]) + c.s3[byte(xl)] ^ c.p[3]
|
||||
xl ^= ((c.s0[byte(xr>>24)] + c.s1[byte(xr>>16)]) ^ c.s2[byte(xr>>8)]) + c.s3[byte(xr)] ^ c.p[4]
|
||||
xr ^= ((c.s0[byte(xl>>24)] + c.s1[byte(xl>>16)]) ^ c.s2[byte(xl>>8)]) + c.s3[byte(xl)] ^ c.p[5]
|
||||
xl ^= ((c.s0[byte(xr>>24)] + c.s1[byte(xr>>16)]) ^ c.s2[byte(xr>>8)]) + c.s3[byte(xr)] ^ c.p[6]
|
||||
xr ^= ((c.s0[byte(xl>>24)] + c.s1[byte(xl>>16)]) ^ c.s2[byte(xl>>8)]) + c.s3[byte(xl)] ^ c.p[7]
|
||||
xl ^= ((c.s0[byte(xr>>24)] + c.s1[byte(xr>>16)]) ^ c.s2[byte(xr>>8)]) + c.s3[byte(xr)] ^ c.p[8]
|
||||
xr ^= ((c.s0[byte(xl>>24)] + c.s1[byte(xl>>16)]) ^ c.s2[byte(xl>>8)]) + c.s3[byte(xl)] ^ c.p[9]
|
||||
xl ^= ((c.s0[byte(xr>>24)] + c.s1[byte(xr>>16)]) ^ c.s2[byte(xr>>8)]) + c.s3[byte(xr)] ^ c.p[10]
|
||||
xr ^= ((c.s0[byte(xl>>24)] + c.s1[byte(xl>>16)]) ^ c.s2[byte(xl>>8)]) + c.s3[byte(xl)] ^ c.p[11]
|
||||
xl ^= ((c.s0[byte(xr>>24)] + c.s1[byte(xr>>16)]) ^ c.s2[byte(xr>>8)]) + c.s3[byte(xr)] ^ c.p[12]
|
||||
xr ^= ((c.s0[byte(xl>>24)] + c.s1[byte(xl>>16)]) ^ c.s2[byte(xl>>8)]) + c.s3[byte(xl)] ^ c.p[13]
|
||||
xl ^= ((c.s0[byte(xr>>24)] + c.s1[byte(xr>>16)]) ^ c.s2[byte(xr>>8)]) + c.s3[byte(xr)] ^ c.p[14]
|
||||
xr ^= ((c.s0[byte(xl>>24)] + c.s1[byte(xl>>16)]) ^ c.s2[byte(xl>>8)]) + c.s3[byte(xl)] ^ c.p[15]
|
||||
xl ^= ((c.s0[byte(xr>>24)] + c.s1[byte(xr>>16)]) ^ c.s2[byte(xr>>8)]) + c.s3[byte(xr)] ^ c.p[16]
|
||||
xr ^= c.p[17]
|
||||
return xr, xl
|
||||
}
|
||||
|
||||
func decryptBlock(l, r uint32, c *Cipher) (uint32, uint32) {
|
||||
xl, xr := l, r
|
||||
xl ^= c.p[17]
|
||||
xr ^= ((c.s0[byte(xl>>24)] + c.s1[byte(xl>>16)]) ^ c.s2[byte(xl>>8)]) + c.s3[byte(xl)] ^ c.p[16]
|
||||
xl ^= ((c.s0[byte(xr>>24)] + c.s1[byte(xr>>16)]) ^ c.s2[byte(xr>>8)]) + c.s3[byte(xr)] ^ c.p[15]
|
||||
xr ^= ((c.s0[byte(xl>>24)] + c.s1[byte(xl>>16)]) ^ c.s2[byte(xl>>8)]) + c.s3[byte(xl)] ^ c.p[14]
|
||||
xl ^= ((c.s0[byte(xr>>24)] + c.s1[byte(xr>>16)]) ^ c.s2[byte(xr>>8)]) + c.s3[byte(xr)] ^ c.p[13]
|
||||
xr ^= ((c.s0[byte(xl>>24)] + c.s1[byte(xl>>16)]) ^ c.s2[byte(xl>>8)]) + c.s3[byte(xl)] ^ c.p[12]
|
||||
xl ^= ((c.s0[byte(xr>>24)] + c.s1[byte(xr>>16)]) ^ c.s2[byte(xr>>8)]) + c.s3[byte(xr)] ^ c.p[11]
|
||||
xr ^= ((c.s0[byte(xl>>24)] + c.s1[byte(xl>>16)]) ^ c.s2[byte(xl>>8)]) + c.s3[byte(xl)] ^ c.p[10]
|
||||
xl ^= ((c.s0[byte(xr>>24)] + c.s1[byte(xr>>16)]) ^ c.s2[byte(xr>>8)]) + c.s3[byte(xr)] ^ c.p[9]
|
||||
xr ^= ((c.s0[byte(xl>>24)] + c.s1[byte(xl>>16)]) ^ c.s2[byte(xl>>8)]) + c.s3[byte(xl)] ^ c.p[8]
|
||||
xl ^= ((c.s0[byte(xr>>24)] + c.s1[byte(xr>>16)]) ^ c.s2[byte(xr>>8)]) + c.s3[byte(xr)] ^ c.p[7]
|
||||
xr ^= ((c.s0[byte(xl>>24)] + c.s1[byte(xl>>16)]) ^ c.s2[byte(xl>>8)]) + c.s3[byte(xl)] ^ c.p[6]
|
||||
xl ^= ((c.s0[byte(xr>>24)] + c.s1[byte(xr>>16)]) ^ c.s2[byte(xr>>8)]) + c.s3[byte(xr)] ^ c.p[5]
|
||||
xr ^= ((c.s0[byte(xl>>24)] + c.s1[byte(xl>>16)]) ^ c.s2[byte(xl>>8)]) + c.s3[byte(xl)] ^ c.p[4]
|
||||
xl ^= ((c.s0[byte(xr>>24)] + c.s1[byte(xr>>16)]) ^ c.s2[byte(xr>>8)]) + c.s3[byte(xr)] ^ c.p[3]
|
||||
xr ^= ((c.s0[byte(xl>>24)] + c.s1[byte(xl>>16)]) ^ c.s2[byte(xl>>8)]) + c.s3[byte(xl)] ^ c.p[2]
|
||||
xl ^= ((c.s0[byte(xr>>24)] + c.s1[byte(xr>>16)]) ^ c.s2[byte(xr>>8)]) + c.s3[byte(xr)] ^ c.p[1]
|
||||
xr ^= c.p[0]
|
||||
return xr, xl
|
||||
}
|
||||
|
||||
func zero(x []uint32) {
|
||||
for i := range x {
|
||||
x[i] = 0
|
||||
}
|
||||
}
|
||||
204
Godeps/_workspace/src/code.google.com/p/go.crypto/blowfish/blowfish_test.go
generated
vendored
Normal file
204
Godeps/_workspace/src/code.google.com/p/go.crypto/blowfish/blowfish_test.go
generated
vendored
Normal file
@@ -0,0 +1,204 @@
|
||||
// Copyright 2010 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package blowfish
|
||||
|
||||
import (
|
||||
"testing"
|
||||
)
|
||||
|
||||
type CryptTest struct {
|
||||
key []byte
|
||||
in []byte
|
||||
out []byte
|
||||
}
|
||||
|
||||
// Test vector values are from http://www.schneier.com/code/vectors.txt.
|
||||
var encryptTests = []CryptTest{
|
||||
{
|
||||
[]byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
|
||||
[]byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
|
||||
[]byte{0x4E, 0xF9, 0x97, 0x45, 0x61, 0x98, 0xDD, 0x78}},
|
||||
{
|
||||
[]byte{0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF},
|
||||
[]byte{0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF},
|
||||
[]byte{0x51, 0x86, 0x6F, 0xD5, 0xB8, 0x5E, 0xCB, 0x8A}},
|
||||
{
|
||||
[]byte{0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
|
||||
[]byte{0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01},
|
||||
[]byte{0x7D, 0x85, 0x6F, 0x9A, 0x61, 0x30, 0x63, 0xF2}},
|
||||
{
|
||||
[]byte{0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11},
|
||||
[]byte{0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11},
|
||||
[]byte{0x24, 0x66, 0xDD, 0x87, 0x8B, 0x96, 0x3C, 0x9D}},
|
||||
|
||||
{
|
||||
[]byte{0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF},
|
||||
[]byte{0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11},
|
||||
[]byte{0x61, 0xF9, 0xC3, 0x80, 0x22, 0x81, 0xB0, 0x96}},
|
||||
{
|
||||
[]byte{0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11},
|
||||
[]byte{0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF},
|
||||
[]byte{0x7D, 0x0C, 0xC6, 0x30, 0xAF, 0xDA, 0x1E, 0xC7}},
|
||||
{
|
||||
[]byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
|
||||
[]byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
|
||||
[]byte{0x4E, 0xF9, 0x97, 0x45, 0x61, 0x98, 0xDD, 0x78}},
|
||||
{
|
||||
[]byte{0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10},
|
||||
[]byte{0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF},
|
||||
[]byte{0x0A, 0xCE, 0xAB, 0x0F, 0xC6, 0xA0, 0xA2, 0x8D}},
|
||||
{
|
||||
[]byte{0x7C, 0xA1, 0x10, 0x45, 0x4A, 0x1A, 0x6E, 0x57},
|
||||
[]byte{0x01, 0xA1, 0xD6, 0xD0, 0x39, 0x77, 0x67, 0x42},
|
||||
[]byte{0x59, 0xC6, 0x82, 0x45, 0xEB, 0x05, 0x28, 0x2B}},
|
||||
{
|
||||
[]byte{0x01, 0x31, 0xD9, 0x61, 0x9D, 0xC1, 0x37, 0x6E},
|
||||
[]byte{0x5C, 0xD5, 0x4C, 0xA8, 0x3D, 0xEF, 0x57, 0xDA},
|
||||
[]byte{0xB1, 0xB8, 0xCC, 0x0B, 0x25, 0x0F, 0x09, 0xA0}},
|
||||
{
|
||||
[]byte{0x07, 0xA1, 0x13, 0x3E, 0x4A, 0x0B, 0x26, 0x86},
|
||||
[]byte{0x02, 0x48, 0xD4, 0x38, 0x06, 0xF6, 0x71, 0x72},
|
||||
[]byte{0x17, 0x30, 0xE5, 0x77, 0x8B, 0xEA, 0x1D, 0xA4}},
|
||||
{
|
||||
[]byte{0x38, 0x49, 0x67, 0x4C, 0x26, 0x02, 0x31, 0x9E},
|
||||
[]byte{0x51, 0x45, 0x4B, 0x58, 0x2D, 0xDF, 0x44, 0x0A},
|
||||
[]byte{0xA2, 0x5E, 0x78, 0x56, 0xCF, 0x26, 0x51, 0xEB}},
|
||||
{
|
||||
[]byte{0x04, 0xB9, 0x15, 0xBA, 0x43, 0xFE, 0xB5, 0xB6},
|
||||
[]byte{0x42, 0xFD, 0x44, 0x30, 0x59, 0x57, 0x7F, 0xA2},
|
||||
[]byte{0x35, 0x38, 0x82, 0xB1, 0x09, 0xCE, 0x8F, 0x1A}},
|
||||
{
|
||||
[]byte{0x01, 0x13, 0xB9, 0x70, 0xFD, 0x34, 0xF2, 0xCE},
|
||||
[]byte{0x05, 0x9B, 0x5E, 0x08, 0x51, 0xCF, 0x14, 0x3A},
|
||||
[]byte{0x48, 0xF4, 0xD0, 0x88, 0x4C, 0x37, 0x99, 0x18}},
|
||||
{
|
||||
[]byte{0x01, 0x70, 0xF1, 0x75, 0x46, 0x8F, 0xB5, 0xE6},
|
||||
[]byte{0x07, 0x56, 0xD8, 0xE0, 0x77, 0x47, 0x61, 0xD2},
|
||||
[]byte{0x43, 0x21, 0x93, 0xB7, 0x89, 0x51, 0xFC, 0x98}},
|
||||
{
|
||||
[]byte{0x43, 0x29, 0x7F, 0xAD, 0x38, 0xE3, 0x73, 0xFE},
|
||||
[]byte{0x76, 0x25, 0x14, 0xB8, 0x29, 0xBF, 0x48, 0x6A},
|
||||
[]byte{0x13, 0xF0, 0x41, 0x54, 0xD6, 0x9D, 0x1A, 0xE5}},
|
||||
{
|
||||
[]byte{0x07, 0xA7, 0x13, 0x70, 0x45, 0xDA, 0x2A, 0x16},
|
||||
[]byte{0x3B, 0xDD, 0x11, 0x90, 0x49, 0x37, 0x28, 0x02},
|
||||
[]byte{0x2E, 0xED, 0xDA, 0x93, 0xFF, 0xD3, 0x9C, 0x79}},
|
||||
{
|
||||
[]byte{0x04, 0x68, 0x91, 0x04, 0xC2, 0xFD, 0x3B, 0x2F},
|
||||
[]byte{0x26, 0x95, 0x5F, 0x68, 0x35, 0xAF, 0x60, 0x9A},
|
||||
[]byte{0xD8, 0x87, 0xE0, 0x39, 0x3C, 0x2D, 0xA6, 0xE3}},
|
||||
{
|
||||
[]byte{0x37, 0xD0, 0x6B, 0xB5, 0x16, 0xCB, 0x75, 0x46},
|
||||
[]byte{0x16, 0x4D, 0x5E, 0x40, 0x4F, 0x27, 0x52, 0x32},
|
||||
[]byte{0x5F, 0x99, 0xD0, 0x4F, 0x5B, 0x16, 0x39, 0x69}},
|
||||
{
|
||||
[]byte{0x1F, 0x08, 0x26, 0x0D, 0x1A, 0xC2, 0x46, 0x5E},
|
||||
[]byte{0x6B, 0x05, 0x6E, 0x18, 0x75, 0x9F, 0x5C, 0xCA},
|
||||
[]byte{0x4A, 0x05, 0x7A, 0x3B, 0x24, 0xD3, 0x97, 0x7B}},
|
||||
{
|
||||
[]byte{0x58, 0x40, 0x23, 0x64, 0x1A, 0xBA, 0x61, 0x76},
|
||||
[]byte{0x00, 0x4B, 0xD6, 0xEF, 0x09, 0x17, 0x60, 0x62},
|
||||
[]byte{0x45, 0x20, 0x31, 0xC1, 0xE4, 0xFA, 0xDA, 0x8E}},
|
||||
{
|
||||
[]byte{0x02, 0x58, 0x16, 0x16, 0x46, 0x29, 0xB0, 0x07},
|
||||
[]byte{0x48, 0x0D, 0x39, 0x00, 0x6E, 0xE7, 0x62, 0xF2},
|
||||
[]byte{0x75, 0x55, 0xAE, 0x39, 0xF5, 0x9B, 0x87, 0xBD}},
|
||||
{
|
||||
[]byte{0x49, 0x79, 0x3E, 0xBC, 0x79, 0xB3, 0x25, 0x8F},
|
||||
[]byte{0x43, 0x75, 0x40, 0xC8, 0x69, 0x8F, 0x3C, 0xFA},
|
||||
[]byte{0x53, 0xC5, 0x5F, 0x9C, 0xB4, 0x9F, 0xC0, 0x19}},
|
||||
{
|
||||
[]byte{0x4F, 0xB0, 0x5E, 0x15, 0x15, 0xAB, 0x73, 0xA7},
|
||||
[]byte{0x07, 0x2D, 0x43, 0xA0, 0x77, 0x07, 0x52, 0x92},
|
||||
[]byte{0x7A, 0x8E, 0x7B, 0xFA, 0x93, 0x7E, 0x89, 0xA3}},
|
||||
{
|
||||
[]byte{0x49, 0xE9, 0x5D, 0x6D, 0x4C, 0xA2, 0x29, 0xBF},
|
||||
[]byte{0x02, 0xFE, 0x55, 0x77, 0x81, 0x17, 0xF1, 0x2A},
|
||||
[]byte{0xCF, 0x9C, 0x5D, 0x7A, 0x49, 0x86, 0xAD, 0xB5}},
|
||||
{
|
||||
[]byte{0x01, 0x83, 0x10, 0xDC, 0x40, 0x9B, 0x26, 0xD6},
|
||||
[]byte{0x1D, 0x9D, 0x5C, 0x50, 0x18, 0xF7, 0x28, 0xC2},
|
||||
[]byte{0xD1, 0xAB, 0xB2, 0x90, 0x65, 0x8B, 0xC7, 0x78}},
|
||||
{
|
||||
[]byte{0x1C, 0x58, 0x7F, 0x1C, 0x13, 0x92, 0x4F, 0xEF},
|
||||
[]byte{0x30, 0x55, 0x32, 0x28, 0x6D, 0x6F, 0x29, 0x5A},
|
||||
[]byte{0x55, 0xCB, 0x37, 0x74, 0xD1, 0x3E, 0xF2, 0x01}},
|
||||
{
|
||||
[]byte{0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01},
|
||||
[]byte{0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF},
|
||||
[]byte{0xFA, 0x34, 0xEC, 0x48, 0x47, 0xB2, 0x68, 0xB2}},
|
||||
{
|
||||
[]byte{0x1F, 0x1F, 0x1F, 0x1F, 0x0E, 0x0E, 0x0E, 0x0E},
|
||||
[]byte{0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF},
|
||||
[]byte{0xA7, 0x90, 0x79, 0x51, 0x08, 0xEA, 0x3C, 0xAE}},
|
||||
{
|
||||
[]byte{0xE0, 0xFE, 0xE0, 0xFE, 0xF1, 0xFE, 0xF1, 0xFE},
|
||||
[]byte{0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF},
|
||||
[]byte{0xC3, 0x9E, 0x07, 0x2D, 0x9F, 0xAC, 0x63, 0x1D}},
|
||||
{
|
||||
[]byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
|
||||
[]byte{0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF},
|
||||
[]byte{0x01, 0x49, 0x33, 0xE0, 0xCD, 0xAF, 0xF6, 0xE4}},
|
||||
{
|
||||
[]byte{0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF},
|
||||
[]byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
|
||||
[]byte{0xF2, 0x1E, 0x9A, 0x77, 0xB7, 0x1C, 0x49, 0xBC}},
|
||||
{
|
||||
[]byte{0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF},
|
||||
[]byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
|
||||
[]byte{0x24, 0x59, 0x46, 0x88, 0x57, 0x54, 0x36, 0x9A}},
|
||||
{
|
||||
[]byte{0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10},
|
||||
[]byte{0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF},
|
||||
[]byte{0x6B, 0x5C, 0x5A, 0x9C, 0x5D, 0x9E, 0x0A, 0x5A}},
|
||||
}
|
||||
|
||||
func TestCipherEncrypt(t *testing.T) {
|
||||
for i, tt := range encryptTests {
|
||||
c, err := NewCipher(tt.key)
|
||||
if err != nil {
|
||||
t.Errorf("NewCipher(%d bytes) = %s", len(tt.key), err)
|
||||
continue
|
||||
}
|
||||
ct := make([]byte, len(tt.out))
|
||||
c.Encrypt(ct, tt.in)
|
||||
for j, v := range ct {
|
||||
if v != tt.out[j] {
|
||||
t.Errorf("Cipher.Encrypt, test vector #%d: cipher-text[%d] = %#x, expected %#x", i, j, v, tt.out[j])
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestCipherDecrypt(t *testing.T) {
|
||||
for i, tt := range encryptTests {
|
||||
c, err := NewCipher(tt.key)
|
||||
if err != nil {
|
||||
t.Errorf("NewCipher(%d bytes) = %s", len(tt.key), err)
|
||||
continue
|
||||
}
|
||||
pt := make([]byte, len(tt.in))
|
||||
c.Decrypt(pt, tt.out)
|
||||
for j, v := range pt {
|
||||
if v != tt.in[j] {
|
||||
t.Errorf("Cipher.Decrypt, test vector #%d: plain-text[%d] = %#x, expected %#x", i, j, v, tt.in[j])
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestSaltedCipherKeyLength(t *testing.T) {
|
||||
if _, err := NewSaltedCipher(nil, []byte{'a'}); err != KeySizeError(0) {
|
||||
t.Errorf("NewSaltedCipher with short key, gave error %#v, expected %#v", err, KeySizeError(0))
|
||||
}
|
||||
|
||||
// A 57-byte key. One over the typical blowfish restriction.
|
||||
key := []byte("012345678901234567890123456789012345678901234567890123456")
|
||||
if _, err := NewSaltedCipher(key, []byte{'a'}); err != nil {
|
||||
t.Errorf("NewSaltedCipher with long key, gave error %#v", err)
|
||||
}
|
||||
}
|
||||
88
Godeps/_workspace/src/code.google.com/p/go.crypto/blowfish/cipher.go
generated
vendored
Normal file
88
Godeps/_workspace/src/code.google.com/p/go.crypto/blowfish/cipher.go
generated
vendored
Normal file
@@ -0,0 +1,88 @@
|
||||
// Copyright 2010 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// Package blowfish implements Bruce Schneier's Blowfish encryption algorithm.
|
||||
package blowfish
|
||||
|
||||
// The code is a port of Bruce Schneier's C implementation.
|
||||
// See http://www.schneier.com/blowfish.html.
|
||||
|
||||
import "strconv"
|
||||
|
||||
// The Blowfish block size in bytes.
|
||||
const BlockSize = 8
|
||||
|
||||
// A Cipher is an instance of Blowfish encryption using a particular key.
|
||||
type Cipher struct {
|
||||
p [18]uint32
|
||||
s0, s1, s2, s3 [256]uint32
|
||||
}
|
||||
|
||||
type KeySizeError int
|
||||
|
||||
func (k KeySizeError) Error() string {
|
||||
return "crypto/blowfish: invalid key size " + strconv.Itoa(int(k))
|
||||
}
|
||||
|
||||
// NewCipher creates and returns a Cipher.
|
||||
// The key argument should be the Blowfish key, from 1 to 56 bytes.
|
||||
func NewCipher(key []byte) (*Cipher, error) {
|
||||
var result Cipher
|
||||
if k := len(key); k < 1 || k > 56 {
|
||||
return nil, KeySizeError(k)
|
||||
}
|
||||
initCipher(&result)
|
||||
ExpandKey(key, &result)
|
||||
return &result, nil
|
||||
}
|
||||
|
||||
// NewSaltedCipher creates a returns a Cipher that folds a salt into its key
|
||||
// schedule. For most purposes, NewCipher, instead of NewSaltedCipher, is
|
||||
// sufficient and desirable. For bcrypt compatiblity, the key can be over 56
|
||||
// bytes. Only the first 16 bytes of salt are used.
|
||||
func NewSaltedCipher(key, salt []byte) (*Cipher, error) {
|
||||
var result Cipher
|
||||
if k := len(key); k < 1 {
|
||||
return nil, KeySizeError(k)
|
||||
}
|
||||
initCipher(&result)
|
||||
expandKeyWithSalt(key, salt, &result)
|
||||
return &result, nil
|
||||
}
|
||||
|
||||
// BlockSize returns the Blowfish block size, 8 bytes.
|
||||
// It is necessary to satisfy the Block interface in the
|
||||
// package "crypto/cipher".
|
||||
func (c *Cipher) BlockSize() int { return BlockSize }
|
||||
|
||||
// Encrypt encrypts the 8-byte buffer src using the key k
|
||||
// and stores the result in dst.
|
||||
// Note that for amounts of data larger than a block,
|
||||
// it is not safe to just call Encrypt on successive blocks;
|
||||
// instead, use an encryption mode like CBC (see crypto/cipher/cbc.go).
|
||||
func (c *Cipher) Encrypt(dst, src []byte) {
|
||||
l := uint32(src[0])<<24 | uint32(src[1])<<16 | uint32(src[2])<<8 | uint32(src[3])
|
||||
r := uint32(src[4])<<24 | uint32(src[5])<<16 | uint32(src[6])<<8 | uint32(src[7])
|
||||
l, r = encryptBlock(l, r, c)
|
||||
dst[0], dst[1], dst[2], dst[3] = byte(l>>24), byte(l>>16), byte(l>>8), byte(l)
|
||||
dst[4], dst[5], dst[6], dst[7] = byte(r>>24), byte(r>>16), byte(r>>8), byte(r)
|
||||
}
|
||||
|
||||
// Decrypt decrypts the 8-byte buffer src using the key k
|
||||
// and stores the result in dst.
|
||||
func (c *Cipher) Decrypt(dst, src []byte) {
|
||||
l := uint32(src[0])<<24 | uint32(src[1])<<16 | uint32(src[2])<<8 | uint32(src[3])
|
||||
r := uint32(src[4])<<24 | uint32(src[5])<<16 | uint32(src[6])<<8 | uint32(src[7])
|
||||
l, r = decryptBlock(l, r, c)
|
||||
dst[0], dst[1], dst[2], dst[3] = byte(l>>24), byte(l>>16), byte(l>>8), byte(l)
|
||||
dst[4], dst[5], dst[6], dst[7] = byte(r>>24), byte(r>>16), byte(r>>8), byte(r)
|
||||
}
|
||||
|
||||
func initCipher(c *Cipher) {
|
||||
copy(c.p[0:], p[0:])
|
||||
copy(c.s0[0:], s0[0:])
|
||||
copy(c.s1[0:], s1[0:])
|
||||
copy(c.s2[0:], s2[0:])
|
||||
copy(c.s3[0:], s3[0:])
|
||||
}
|
||||
199
Godeps/_workspace/src/code.google.com/p/go.crypto/blowfish/const.go
generated
vendored
Normal file
199
Godeps/_workspace/src/code.google.com/p/go.crypto/blowfish/const.go
generated
vendored
Normal file
@@ -0,0 +1,199 @@
|
||||
// Copyright 2010 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// The startup permutation array and substitution boxes.
|
||||
// They are the hexadecimal digits of PI; see:
|
||||
// http://www.schneier.com/code/constants.txt.
|
||||
|
||||
package blowfish
|
||||
|
||||
var s0 = [256]uint32{
|
||||
0xd1310ba6, 0x98dfb5ac, 0x2ffd72db, 0xd01adfb7, 0xb8e1afed, 0x6a267e96,
|
||||
0xba7c9045, 0xf12c7f99, 0x24a19947, 0xb3916cf7, 0x0801f2e2, 0x858efc16,
|
||||
0x636920d8, 0x71574e69, 0xa458fea3, 0xf4933d7e, 0x0d95748f, 0x728eb658,
|
||||
0x718bcd58, 0x82154aee, 0x7b54a41d, 0xc25a59b5, 0x9c30d539, 0x2af26013,
|
||||
0xc5d1b023, 0x286085f0, 0xca417918, 0xb8db38ef, 0x8e79dcb0, 0x603a180e,
|
||||
0x6c9e0e8b, 0xb01e8a3e, 0xd71577c1, 0xbd314b27, 0x78af2fda, 0x55605c60,
|
||||
0xe65525f3, 0xaa55ab94, 0x57489862, 0x63e81440, 0x55ca396a, 0x2aab10b6,
|
||||
0xb4cc5c34, 0x1141e8ce, 0xa15486af, 0x7c72e993, 0xb3ee1411, 0x636fbc2a,
|
||||
0x2ba9c55d, 0x741831f6, 0xce5c3e16, 0x9b87931e, 0xafd6ba33, 0x6c24cf5c,
|
||||
0x7a325381, 0x28958677, 0x3b8f4898, 0x6b4bb9af, 0xc4bfe81b, 0x66282193,
|
||||
0x61d809cc, 0xfb21a991, 0x487cac60, 0x5dec8032, 0xef845d5d, 0xe98575b1,
|
||||
0xdc262302, 0xeb651b88, 0x23893e81, 0xd396acc5, 0x0f6d6ff3, 0x83f44239,
|
||||
0x2e0b4482, 0xa4842004, 0x69c8f04a, 0x9e1f9b5e, 0x21c66842, 0xf6e96c9a,
|
||||
0x670c9c61, 0xabd388f0, 0x6a51a0d2, 0xd8542f68, 0x960fa728, 0xab5133a3,
|
||||
0x6eef0b6c, 0x137a3be4, 0xba3bf050, 0x7efb2a98, 0xa1f1651d, 0x39af0176,
|
||||
0x66ca593e, 0x82430e88, 0x8cee8619, 0x456f9fb4, 0x7d84a5c3, 0x3b8b5ebe,
|
||||
0xe06f75d8, 0x85c12073, 0x401a449f, 0x56c16aa6, 0x4ed3aa62, 0x363f7706,
|
||||
0x1bfedf72, 0x429b023d, 0x37d0d724, 0xd00a1248, 0xdb0fead3, 0x49f1c09b,
|
||||
0x075372c9, 0x80991b7b, 0x25d479d8, 0xf6e8def7, 0xe3fe501a, 0xb6794c3b,
|
||||
0x976ce0bd, 0x04c006ba, 0xc1a94fb6, 0x409f60c4, 0x5e5c9ec2, 0x196a2463,
|
||||
0x68fb6faf, 0x3e6c53b5, 0x1339b2eb, 0x3b52ec6f, 0x6dfc511f, 0x9b30952c,
|
||||
0xcc814544, 0xaf5ebd09, 0xbee3d004, 0xde334afd, 0x660f2807, 0x192e4bb3,
|
||||
0xc0cba857, 0x45c8740f, 0xd20b5f39, 0xb9d3fbdb, 0x5579c0bd, 0x1a60320a,
|
||||
0xd6a100c6, 0x402c7279, 0x679f25fe, 0xfb1fa3cc, 0x8ea5e9f8, 0xdb3222f8,
|
||||
0x3c7516df, 0xfd616b15, 0x2f501ec8, 0xad0552ab, 0x323db5fa, 0xfd238760,
|
||||
0x53317b48, 0x3e00df82, 0x9e5c57bb, 0xca6f8ca0, 0x1a87562e, 0xdf1769db,
|
||||
0xd542a8f6, 0x287effc3, 0xac6732c6, 0x8c4f5573, 0x695b27b0, 0xbbca58c8,
|
||||
0xe1ffa35d, 0xb8f011a0, 0x10fa3d98, 0xfd2183b8, 0x4afcb56c, 0x2dd1d35b,
|
||||
0x9a53e479, 0xb6f84565, 0xd28e49bc, 0x4bfb9790, 0xe1ddf2da, 0xa4cb7e33,
|
||||
0x62fb1341, 0xcee4c6e8, 0xef20cada, 0x36774c01, 0xd07e9efe, 0x2bf11fb4,
|
||||
0x95dbda4d, 0xae909198, 0xeaad8e71, 0x6b93d5a0, 0xd08ed1d0, 0xafc725e0,
|
||||
0x8e3c5b2f, 0x8e7594b7, 0x8ff6e2fb, 0xf2122b64, 0x8888b812, 0x900df01c,
|
||||
0x4fad5ea0, 0x688fc31c, 0xd1cff191, 0xb3a8c1ad, 0x2f2f2218, 0xbe0e1777,
|
||||
0xea752dfe, 0x8b021fa1, 0xe5a0cc0f, 0xb56f74e8, 0x18acf3d6, 0xce89e299,
|
||||
0xb4a84fe0, 0xfd13e0b7, 0x7cc43b81, 0xd2ada8d9, 0x165fa266, 0x80957705,
|
||||
0x93cc7314, 0x211a1477, 0xe6ad2065, 0x77b5fa86, 0xc75442f5, 0xfb9d35cf,
|
||||
0xebcdaf0c, 0x7b3e89a0, 0xd6411bd3, 0xae1e7e49, 0x00250e2d, 0x2071b35e,
|
||||
0x226800bb, 0x57b8e0af, 0x2464369b, 0xf009b91e, 0x5563911d, 0x59dfa6aa,
|
||||
0x78c14389, 0xd95a537f, 0x207d5ba2, 0x02e5b9c5, 0x83260376, 0x6295cfa9,
|
||||
0x11c81968, 0x4e734a41, 0xb3472dca, 0x7b14a94a, 0x1b510052, 0x9a532915,
|
||||
0xd60f573f, 0xbc9bc6e4, 0x2b60a476, 0x81e67400, 0x08ba6fb5, 0x571be91f,
|
||||
0xf296ec6b, 0x2a0dd915, 0xb6636521, 0xe7b9f9b6, 0xff34052e, 0xc5855664,
|
||||
0x53b02d5d, 0xa99f8fa1, 0x08ba4799, 0x6e85076a,
|
||||
}
|
||||
|
||||
var s1 = [256]uint32{
|
||||
0x4b7a70e9, 0xb5b32944, 0xdb75092e, 0xc4192623, 0xad6ea6b0, 0x49a7df7d,
|
||||
0x9cee60b8, 0x8fedb266, 0xecaa8c71, 0x699a17ff, 0x5664526c, 0xc2b19ee1,
|
||||
0x193602a5, 0x75094c29, 0xa0591340, 0xe4183a3e, 0x3f54989a, 0x5b429d65,
|
||||
0x6b8fe4d6, 0x99f73fd6, 0xa1d29c07, 0xefe830f5, 0x4d2d38e6, 0xf0255dc1,
|
||||
0x4cdd2086, 0x8470eb26, 0x6382e9c6, 0x021ecc5e, 0x09686b3f, 0x3ebaefc9,
|
||||
0x3c971814, 0x6b6a70a1, 0x687f3584, 0x52a0e286, 0xb79c5305, 0xaa500737,
|
||||
0x3e07841c, 0x7fdeae5c, 0x8e7d44ec, 0x5716f2b8, 0xb03ada37, 0xf0500c0d,
|
||||
0xf01c1f04, 0x0200b3ff, 0xae0cf51a, 0x3cb574b2, 0x25837a58, 0xdc0921bd,
|
||||
0xd19113f9, 0x7ca92ff6, 0x94324773, 0x22f54701, 0x3ae5e581, 0x37c2dadc,
|
||||
0xc8b57634, 0x9af3dda7, 0xa9446146, 0x0fd0030e, 0xecc8c73e, 0xa4751e41,
|
||||
0xe238cd99, 0x3bea0e2f, 0x3280bba1, 0x183eb331, 0x4e548b38, 0x4f6db908,
|
||||
0x6f420d03, 0xf60a04bf, 0x2cb81290, 0x24977c79, 0x5679b072, 0xbcaf89af,
|
||||
0xde9a771f, 0xd9930810, 0xb38bae12, 0xdccf3f2e, 0x5512721f, 0x2e6b7124,
|
||||
0x501adde6, 0x9f84cd87, 0x7a584718, 0x7408da17, 0xbc9f9abc, 0xe94b7d8c,
|
||||
0xec7aec3a, 0xdb851dfa, 0x63094366, 0xc464c3d2, 0xef1c1847, 0x3215d908,
|
||||
0xdd433b37, 0x24c2ba16, 0x12a14d43, 0x2a65c451, 0x50940002, 0x133ae4dd,
|
||||
0x71dff89e, 0x10314e55, 0x81ac77d6, 0x5f11199b, 0x043556f1, 0xd7a3c76b,
|
||||
0x3c11183b, 0x5924a509, 0xf28fe6ed, 0x97f1fbfa, 0x9ebabf2c, 0x1e153c6e,
|
||||
0x86e34570, 0xeae96fb1, 0x860e5e0a, 0x5a3e2ab3, 0x771fe71c, 0x4e3d06fa,
|
||||
0x2965dcb9, 0x99e71d0f, 0x803e89d6, 0x5266c825, 0x2e4cc978, 0x9c10b36a,
|
||||
0xc6150eba, 0x94e2ea78, 0xa5fc3c53, 0x1e0a2df4, 0xf2f74ea7, 0x361d2b3d,
|
||||
0x1939260f, 0x19c27960, 0x5223a708, 0xf71312b6, 0xebadfe6e, 0xeac31f66,
|
||||
0xe3bc4595, 0xa67bc883, 0xb17f37d1, 0x018cff28, 0xc332ddef, 0xbe6c5aa5,
|
||||
0x65582185, 0x68ab9802, 0xeecea50f, 0xdb2f953b, 0x2aef7dad, 0x5b6e2f84,
|
||||
0x1521b628, 0x29076170, 0xecdd4775, 0x619f1510, 0x13cca830, 0xeb61bd96,
|
||||
0x0334fe1e, 0xaa0363cf, 0xb5735c90, 0x4c70a239, 0xd59e9e0b, 0xcbaade14,
|
||||
0xeecc86bc, 0x60622ca7, 0x9cab5cab, 0xb2f3846e, 0x648b1eaf, 0x19bdf0ca,
|
||||
0xa02369b9, 0x655abb50, 0x40685a32, 0x3c2ab4b3, 0x319ee9d5, 0xc021b8f7,
|
||||
0x9b540b19, 0x875fa099, 0x95f7997e, 0x623d7da8, 0xf837889a, 0x97e32d77,
|
||||
0x11ed935f, 0x16681281, 0x0e358829, 0xc7e61fd6, 0x96dedfa1, 0x7858ba99,
|
||||
0x57f584a5, 0x1b227263, 0x9b83c3ff, 0x1ac24696, 0xcdb30aeb, 0x532e3054,
|
||||
0x8fd948e4, 0x6dbc3128, 0x58ebf2ef, 0x34c6ffea, 0xfe28ed61, 0xee7c3c73,
|
||||
0x5d4a14d9, 0xe864b7e3, 0x42105d14, 0x203e13e0, 0x45eee2b6, 0xa3aaabea,
|
||||
0xdb6c4f15, 0xfacb4fd0, 0xc742f442, 0xef6abbb5, 0x654f3b1d, 0x41cd2105,
|
||||
0xd81e799e, 0x86854dc7, 0xe44b476a, 0x3d816250, 0xcf62a1f2, 0x5b8d2646,
|
||||
0xfc8883a0, 0xc1c7b6a3, 0x7f1524c3, 0x69cb7492, 0x47848a0b, 0x5692b285,
|
||||
0x095bbf00, 0xad19489d, 0x1462b174, 0x23820e00, 0x58428d2a, 0x0c55f5ea,
|
||||
0x1dadf43e, 0x233f7061, 0x3372f092, 0x8d937e41, 0xd65fecf1, 0x6c223bdb,
|
||||
0x7cde3759, 0xcbee7460, 0x4085f2a7, 0xce77326e, 0xa6078084, 0x19f8509e,
|
||||
0xe8efd855, 0x61d99735, 0xa969a7aa, 0xc50c06c2, 0x5a04abfc, 0x800bcadc,
|
||||
0x9e447a2e, 0xc3453484, 0xfdd56705, 0x0e1e9ec9, 0xdb73dbd3, 0x105588cd,
|
||||
0x675fda79, 0xe3674340, 0xc5c43465, 0x713e38d8, 0x3d28f89e, 0xf16dff20,
|
||||
0x153e21e7, 0x8fb03d4a, 0xe6e39f2b, 0xdb83adf7,
|
||||
}
|
||||
|
||||
var s2 = [256]uint32{
|
||||
0xe93d5a68, 0x948140f7, 0xf64c261c, 0x94692934, 0x411520f7, 0x7602d4f7,
|
||||
0xbcf46b2e, 0xd4a20068, 0xd4082471, 0x3320f46a, 0x43b7d4b7, 0x500061af,
|
||||
0x1e39f62e, 0x97244546, 0x14214f74, 0xbf8b8840, 0x4d95fc1d, 0x96b591af,
|
||||
0x70f4ddd3, 0x66a02f45, 0xbfbc09ec, 0x03bd9785, 0x7fac6dd0, 0x31cb8504,
|
||||
0x96eb27b3, 0x55fd3941, 0xda2547e6, 0xabca0a9a, 0x28507825, 0x530429f4,
|
||||
0x0a2c86da, 0xe9b66dfb, 0x68dc1462, 0xd7486900, 0x680ec0a4, 0x27a18dee,
|
||||
0x4f3ffea2, 0xe887ad8c, 0xb58ce006, 0x7af4d6b6, 0xaace1e7c, 0xd3375fec,
|
||||
0xce78a399, 0x406b2a42, 0x20fe9e35, 0xd9f385b9, 0xee39d7ab, 0x3b124e8b,
|
||||
0x1dc9faf7, 0x4b6d1856, 0x26a36631, 0xeae397b2, 0x3a6efa74, 0xdd5b4332,
|
||||
0x6841e7f7, 0xca7820fb, 0xfb0af54e, 0xd8feb397, 0x454056ac, 0xba489527,
|
||||
0x55533a3a, 0x20838d87, 0xfe6ba9b7, 0xd096954b, 0x55a867bc, 0xa1159a58,
|
||||
0xcca92963, 0x99e1db33, 0xa62a4a56, 0x3f3125f9, 0x5ef47e1c, 0x9029317c,
|
||||
0xfdf8e802, 0x04272f70, 0x80bb155c, 0x05282ce3, 0x95c11548, 0xe4c66d22,
|
||||
0x48c1133f, 0xc70f86dc, 0x07f9c9ee, 0x41041f0f, 0x404779a4, 0x5d886e17,
|
||||
0x325f51eb, 0xd59bc0d1, 0xf2bcc18f, 0x41113564, 0x257b7834, 0x602a9c60,
|
||||
0xdff8e8a3, 0x1f636c1b, 0x0e12b4c2, 0x02e1329e, 0xaf664fd1, 0xcad18115,
|
||||
0x6b2395e0, 0x333e92e1, 0x3b240b62, 0xeebeb922, 0x85b2a20e, 0xe6ba0d99,
|
||||
0xde720c8c, 0x2da2f728, 0xd0127845, 0x95b794fd, 0x647d0862, 0xe7ccf5f0,
|
||||
0x5449a36f, 0x877d48fa, 0xc39dfd27, 0xf33e8d1e, 0x0a476341, 0x992eff74,
|
||||
0x3a6f6eab, 0xf4f8fd37, 0xa812dc60, 0xa1ebddf8, 0x991be14c, 0xdb6e6b0d,
|
||||
0xc67b5510, 0x6d672c37, 0x2765d43b, 0xdcd0e804, 0xf1290dc7, 0xcc00ffa3,
|
||||
0xb5390f92, 0x690fed0b, 0x667b9ffb, 0xcedb7d9c, 0xa091cf0b, 0xd9155ea3,
|
||||
0xbb132f88, 0x515bad24, 0x7b9479bf, 0x763bd6eb, 0x37392eb3, 0xcc115979,
|
||||
0x8026e297, 0xf42e312d, 0x6842ada7, 0xc66a2b3b, 0x12754ccc, 0x782ef11c,
|
||||
0x6a124237, 0xb79251e7, 0x06a1bbe6, 0x4bfb6350, 0x1a6b1018, 0x11caedfa,
|
||||
0x3d25bdd8, 0xe2e1c3c9, 0x44421659, 0x0a121386, 0xd90cec6e, 0xd5abea2a,
|
||||
0x64af674e, 0xda86a85f, 0xbebfe988, 0x64e4c3fe, 0x9dbc8057, 0xf0f7c086,
|
||||
0x60787bf8, 0x6003604d, 0xd1fd8346, 0xf6381fb0, 0x7745ae04, 0xd736fccc,
|
||||
0x83426b33, 0xf01eab71, 0xb0804187, 0x3c005e5f, 0x77a057be, 0xbde8ae24,
|
||||
0x55464299, 0xbf582e61, 0x4e58f48f, 0xf2ddfda2, 0xf474ef38, 0x8789bdc2,
|
||||
0x5366f9c3, 0xc8b38e74, 0xb475f255, 0x46fcd9b9, 0x7aeb2661, 0x8b1ddf84,
|
||||
0x846a0e79, 0x915f95e2, 0x466e598e, 0x20b45770, 0x8cd55591, 0xc902de4c,
|
||||
0xb90bace1, 0xbb8205d0, 0x11a86248, 0x7574a99e, 0xb77f19b6, 0xe0a9dc09,
|
||||
0x662d09a1, 0xc4324633, 0xe85a1f02, 0x09f0be8c, 0x4a99a025, 0x1d6efe10,
|
||||
0x1ab93d1d, 0x0ba5a4df, 0xa186f20f, 0x2868f169, 0xdcb7da83, 0x573906fe,
|
||||
0xa1e2ce9b, 0x4fcd7f52, 0x50115e01, 0xa70683fa, 0xa002b5c4, 0x0de6d027,
|
||||
0x9af88c27, 0x773f8641, 0xc3604c06, 0x61a806b5, 0xf0177a28, 0xc0f586e0,
|
||||
0x006058aa, 0x30dc7d62, 0x11e69ed7, 0x2338ea63, 0x53c2dd94, 0xc2c21634,
|
||||
0xbbcbee56, 0x90bcb6de, 0xebfc7da1, 0xce591d76, 0x6f05e409, 0x4b7c0188,
|
||||
0x39720a3d, 0x7c927c24, 0x86e3725f, 0x724d9db9, 0x1ac15bb4, 0xd39eb8fc,
|
||||
0xed545578, 0x08fca5b5, 0xd83d7cd3, 0x4dad0fc4, 0x1e50ef5e, 0xb161e6f8,
|
||||
0xa28514d9, 0x6c51133c, 0x6fd5c7e7, 0x56e14ec4, 0x362abfce, 0xddc6c837,
|
||||
0xd79a3234, 0x92638212, 0x670efa8e, 0x406000e0,
|
||||
}
|
||||
|
||||
var s3 = [256]uint32{
|
||||
0x3a39ce37, 0xd3faf5cf, 0xabc27737, 0x5ac52d1b, 0x5cb0679e, 0x4fa33742,
|
||||
0xd3822740, 0x99bc9bbe, 0xd5118e9d, 0xbf0f7315, 0xd62d1c7e, 0xc700c47b,
|
||||
0xb78c1b6b, 0x21a19045, 0xb26eb1be, 0x6a366eb4, 0x5748ab2f, 0xbc946e79,
|
||||
0xc6a376d2, 0x6549c2c8, 0x530ff8ee, 0x468dde7d, 0xd5730a1d, 0x4cd04dc6,
|
||||
0x2939bbdb, 0xa9ba4650, 0xac9526e8, 0xbe5ee304, 0xa1fad5f0, 0x6a2d519a,
|
||||
0x63ef8ce2, 0x9a86ee22, 0xc089c2b8, 0x43242ef6, 0xa51e03aa, 0x9cf2d0a4,
|
||||
0x83c061ba, 0x9be96a4d, 0x8fe51550, 0xba645bd6, 0x2826a2f9, 0xa73a3ae1,
|
||||
0x4ba99586, 0xef5562e9, 0xc72fefd3, 0xf752f7da, 0x3f046f69, 0x77fa0a59,
|
||||
0x80e4a915, 0x87b08601, 0x9b09e6ad, 0x3b3ee593, 0xe990fd5a, 0x9e34d797,
|
||||
0x2cf0b7d9, 0x022b8b51, 0x96d5ac3a, 0x017da67d, 0xd1cf3ed6, 0x7c7d2d28,
|
||||
0x1f9f25cf, 0xadf2b89b, 0x5ad6b472, 0x5a88f54c, 0xe029ac71, 0xe019a5e6,
|
||||
0x47b0acfd, 0xed93fa9b, 0xe8d3c48d, 0x283b57cc, 0xf8d56629, 0x79132e28,
|
||||
0x785f0191, 0xed756055, 0xf7960e44, 0xe3d35e8c, 0x15056dd4, 0x88f46dba,
|
||||
0x03a16125, 0x0564f0bd, 0xc3eb9e15, 0x3c9057a2, 0x97271aec, 0xa93a072a,
|
||||
0x1b3f6d9b, 0x1e6321f5, 0xf59c66fb, 0x26dcf319, 0x7533d928, 0xb155fdf5,
|
||||
0x03563482, 0x8aba3cbb, 0x28517711, 0xc20ad9f8, 0xabcc5167, 0xccad925f,
|
||||
0x4de81751, 0x3830dc8e, 0x379d5862, 0x9320f991, 0xea7a90c2, 0xfb3e7bce,
|
||||
0x5121ce64, 0x774fbe32, 0xa8b6e37e, 0xc3293d46, 0x48de5369, 0x6413e680,
|
||||
0xa2ae0810, 0xdd6db224, 0x69852dfd, 0x09072166, 0xb39a460a, 0x6445c0dd,
|
||||
0x586cdecf, 0x1c20c8ae, 0x5bbef7dd, 0x1b588d40, 0xccd2017f, 0x6bb4e3bb,
|
||||
0xdda26a7e, 0x3a59ff45, 0x3e350a44, 0xbcb4cdd5, 0x72eacea8, 0xfa6484bb,
|
||||
0x8d6612ae, 0xbf3c6f47, 0xd29be463, 0x542f5d9e, 0xaec2771b, 0xf64e6370,
|
||||
0x740e0d8d, 0xe75b1357, 0xf8721671, 0xaf537d5d, 0x4040cb08, 0x4eb4e2cc,
|
||||
0x34d2466a, 0x0115af84, 0xe1b00428, 0x95983a1d, 0x06b89fb4, 0xce6ea048,
|
||||
0x6f3f3b82, 0x3520ab82, 0x011a1d4b, 0x277227f8, 0x611560b1, 0xe7933fdc,
|
||||
0xbb3a792b, 0x344525bd, 0xa08839e1, 0x51ce794b, 0x2f32c9b7, 0xa01fbac9,
|
||||
0xe01cc87e, 0xbcc7d1f6, 0xcf0111c3, 0xa1e8aac7, 0x1a908749, 0xd44fbd9a,
|
||||
0xd0dadecb, 0xd50ada38, 0x0339c32a, 0xc6913667, 0x8df9317c, 0xe0b12b4f,
|
||||
0xf79e59b7, 0x43f5bb3a, 0xf2d519ff, 0x27d9459c, 0xbf97222c, 0x15e6fc2a,
|
||||
0x0f91fc71, 0x9b941525, 0xfae59361, 0xceb69ceb, 0xc2a86459, 0x12baa8d1,
|
||||
0xb6c1075e, 0xe3056a0c, 0x10d25065, 0xcb03a442, 0xe0ec6e0e, 0x1698db3b,
|
||||
0x4c98a0be, 0x3278e964, 0x9f1f9532, 0xe0d392df, 0xd3a0342b, 0x8971f21e,
|
||||
0x1b0a7441, 0x4ba3348c, 0xc5be7120, 0xc37632d8, 0xdf359f8d, 0x9b992f2e,
|
||||
0xe60b6f47, 0x0fe3f11d, 0xe54cda54, 0x1edad891, 0xce6279cf, 0xcd3e7e6f,
|
||||
0x1618b166, 0xfd2c1d05, 0x848fd2c5, 0xf6fb2299, 0xf523f357, 0xa6327623,
|
||||
0x93a83531, 0x56cccd02, 0xacf08162, 0x5a75ebb5, 0x6e163697, 0x88d273cc,
|
||||
0xde966292, 0x81b949d0, 0x4c50901b, 0x71c65614, 0xe6c6c7bd, 0x327a140a,
|
||||
0x45e1d006, 0xc3f27b9a, 0xc9aa53fd, 0x62a80f00, 0xbb25bfe2, 0x35bdd2f6,
|
||||
0x71126905, 0xb2040222, 0xb6cbcf7c, 0xcd769c2b, 0x53113ec0, 0x1640e3d3,
|
||||
0x38abbd60, 0x2547adf0, 0xba38209c, 0xf746ce76, 0x77afa1c5, 0x20756060,
|
||||
0x85cbfe4e, 0x8ae88dd8, 0x7aaaf9b0, 0x4cf9aa7e, 0x1948c25c, 0x02fb8a8c,
|
||||
0x01c36ae4, 0xd6ebe1f9, 0x90d4f869, 0xa65cdea0, 0x3f09252d, 0xc208e69f,
|
||||
0xb74e6132, 0xce77e25b, 0x578fdfe3, 0x3ac372e6,
|
||||
}
|
||||
|
||||
var p = [18]uint32{
|
||||
0x243f6a88, 0x85a308d3, 0x13198a2e, 0x03707344, 0xa4093822, 0x299f31d0,
|
||||
0x082efa98, 0xec4e6c89, 0x452821e6, 0x38d01377, 0xbe5466cf, 0x34e90c6c,
|
||||
0xc0ac29b7, 0xc97c50dd, 0x3f84d5b5, 0xb5470917, 0x9216d5d9, 0x8979fb1b,
|
||||
}
|
||||
83
Godeps/_workspace/src/code.google.com/p/go.net/ipv6/control.go
generated
vendored
83
Godeps/_workspace/src/code.google.com/p/go.net/ipv6/control.go
generated
vendored
@@ -1,83 +0,0 @@
|
||||
// Copyright 2013 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package ipv6
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"net"
|
||||
"sync"
|
||||
)
|
||||
|
||||
var (
|
||||
errMissingAddress = errors.New("missing address")
|
||||
errInvalidConnType = errors.New("invalid conn type")
|
||||
errNoSuchInterface = errors.New("no such interface")
|
||||
)
|
||||
|
||||
// References:
|
||||
//
|
||||
// RFC 2292 Advanced Sockets API for IPv6
|
||||
// http://tools.ietf.org/html/rfc2292
|
||||
// RFC 2460 Internet Protocol, Version 6 (IPv6) Specification
|
||||
// http://tools.ietf.org/html/rfc2460
|
||||
// RFC 3493 Basic Socket Interface Extensions for IPv6
|
||||
// http://tools.ietf.org/html/rfc3493.html
|
||||
// RFC 3542 Advanced Sockets Application Program Interface (API) for IPv6
|
||||
// http://tools.ietf.org/html/rfc3542
|
||||
//
|
||||
// Note that RFC 3542 obsoltes RFC 2292 but OS X Snow Leopard and the
|
||||
// former still support RFC 2292 only. Please be aware that almost
|
||||
// all protocol implementations prohibit using a combination of RFC
|
||||
// 2292 and RFC 3542 for some practical reasons.
|
||||
|
||||
type rawOpt struct {
|
||||
sync.Mutex
|
||||
cflags ControlFlags
|
||||
}
|
||||
|
||||
func (c *rawOpt) set(f ControlFlags) { c.cflags |= f }
|
||||
func (c *rawOpt) clear(f ControlFlags) { c.cflags &^= f }
|
||||
func (c *rawOpt) isset(f ControlFlags) bool { return c.cflags&f != 0 }
|
||||
|
||||
// A ControlFlags reprensents per packet basis IP-level socket option
|
||||
// control flags.
|
||||
type ControlFlags uint
|
||||
|
||||
const (
|
||||
FlagTrafficClass ControlFlags = 1 << iota // pass the traffic class on the received packet
|
||||
FlagHopLimit // pass the hop limit on the received packet
|
||||
FlagSrc // pass the source address on the received packet
|
||||
FlagDst // pass the destination address on the received packet
|
||||
FlagInterface // pass the interface index on the received packet
|
||||
FlagPathMTU // pass the path MTU on the received packet path
|
||||
)
|
||||
|
||||
// A ControlMessage represents per packet basis IP-level socket
|
||||
// options.
|
||||
type ControlMessage struct {
|
||||
// Receiving socket options: SetControlMessage allows to
|
||||
// receive the options from the protocol stack using ReadFrom
|
||||
// method of PacketConn.
|
||||
//
|
||||
// Specifying socket options: ControlMessage for WriteTo
|
||||
// method of PacketConn allows to send the options to the
|
||||
// protocol stack.
|
||||
//
|
||||
TrafficClass int // traffic class, must be 1 <= value <= 255 when specifying
|
||||
HopLimit int // hop limit, must be 1 <= value <= 255 when specifying
|
||||
Src net.IP // source address, specifying only
|
||||
Dst net.IP // destination address, receiving only
|
||||
IfIndex int // interface index, must be 1 <= value when specifying
|
||||
NextHop net.IP // next hop address, specifying only
|
||||
MTU int // path MTU, receiving only
|
||||
}
|
||||
|
||||
func (cm *ControlMessage) String() string {
|
||||
if cm == nil {
|
||||
return "<nil>"
|
||||
}
|
||||
return fmt.Sprintf("tclass: %#x, hoplim: %v, src: %v, dst: %v, ifindex: %v, nexthop: %v, mtu: %v", cm.TrafficClass, cm.HopLimit, cm.Src, cm.Dst, cm.IfIndex, cm.NextHop, cm.MTU)
|
||||
}
|
||||
151
Godeps/_workspace/src/code.google.com/p/go.net/ipv6/control_rfc2292_unix.go
generated
vendored
151
Godeps/_workspace/src/code.google.com/p/go.net/ipv6/control_rfc2292_unix.go
generated
vendored
@@ -1,151 +0,0 @@
|
||||
// Copyright 2013 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build darwin
|
||||
|
||||
package ipv6
|
||||
|
||||
import (
|
||||
"net"
|
||||
"os"
|
||||
"syscall"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
const pktinfo = FlagDst | FlagInterface
|
||||
|
||||
func setControlMessage(fd int, opt *rawOpt, cf ControlFlags, on bool) error {
|
||||
opt.Lock()
|
||||
defer opt.Unlock()
|
||||
if cf&FlagHopLimit != 0 {
|
||||
if err := setIPv6ReceiveHopLimit(fd, on); err != nil {
|
||||
return err
|
||||
}
|
||||
if on {
|
||||
opt.set(FlagHopLimit)
|
||||
} else {
|
||||
opt.clear(FlagHopLimit)
|
||||
}
|
||||
}
|
||||
if cf&pktinfo != 0 {
|
||||
if err := setIPv6ReceivePacketInfo(fd, on); err != nil {
|
||||
return err
|
||||
}
|
||||
if on {
|
||||
opt.set(cf & pktinfo)
|
||||
} else {
|
||||
opt.clear(cf & pktinfo)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func newControlMessage(opt *rawOpt) (oob []byte) {
|
||||
opt.Lock()
|
||||
defer opt.Unlock()
|
||||
l, off := 0, 0
|
||||
if opt.isset(FlagHopLimit) {
|
||||
l += syscall.CmsgSpace(4)
|
||||
}
|
||||
if opt.isset(pktinfo) {
|
||||
l += syscall.CmsgSpace(sysSizeofPacketInfo)
|
||||
}
|
||||
if l > 0 {
|
||||
oob = make([]byte, l)
|
||||
if opt.isset(FlagHopLimit) {
|
||||
m := (*syscall.Cmsghdr)(unsafe.Pointer(&oob[off]))
|
||||
m.Level = ianaProtocolIPv6
|
||||
m.Type = sysSockopt2292HopLimit
|
||||
m.SetLen(syscall.CmsgLen(4))
|
||||
off += syscall.CmsgSpace(4)
|
||||
}
|
||||
if opt.isset(pktinfo) {
|
||||
m := (*syscall.Cmsghdr)(unsafe.Pointer(&oob[off]))
|
||||
m.Level = ianaProtocolIPv6
|
||||
m.Type = sysSockopt2292PacketInfo
|
||||
m.SetLen(syscall.CmsgLen(sysSizeofPacketInfo))
|
||||
off += syscall.CmsgSpace(sysSizeofPacketInfo)
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func parseControlMessage(b []byte) (*ControlMessage, error) {
|
||||
if len(b) == 0 {
|
||||
return nil, nil
|
||||
}
|
||||
cmsgs, err := syscall.ParseSocketControlMessage(b)
|
||||
if err != nil {
|
||||
return nil, os.NewSyscallError("parse socket control message", err)
|
||||
}
|
||||
cm := &ControlMessage{}
|
||||
for _, m := range cmsgs {
|
||||
if m.Header.Level != ianaProtocolIPv6 {
|
||||
continue
|
||||
}
|
||||
switch m.Header.Type {
|
||||
case sysSockopt2292HopLimit:
|
||||
cm.HopLimit = int(*(*byte)(unsafe.Pointer(&m.Data[:1][0])))
|
||||
case sysSockopt2292PacketInfo:
|
||||
pi := (*sysPacketInfo)(unsafe.Pointer(&m.Data[0]))
|
||||
cm.IfIndex = int(pi.IfIndex)
|
||||
cm.Dst = pi.IP[:]
|
||||
}
|
||||
}
|
||||
return cm, nil
|
||||
}
|
||||
|
||||
func marshalControlMessage(cm *ControlMessage) (oob []byte) {
|
||||
if cm == nil {
|
||||
return
|
||||
}
|
||||
l, off := 0, 0
|
||||
if cm.HopLimit > 0 {
|
||||
l += syscall.CmsgSpace(4)
|
||||
}
|
||||
pion := false
|
||||
if cm.Src.To4() == nil && cm.Src.To16() != nil || cm.IfIndex != 0 {
|
||||
pion = true
|
||||
l += syscall.CmsgSpace(sysSizeofPacketInfo)
|
||||
}
|
||||
if len(cm.NextHop) == net.IPv6len {
|
||||
l += syscall.CmsgSpace(syscall.SizeofSockaddrInet6)
|
||||
}
|
||||
if l > 0 {
|
||||
oob = make([]byte, l)
|
||||
if cm.HopLimit > 0 {
|
||||
m := (*syscall.Cmsghdr)(unsafe.Pointer(&oob[off]))
|
||||
m.Level = ianaProtocolIPv6
|
||||
m.Type = sysSockopt2292HopLimit
|
||||
m.SetLen(syscall.CmsgLen(4))
|
||||
data := oob[off+syscall.CmsgLen(0):]
|
||||
*(*byte)(unsafe.Pointer(&data[:1][0])) = byte(cm.HopLimit)
|
||||
off += syscall.CmsgSpace(4)
|
||||
}
|
||||
if pion {
|
||||
m := (*syscall.Cmsghdr)(unsafe.Pointer(&oob[off]))
|
||||
m.Level = ianaProtocolIPv6
|
||||
m.Type = sysSockopt2292PacketInfo
|
||||
m.SetLen(syscall.CmsgLen(sysSizeofPacketInfo))
|
||||
pi := (*sysPacketInfo)(unsafe.Pointer(&oob[off+syscall.CmsgLen(0)]))
|
||||
if ip := cm.Src.To16(); ip != nil && ip.To4() == nil {
|
||||
copy(pi.IP[:], ip)
|
||||
}
|
||||
if cm.IfIndex != 0 {
|
||||
pi.IfIndex = uint32(cm.IfIndex)
|
||||
}
|
||||
off += syscall.CmsgSpace(sysSizeofPacketInfo)
|
||||
}
|
||||
if len(cm.NextHop) == net.IPv6len {
|
||||
m := (*syscall.Cmsghdr)(unsafe.Pointer(&oob[off]))
|
||||
m.Level = ianaProtocolIPv6
|
||||
m.Type = sysSockopt2292NextHop
|
||||
m.SetLen(syscall.CmsgLen(syscall.SizeofSockaddrInet6))
|
||||
sa := (*syscall.RawSockaddrInet6)(unsafe.Pointer(&oob[off+syscall.CmsgLen(0)]))
|
||||
setSockaddr(sa, cm.NextHop, cm.IfIndex)
|
||||
off += syscall.CmsgSpace(syscall.SizeofSockaddrInet6)
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
27
Godeps/_workspace/src/code.google.com/p/go.net/ipv6/control_rfc3542_stub.go
generated
vendored
27
Godeps/_workspace/src/code.google.com/p/go.net/ipv6/control_rfc3542_stub.go
generated
vendored
@@ -1,27 +0,0 @@
|
||||
// Copyright 2013 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build dragonfly plan9 solaris
|
||||
|
||||
package ipv6
|
||||
|
||||
func setControlMessage(fd int, opt *rawOpt, cf ControlFlags, on bool) error {
|
||||
// TODO(mikio): Implement this
|
||||
return errOpNoSupport
|
||||
}
|
||||
|
||||
func newControlMessage(opt *rawOpt) (oob []byte) {
|
||||
// TODO(mikio): Implement this
|
||||
return nil
|
||||
}
|
||||
|
||||
func parseControlMessage(b []byte) (*ControlMessage, error) {
|
||||
// TODO(mikio): Implement this
|
||||
return nil, errOpNoSupport
|
||||
}
|
||||
|
||||
func marshalControlMessage(cm *ControlMessage) (oob []byte) {
|
||||
// TODO(mikio): Implement this
|
||||
return nil
|
||||
}
|
||||
210
Godeps/_workspace/src/code.google.com/p/go.net/ipv6/control_rfc3542_unix.go
generated
vendored
210
Godeps/_workspace/src/code.google.com/p/go.net/ipv6/control_rfc3542_unix.go
generated
vendored
@@ -1,210 +0,0 @@
|
||||
// Copyright 2013 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build freebsd linux netbsd openbsd
|
||||
|
||||
package ipv6
|
||||
|
||||
import (
|
||||
"net"
|
||||
"os"
|
||||
"syscall"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
const pktinfo = FlagDst | FlagInterface
|
||||
|
||||
func setControlMessage(fd int, opt *rawOpt, cf ControlFlags, on bool) error {
|
||||
opt.Lock()
|
||||
defer opt.Unlock()
|
||||
if cf&FlagTrafficClass != 0 {
|
||||
if err := setIPv6ReceiveTrafficClass(fd, on); err != nil {
|
||||
return err
|
||||
}
|
||||
if on {
|
||||
opt.set(FlagTrafficClass)
|
||||
} else {
|
||||
opt.clear(FlagTrafficClass)
|
||||
}
|
||||
}
|
||||
if cf&FlagHopLimit != 0 {
|
||||
if err := setIPv6ReceiveHopLimit(fd, on); err != nil {
|
||||
return err
|
||||
}
|
||||
if on {
|
||||
opt.set(FlagHopLimit)
|
||||
} else {
|
||||
opt.clear(FlagHopLimit)
|
||||
}
|
||||
}
|
||||
if cf&pktinfo != 0 {
|
||||
if err := setIPv6ReceivePacketInfo(fd, on); err != nil {
|
||||
return err
|
||||
}
|
||||
if on {
|
||||
opt.set(cf & pktinfo)
|
||||
} else {
|
||||
opt.clear(cf & pktinfo)
|
||||
}
|
||||
}
|
||||
if cf&FlagPathMTU != 0 {
|
||||
if err := setIPv6ReceivePathMTU(fd, on); err != nil {
|
||||
return err
|
||||
}
|
||||
if on {
|
||||
opt.set(FlagPathMTU)
|
||||
} else {
|
||||
opt.clear(FlagPathMTU)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func newControlMessage(opt *rawOpt) (oob []byte) {
|
||||
opt.Lock()
|
||||
defer opt.Unlock()
|
||||
l, off := 0, 0
|
||||
if opt.isset(FlagTrafficClass) {
|
||||
l += syscall.CmsgSpace(4)
|
||||
}
|
||||
if opt.isset(FlagHopLimit) {
|
||||
l += syscall.CmsgSpace(4)
|
||||
}
|
||||
if opt.isset(pktinfo) {
|
||||
l += syscall.CmsgSpace(sysSizeofPacketInfo)
|
||||
}
|
||||
if opt.isset(FlagPathMTU) {
|
||||
l += syscall.CmsgSpace(sysSizeofMTUInfo)
|
||||
}
|
||||
if l > 0 {
|
||||
oob = make([]byte, l)
|
||||
if opt.isset(FlagTrafficClass) {
|
||||
m := (*syscall.Cmsghdr)(unsafe.Pointer(&oob[off]))
|
||||
m.Level = ianaProtocolIPv6
|
||||
m.Type = sysSockoptReceiveTrafficClass
|
||||
m.SetLen(syscall.CmsgLen(4))
|
||||
off += syscall.CmsgSpace(4)
|
||||
}
|
||||
if opt.isset(FlagHopLimit) {
|
||||
m := (*syscall.Cmsghdr)(unsafe.Pointer(&oob[off]))
|
||||
m.Level = ianaProtocolIPv6
|
||||
m.Type = sysSockoptReceiveHopLimit
|
||||
m.SetLen(syscall.CmsgLen(4))
|
||||
off += syscall.CmsgSpace(4)
|
||||
}
|
||||
if opt.isset(pktinfo) {
|
||||
m := (*syscall.Cmsghdr)(unsafe.Pointer(&oob[off]))
|
||||
m.Level = ianaProtocolIPv6
|
||||
m.Type = sysSockoptReceivePacketInfo
|
||||
m.SetLen(syscall.CmsgLen(sysSizeofPacketInfo))
|
||||
off += syscall.CmsgSpace(sysSizeofPacketInfo)
|
||||
}
|
||||
if opt.isset(FlagPathMTU) {
|
||||
m := (*syscall.Cmsghdr)(unsafe.Pointer(&oob[off]))
|
||||
m.Level = ianaProtocolIPv6
|
||||
m.Type = sysSockoptReceivePathMTU
|
||||
m.SetLen(syscall.CmsgLen(sysSizeofMTUInfo))
|
||||
off += syscall.CmsgSpace(sysSizeofMTUInfo)
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func parseControlMessage(b []byte) (*ControlMessage, error) {
|
||||
if len(b) == 0 {
|
||||
return nil, nil
|
||||
}
|
||||
cmsgs, err := syscall.ParseSocketControlMessage(b)
|
||||
if err != nil {
|
||||
return nil, os.NewSyscallError("parse socket control message", err)
|
||||
}
|
||||
cm := &ControlMessage{}
|
||||
for _, m := range cmsgs {
|
||||
if m.Header.Level != ianaProtocolIPv6 {
|
||||
continue
|
||||
}
|
||||
switch m.Header.Type {
|
||||
case sysSockoptTrafficClass:
|
||||
cm.TrafficClass = int(*(*byte)(unsafe.Pointer(&m.Data[:1][0])))
|
||||
case sysSockoptHopLimit:
|
||||
cm.HopLimit = int(*(*byte)(unsafe.Pointer(&m.Data[:1][0])))
|
||||
case sysSockoptPacketInfo:
|
||||
pi := (*sysPacketInfo)(unsafe.Pointer(&m.Data[0]))
|
||||
cm.Dst = pi.IP[:]
|
||||
cm.IfIndex = int(pi.IfIndex)
|
||||
case sysSockoptPathMTU:
|
||||
mi := (*sysMTUInfo)(unsafe.Pointer(&m.Data[0]))
|
||||
cm.Dst = mi.Addr.Addr[:]
|
||||
cm.IfIndex = int(mi.Addr.Scope_id)
|
||||
cm.MTU = int(mi.MTU)
|
||||
}
|
||||
}
|
||||
return cm, nil
|
||||
}
|
||||
|
||||
func marshalControlMessage(cm *ControlMessage) (oob []byte) {
|
||||
if cm == nil {
|
||||
return
|
||||
}
|
||||
l, off := 0, 0
|
||||
if cm.TrafficClass > 0 {
|
||||
l += syscall.CmsgSpace(4)
|
||||
}
|
||||
if cm.HopLimit > 0 {
|
||||
l += syscall.CmsgSpace(4)
|
||||
}
|
||||
pion := false
|
||||
if cm.Src.To4() == nil && cm.Src.To16() != nil || cm.IfIndex != 0 {
|
||||
pion = true
|
||||
l += syscall.CmsgSpace(sysSizeofPacketInfo)
|
||||
}
|
||||
if len(cm.NextHop) == net.IPv6len {
|
||||
l += syscall.CmsgSpace(syscall.SizeofSockaddrInet6)
|
||||
}
|
||||
if l > 0 {
|
||||
oob = make([]byte, l)
|
||||
if cm.TrafficClass > 0 {
|
||||
m := (*syscall.Cmsghdr)(unsafe.Pointer(&oob[off]))
|
||||
m.Level = ianaProtocolIPv6
|
||||
m.Type = sysSockoptTrafficClass
|
||||
m.SetLen(syscall.CmsgLen(4))
|
||||
data := oob[off+syscall.CmsgLen(0):]
|
||||
*(*byte)(unsafe.Pointer(&data[:1][0])) = byte(cm.TrafficClass)
|
||||
off += syscall.CmsgSpace(4)
|
||||
}
|
||||
if cm.HopLimit > 0 {
|
||||
m := (*syscall.Cmsghdr)(unsafe.Pointer(&oob[off]))
|
||||
m.Level = ianaProtocolIPv6
|
||||
m.Type = sysSockoptHopLimit
|
||||
m.SetLen(syscall.CmsgLen(4))
|
||||
data := oob[off+syscall.CmsgLen(0):]
|
||||
*(*byte)(unsafe.Pointer(&data[:1][0])) = byte(cm.HopLimit)
|
||||
off += syscall.CmsgSpace(4)
|
||||
}
|
||||
if pion {
|
||||
m := (*syscall.Cmsghdr)(unsafe.Pointer(&oob[off]))
|
||||
m.Level = ianaProtocolIPv6
|
||||
m.Type = sysSockoptPacketInfo
|
||||
m.SetLen(syscall.CmsgLen(sysSizeofPacketInfo))
|
||||
pi := (*sysPacketInfo)(unsafe.Pointer(&oob[off+syscall.CmsgLen(0)]))
|
||||
if ip := cm.Src.To16(); ip != nil && ip.To4() == nil {
|
||||
copy(pi.IP[:], ip)
|
||||
}
|
||||
if cm.IfIndex != 0 {
|
||||
pi.IfIndex = uint32(cm.IfIndex)
|
||||
}
|
||||
off += syscall.CmsgSpace(sysSizeofPacketInfo)
|
||||
}
|
||||
if len(cm.NextHop) == net.IPv6len {
|
||||
m := (*syscall.Cmsghdr)(unsafe.Pointer(&oob[off]))
|
||||
m.Level = ianaProtocolIPv6
|
||||
m.Type = sysSockoptNextHop
|
||||
m.SetLen(syscall.CmsgLen(syscall.SizeofSockaddrInet6))
|
||||
sa := (*syscall.RawSockaddrInet6)(unsafe.Pointer(&oob[off+syscall.CmsgLen(0)]))
|
||||
setSockaddr(sa, cm.NextHop, cm.IfIndex)
|
||||
off += syscall.CmsgSpace(syscall.SizeofSockaddrInet6)
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
27
Godeps/_workspace/src/code.google.com/p/go.net/ipv6/control_rfc3542_windows.go
generated
vendored
27
Godeps/_workspace/src/code.google.com/p/go.net/ipv6/control_rfc3542_windows.go
generated
vendored
@@ -1,27 +0,0 @@
|
||||
// Copyright 2013 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package ipv6
|
||||
|
||||
import "syscall"
|
||||
|
||||
func setControlMessage(fd syscall.Handle, opt *rawOpt, cf ControlFlags, on bool) error {
|
||||
// TODO(mikio): Implement this
|
||||
return syscall.EWINDOWS
|
||||
}
|
||||
|
||||
func newControlMessage(opt *rawOpt) (oob []byte) {
|
||||
// TODO(mikio): Implement this
|
||||
return nil
|
||||
}
|
||||
|
||||
func parseControlMessage(b []byte) (*ControlMessage, error) {
|
||||
// TODO(mikio): Implement this
|
||||
return nil, syscall.EWINDOWS
|
||||
}
|
||||
|
||||
func marshalControlMessage(cm *ControlMessage) (oob []byte) {
|
||||
// TODO(mikio): Implement this
|
||||
return nil
|
||||
}
|
||||
178
Godeps/_workspace/src/code.google.com/p/go.net/ipv6/dgramopt_posix.go
generated
vendored
178
Godeps/_workspace/src/code.google.com/p/go.net/ipv6/dgramopt_posix.go
generated
vendored
@@ -1,178 +0,0 @@
|
||||
// Copyright 2013 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build darwin freebsd linux netbsd openbsd windows
|
||||
|
||||
package ipv6
|
||||
|
||||
import (
|
||||
"net"
|
||||
"syscall"
|
||||
)
|
||||
|
||||
// MulticastHopLimit returns the hop limit field value for outgoing
|
||||
// multicast packets.
|
||||
func (c *dgramOpt) MulticastHopLimit() (int, error) {
|
||||
if !c.ok() {
|
||||
return 0, syscall.EINVAL
|
||||
}
|
||||
fd, err := c.sysfd()
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return ipv6MulticastHopLimit(fd)
|
||||
}
|
||||
|
||||
// SetMulticastHopLimit sets the hop limit field value for future
|
||||
// outgoing multicast packets.
|
||||
func (c *dgramOpt) SetMulticastHopLimit(hoplim int) error {
|
||||
if !c.ok() {
|
||||
return syscall.EINVAL
|
||||
}
|
||||
fd, err := c.sysfd()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return setIPv6MulticastHopLimit(fd, hoplim)
|
||||
}
|
||||
|
||||
// MulticastInterface returns the default interface for multicast
|
||||
// packet transmissions.
|
||||
func (c *dgramOpt) MulticastInterface() (*net.Interface, error) {
|
||||
if !c.ok() {
|
||||
return nil, syscall.EINVAL
|
||||
}
|
||||
fd, err := c.sysfd()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return ipv6MulticastInterface(fd)
|
||||
}
|
||||
|
||||
// SetMulticastInterface sets the default interface for future
|
||||
// multicast packet transmissions.
|
||||
func (c *dgramOpt) SetMulticastInterface(ifi *net.Interface) error {
|
||||
if !c.ok() {
|
||||
return syscall.EINVAL
|
||||
}
|
||||
fd, err := c.sysfd()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return setIPv6MulticastInterface(fd, ifi)
|
||||
}
|
||||
|
||||
// MulticastLoopback reports whether transmitted multicast packets
|
||||
// should be copied and send back to the originator.
|
||||
func (c *dgramOpt) MulticastLoopback() (bool, error) {
|
||||
if !c.ok() {
|
||||
return false, syscall.EINVAL
|
||||
}
|
||||
fd, err := c.sysfd()
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
return ipv6MulticastLoopback(fd)
|
||||
}
|
||||
|
||||
// SetMulticastLoopback sets whether transmitted multicast packets
|
||||
// should be copied and send back to the originator.
|
||||
func (c *dgramOpt) SetMulticastLoopback(on bool) error {
|
||||
if !c.ok() {
|
||||
return syscall.EINVAL
|
||||
}
|
||||
fd, err := c.sysfd()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return setIPv6MulticastLoopback(fd, on)
|
||||
}
|
||||
|
||||
// JoinGroup joins the group address group on the interface ifi.
|
||||
// It uses the system assigned multicast interface when ifi is nil,
|
||||
// although this is not recommended because the assignment depends on
|
||||
// platforms and sometimes it might require routing configuration.
|
||||
func (c *dgramOpt) JoinGroup(ifi *net.Interface, group net.Addr) error {
|
||||
if !c.ok() {
|
||||
return syscall.EINVAL
|
||||
}
|
||||
fd, err := c.sysfd()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
grp := netAddrToIP16(group)
|
||||
if grp == nil {
|
||||
return errMissingAddress
|
||||
}
|
||||
return joinIPv6Group(fd, ifi, grp)
|
||||
}
|
||||
|
||||
// LeaveGroup leaves the group address group on the interface ifi.
|
||||
func (c *dgramOpt) LeaveGroup(ifi *net.Interface, group net.Addr) error {
|
||||
if !c.ok() {
|
||||
return syscall.EINVAL
|
||||
}
|
||||
fd, err := c.sysfd()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
grp := netAddrToIP16(group)
|
||||
if grp == nil {
|
||||
return errMissingAddress
|
||||
}
|
||||
return leaveIPv6Group(fd, ifi, grp)
|
||||
}
|
||||
|
||||
// Checksum reports whether the kernel will compute, store or verify a
|
||||
// checksum for both incoming and outgoing packets. If on is true, it
|
||||
// returns an offset in bytes into the data of where the checksum
|
||||
// field is located.
|
||||
func (c *dgramOpt) Checksum() (on bool, offset int, err error) {
|
||||
if !c.ok() {
|
||||
return false, 0, syscall.EINVAL
|
||||
}
|
||||
fd, err := c.sysfd()
|
||||
if err != nil {
|
||||
return false, 0, err
|
||||
}
|
||||
return ipv6Checksum(fd)
|
||||
}
|
||||
|
||||
// SetChecksum enables the kernel checksum processing. If on is ture,
|
||||
// the offset should be an offset in bytes into the data of where the
|
||||
// checksum field is located.
|
||||
func (c *dgramOpt) SetChecksum(on bool, offset int) error {
|
||||
if !c.ok() {
|
||||
return syscall.EINVAL
|
||||
}
|
||||
fd, err := c.sysfd()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return setIPv6Checksum(fd, on, offset)
|
||||
}
|
||||
|
||||
// ICMPFilter returns an ICMP filter.
|
||||
func (c *dgramOpt) ICMPFilter() (*ICMPFilter, error) {
|
||||
if !c.ok() {
|
||||
return nil, syscall.EINVAL
|
||||
}
|
||||
fd, err := c.sysfd()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return ipv6ICMPFilter(fd)
|
||||
}
|
||||
|
||||
// SetICMPFilter deploys the ICMP filter.
|
||||
func (c *dgramOpt) SetICMPFilter(f *ICMPFilter) error {
|
||||
if !c.ok() {
|
||||
return syscall.EINVAL
|
||||
}
|
||||
fd, err := c.sysfd()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return setIPv6ICMPFilter(fd, f)
|
||||
}
|
||||
95
Godeps/_workspace/src/code.google.com/p/go.net/ipv6/dgramopt_stub.go
generated
vendored
95
Godeps/_workspace/src/code.google.com/p/go.net/ipv6/dgramopt_stub.go
generated
vendored
@@ -1,95 +0,0 @@
|
||||
// Copyright 2013 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build dragonfly plan9 solaris
|
||||
|
||||
package ipv6
|
||||
|
||||
import "net"
|
||||
|
||||
// MulticastHopLimit returns the hop limit field value for outgoing
|
||||
// multicast packets.
|
||||
func (c *dgramOpt) MulticastHopLimit() (int, error) {
|
||||
// TODO(mikio): Implement this
|
||||
return 0, errOpNoSupport
|
||||
}
|
||||
|
||||
// SetMulticastHopLimit sets the hop limit field value for future
|
||||
// outgoing multicast packets.
|
||||
func (c *dgramOpt) SetMulticastHopLimit(hoplim int) error {
|
||||
// TODO(mikio): Implement this
|
||||
return errOpNoSupport
|
||||
}
|
||||
|
||||
// MulticastInterface returns the default interface for multicast
|
||||
// packet transmissions.
|
||||
func (c *dgramOpt) MulticastInterface() (*net.Interface, error) {
|
||||
// TODO(mikio): Implement this
|
||||
return nil, errOpNoSupport
|
||||
}
|
||||
|
||||
// SetMulticastInterface sets the default interface for future
|
||||
// multicast packet transmissions.
|
||||
func (c *dgramOpt) SetMulticastInterface(ifi *net.Interface) error {
|
||||
// TODO(mikio): Implement this
|
||||
return errOpNoSupport
|
||||
}
|
||||
|
||||
// MulticastLoopback reports whether transmitted multicast packets
|
||||
// should be copied and send back to the originator.
|
||||
func (c *dgramOpt) MulticastLoopback() (bool, error) {
|
||||
// TODO(mikio): Implement this
|
||||
return false, errOpNoSupport
|
||||
}
|
||||
|
||||
// SetMulticastLoopback sets whether transmitted multicast packets
|
||||
// should be copied and send back to the originator.
|
||||
func (c *dgramOpt) SetMulticastLoopback(on bool) error {
|
||||
// TODO(mikio): Implement this
|
||||
return errOpNoSupport
|
||||
}
|
||||
|
||||
// JoinGroup joins the group address group on the interface ifi.
|
||||
// It uses the system assigned multicast interface when ifi is nil,
|
||||
// although this is not recommended because the assignment depends on
|
||||
// platforms and sometimes it might require routing configuration.
|
||||
func (c *dgramOpt) JoinGroup(ifi *net.Interface, group net.Addr) error {
|
||||
// TODO(mikio): Implement this
|
||||
return errOpNoSupport
|
||||
}
|
||||
|
||||
// LeaveGroup leaves the group address group on the interface ifi.
|
||||
func (c *dgramOpt) LeaveGroup(ifi *net.Interface, group net.Addr) error {
|
||||
// TODO(mikio): Implement this
|
||||
return errOpNoSupport
|
||||
}
|
||||
|
||||
// Checksum reports whether the kernel will compute, store or verify a
|
||||
// checksum for both incoming and outgoing packets. If on is true, it
|
||||
// returns an offset in bytes into the data of where the checksum
|
||||
// field is located.
|
||||
func (c *dgramOpt) Checksum() (on bool, offset int, err error) {
|
||||
// TODO(mikio): Implement this
|
||||
return false, 0, errOpNoSupport
|
||||
}
|
||||
|
||||
// SetChecksum enables the kernel checksum processing. If on is ture,
|
||||
// the offset should be an offset in bytes into the data of where the
|
||||
// checksum field is located.
|
||||
func (c *dgramOpt) SetChecksum(on bool, offset int) error {
|
||||
// TODO(mikio): Implement this
|
||||
return errOpNoSupport
|
||||
}
|
||||
|
||||
// ICMPFilter returns an ICMP filter.
|
||||
func (c *dgramOpt) ICMPFilter() (*ICMPFilter, error) {
|
||||
// TODO(mikio): Implement this
|
||||
return nil, errOpNoSupport
|
||||
}
|
||||
|
||||
// SetICMPFilter deploys the ICMP filter.
|
||||
func (c *dgramOpt) SetICMPFilter(f *ICMPFilter) error {
|
||||
// TODO(mikio): Implement this
|
||||
return errOpNoSupport
|
||||
}
|
||||
193
Godeps/_workspace/src/code.google.com/p/go.net/ipv6/doc.go
generated
vendored
193
Godeps/_workspace/src/code.google.com/p/go.net/ipv6/doc.go
generated
vendored
@@ -1,193 +0,0 @@
|
||||
// Copyright 2013 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// Package ipv6 implements IP-level socket options for the Internet
|
||||
// Protocol version 6.
|
||||
//
|
||||
// The package provides IP-level socket options that allow
|
||||
// manipulation of IPv6 facilities. The IPv6 and socket options for
|
||||
// IPv6 are defined in RFC 2460, RFC 3493 and RFC 3542.
|
||||
//
|
||||
//
|
||||
// Unicasting
|
||||
//
|
||||
// The options for unicasting are available for net.TCPConn,
|
||||
// net.UDPConn and net.IPConn which are created as network connections
|
||||
// that use the IPv6 transport. When a single TCP connection carrying
|
||||
// a data flow of multiple packets needs to indicate the flow is
|
||||
// important, ipv6.Conn is used to set the traffic class field on the
|
||||
// IPv6 header for each packet.
|
||||
//
|
||||
// ln, err := net.Listen("tcp6", "[::]:1024")
|
||||
// if err != nil {
|
||||
// // error handling
|
||||
// }
|
||||
// defer ln.Close()
|
||||
// for {
|
||||
// c, err := ln.Accept()
|
||||
// if err != nil {
|
||||
// // error handling
|
||||
// }
|
||||
// go func(c net.Conn) {
|
||||
// defer c.Close()
|
||||
//
|
||||
// The outgoing packets will be labeled DiffServ assured forwarding
|
||||
// class 1 low drop precedence, as known as AF11 packets.
|
||||
//
|
||||
// if err := ipv6.NewConn(c).SetTrafficClass(DiffServAF11); err != nil {
|
||||
// // error handling
|
||||
// }
|
||||
// if _, err := c.Write(data); err != nil {
|
||||
// // error handling
|
||||
// }
|
||||
// }(c)
|
||||
// }
|
||||
//
|
||||
//
|
||||
// Multicasting
|
||||
//
|
||||
// The options for multicasting are available for net.UDPConn and
|
||||
// net.IPconn which are created as network connections that use the
|
||||
// IPv6 transport. A few network facilities must be prepared before
|
||||
// you begin multicasting, at a minimum joining network interfaces and
|
||||
// multicast groups.
|
||||
//
|
||||
// en0, err := net.InterfaceByName("en0")
|
||||
// if err != nil {
|
||||
// // error handling
|
||||
// }
|
||||
// en1, err := net.InterfaceByIndex(911)
|
||||
// if err != nil {
|
||||
// // error handling
|
||||
// }
|
||||
// group := net.ParseIP("ff02::114")
|
||||
//
|
||||
// First, an application listens to an appropriate address with an
|
||||
// appropriate service port.
|
||||
//
|
||||
// c, err := net.ListenPacket("udp6", "[::]:1024")
|
||||
// if err != nil {
|
||||
// // error handling
|
||||
// }
|
||||
// defer c.Close()
|
||||
//
|
||||
// Second, the application joins multicast groups, starts listening to
|
||||
// the groups on the specified network interfaces. Note that the
|
||||
// service port for transport layer protocol does not matter with this
|
||||
// operation as joining groups affects only network and link layer
|
||||
// protocols, such as IPv6 and Ethernet.
|
||||
//
|
||||
// p := ipv6.NewPacketConn(c)
|
||||
// if err := p.JoinGroup(en0, &net.UDPAddr{IP: group}); err != nil {
|
||||
// // error handling
|
||||
// }
|
||||
// if err := p.JoinGroup(en1, &net.UDPAddr{IP: group}); err != nil {
|
||||
// // error handling
|
||||
// }
|
||||
//
|
||||
// The application might set per packet control message transmissions
|
||||
// between the protocol stack within the kernel. When the application
|
||||
// needs a destination address on an incoming packet,
|
||||
// SetControlMessage of ipv6.PacketConn is used to enable control
|
||||
// message transmissons.
|
||||
//
|
||||
// if err := p.SetControlMessage(ipv6.FlagDst, true); err != nil {
|
||||
// // error handling
|
||||
// }
|
||||
//
|
||||
// The application could identify whether the received packets are
|
||||
// of interest by using the control message that contains the
|
||||
// destination address of the received packet.
|
||||
//
|
||||
// b := make([]byte, 1500)
|
||||
// for {
|
||||
// n, rcm, src, err := p.ReadFrom(b)
|
||||
// if err != nil {
|
||||
// // error handling
|
||||
// }
|
||||
// if rcm.Dst.IsMulticast() {
|
||||
// if rcm.Dst.Equal(group)
|
||||
// // joined group, do something
|
||||
// } else {
|
||||
// // unknown group, discard
|
||||
// continue
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// The application can also send both unicast and multicast packets.
|
||||
//
|
||||
// p.SetTrafficClass(DiffServCS0)
|
||||
// p.SetHopLimit(16)
|
||||
// if _, err := p.WriteTo(data[:n], nil, src); err != nil {
|
||||
// // error handling
|
||||
// }
|
||||
// dst := &net.UDPAddr{IP: group, Port: 1024}
|
||||
// wcm := ipv6.ControlMessage{TrafficClass: DiffServCS7, HopLimit: 1}
|
||||
// for _, ifi := range []*net.Interface{en0, en1} {
|
||||
// wcm.IfIndex = ifi.Index
|
||||
// if _, err := p.WriteTo(data[:n], &wcm, dst); err != nil {
|
||||
// // error handling
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
//
|
||||
//
|
||||
// More multicasting
|
||||
//
|
||||
// An application that uses PacketConn may join multiple multicast
|
||||
// groups. For example, a UDP listener with port 1024 might join two
|
||||
// different groups across over two different network interfaces by
|
||||
// using:
|
||||
//
|
||||
// c, err := net.ListenPacket("udp6", "[::]:1024")
|
||||
// if err != nil {
|
||||
// // error handling
|
||||
// }
|
||||
// defer c.Close()
|
||||
// p := ipv6.NewPacketConn(c)
|
||||
// if err := p.JoinGroup(en0, &net.UDPAddr{IP: net.ParseIP("ff02::1:114")}); err != nil {
|
||||
// // error handling
|
||||
// }
|
||||
// if err := p.JoinGroup(en0, &net.UDPAddr{IP: net.ParseIP("ff02::2:114")}); err != nil {
|
||||
// // error handling
|
||||
// }
|
||||
// if err := p.JoinGroup(en1, &net.UDPAddr{IP: net.ParseIP("ff02::2:114")}); err != nil {
|
||||
// // error handling
|
||||
// }
|
||||
//
|
||||
// It is possible for multiple UDP listeners that listen on the same
|
||||
// UDP port to join the same multicast group. The net package will
|
||||
// provide a socket that listens to a wildcard address with reusable
|
||||
// UDP port when an appropriate multicast address prefix is passed to
|
||||
// the net.ListenPacket or net.ListenUDP.
|
||||
//
|
||||
// c1, err := net.ListenPacket("udp6", "[ff02::]:1024")
|
||||
// if err != nil {
|
||||
// // error handling
|
||||
// }
|
||||
// defer c1.Close()
|
||||
// c2, err := net.ListenPacket("udp6", "[ff02::]:1024")
|
||||
// if err != nil {
|
||||
// // error handling
|
||||
// }
|
||||
// defer c2.Close()
|
||||
// p1 := ipv6.NewPacketConn(c1)
|
||||
// if err := p1.JoinGroup(en0, &net.UDPAddr{IP: net.ParseIP("ff02::114")}); err != nil {
|
||||
// // error handling
|
||||
// }
|
||||
// p2 := ipv6.NewPacketConn(c2)
|
||||
// if err := p2.JoinGroup(en0, &net.UDPAddr{IP: net.ParseIP("ff02::114")}); err != nil {
|
||||
// // error handling
|
||||
// }
|
||||
//
|
||||
// Also it is possible for the application to leave or rejoin a
|
||||
// multicast group on the network interface.
|
||||
//
|
||||
// if err := p.LeaveGroup(en0, &net.UDPAddr{IP: net.ParseIP("ff02::114")}); err != nil {
|
||||
// // error handling
|
||||
// }
|
||||
// if err := p.JoinGroup(en0, &net.UDPAddr{IP: net.ParseIP("ff01::114")}); err != nil {
|
||||
// // error handling
|
||||
// }
|
||||
package ipv6
|
||||
119
Godeps/_workspace/src/code.google.com/p/go.net/ipv6/endpoint.go
generated
vendored
119
Godeps/_workspace/src/code.google.com/p/go.net/ipv6/endpoint.go
generated
vendored
@@ -1,119 +0,0 @@
|
||||
// Copyright 2013 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package ipv6
|
||||
|
||||
import (
|
||||
"net"
|
||||
"syscall"
|
||||
"time"
|
||||
)
|
||||
|
||||
// A Conn represents a network endpoint that uses IPv6 transport.
|
||||
// It allows to set basic IP-level socket options such as traffic
|
||||
// class and hop limit.
|
||||
type Conn struct {
|
||||
genericOpt
|
||||
}
|
||||
|
||||
type genericOpt struct {
|
||||
net.Conn
|
||||
}
|
||||
|
||||
func (c *genericOpt) ok() bool { return c != nil && c.Conn != nil }
|
||||
|
||||
// PathMTU returns a path MTU value for the destination associated
|
||||
// with the endpoint.
|
||||
func (c *Conn) PathMTU() (int, error) {
|
||||
if !c.genericOpt.ok() {
|
||||
return 0, syscall.EINVAL
|
||||
}
|
||||
fd, err := c.genericOpt.sysfd()
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return ipv6PathMTU(fd)
|
||||
}
|
||||
|
||||
// NewConn returns a new Conn.
|
||||
func NewConn(c net.Conn) *Conn {
|
||||
return &Conn{
|
||||
genericOpt: genericOpt{Conn: c},
|
||||
}
|
||||
}
|
||||
|
||||
// A PacketConn represents a packet network endpoint that uses IPv6
|
||||
// transport. It is used to control several IP-level socket options
|
||||
// including IPv6 header manipulation. It also provides datagram
|
||||
// based network I/O methods specific to the IPv6 and higher layer
|
||||
// protocols such as OSPF, GRE, and UDP.
|
||||
type PacketConn struct {
|
||||
genericOpt
|
||||
dgramOpt
|
||||
payloadHandler
|
||||
}
|
||||
|
||||
type dgramOpt struct {
|
||||
net.PacketConn
|
||||
}
|
||||
|
||||
func (c *dgramOpt) ok() bool { return c != nil && c.PacketConn != nil }
|
||||
|
||||
// SetControlMessage allows to receive the per packet basis IP-level
|
||||
// socket options.
|
||||
func (c *PacketConn) SetControlMessage(cf ControlFlags, on bool) error {
|
||||
if !c.payloadHandler.ok() {
|
||||
return syscall.EINVAL
|
||||
}
|
||||
fd, err := c.payloadHandler.sysfd()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return setControlMessage(fd, &c.payloadHandler.rawOpt, cf, on)
|
||||
}
|
||||
|
||||
// SetDeadline sets the read and write deadlines associated with the
|
||||
// endpoint.
|
||||
func (c *PacketConn) SetDeadline(t time.Time) error {
|
||||
if !c.payloadHandler.ok() {
|
||||
return syscall.EINVAL
|
||||
}
|
||||
return c.payloadHandler.SetDeadline(t)
|
||||
}
|
||||
|
||||
// SetReadDeadline sets the read deadline associated with the
|
||||
// endpoint.
|
||||
func (c *PacketConn) SetReadDeadline(t time.Time) error {
|
||||
if !c.payloadHandler.ok() {
|
||||
return syscall.EINVAL
|
||||
}
|
||||
return c.payloadHandler.SetReadDeadline(t)
|
||||
}
|
||||
|
||||
// SetWriteDeadline sets the write deadline associated with the
|
||||
// endpoint.
|
||||
func (c *PacketConn) SetWriteDeadline(t time.Time) error {
|
||||
if !c.payloadHandler.ok() {
|
||||
return syscall.EINVAL
|
||||
}
|
||||
return c.payloadHandler.SetWriteDeadline(t)
|
||||
}
|
||||
|
||||
// Close closes the endpoint.
|
||||
func (c *PacketConn) Close() error {
|
||||
if !c.payloadHandler.ok() {
|
||||
return syscall.EINVAL
|
||||
}
|
||||
return c.payloadHandler.Close()
|
||||
}
|
||||
|
||||
// NewPacketConn returns a new PacketConn using c as its underlying
|
||||
// transport.
|
||||
func NewPacketConn(c net.PacketConn) *PacketConn {
|
||||
return &PacketConn{
|
||||
genericOpt: genericOpt{Conn: c.(net.Conn)},
|
||||
dgramOpt: dgramOpt{PacketConn: c},
|
||||
payloadHandler: payloadHandler{PacketConn: c},
|
||||
}
|
||||
}
|
||||
241
Godeps/_workspace/src/code.google.com/p/go.net/ipv6/gen.go
generated
vendored
241
Godeps/_workspace/src/code.google.com/p/go.net/ipv6/gen.go
generated
vendored
@@ -1,241 +0,0 @@
|
||||
// Copyright 2013 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build ignore
|
||||
|
||||
// This program generates internet protocol constatns and tables by
|
||||
// reading IANA protocol registries.
|
||||
//
|
||||
// Usage:
|
||||
// go run gen.go > iana.go
|
||||
package main
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/xml"
|
||||
"fmt"
|
||||
"go/format"
|
||||
"io"
|
||||
"net/http"
|
||||
"os"
|
||||
"strconv"
|
||||
"strings"
|
||||
)
|
||||
|
||||
var registries = []struct {
|
||||
url string
|
||||
parse func(io.Writer, io.Reader) error
|
||||
}{
|
||||
{
|
||||
"http://www.iana.org/assignments/icmpv6-parameters/icmpv6-parameters.xml",
|
||||
parseICMPv6Parameters,
|
||||
},
|
||||
{
|
||||
"http://www.iana.org/assignments/protocol-numbers/protocol-numbers.xml",
|
||||
parseProtocolNumbers,
|
||||
},
|
||||
}
|
||||
|
||||
func main() {
|
||||
var bb bytes.Buffer
|
||||
fmt.Fprintf(&bb, "// go run gen.go\n")
|
||||
fmt.Fprintf(&bb, "// GENERATED BY THE COMMAND ABOVE; DO NOT EDIT\n\n")
|
||||
fmt.Fprintf(&bb, "package ipv6\n\n")
|
||||
for _, r := range registries {
|
||||
resp, err := http.Get(r.url)
|
||||
if err != nil {
|
||||
fmt.Fprintln(os.Stderr, err)
|
||||
os.Exit(1)
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
if resp.StatusCode != http.StatusOK {
|
||||
fmt.Fprintf(os.Stderr, "got HTTP status code %v for %v\n", resp.StatusCode, r.url)
|
||||
os.Exit(1)
|
||||
}
|
||||
if err := r.parse(&bb, resp.Body); err != nil {
|
||||
fmt.Fprintln(os.Stderr, err)
|
||||
os.Exit(1)
|
||||
}
|
||||
fmt.Fprintf(&bb, "\n")
|
||||
}
|
||||
b, err := format.Source(bb.Bytes())
|
||||
if err != nil {
|
||||
fmt.Fprintln(os.Stderr, err)
|
||||
os.Exit(1)
|
||||
}
|
||||
os.Stdout.Write(b)
|
||||
}
|
||||
|
||||
func parseICMPv6Parameters(w io.Writer, r io.Reader) error {
|
||||
dec := xml.NewDecoder(r)
|
||||
var icp icmpv6Parameters
|
||||
if err := dec.Decode(&icp); err != nil {
|
||||
return err
|
||||
}
|
||||
prs := icp.escape()
|
||||
fmt.Fprintf(w, "// %s, Updated: %s\n", icp.Title, icp.Updated)
|
||||
fmt.Fprintf(w, "const (\n")
|
||||
for _, pr := range prs {
|
||||
if pr.Name == "" {
|
||||
continue
|
||||
}
|
||||
fmt.Fprintf(w, "ICMPType%s ICMPType = %d", pr.Name, pr.Value)
|
||||
fmt.Fprintf(w, "// %s\n", pr.OrigName)
|
||||
}
|
||||
fmt.Fprintf(w, ")\n\n")
|
||||
fmt.Fprintf(w, "// %s, Updated: %s\n", icp.Title, icp.Updated)
|
||||
fmt.Fprintf(w, "var icmpTypes = map[ICMPType]string{\n")
|
||||
for _, pr := range prs {
|
||||
if pr.Name == "" {
|
||||
continue
|
||||
}
|
||||
fmt.Fprintf(w, "%d: %q,\n", pr.Value, strings.ToLower(pr.OrigName))
|
||||
}
|
||||
fmt.Fprintf(w, "}\n")
|
||||
return nil
|
||||
}
|
||||
|
||||
type icmpv6Parameters struct {
|
||||
XMLName xml.Name `xml:"registry"`
|
||||
Title string `xml:"title"`
|
||||
Updated string `xml:"updated"`
|
||||
Registries []struct {
|
||||
Title string `xml:"title"`
|
||||
Records []struct {
|
||||
Value string `xml:"value"`
|
||||
Name string `xml:"name"`
|
||||
} `xml:"record"`
|
||||
} `xml:"registry"`
|
||||
}
|
||||
|
||||
type canonICMPv6ParamRecord struct {
|
||||
OrigName string
|
||||
Name string
|
||||
Value int
|
||||
}
|
||||
|
||||
func (icp *icmpv6Parameters) escape() []canonICMPv6ParamRecord {
|
||||
id := -1
|
||||
for i, r := range icp.Registries {
|
||||
if strings.Contains(r.Title, "Type") || strings.Contains(r.Title, "type") {
|
||||
id = i
|
||||
break
|
||||
}
|
||||
}
|
||||
if id < 0 {
|
||||
return nil
|
||||
}
|
||||
prs := make([]canonICMPv6ParamRecord, len(icp.Registries[id].Records))
|
||||
sr := strings.NewReplacer(
|
||||
"Messages", "",
|
||||
"Message", "",
|
||||
"ICMP", "",
|
||||
"+", "P",
|
||||
"-", "",
|
||||
"/", "",
|
||||
".", "",
|
||||
" ", "",
|
||||
)
|
||||
for i, pr := range icp.Registries[id].Records {
|
||||
if strings.Contains(pr.Name, "Reserved") ||
|
||||
strings.Contains(pr.Name, "Unassigned") ||
|
||||
strings.Contains(pr.Name, "Deprecated") ||
|
||||
strings.Contains(pr.Name, "Experiment") ||
|
||||
strings.Contains(pr.Name, "experiment") {
|
||||
continue
|
||||
}
|
||||
ss := strings.Split(pr.Name, "\n")
|
||||
if len(ss) > 1 {
|
||||
prs[i].Name = strings.Join(ss, " ")
|
||||
} else {
|
||||
prs[i].Name = ss[0]
|
||||
}
|
||||
s := strings.TrimSpace(prs[i].Name)
|
||||
prs[i].OrigName = s
|
||||
prs[i].Name = sr.Replace(s)
|
||||
prs[i].Value, _ = strconv.Atoi(pr.Value)
|
||||
}
|
||||
return prs
|
||||
}
|
||||
|
||||
func parseProtocolNumbers(w io.Writer, r io.Reader) error {
|
||||
dec := xml.NewDecoder(r)
|
||||
var pn protocolNumbers
|
||||
if err := dec.Decode(&pn); err != nil {
|
||||
return err
|
||||
}
|
||||
prs := pn.escape()
|
||||
fmt.Fprintf(w, "// %s, Updated: %s\n", pn.Title, pn.Updated)
|
||||
fmt.Fprintf(w, "const (\n")
|
||||
for _, pr := range prs {
|
||||
if pr.Name == "" {
|
||||
continue
|
||||
}
|
||||
fmt.Fprintf(w, "ianaProtocol%s = %d", pr.Name, pr.Value)
|
||||
s := pr.Descr
|
||||
if s == "" {
|
||||
s = pr.OrigName
|
||||
}
|
||||
fmt.Fprintf(w, "// %s\n", s)
|
||||
}
|
||||
fmt.Fprintf(w, ")\n")
|
||||
return nil
|
||||
}
|
||||
|
||||
type protocolNumbers struct {
|
||||
XMLName xml.Name `xml:"registry"`
|
||||
Title string `xml:"title"`
|
||||
Updated string `xml:"updated"`
|
||||
RegTitle string `xml:"registry>title"`
|
||||
Note string `xml:"registry>note"`
|
||||
Records []struct {
|
||||
Value string `xml:"value"`
|
||||
Name string `xml:"name"`
|
||||
Descr string `xml:"description"`
|
||||
} `xml:"registry>record"`
|
||||
}
|
||||
|
||||
type canonProtocolRecord struct {
|
||||
OrigName string
|
||||
Name string
|
||||
Descr string
|
||||
Value int
|
||||
}
|
||||
|
||||
func (pn *protocolNumbers) escape() []canonProtocolRecord {
|
||||
prs := make([]canonProtocolRecord, len(pn.Records))
|
||||
sr := strings.NewReplacer(
|
||||
"-in-", "in",
|
||||
"-within-", "within",
|
||||
"-over-", "over",
|
||||
"+", "P",
|
||||
"-", "",
|
||||
"/", "",
|
||||
".", "",
|
||||
" ", "",
|
||||
)
|
||||
for i, pr := range pn.Records {
|
||||
prs[i].OrigName = pr.Name
|
||||
s := strings.TrimSpace(pr.Name)
|
||||
switch pr.Name {
|
||||
case "ISIS over IPv4":
|
||||
prs[i].Name = "ISIS"
|
||||
case "manet":
|
||||
prs[i].Name = "MANET"
|
||||
default:
|
||||
prs[i].Name = sr.Replace(s)
|
||||
}
|
||||
ss := strings.Split(pr.Descr, "\n")
|
||||
for i := range ss {
|
||||
ss[i] = strings.TrimSpace(ss[i])
|
||||
}
|
||||
if len(ss) > 1 {
|
||||
prs[i].Descr = strings.Join(ss, " ")
|
||||
} else {
|
||||
prs[i].Descr = ss[0]
|
||||
}
|
||||
prs[i].Value, _ = strconv.Atoi(pr.Value)
|
||||
}
|
||||
return prs
|
||||
}
|
||||
60
Godeps/_workspace/src/code.google.com/p/go.net/ipv6/genericopt_posix.go
generated
vendored
60
Godeps/_workspace/src/code.google.com/p/go.net/ipv6/genericopt_posix.go
generated
vendored
@@ -1,60 +0,0 @@
|
||||
// Copyright 2013 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build darwin freebsd linux netbsd openbsd windows
|
||||
|
||||
package ipv6
|
||||
|
||||
import "syscall"
|
||||
|
||||
// TrafficClass returns the traffic class field value for outgoing
|
||||
// packets.
|
||||
func (c *genericOpt) TrafficClass() (int, error) {
|
||||
if !c.ok() {
|
||||
return 0, syscall.EINVAL
|
||||
}
|
||||
fd, err := c.sysfd()
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return ipv6TrafficClass(fd)
|
||||
}
|
||||
|
||||
// SetTrafficClass sets the traffic class field value for future
|
||||
// outgoing packets.
|
||||
func (c *genericOpt) SetTrafficClass(tclass int) error {
|
||||
if !c.ok() {
|
||||
return syscall.EINVAL
|
||||
}
|
||||
fd, err := c.sysfd()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return setIPv6TrafficClass(fd, tclass)
|
||||
}
|
||||
|
||||
// HopLimit returns the hop limit field value for outgoing packets.
|
||||
func (c *genericOpt) HopLimit() (int, error) {
|
||||
if !c.ok() {
|
||||
return 0, syscall.EINVAL
|
||||
}
|
||||
fd, err := c.sysfd()
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return ipv6HopLimit(fd)
|
||||
}
|
||||
|
||||
// SetHopLimit sets the hop limit field value for future outgoing
|
||||
// packets.
|
||||
func (c *genericOpt) SetHopLimit(hoplim int) error {
|
||||
if !c.ok() {
|
||||
return syscall.EINVAL
|
||||
}
|
||||
fd, err := c.sysfd()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return setIPv6HopLimit(fd, hoplim)
|
||||
}
|
||||
34
Godeps/_workspace/src/code.google.com/p/go.net/ipv6/genericopt_stub.go
generated
vendored
34
Godeps/_workspace/src/code.google.com/p/go.net/ipv6/genericopt_stub.go
generated
vendored
@@ -1,34 +0,0 @@
|
||||
// Copyright 2013 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build dragonfly plan9 solaris
|
||||
|
||||
package ipv6
|
||||
|
||||
// TrafficClass returns the traffic class field value for outgoing
|
||||
// packets.
|
||||
func (c *genericOpt) TrafficClass() (int, error) {
|
||||
// TODO(mikio): Implement this
|
||||
return 0, errOpNoSupport
|
||||
}
|
||||
|
||||
// SetTrafficClass sets the traffic class field value for future
|
||||
// outgoing packets.
|
||||
func (c *genericOpt) SetTrafficClass(tclass int) error {
|
||||
// TODO(mikio): Implement this
|
||||
return errOpNoSupport
|
||||
}
|
||||
|
||||
// HopLimit returns the hop limit field value for outgoing packets.
|
||||
func (c *genericOpt) HopLimit() (int, error) {
|
||||
// TODO(mikio): Implement this
|
||||
return 0, errOpNoSupport
|
||||
}
|
||||
|
||||
// SetHopLimit sets the hop limit field value for future outgoing
|
||||
// packets.
|
||||
func (c *genericOpt) SetHopLimit(hoplim int) error {
|
||||
// TODO(mikio): Implement this
|
||||
return errOpNoSupport
|
||||
}
|
||||
195
Godeps/_workspace/src/code.google.com/p/go.net/ipv6/gentest.go
generated
vendored
195
Godeps/_workspace/src/code.google.com/p/go.net/ipv6/gentest.go
generated
vendored
@@ -1,195 +0,0 @@
|
||||
// Copyright 2013 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build ignore
|
||||
|
||||
// This program generates internet protocol constants by reading IANA
|
||||
// protocol registries.
|
||||
//
|
||||
// Usage:
|
||||
// go run gentest.go > iana_test.go
|
||||
package main
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/xml"
|
||||
"fmt"
|
||||
"go/format"
|
||||
"io"
|
||||
"net/http"
|
||||
"os"
|
||||
"strconv"
|
||||
"strings"
|
||||
)
|
||||
|
||||
var registries = []struct {
|
||||
url string
|
||||
parse func(io.Writer, io.Reader) error
|
||||
}{
|
||||
{
|
||||
"http://www.iana.org/assignments/dscp-registry/dscp-registry.xml",
|
||||
parseDSCPRegistry,
|
||||
},
|
||||
{
|
||||
"http://www.iana.org/assignments/ipv4-tos-byte/ipv4-tos-byte.xml",
|
||||
parseTOSTCByte,
|
||||
},
|
||||
}
|
||||
|
||||
func main() {
|
||||
var bb bytes.Buffer
|
||||
fmt.Fprintf(&bb, "// go run gentest.go\n")
|
||||
fmt.Fprintf(&bb, "// GENERATED BY THE COMMAND ABOVE; DO NOT EDIT\n\n")
|
||||
fmt.Fprintf(&bb, "package ipv6_test\n\n")
|
||||
for _, r := range registries {
|
||||
resp, err := http.Get(r.url)
|
||||
if err != nil {
|
||||
fmt.Fprintln(os.Stderr, err)
|
||||
os.Exit(1)
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
if resp.StatusCode != http.StatusOK {
|
||||
fmt.Fprintf(os.Stderr, "got HTTP status code %v for %v\n", resp.StatusCode, r.url)
|
||||
os.Exit(1)
|
||||
}
|
||||
if err := r.parse(&bb, resp.Body); err != nil {
|
||||
fmt.Fprintln(os.Stderr, err)
|
||||
os.Exit(1)
|
||||
}
|
||||
fmt.Fprintf(&bb, "\n")
|
||||
}
|
||||
b, err := format.Source(bb.Bytes())
|
||||
if err != nil {
|
||||
fmt.Fprintln(os.Stderr, err)
|
||||
os.Exit(1)
|
||||
}
|
||||
os.Stdout.Write(b)
|
||||
}
|
||||
|
||||
func parseDSCPRegistry(w io.Writer, r io.Reader) error {
|
||||
dec := xml.NewDecoder(r)
|
||||
var dr dscpRegistry
|
||||
if err := dec.Decode(&dr); err != nil {
|
||||
return err
|
||||
}
|
||||
drs := dr.escape()
|
||||
fmt.Fprintf(w, "// %s, Updated: %s\n", dr.Title, dr.Updated)
|
||||
fmt.Fprintf(w, "const (\n")
|
||||
for _, dr := range drs {
|
||||
fmt.Fprintf(w, "DiffServ%s = %#x", dr.Name, dr.Value)
|
||||
fmt.Fprintf(w, "// %s\n", dr.OrigName)
|
||||
}
|
||||
fmt.Fprintf(w, ")\n")
|
||||
return nil
|
||||
}
|
||||
|
||||
type dscpRegistry struct {
|
||||
XMLName xml.Name `xml:"registry"`
|
||||
Title string `xml:"title"`
|
||||
Updated string `xml:"updated"`
|
||||
Note string `xml:"note"`
|
||||
RegTitle string `xml:"registry>title"`
|
||||
PoolRecords []struct {
|
||||
Name string `xml:"name"`
|
||||
Space string `xml:"space"`
|
||||
} `xml:"registry>record"`
|
||||
Records []struct {
|
||||
Name string `xml:"name"`
|
||||
Space string `xml:"space"`
|
||||
} `xml:"registry>registry>record"`
|
||||
}
|
||||
|
||||
type canonDSCPRecord struct {
|
||||
OrigName string
|
||||
Name string
|
||||
Value int
|
||||
}
|
||||
|
||||
func (drr *dscpRegistry) escape() []canonDSCPRecord {
|
||||
drs := make([]canonDSCPRecord, len(drr.Records))
|
||||
sr := strings.NewReplacer(
|
||||
"+", "",
|
||||
"-", "",
|
||||
"/", "",
|
||||
".", "",
|
||||
" ", "",
|
||||
)
|
||||
for i, dr := range drr.Records {
|
||||
s := strings.TrimSpace(dr.Name)
|
||||
drs[i].OrigName = s
|
||||
drs[i].Name = sr.Replace(s)
|
||||
n, err := strconv.ParseUint(dr.Space, 2, 8)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
drs[i].Value = int(n) << 2
|
||||
}
|
||||
return drs
|
||||
}
|
||||
|
||||
func parseTOSTCByte(w io.Writer, r io.Reader) error {
|
||||
dec := xml.NewDecoder(r)
|
||||
var ttb tosTCByte
|
||||
if err := dec.Decode(&ttb); err != nil {
|
||||
return err
|
||||
}
|
||||
trs := ttb.escape()
|
||||
fmt.Fprintf(w, "// %s, Updated: %s\n", ttb.Title, ttb.Updated)
|
||||
fmt.Fprintf(w, "const (\n")
|
||||
for _, tr := range trs {
|
||||
fmt.Fprintf(w, "%s = %#x", tr.Keyword, tr.Value)
|
||||
fmt.Fprintf(w, "// %s\n", tr.OrigKeyword)
|
||||
}
|
||||
fmt.Fprintf(w, ")\n")
|
||||
return nil
|
||||
}
|
||||
|
||||
type tosTCByte struct {
|
||||
XMLName xml.Name `xml:"registry"`
|
||||
Title string `xml:"title"`
|
||||
Updated string `xml:"updated"`
|
||||
Note string `xml:"note"`
|
||||
RegTitle string `xml:"registry>title"`
|
||||
Records []struct {
|
||||
Binary string `xml:"binary"`
|
||||
Keyword string `xml:"keyword"`
|
||||
} `xml:"registry>record"`
|
||||
}
|
||||
|
||||
type canonTOSTCByteRecord struct {
|
||||
OrigKeyword string
|
||||
Keyword string
|
||||
Value int
|
||||
}
|
||||
|
||||
func (ttb *tosTCByte) escape() []canonTOSTCByteRecord {
|
||||
trs := make([]canonTOSTCByteRecord, len(ttb.Records))
|
||||
sr := strings.NewReplacer(
|
||||
"Capable", "",
|
||||
"(", "",
|
||||
")", "",
|
||||
"+", "",
|
||||
"-", "",
|
||||
"/", "",
|
||||
".", "",
|
||||
" ", "",
|
||||
)
|
||||
for i, tr := range ttb.Records {
|
||||
s := strings.TrimSpace(tr.Keyword)
|
||||
trs[i].OrigKeyword = s
|
||||
ss := strings.Split(s, " ")
|
||||
if len(ss) > 1 {
|
||||
trs[i].Keyword = strings.Join(ss[1:], " ")
|
||||
} else {
|
||||
trs[i].Keyword = ss[0]
|
||||
}
|
||||
trs[i].Keyword = sr.Replace(trs[i].Keyword)
|
||||
n, err := strconv.ParseUint(tr.Binary, 2, 8)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
trs[i].Value = int(n)
|
||||
}
|
||||
return trs
|
||||
}
|
||||
33
Godeps/_workspace/src/code.google.com/p/go.net/ipv6/helper.go
generated
vendored
33
Godeps/_workspace/src/code.google.com/p/go.net/ipv6/helper.go
generated
vendored
@@ -1,33 +0,0 @@
|
||||
// Copyright 2013 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package ipv6
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"net"
|
||||
)
|
||||
|
||||
var errOpNoSupport = errors.New("operation not supported")
|
||||
|
||||
func boolint(b bool) int {
|
||||
if b {
|
||||
return 1
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func netAddrToIP16(a net.Addr) net.IP {
|
||||
switch v := a.(type) {
|
||||
case *net.UDPAddr:
|
||||
if ip := v.IP.To16(); ip != nil && ip.To4() == nil {
|
||||
return ip
|
||||
}
|
||||
case *net.IPAddr:
|
||||
if ip := v.IP.To16(); ip != nil && ip.To4() == nil {
|
||||
return ip
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
22
Godeps/_workspace/src/code.google.com/p/go.net/ipv6/helper_stub.go
generated
vendored
22
Godeps/_workspace/src/code.google.com/p/go.net/ipv6/helper_stub.go
generated
vendored
@@ -1,22 +0,0 @@
|
||||
// Copyright 2013 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build dragonfly plan9 solaris
|
||||
|
||||
package ipv6
|
||||
|
||||
func (c *genericOpt) sysfd() (int, error) {
|
||||
// TODO(mikio): Implement this
|
||||
return 0, errOpNoSupport
|
||||
}
|
||||
|
||||
func (c *dgramOpt) sysfd() (int, error) {
|
||||
// TODO(mikio): Implement this
|
||||
return 0, errOpNoSupport
|
||||
}
|
||||
|
||||
func (c *payloadHandler) sysfd() (int, error) {
|
||||
// TODO(mikio): Implement this
|
||||
return 0, errOpNoSupport
|
||||
}
|
||||
46
Godeps/_workspace/src/code.google.com/p/go.net/ipv6/helper_unix.go
generated
vendored
46
Godeps/_workspace/src/code.google.com/p/go.net/ipv6/helper_unix.go
generated
vendored
@@ -1,46 +0,0 @@
|
||||
// Copyright 2013 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build darwin freebsd linux netbsd openbsd
|
||||
|
||||
package ipv6
|
||||
|
||||
import (
|
||||
"net"
|
||||
"reflect"
|
||||
)
|
||||
|
||||
func (c *genericOpt) sysfd() (int, error) {
|
||||
switch p := c.Conn.(type) {
|
||||
case *net.TCPConn, *net.UDPConn, *net.IPConn:
|
||||
return sysfd(p)
|
||||
}
|
||||
return 0, errInvalidConnType
|
||||
}
|
||||
|
||||
func (c *dgramOpt) sysfd() (int, error) {
|
||||
switch p := c.PacketConn.(type) {
|
||||
case *net.UDPConn, *net.IPConn:
|
||||
return sysfd(p.(net.Conn))
|
||||
}
|
||||
return 0, errInvalidConnType
|
||||
}
|
||||
|
||||
func (c *payloadHandler) sysfd() (int, error) {
|
||||
return sysfd(c.PacketConn.(net.Conn))
|
||||
}
|
||||
|
||||
func sysfd(c net.Conn) (int, error) {
|
||||
cv := reflect.ValueOf(c)
|
||||
switch ce := cv.Elem(); ce.Kind() {
|
||||
case reflect.Struct:
|
||||
nfd := ce.FieldByName("conn").FieldByName("fd")
|
||||
switch fe := nfd.Elem(); fe.Kind() {
|
||||
case reflect.Struct:
|
||||
fd := fe.FieldByName("sysfd")
|
||||
return int(fd.Int()), nil
|
||||
}
|
||||
}
|
||||
return 0, errInvalidConnType
|
||||
}
|
||||
45
Godeps/_workspace/src/code.google.com/p/go.net/ipv6/helper_windows.go
generated
vendored
45
Godeps/_workspace/src/code.google.com/p/go.net/ipv6/helper_windows.go
generated
vendored
@@ -1,45 +0,0 @@
|
||||
// Copyright 2013 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package ipv6
|
||||
|
||||
import (
|
||||
"net"
|
||||
"reflect"
|
||||
"syscall"
|
||||
)
|
||||
|
||||
func (c *genericOpt) sysfd() (syscall.Handle, error) {
|
||||
switch p := c.Conn.(type) {
|
||||
case *net.TCPConn, *net.UDPConn, *net.IPConn:
|
||||
return sysfd(p)
|
||||
}
|
||||
return syscall.InvalidHandle, errInvalidConnType
|
||||
}
|
||||
|
||||
func (c *dgramOpt) sysfd() (syscall.Handle, error) {
|
||||
switch p := c.PacketConn.(type) {
|
||||
case *net.UDPConn, *net.IPConn:
|
||||
return sysfd(p.(net.Conn))
|
||||
}
|
||||
return syscall.InvalidHandle, errInvalidConnType
|
||||
}
|
||||
|
||||
func (c *payloadHandler) sysfd() (syscall.Handle, error) {
|
||||
return sysfd(c.PacketConn.(net.Conn))
|
||||
}
|
||||
|
||||
func sysfd(c net.Conn) (syscall.Handle, error) {
|
||||
cv := reflect.ValueOf(c)
|
||||
switch ce := cv.Elem(); ce.Kind() {
|
||||
case reflect.Struct:
|
||||
netfd := ce.FieldByName("conn").FieldByName("fd")
|
||||
switch fe := netfd.Elem(); fe.Kind() {
|
||||
case reflect.Struct:
|
||||
fd := fe.FieldByName("sysfd")
|
||||
return syscall.Handle(fd.Uint()), nil
|
||||
}
|
||||
}
|
||||
return syscall.InvalidHandle, errInvalidConnType
|
||||
}
|
||||
224
Godeps/_workspace/src/code.google.com/p/go.net/ipv6/iana.go
generated
vendored
224
Godeps/_workspace/src/code.google.com/p/go.net/ipv6/iana.go
generated
vendored
@@ -1,224 +0,0 @@
|
||||
// go run gen.go
|
||||
// GENERATED BY THE COMMAND ABOVE; DO NOT EDIT
|
||||
|
||||
package ipv6
|
||||
|
||||
// Internet Control Message Protocol version 6 (ICMPv6) Parameters, Updated: 2013-07-03
|
||||
const (
|
||||
ICMPTypeDestinationUnreachable ICMPType = 1 // Destination Unreachable
|
||||
ICMPTypePacketTooBig ICMPType = 2 // Packet Too Big
|
||||
ICMPTypeTimeExceeded ICMPType = 3 // Time Exceeded
|
||||
ICMPTypeParameterProblem ICMPType = 4 // Parameter Problem
|
||||
ICMPTypeEchoRequest ICMPType = 128 // Echo Request
|
||||
ICMPTypeEchoReply ICMPType = 129 // Echo Reply
|
||||
ICMPTypeMulticastListenerQuery ICMPType = 130 // Multicast Listener Query
|
||||
ICMPTypeMulticastListenerReport ICMPType = 131 // Multicast Listener Report
|
||||
ICMPTypeMulticastListenerDone ICMPType = 132 // Multicast Listener Done
|
||||
ICMPTypeRouterSolicitation ICMPType = 133 // Router Solicitation
|
||||
ICMPTypeRouterAdvertisement ICMPType = 134 // Router Advertisement
|
||||
ICMPTypeNeighborSolicitation ICMPType = 135 // Neighbor Solicitation
|
||||
ICMPTypeNeighborAdvertisement ICMPType = 136 // Neighbor Advertisement
|
||||
ICMPTypeRedirect ICMPType = 137 // Redirect Message
|
||||
ICMPTypeRouterRenumbering ICMPType = 138 // Router Renumbering
|
||||
ICMPTypeNodeInformationQuery ICMPType = 139 // ICMP Node Information Query
|
||||
ICMPTypeNodeInformationResponse ICMPType = 140 // ICMP Node Information Response
|
||||
ICMPTypeInverseNeighborDiscoverySolicitation ICMPType = 141 // Inverse Neighbor Discovery Solicitation Message
|
||||
ICMPTypeInverseNeighborDiscoveryAdvertisement ICMPType = 142 // Inverse Neighbor Discovery Advertisement Message
|
||||
ICMPTypeVersion2MulticastListenerReport ICMPType = 143 // Version 2 Multicast Listener Report
|
||||
ICMPTypeHomeAgentAddressDiscoveryRequest ICMPType = 144 // Home Agent Address Discovery Request Message
|
||||
ICMPTypeHomeAgentAddressDiscoveryReply ICMPType = 145 // Home Agent Address Discovery Reply Message
|
||||
ICMPTypeMobilePrefixSolicitation ICMPType = 146 // Mobile Prefix Solicitation
|
||||
ICMPTypeMobilePrefixAdvertisement ICMPType = 147 // Mobile Prefix Advertisement
|
||||
ICMPTypeCertificationPathSolicitation ICMPType = 148 // Certification Path Solicitation Message
|
||||
ICMPTypeCertificationPathAdvertisement ICMPType = 149 // Certification Path Advertisement Message
|
||||
ICMPTypeMulticastRouterAdvertisement ICMPType = 151 // Multicast Router Advertisement
|
||||
ICMPTypeMulticastRouterSolicitation ICMPType = 152 // Multicast Router Solicitation
|
||||
ICMPTypeMulticastRouterTermination ICMPType = 153 // Multicast Router Termination
|
||||
ICMPTypeFMIPv6 ICMPType = 154 // FMIPv6 Messages
|
||||
ICMPTypeRPLControl ICMPType = 155 // RPL Control Message
|
||||
ICMPTypeILNPv6LocatorUpdate ICMPType = 156 // ILNPv6 Locator Update Message
|
||||
ICMPTypeDuplicateAddressRequest ICMPType = 157 // Duplicate Address Request
|
||||
ICMPTypeDuplicateAddressConfirmation ICMPType = 158 // Duplicate Address Confirmation
|
||||
)
|
||||
|
||||
// Internet Control Message Protocol version 6 (ICMPv6) Parameters, Updated: 2013-07-03
|
||||
var icmpTypes = map[ICMPType]string{
|
||||
1: "destination unreachable",
|
||||
2: "packet too big",
|
||||
3: "time exceeded",
|
||||
4: "parameter problem",
|
||||
128: "echo request",
|
||||
129: "echo reply",
|
||||
130: "multicast listener query",
|
||||
131: "multicast listener report",
|
||||
132: "multicast listener done",
|
||||
133: "router solicitation",
|
||||
134: "router advertisement",
|
||||
135: "neighbor solicitation",
|
||||
136: "neighbor advertisement",
|
||||
137: "redirect message",
|
||||
138: "router renumbering",
|
||||
139: "icmp node information query",
|
||||
140: "icmp node information response",
|
||||
141: "inverse neighbor discovery solicitation message",
|
||||
142: "inverse neighbor discovery advertisement message",
|
||||
143: "version 2 multicast listener report",
|
||||
144: "home agent address discovery request message",
|
||||
145: "home agent address discovery reply message",
|
||||
146: "mobile prefix solicitation",
|
||||
147: "mobile prefix advertisement",
|
||||
148: "certification path solicitation message",
|
||||
149: "certification path advertisement message",
|
||||
151: "multicast router advertisement",
|
||||
152: "multicast router solicitation",
|
||||
153: "multicast router termination",
|
||||
154: "fmipv6 messages",
|
||||
155: "rpl control message",
|
||||
156: "ilnpv6 locator update message",
|
||||
157: "duplicate address request",
|
||||
158: "duplicate address confirmation",
|
||||
}
|
||||
|
||||
// Protocol Numbers, Updated: 2013-02-17
|
||||
const (
|
||||
ianaProtocolHOPOPT = 0 // IPv6 Hop-by-Hop Option
|
||||
ianaProtocolICMP = 1 // Internet Control Message
|
||||
ianaProtocolIGMP = 2 // Internet Group Management
|
||||
ianaProtocolGGP = 3 // Gateway-to-Gateway
|
||||
ianaProtocolIPv4 = 4 // IPv4 encapsulation
|
||||
ianaProtocolST = 5 // Stream
|
||||
ianaProtocolTCP = 6 // Transmission Control
|
||||
ianaProtocolCBT = 7 // CBT
|
||||
ianaProtocolEGP = 8 // Exterior Gateway Protocol
|
||||
ianaProtocolIGP = 9 // any private interior gateway (used by Cisco for their IGRP)
|
||||
ianaProtocolBBNRCCMON = 10 // BBN RCC Monitoring
|
||||
ianaProtocolNVPII = 11 // Network Voice Protocol
|
||||
ianaProtocolPUP = 12 // PUP
|
||||
ianaProtocolARGUS = 13 // ARGUS
|
||||
ianaProtocolEMCON = 14 // EMCON
|
||||
ianaProtocolXNET = 15 // Cross Net Debugger
|
||||
ianaProtocolCHAOS = 16 // Chaos
|
||||
ianaProtocolUDP = 17 // User Datagram
|
||||
ianaProtocolMUX = 18 // Multiplexing
|
||||
ianaProtocolDCNMEAS = 19 // DCN Measurement Subsystems
|
||||
ianaProtocolHMP = 20 // Host Monitoring
|
||||
ianaProtocolPRM = 21 // Packet Radio Measurement
|
||||
ianaProtocolXNSIDP = 22 // XEROX NS IDP
|
||||
ianaProtocolTRUNK1 = 23 // Trunk-1
|
||||
ianaProtocolTRUNK2 = 24 // Trunk-2
|
||||
ianaProtocolLEAF1 = 25 // Leaf-1
|
||||
ianaProtocolLEAF2 = 26 // Leaf-2
|
||||
ianaProtocolRDP = 27 // Reliable Data Protocol
|
||||
ianaProtocolIRTP = 28 // Internet Reliable Transaction
|
||||
ianaProtocolISOTP4 = 29 // ISO Transport Protocol Class 4
|
||||
ianaProtocolNETBLT = 30 // Bulk Data Transfer Protocol
|
||||
ianaProtocolMFENSP = 31 // MFE Network Services Protocol
|
||||
ianaProtocolMERITINP = 32 // MERIT Internodal Protocol
|
||||
ianaProtocolDCCP = 33 // Datagram Congestion Control Protocol
|
||||
ianaProtocol3PC = 34 // Third Party Connect Protocol
|
||||
ianaProtocolIDPR = 35 // Inter-Domain Policy Routing Protocol
|
||||
ianaProtocolXTP = 36 // XTP
|
||||
ianaProtocolDDP = 37 // Datagram Delivery Protocol
|
||||
ianaProtocolIDPRCMTP = 38 // IDPR Control Message Transport Proto
|
||||
ianaProtocolTPPP = 39 // TP++ Transport Protocol
|
||||
ianaProtocolIL = 40 // IL Transport Protocol
|
||||
ianaProtocolIPv6 = 41 // IPv6 encapsulation
|
||||
ianaProtocolSDRP = 42 // Source Demand Routing Protocol
|
||||
ianaProtocolIPv6Route = 43 // Routing Header for IPv6
|
||||
ianaProtocolIPv6Frag = 44 // Fragment Header for IPv6
|
||||
ianaProtocolIDRP = 45 // Inter-Domain Routing Protocol
|
||||
ianaProtocolRSVP = 46 // Reservation Protocol
|
||||
ianaProtocolGRE = 47 // Generic Routing Encapsulation
|
||||
ianaProtocolDSR = 48 // Dynamic Source Routing Protocol
|
||||
ianaProtocolBNA = 49 // BNA
|
||||
ianaProtocolESP = 50 // Encap Security Payload
|
||||
ianaProtocolAH = 51 // Authentication Header
|
||||
ianaProtocolINLSP = 52 // Integrated Net Layer Security TUBA
|
||||
ianaProtocolSWIPE = 53 // IP with Encryption
|
||||
ianaProtocolNARP = 54 // NBMA Address Resolution Protocol
|
||||
ianaProtocolMOBILE = 55 // IP Mobility
|
||||
ianaProtocolTLSP = 56 // Transport Layer Security Protocol using Kryptonet key management
|
||||
ianaProtocolSKIP = 57 // SKIP
|
||||
ianaProtocolIPv6ICMP = 58 // ICMP for IPv6
|
||||
ianaProtocolIPv6NoNxt = 59 // No Next Header for IPv6
|
||||
ianaProtocolIPv6Opts = 60 // Destination Options for IPv6
|
||||
ianaProtocolCFTP = 62 // CFTP
|
||||
ianaProtocolSATEXPAK = 64 // SATNET and Backroom EXPAK
|
||||
ianaProtocolKRYPTOLAN = 65 // Kryptolan
|
||||
ianaProtocolRVD = 66 // MIT Remote Virtual Disk Protocol
|
||||
ianaProtocolIPPC = 67 // Internet Pluribus Packet Core
|
||||
ianaProtocolSATMON = 69 // SATNET Monitoring
|
||||
ianaProtocolVISA = 70 // VISA Protocol
|
||||
ianaProtocolIPCV = 71 // Internet Packet Core Utility
|
||||
ianaProtocolCPNX = 72 // Computer Protocol Network Executive
|
||||
ianaProtocolCPHB = 73 // Computer Protocol Heart Beat
|
||||
ianaProtocolWSN = 74 // Wang Span Network
|
||||
ianaProtocolPVP = 75 // Packet Video Protocol
|
||||
ianaProtocolBRSATMON = 76 // Backroom SATNET Monitoring
|
||||
ianaProtocolSUNND = 77 // SUN ND PROTOCOL-Temporary
|
||||
ianaProtocolWBMON = 78 // WIDEBAND Monitoring
|
||||
ianaProtocolWBEXPAK = 79 // WIDEBAND EXPAK
|
||||
ianaProtocolISOIP = 80 // ISO Internet Protocol
|
||||
ianaProtocolVMTP = 81 // VMTP
|
||||
ianaProtocolSECUREVMTP = 82 // SECURE-VMTP
|
||||
ianaProtocolVINES = 83 // VINES
|
||||
ianaProtocolTTP = 84 // TTP
|
||||
ianaProtocolIPTM = 84 // Protocol Internet Protocol Traffic Manager
|
||||
ianaProtocolNSFNETIGP = 85 // NSFNET-IGP
|
||||
ianaProtocolDGP = 86 // Dissimilar Gateway Protocol
|
||||
ianaProtocolTCF = 87 // TCF
|
||||
ianaProtocolEIGRP = 88 // EIGRP
|
||||
ianaProtocolOSPFIGP = 89 // OSPFIGP
|
||||
ianaProtocolSpriteRPC = 90 // Sprite RPC Protocol
|
||||
ianaProtocolLARP = 91 // Locus Address Resolution Protocol
|
||||
ianaProtocolMTP = 92 // Multicast Transport Protocol
|
||||
ianaProtocolAX25 = 93 // AX.25 Frames
|
||||
ianaProtocolIPIP = 94 // IP-within-IP Encapsulation Protocol
|
||||
ianaProtocolMICP = 95 // Mobile Internetworking Control Pro.
|
||||
ianaProtocolSCCSP = 96 // Semaphore Communications Sec. Pro.
|
||||
ianaProtocolETHERIP = 97 // Ethernet-within-IP Encapsulation
|
||||
ianaProtocolENCAP = 98 // Encapsulation Header
|
||||
ianaProtocolGMTP = 100 // GMTP
|
||||
ianaProtocolIFMP = 101 // Ipsilon Flow Management Protocol
|
||||
ianaProtocolPNNI = 102 // PNNI over IP
|
||||
ianaProtocolPIM = 103 // Protocol Independent Multicast
|
||||
ianaProtocolARIS = 104 // ARIS
|
||||
ianaProtocolSCPS = 105 // SCPS
|
||||
ianaProtocolQNX = 106 // QNX
|
||||
ianaProtocolAN = 107 // Active Networks
|
||||
ianaProtocolIPComp = 108 // IP Payload Compression Protocol
|
||||
ianaProtocolSNP = 109 // Sitara Networks Protocol
|
||||
ianaProtocolCompaqPeer = 110 // Compaq Peer Protocol
|
||||
ianaProtocolIPXinIP = 111 // IPX in IP
|
||||
ianaProtocolVRRP = 112 // Virtual Router Redundancy Protocol
|
||||
ianaProtocolPGM = 113 // PGM Reliable Transport Protocol
|
||||
ianaProtocolL2TP = 115 // Layer Two Tunneling Protocol
|
||||
ianaProtocolDDX = 116 // D-II Data Exchange (DDX)
|
||||
ianaProtocolIATP = 117 // Interactive Agent Transfer Protocol
|
||||
ianaProtocolSTP = 118 // Schedule Transfer Protocol
|
||||
ianaProtocolSRP = 119 // SpectraLink Radio Protocol
|
||||
ianaProtocolUTI = 120 // UTI
|
||||
ianaProtocolSMP = 121 // Simple Message Protocol
|
||||
ianaProtocolSM = 122 // SM
|
||||
ianaProtocolPTP = 123 // Performance Transparency Protocol
|
||||
ianaProtocolISIS = 124 // ISIS over IPv4
|
||||
ianaProtocolFIRE = 125 // FIRE
|
||||
ianaProtocolCRTP = 126 // Combat Radio Transport Protocol
|
||||
ianaProtocolCRUDP = 127 // Combat Radio User Datagram
|
||||
ianaProtocolSSCOPMCE = 128 // SSCOPMCE
|
||||
ianaProtocolIPLT = 129 // IPLT
|
||||
ianaProtocolSPS = 130 // Secure Packet Shield
|
||||
ianaProtocolPIPE = 131 // Private IP Encapsulation within IP
|
||||
ianaProtocolSCTP = 132 // Stream Control Transmission Protocol
|
||||
ianaProtocolFC = 133 // Fibre Channel
|
||||
ianaProtocolRSVPE2EIGNORE = 134 // RSVP-E2E-IGNORE
|
||||
ianaProtocolMobilityHeader = 135 // Mobility Header
|
||||
ianaProtocolUDPLite = 136 // UDPLite
|
||||
ianaProtocolMPLSinIP = 137 // MPLS-in-IP
|
||||
ianaProtocolMANET = 138 // MANET Protocols
|
||||
ianaProtocolHIP = 139 // Host Identity Protocol
|
||||
ianaProtocolShim6 = 140 // Shim6 Protocol
|
||||
ianaProtocolWESP = 141 // Wrapped Encapsulating Security Payload
|
||||
ianaProtocolROHC = 142 // Robust Header Compression
|
||||
ianaProtocolReserved = 255 // Reserved
|
||||
)
|
||||
38
Godeps/_workspace/src/code.google.com/p/go.net/ipv6/iana_test.go
generated
vendored
38
Godeps/_workspace/src/code.google.com/p/go.net/ipv6/iana_test.go
generated
vendored
@@ -1,38 +0,0 @@
|
||||
// go run gentest.go
|
||||
// GENERATED BY THE COMMAND ABOVE; DO NOT EDIT
|
||||
|
||||
package ipv6_test
|
||||
|
||||
// Differentiated Services Field Codepoints (DSCP), Updated: 2013-06-25
|
||||
const (
|
||||
DiffServCS0 = 0x0 // CS0
|
||||
DiffServCS1 = 0x20 // CS1
|
||||
DiffServCS2 = 0x40 // CS2
|
||||
DiffServCS3 = 0x60 // CS3
|
||||
DiffServCS4 = 0x80 // CS4
|
||||
DiffServCS5 = 0xa0 // CS5
|
||||
DiffServCS6 = 0xc0 // CS6
|
||||
DiffServCS7 = 0xe0 // CS7
|
||||
DiffServAF11 = 0x28 // AF11
|
||||
DiffServAF12 = 0x30 // AF12
|
||||
DiffServAF13 = 0x38 // AF13
|
||||
DiffServAF21 = 0x48 // AF21
|
||||
DiffServAF22 = 0x50 // AF22
|
||||
DiffServAF23 = 0x58 // AF23
|
||||
DiffServAF31 = 0x68 // AF31
|
||||
DiffServAF32 = 0x70 // AF32
|
||||
DiffServAF33 = 0x78 // AF33
|
||||
DiffServAF41 = 0x88 // AF41
|
||||
DiffServAF42 = 0x90 // AF42
|
||||
DiffServAF43 = 0x98 // AF43
|
||||
DiffServEFPHB = 0xb8 // EF PHB
|
||||
DiffServVOICEADMIT = 0xb0 // VOICE-ADMIT
|
||||
)
|
||||
|
||||
// IPv4 TOS Byte and IPv6 Traffic Class Octet, Updated: 2001-09-06
|
||||
const (
|
||||
NotECNTransport = 0x0 // Not-ECT (Not ECN-Capable Transport)
|
||||
ECNTransport1 = 0x1 // ECT(1) (ECN-Capable Transport(1))
|
||||
ECNTransport0 = 0x2 // ECT(0) (ECN-Capable Transport(0))
|
||||
CongestionExperienced = 0x3 // CE (Congestion Experienced)
|
||||
)
|
||||
47
Godeps/_workspace/src/code.google.com/p/go.net/ipv6/icmp.go
generated
vendored
47
Godeps/_workspace/src/code.google.com/p/go.net/ipv6/icmp.go
generated
vendored
@@ -1,47 +0,0 @@
|
||||
// Copyright 2013 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package ipv6
|
||||
|
||||
import "sync"
|
||||
|
||||
// An ICMPType represents a type of ICMP message.
|
||||
type ICMPType int
|
||||
|
||||
func (typ ICMPType) String() string {
|
||||
s, ok := icmpTypes[typ]
|
||||
if !ok {
|
||||
return "<nil>"
|
||||
}
|
||||
return s
|
||||
}
|
||||
|
||||
// An ICMPFilter represents an ICMP message filter for incoming
|
||||
// packets.
|
||||
type ICMPFilter struct {
|
||||
mu sync.RWMutex
|
||||
sysICMPFilter
|
||||
}
|
||||
|
||||
// Set sets the ICMP type and filter action to the filter.
|
||||
func (f *ICMPFilter) Set(typ ICMPType, block bool) {
|
||||
f.mu.Lock()
|
||||
f.set(typ, block)
|
||||
f.mu.Unlock()
|
||||
}
|
||||
|
||||
// SetAll sets the filter action to the filter.
|
||||
func (f *ICMPFilter) SetAll(block bool) {
|
||||
f.mu.Lock()
|
||||
f.setAll(block)
|
||||
f.mu.Unlock()
|
||||
}
|
||||
|
||||
// WillBlock reports whether the ICMP type will be blocked.
|
||||
func (f *ICMPFilter) WillBlock(typ ICMPType) bool {
|
||||
f.mu.RLock()
|
||||
ok := f.willBlock(typ)
|
||||
f.mu.RUnlock()
|
||||
return ok
|
||||
}
|
||||
33
Godeps/_workspace/src/code.google.com/p/go.net/ipv6/icmp_bsd.go
generated
vendored
33
Godeps/_workspace/src/code.google.com/p/go.net/ipv6/icmp_bsd.go
generated
vendored
@@ -1,33 +0,0 @@
|
||||
// Copyright 2013 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build darwin freebsd netbsd openbsd
|
||||
|
||||
package ipv6
|
||||
|
||||
type sysICMPFilter struct {
|
||||
Filt [8]uint32
|
||||
}
|
||||
|
||||
func (f *sysICMPFilter) set(typ ICMPType, block bool) {
|
||||
if block {
|
||||
f.Filt[typ>>5] &^= 1 << (uint32(typ) & 31)
|
||||
} else {
|
||||
f.Filt[typ>>5] |= 1 << (uint32(typ) & 31)
|
||||
}
|
||||
}
|
||||
|
||||
func (f *sysICMPFilter) setAll(block bool) {
|
||||
for i := range f.Filt {
|
||||
if block {
|
||||
f.Filt[i] = 0
|
||||
} else {
|
||||
f.Filt[i] = 1<<32 - 1
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (f *sysICMPFilter) willBlock(typ ICMPType) bool {
|
||||
return f.Filt[typ>>5]&(1<<(uint32(typ)&31)) == 0
|
||||
}
|
||||
31
Godeps/_workspace/src/code.google.com/p/go.net/ipv6/icmp_linux.go
generated
vendored
31
Godeps/_workspace/src/code.google.com/p/go.net/ipv6/icmp_linux.go
generated
vendored
@@ -1,31 +0,0 @@
|
||||
// Copyright 2013 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package ipv6
|
||||
|
||||
type sysICMPFilter struct {
|
||||
Data [8]uint32
|
||||
}
|
||||
|
||||
func (f *sysICMPFilter) set(typ ICMPType, block bool) {
|
||||
if block {
|
||||
f.Data[typ>>5] |= 1 << (uint32(typ) & 31)
|
||||
} else {
|
||||
f.Data[typ>>5] &^= 1 << (uint32(typ) & 31)
|
||||
}
|
||||
}
|
||||
|
||||
func (f *sysICMPFilter) setAll(block bool) {
|
||||
for i := range f.Data {
|
||||
if block {
|
||||
f.Data[i] = 1<<32 - 1
|
||||
} else {
|
||||
f.Data[i] = 0
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (f *sysICMPFilter) willBlock(typ ICMPType) bool {
|
||||
return f.Data[typ>>5]&(1<<(uint32(typ)&31)) != 0
|
||||
}
|
||||
24
Godeps/_workspace/src/code.google.com/p/go.net/ipv6/icmp_stub.go
generated
vendored
24
Godeps/_workspace/src/code.google.com/p/go.net/ipv6/icmp_stub.go
generated
vendored
@@ -1,24 +0,0 @@
|
||||
// Copyright 2013 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build dragonfly plan9 solaris
|
||||
|
||||
package ipv6
|
||||
|
||||
type sysICMPFilter struct {
|
||||
// TODO(mikio): Implement this
|
||||
}
|
||||
|
||||
func (f *sysICMPFilter) set(typ ICMPType, block bool) {
|
||||
// TODO(mikio): Implement this
|
||||
}
|
||||
|
||||
func (f *sysICMPFilter) setAll(block bool) {
|
||||
// TODO(mikio): Implement this
|
||||
}
|
||||
|
||||
func (f *sysICMPFilter) willBlock(typ ICMPType) bool {
|
||||
// TODO(mikio): Implement this
|
||||
return false
|
||||
}
|
||||
102
Godeps/_workspace/src/code.google.com/p/go.net/ipv6/icmp_test.go
generated
vendored
102
Godeps/_workspace/src/code.google.com/p/go.net/ipv6/icmp_test.go
generated
vendored
@@ -1,102 +0,0 @@
|
||||
// Copyright 2013 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package ipv6_test
|
||||
|
||||
import (
|
||||
"code.google.com/p/go.net/ipv6"
|
||||
"net"
|
||||
"os"
|
||||
"reflect"
|
||||
"runtime"
|
||||
"sync"
|
||||
"testing"
|
||||
)
|
||||
|
||||
var icmpStringTests = []struct {
|
||||
in ipv6.ICMPType
|
||||
out string
|
||||
}{
|
||||
{ipv6.ICMPTypeDestinationUnreachable, "destination unreachable"},
|
||||
|
||||
{256, "<nil>"},
|
||||
}
|
||||
|
||||
func TestICMPString(t *testing.T) {
|
||||
for _, tt := range icmpStringTests {
|
||||
s := tt.in.String()
|
||||
if s != tt.out {
|
||||
t.Errorf("got %s; expected %s", s, tt.out)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestICMPFilter(t *testing.T) {
|
||||
switch runtime.GOOS {
|
||||
case "dragonfly", "plan9", "solaris", "windows":
|
||||
t.Skipf("not supported on %q", runtime.GOOS)
|
||||
}
|
||||
|
||||
var f ipv6.ICMPFilter
|
||||
for _, toggle := range []bool{false, true} {
|
||||
f.SetAll(toggle)
|
||||
var wg sync.WaitGroup
|
||||
for _, typ := range []ipv6.ICMPType{
|
||||
ipv6.ICMPTypeDestinationUnreachable,
|
||||
ipv6.ICMPTypeEchoReply,
|
||||
ipv6.ICMPTypeNeighborSolicitation,
|
||||
ipv6.ICMPTypeDuplicateAddressConfirmation,
|
||||
} {
|
||||
wg.Add(1)
|
||||
go func(typ ipv6.ICMPType) {
|
||||
defer wg.Done()
|
||||
f.Set(typ, false)
|
||||
if f.WillBlock(typ) {
|
||||
t.Errorf("ipv6.ICMPFilter.Set(%v, false) failed", typ)
|
||||
}
|
||||
f.Set(typ, true)
|
||||
if !f.WillBlock(typ) {
|
||||
t.Errorf("ipv6.ICMPFilter.Set(%v, true) failed", typ)
|
||||
}
|
||||
}(typ)
|
||||
}
|
||||
wg.Wait()
|
||||
}
|
||||
}
|
||||
|
||||
func TestSetICMPFilter(t *testing.T) {
|
||||
switch runtime.GOOS {
|
||||
case "dragonfly", "plan9", "solaris", "windows":
|
||||
t.Skipf("not supported on %q", runtime.GOOS)
|
||||
}
|
||||
if !supportsIPv6 {
|
||||
t.Skip("ipv6 is not supported")
|
||||
}
|
||||
if os.Getuid() != 0 {
|
||||
t.Skip("must be root")
|
||||
}
|
||||
|
||||
c, err := net.ListenPacket("ip6:ipv6-icmp", "::1")
|
||||
if err != nil {
|
||||
t.Fatalf("net.ListenPacket failed: %v", err)
|
||||
}
|
||||
defer c.Close()
|
||||
|
||||
p := ipv6.NewPacketConn(c)
|
||||
|
||||
var f ipv6.ICMPFilter
|
||||
f.SetAll(true)
|
||||
f.Set(ipv6.ICMPTypeEchoRequest, false)
|
||||
f.Set(ipv6.ICMPTypeEchoReply, false)
|
||||
if err := p.SetICMPFilter(&f); err != nil {
|
||||
t.Fatalf("ipv6.PacketConn.SetICMPFilter failed: %v", err)
|
||||
}
|
||||
kf, err := p.ICMPFilter()
|
||||
if err != nil {
|
||||
t.Fatalf("ipv6.PacketConn.ICMPFilter failed: %v", err)
|
||||
}
|
||||
if !reflect.DeepEqual(kf, &f) {
|
||||
t.Fatalf("got unexpected filter %#v; expected %#v", kf, f)
|
||||
}
|
||||
}
|
||||
22
Godeps/_workspace/src/code.google.com/p/go.net/ipv6/icmp_windows.go
generated
vendored
22
Godeps/_workspace/src/code.google.com/p/go.net/ipv6/icmp_windows.go
generated
vendored
@@ -1,22 +0,0 @@
|
||||
// Copyright 2013 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package ipv6
|
||||
|
||||
type sysICMPFilter struct {
|
||||
// TODO(mikio): Implement this
|
||||
}
|
||||
|
||||
func (f *sysICMPFilter) set(typ ICMPType, block bool) {
|
||||
// TODO(mikio): Implement this
|
||||
}
|
||||
|
||||
func (f *sysICMPFilter) setAll(block bool) {
|
||||
// TODO(mikio): Implement this
|
||||
}
|
||||
|
||||
func (f *sysICMPFilter) willBlock(typ ICMPType) bool {
|
||||
// TODO(mikio): Implement this
|
||||
return false
|
||||
}
|
||||
130
Godeps/_workspace/src/code.google.com/p/go.net/ipv6/mockicmp_test.go
generated
vendored
130
Godeps/_workspace/src/code.google.com/p/go.net/ipv6/mockicmp_test.go
generated
vendored
@@ -1,130 +0,0 @@
|
||||
// Copyright 2013 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package ipv6_test
|
||||
|
||||
import (
|
||||
"code.google.com/p/go.net/ipv6"
|
||||
"errors"
|
||||
"net"
|
||||
)
|
||||
|
||||
const (
|
||||
ipv6PseudoHeaderLen = 2*net.IPv6len + 8
|
||||
ianaProtocolIPv6ICMP = 58
|
||||
)
|
||||
|
||||
func ipv6PseudoHeader(src, dst net.IP, nextHeader int) []byte {
|
||||
b := make([]byte, ipv6PseudoHeaderLen)
|
||||
copy(b[:net.IPv6len], src)
|
||||
copy(b[net.IPv6len:], dst)
|
||||
b[len(b)-1] = byte(nextHeader)
|
||||
return b
|
||||
}
|
||||
|
||||
// icmpMessage represents an ICMP message.
|
||||
type icmpMessage struct {
|
||||
Type ipv6.ICMPType // type
|
||||
Code int // code
|
||||
Checksum int // checksum
|
||||
Body icmpMessageBody // body
|
||||
}
|
||||
|
||||
// icmpMessageBody represents an ICMP message body.
|
||||
type icmpMessageBody interface {
|
||||
Len() int
|
||||
Marshal() ([]byte, error)
|
||||
}
|
||||
|
||||
// Marshal returns the binary enconding of the ICMP echo request or
|
||||
// reply message m.
|
||||
func (m *icmpMessage) Marshal(psh []byte) ([]byte, error) {
|
||||
b := []byte{byte(m.Type), byte(m.Code), 0, 0}
|
||||
if psh != nil {
|
||||
b = append(psh, b...)
|
||||
}
|
||||
if m.Body != nil && m.Body.Len() != 0 {
|
||||
mb, err := m.Body.Marshal()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
b = append(b, mb...)
|
||||
}
|
||||
if psh == nil {
|
||||
return b, nil
|
||||
}
|
||||
off, l := 2*net.IPv6len, len(b)-len(psh)
|
||||
b[off], b[off+1], b[off+2], b[off+3] = byte(l>>24), byte(l>>16), byte(l>>8), byte(l)
|
||||
csumcv := len(b) - 1 // checksum coverage
|
||||
s := uint32(0)
|
||||
for i := 0; i < csumcv; i += 2 {
|
||||
s += uint32(b[i+1])<<8 | uint32(b[i])
|
||||
}
|
||||
if csumcv&1 == 0 {
|
||||
s += uint32(b[csumcv])
|
||||
}
|
||||
s = s>>16 + s&0xffff
|
||||
s = s + s>>16
|
||||
// Place checksum back in header; using ^= avoids the
|
||||
// assumption the checksum bytes are zero.
|
||||
b[len(psh)+2] ^= byte(^s)
|
||||
b[len(psh)+3] ^= byte(^s >> 8)
|
||||
return b[len(psh):], nil
|
||||
}
|
||||
|
||||
// parseICMPMessage parses b as an ICMP message.
|
||||
func parseICMPMessage(b []byte) (*icmpMessage, error) {
|
||||
msglen := len(b)
|
||||
if msglen < 4 {
|
||||
return nil, errors.New("message too short")
|
||||
}
|
||||
m := &icmpMessage{Type: ipv6.ICMPType(b[0]), Code: int(b[1]), Checksum: int(b[2])<<8 | int(b[3])}
|
||||
if msglen > 4 {
|
||||
var err error
|
||||
switch m.Type {
|
||||
case ipv6.ICMPTypeEchoRequest, ipv6.ICMPTypeEchoReply:
|
||||
m.Body, err = parseICMPEcho(b[4:])
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
}
|
||||
return m, nil
|
||||
}
|
||||
|
||||
// imcpEcho represenets an ICMP echo request or reply message body.
|
||||
type icmpEcho struct {
|
||||
ID int // identifier
|
||||
Seq int // sequence number
|
||||
Data []byte // data
|
||||
}
|
||||
|
||||
func (p *icmpEcho) Len() int {
|
||||
if p == nil {
|
||||
return 0
|
||||
}
|
||||
return 4 + len(p.Data)
|
||||
}
|
||||
|
||||
// Marshal returns the binary enconding of the ICMP echo request or
|
||||
// reply message body p.
|
||||
func (p *icmpEcho) Marshal() ([]byte, error) {
|
||||
b := make([]byte, 4+len(p.Data))
|
||||
b[0], b[1] = byte(p.ID>>8), byte(p.ID)
|
||||
b[2], b[3] = byte(p.Seq>>8), byte(p.Seq)
|
||||
copy(b[4:], p.Data)
|
||||
return b, nil
|
||||
}
|
||||
|
||||
// parseICMPEcho parses b as an ICMP echo request or reply message
|
||||
// body.
|
||||
func parseICMPEcho(b []byte) (*icmpEcho, error) {
|
||||
bodylen := len(b)
|
||||
p := &icmpEcho{ID: int(b[0])<<8 | int(b[1]), Seq: int(b[2])<<8 | int(b[3])}
|
||||
if bodylen > 4 {
|
||||
p.Data = make([]byte, bodylen-4)
|
||||
copy(p.Data, b[4:])
|
||||
}
|
||||
return p, nil
|
||||
}
|
||||
88
Godeps/_workspace/src/code.google.com/p/go.net/ipv6/mocktransponder_test.go
generated
vendored
88
Godeps/_workspace/src/code.google.com/p/go.net/ipv6/mocktransponder_test.go
generated
vendored
@@ -1,88 +0,0 @@
|
||||
// Copyright 2013 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package ipv6_test
|
||||
|
||||
import (
|
||||
"net"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func isLinkLocalUnicast(ip net.IP) bool {
|
||||
return ip.To4() == nil && ip.To16() != nil && ip.IsLinkLocalUnicast()
|
||||
}
|
||||
|
||||
func loopbackInterface() *net.Interface {
|
||||
ift, err := net.Interfaces()
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
for _, ifi := range ift {
|
||||
if ifi.Flags&net.FlagLoopback == 0 || ifi.Flags&net.FlagUp == 0 {
|
||||
continue
|
||||
}
|
||||
ifat, err := ifi.Addrs()
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
for _, ifa := range ifat {
|
||||
switch ifa := ifa.(type) {
|
||||
case *net.IPAddr:
|
||||
if isLinkLocalUnicast(ifa.IP) {
|
||||
return &ifi
|
||||
}
|
||||
case *net.IPNet:
|
||||
if isLinkLocalUnicast(ifa.IP) {
|
||||
return &ifi
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func isMulticastAvailable(ifi *net.Interface) (net.IP, bool) {
|
||||
if ifi == nil || ifi.Flags&net.FlagUp == 0 || ifi.Flags&net.FlagMulticast == 0 {
|
||||
return nil, false
|
||||
}
|
||||
ifat, err := ifi.Addrs()
|
||||
if err != nil {
|
||||
return nil, false
|
||||
}
|
||||
for _, ifa := range ifat {
|
||||
switch ifa := ifa.(type) {
|
||||
case *net.IPAddr:
|
||||
if isLinkLocalUnicast(ifa.IP) {
|
||||
return ifa.IP, true
|
||||
}
|
||||
case *net.IPNet:
|
||||
if isLinkLocalUnicast(ifa.IP) {
|
||||
return ifa.IP, true
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil, false
|
||||
}
|
||||
|
||||
func connector(t *testing.T, network, addr string, done chan<- bool) {
|
||||
defer func() { done <- true }()
|
||||
|
||||
c, err := net.Dial(network, addr)
|
||||
if err != nil {
|
||||
t.Errorf("net.Dial failed: %v", err)
|
||||
return
|
||||
}
|
||||
c.Close()
|
||||
}
|
||||
|
||||
func acceptor(t *testing.T, ln net.Listener, done chan<- bool) {
|
||||
defer func() { done <- true }()
|
||||
|
||||
c, err := ln.Accept()
|
||||
if err != nil {
|
||||
t.Errorf("net.Listener.Accept failed: %v", err)
|
||||
return
|
||||
}
|
||||
c.Close()
|
||||
}
|
||||
205
Godeps/_workspace/src/code.google.com/p/go.net/ipv6/multicast_test.go
generated
vendored
205
Godeps/_workspace/src/code.google.com/p/go.net/ipv6/multicast_test.go
generated
vendored
@@ -1,205 +0,0 @@
|
||||
// Copyright 2013 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package ipv6_test
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"code.google.com/p/go.net/ipv6"
|
||||
"net"
|
||||
"os"
|
||||
"runtime"
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
func TestPacketConnReadWriteMulticastUDP(t *testing.T) {
|
||||
switch runtime.GOOS {
|
||||
case "freebsd": // due to a bug on loopback marking
|
||||
// See http://www.freebsd.org/cgi/query-pr.cgi?pr=180065.
|
||||
t.Skipf("not supported on %q", runtime.GOOS)
|
||||
case "dragonfly", "plan9", "solaris", "windows":
|
||||
t.Skipf("not supported on %q", runtime.GOOS)
|
||||
}
|
||||
if !supportsIPv6 {
|
||||
t.Skip("ipv6 is not supported")
|
||||
}
|
||||
ifi := loopbackInterface()
|
||||
if ifi == nil {
|
||||
t.Skipf("not available on %q", runtime.GOOS)
|
||||
}
|
||||
|
||||
c, err := net.ListenPacket("udp6", "[ff02::114]:0") // see RFC 4727
|
||||
if err != nil {
|
||||
t.Fatalf("net.ListenPacket failed: %v", err)
|
||||
}
|
||||
defer c.Close()
|
||||
|
||||
_, port, err := net.SplitHostPort(c.LocalAddr().String())
|
||||
if err != nil {
|
||||
t.Fatalf("net.SplitHostPort failed: %v", err)
|
||||
}
|
||||
dst, err := net.ResolveUDPAddr("udp6", "[ff02::114]:"+port) // see RFC 4727
|
||||
if err != nil {
|
||||
t.Fatalf("net.ResolveUDPAddr failed: %v", err)
|
||||
}
|
||||
|
||||
p := ipv6.NewPacketConn(c)
|
||||
defer p.Close()
|
||||
if err := p.JoinGroup(ifi, dst); err != nil {
|
||||
t.Fatalf("ipv6.PacketConn.JoinGroup on %v failed: %v", ifi, err)
|
||||
}
|
||||
if err := p.SetMulticastInterface(ifi); err != nil {
|
||||
t.Fatalf("ipv6.PacketConn.SetMulticastInterface failed: %v", err)
|
||||
}
|
||||
if _, err := p.MulticastInterface(); err != nil {
|
||||
t.Fatalf("ipv6.PacketConn.MulticastInterface failed: %v", err)
|
||||
}
|
||||
if err := p.SetMulticastLoopback(true); err != nil {
|
||||
t.Fatalf("ipv6.PacketConn.SetMulticastLoopback failed: %v", err)
|
||||
}
|
||||
if _, err := p.MulticastLoopback(); err != nil {
|
||||
t.Fatalf("ipv6.PacketConn.MulticastLoopback failed: %v", err)
|
||||
}
|
||||
|
||||
cm := ipv6.ControlMessage{
|
||||
TrafficClass: DiffServAF11 | CongestionExperienced,
|
||||
Src: net.IPv6loopback,
|
||||
IfIndex: ifi.Index,
|
||||
}
|
||||
cf := ipv6.FlagTrafficClass | ipv6.FlagHopLimit | ipv6.FlagSrc | ipv6.FlagDst | ipv6.FlagInterface | ipv6.FlagPathMTU
|
||||
wb := []byte("HELLO-R-U-THERE")
|
||||
|
||||
for i, toggle := range []bool{true, false, true} {
|
||||
if err := p.SetControlMessage(cf, toggle); err != nil {
|
||||
t.Fatalf("ipv6.PacketConn.SetControlMessage failed: %v", err)
|
||||
}
|
||||
if err := p.SetDeadline(time.Now().Add(200 * time.Millisecond)); err != nil {
|
||||
t.Fatalf("ipv6.PacketConn.SetDeadline failed: %v", err)
|
||||
}
|
||||
cm.HopLimit = i + 1
|
||||
if n, err := p.WriteTo(wb, &cm, dst); err != nil {
|
||||
t.Fatalf("ipv6.PacketConn.WriteTo failed: %v", err)
|
||||
} else if n != len(wb) {
|
||||
t.Fatalf("ipv6.PacketConn.WriteTo failed: short write: %v", n)
|
||||
}
|
||||
rb := make([]byte, 128)
|
||||
if n, cm, _, err := p.ReadFrom(rb); err != nil {
|
||||
t.Fatalf("ipv6.PacketConn.ReadFrom failed: %v", err)
|
||||
} else if !bytes.Equal(rb[:n], wb) {
|
||||
t.Fatalf("got %v; expected %v", rb[:n], wb)
|
||||
} else {
|
||||
t.Logf("rcvd cmsg: %v", cm)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestPacketConnReadWriteMulticastICMP(t *testing.T) {
|
||||
switch runtime.GOOS {
|
||||
case "dragonfly", "plan9", "solaris", "windows":
|
||||
t.Skipf("not supported on %q", runtime.GOOS)
|
||||
}
|
||||
if !supportsIPv6 {
|
||||
t.Skip("ipv6 is not supported")
|
||||
}
|
||||
if os.Getuid() != 0 {
|
||||
t.Skip("must be root")
|
||||
}
|
||||
ifi := loopbackInterface()
|
||||
if ifi == nil {
|
||||
t.Skipf("not available on %q", runtime.GOOS)
|
||||
}
|
||||
|
||||
c, err := net.ListenPacket("ip6:ipv6-icmp", "::")
|
||||
if err != nil {
|
||||
t.Fatalf("net.ListenPacket failed: %v", err)
|
||||
}
|
||||
defer c.Close()
|
||||
|
||||
dst, err := net.ResolveIPAddr("ip6", "ff02::114") // see RFC 4727
|
||||
if err != nil {
|
||||
t.Fatalf("net.ResolveIPAddr failed: %v", err)
|
||||
}
|
||||
|
||||
pshicmp := ipv6PseudoHeader(c.LocalAddr().(*net.IPAddr).IP, dst.IP, ianaProtocolIPv6ICMP)
|
||||
p := ipv6.NewPacketConn(c)
|
||||
defer p.Close()
|
||||
if err := p.JoinGroup(ifi, dst); err != nil {
|
||||
t.Fatalf("ipv6.PacketConn.JoinGroup on %v failed: %v", ifi, err)
|
||||
}
|
||||
if err := p.SetMulticastInterface(ifi); err != nil {
|
||||
t.Fatalf("ipv6.PacketConn.SetMulticastInterface failed: %v", err)
|
||||
}
|
||||
if _, err := p.MulticastInterface(); err != nil {
|
||||
t.Fatalf("ipv6.PacketConn.MulticastInterface failed: %v", err)
|
||||
}
|
||||
if err := p.SetMulticastLoopback(true); err != nil {
|
||||
t.Fatalf("ipv6.PacketConn.SetMulticastLoopback failed: %v", err)
|
||||
}
|
||||
if _, err := p.MulticastLoopback(); err != nil {
|
||||
t.Fatalf("ipv6.PacketConn.MulticastLoopback failed: %v", err)
|
||||
}
|
||||
|
||||
cm := ipv6.ControlMessage{
|
||||
TrafficClass: DiffServAF11 | CongestionExperienced,
|
||||
Src: net.IPv6loopback,
|
||||
IfIndex: ifi.Index,
|
||||
}
|
||||
cf := ipv6.FlagTrafficClass | ipv6.FlagHopLimit | ipv6.FlagSrc | ipv6.FlagDst | ipv6.FlagInterface | ipv6.FlagPathMTU
|
||||
|
||||
var f ipv6.ICMPFilter
|
||||
f.SetAll(true)
|
||||
f.Set(ipv6.ICMPTypeEchoReply, false)
|
||||
if err := p.SetICMPFilter(&f); err != nil {
|
||||
t.Fatalf("ipv6.PacketConn.SetICMPFilter failed: %v", err)
|
||||
}
|
||||
|
||||
var psh []byte
|
||||
for i, toggle := range []bool{true, false, true} {
|
||||
if toggle {
|
||||
psh = nil
|
||||
if err := p.SetChecksum(true, 2); err != nil {
|
||||
t.Fatalf("ipv6.PacketConn.SetChecksum failed: %v", err)
|
||||
}
|
||||
} else {
|
||||
psh = pshicmp
|
||||
// Some platforms never allow to disable the
|
||||
// kernel checksum processing.
|
||||
p.SetChecksum(false, -1)
|
||||
}
|
||||
wb, err := (&icmpMessage{
|
||||
Type: ipv6.ICMPTypeEchoRequest, Code: 0,
|
||||
Body: &icmpEcho{
|
||||
ID: os.Getpid() & 0xffff, Seq: i + 1,
|
||||
Data: []byte("HELLO-R-U-THERE"),
|
||||
},
|
||||
}).Marshal(psh)
|
||||
if err != nil {
|
||||
t.Fatalf("icmpMessage.Marshal failed: %v", err)
|
||||
}
|
||||
if err := p.SetControlMessage(cf, toggle); err != nil {
|
||||
t.Fatalf("ipv6.PacketConn.SetControlMessage failed: %v", err)
|
||||
}
|
||||
if err := p.SetDeadline(time.Now().Add(200 * time.Millisecond)); err != nil {
|
||||
t.Fatalf("ipv6.PacketConn.SetDeadline failed: %v", err)
|
||||
}
|
||||
cm.HopLimit = i + 1
|
||||
if n, err := p.WriteTo(wb, &cm, dst); err != nil {
|
||||
t.Fatalf("ipv6.PacketConn.WriteTo failed: %v", err)
|
||||
} else if n != len(wb) {
|
||||
t.Fatalf("ipv6.PacketConn.WriteTo failed: short write: %v", n)
|
||||
}
|
||||
rb := make([]byte, 128)
|
||||
if n, cm, _, err := p.ReadFrom(rb); err != nil {
|
||||
t.Fatalf("ipv6.PacketConn.ReadFrom failed: %v", err)
|
||||
} else {
|
||||
t.Logf("rcvd cmsg: %v", cm)
|
||||
if m, err := parseICMPMessage(rb[:n]); err != nil {
|
||||
t.Fatalf("parseICMPMessage failed: %v", err)
|
||||
} else if m.Type != ipv6.ICMPTypeEchoReply || m.Code != 0 {
|
||||
t.Fatalf("got type=%v, code=%v; expected type=%v, code=%v", m.Type, m.Code, ipv6.ICMPTypeEchoReply, 0)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
243
Godeps/_workspace/src/code.google.com/p/go.net/ipv6/multicastlistener_test.go
generated
vendored
243
Godeps/_workspace/src/code.google.com/p/go.net/ipv6/multicastlistener_test.go
generated
vendored
@@ -1,243 +0,0 @@
|
||||
// Copyright 2013 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package ipv6_test
|
||||
|
||||
import (
|
||||
"code.google.com/p/go.net/ipv6"
|
||||
"fmt"
|
||||
"net"
|
||||
"os"
|
||||
"runtime"
|
||||
"testing"
|
||||
)
|
||||
|
||||
var udpMultipleGroupListenerTests = []net.Addr{
|
||||
&net.UDPAddr{IP: net.ParseIP("ff02::114")}, // see RFC 4727
|
||||
&net.UDPAddr{IP: net.ParseIP("ff02::1:114")},
|
||||
&net.UDPAddr{IP: net.ParseIP("ff02::2:114")},
|
||||
}
|
||||
|
||||
func TestUDPSinglePacketConnWithMultipleGroupListeners(t *testing.T) {
|
||||
switch runtime.GOOS {
|
||||
case "dragonfly", "plan9", "solaris", "windows":
|
||||
t.Skipf("not supported on %q", runtime.GOOS)
|
||||
}
|
||||
if !supportsIPv6 {
|
||||
t.Skip("ipv6 is not supported")
|
||||
}
|
||||
|
||||
for _, gaddr := range udpMultipleGroupListenerTests {
|
||||
c, err := net.ListenPacket("udp6", "[::]:0") // wildcard address with non-reusable port
|
||||
if err != nil {
|
||||
t.Fatalf("net.ListenPacket failed: %v", err)
|
||||
}
|
||||
defer c.Close()
|
||||
|
||||
p := ipv6.NewPacketConn(c)
|
||||
var mift []*net.Interface
|
||||
|
||||
ift, err := net.Interfaces()
|
||||
if err != nil {
|
||||
t.Fatalf("net.Interfaces failed: %v", err)
|
||||
}
|
||||
for i, ifi := range ift {
|
||||
if _, ok := isMulticastAvailable(&ifi); !ok {
|
||||
continue
|
||||
}
|
||||
if err := p.JoinGroup(&ifi, gaddr); err != nil {
|
||||
t.Fatalf("ipv6.PacketConn.JoinGroup %v on %v failed: %v", gaddr, ifi, err)
|
||||
}
|
||||
mift = append(mift, &ift[i])
|
||||
}
|
||||
for _, ifi := range mift {
|
||||
if err := p.LeaveGroup(ifi, gaddr); err != nil {
|
||||
t.Fatalf("ipv6.PacketConn.LeaveGroup %v on %v failed: %v", gaddr, ifi, err)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestUDPMultiplePacketConnWithMultipleGroupListeners(t *testing.T) {
|
||||
switch runtime.GOOS {
|
||||
case "dragonfly", "plan9", "solaris", "windows":
|
||||
t.Skipf("not supported on %q", runtime.GOOS)
|
||||
}
|
||||
if !supportsIPv6 {
|
||||
t.Skip("ipv6 is not supported")
|
||||
}
|
||||
|
||||
for _, gaddr := range udpMultipleGroupListenerTests {
|
||||
c1, err := net.ListenPacket("udp6", "[ff02::]:1024") // wildcard address with reusable port
|
||||
if err != nil {
|
||||
t.Fatalf("net.ListenPacket failed: %v", err)
|
||||
}
|
||||
defer c1.Close()
|
||||
|
||||
c2, err := net.ListenPacket("udp6", "[ff02::]:1024") // wildcard address with reusable port
|
||||
if err != nil {
|
||||
t.Fatalf("net.ListenPacket failed: %v", err)
|
||||
}
|
||||
defer c2.Close()
|
||||
|
||||
var ps [2]*ipv6.PacketConn
|
||||
ps[0] = ipv6.NewPacketConn(c1)
|
||||
ps[1] = ipv6.NewPacketConn(c2)
|
||||
var mift []*net.Interface
|
||||
|
||||
ift, err := net.Interfaces()
|
||||
if err != nil {
|
||||
t.Fatalf("net.Interfaces failed: %v", err)
|
||||
}
|
||||
for i, ifi := range ift {
|
||||
if _, ok := isMulticastAvailable(&ifi); !ok {
|
||||
continue
|
||||
}
|
||||
for _, p := range ps {
|
||||
if err := p.JoinGroup(&ifi, gaddr); err != nil {
|
||||
t.Fatalf("ipv6.PacketConn.JoinGroup %v on %v failed: %v", gaddr, ifi, err)
|
||||
}
|
||||
}
|
||||
mift = append(mift, &ift[i])
|
||||
}
|
||||
for _, ifi := range mift {
|
||||
for _, p := range ps {
|
||||
if err := p.LeaveGroup(ifi, gaddr); err != nil {
|
||||
t.Fatalf("ipv6.PacketConn.LeaveGroup %v on %v failed: %v", gaddr, ifi, err)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestUDPPerInterfaceSinglePacketConnWithSingleGroupListener(t *testing.T) {
|
||||
switch runtime.GOOS {
|
||||
case "dragonfly", "plan9", "solaris", "windows":
|
||||
t.Skipf("not supported on %q", runtime.GOOS)
|
||||
}
|
||||
if !supportsIPv6 {
|
||||
t.Skip("ipv6 is not supported")
|
||||
}
|
||||
|
||||
gaddr := net.IPAddr{IP: net.ParseIP("ff02::114")} // see RFC 4727
|
||||
type ml struct {
|
||||
c *ipv6.PacketConn
|
||||
ifi *net.Interface
|
||||
}
|
||||
var mlt []*ml
|
||||
|
||||
ift, err := net.Interfaces()
|
||||
if err != nil {
|
||||
t.Fatalf("net.Interfaces failed: %v", err)
|
||||
}
|
||||
for i, ifi := range ift {
|
||||
ip, ok := isMulticastAvailable(&ifi)
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
c, err := net.ListenPacket("udp6", fmt.Sprintf("[%s%%%s]:1024", ip.String(), ifi.Name)) // unicast address with non-reusable port
|
||||
if err != nil {
|
||||
t.Fatalf("net.ListenPacket with %v failed: %v", ip, err)
|
||||
}
|
||||
defer c.Close()
|
||||
p := ipv6.NewPacketConn(c)
|
||||
if err := p.JoinGroup(&ifi, &gaddr); err != nil {
|
||||
t.Fatalf("ipv6.PacketConn.JoinGroup on %v failed: %v", ifi, err)
|
||||
}
|
||||
mlt = append(mlt, &ml{p, &ift[i]})
|
||||
}
|
||||
for _, m := range mlt {
|
||||
if err := m.c.LeaveGroup(m.ifi, &gaddr); err != nil {
|
||||
t.Fatalf("ipv6.PacketConn.LeaveGroup on %v failed: %v", m.ifi, err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestIPSinglePacketConnWithSingleGroupListener(t *testing.T) {
|
||||
switch runtime.GOOS {
|
||||
case "dragonfly", "plan9", "solaris", "windows":
|
||||
t.Skipf("not supported on %q", runtime.GOOS)
|
||||
}
|
||||
if !supportsIPv6 {
|
||||
t.Skip("ipv6 is not supported")
|
||||
}
|
||||
if os.Getuid() != 0 {
|
||||
t.Skip("must be root")
|
||||
}
|
||||
|
||||
c, err := net.ListenPacket("ip6:ipv6-icmp", "::") // wildcard address
|
||||
if err != nil {
|
||||
t.Fatalf("net.ListenPacket failed: %v", err)
|
||||
}
|
||||
defer c.Close()
|
||||
|
||||
p := ipv6.NewPacketConn(c)
|
||||
gaddr := net.IPAddr{IP: net.ParseIP("ff02::114")} // see RFC 4727
|
||||
var mift []*net.Interface
|
||||
|
||||
ift, err := net.Interfaces()
|
||||
if err != nil {
|
||||
t.Fatalf("net.Interfaces failed: %v", err)
|
||||
}
|
||||
for i, ifi := range ift {
|
||||
if _, ok := isMulticastAvailable(&ifi); !ok {
|
||||
continue
|
||||
}
|
||||
if err := p.JoinGroup(&ifi, &gaddr); err != nil {
|
||||
t.Fatalf("ipv6.PacketConn.JoinGroup on %v failed: %v", ifi, err)
|
||||
}
|
||||
mift = append(mift, &ift[i])
|
||||
}
|
||||
for _, ifi := range mift {
|
||||
if err := p.LeaveGroup(ifi, &gaddr); err != nil {
|
||||
t.Fatalf("ipv6.PacketConn.LeaveGroup on %v failed: %v", ifi, err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestIPPerInterfaceSinglePacketConnWithSingleGroupListener(t *testing.T) {
|
||||
switch runtime.GOOS {
|
||||
case "darwin", "dragonfly", "plan9", "solaris", "windows":
|
||||
t.Skipf("not supported on %q", runtime.GOOS)
|
||||
}
|
||||
if !supportsIPv6 {
|
||||
t.Skip("ipv6 is not supported")
|
||||
}
|
||||
if os.Getuid() != 0 {
|
||||
t.Skip("must be root")
|
||||
}
|
||||
|
||||
gaddr := net.IPAddr{IP: net.ParseIP("ff02::114")} // see RFC 4727
|
||||
type ml struct {
|
||||
c *ipv6.PacketConn
|
||||
ifi *net.Interface
|
||||
}
|
||||
var mlt []*ml
|
||||
|
||||
ift, err := net.Interfaces()
|
||||
if err != nil {
|
||||
t.Fatalf("net.Interfaces failed: %v", err)
|
||||
}
|
||||
for i, ifi := range ift {
|
||||
ip, ok := isMulticastAvailable(&ifi)
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
c, err := net.ListenPacket("ip6:ipv6-icmp", fmt.Sprintf("%s%%%s", ip.String(), ifi.Name)) // unicast address
|
||||
if err != nil {
|
||||
t.Fatalf("net.ListenPacket failed: %v", err)
|
||||
}
|
||||
defer c.Close()
|
||||
p := ipv6.NewPacketConn(c)
|
||||
if err := p.JoinGroup(&ifi, &gaddr); err != nil {
|
||||
t.Fatalf("ipv6.PacketConn.JoinGroup on %v failed: %v", ifi, err)
|
||||
}
|
||||
mlt = append(mlt, &ml{p, &ift[i]})
|
||||
}
|
||||
for _, m := range mlt {
|
||||
if err := m.c.LeaveGroup(m.ifi, &gaddr); err != nil {
|
||||
t.Fatalf("ipv6.PacketConn.LeaveGroup on %v failed: %v", m.ifi, err)
|
||||
}
|
||||
}
|
||||
}
|
||||
76
Godeps/_workspace/src/code.google.com/p/go.net/ipv6/multicastsockopt_test.go
generated
vendored
76
Godeps/_workspace/src/code.google.com/p/go.net/ipv6/multicastsockopt_test.go
generated
vendored
@@ -1,76 +0,0 @@
|
||||
// Copyright 2013 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package ipv6_test
|
||||
|
||||
import (
|
||||
"code.google.com/p/go.net/ipv6"
|
||||
"net"
|
||||
"os"
|
||||
"runtime"
|
||||
"testing"
|
||||
)
|
||||
|
||||
var packetConnMulticastSocketOptionTests = []struct {
|
||||
net, proto, addr string
|
||||
gaddr net.Addr
|
||||
}{
|
||||
{"udp6", "", "[ff02::]:0", &net.UDPAddr{IP: net.ParseIP("ff02::114")}}, // see RFC 4727
|
||||
{"ip6", ":ipv6-icmp", "::", &net.IPAddr{IP: net.ParseIP("ff02::114")}}, // see RFC 4727
|
||||
}
|
||||
|
||||
func TestPacketConnMulticastSocketOptions(t *testing.T) {
|
||||
switch runtime.GOOS {
|
||||
case "dragonfly", "plan9", "solaris", "windows":
|
||||
t.Skipf("not supported on %q", runtime.GOOS)
|
||||
}
|
||||
if !supportsIPv6 {
|
||||
t.Skip("ipv6 is not supported")
|
||||
}
|
||||
ifi := loopbackInterface()
|
||||
if ifi == nil {
|
||||
t.Skipf("not available on %q", runtime.GOOS)
|
||||
}
|
||||
|
||||
for _, tt := range packetConnMulticastSocketOptionTests {
|
||||
if tt.net == "ip6" && os.Getuid() != 0 {
|
||||
t.Skip("must be root")
|
||||
}
|
||||
c, err := net.ListenPacket(tt.net+tt.proto, tt.addr)
|
||||
if err != nil {
|
||||
t.Fatalf("net.ListenPacket failed: %v", err)
|
||||
}
|
||||
defer c.Close()
|
||||
|
||||
p := ipv6.NewPacketConn(c)
|
||||
|
||||
hoplim := 255
|
||||
if err := p.SetMulticastHopLimit(hoplim); err != nil {
|
||||
t.Fatalf("ipv6.PacketConn.SetMulticastHopLimit failed: %v", err)
|
||||
}
|
||||
if v, err := p.MulticastHopLimit(); err != nil {
|
||||
t.Fatalf("ipv6.PacketConn.MulticastHopLimit failed: %v", err)
|
||||
} else if v != hoplim {
|
||||
t.Fatalf("got unexpected multicast hop limit %v; expected %v", v, hoplim)
|
||||
}
|
||||
|
||||
for _, toggle := range []bool{true, false} {
|
||||
if err := p.SetMulticastLoopback(toggle); err != nil {
|
||||
t.Fatalf("ipv6.PacketConn.SetMulticastLoopback failed: %v", err)
|
||||
}
|
||||
if v, err := p.MulticastLoopback(); err != nil {
|
||||
t.Fatalf("ipv6.PacketConn.MulticastLoopback failed: %v", err)
|
||||
} else if v != toggle {
|
||||
t.Fatalf("got unexpected multicast loopback %v; expected %v", v, toggle)
|
||||
}
|
||||
}
|
||||
|
||||
if err := p.JoinGroup(ifi, tt.gaddr); err != nil {
|
||||
t.Fatalf("ipv6.PacketConn.JoinGroup(%v, %v) failed: %v", ifi, tt.gaddr, err)
|
||||
}
|
||||
if err := p.LeaveGroup(ifi, tt.gaddr); err != nil {
|
||||
t.Fatalf("ipv6.PacketConn.LeaveGroup(%v, %v) failed: %v", ifi, tt.gaddr, err)
|
||||
}
|
||||
}
|
||||
}
|
||||
15
Godeps/_workspace/src/code.google.com/p/go.net/ipv6/payload.go
generated
vendored
15
Godeps/_workspace/src/code.google.com/p/go.net/ipv6/payload.go
generated
vendored
@@ -1,15 +0,0 @@
|
||||
// Copyright 2013 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package ipv6
|
||||
|
||||
import "net"
|
||||
|
||||
// A payloadHandler represents the IPv6 datagram payload handler.
|
||||
type payloadHandler struct {
|
||||
net.PacketConn
|
||||
rawOpt
|
||||
}
|
||||
|
||||
func (c *payloadHandler) ok() bool { return c != nil && c.PacketConn != nil }
|
||||
70
Godeps/_workspace/src/code.google.com/p/go.net/ipv6/payload_cmsg.go
generated
vendored
70
Godeps/_workspace/src/code.google.com/p/go.net/ipv6/payload_cmsg.go
generated
vendored
@@ -1,70 +0,0 @@
|
||||
// Copyright 2013 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build !plan9,!windows
|
||||
|
||||
package ipv6
|
||||
|
||||
import (
|
||||
"net"
|
||||
"syscall"
|
||||
)
|
||||
|
||||
// ReadFrom reads a payload of the received IPv6 datagram, from the
|
||||
// endpoint c, copying the payload into b. It returns the number of
|
||||
// bytes copied into b, the control message cm and the source address
|
||||
// src of the received datagram.
|
||||
func (c *payloadHandler) ReadFrom(b []byte) (n int, cm *ControlMessage, src net.Addr, err error) {
|
||||
if !c.ok() {
|
||||
return 0, nil, nil, syscall.EINVAL
|
||||
}
|
||||
oob := newControlMessage(&c.rawOpt)
|
||||
var oobn int
|
||||
switch c := c.PacketConn.(type) {
|
||||
case *net.UDPConn:
|
||||
if n, oobn, _, src, err = c.ReadMsgUDP(b, oob); err != nil {
|
||||
return 0, nil, nil, err
|
||||
}
|
||||
case *net.IPConn:
|
||||
if n, oobn, _, src, err = c.ReadMsgIP(b, oob); err != nil {
|
||||
return 0, nil, nil, err
|
||||
}
|
||||
default:
|
||||
return 0, nil, nil, errInvalidConnType
|
||||
}
|
||||
if cm, err = parseControlMessage(oob[:oobn]); err != nil {
|
||||
return 0, nil, nil, err
|
||||
}
|
||||
if cm != nil {
|
||||
cm.Src = netAddrToIP16(src)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// WriteTo writes a payload of the IPv6 datagram, to the destination
|
||||
// address dst through the endpoint c, copying the payload from b. It
|
||||
// returns the number of bytes written. The control message cm allows
|
||||
// the IPv6 header fields and the datagram path to be specified. The
|
||||
// cm may be nil if control of the outgoing datagram is not required.
|
||||
func (c *payloadHandler) WriteTo(b []byte, cm *ControlMessage, dst net.Addr) (n int, err error) {
|
||||
if !c.ok() {
|
||||
return 0, syscall.EINVAL
|
||||
}
|
||||
oob := marshalControlMessage(cm)
|
||||
if dst == nil {
|
||||
return 0, errMissingAddress
|
||||
}
|
||||
switch c := c.PacketConn.(type) {
|
||||
case *net.UDPConn:
|
||||
n, _, err = c.WriteMsgUDP(b, oob, dst.(*net.UDPAddr))
|
||||
case *net.IPConn:
|
||||
n, _, err = c.WriteMsgIP(b, oob, dst.(*net.IPAddr))
|
||||
default:
|
||||
return 0, errInvalidConnType
|
||||
}
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return
|
||||
}
|
||||
41
Godeps/_workspace/src/code.google.com/p/go.net/ipv6/payload_noncmsg.go
generated
vendored
41
Godeps/_workspace/src/code.google.com/p/go.net/ipv6/payload_noncmsg.go
generated
vendored
@@ -1,41 +0,0 @@
|
||||
// Copyright 2013 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build plan9 windows
|
||||
|
||||
package ipv6
|
||||
|
||||
import (
|
||||
"net"
|
||||
"syscall"
|
||||
)
|
||||
|
||||
// ReadFrom reads a payload of the received IPv6 datagram, from the
|
||||
// endpoint c, copying the payload into b. It returns the number of
|
||||
// bytes copied into b, the control message cm and the source address
|
||||
// src of the received datagram.
|
||||
func (c *payloadHandler) ReadFrom(b []byte) (n int, cm *ControlMessage, src net.Addr, err error) {
|
||||
if !c.ok() {
|
||||
return 0, nil, nil, syscall.EINVAL
|
||||
}
|
||||
if n, src, err = c.PacketConn.ReadFrom(b); err != nil {
|
||||
return 0, nil, nil, err
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// WriteTo writes a payload of the IPv6 datagram, to the destination
|
||||
// address dst through the endpoint c, copying the payload from b. It
|
||||
// returns the number of bytes written. The control message cm allows
|
||||
// the IPv6 header fields and the datagram path to be specified. The
|
||||
// cm may be nil if control of the outgoing datagram is not required.
|
||||
func (c *payloadHandler) WriteTo(b []byte, cm *ControlMessage, dst net.Addr) (n int, err error) {
|
||||
if !c.ok() {
|
||||
return 0, syscall.EINVAL
|
||||
}
|
||||
if dst == nil {
|
||||
return 0, errMissingAddress
|
||||
}
|
||||
return c.PacketConn.WriteTo(b, dst)
|
||||
}
|
||||
168
Godeps/_workspace/src/code.google.com/p/go.net/ipv6/readwrite_test.go
generated
vendored
168
Godeps/_workspace/src/code.google.com/p/go.net/ipv6/readwrite_test.go
generated
vendored
@@ -1,168 +0,0 @@
|
||||
// Copyright 2013 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package ipv6_test
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"code.google.com/p/go.net/ipv6"
|
||||
"net"
|
||||
"runtime"
|
||||
"sync"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func benchmarkUDPListener() (net.PacketConn, net.Addr, error) {
|
||||
c, err := net.ListenPacket("udp6", "[::1]:0")
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
dst, err := net.ResolveUDPAddr("udp6", c.LocalAddr().String())
|
||||
if err != nil {
|
||||
c.Close()
|
||||
return nil, nil, err
|
||||
}
|
||||
return c, dst, nil
|
||||
}
|
||||
|
||||
func BenchmarkReadWriteNetUDP(b *testing.B) {
|
||||
c, dst, err := benchmarkUDPListener()
|
||||
if err != nil {
|
||||
b.Fatalf("benchmarkUDPListener failed: %v", err)
|
||||
}
|
||||
defer c.Close()
|
||||
|
||||
wb, rb := []byte("HELLO-R-U-THERE"), make([]byte, 128)
|
||||
b.ResetTimer()
|
||||
for i := 0; i < b.N; i++ {
|
||||
benchmarkReadWriteNetUDP(b, c, wb, rb, dst)
|
||||
}
|
||||
}
|
||||
|
||||
func benchmarkReadWriteNetUDP(b *testing.B, c net.PacketConn, wb, rb []byte, dst net.Addr) {
|
||||
if _, err := c.WriteTo(wb, dst); err != nil {
|
||||
b.Fatalf("net.PacketConn.WriteTo failed: %v", err)
|
||||
}
|
||||
if _, _, err := c.ReadFrom(rb); err != nil {
|
||||
b.Fatalf("net.PacketConn.ReadFrom failed: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkReadWriteIPv6UDP(b *testing.B) {
|
||||
c, dst, err := benchmarkUDPListener()
|
||||
if err != nil {
|
||||
b.Fatalf("benchmarkUDPListener failed: %v", err)
|
||||
}
|
||||
defer c.Close()
|
||||
|
||||
p := ipv6.NewPacketConn(c)
|
||||
cf := ipv6.FlagTrafficClass | ipv6.FlagHopLimit | ipv6.FlagInterface | ipv6.FlagPathMTU
|
||||
if err := p.SetControlMessage(cf, true); err != nil {
|
||||
b.Fatalf("ipv6.PacketConn.SetControlMessage failed: %v", err)
|
||||
}
|
||||
ifi := loopbackInterface()
|
||||
|
||||
wb, rb := []byte("HELLO-R-U-THERE"), make([]byte, 128)
|
||||
b.ResetTimer()
|
||||
for i := 0; i < b.N; i++ {
|
||||
benchmarkReadWriteIPv6UDP(b, p, wb, rb, dst, ifi)
|
||||
}
|
||||
}
|
||||
|
||||
func benchmarkReadWriteIPv6UDP(b *testing.B, p *ipv6.PacketConn, wb, rb []byte, dst net.Addr, ifi *net.Interface) {
|
||||
cm := ipv6.ControlMessage{
|
||||
TrafficClass: DiffServAF11 | CongestionExperienced,
|
||||
HopLimit: 1,
|
||||
}
|
||||
if ifi != nil {
|
||||
cm.IfIndex = ifi.Index
|
||||
}
|
||||
if n, err := p.WriteTo(wb, &cm, dst); err != nil {
|
||||
b.Fatalf("ipv6.PacketConn.WriteTo failed: %v", err)
|
||||
} else if n != len(wb) {
|
||||
b.Fatalf("ipv6.PacketConn.WriteTo failed: short write: %v", n)
|
||||
}
|
||||
if _, _, _, err := p.ReadFrom(rb); err != nil {
|
||||
b.Fatalf("ipv6.PacketConn.ReadFrom failed: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestPacketConnConcurrentReadWriteUnicastUDP(t *testing.T) {
|
||||
switch runtime.GOOS {
|
||||
case "dragonfly", "plan9", "solaris", "windows":
|
||||
t.Skipf("not supported on %q", runtime.GOOS)
|
||||
}
|
||||
if !supportsIPv6 {
|
||||
t.Skip("ipv6 is not supported")
|
||||
}
|
||||
|
||||
c, err := net.ListenPacket("udp6", "[::1]:0")
|
||||
if err != nil {
|
||||
t.Fatalf("net.ListenPacket failed: %v", err)
|
||||
}
|
||||
defer c.Close()
|
||||
p := ipv6.NewPacketConn(c)
|
||||
defer p.Close()
|
||||
|
||||
dst, err := net.ResolveUDPAddr("udp6", c.LocalAddr().String())
|
||||
if err != nil {
|
||||
t.Fatalf("net.ResolveUDPAddr failed: %v", err)
|
||||
}
|
||||
|
||||
ifi := loopbackInterface()
|
||||
cf := ipv6.FlagTrafficClass | ipv6.FlagHopLimit | ipv6.FlagSrc | ipv6.FlagDst | ipv6.FlagInterface | ipv6.FlagPathMTU
|
||||
wb := []byte("HELLO-R-U-THERE")
|
||||
|
||||
var wg sync.WaitGroup
|
||||
reader := func() {
|
||||
defer wg.Done()
|
||||
rb := make([]byte, 128)
|
||||
if n, cm, _, err := p.ReadFrom(rb); err != nil {
|
||||
t.Errorf("ipv6.PacketConn.ReadFrom failed: %v", err)
|
||||
return
|
||||
} else if !bytes.Equal(rb[:n], wb) {
|
||||
t.Errorf("got %v; expected %v", rb[:n], wb)
|
||||
return
|
||||
} else {
|
||||
t.Logf("rcvd cmsg: %v", cm)
|
||||
}
|
||||
}
|
||||
writer := func(toggle bool) {
|
||||
defer wg.Done()
|
||||
cm := ipv6.ControlMessage{
|
||||
TrafficClass: DiffServAF11 | CongestionExperienced,
|
||||
Src: net.IPv6loopback,
|
||||
Dst: net.IPv6loopback,
|
||||
}
|
||||
if ifi != nil {
|
||||
cm.IfIndex = ifi.Index
|
||||
}
|
||||
if err := p.SetControlMessage(cf, toggle); err != nil {
|
||||
t.Errorf("ipv6.PacketConn.SetControlMessage failed: %v", err)
|
||||
return
|
||||
}
|
||||
if n, err := p.WriteTo(wb, &cm, dst); err != nil {
|
||||
t.Errorf("ipv6.PacketConn.WriteTo failed: %v", err)
|
||||
return
|
||||
} else if n != len(wb) {
|
||||
t.Errorf("ipv6.PacketConn.WriteTo failed: short write: %v", n)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
const N = 10
|
||||
wg.Add(N)
|
||||
for i := 0; i < N; i++ {
|
||||
go reader()
|
||||
}
|
||||
wg.Add(2 * N)
|
||||
for i := 0; i < 2*N; i++ {
|
||||
go writer(i%2 != 0)
|
||||
}
|
||||
wg.Add(N)
|
||||
for i := 0; i < N; i++ {
|
||||
go reader()
|
||||
}
|
||||
wg.Wait()
|
||||
}
|
||||
73
Godeps/_workspace/src/code.google.com/p/go.net/ipv6/sockopt_rfc2292_unix.go
generated
vendored
73
Godeps/_workspace/src/code.google.com/p/go.net/ipv6/sockopt_rfc2292_unix.go
generated
vendored
@@ -1,73 +0,0 @@
|
||||
// Copyright 2013 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build darwin
|
||||
|
||||
package ipv6
|
||||
|
||||
import (
|
||||
"os"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
func ipv6ReceiveTrafficClass(fd int) (bool, error) {
|
||||
return false, errOpNoSupport
|
||||
}
|
||||
|
||||
func setIPv6ReceiveTrafficClass(fd int, v bool) error {
|
||||
return errOpNoSupport
|
||||
}
|
||||
|
||||
func ipv6ReceiveHopLimit(fd int) (bool, error) {
|
||||
var v int32
|
||||
l := sysSockoptLen(4)
|
||||
if err := getsockopt(fd, ianaProtocolIPv6, sysSockopt2292HopLimit, uintptr(unsafe.Pointer(&v)), &l); err != nil {
|
||||
return false, os.NewSyscallError("getsockopt", err)
|
||||
}
|
||||
return v == 1, nil
|
||||
}
|
||||
|
||||
func setIPv6ReceiveHopLimit(fd int, v bool) error {
|
||||
vv := int32(boolint(v))
|
||||
return os.NewSyscallError("setsockopt", setsockopt(fd, ianaProtocolIPv6, sysSockopt2292HopLimit, uintptr(unsafe.Pointer(&vv)), 4))
|
||||
}
|
||||
|
||||
func ipv6ReceivePacketInfo(fd int) (bool, error) {
|
||||
var v int32
|
||||
l := sysSockoptLen(4)
|
||||
if err := getsockopt(fd, ianaProtocolIPv6, sysSockopt2292PacketInfo, uintptr(unsafe.Pointer(&v)), &l); err != nil {
|
||||
return false, os.NewSyscallError("getsockopt", err)
|
||||
}
|
||||
return v == 1, nil
|
||||
}
|
||||
|
||||
func setIPv6ReceivePacketInfo(fd int, v bool) error {
|
||||
vv := int32(boolint(v))
|
||||
return os.NewSyscallError("setsockopt", setsockopt(fd, ianaProtocolIPv6, sysSockopt2292PacketInfo, uintptr(unsafe.Pointer(&vv)), 4))
|
||||
}
|
||||
|
||||
func ipv6PathMTU(fd int) (int, error) {
|
||||
return 0, errOpNoSupport
|
||||
}
|
||||
|
||||
func ipv6ReceivePathMTU(fd int) (bool, error) {
|
||||
return false, errOpNoSupport
|
||||
}
|
||||
|
||||
func setIPv6ReceivePathMTU(fd int, v bool) error {
|
||||
return errOpNoSupport
|
||||
}
|
||||
|
||||
func ipv6ICMPFilter(fd int) (*ICMPFilter, error) {
|
||||
var v ICMPFilter
|
||||
l := sysSockoptLen(sysSizeofICMPFilter)
|
||||
if err := getsockopt(fd, ianaProtocolIPv6ICMP, sysSockoptICMPFilter, uintptr(unsafe.Pointer(&v.sysICMPFilter)), &l); err != nil {
|
||||
return nil, os.NewSyscallError("getsockopt", err)
|
||||
}
|
||||
return &v, nil
|
||||
}
|
||||
|
||||
func setIPv6ICMPFilter(fd int, f *ICMPFilter) error {
|
||||
return os.NewSyscallError("setsockopt", setsockopt(fd, ianaProtocolIPv6ICMP, sysSockoptICMPFilter, uintptr(unsafe.Pointer(&f.sysICMPFilter)), sysSizeofICMPFilter))
|
||||
}
|
||||
20
Godeps/_workspace/src/code.google.com/p/go.net/ipv6/sockopt_rfc3493_bsd.go
generated
vendored
20
Godeps/_workspace/src/code.google.com/p/go.net/ipv6/sockopt_rfc3493_bsd.go
generated
vendored
@@ -1,20 +0,0 @@
|
||||
// Copyright 2013 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build darwin freebsd netbsd openbsd
|
||||
|
||||
package ipv6
|
||||
|
||||
import (
|
||||
"os"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
func setIPv6Checksum(fd int, on bool, offset int) error {
|
||||
if !on {
|
||||
offset = -1
|
||||
}
|
||||
v := int32(offset)
|
||||
return os.NewSyscallError("setsockopt", setsockopt(fd, ianaProtocolIPv6, sysSockoptChecksum, uintptr(unsafe.Pointer(&v)), 4))
|
||||
}
|
||||
18
Godeps/_workspace/src/code.google.com/p/go.net/ipv6/sockopt_rfc3493_linux.go
generated
vendored
18
Godeps/_workspace/src/code.google.com/p/go.net/ipv6/sockopt_rfc3493_linux.go
generated
vendored
@@ -1,18 +0,0 @@
|
||||
// Copyright 2013 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package ipv6
|
||||
|
||||
import (
|
||||
"os"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
func setIPv6Checksum(fd int, on bool, offset int) error {
|
||||
if !on {
|
||||
offset = -1
|
||||
}
|
||||
v := int32(offset)
|
||||
return os.NewSyscallError("setsockopt", setsockopt(fd, ianaProtocolReserved, sysSockoptChecksum, uintptr(unsafe.Pointer(&v)), 4))
|
||||
}
|
||||
124
Godeps/_workspace/src/code.google.com/p/go.net/ipv6/sockopt_rfc3493_unix.go
generated
vendored
124
Godeps/_workspace/src/code.google.com/p/go.net/ipv6/sockopt_rfc3493_unix.go
generated
vendored
@@ -1,124 +0,0 @@
|
||||
// Copyright 2013 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build darwin freebsd linux netbsd openbsd
|
||||
|
||||
package ipv6
|
||||
|
||||
import (
|
||||
"net"
|
||||
"os"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
func ipv6TrafficClass(fd int) (int, error) {
|
||||
var v int32
|
||||
l := sysSockoptLen(4)
|
||||
if err := getsockopt(fd, ianaProtocolIPv6, sysSockoptTrafficClass, uintptr(unsafe.Pointer(&v)), &l); err != nil {
|
||||
return 0, os.NewSyscallError("getsockopt", err)
|
||||
}
|
||||
return int(v), nil
|
||||
}
|
||||
|
||||
func setIPv6TrafficClass(fd, v int) error {
|
||||
vv := int32(v)
|
||||
return os.NewSyscallError("setsockopt", setsockopt(fd, ianaProtocolIPv6, sysSockoptTrafficClass, uintptr(unsafe.Pointer(&vv)), 4))
|
||||
}
|
||||
|
||||
func ipv6HopLimit(fd int) (int, error) {
|
||||
var v int32
|
||||
l := sysSockoptLen(4)
|
||||
if err := getsockopt(fd, ianaProtocolIPv6, sysSockoptUnicastHopLimit, uintptr(unsafe.Pointer(&v)), &l); err != nil {
|
||||
return 0, os.NewSyscallError("getsockopt", err)
|
||||
}
|
||||
return int(v), nil
|
||||
}
|
||||
|
||||
func setIPv6HopLimit(fd, v int) error {
|
||||
vv := int32(v)
|
||||
return os.NewSyscallError("setsockopt", setsockopt(fd, ianaProtocolIPv6, sysSockoptUnicastHopLimit, uintptr(unsafe.Pointer(&vv)), 4))
|
||||
}
|
||||
|
||||
func ipv6Checksum(fd int) (bool, int, error) {
|
||||
var v int32
|
||||
l := sysSockoptLen(4)
|
||||
if err := getsockopt(fd, ianaProtocolIPv6, sysSockoptChecksum, uintptr(unsafe.Pointer(&v)), &l); err != nil {
|
||||
return false, 0, os.NewSyscallError("getsockopt", err)
|
||||
}
|
||||
on := true
|
||||
if v == -1 {
|
||||
on = false
|
||||
}
|
||||
return on, int(v), nil
|
||||
}
|
||||
|
||||
func ipv6MulticastHopLimit(fd int) (int, error) {
|
||||
var v int32
|
||||
l := sysSockoptLen(4)
|
||||
if err := getsockopt(fd, ianaProtocolIPv6, sysSockoptMulticastHopLimit, uintptr(unsafe.Pointer(&v)), &l); err != nil {
|
||||
return 0, os.NewSyscallError("getsockopt", err)
|
||||
}
|
||||
return int(v), nil
|
||||
}
|
||||
|
||||
func setIPv6MulticastHopLimit(fd, v int) error {
|
||||
vv := int32(v)
|
||||
return os.NewSyscallError("setsockopt", setsockopt(fd, ianaProtocolIPv6, sysSockoptMulticastHopLimit, uintptr(unsafe.Pointer(&vv)), 4))
|
||||
}
|
||||
|
||||
func ipv6MulticastInterface(fd int) (*net.Interface, error) {
|
||||
var v int32
|
||||
l := sysSockoptLen(4)
|
||||
if err := getsockopt(fd, ianaProtocolIPv6, sysSockoptMulticastInterface, uintptr(unsafe.Pointer(&v)), &l); err != nil {
|
||||
return nil, os.NewSyscallError("getsockopt", err)
|
||||
}
|
||||
if v == 0 {
|
||||
return nil, nil
|
||||
}
|
||||
ifi, err := net.InterfaceByIndex(int(v))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return ifi, nil
|
||||
}
|
||||
|
||||
func setIPv6MulticastInterface(fd int, ifi *net.Interface) error {
|
||||
var v int32
|
||||
if ifi != nil {
|
||||
v = int32(ifi.Index)
|
||||
}
|
||||
return os.NewSyscallError("setsockopt", setsockopt(fd, ianaProtocolIPv6, sysSockoptMulticastInterface, uintptr(unsafe.Pointer(&v)), 4))
|
||||
}
|
||||
|
||||
func ipv6MulticastLoopback(fd int) (bool, error) {
|
||||
var v int32
|
||||
l := sysSockoptLen(4)
|
||||
if err := getsockopt(fd, ianaProtocolIPv6, sysSockoptMulticastLoopback, uintptr(unsafe.Pointer(&v)), &l); err != nil {
|
||||
return false, os.NewSyscallError("getsockopt", err)
|
||||
}
|
||||
return v == 1, nil
|
||||
}
|
||||
|
||||
func setIPv6MulticastLoopback(fd int, v bool) error {
|
||||
vv := int32(boolint(v))
|
||||
return os.NewSyscallError("setsockopt", setsockopt(fd, ianaProtocolIPv6, sysSockoptMulticastLoopback, uintptr(unsafe.Pointer(&vv)), 4))
|
||||
}
|
||||
|
||||
func joinIPv6Group(fd int, ifi *net.Interface, grp net.IP) error {
|
||||
mreq := sysMulticastReq{}
|
||||
copy(mreq.IP[:], grp)
|
||||
if ifi != nil {
|
||||
mreq.IfIndex = uint32(ifi.Index)
|
||||
}
|
||||
return os.NewSyscallError("setsockopt", setsockopt(fd, ianaProtocolIPv6, sysSockoptJoinGroup, uintptr(unsafe.Pointer(&mreq)), sysSizeofMulticastReq))
|
||||
}
|
||||
|
||||
func leaveIPv6Group(fd int, ifi *net.Interface, grp net.IP) error {
|
||||
mreq := sysMulticastReq{}
|
||||
copy(mreq.IP[:], grp)
|
||||
if ifi != nil {
|
||||
mreq.IfIndex = uint32(ifi.Index)
|
||||
}
|
||||
return os.NewSyscallError("setsockopt", setsockopt(fd, ianaProtocolIPv6, sysSockoptLeaveGroup, uintptr(unsafe.Pointer(&mreq)), sysSizeofMulticastReq))
|
||||
}
|
||||
116
Godeps/_workspace/src/code.google.com/p/go.net/ipv6/sockopt_rfc3493_windows.go
generated
vendored
116
Godeps/_workspace/src/code.google.com/p/go.net/ipv6/sockopt_rfc3493_windows.go
generated
vendored
@@ -1,116 +0,0 @@
|
||||
// Copyright 2013 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package ipv6
|
||||
|
||||
import (
|
||||
"net"
|
||||
"os"
|
||||
"syscall"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
func ipv6TrafficClass(fd syscall.Handle) (int, error) {
|
||||
// TODO(mikio): Implement this
|
||||
return 0, syscall.EWINDOWS
|
||||
}
|
||||
|
||||
func setIPv6TrafficClass(fd syscall.Handle, v int) error {
|
||||
// TODO(mikio): Implement this
|
||||
return syscall.EWINDOWS
|
||||
}
|
||||
|
||||
func ipv6HopLimit(fd syscall.Handle) (int, error) {
|
||||
var v int32
|
||||
l := int32(4)
|
||||
if err := syscall.Getsockopt(fd, ianaProtocolIPv6, sysSockoptUnicastHopLimit, (*byte)(unsafe.Pointer(&v)), &l); err != nil {
|
||||
return 0, os.NewSyscallError("getsockopt", err)
|
||||
}
|
||||
return int(v), nil
|
||||
}
|
||||
|
||||
func setIPv6HopLimit(fd syscall.Handle, v int) error {
|
||||
vv := int32(v)
|
||||
return os.NewSyscallError("setsockopt", syscall.Setsockopt(fd, ianaProtocolIPv6, sysSockoptUnicastHopLimit, (*byte)(unsafe.Pointer(&vv)), 4))
|
||||
}
|
||||
|
||||
func ipv6Checksum(fd syscall.Handle) (bool, int, error) {
|
||||
// TODO(mikio): Implement this
|
||||
return false, 0, syscall.EWINDOWS
|
||||
}
|
||||
|
||||
func ipv6MulticastHopLimit(fd syscall.Handle) (int, error) {
|
||||
var v int32
|
||||
l := int32(4)
|
||||
if err := syscall.Getsockopt(fd, ianaProtocolIPv6, sysSockoptMulticastHopLimit, (*byte)(unsafe.Pointer(&v)), &l); err != nil {
|
||||
return 0, os.NewSyscallError("getsockopt", err)
|
||||
}
|
||||
return int(v), nil
|
||||
}
|
||||
|
||||
func setIPv6MulticastHopLimit(fd syscall.Handle, v int) error {
|
||||
vv := int32(v)
|
||||
return os.NewSyscallError("setsockopt", syscall.Setsockopt(fd, ianaProtocolIPv6, sysSockoptMulticastHopLimit, (*byte)(unsafe.Pointer(&vv)), 4))
|
||||
}
|
||||
|
||||
func ipv6MulticastInterface(fd syscall.Handle) (*net.Interface, error) {
|
||||
var v int32
|
||||
l := int32(4)
|
||||
if err := syscall.Getsockopt(fd, ianaProtocolIPv6, sysSockoptMulticastInterface, (*byte)(unsafe.Pointer(&v)), &l); err != nil {
|
||||
return nil, os.NewSyscallError("getsockopt", err)
|
||||
}
|
||||
if v == 0 {
|
||||
return nil, nil
|
||||
}
|
||||
ifi, err := net.InterfaceByIndex(int(v))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return ifi, nil
|
||||
}
|
||||
|
||||
func setIPv6MulticastInterface(fd syscall.Handle, ifi *net.Interface) error {
|
||||
var v int32
|
||||
if ifi != nil {
|
||||
v = int32(ifi.Index)
|
||||
}
|
||||
return os.NewSyscallError("setsockopt", syscall.Setsockopt(fd, ianaProtocolIPv6, sysSockoptMulticastInterface, (*byte)(unsafe.Pointer(&v)), 4))
|
||||
}
|
||||
|
||||
func ipv6MulticastLoopback(fd syscall.Handle) (bool, error) {
|
||||
var v int32
|
||||
l := int32(4)
|
||||
if err := syscall.Getsockopt(fd, ianaProtocolIPv6, sysSockoptMulticastLoopback, (*byte)(unsafe.Pointer(&v)), &l); err != nil {
|
||||
return false, os.NewSyscallError("getsockopt", err)
|
||||
}
|
||||
return v == 1, nil
|
||||
}
|
||||
|
||||
func setIPv6MulticastLoopback(fd syscall.Handle, v bool) error {
|
||||
vv := int32(boolint(v))
|
||||
return os.NewSyscallError("setsockopt", syscall.Setsockopt(fd, ianaProtocolIPv6, sysSockoptMulticastLoopback, (*byte)(unsafe.Pointer(&vv)), 4))
|
||||
}
|
||||
|
||||
func joinIPv6Group(fd syscall.Handle, ifi *net.Interface, grp net.IP) error {
|
||||
mreq := sysMulticastReq{}
|
||||
copy(mreq.IP[:], grp)
|
||||
if ifi != nil {
|
||||
mreq.IfIndex = uint32(ifi.Index)
|
||||
}
|
||||
return os.NewSyscallError("setsockopt", syscall.Setsockopt(fd, ianaProtocolIPv6, sysSockoptJoinGroup, (*byte)(unsafe.Pointer(&mreq)), int32(sysSizeofMulticastReq)))
|
||||
}
|
||||
|
||||
func leaveIPv6Group(fd syscall.Handle, ifi *net.Interface, grp net.IP) error {
|
||||
mreq := sysMulticastReq{}
|
||||
copy(mreq.IP[:], grp)
|
||||
if ifi != nil {
|
||||
mreq.IfIndex = uint32(ifi.Index)
|
||||
}
|
||||
return os.NewSyscallError("setsockopt", syscall.Setsockopt(fd, ianaProtocolIPv6, sysSockoptLeaveGroup, (*byte)(unsafe.Pointer(&mreq)), int32(sysSizeofMulticastReq)))
|
||||
}
|
||||
|
||||
func setIPv6Checksum(fd syscall.Handle, on bool, offset int) error {
|
||||
// TODO(mikio): Implement this
|
||||
return syscall.EWINDOWS
|
||||
}
|
||||
12
Godeps/_workspace/src/code.google.com/p/go.net/ipv6/sockopt_rfc3542_stub.go
generated
vendored
12
Godeps/_workspace/src/code.google.com/p/go.net/ipv6/sockopt_rfc3542_stub.go
generated
vendored
@@ -1,12 +0,0 @@
|
||||
// Copyright 2013 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build dragonfly plan9 solaris
|
||||
|
||||
package ipv6
|
||||
|
||||
func ipv6PathMTU(fd int) (int, error) {
|
||||
// TODO(mikio): Implement this
|
||||
return 0, errOpNoSupport
|
||||
}
|
||||
90
Godeps/_workspace/src/code.google.com/p/go.net/ipv6/sockopt_rfc3542_unix.go
generated
vendored
90
Godeps/_workspace/src/code.google.com/p/go.net/ipv6/sockopt_rfc3542_unix.go
generated
vendored
@@ -1,90 +0,0 @@
|
||||
// Copyright 2013 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build freebsd linux netbsd openbsd
|
||||
|
||||
package ipv6
|
||||
|
||||
import (
|
||||
"os"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
func ipv6ReceiveTrafficClass(fd int) (bool, error) {
|
||||
var v int32
|
||||
l := sysSockoptLen(4)
|
||||
if err := getsockopt(fd, ianaProtocolIPv6, sysSockoptReceiveTrafficClass, uintptr(unsafe.Pointer(&v)), &l); err != nil {
|
||||
return false, os.NewSyscallError("getsockopt", err)
|
||||
}
|
||||
return v == 1, nil
|
||||
}
|
||||
|
||||
func setIPv6ReceiveTrafficClass(fd int, v bool) error {
|
||||
vv := int32(boolint(v))
|
||||
return os.NewSyscallError("setsockopt", setsockopt(fd, ianaProtocolIPv6, sysSockoptReceiveTrafficClass, uintptr(unsafe.Pointer(&vv)), 4))
|
||||
}
|
||||
|
||||
func ipv6ReceiveHopLimit(fd int) (bool, error) {
|
||||
var v int32
|
||||
l := sysSockoptLen(4)
|
||||
if err := getsockopt(fd, ianaProtocolIPv6, sysSockoptReceiveHopLimit, uintptr(unsafe.Pointer(&v)), &l); err != nil {
|
||||
return false, os.NewSyscallError("getsockopt", err)
|
||||
}
|
||||
return v == 1, nil
|
||||
}
|
||||
|
||||
func setIPv6ReceiveHopLimit(fd int, v bool) error {
|
||||
vv := int32(boolint(v))
|
||||
return os.NewSyscallError("setsockopt", setsockopt(fd, ianaProtocolIPv6, sysSockoptReceiveHopLimit, uintptr(unsafe.Pointer(&vv)), 4))
|
||||
}
|
||||
|
||||
func ipv6ReceivePacketInfo(fd int) (bool, error) {
|
||||
var v int32
|
||||
l := sysSockoptLen(4)
|
||||
if err := getsockopt(fd, ianaProtocolIPv6, sysSockoptReceivePacketInfo, uintptr(unsafe.Pointer(&v)), &l); err != nil {
|
||||
return false, os.NewSyscallError("getsockopt", err)
|
||||
}
|
||||
return v == 1, nil
|
||||
}
|
||||
|
||||
func setIPv6ReceivePacketInfo(fd int, v bool) error {
|
||||
vv := int32(boolint(v))
|
||||
return os.NewSyscallError("setsockopt", setsockopt(fd, ianaProtocolIPv6, sysSockoptReceivePacketInfo, uintptr(unsafe.Pointer(&vv)), 4))
|
||||
}
|
||||
|
||||
func ipv6PathMTU(fd int) (int, error) {
|
||||
var v sysMTUInfo
|
||||
l := sysSockoptLen(sysSizeofMTUInfo)
|
||||
if err := getsockopt(fd, ianaProtocolIPv6, sysSockoptPathMTU, uintptr(unsafe.Pointer(&v)), &l); err != nil {
|
||||
return 0, os.NewSyscallError("getsockopt", err)
|
||||
}
|
||||
return int(v.MTU), nil
|
||||
}
|
||||
|
||||
func ipv6ReceivePathMTU(fd int) (bool, error) {
|
||||
var v int32
|
||||
l := sysSockoptLen(4)
|
||||
if err := getsockopt(fd, ianaProtocolIPv6, sysSockoptReceivePathMTU, uintptr(unsafe.Pointer(&v)), &l); err != nil {
|
||||
return false, os.NewSyscallError("getsockopt", err)
|
||||
}
|
||||
return v == 1, nil
|
||||
}
|
||||
|
||||
func setIPv6ReceivePathMTU(fd int, v bool) error {
|
||||
vv := int32(boolint(v))
|
||||
return os.NewSyscallError("setsockopt", setsockopt(fd, ianaProtocolIPv6, sysSockoptReceivePathMTU, uintptr(unsafe.Pointer(&vv)), 4))
|
||||
}
|
||||
|
||||
func ipv6ICMPFilter(fd int) (*ICMPFilter, error) {
|
||||
var v ICMPFilter
|
||||
l := sysSockoptLen(sysSizeofICMPFilter)
|
||||
if err := getsockopt(fd, ianaProtocolIPv6ICMP, sysSockoptICMPFilter, uintptr(unsafe.Pointer(&v.sysICMPFilter)), &l); err != nil {
|
||||
return nil, os.NewSyscallError("getsockopt", err)
|
||||
}
|
||||
return &v, nil
|
||||
}
|
||||
|
||||
func setIPv6ICMPFilter(fd int, f *ICMPFilter) error {
|
||||
return os.NewSyscallError("setsockopt", setsockopt(fd, ianaProtocolIPv6ICMP, sysSockoptICMPFilter, uintptr(unsafe.Pointer(&f.sysICMPFilter)), sysSizeofICMPFilter))
|
||||
}
|
||||
62
Godeps/_workspace/src/code.google.com/p/go.net/ipv6/sockopt_rfc3542_windows.go
generated
vendored
62
Godeps/_workspace/src/code.google.com/p/go.net/ipv6/sockopt_rfc3542_windows.go
generated
vendored
@@ -1,62 +0,0 @@
|
||||
// Copyright 2013 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package ipv6
|
||||
|
||||
import "syscall"
|
||||
|
||||
func ipv6ReceiveTrafficClass(fd syscall.Handle) (bool, error) {
|
||||
// TODO(mikio): Implement this
|
||||
return false, syscall.EWINDOWS
|
||||
}
|
||||
|
||||
func setIPv6ReceiveTrafficClass(fd syscall.Handle, v bool) error {
|
||||
// TODO(mikio): Implement this
|
||||
return syscall.EWINDOWS
|
||||
}
|
||||
|
||||
func ipv6ReceiveHopLimit(fd syscall.Handle) (bool, error) {
|
||||
// TODO(mikio): Implement this
|
||||
return false, syscall.EWINDOWS
|
||||
}
|
||||
|
||||
func setIPv6ReceiveHopLimit(fd syscall.Handle, v bool) error {
|
||||
// TODO(mikio): Implement this
|
||||
return syscall.EWINDOWS
|
||||
}
|
||||
|
||||
func ipv6ReceivePacketInfo(fd syscall.Handle) (bool, error) {
|
||||
// TODO(mikio): Implement this
|
||||
return false, syscall.EWINDOWS
|
||||
}
|
||||
|
||||
func setIPv6ReceivePacketInfo(fd syscall.Handle, v bool) error {
|
||||
// TODO(mikio): Implement this
|
||||
return syscall.EWINDOWS
|
||||
}
|
||||
|
||||
func ipv6PathMTU(fd syscall.Handle) (int, error) {
|
||||
// TODO(mikio): Implement this
|
||||
return 0, syscall.EWINDOWS
|
||||
}
|
||||
|
||||
func ipv6ReceivePathMTU(fd syscall.Handle) (bool, error) {
|
||||
// TODO(mikio): Implement this
|
||||
return false, syscall.EWINDOWS
|
||||
}
|
||||
|
||||
func setIPv6ReceivePathMTU(fd syscall.Handle, v bool) error {
|
||||
// TODO(mikio): Implement this
|
||||
return syscall.EWINDOWS
|
||||
}
|
||||
|
||||
func ipv6ICMPFilter(fd syscall.Handle) (*ICMPFilter, error) {
|
||||
// TODO(mikio): Implement this
|
||||
return nil, syscall.EWINDOWS
|
||||
}
|
||||
|
||||
func setIPv6ICMPFilter(fd syscall.Handle, f *ICMPFilter) error {
|
||||
// TODO(mikio): Implement this
|
||||
return syscall.EWINDOWS
|
||||
}
|
||||
136
Godeps/_workspace/src/code.google.com/p/go.net/ipv6/sockopt_test.go
generated
vendored
136
Godeps/_workspace/src/code.google.com/p/go.net/ipv6/sockopt_test.go
generated
vendored
@@ -1,136 +0,0 @@
|
||||
// Copyright 2013 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package ipv6_test
|
||||
|
||||
import (
|
||||
"code.google.com/p/go.net/ipv6"
|
||||
"net"
|
||||
"os"
|
||||
"runtime"
|
||||
"testing"
|
||||
)
|
||||
|
||||
var supportsIPv6 bool
|
||||
|
||||
func init() {
|
||||
if ln, err := net.Listen("tcp6", "[::1]:0"); err == nil {
|
||||
ln.Close()
|
||||
supportsIPv6 = true
|
||||
}
|
||||
}
|
||||
|
||||
var condFatalf = func() func(*testing.T, string, ...interface{}) {
|
||||
// A few APIs are not implemented yet on some platforms.
|
||||
switch runtime.GOOS {
|
||||
case "darwin", "dragonfly", "plan9", "solaris", "windows":
|
||||
return (*testing.T).Logf
|
||||
}
|
||||
return (*testing.T).Fatalf
|
||||
}()
|
||||
|
||||
func TestConnInitiatorPathMTU(t *testing.T) {
|
||||
switch runtime.GOOS {
|
||||
case "dragonfly", "plan9", "solaris", "windows":
|
||||
t.Skipf("not supported on %q", runtime.GOOS)
|
||||
}
|
||||
if !supportsIPv6 {
|
||||
t.Skip("ipv6 is not supported")
|
||||
}
|
||||
|
||||
ln, err := net.Listen("tcp6", "[::1]:0")
|
||||
if err != nil {
|
||||
t.Fatalf("net.Listen failed: %v", err)
|
||||
}
|
||||
defer ln.Close()
|
||||
|
||||
done := make(chan bool)
|
||||
go acceptor(t, ln, done)
|
||||
|
||||
c, err := net.Dial("tcp6", ln.Addr().String())
|
||||
if err != nil {
|
||||
t.Fatalf("net.Dial failed: %v", err)
|
||||
}
|
||||
defer c.Close()
|
||||
|
||||
if pmtu, err := ipv6.NewConn(c).PathMTU(); err != nil {
|
||||
condFatalf(t, "ipv6.Conn.PathMTU failed: %v", err)
|
||||
} else {
|
||||
t.Logf("path mtu for %v: %v", c.RemoteAddr(), pmtu)
|
||||
}
|
||||
|
||||
<-done
|
||||
}
|
||||
|
||||
func TestConnResponderPathMTU(t *testing.T) {
|
||||
switch runtime.GOOS {
|
||||
case "dragonfly", "plan9", "solaris", "windows":
|
||||
t.Skipf("not supported on %q", runtime.GOOS)
|
||||
}
|
||||
if !supportsIPv6 {
|
||||
t.Skip("ipv6 is not supported")
|
||||
}
|
||||
|
||||
ln, err := net.Listen("tcp6", "[::1]:0")
|
||||
if err != nil {
|
||||
t.Fatalf("net.Listen failed: %v", err)
|
||||
}
|
||||
defer ln.Close()
|
||||
|
||||
done := make(chan bool)
|
||||
go connector(t, "tcp6", ln.Addr().String(), done)
|
||||
|
||||
c, err := ln.Accept()
|
||||
if err != nil {
|
||||
t.Fatalf("net.Accept failed: %v", err)
|
||||
}
|
||||
defer c.Close()
|
||||
|
||||
if pmtu, err := ipv6.NewConn(c).PathMTU(); err != nil {
|
||||
condFatalf(t, "ipv6.Conn.PathMTU failed: %v", err)
|
||||
} else {
|
||||
t.Logf("path mtu for %v: %v", c.RemoteAddr(), pmtu)
|
||||
}
|
||||
|
||||
<-done
|
||||
}
|
||||
|
||||
func TestPacketConnChecksum(t *testing.T) {
|
||||
switch runtime.GOOS {
|
||||
case "dragonfly", "plan9", "solaris", "windows":
|
||||
t.Skipf("not supported on %q", runtime.GOOS)
|
||||
}
|
||||
if !supportsIPv6 {
|
||||
t.Skip("ipv6 is not supported")
|
||||
}
|
||||
if os.Getuid() != 0 {
|
||||
t.Skip("must be root")
|
||||
}
|
||||
|
||||
c, err := net.ListenPacket("ip6:89", "::") // OSPF for IPv6
|
||||
if err != nil {
|
||||
t.Fatalf("net.ListenPacket failed: %v", err)
|
||||
}
|
||||
defer c.Close()
|
||||
|
||||
p := ipv6.NewPacketConn(c)
|
||||
offset := 12 // see RFC 5340
|
||||
|
||||
for _, toggle := range []bool{false, true} {
|
||||
if err := p.SetChecksum(toggle, offset); err != nil {
|
||||
if toggle {
|
||||
t.Fatalf("ipv6.PacketConn.SetChecksum(%v, %v) failed: %v", toggle, offset, err)
|
||||
} else {
|
||||
// Some platforms never allow to disable the kernel
|
||||
// checksum processing.
|
||||
t.Logf("ipv6.PacketConn.SetChecksum(%v, %v) failed: %v", toggle, offset, err)
|
||||
}
|
||||
}
|
||||
if on, offset, err := p.Checksum(); err != nil {
|
||||
t.Fatalf("ipv6.PacketConn.Checksum failed: %v", err)
|
||||
} else {
|
||||
t.Logf("kernel checksum processing enabled=%v, offset=%v", on, offset)
|
||||
}
|
||||
}
|
||||
}
|
||||
23
Godeps/_workspace/src/code.google.com/p/go.net/ipv6/sys.go
generated
vendored
23
Godeps/_workspace/src/code.google.com/p/go.net/ipv6/sys.go
generated
vendored
@@ -1,23 +0,0 @@
|
||||
// Copyright 2013 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package ipv6
|
||||
|
||||
type sysSockoptLen uint32
|
||||
|
||||
const (
|
||||
sysSizeofPacketInfo = 0x14
|
||||
sysSizeofMulticastReq = 0x14
|
||||
sysSizeofICMPFilter = 0x20
|
||||
)
|
||||
|
||||
type sysPacketInfo struct {
|
||||
IP [16]byte
|
||||
IfIndex uint32
|
||||
}
|
||||
|
||||
type sysMulticastReq struct {
|
||||
IP [16]byte
|
||||
IfIndex uint32
|
||||
}
|
||||
48
Godeps/_workspace/src/code.google.com/p/go.net/ipv6/sys_bsd.go
generated
vendored
48
Godeps/_workspace/src/code.google.com/p/go.net/ipv6/sys_bsd.go
generated
vendored
@@ -1,48 +0,0 @@
|
||||
// Copyright 2013 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build freebsd netbsd openbsd
|
||||
|
||||
package ipv6
|
||||
|
||||
import (
|
||||
"net"
|
||||
"syscall"
|
||||
)
|
||||
|
||||
// RFC 3493 options
|
||||
const (
|
||||
// See /usr/include/netinet6/in6.h.
|
||||
sysSockoptUnicastHopLimit = 0x4
|
||||
sysSockoptMulticastHopLimit = 0xa
|
||||
sysSockoptMulticastInterface = 0x9
|
||||
sysSockoptMulticastLoopback = 0xb
|
||||
sysSockoptJoinGroup = 0xc
|
||||
sysSockoptLeaveGroup = 0xd
|
||||
)
|
||||
|
||||
// RFC 3542 options
|
||||
const (
|
||||
// See /usr/include/netinet6/in6.h.
|
||||
sysSockoptReceiveTrafficClass = 0x39
|
||||
sysSockoptTrafficClass = 0x3d
|
||||
sysSockoptReceiveHopLimit = 0x25
|
||||
sysSockoptHopLimit = 0x2f
|
||||
sysSockoptReceivePacketInfo = 0x24
|
||||
sysSockoptPacketInfo = 0x2e
|
||||
sysSockoptReceivePathMTU = 0x2b
|
||||
sysSockoptPathMTU = 0x2c
|
||||
sysSockoptNextHop = 0x30
|
||||
sysSockoptChecksum = 0x1a
|
||||
|
||||
// See /usr/include/netinet6/in6.h.
|
||||
sysSockoptICMPFilter = 0x12
|
||||
)
|
||||
|
||||
func setSockaddr(sa *syscall.RawSockaddrInet6, ip net.IP, ifindex int) {
|
||||
sa.Len = syscall.SizeofSockaddrInet6
|
||||
sa.Family = syscall.AF_INET6
|
||||
copy(sa.Addr[:], ip)
|
||||
sa.Scope_id = uint32(ifindex)
|
||||
}
|
||||
54
Godeps/_workspace/src/code.google.com/p/go.net/ipv6/sys_darwin.go
generated
vendored
54
Godeps/_workspace/src/code.google.com/p/go.net/ipv6/sys_darwin.go
generated
vendored
@@ -1,54 +0,0 @@
|
||||
// Copyright 2013 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package ipv6
|
||||
|
||||
import (
|
||||
"net"
|
||||
"syscall"
|
||||
)
|
||||
|
||||
// RFC 2292 options
|
||||
const (
|
||||
// See /usr/include/netinet6/in6.h.
|
||||
sysSockopt2292HopLimit = 0x14
|
||||
sysSockopt2292PacketInfo = 0x13
|
||||
sysSockopt2292NextHop = 0x15
|
||||
)
|
||||
|
||||
// RFC 3493 options
|
||||
const (
|
||||
// See /usr/include/netinet6/in6.h.
|
||||
sysSockoptUnicastHopLimit = 0x4
|
||||
sysSockoptMulticastHopLimit = 0xa
|
||||
sysSockoptMulticastInterface = 0x9
|
||||
sysSockoptMulticastLoopback = 0xb
|
||||
sysSockoptJoinGroup = 0xc
|
||||
sysSockoptLeaveGroup = 0xd
|
||||
)
|
||||
|
||||
// RFC 3542 options
|
||||
const (
|
||||
// See /usr/include/netinet6/in6.h.
|
||||
sysSockoptReceiveTrafficClass = 0x23
|
||||
sysSockoptTrafficClass = 0x24
|
||||
sysSockoptReceiveHopLimit = 0x25
|
||||
sysSockoptHopLimit = 0x2f
|
||||
sysSockoptReceivePacketInfo = 0x3d
|
||||
sysSockoptPacketInfo = 0x2e
|
||||
sysSockoptReceivePathMTU = 0x2b
|
||||
sysSockoptPathMTU = 0x2c
|
||||
sysSockoptNextHop = 0x30
|
||||
sysSockoptChecksum = 0x1a
|
||||
|
||||
// See /usr/include/netinet6/in6.h.
|
||||
sysSockoptICMPFilter = 0x12
|
||||
)
|
||||
|
||||
func setSockaddr(sa *syscall.RawSockaddrInet6, ip net.IP, ifindex int) {
|
||||
sa.Len = syscall.SizeofSockaddrInet6
|
||||
sa.Family = syscall.AF_INET6
|
||||
copy(sa.Addr[:], ip)
|
||||
sa.Scope_id = uint32(ifindex)
|
||||
}
|
||||
45
Godeps/_workspace/src/code.google.com/p/go.net/ipv6/sys_linux.go
generated
vendored
45
Godeps/_workspace/src/code.google.com/p/go.net/ipv6/sys_linux.go
generated
vendored
@@ -1,45 +0,0 @@
|
||||
// Copyright 2013 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package ipv6
|
||||
|
||||
import (
|
||||
"net"
|
||||
"syscall"
|
||||
)
|
||||
|
||||
// RFC 3493 options
|
||||
const (
|
||||
// See /usr/include/linux/in6.h.
|
||||
sysSockoptUnicastHopLimit = 0x10
|
||||
sysSockoptMulticastHopLimit = 0x12
|
||||
sysSockoptMulticastInterface = 0x11
|
||||
sysSockoptMulticastLoopback = 0x13
|
||||
sysSockoptJoinGroup = 0x14
|
||||
sysSockoptLeaveGroup = 0x15
|
||||
)
|
||||
|
||||
// RFC 3542 options
|
||||
const (
|
||||
// See /usr/include/linux/ipv6.h,in6.h.
|
||||
sysSockoptReceiveTrafficClass = 0x42
|
||||
sysSockoptTrafficClass = 0x43
|
||||
sysSockoptReceiveHopLimit = 0x33
|
||||
sysSockoptHopLimit = 0x34
|
||||
sysSockoptReceivePacketInfo = 0x31
|
||||
sysSockoptPacketInfo = 0x32
|
||||
sysSockoptReceivePathMTU = 0x3c
|
||||
sysSockoptPathMTU = 0x3d
|
||||
sysSockoptNextHop = 0x9
|
||||
sysSockoptChecksum = 0x7
|
||||
|
||||
// See /usr/include/linux/icmpv6.h.
|
||||
sysSockoptICMPFilter = 0x1
|
||||
)
|
||||
|
||||
func setSockaddr(sa *syscall.RawSockaddrInet6, ip net.IP, ifindex int) {
|
||||
sa.Family = syscall.AF_INET6
|
||||
copy(sa.Addr[:], ip)
|
||||
sa.Scope_id = uint32(ifindex)
|
||||
}
|
||||
16
Godeps/_workspace/src/code.google.com/p/go.net/ipv6/sys_unix.go
generated
vendored
16
Godeps/_workspace/src/code.google.com/p/go.net/ipv6/sys_unix.go
generated
vendored
@@ -1,16 +0,0 @@
|
||||
// Copyright 2013 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build darwin freebsd linux netbsd openbsd
|
||||
|
||||
package ipv6
|
||||
|
||||
import "syscall"
|
||||
|
||||
const sysSizeofMTUInfo = 0x20
|
||||
|
||||
type sysMTUInfo struct {
|
||||
Addr syscall.RawSockaddrInet6
|
||||
MTU uint32
|
||||
}
|
||||
33
Godeps/_workspace/src/code.google.com/p/go.net/ipv6/sys_windows.go
generated
vendored
33
Godeps/_workspace/src/code.google.com/p/go.net/ipv6/sys_windows.go
generated
vendored
@@ -1,33 +0,0 @@
|
||||
// Copyright 2013 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package ipv6
|
||||
|
||||
import (
|
||||
"net"
|
||||
"syscall"
|
||||
)
|
||||
|
||||
// RFC 3493 options
|
||||
const (
|
||||
// See ws2tcpip.h.
|
||||
sysSockoptUnicastHopLimit = 0x4
|
||||
sysSockoptMulticastHopLimit = 0xa
|
||||
sysSockoptMulticastInterface = 0x9
|
||||
sysSockoptMulticastLoopback = 0xb
|
||||
sysSockoptJoinGroup = 0xc
|
||||
sysSockoptLeaveGroup = 0xd
|
||||
)
|
||||
|
||||
// RFC 3542 options
|
||||
const (
|
||||
// See ws2tcpip.h.
|
||||
sysSockoptPacketInfo = 0x13
|
||||
)
|
||||
|
||||
func setSockaddr(sa *syscall.RawSockaddrInet6, ip net.IP, ifindex int) {
|
||||
sa.Family = syscall.AF_INET6
|
||||
copy(sa.Addr[:], ip)
|
||||
sa.Scope_id = uint32(ifindex)
|
||||
}
|
||||
42
Godeps/_workspace/src/code.google.com/p/go.net/ipv6/syscall_linux_386.go
generated
vendored
42
Godeps/_workspace/src/code.google.com/p/go.net/ipv6/syscall_linux_386.go
generated
vendored
@@ -1,42 +0,0 @@
|
||||
// Copyright 2009 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// This code is a duplicate of syscall/syscall_linux_386.go with small
|
||||
// modifications.
|
||||
|
||||
package ipv6
|
||||
|
||||
import (
|
||||
"syscall"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
// On x86 Linux, all the socket calls go through an extra indirection,
|
||||
// I think because the 5-register system call interface can't handle
|
||||
// the 6-argument calls like sendto and recvfrom. Instead the
|
||||
// arguments to the underlying system call are the number below and a
|
||||
// pointer to an array of uintptr. We hide the pointer in the
|
||||
// socketcall assembly to avoid allocation on every system call.
|
||||
|
||||
const (
|
||||
// See /usr/include/linux/net.h.
|
||||
_SETSOCKOPT = 14
|
||||
_GETSOCKOPT = 15
|
||||
)
|
||||
|
||||
var socketcall func(call int, a0, a1, a2, a3, a4, a5 uintptr) (int, syscall.Errno)
|
||||
|
||||
func getsockopt(fd int, level int, name int, v uintptr, l *sysSockoptLen) error {
|
||||
if _, errno := socketcall(_GETSOCKOPT, uintptr(fd), uintptr(level), uintptr(name), uintptr(v), uintptr(unsafe.Pointer(l)), 0); errno != 0 {
|
||||
return error(errno)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func setsockopt(fd int, level int, name int, v uintptr, l uintptr) error {
|
||||
if _, errno := socketcall(_SETSOCKOPT, uintptr(fd), uintptr(level), uintptr(name), v, l, 0); errno != 0 {
|
||||
return error(errno)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
56
Godeps/_workspace/src/code.google.com/p/go.net/ipv6/syscall_linux_386.s
generated
vendored
56
Godeps/_workspace/src/code.google.com/p/go.net/ipv6/syscall_linux_386.s
generated
vendored
@@ -1,56 +0,0 @@
|
||||
// Copyright 2009 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// This code is a duplicate of syscall/syscall_linux_386.s with small
|
||||
// modifications.
|
||||
|
||||
#define SYS_SOCKETCALL 102 // from zsysnum_linux_386.go
|
||||
|
||||
// func socketcallnosplit7(call int, a0, a1, a2, a3, a4, a5 uintptr) (n int, errno int)
|
||||
// Kernel interface gets call sub-number and pointer to a0 for Go 1.1.
|
||||
TEXT ·socketcallnosplit7(SB),7,$0
|
||||
CALL runtime·entersyscall(SB)
|
||||
MOVL $SYS_SOCKETCALL, AX // syscall entry
|
||||
MOVL 4(SP), BX // socket call number
|
||||
LEAL 8(SP), CX // pointer to call arguments
|
||||
MOVL $0, DX
|
||||
MOVL $0, SI
|
||||
MOVL $0, DI
|
||||
CALL *runtime·_vdso(SB)
|
||||
CMPL AX, $0xfffff001
|
||||
JLS ok1
|
||||
MOVL $-1, 32(SP) // n
|
||||
NEGL AX
|
||||
MOVL AX, 36(SP) // errno
|
||||
CALL runtime·exitsyscall(SB)
|
||||
RET
|
||||
ok1:
|
||||
MOVL AX, 32(SP) // n
|
||||
MOVL $0, 36(SP) // errno
|
||||
CALL runtime·exitsyscall(SB)
|
||||
RET
|
||||
|
||||
// func socketcallnosplit4(call int, a0, a1, a2, a3, a4, a5 uintptr) (n int, errno int)
|
||||
// Kernel interface gets call sub-number and pointer to a0 for Go 1.2.
|
||||
TEXT ·socketcallnosplit4(SB),4,$0-40
|
||||
CALL runtime·entersyscall(SB)
|
||||
MOVL $SYS_SOCKETCALL, AX // syscall entry
|
||||
MOVL 4(SP), BX // socket call number
|
||||
LEAL 8(SP), CX // pointer to call arguments
|
||||
MOVL $0, DX
|
||||
MOVL $0, SI
|
||||
MOVL $0, DI
|
||||
CALL *runtime·_vdso(SB)
|
||||
CMPL AX, $0xfffff001
|
||||
JLS ok2
|
||||
MOVL $-1, 32(SP) // n
|
||||
NEGL AX
|
||||
MOVL AX, 36(SP) // errno
|
||||
CALL runtime·exitsyscall(SB)
|
||||
RET
|
||||
ok2:
|
||||
MOVL AX, 32(SP) // n
|
||||
MOVL $0, 36(SP) // errno
|
||||
CALL runtime·exitsyscall(SB)
|
||||
RET
|
||||
15
Godeps/_workspace/src/code.google.com/p/go.net/ipv6/syscall_nosplit4_linux_386.go
generated
vendored
15
Godeps/_workspace/src/code.google.com/p/go.net/ipv6/syscall_nosplit4_linux_386.go
generated
vendored
@@ -1,15 +0,0 @@
|
||||
// Copyright 2013 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build go1.2
|
||||
|
||||
package ipv6
|
||||
|
||||
import "syscall"
|
||||
|
||||
func socketcallnosplit4(call int, a0, a1, a2, a3, a4, a5 uintptr) (int, syscall.Errno)
|
||||
|
||||
func init() {
|
||||
socketcall = socketcallnosplit4
|
||||
}
|
||||
15
Godeps/_workspace/src/code.google.com/p/go.net/ipv6/syscall_nosplit7_linux_386.go
generated
vendored
15
Godeps/_workspace/src/code.google.com/p/go.net/ipv6/syscall_nosplit7_linux_386.go
generated
vendored
@@ -1,15 +0,0 @@
|
||||
// Copyright 2013 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build go1.1,!go1.2
|
||||
|
||||
package ipv6
|
||||
|
||||
import "syscall"
|
||||
|
||||
func socketcallnosplit7(call int, a0, a1, a2, a3, a4, a5 uintptr) (int, syscall.Errno)
|
||||
|
||||
func init() {
|
||||
socketcall = socketcallnosplit7
|
||||
}
|
||||
26
Godeps/_workspace/src/code.google.com/p/go.net/ipv6/syscall_unix.go
generated
vendored
26
Godeps/_workspace/src/code.google.com/p/go.net/ipv6/syscall_unix.go
generated
vendored
@@ -1,26 +0,0 @@
|
||||
// Copyright 2013 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build darwin freebsd linux,amd64 linux,arm netbsd openbsd
|
||||
|
||||
package ipv6
|
||||
|
||||
import (
|
||||
"syscall"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
func getsockopt(fd int, level, name int, v uintptr, l *sysSockoptLen) error {
|
||||
if _, _, errno := syscall.Syscall6(syscall.SYS_GETSOCKOPT, uintptr(fd), uintptr(level), uintptr(name), uintptr(v), uintptr(unsafe.Pointer(l)), 0); errno != 0 {
|
||||
return error(errno)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func setsockopt(fd int, level int, name int, v uintptr, l uintptr) error {
|
||||
if _, _, errno := syscall.Syscall6(syscall.SYS_SETSOCKOPT, uintptr(fd), uintptr(level), uintptr(name), uintptr(v), uintptr(l), 0); errno != 0 {
|
||||
return error(errno)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
172
Godeps/_workspace/src/code.google.com/p/go.net/ipv6/unicast_test.go
generated
vendored
172
Godeps/_workspace/src/code.google.com/p/go.net/ipv6/unicast_test.go
generated
vendored
@@ -1,172 +0,0 @@
|
||||
// Copyright 2013 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package ipv6_test
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"code.google.com/p/go.net/ipv6"
|
||||
"net"
|
||||
"os"
|
||||
"runtime"
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
func TestPacketConnReadWriteUnicastUDP(t *testing.T) {
|
||||
switch runtime.GOOS {
|
||||
case "dragonfly", "plan9", "solaris", "windows":
|
||||
t.Skipf("not supported on %q", runtime.GOOS)
|
||||
}
|
||||
if !supportsIPv6 {
|
||||
t.Skip("ipv6 is not supported")
|
||||
}
|
||||
|
||||
c, err := net.ListenPacket("udp6", "[::1]:0")
|
||||
if err != nil {
|
||||
t.Fatalf("net.ListenPacket failed: %v", err)
|
||||
}
|
||||
defer c.Close()
|
||||
p := ipv6.NewPacketConn(c)
|
||||
defer p.Close()
|
||||
|
||||
dst, err := net.ResolveUDPAddr("udp6", c.LocalAddr().String())
|
||||
if err != nil {
|
||||
t.Fatalf("net.ResolveUDPAddr failed: %v", err)
|
||||
}
|
||||
|
||||
cm := ipv6.ControlMessage{
|
||||
TrafficClass: DiffServAF11 | CongestionExperienced,
|
||||
Src: net.IPv6loopback,
|
||||
Dst: net.IPv6loopback,
|
||||
}
|
||||
cf := ipv6.FlagTrafficClass | ipv6.FlagHopLimit | ipv6.FlagSrc | ipv6.FlagDst | ipv6.FlagInterface | ipv6.FlagPathMTU
|
||||
ifi := loopbackInterface()
|
||||
if ifi != nil {
|
||||
cm.IfIndex = ifi.Index
|
||||
}
|
||||
wb := []byte("HELLO-R-U-THERE")
|
||||
|
||||
for i, toggle := range []bool{true, false, true} {
|
||||
if err := p.SetControlMessage(cf, toggle); err != nil {
|
||||
t.Fatalf("ipv6.PacketConn.SetControlMessage failed: %v", err)
|
||||
}
|
||||
cm.HopLimit = i + 1
|
||||
if err := p.SetWriteDeadline(time.Now().Add(100 * time.Millisecond)); err != nil {
|
||||
t.Fatalf("ipv6.PacketConn.SetWriteDeadline failed: %v", err)
|
||||
}
|
||||
if n, err := p.WriteTo(wb, &cm, dst); err != nil {
|
||||
t.Fatalf("ipv6.PacketConn.WriteTo failed: %v", err)
|
||||
} else if n != len(wb) {
|
||||
t.Fatalf("ipv6.PacketConn.WriteTo failed: short write: %v", n)
|
||||
}
|
||||
rb := make([]byte, 128)
|
||||
if err := p.SetReadDeadline(time.Now().Add(100 * time.Millisecond)); err != nil {
|
||||
t.Fatalf("ipv6.PacketConn.SetReadDeadline failed: %v", err)
|
||||
}
|
||||
if n, cm, _, err := p.ReadFrom(rb); err != nil {
|
||||
t.Fatalf("ipv6.PacketConn.ReadFrom failed: %v", err)
|
||||
} else if !bytes.Equal(rb[:n], wb) {
|
||||
t.Fatalf("got %v; expected %v", rb[:n], wb)
|
||||
} else {
|
||||
t.Logf("rcvd cmsg: %v", cm)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestPacketConnReadWriteUnicastICMP(t *testing.T) {
|
||||
switch runtime.GOOS {
|
||||
case "dragonfly", "plan9", "solaris", "windows":
|
||||
t.Skipf("not supported on %q", runtime.GOOS)
|
||||
}
|
||||
if !supportsIPv6 {
|
||||
t.Skip("ipv6 is not supported")
|
||||
}
|
||||
if os.Getuid() != 0 {
|
||||
t.Skip("must be root")
|
||||
}
|
||||
|
||||
c, err := net.ListenPacket("ip6:ipv6-icmp", "::1")
|
||||
if err != nil {
|
||||
t.Fatalf("net.ListenPacket failed: %v", err)
|
||||
}
|
||||
defer c.Close()
|
||||
p := ipv6.NewPacketConn(c)
|
||||
defer p.Close()
|
||||
|
||||
dst, err := net.ResolveIPAddr("ip6", "::1")
|
||||
if err != nil {
|
||||
t.Fatalf("net.ResolveIPAddr failed: %v", err)
|
||||
}
|
||||
|
||||
pshicmp := ipv6PseudoHeader(c.LocalAddr().(*net.IPAddr).IP, dst.IP, ianaProtocolIPv6ICMP)
|
||||
cm := ipv6.ControlMessage{
|
||||
TrafficClass: DiffServAF11 | CongestionExperienced,
|
||||
Src: net.IPv6loopback,
|
||||
Dst: net.IPv6loopback,
|
||||
}
|
||||
cf := ipv6.FlagTrafficClass | ipv6.FlagHopLimit | ipv6.FlagSrc | ipv6.FlagDst | ipv6.FlagInterface | ipv6.FlagPathMTU
|
||||
ifi := loopbackInterface()
|
||||
if ifi != nil {
|
||||
cm.IfIndex = ifi.Index
|
||||
}
|
||||
|
||||
var f ipv6.ICMPFilter
|
||||
f.SetAll(true)
|
||||
f.Set(ipv6.ICMPTypeEchoReply, false)
|
||||
if err := p.SetICMPFilter(&f); err != nil {
|
||||
t.Fatalf("ipv6.PacketConn.SetICMPFilter failed: %v", err)
|
||||
}
|
||||
|
||||
var psh []byte
|
||||
for i, toggle := range []bool{true, false, true} {
|
||||
if toggle {
|
||||
psh = nil
|
||||
if err := p.SetChecksum(true, 2); err != nil {
|
||||
t.Fatalf("ipv6.PacketConn.SetChecksum failed: %v", err)
|
||||
}
|
||||
} else {
|
||||
psh = pshicmp
|
||||
// Some platforms never allow to disable the
|
||||
// kernel checksum processing.
|
||||
p.SetChecksum(false, -1)
|
||||
}
|
||||
wb, err := (&icmpMessage{
|
||||
Type: ipv6.ICMPTypeEchoRequest, Code: 0,
|
||||
Body: &icmpEcho{
|
||||
ID: os.Getpid() & 0xffff, Seq: i + 1,
|
||||
Data: []byte("HELLO-R-U-THERE"),
|
||||
},
|
||||
}).Marshal(psh)
|
||||
if err != nil {
|
||||
t.Fatalf("icmpMessage.Marshal failed: %v", err)
|
||||
}
|
||||
if err := p.SetControlMessage(cf, toggle); err != nil {
|
||||
t.Fatalf("ipv6.PacketConn.SetControlMessage failed: %v", err)
|
||||
}
|
||||
cm.HopLimit = i + 1
|
||||
if err := p.SetWriteDeadline(time.Now().Add(100 * time.Millisecond)); err != nil {
|
||||
t.Fatalf("ipv6.PacketConn.SetWriteDeadline failed: %v", err)
|
||||
}
|
||||
if n, err := p.WriteTo(wb, &cm, dst); err != nil {
|
||||
t.Fatalf("ipv6.PacketConn.WriteTo failed: %v", err)
|
||||
} else if n != len(wb) {
|
||||
t.Fatalf("ipv6.PacketConn.WriteTo failed: short write: %v", n)
|
||||
}
|
||||
rb := make([]byte, 128)
|
||||
if err := p.SetReadDeadline(time.Now().Add(100 * time.Millisecond)); err != nil {
|
||||
t.Fatalf("ipv6.PacketConn.SetReadDeadline failed: %v", err)
|
||||
}
|
||||
if n, cm, _, err := p.ReadFrom(rb); err != nil {
|
||||
t.Fatalf("ipv6.PacketConn.ReadFrom failed: %v", err)
|
||||
} else {
|
||||
t.Logf("rcvd cmsg: %v", cm)
|
||||
if m, err := parseICMPMessage(rb[:n]); err != nil {
|
||||
t.Fatalf("parseICMPMessage failed: %v", err)
|
||||
} else if m.Type != ipv6.ICMPTypeEchoReply || m.Code != 0 {
|
||||
t.Fatalf("got type=%v, code=%v; expected type=%v, code=%v", m.Type, m.Code, ipv6.ICMPTypeEchoReply, 0)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
101
Godeps/_workspace/src/code.google.com/p/go.net/ipv6/unicastsockopt_test.go
generated
vendored
101
Godeps/_workspace/src/code.google.com/p/go.net/ipv6/unicastsockopt_test.go
generated
vendored
@@ -1,101 +0,0 @@
|
||||
// Copyright 2013 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package ipv6_test
|
||||
|
||||
import (
|
||||
"code.google.com/p/go.net/ipv6"
|
||||
"net"
|
||||
"os"
|
||||
"runtime"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestConnUnicastSocketOptions(t *testing.T) {
|
||||
switch runtime.GOOS {
|
||||
case "dragonfly", "plan9", "solaris", "windows":
|
||||
t.Skipf("not supported on %q", runtime.GOOS)
|
||||
}
|
||||
if !supportsIPv6 {
|
||||
t.Skip("ipv6 is not supported")
|
||||
}
|
||||
|
||||
ln, err := net.Listen("tcp6", "[::1]:0")
|
||||
if err != nil {
|
||||
t.Fatalf("net.Listen failed: %v", err)
|
||||
}
|
||||
defer ln.Close()
|
||||
|
||||
done := make(chan bool)
|
||||
go acceptor(t, ln, done)
|
||||
|
||||
c, err := net.Dial("tcp6", ln.Addr().String())
|
||||
if err != nil {
|
||||
t.Fatalf("net.Dial failed: %v", err)
|
||||
}
|
||||
defer c.Close()
|
||||
|
||||
testUnicastSocketOptions(t, ipv6.NewConn(c))
|
||||
|
||||
<-done
|
||||
}
|
||||
|
||||
var packetConnUnicastSocketOptionTests = []struct {
|
||||
net, proto, addr string
|
||||
}{
|
||||
{"udp6", "", "[::1]:0"},
|
||||
{"ip6", ":ipv6-icmp", "::1"},
|
||||
}
|
||||
|
||||
func TestPacketConnUnicastSocketOptions(t *testing.T) {
|
||||
switch runtime.GOOS {
|
||||
case "dragonfly", "plan9", "solaris", "windows":
|
||||
t.Skipf("not supported on %q", runtime.GOOS)
|
||||
}
|
||||
if !supportsIPv6 {
|
||||
t.Skip("ipv6 is not supported")
|
||||
}
|
||||
|
||||
for _, tt := range packetConnUnicastSocketOptionTests {
|
||||
if tt.net == "ip6" && os.Getuid() != 0 {
|
||||
t.Skip("must be root")
|
||||
}
|
||||
c, err := net.ListenPacket(tt.net+tt.proto, tt.addr)
|
||||
if err != nil {
|
||||
t.Fatalf("net.ListenPacket(%q, %q) failed: %v", tt.net+tt.proto, tt.addr, err)
|
||||
}
|
||||
defer c.Close()
|
||||
|
||||
testUnicastSocketOptions(t, ipv6.NewPacketConn(c))
|
||||
}
|
||||
}
|
||||
|
||||
type testIPv6UnicastConn interface {
|
||||
TrafficClass() (int, error)
|
||||
SetTrafficClass(int) error
|
||||
HopLimit() (int, error)
|
||||
SetHopLimit(int) error
|
||||
}
|
||||
|
||||
func testUnicastSocketOptions(t *testing.T, c testIPv6UnicastConn) {
|
||||
tclass := DiffServCS0 | NotECNTransport
|
||||
if err := c.SetTrafficClass(tclass); err != nil {
|
||||
t.Fatalf("ipv6.Conn.SetTrafficClass failed: %v", err)
|
||||
}
|
||||
if v, err := c.TrafficClass(); err != nil {
|
||||
t.Fatalf("ipv6.Conn.TrafficClass failed: %v", err)
|
||||
} else if v != tclass {
|
||||
t.Fatalf("got unexpected traffic class %v; expected %v", v, tclass)
|
||||
}
|
||||
|
||||
hoplim := 255
|
||||
if err := c.SetHopLimit(hoplim); err != nil {
|
||||
t.Fatalf("ipv6.Conn.SetHopLimit failed: %v", err)
|
||||
}
|
||||
if v, err := c.HopLimit(); err != nil {
|
||||
t.Fatalf("ipv6.Conn.HopLimit failed: %v", err)
|
||||
} else if v != hoplim {
|
||||
t.Fatalf("got unexpected hop limit %v; expected %v", v, hoplim)
|
||||
}
|
||||
}
|
||||
124
Godeps/_workspace/src/code.google.com/p/snappy-go/snappy/decode.go
generated
vendored
Normal file
124
Godeps/_workspace/src/code.google.com/p/snappy-go/snappy/decode.go
generated
vendored
Normal file
@@ -0,0 +1,124 @@
|
||||
// Copyright 2011 The Snappy-Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package snappy
|
||||
|
||||
import (
|
||||
"encoding/binary"
|
||||
"errors"
|
||||
)
|
||||
|
||||
// ErrCorrupt reports that the input is invalid.
|
||||
var ErrCorrupt = errors.New("snappy: corrupt input")
|
||||
|
||||
// DecodedLen returns the length of the decoded block.
|
||||
func DecodedLen(src []byte) (int, error) {
|
||||
v, _, err := decodedLen(src)
|
||||
return v, err
|
||||
}
|
||||
|
||||
// decodedLen returns the length of the decoded block and the number of bytes
|
||||
// that the length header occupied.
|
||||
func decodedLen(src []byte) (blockLen, headerLen int, err error) {
|
||||
v, n := binary.Uvarint(src)
|
||||
if n == 0 {
|
||||
return 0, 0, ErrCorrupt
|
||||
}
|
||||
if uint64(int(v)) != v {
|
||||
return 0, 0, errors.New("snappy: decoded block is too large")
|
||||
}
|
||||
return int(v), n, nil
|
||||
}
|
||||
|
||||
// Decode returns the decoded form of src. The returned slice may be a sub-
|
||||
// slice of dst if dst was large enough to hold the entire decoded block.
|
||||
// Otherwise, a newly allocated slice will be returned.
|
||||
// It is valid to pass a nil dst.
|
||||
func Decode(dst, src []byte) ([]byte, error) {
|
||||
dLen, s, err := decodedLen(src)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if len(dst) < dLen {
|
||||
dst = make([]byte, dLen)
|
||||
}
|
||||
|
||||
var d, offset, length int
|
||||
for s < len(src) {
|
||||
switch src[s] & 0x03 {
|
||||
case tagLiteral:
|
||||
x := uint(src[s] >> 2)
|
||||
switch {
|
||||
case x < 60:
|
||||
s += 1
|
||||
case x == 60:
|
||||
s += 2
|
||||
if s > len(src) {
|
||||
return nil, ErrCorrupt
|
||||
}
|
||||
x = uint(src[s-1])
|
||||
case x == 61:
|
||||
s += 3
|
||||
if s > len(src) {
|
||||
return nil, ErrCorrupt
|
||||
}
|
||||
x = uint(src[s-2]) | uint(src[s-1])<<8
|
||||
case x == 62:
|
||||
s += 4
|
||||
if s > len(src) {
|
||||
return nil, ErrCorrupt
|
||||
}
|
||||
x = uint(src[s-3]) | uint(src[s-2])<<8 | uint(src[s-1])<<16
|
||||
case x == 63:
|
||||
s += 5
|
||||
if s > len(src) {
|
||||
return nil, ErrCorrupt
|
||||
}
|
||||
x = uint(src[s-4]) | uint(src[s-3])<<8 | uint(src[s-2])<<16 | uint(src[s-1])<<24
|
||||
}
|
||||
length = int(x + 1)
|
||||
if length <= 0 {
|
||||
return nil, errors.New("snappy: unsupported literal length")
|
||||
}
|
||||
if length > len(dst)-d || length > len(src)-s {
|
||||
return nil, ErrCorrupt
|
||||
}
|
||||
copy(dst[d:], src[s:s+length])
|
||||
d += length
|
||||
s += length
|
||||
continue
|
||||
|
||||
case tagCopy1:
|
||||
s += 2
|
||||
if s > len(src) {
|
||||
return nil, ErrCorrupt
|
||||
}
|
||||
length = 4 + int(src[s-2])>>2&0x7
|
||||
offset = int(src[s-2])&0xe0<<3 | int(src[s-1])
|
||||
|
||||
case tagCopy2:
|
||||
s += 3
|
||||
if s > len(src) {
|
||||
return nil, ErrCorrupt
|
||||
}
|
||||
length = 1 + int(src[s-3])>>2
|
||||
offset = int(src[s-2]) | int(src[s-1])<<8
|
||||
|
||||
case tagCopy4:
|
||||
return nil, errors.New("snappy: unsupported COPY_4 tag")
|
||||
}
|
||||
|
||||
end := d + length
|
||||
if offset > d || end > len(dst) {
|
||||
return nil, ErrCorrupt
|
||||
}
|
||||
for ; d < end; d++ {
|
||||
dst[d] = dst[d-offset]
|
||||
}
|
||||
}
|
||||
if d != dLen {
|
||||
return nil, ErrCorrupt
|
||||
}
|
||||
return dst[:d], nil
|
||||
}
|
||||
174
Godeps/_workspace/src/code.google.com/p/snappy-go/snappy/encode.go
generated
vendored
Normal file
174
Godeps/_workspace/src/code.google.com/p/snappy-go/snappy/encode.go
generated
vendored
Normal file
@@ -0,0 +1,174 @@
|
||||
// Copyright 2011 The Snappy-Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package snappy
|
||||
|
||||
import (
|
||||
"encoding/binary"
|
||||
)
|
||||
|
||||
// We limit how far copy back-references can go, the same as the C++ code.
|
||||
const maxOffset = 1 << 15
|
||||
|
||||
// emitLiteral writes a literal chunk and returns the number of bytes written.
|
||||
func emitLiteral(dst, lit []byte) int {
|
||||
i, n := 0, uint(len(lit)-1)
|
||||
switch {
|
||||
case n < 60:
|
||||
dst[0] = uint8(n)<<2 | tagLiteral
|
||||
i = 1
|
||||
case n < 1<<8:
|
||||
dst[0] = 60<<2 | tagLiteral
|
||||
dst[1] = uint8(n)
|
||||
i = 2
|
||||
case n < 1<<16:
|
||||
dst[0] = 61<<2 | tagLiteral
|
||||
dst[1] = uint8(n)
|
||||
dst[2] = uint8(n >> 8)
|
||||
i = 3
|
||||
case n < 1<<24:
|
||||
dst[0] = 62<<2 | tagLiteral
|
||||
dst[1] = uint8(n)
|
||||
dst[2] = uint8(n >> 8)
|
||||
dst[3] = uint8(n >> 16)
|
||||
i = 4
|
||||
case int64(n) < 1<<32:
|
||||
dst[0] = 63<<2 | tagLiteral
|
||||
dst[1] = uint8(n)
|
||||
dst[2] = uint8(n >> 8)
|
||||
dst[3] = uint8(n >> 16)
|
||||
dst[4] = uint8(n >> 24)
|
||||
i = 5
|
||||
default:
|
||||
panic("snappy: source buffer is too long")
|
||||
}
|
||||
if copy(dst[i:], lit) != len(lit) {
|
||||
panic("snappy: destination buffer is too short")
|
||||
}
|
||||
return i + len(lit)
|
||||
}
|
||||
|
||||
// emitCopy writes a copy chunk and returns the number of bytes written.
|
||||
func emitCopy(dst []byte, offset, length int) int {
|
||||
i := 0
|
||||
for length > 0 {
|
||||
x := length - 4
|
||||
if 0 <= x && x < 1<<3 && offset < 1<<11 {
|
||||
dst[i+0] = uint8(offset>>8)&0x07<<5 | uint8(x)<<2 | tagCopy1
|
||||
dst[i+1] = uint8(offset)
|
||||
i += 2
|
||||
break
|
||||
}
|
||||
|
||||
x = length
|
||||
if x > 1<<6 {
|
||||
x = 1 << 6
|
||||
}
|
||||
dst[i+0] = uint8(x-1)<<2 | tagCopy2
|
||||
dst[i+1] = uint8(offset)
|
||||
dst[i+2] = uint8(offset >> 8)
|
||||
i += 3
|
||||
length -= x
|
||||
}
|
||||
return i
|
||||
}
|
||||
|
||||
// Encode returns the encoded form of src. The returned slice may be a sub-
|
||||
// slice of dst if dst was large enough to hold the entire encoded block.
|
||||
// Otherwise, a newly allocated slice will be returned.
|
||||
// It is valid to pass a nil dst.
|
||||
func Encode(dst, src []byte) ([]byte, error) {
|
||||
if n := MaxEncodedLen(len(src)); len(dst) < n {
|
||||
dst = make([]byte, n)
|
||||
}
|
||||
|
||||
// The block starts with the varint-encoded length of the decompressed bytes.
|
||||
d := binary.PutUvarint(dst, uint64(len(src)))
|
||||
|
||||
// Return early if src is short.
|
||||
if len(src) <= 4 {
|
||||
if len(src) != 0 {
|
||||
d += emitLiteral(dst[d:], src)
|
||||
}
|
||||
return dst[:d], nil
|
||||
}
|
||||
|
||||
// Initialize the hash table. Its size ranges from 1<<8 to 1<<14 inclusive.
|
||||
const maxTableSize = 1 << 14
|
||||
shift, tableSize := uint(32-8), 1<<8
|
||||
for tableSize < maxTableSize && tableSize < len(src) {
|
||||
shift--
|
||||
tableSize *= 2
|
||||
}
|
||||
var table [maxTableSize]int
|
||||
|
||||
// Iterate over the source bytes.
|
||||
var (
|
||||
s int // The iterator position.
|
||||
t int // The last position with the same hash as s.
|
||||
lit int // The start position of any pending literal bytes.
|
||||
)
|
||||
for s+3 < len(src) {
|
||||
// Update the hash table.
|
||||
b0, b1, b2, b3 := src[s], src[s+1], src[s+2], src[s+3]
|
||||
h := uint32(b0) | uint32(b1)<<8 | uint32(b2)<<16 | uint32(b3)<<24
|
||||
p := &table[(h*0x1e35a7bd)>>shift]
|
||||
// We need to to store values in [-1, inf) in table. To save
|
||||
// some initialization time, (re)use the table's zero value
|
||||
// and shift the values against this zero: add 1 on writes,
|
||||
// subtract 1 on reads.
|
||||
t, *p = *p-1, s+1
|
||||
// If t is invalid or src[s:s+4] differs from src[t:t+4], accumulate a literal byte.
|
||||
if t < 0 || s-t >= maxOffset || b0 != src[t] || b1 != src[t+1] || b2 != src[t+2] || b3 != src[t+3] {
|
||||
s++
|
||||
continue
|
||||
}
|
||||
// Otherwise, we have a match. First, emit any pending literal bytes.
|
||||
if lit != s {
|
||||
d += emitLiteral(dst[d:], src[lit:s])
|
||||
}
|
||||
// Extend the match to be as long as possible.
|
||||
s0 := s
|
||||
s, t = s+4, t+4
|
||||
for s < len(src) && src[s] == src[t] {
|
||||
s++
|
||||
t++
|
||||
}
|
||||
// Emit the copied bytes.
|
||||
d += emitCopy(dst[d:], s-t, s-s0)
|
||||
lit = s
|
||||
}
|
||||
|
||||
// Emit any final pending literal bytes and return.
|
||||
if lit != len(src) {
|
||||
d += emitLiteral(dst[d:], src[lit:])
|
||||
}
|
||||
return dst[:d], nil
|
||||
}
|
||||
|
||||
// MaxEncodedLen returns the maximum length of a snappy block, given its
|
||||
// uncompressed length.
|
||||
func MaxEncodedLen(srcLen int) int {
|
||||
// Compressed data can be defined as:
|
||||
// compressed := item* literal*
|
||||
// item := literal* copy
|
||||
//
|
||||
// The trailing literal sequence has a space blowup of at most 62/60
|
||||
// since a literal of length 60 needs one tag byte + one extra byte
|
||||
// for length information.
|
||||
//
|
||||
// Item blowup is trickier to measure. Suppose the "copy" op copies
|
||||
// 4 bytes of data. Because of a special check in the encoding code,
|
||||
// we produce a 4-byte copy only if the offset is < 65536. Therefore
|
||||
// the copy op takes 3 bytes to encode, and this type of item leads
|
||||
// to at most the 62/60 blowup for representing literals.
|
||||
//
|
||||
// Suppose the "copy" op copies 5 bytes of data. If the offset is big
|
||||
// enough, it will take 5 bytes to encode the copy op. Therefore the
|
||||
// worst case here is a one-byte literal followed by a five-byte copy.
|
||||
// That is, 6 bytes of input turn into 7 bytes of "compressed" data.
|
||||
//
|
||||
// This last factor dominates the blowup, so the final estimate is:
|
||||
return 32 + srcLen + srcLen/6
|
||||
}
|
||||
38
Godeps/_workspace/src/code.google.com/p/snappy-go/snappy/snappy.go
generated
vendored
Normal file
38
Godeps/_workspace/src/code.google.com/p/snappy-go/snappy/snappy.go
generated
vendored
Normal file
@@ -0,0 +1,38 @@
|
||||
// Copyright 2011 The Snappy-Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// Package snappy implements the snappy block-based compression format.
|
||||
// It aims for very high speeds and reasonable compression.
|
||||
//
|
||||
// The C++ snappy implementation is at http://code.google.com/p/snappy/
|
||||
package snappy
|
||||
|
||||
/*
|
||||
Each encoded block begins with the varint-encoded length of the decoded data,
|
||||
followed by a sequence of chunks. Chunks begin and end on byte boundaries. The
|
||||
first byte of each chunk is broken into its 2 least and 6 most significant bits
|
||||
called l and m: l ranges in [0, 4) and m ranges in [0, 64). l is the chunk tag.
|
||||
Zero means a literal tag. All other values mean a copy tag.
|
||||
|
||||
For literal tags:
|
||||
- If m < 60, the next 1 + m bytes are literal bytes.
|
||||
- Otherwise, let n be the little-endian unsigned integer denoted by the next
|
||||
m - 59 bytes. The next 1 + n bytes after that are literal bytes.
|
||||
|
||||
For copy tags, length bytes are copied from offset bytes ago, in the style of
|
||||
Lempel-Ziv compression algorithms. In particular:
|
||||
- For l == 1, the offset ranges in [0, 1<<11) and the length in [4, 12).
|
||||
The length is 4 + the low 3 bits of m. The high 3 bits of m form bits 8-10
|
||||
of the offset. The next byte is bits 0-7 of the offset.
|
||||
- For l == 2, the offset ranges in [0, 1<<16) and the length in [1, 65).
|
||||
The length is 1 + m. The offset is the little-endian unsigned integer
|
||||
denoted by the next 2 bytes.
|
||||
- For l == 3, this tag is a legacy format that is no longer supported.
|
||||
*/
|
||||
const (
|
||||
tagLiteral = 0x00
|
||||
tagCopy1 = 0x01
|
||||
tagCopy2 = 0x02
|
||||
tagCopy4 = 0x03
|
||||
)
|
||||
261
Godeps/_workspace/src/code.google.com/p/snappy-go/snappy/snappy_test.go
generated
vendored
Normal file
261
Godeps/_workspace/src/code.google.com/p/snappy-go/snappy/snappy_test.go
generated
vendored
Normal file
@@ -0,0 +1,261 @@
|
||||
// Copyright 2011 The Snappy-Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package snappy
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"flag"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"math/rand"
|
||||
"net/http"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"testing"
|
||||
)
|
||||
|
||||
var download = flag.Bool("download", false, "If true, download any missing files before running benchmarks")
|
||||
|
||||
func roundtrip(b, ebuf, dbuf []byte) error {
|
||||
e, err := Encode(ebuf, b)
|
||||
if err != nil {
|
||||
return fmt.Errorf("encoding error: %v", err)
|
||||
}
|
||||
d, err := Decode(dbuf, e)
|
||||
if err != nil {
|
||||
return fmt.Errorf("decoding error: %v", err)
|
||||
}
|
||||
if !bytes.Equal(b, d) {
|
||||
return fmt.Errorf("roundtrip mismatch:\n\twant %v\n\tgot %v", b, d)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func TestEmpty(t *testing.T) {
|
||||
if err := roundtrip(nil, nil, nil); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestSmallCopy(t *testing.T) {
|
||||
for _, ebuf := range [][]byte{nil, make([]byte, 20), make([]byte, 64)} {
|
||||
for _, dbuf := range [][]byte{nil, make([]byte, 20), make([]byte, 64)} {
|
||||
for i := 0; i < 32; i++ {
|
||||
s := "aaaa" + strings.Repeat("b", i) + "aaaabbbb"
|
||||
if err := roundtrip([]byte(s), ebuf, dbuf); err != nil {
|
||||
t.Errorf("len(ebuf)=%d, len(dbuf)=%d, i=%d: %v", len(ebuf), len(dbuf), i, err)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestSmallRand(t *testing.T) {
|
||||
rand.Seed(27354294)
|
||||
for n := 1; n < 20000; n += 23 {
|
||||
b := make([]byte, n)
|
||||
for i, _ := range b {
|
||||
b[i] = uint8(rand.Uint32())
|
||||
}
|
||||
if err := roundtrip(b, nil, nil); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestSmallRegular(t *testing.T) {
|
||||
for n := 1; n < 20000; n += 23 {
|
||||
b := make([]byte, n)
|
||||
for i, _ := range b {
|
||||
b[i] = uint8(i%10 + 'a')
|
||||
}
|
||||
if err := roundtrip(b, nil, nil); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func benchDecode(b *testing.B, src []byte) {
|
||||
encoded, err := Encode(nil, src)
|
||||
if err != nil {
|
||||
b.Fatal(err)
|
||||
}
|
||||
// Bandwidth is in amount of uncompressed data.
|
||||
b.SetBytes(int64(len(src)))
|
||||
b.ResetTimer()
|
||||
for i := 0; i < b.N; i++ {
|
||||
Decode(src, encoded)
|
||||
}
|
||||
}
|
||||
|
||||
func benchEncode(b *testing.B, src []byte) {
|
||||
// Bandwidth is in amount of uncompressed data.
|
||||
b.SetBytes(int64(len(src)))
|
||||
dst := make([]byte, MaxEncodedLen(len(src)))
|
||||
b.ResetTimer()
|
||||
for i := 0; i < b.N; i++ {
|
||||
Encode(dst, src)
|
||||
}
|
||||
}
|
||||
|
||||
func readFile(b *testing.B, filename string) []byte {
|
||||
src, err := ioutil.ReadFile(filename)
|
||||
if err != nil {
|
||||
b.Fatalf("failed reading %s: %s", filename, err)
|
||||
}
|
||||
if len(src) == 0 {
|
||||
b.Fatalf("%s has zero length", filename)
|
||||
}
|
||||
return src
|
||||
}
|
||||
|
||||
// expand returns a slice of length n containing repeated copies of src.
|
||||
func expand(src []byte, n int) []byte {
|
||||
dst := make([]byte, n)
|
||||
for x := dst; len(x) > 0; {
|
||||
i := copy(x, src)
|
||||
x = x[i:]
|
||||
}
|
||||
return dst
|
||||
}
|
||||
|
||||
func benchWords(b *testing.B, n int, decode bool) {
|
||||
// Note: the file is OS-language dependent so the resulting values are not
|
||||
// directly comparable for non-US-English OS installations.
|
||||
data := expand(readFile(b, "/usr/share/dict/words"), n)
|
||||
if decode {
|
||||
benchDecode(b, data)
|
||||
} else {
|
||||
benchEncode(b, data)
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkWordsDecode1e3(b *testing.B) { benchWords(b, 1e3, true) }
|
||||
func BenchmarkWordsDecode1e4(b *testing.B) { benchWords(b, 1e4, true) }
|
||||
func BenchmarkWordsDecode1e5(b *testing.B) { benchWords(b, 1e5, true) }
|
||||
func BenchmarkWordsDecode1e6(b *testing.B) { benchWords(b, 1e6, true) }
|
||||
func BenchmarkWordsEncode1e3(b *testing.B) { benchWords(b, 1e3, false) }
|
||||
func BenchmarkWordsEncode1e4(b *testing.B) { benchWords(b, 1e4, false) }
|
||||
func BenchmarkWordsEncode1e5(b *testing.B) { benchWords(b, 1e5, false) }
|
||||
func BenchmarkWordsEncode1e6(b *testing.B) { benchWords(b, 1e6, false) }
|
||||
|
||||
// testFiles' values are copied directly from
|
||||
// https://code.google.com/p/snappy/source/browse/trunk/snappy_unittest.cc.
|
||||
// The label field is unused in snappy-go.
|
||||
var testFiles = []struct {
|
||||
label string
|
||||
filename string
|
||||
}{
|
||||
{"html", "html"},
|
||||
{"urls", "urls.10K"},
|
||||
{"jpg", "house.jpg"},
|
||||
{"pdf", "mapreduce-osdi-1.pdf"},
|
||||
{"html4", "html_x_4"},
|
||||
{"cp", "cp.html"},
|
||||
{"c", "fields.c"},
|
||||
{"lsp", "grammar.lsp"},
|
||||
{"xls", "kennedy.xls"},
|
||||
{"txt1", "alice29.txt"},
|
||||
{"txt2", "asyoulik.txt"},
|
||||
{"txt3", "lcet10.txt"},
|
||||
{"txt4", "plrabn12.txt"},
|
||||
{"bin", "ptt5"},
|
||||
{"sum", "sum"},
|
||||
{"man", "xargs.1"},
|
||||
{"pb", "geo.protodata"},
|
||||
{"gaviota", "kppkn.gtb"},
|
||||
}
|
||||
|
||||
// The test data files are present at this canonical URL.
|
||||
const baseURL = "https://snappy.googlecode.com/svn/trunk/testdata/"
|
||||
|
||||
func downloadTestdata(basename string) (errRet error) {
|
||||
filename := filepath.Join("testdata", basename)
|
||||
f, err := os.Create(filename)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to create %s: %s", filename, err)
|
||||
}
|
||||
defer f.Close()
|
||||
defer func() {
|
||||
if errRet != nil {
|
||||
os.Remove(filename)
|
||||
}
|
||||
}()
|
||||
resp, err := http.Get(baseURL + basename)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to download %s: %s", baseURL+basename, err)
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
_, err = io.Copy(f, resp.Body)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to write %s: %s", filename, err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func benchFile(b *testing.B, n int, decode bool) {
|
||||
filename := filepath.Join("testdata", testFiles[n].filename)
|
||||
if stat, err := os.Stat(filename); err != nil || stat.Size() == 0 {
|
||||
if !*download {
|
||||
b.Fatal("test data not found; skipping benchmark without the -download flag")
|
||||
}
|
||||
// Download the official snappy C++ implementation reference test data
|
||||
// files for benchmarking.
|
||||
if err := os.Mkdir("testdata", 0777); err != nil && !os.IsExist(err) {
|
||||
b.Fatalf("failed to create testdata: %s", err)
|
||||
}
|
||||
for _, tf := range testFiles {
|
||||
if err := downloadTestdata(tf.filename); err != nil {
|
||||
b.Fatalf("failed to download testdata: %s", err)
|
||||
}
|
||||
}
|
||||
}
|
||||
data := readFile(b, filename)
|
||||
if decode {
|
||||
benchDecode(b, data)
|
||||
} else {
|
||||
benchEncode(b, data)
|
||||
}
|
||||
}
|
||||
|
||||
// Naming convention is kept similar to what snappy's C++ implementation uses.
|
||||
func Benchmark_UFlat0(b *testing.B) { benchFile(b, 0, true) }
|
||||
func Benchmark_UFlat1(b *testing.B) { benchFile(b, 1, true) }
|
||||
func Benchmark_UFlat2(b *testing.B) { benchFile(b, 2, true) }
|
||||
func Benchmark_UFlat3(b *testing.B) { benchFile(b, 3, true) }
|
||||
func Benchmark_UFlat4(b *testing.B) { benchFile(b, 4, true) }
|
||||
func Benchmark_UFlat5(b *testing.B) { benchFile(b, 5, true) }
|
||||
func Benchmark_UFlat6(b *testing.B) { benchFile(b, 6, true) }
|
||||
func Benchmark_UFlat7(b *testing.B) { benchFile(b, 7, true) }
|
||||
func Benchmark_UFlat8(b *testing.B) { benchFile(b, 8, true) }
|
||||
func Benchmark_UFlat9(b *testing.B) { benchFile(b, 9, true) }
|
||||
func Benchmark_UFlat10(b *testing.B) { benchFile(b, 10, true) }
|
||||
func Benchmark_UFlat11(b *testing.B) { benchFile(b, 11, true) }
|
||||
func Benchmark_UFlat12(b *testing.B) { benchFile(b, 12, true) }
|
||||
func Benchmark_UFlat13(b *testing.B) { benchFile(b, 13, true) }
|
||||
func Benchmark_UFlat14(b *testing.B) { benchFile(b, 14, true) }
|
||||
func Benchmark_UFlat15(b *testing.B) { benchFile(b, 15, true) }
|
||||
func Benchmark_UFlat16(b *testing.B) { benchFile(b, 16, true) }
|
||||
func Benchmark_UFlat17(b *testing.B) { benchFile(b, 17, true) }
|
||||
func Benchmark_ZFlat0(b *testing.B) { benchFile(b, 0, false) }
|
||||
func Benchmark_ZFlat1(b *testing.B) { benchFile(b, 1, false) }
|
||||
func Benchmark_ZFlat2(b *testing.B) { benchFile(b, 2, false) }
|
||||
func Benchmark_ZFlat3(b *testing.B) { benchFile(b, 3, false) }
|
||||
func Benchmark_ZFlat4(b *testing.B) { benchFile(b, 4, false) }
|
||||
func Benchmark_ZFlat5(b *testing.B) { benchFile(b, 5, false) }
|
||||
func Benchmark_ZFlat6(b *testing.B) { benchFile(b, 6, false) }
|
||||
func Benchmark_ZFlat7(b *testing.B) { benchFile(b, 7, false) }
|
||||
func Benchmark_ZFlat8(b *testing.B) { benchFile(b, 8, false) }
|
||||
func Benchmark_ZFlat9(b *testing.B) { benchFile(b, 9, false) }
|
||||
func Benchmark_ZFlat10(b *testing.B) { benchFile(b, 10, false) }
|
||||
func Benchmark_ZFlat11(b *testing.B) { benchFile(b, 11, false) }
|
||||
func Benchmark_ZFlat12(b *testing.B) { benchFile(b, 12, false) }
|
||||
func Benchmark_ZFlat13(b *testing.B) { benchFile(b, 13, false) }
|
||||
func Benchmark_ZFlat14(b *testing.B) { benchFile(b, 14, false) }
|
||||
func Benchmark_ZFlat15(b *testing.B) { benchFile(b, 15, false) }
|
||||
func Benchmark_ZFlat16(b *testing.B) { benchFile(b, 16, false) }
|
||||
func Benchmark_ZFlat17(b *testing.B) { benchFile(b, 17, false) }
|
||||
19
Godeps/_workspace/src/github.com/calmh/ini/LICENSE
generated
vendored
19
Godeps/_workspace/src/github.com/calmh/ini/LICENSE
generated
vendored
@@ -1,19 +0,0 @@
|
||||
Copyright (C) 2013 Jakob Borg
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
this software and associated documentation files (the "Software"), to deal in
|
||||
the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
of the Software, and to permit persons to whom the Software is furnished to do
|
||||
so, subject to the following conditions:
|
||||
|
||||
- The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
39
Godeps/_workspace/src/github.com/calmh/ini/README.md
generated
vendored
39
Godeps/_workspace/src/github.com/calmh/ini/README.md
generated
vendored
@@ -1,39 +0,0 @@
|
||||
ini [](https://drone.io/github.com/calmh/ini/latest)
|
||||
===
|
||||
|
||||
Yet another .INI file parser / writer. Created because the existing ones
|
||||
were either not general enough (allowing easy access to all parts of the
|
||||
original file) or made annoying assumptions about the format. And
|
||||
probably equal parts NIH. You might want to just write your own instead
|
||||
of using this one, you know that's where you'll end up in the end
|
||||
anyhow.
|
||||
|
||||
Documentation
|
||||
-------------
|
||||
|
||||
http://godoc.org/github.com/calmh/ini
|
||||
|
||||
Example
|
||||
-------
|
||||
|
||||
```go
|
||||
fd, _ := os.Open("foo.ini")
|
||||
cfg := ini.Parse(fd)
|
||||
fd.Close()
|
||||
|
||||
val := cfg.Get("general", "foo")
|
||||
cfg.Set("general", "bar", "baz")
|
||||
|
||||
fd, _ = os.Create("bar.ini")
|
||||
err := cfg.Write(fd)
|
||||
if err != nil {
|
||||
// ...
|
||||
}
|
||||
err = fd.Close()
|
||||
|
||||
```
|
||||
|
||||
License
|
||||
-------
|
||||
|
||||
MIT
|
||||
235
Godeps/_workspace/src/github.com/calmh/ini/ini.go
generated
vendored
235
Godeps/_workspace/src/github.com/calmh/ini/ini.go
generated
vendored
@@ -1,235 +0,0 @@
|
||||
// Package ini provides trivial parsing of .INI format files.
|
||||
package ini
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"fmt"
|
||||
"io"
|
||||
"regexp"
|
||||
"strconv"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// Config is a parsed INI format file.
|
||||
type Config struct {
|
||||
sections []section
|
||||
comments []string
|
||||
}
|
||||
|
||||
type section struct {
|
||||
name string
|
||||
comments []string
|
||||
options []option
|
||||
}
|
||||
|
||||
type option struct {
|
||||
name, value string
|
||||
}
|
||||
|
||||
var (
|
||||
iniSectionRe = regexp.MustCompile(`^\[(.+)\]$`)
|
||||
iniOptionRe = regexp.MustCompile(`^([^\s=]+)\s*=\s*(.+?)$`)
|
||||
)
|
||||
|
||||
// Sections returns the list of sections in the file.
|
||||
func (c *Config) Sections() []string {
|
||||
var sections []string
|
||||
for _, sect := range c.sections {
|
||||
sections = append(sections, sect.name)
|
||||
}
|
||||
return sections
|
||||
}
|
||||
|
||||
// Options returns the list of options in a given section.
|
||||
func (c *Config) Options(section string) []string {
|
||||
var options []string
|
||||
for _, sect := range c.sections {
|
||||
if sect.name == section {
|
||||
for _, opt := range sect.options {
|
||||
options = append(options, opt.name)
|
||||
}
|
||||
break
|
||||
}
|
||||
}
|
||||
return options
|
||||
}
|
||||
|
||||
// OptionMap returns the map option => value for a given section.
|
||||
func (c *Config) OptionMap(section string) map[string]string {
|
||||
options := make(map[string]string)
|
||||
for _, sect := range c.sections {
|
||||
if sect.name == section {
|
||||
for _, opt := range sect.options {
|
||||
options[opt.name] = opt.value
|
||||
}
|
||||
break
|
||||
}
|
||||
}
|
||||
return options
|
||||
}
|
||||
|
||||
// Comments returns the list of comments in a given section.
|
||||
// For the empty string, returns the file comments.
|
||||
func (c *Config) Comments(section string) []string {
|
||||
if section == "" {
|
||||
return c.comments
|
||||
}
|
||||
for _, sect := range c.sections {
|
||||
if sect.name == section {
|
||||
return sect.comments
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// AddComments appends the comment to the list of comments for the section.
|
||||
func (c *Config) AddComment(sect, comment string) {
|
||||
if sect == "" {
|
||||
c.comments = append(c.comments, comment)
|
||||
return
|
||||
}
|
||||
|
||||
for i, s := range c.sections {
|
||||
if s.name == sect {
|
||||
c.sections[i].comments = append(s.comments, comment)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
c.sections = append(c.sections, section{
|
||||
name: sect,
|
||||
comments: []string{comment},
|
||||
})
|
||||
}
|
||||
|
||||
// Parse reads the given io.Reader and returns a parsed Config object.
|
||||
func Parse(stream io.Reader) Config {
|
||||
var cfg Config
|
||||
var curSection string
|
||||
|
||||
scanner := bufio.NewScanner(bufio.NewReader(stream))
|
||||
for scanner.Scan() {
|
||||
line := strings.TrimSpace(scanner.Text())
|
||||
if strings.HasPrefix(line, "#") || strings.HasPrefix(line, ";") {
|
||||
comment := strings.TrimLeft(line, ";# ")
|
||||
cfg.AddComment(curSection, comment)
|
||||
} else if len(line) > 0 {
|
||||
if m := iniSectionRe.FindStringSubmatch(line); len(m) > 0 {
|
||||
curSection = m[1]
|
||||
} else if m := iniOptionRe.FindStringSubmatch(line); len(m) > 0 {
|
||||
key := m[1]
|
||||
val := m[2]
|
||||
if !strings.Contains(val, "\"") {
|
||||
// If val does not contain any quote characers, we can make it
|
||||
// a quoted string and safely let strconv.Unquote sort out any
|
||||
// escapes
|
||||
val = "\"" + val + "\""
|
||||
}
|
||||
if val[0] == '"' {
|
||||
val, _ = strconv.Unquote(val)
|
||||
}
|
||||
|
||||
cfg.Set(curSection, key, val)
|
||||
}
|
||||
}
|
||||
}
|
||||
return cfg
|
||||
}
|
||||
|
||||
// Write writes the sections and options to the io.Writer in INI format.
|
||||
func (c *Config) Write(out io.Writer) error {
|
||||
for _, cmt := range c.comments {
|
||||
fmt.Fprintln(out, "; "+cmt)
|
||||
}
|
||||
if len(c.comments) > 0 {
|
||||
fmt.Fprintln(out)
|
||||
}
|
||||
|
||||
for _, sect := range c.sections {
|
||||
fmt.Fprintf(out, "[%s]\n", sect.name)
|
||||
for _, cmt := range sect.comments {
|
||||
fmt.Fprintln(out, "; "+cmt)
|
||||
}
|
||||
for _, opt := range sect.options {
|
||||
val := opt.value
|
||||
if len(val) == 0 {
|
||||
continue
|
||||
}
|
||||
|
||||
// Quote the string if it begins or ends with space
|
||||
needsQuoting := val[0] == ' ' || val[len(val)-1] == ' '
|
||||
|
||||
if !needsQuoting {
|
||||
// Quote the string if it contains any unprintable characters
|
||||
for _, r := range val {
|
||||
if !strconv.IsPrint(r) {
|
||||
needsQuoting = true
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if needsQuoting {
|
||||
val = strconv.Quote(val)
|
||||
}
|
||||
|
||||
fmt.Fprintf(out, "%s=%s\n", opt.name, val)
|
||||
}
|
||||
fmt.Fprintln(out)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Get gets the value from the specified section and key name, or the empty
|
||||
// string if either the section or the key is missing.
|
||||
func (c *Config) Get(section, key string) string {
|
||||
for _, sect := range c.sections {
|
||||
if sect.name == section {
|
||||
for _, opt := range sect.options {
|
||||
if opt.name == key {
|
||||
return opt.value
|
||||
}
|
||||
}
|
||||
return ""
|
||||
}
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
// Set sets a value for an option in a section. If the option exists, it's
|
||||
// value will be overwritten. If the option does not exist, it will be added.
|
||||
// If the section does not exist, it will be added and the option added to it.
|
||||
func (c *Config) Set(sectionName, key, value string) {
|
||||
for i, sect := range c.sections {
|
||||
if sect.name == sectionName {
|
||||
for j, opt := range sect.options {
|
||||
if opt.name == key {
|
||||
c.sections[i].options[j].value = value
|
||||
return
|
||||
}
|
||||
}
|
||||
c.sections[i].options = append(sect.options, option{key, value})
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
c.sections = append(c.sections, section{
|
||||
name: sectionName,
|
||||
options: []option{{key, value}},
|
||||
})
|
||||
}
|
||||
|
||||
// Delete removes the option from the specified section.
|
||||
func (c *Config) Delete(section, key string) {
|
||||
for sn, sect := range c.sections {
|
||||
if sect.name == section {
|
||||
for i, opt := range sect.options {
|
||||
if opt.name == key {
|
||||
c.sections[sn].options = append(sect.options[:i], sect.options[i+1:]...)
|
||||
return
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
214
Godeps/_workspace/src/github.com/calmh/ini/ini_test.go
generated
vendored
214
Godeps/_workspace/src/github.com/calmh/ini/ini_test.go
generated
vendored
@@ -1,214 +0,0 @@
|
||||
package ini_test
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/calmh/ini"
|
||||
)
|
||||
|
||||
func TestParseValues(t *testing.T) {
|
||||
strs := []string{
|
||||
`[general]`,
|
||||
`k1=v1`,
|
||||
`k2 = v2`,
|
||||
` k3 = v3 `,
|
||||
`k4=" quoted spaces "`,
|
||||
`k5 = " quoted spaces " `,
|
||||
`k6 = with\nnewline`,
|
||||
`k7 = "with\nnewline"`,
|
||||
`k8 = a "quoted" word`,
|
||||
`k9 = "a \"quoted\" word"`,
|
||||
}
|
||||
buf := bytes.NewBufferString(strings.Join(strs, "\n"))
|
||||
cfg := ini.Parse(buf)
|
||||
|
||||
correct := map[string]string{
|
||||
"k1": "v1",
|
||||
"k2": "v2",
|
||||
"k3": "v3",
|
||||
"k4": " quoted spaces ",
|
||||
"k5": " quoted spaces ",
|
||||
"k6": "with\nnewline",
|
||||
"k7": "with\nnewline",
|
||||
"k8": "a \"quoted\" word",
|
||||
"k9": "a \"quoted\" word",
|
||||
}
|
||||
|
||||
for k, v := range correct {
|
||||
if v2 := cfg.Get("general", k); v2 != v {
|
||||
t.Errorf("Incorrect general.%s, %q != %q", k, v2, v)
|
||||
}
|
||||
}
|
||||
|
||||
if v := cfg.Get("general", "nonexistant"); v != "" {
|
||||
t.Errorf("Unexpected non-empty value %q", v)
|
||||
}
|
||||
}
|
||||
|
||||
func TestParseComments(t *testing.T) {
|
||||
strs := []string{
|
||||
";file comment 1", // No leading space
|
||||
"; file comment 2 ", // Trailing space
|
||||
"; file comment 3", // Multiple leading spaces
|
||||
"[general]",
|
||||
"; b general comment 1", // Comments in unsorted order
|
||||
"somekey = somevalue",
|
||||
"; a general comment 2",
|
||||
"[other]",
|
||||
"; other comment 1", // Comments in section with no values
|
||||
"; other comment 2",
|
||||
"[other2]",
|
||||
"; other2 comment 1",
|
||||
"; other2 comment 2", // Comments on last section
|
||||
"somekey = somevalue",
|
||||
}
|
||||
buf := bytes.NewBufferString(strings.Join(strs, "\n"))
|
||||
|
||||
correct := map[string][]string{
|
||||
"": []string{"file comment 1", "file comment 2", "file comment 3"},
|
||||
"general": []string{"b general comment 1", "a general comment 2"},
|
||||
"other": []string{"other comment 1", "other comment 2"},
|
||||
"other2": []string{"other2 comment 1", "other2 comment 2"},
|
||||
}
|
||||
|
||||
cfg := ini.Parse(buf)
|
||||
|
||||
for section, comments := range correct {
|
||||
cmts := cfg.Comments(section)
|
||||
if len(cmts) != len(comments) {
|
||||
t.Errorf("Incorrect number of comments for section %q: %d != %d", section, len(cmts), len(comments))
|
||||
} else {
|
||||
for i := range comments {
|
||||
if cmts[i] != comments[i] {
|
||||
t.Errorf("Incorrect comment: %q != %q", cmts[i], comments[i])
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestWrite(t *testing.T) {
|
||||
cfg := ini.Config{}
|
||||
cfg.Set("general", "k1", "v1")
|
||||
cfg.Set("general", "k2", "foo bar")
|
||||
cfg.Set("general", "k3", " foo bar ")
|
||||
cfg.Set("general", "k4", "foo\nbar")
|
||||
|
||||
var out bytes.Buffer
|
||||
cfg.Write(&out)
|
||||
|
||||
correct := `[general]
|
||||
k1=v1
|
||||
k2=foo bar
|
||||
k3=" foo bar "
|
||||
k4="foo\nbar"
|
||||
|
||||
`
|
||||
if s := out.String(); s != correct {
|
||||
t.Errorf("Incorrect written .INI:\n%s\ncorrect:\n%s", s, correct)
|
||||
}
|
||||
}
|
||||
|
||||
func TestSet(t *testing.T) {
|
||||
buf := bytes.NewBufferString("[general]\nfoo=bar\nfoo2=bar2\n")
|
||||
cfg := ini.Parse(buf)
|
||||
|
||||
cfg.Set("general", "foo", "baz") // Overwrite existing
|
||||
cfg.Set("general", "baz", "quux") // Create new value
|
||||
cfg.Set("other", "baz2", "quux2") // Create new section + value
|
||||
|
||||
var out bytes.Buffer
|
||||
cfg.Write(&out)
|
||||
|
||||
correct := `[general]
|
||||
foo=baz
|
||||
foo2=bar2
|
||||
baz=quux
|
||||
|
||||
[other]
|
||||
baz2=quux2
|
||||
|
||||
`
|
||||
|
||||
if s := out.String(); s != correct {
|
||||
t.Errorf("Incorrect INI after set:\n%s", s)
|
||||
}
|
||||
}
|
||||
|
||||
func TestDelete(t *testing.T) {
|
||||
buf := bytes.NewBufferString("[general]\nfoo=bar\nfoo2=bar2\nfoo3=baz\n")
|
||||
cfg := ini.Parse(buf)
|
||||
cfg.Delete("general", "foo")
|
||||
out := new(bytes.Buffer)
|
||||
cfg.Write(out)
|
||||
correct := "[general]\nfoo2=bar2\nfoo3=baz\n\n"
|
||||
|
||||
if s := out.String(); s != correct {
|
||||
t.Errorf("Incorrect INI after delete:\n%s", s)
|
||||
}
|
||||
|
||||
buf = bytes.NewBufferString("[general]\nfoo=bar\nfoo2=bar2\nfoo3=baz\n")
|
||||
cfg = ini.Parse(buf)
|
||||
cfg.Delete("general", "foo2")
|
||||
out = new(bytes.Buffer)
|
||||
cfg.Write(out)
|
||||
correct = "[general]\nfoo=bar\nfoo3=baz\n\n"
|
||||
|
||||
if s := out.String(); s != correct {
|
||||
t.Errorf("Incorrect INI after delete:\n%s", s)
|
||||
}
|
||||
|
||||
buf = bytes.NewBufferString("[general]\nfoo=bar\nfoo2=bar2\nfoo3=baz\n")
|
||||
cfg = ini.Parse(buf)
|
||||
cfg.Delete("general", "foo3")
|
||||
out = new(bytes.Buffer)
|
||||
cfg.Write(out)
|
||||
correct = "[general]\nfoo=bar\nfoo2=bar2\n\n"
|
||||
|
||||
if s := out.String(); s != correct {
|
||||
t.Errorf("Incorrect INI after delete:\n%s", s)
|
||||
}
|
||||
}
|
||||
|
||||
func TestSetManyEquals(t *testing.T) {
|
||||
buf := bytes.NewBufferString("[general]\nfoo=bar==\nfoo2=bar2==\n")
|
||||
cfg := ini.Parse(buf)
|
||||
|
||||
cfg.Set("general", "foo", "baz==")
|
||||
|
||||
var out bytes.Buffer
|
||||
cfg.Write(&out)
|
||||
|
||||
correct := `[general]
|
||||
foo=baz==
|
||||
foo2=bar2==
|
||||
|
||||
`
|
||||
|
||||
if s := out.String(); s != correct {
|
||||
t.Errorf("Incorrect INI after set:\n%s", s)
|
||||
}
|
||||
}
|
||||
|
||||
func TestRewriteDuplicate(t *testing.T) {
|
||||
buf := bytes.NewBufferString("[general]\nfoo=bar==\nfoo=bar2==\n")
|
||||
cfg := ini.Parse(buf)
|
||||
|
||||
if v := cfg.Get("general", "foo"); v != "bar2==" {
|
||||
t.Errorf("incorrect get %q", v)
|
||||
}
|
||||
|
||||
var out bytes.Buffer
|
||||
cfg.Write(&out)
|
||||
|
||||
correct := `[general]
|
||||
foo=bar2==
|
||||
|
||||
`
|
||||
|
||||
if s := out.String(); s != correct {
|
||||
t.Errorf("Incorrect INI after set:\n%s", s)
|
||||
}
|
||||
}
|
||||
2
Godeps/_workspace/src/github.com/codegangsta/inject/.gitignore
generated
vendored
2
Godeps/_workspace/src/github.com/codegangsta/inject/.gitignore
generated
vendored
@@ -1,2 +0,0 @@
|
||||
inject
|
||||
inject.test
|
||||
20
Godeps/_workspace/src/github.com/codegangsta/inject/LICENSE
generated
vendored
20
Godeps/_workspace/src/github.com/codegangsta/inject/LICENSE
generated
vendored
@@ -1,20 +0,0 @@
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2013 Jeremy Saenz
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
this software and associated documentation files (the "Software"), to deal in
|
||||
the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
4
Godeps/_workspace/src/github.com/codegangsta/inject/README.md
generated
vendored
4
Godeps/_workspace/src/github.com/codegangsta/inject/README.md
generated
vendored
@@ -1,4 +0,0 @@
|
||||
inject
|
||||
======
|
||||
|
||||
Dependency injection for go
|
||||
168
Godeps/_workspace/src/github.com/codegangsta/inject/inject.go
generated
vendored
168
Godeps/_workspace/src/github.com/codegangsta/inject/inject.go
generated
vendored
@@ -1,168 +0,0 @@
|
||||
// Package inject provides utilities for mapping and injecting dependencies in various ways.
|
||||
package inject
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"reflect"
|
||||
)
|
||||
|
||||
// Injector represents an interface for mapping and injecting dependencies into structs
|
||||
// and function arguments.
|
||||
type Injector interface {
|
||||
Applicator
|
||||
Invoker
|
||||
TypeMapper
|
||||
// SetParent sets the parent of the injector. If the injector cannot find a
|
||||
// dependency in its Type map it will check its parent before returning an
|
||||
// error.
|
||||
SetParent(Injector)
|
||||
}
|
||||
|
||||
// Applicator represents an interface for mapping dependencies to a struct.
|
||||
type Applicator interface {
|
||||
// Maps dependencies in the Type map to each field in the struct
|
||||
// that is tagged with 'inject'. Returns an error if the injection
|
||||
// fails.
|
||||
Apply(interface{}) error
|
||||
}
|
||||
|
||||
// Invoker represents an interface for calling functions via reflection.
|
||||
type Invoker interface {
|
||||
// Invoke attempts to call the interface{} provided as a function,
|
||||
// providing dependencies for function arguments based on Type. Returns
|
||||
// a slice of reflect.Value representing the returned values of the function.
|
||||
// Returns an error if the injection fails.
|
||||
Invoke(interface{}) ([]reflect.Value, error)
|
||||
}
|
||||
|
||||
// TypeMapper represents an interface for mapping interface{} values based on type.
|
||||
type TypeMapper interface {
|
||||
// Maps the interface{} value based on its immediate type from reflect.TypeOf.
|
||||
Map(interface{}) TypeMapper
|
||||
// Maps the interface{} value based on the pointer of an Interface provided.
|
||||
// This is really only useful for mapping a value as an interface, as interfaces
|
||||
// cannot at this time be referenced directly without a pointer.
|
||||
MapTo(interface{}, interface{}) TypeMapper
|
||||
// Provides a possibility to directly insert a mapping based on type and value.
|
||||
// This makes it possible to directly map type arguments not possible to instantiate
|
||||
// with reflect like unidirectional channels.
|
||||
Set(reflect.Type, reflect.Value) TypeMapper
|
||||
// Returns the Value that is mapped to the current type. Returns a zeroed Value if
|
||||
// the Type has not been mapped.
|
||||
Get(reflect.Type) reflect.Value
|
||||
}
|
||||
|
||||
type injector struct {
|
||||
values map[reflect.Type]reflect.Value
|
||||
parent Injector
|
||||
}
|
||||
|
||||
// InterfaceOf dereferences a pointer to an Interface type.
|
||||
// It panics if value is not an pointer to an interface.
|
||||
func InterfaceOf(value interface{}) reflect.Type {
|
||||
t := reflect.TypeOf(value)
|
||||
|
||||
for t.Kind() == reflect.Ptr {
|
||||
t = t.Elem()
|
||||
}
|
||||
|
||||
if t.Kind() != reflect.Interface {
|
||||
panic("Called inject.InterfaceOf with a value that is not a pointer to an interface. (*MyInterface)(nil)")
|
||||
}
|
||||
|
||||
return t
|
||||
}
|
||||
|
||||
// New returns a new Injector.
|
||||
func New() Injector {
|
||||
return &injector{
|
||||
values: make(map[reflect.Type]reflect.Value),
|
||||
}
|
||||
}
|
||||
|
||||
// Invoke attempts to call the interface{} provided as a function,
|
||||
// providing dependencies for function arguments based on Type.
|
||||
// Returns a slice of reflect.Value representing the returned values of the function.
|
||||
// Returns an error if the injection fails.
|
||||
// It panics if f is not a function
|
||||
func (inj *injector) Invoke(f interface{}) ([]reflect.Value, error) {
|
||||
t := reflect.TypeOf(f)
|
||||
|
||||
var in = make([]reflect.Value, t.NumIn()) //Panic if t is not kind of Func
|
||||
for i := 0; i < t.NumIn(); i++ {
|
||||
argType := t.In(i)
|
||||
val := inj.Get(argType)
|
||||
if !val.IsValid() {
|
||||
return nil, fmt.Errorf("Value not found for type %v", argType)
|
||||
}
|
||||
|
||||
in[i] = val
|
||||
}
|
||||
|
||||
return reflect.ValueOf(f).Call(in), nil
|
||||
}
|
||||
|
||||
// Maps dependencies in the Type map to each field in the struct
|
||||
// that is tagged with 'inject'.
|
||||
// Returns an error if the injection fails.
|
||||
func (inj *injector) Apply(val interface{}) error {
|
||||
v := reflect.ValueOf(val)
|
||||
|
||||
for v.Kind() == reflect.Ptr {
|
||||
v = v.Elem()
|
||||
}
|
||||
|
||||
if v.Kind() != reflect.Struct {
|
||||
return nil // Should not panic here ?
|
||||
}
|
||||
|
||||
t := v.Type()
|
||||
|
||||
for i := 0; i < v.NumField(); i++ {
|
||||
f := v.Field(i)
|
||||
structField := t.Field(i)
|
||||
if f.CanSet() && structField.Tag == "inject" {
|
||||
ft := f.Type()
|
||||
v := inj.Get(ft)
|
||||
if !v.IsValid() {
|
||||
return fmt.Errorf("Value not found for type %v", ft)
|
||||
}
|
||||
|
||||
f.Set(v)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// Maps the concrete value of val to its dynamic type using reflect.TypeOf,
|
||||
// It returns the TypeMapper registered in.
|
||||
func (i *injector) Map(val interface{}) TypeMapper {
|
||||
i.values[reflect.TypeOf(val)] = reflect.ValueOf(val)
|
||||
return i
|
||||
}
|
||||
|
||||
func (i *injector) MapTo(val interface{}, ifacePtr interface{}) TypeMapper {
|
||||
i.values[InterfaceOf(ifacePtr)] = reflect.ValueOf(val)
|
||||
return i
|
||||
}
|
||||
|
||||
// Maps the given reflect.Type to the given reflect.Value and returns
|
||||
// the Typemapper the mapping has been registered in.
|
||||
func (i *injector) Set(typ reflect.Type, val reflect.Value) TypeMapper {
|
||||
i.values[typ] = val
|
||||
return i
|
||||
}
|
||||
|
||||
func (i *injector) Get(t reflect.Type) reflect.Value {
|
||||
val := i.values[t]
|
||||
if !val.IsValid() && i.parent != nil {
|
||||
val = i.parent.Get(t)
|
||||
}
|
||||
return val
|
||||
}
|
||||
|
||||
func (i *injector) SetParent(parent Injector) {
|
||||
i.parent = parent
|
||||
}
|
||||
142
Godeps/_workspace/src/github.com/codegangsta/inject/inject_test.go
generated
vendored
142
Godeps/_workspace/src/github.com/codegangsta/inject/inject_test.go
generated
vendored
@@ -1,142 +0,0 @@
|
||||
package inject_test
|
||||
|
||||
import (
|
||||
"github.com/codegangsta/inject"
|
||||
"reflect"
|
||||
"testing"
|
||||
)
|
||||
|
||||
type SpecialString interface {
|
||||
}
|
||||
|
||||
type TestStruct struct {
|
||||
Dep1 string `inject`
|
||||
Dep2 SpecialString `inject`
|
||||
Dep3 string
|
||||
}
|
||||
|
||||
/* Test Helpers */
|
||||
func expect(t *testing.T, a interface{}, b interface{}) {
|
||||
if a != b {
|
||||
t.Errorf("Expected %v (type %v) - Got %v (type %v)", b, reflect.TypeOf(b), a, reflect.TypeOf(a))
|
||||
}
|
||||
}
|
||||
|
||||
func refute(t *testing.T, a interface{}, b interface{}) {
|
||||
if a == b {
|
||||
t.Errorf("Did not expect %v (type %v) - Got %v (type %v)", b, reflect.TypeOf(b), a, reflect.TypeOf(a))
|
||||
}
|
||||
}
|
||||
|
||||
func Test_InjectorInvoke(t *testing.T) {
|
||||
injector := inject.New()
|
||||
expect(t, injector == nil, false)
|
||||
|
||||
dep := "some dependency"
|
||||
injector.Map(dep)
|
||||
dep2 := "another dep"
|
||||
injector.MapTo(dep2, (*SpecialString)(nil))
|
||||
dep3 := make(chan *SpecialString)
|
||||
dep4 := make(chan *SpecialString)
|
||||
typRecv := reflect.ChanOf(reflect.RecvDir, reflect.TypeOf(dep3).Elem())
|
||||
typSend := reflect.ChanOf(reflect.SendDir, reflect.TypeOf(dep4).Elem())
|
||||
injector.Set(typRecv, reflect.ValueOf(dep3))
|
||||
injector.Set(typSend, reflect.ValueOf(dep4))
|
||||
|
||||
_, err := injector.Invoke(func(d1 string, d2 SpecialString, d3 <-chan *SpecialString, d4 chan<- *SpecialString) {
|
||||
expect(t, d1, dep)
|
||||
expect(t, d2, dep2)
|
||||
expect(t, reflect.TypeOf(d3).Elem(), reflect.TypeOf(dep3).Elem())
|
||||
expect(t, reflect.TypeOf(d4).Elem(), reflect.TypeOf(dep4).Elem())
|
||||
expect(t, reflect.TypeOf(d3).ChanDir(), reflect.RecvDir)
|
||||
expect(t, reflect.TypeOf(d4).ChanDir(), reflect.SendDir)
|
||||
})
|
||||
|
||||
expect(t, err, nil)
|
||||
}
|
||||
|
||||
func Test_InjectorInvokeReturnValues(t *testing.T) {
|
||||
injector := inject.New()
|
||||
expect(t, injector == nil, false)
|
||||
|
||||
dep := "some dependency"
|
||||
injector.Map(dep)
|
||||
dep2 := "another dep"
|
||||
injector.MapTo(dep2, (*SpecialString)(nil))
|
||||
|
||||
result, err := injector.Invoke(func(d1 string, d2 SpecialString) string {
|
||||
expect(t, d1, dep)
|
||||
expect(t, d2, dep2)
|
||||
return "Hello world"
|
||||
})
|
||||
|
||||
expect(t, result[0].String(), "Hello world")
|
||||
expect(t, err, nil)
|
||||
}
|
||||
|
||||
func Test_InjectorApply(t *testing.T) {
|
||||
injector := inject.New()
|
||||
|
||||
injector.Map("a dep").MapTo("another dep", (*SpecialString)(nil))
|
||||
|
||||
s := TestStruct{}
|
||||
err := injector.Apply(&s)
|
||||
expect(t, err, nil)
|
||||
|
||||
expect(t, s.Dep1, "a dep")
|
||||
expect(t, s.Dep2, "another dep")
|
||||
}
|
||||
|
||||
func Test_InterfaceOf(t *testing.T) {
|
||||
iType := inject.InterfaceOf((*SpecialString)(nil))
|
||||
expect(t, iType.Kind(), reflect.Interface)
|
||||
|
||||
iType = inject.InterfaceOf((**SpecialString)(nil))
|
||||
expect(t, iType.Kind(), reflect.Interface)
|
||||
|
||||
// Expecting nil
|
||||
defer func() {
|
||||
rec := recover()
|
||||
refute(t, rec, nil)
|
||||
}()
|
||||
iType = inject.InterfaceOf((*testing.T)(nil))
|
||||
}
|
||||
|
||||
func Test_InjectorSet(t *testing.T) {
|
||||
injector := inject.New()
|
||||
typ := reflect.TypeOf("string")
|
||||
typSend := reflect.ChanOf(reflect.SendDir, typ)
|
||||
typRecv := reflect.ChanOf(reflect.RecvDir, typ)
|
||||
|
||||
// instantiating unidirectional channels is not possible using reflect
|
||||
// http://golang.org/src/pkg/reflect/value.go?s=60463:60504#L2064
|
||||
chanRecv := reflect.MakeChan(reflect.ChanOf(reflect.BothDir, typ), 0)
|
||||
chanSend := reflect.MakeChan(reflect.ChanOf(reflect.BothDir, typ), 0)
|
||||
|
||||
injector.Set(typSend, chanSend)
|
||||
injector.Set(typRecv, chanRecv)
|
||||
|
||||
expect(t, injector.Get(typSend).IsValid(), true)
|
||||
expect(t, injector.Get(typRecv).IsValid(), true)
|
||||
expect(t, injector.Get(chanSend.Type()).IsValid(), false)
|
||||
}
|
||||
|
||||
|
||||
func Test_InjectorGet(t *testing.T) {
|
||||
injector := inject.New()
|
||||
|
||||
injector.Map("some dependency")
|
||||
|
||||
expect(t, injector.Get(reflect.TypeOf("string")).IsValid(), true)
|
||||
expect(t, injector.Get(reflect.TypeOf(11)).IsValid(), false)
|
||||
}
|
||||
|
||||
func Test_InjectorSetParent(t *testing.T) {
|
||||
injector := inject.New()
|
||||
injector.MapTo("another dep", (*SpecialString)(nil))
|
||||
|
||||
injector2 := inject.New()
|
||||
injector2.SetParent(injector)
|
||||
|
||||
expect(t, injector2.Get(inject.InterfaceOf((*SpecialString)(nil))).IsValid(), true)
|
||||
}
|
||||
23
Godeps/_workspace/src/github.com/codegangsta/martini/.gitignore
generated
vendored
23
Godeps/_workspace/src/github.com/codegangsta/martini/.gitignore
generated
vendored
@@ -1,23 +0,0 @@
|
||||
# Compiled Object files, Static and Dynamic libs (Shared Objects)
|
||||
*.o
|
||||
*.a
|
||||
*.so
|
||||
|
||||
# Folders
|
||||
_obj
|
||||
_test
|
||||
|
||||
# Architecture specific extensions/prefixes
|
||||
*.[568vq]
|
||||
[568vq].out
|
||||
|
||||
*.cgo1.go
|
||||
*.cgo2.c
|
||||
_cgo_defun.c
|
||||
_cgo_gotypes.go
|
||||
_cgo_export.*
|
||||
|
||||
_testmain.go
|
||||
|
||||
*.exe
|
||||
*.test
|
||||
20
Godeps/_workspace/src/github.com/codegangsta/martini/LICENSE
generated
vendored
20
Godeps/_workspace/src/github.com/codegangsta/martini/LICENSE
generated
vendored
@@ -1,20 +0,0 @@
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2013 Jeremy Saenz
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
this software and associated documentation files (the "Software"), to deal in
|
||||
the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
345
Godeps/_workspace/src/github.com/codegangsta/martini/README.md
generated
vendored
345
Godeps/_workspace/src/github.com/codegangsta/martini/README.md
generated
vendored
@@ -1,345 +0,0 @@
|
||||
# Martini [](https://app.wercker.com/project/bykey/174bef7e3c999e103cacfe2770102266) [](http://godoc.org/github.com/codegangsta/martini)
|
||||
|
||||
Martini is a powerful package for quickly writing modular web applications/services in Golang.
|
||||
|
||||
Language Translations: [Simplified Chinese (zh_CN)](translations/README_zh_cn.md)
|
||||
|
||||
|
||||
## Getting Started
|
||||
|
||||
After installing Go and setting up your [GOPATH](http://golang.org/doc/code.html#GOPATH), create your first `.go` file. We'll call it `server.go`.
|
||||
|
||||
~~~ go
|
||||
package main
|
||||
|
||||
import "github.com/codegangsta/martini"
|
||||
|
||||
func main() {
|
||||
m := martini.Classic()
|
||||
m.Get("/", func() string {
|
||||
return "Hello world!"
|
||||
})
|
||||
m.Run()
|
||||
}
|
||||
~~~
|
||||
|
||||
Then install the Martini package (**go 1.1** and greater is required):
|
||||
~~~
|
||||
go get github.com/codegangsta/martini
|
||||
~~~
|
||||
|
||||
Then run your server:
|
||||
~~~
|
||||
go run server.go
|
||||
~~~
|
||||
|
||||
You will now have a Martini webserver running on `localhost:3000`.
|
||||
|
||||
## Getting Help
|
||||
|
||||
Join the [Mailing list](https://groups.google.com/forum/#!forum/martini-go)
|
||||
|
||||
Watch the [Demo Video](http://martini.codegangsta.io/#demo)
|
||||
|
||||
## Features
|
||||
* Extremely simple to use.
|
||||
* Non-intrusive design.
|
||||
* Plays nice with other Golang packages.
|
||||
* Awesome path matching and routing.
|
||||
* Modular design - Easy to add functionality, easy to rip stuff out.
|
||||
* Lots of good handlers/middlewares to use.
|
||||
* Great 'out of the box' feature set.
|
||||
* **Fully compatible with the [http.HandlerFunc](http://godoc.org/net/http#HandlerFunc) interface.**
|
||||
|
||||
## More Middleware
|
||||
For more middleware and functionality, check out the repositories in the [martini-contrib](https://github.com/martini-contrib) organization.
|
||||
|
||||
## Table of Contents
|
||||
* [Classic Martini](#classic-martini)
|
||||
* [Handlers](#handlers)
|
||||
* [Routing](#routing)
|
||||
* [Services](#services)
|
||||
* [Serving Static Files](#serving-static-files)
|
||||
* [Middleware Handlers](#middleware-handlers)
|
||||
* [Next()](#next)
|
||||
* [Martini Env](#martini-env)
|
||||
* [FAQ](#faq)
|
||||
|
||||
## Classic Martini
|
||||
To get up and running quickly, [martini.Classic()](http://godoc.org/github.com/codegangsta/martini#Classic) provides some reasonable defaults that work well for most web applications:
|
||||
~~~ go
|
||||
m := martini.Classic()
|
||||
// ... middleware and routing goes here
|
||||
m.Run()
|
||||
~~~
|
||||
|
||||
Below is some of the functionality [martini.Classic()](http://godoc.org/github.com/codegangsta/martini#Classic) pulls in automatically:
|
||||
* Request/Response Logging - [martini.Logger](http://godoc.org/github.com/codegangsta/martini#Logger)
|
||||
* Panic Recovery - [martini.Recovery](http://godoc.org/github.com/codegangsta/martini#Recovery)
|
||||
* Static File serving - [martini.Static](http://godoc.org/github.com/codegangsta/martini#Static)
|
||||
* Routing - [martini.Router](http://godoc.org/github.com/codegangsta/martini#Router)
|
||||
|
||||
### Handlers
|
||||
Handlers are the heart and soul of Martini. A handler is basically any kind of callable function:
|
||||
~~~ go
|
||||
m.Get("/", func() {
|
||||
println("hello world")
|
||||
})
|
||||
~~~
|
||||
|
||||
#### Return Values
|
||||
If a handler returns something, Martini will write the result to the current [http.ResponseWriter](http://godoc.org/net/http#ResponseWriter) as a string:
|
||||
~~~ go
|
||||
m.Get("/", func() string {
|
||||
return "hello world" // HTTP 200 : "hello world"
|
||||
})
|
||||
~~~
|
||||
|
||||
You can also optionally return a status code:
|
||||
~~~ go
|
||||
m.Get("/", func() (int, string) {
|
||||
return 418, "i'm a teapot" // HTTP 418 : "i'm a teapot"
|
||||
})
|
||||
~~~
|
||||
|
||||
#### Service Injection
|
||||
Handlers are invoked via reflection. Martini makes use of *Dependency Injection* to resolve dependencies in a Handlers argument list. **This makes Martini completely compatible with golang's `http.HandlerFunc` interface.**
|
||||
|
||||
If you add an argument to your Handler, Martini will search its list of services and attempt to resolve the dependency via type assertion:
|
||||
~~~ go
|
||||
m.Get("/", func(res http.ResponseWriter, req *http.Request) { // res and req are injected by Martini
|
||||
res.WriteHeader(200) // HTTP 200
|
||||
})
|
||||
~~~
|
||||
|
||||
The following services are included with [martini.Classic()](http://godoc.org/github.com/codegangsta/martini#Classic):
|
||||
* [*log.Logger](http://godoc.org/log#Logger) - Global logger for Martini.
|
||||
* [martini.Context](http://godoc.org/github.com/codegangsta/martini#Context) - http request context.
|
||||
* [martini.Params](http://godoc.org/github.com/codegangsta/martini#Params) - `map[string]string` of named params found by route matching.
|
||||
* [martini.Routes](http://godoc.org/github.com/codegangsta/martini#Routes) - Route helper service.
|
||||
* [http.ResponseWriter](http://godoc.org/net/http/#ResponseWriter) - http Response writer interface.
|
||||
* [*http.Request](http://godoc.org/net/http/#Request) - http Request.
|
||||
|
||||
### Routing
|
||||
In Martini, a route is an HTTP method paired with a URL-matching pattern.
|
||||
Each route can take one or more handler methods:
|
||||
~~~ go
|
||||
m.Get("/", func() {
|
||||
// show something
|
||||
})
|
||||
|
||||
m.Patch("/", func() {
|
||||
// update something
|
||||
})
|
||||
|
||||
m.Post("/", func() {
|
||||
// create something
|
||||
})
|
||||
|
||||
m.Put("/", func() {
|
||||
// replace something
|
||||
})
|
||||
|
||||
m.Delete("/", func() {
|
||||
// destroy something
|
||||
})
|
||||
|
||||
m.Options("/", func() {
|
||||
// http options
|
||||
})
|
||||
|
||||
m.NotFound(func() {
|
||||
// handle 404
|
||||
})
|
||||
~~~
|
||||
|
||||
Routes are matched in the order they are defined. The first route that
|
||||
matches the request is invoked.
|
||||
|
||||
Route patterns may include named parameters, accessible via the [martini.Params](http://godoc.org/github.com/codegangsta/martini#Params) service:
|
||||
~~~ go
|
||||
m.Get("/hello/:name", func(params martini.Params) string {
|
||||
return "Hello " + params["name"]
|
||||
})
|
||||
~~~
|
||||
|
||||
Routes can be matched with regular expressions and globs as well:
|
||||
~~~ go
|
||||
m.Get("/hello/**", func(params martini.Params) string {
|
||||
return "Hello " + params["_1"]
|
||||
})
|
||||
~~~
|
||||
|
||||
Route handlers can be stacked on top of each other, which is useful for things like authentication and authorization:
|
||||
~~~ go
|
||||
m.Get("/secret", authorize, func() {
|
||||
// this will execute as long as authorize doesn't write a response
|
||||
})
|
||||
~~~
|
||||
|
||||
Route groups can be added too using the Group method.
|
||||
~~~ go
|
||||
m.Group("/books", func(r Router) {
|
||||
r.Get("/:id", GetBooks)
|
||||
r.Post("/new", NewBook)
|
||||
r.Put("/update/:id", UpdateBook)
|
||||
r.Delete("/delete/:id", DeleteBook)
|
||||
})
|
||||
~~~
|
||||
|
||||
Just like you can pass middlewares to a handler you can pass middlewares to groups.
|
||||
~~~ go
|
||||
m.Group("/books", func(r Router) {
|
||||
r.Get("/:id", GetBooks)
|
||||
r.Post("/new", NewBook)
|
||||
r.Put("/update/:id", UpdateBook)
|
||||
r.Delete("/delete/:id", DeleteBook)
|
||||
}, MyMiddleware1, MyMiddleware2)
|
||||
~~~
|
||||
|
||||
### Services
|
||||
Services are objects that are available to be injected into a Handler's argument list. You can map a service on a *Global* or *Request* level.
|
||||
|
||||
#### Global Mapping
|
||||
A Martini instance implements the inject.Injector interface, so mapping a service is easy:
|
||||
~~~ go
|
||||
db := &MyDatabase{}
|
||||
m := martini.Classic()
|
||||
m.Map(db) // the service will be available to all handlers as *MyDatabase
|
||||
// ...
|
||||
m.Run()
|
||||
~~~
|
||||
|
||||
#### Request-Level Mapping
|
||||
Mapping on the request level can be done in a handler via [martini.Context](http://godoc.org/github.com/codegangsta/martini#Context):
|
||||
~~~ go
|
||||
func MyCustomLoggerHandler(c martini.Context, req *http.Request) {
|
||||
logger := &MyCustomLogger{req}
|
||||
c.Map(logger) // mapped as *MyCustomLogger
|
||||
}
|
||||
~~~
|
||||
|
||||
#### Mapping values to Interfaces
|
||||
One of the most powerful parts about services is the ability to map a service to an interface. For instance, if you wanted to override the [http.ResponseWriter](http://godoc.org/net/http#ResponseWriter) with an object that wrapped it and performed extra operations, you can write the following handler:
|
||||
~~~ go
|
||||
func WrapResponseWriter(res http.ResponseWriter, c martini.Context) {
|
||||
rw := NewSpecialResponseWriter(res)
|
||||
c.MapTo(rw, (*http.ResponseWriter)(nil)) // override ResponseWriter with our wrapper ResponseWriter
|
||||
}
|
||||
~~~
|
||||
|
||||
### Serving Static Files
|
||||
A [martini.Classic()](http://godoc.org/github.com/codegangsta/martini#Classic) instance automatically serves static files from the "public" directory in the root of your server.
|
||||
You can serve from more directories by adding more [martini.Static](http://godoc.org/github.com/codegangsta/martini#Static) handlers.
|
||||
~~~ go
|
||||
m.Use(martini.Static("assets")) // serve from the "assets" directory as well
|
||||
~~~
|
||||
|
||||
## Middleware Handlers
|
||||
Middleware Handlers sit between the incoming http request and the router. In essence they are no different than any other Handler in Martini. You can add a middleware handler to the stack like so:
|
||||
~~~ go
|
||||
m.Use(func() {
|
||||
// do some middleware stuff
|
||||
})
|
||||
~~~
|
||||
|
||||
You can have full control over the middleware stack with the `Handlers` function. This will replace any handlers that have been previously set:
|
||||
~~~ go
|
||||
m.Handlers(
|
||||
Middleware1,
|
||||
Middleware2,
|
||||
Middleware3,
|
||||
)
|
||||
~~~
|
||||
|
||||
Middleware Handlers work really well for things like logging, authorization, authentication, sessions, gzipping, error pages and any other operations that must happen before or after an http request:
|
||||
~~~ go
|
||||
// validate an api key
|
||||
m.Use(func(res http.ResponseWriter, req *http.Request) {
|
||||
if req.Header.Get("X-API-KEY") != "secret123" {
|
||||
res.WriteHeader(http.StatusUnauthorized)
|
||||
}
|
||||
})
|
||||
~~~
|
||||
|
||||
### Next()
|
||||
[Context.Next()](http://godoc.org/github.com/codegangsta/martini#Context) is an optional function that Middleware Handlers can call to yield the until after the other Handlers have been executed. This works really well for any operations that must happen after an http request:
|
||||
~~~ go
|
||||
// log before and after a request
|
||||
m.Use(func(c martini.Context, log *log.Logger){
|
||||
log.Println("before a request")
|
||||
|
||||
c.Next()
|
||||
|
||||
log.Println("after a request")
|
||||
})
|
||||
~~~
|
||||
|
||||
## Martini Env
|
||||
|
||||
Some Martini handlers make use of the `martini.Env` global variable to provide special functionality for development environments vs production environments. It is reccomended that the `MARTINI_ENV=production` environment variable to be set when deploying a Martini server into a production environment.
|
||||
|
||||
## FAQ
|
||||
|
||||
### Where do I find middleware X?
|
||||
|
||||
Start by looking in the [martini-contrib](https://github.com/martini-contrib) projects. If it is not there feel free to contact a martini-contrib team member about adding a new repo to the organization.
|
||||
|
||||
* [auth](https://github.com/martini-contrib/auth) - Handlers for authentication.
|
||||
* [binding](https://github.com/martini-contrib/binding) - Handler for mapping/validating a raw request into a structure.
|
||||
* [gzip](https://github.com/martini-contrib/gzip) - Handler for adding gzip compress to requests
|
||||
* [render](https://github.com/martini-contrib/render) - Handler that provides a service for easily rendering JSON and HTML templates.
|
||||
* [acceptlang](https://github.com/martini-contrib/acceptlang) - Handler for parsing the `Accept-Language` HTTP header.
|
||||
* [sessions](https://github.com/martini-contrib/sessions) - Handler that provides a Session service.
|
||||
* [strip](https://github.com/martini-contrib/strip) - URL Prefix stripping.
|
||||
* [method](https://github.com/martini-contrib/method) - HTTP method overriding via Header or form fields.
|
||||
* [secure](https://github.com/martini-contrib/secure) - Implements a few quick security wins.
|
||||
* [encoder](https://github.com/martini-contrib/encoder) - Encoder service for rendering data in several formats and content negotiation.
|
||||
* [cors](https://github.com/martini-contrib/cors) - Handler that enables CORS support.
|
||||
* [oauth2](https://github.com/martini-contrib/oauth2) - Handler that provides OAuth 2.0 login for Martini apps. Google Sign-in, Facebook Connect and Github login is supported.
|
||||
|
||||
### How do I integrate with existing servers?
|
||||
|
||||
A Martini instance implements `http.Handler`, so it can easily be used to serve subtrees
|
||||
on existing Go servers. For example this is a working Martini app for Google App Engine:
|
||||
|
||||
~~~ go
|
||||
package hello
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"github.com/codegangsta/martini"
|
||||
)
|
||||
|
||||
func init() {
|
||||
m := martini.Classic()
|
||||
m.Get("/", func() string {
|
||||
return "Hello world!"
|
||||
})
|
||||
http.Handle("/", m)
|
||||
}
|
||||
~~~
|
||||
|
||||
### How do I change the port/host?
|
||||
|
||||
Martini's `Run` function looks for the PORT and HOST environment variables and uses those. Otherwise Martini will default to localhost:3000.
|
||||
To have more flexibility over port and host, use the `http.ListenAndServe` function instead.
|
||||
|
||||
~~~ go
|
||||
m := martini.Classic()
|
||||
// ...
|
||||
log.Fatal(http.ListenAndServe(":8080", m))
|
||||
~~~
|
||||
|
||||
### Live code reload?
|
||||
|
||||
[gin](https://github.com/codegangsta/gin) and [fresh](https://github.com/pilu/fresh) both live reload martini apps.
|
||||
|
||||
## Contributing
|
||||
Martini is meant to be kept tiny and clean. Most contributions should end up in a repository in the [martini-contrib](https://github.com/martini-contrib) organization. If you do have a contribution for the core of Martini feel free to put up a Pull Request.
|
||||
|
||||
## About
|
||||
|
||||
Inspired by [express](https://github.com/visionmedia/express) and [sinatra](https://github.com/sinatra/sinatra)
|
||||
|
||||
Martini is obsessively designed by none other than the [Code Gangsta](http://codegangsta.io/)
|
||||
25
Godeps/_workspace/src/github.com/codegangsta/martini/env.go
generated
vendored
25
Godeps/_workspace/src/github.com/codegangsta/martini/env.go
generated
vendored
@@ -1,25 +0,0 @@
|
||||
package martini
|
||||
|
||||
import (
|
||||
"os"
|
||||
)
|
||||
|
||||
// Envs
|
||||
const (
|
||||
Dev string = "development"
|
||||
Prod string = "production"
|
||||
Test string = "test"
|
||||
)
|
||||
|
||||
// Env is the environment that Martini is executing in. The MARTINI_ENV is read on initialization to set this variable.
|
||||
var Env = Dev
|
||||
|
||||
func setENV(e string) {
|
||||
if len(e) > 0 {
|
||||
Env = e
|
||||
}
|
||||
}
|
||||
|
||||
func init() {
|
||||
setENV(os.Getenv("MARTINI_ENV"))
|
||||
}
|
||||
22
Godeps/_workspace/src/github.com/codegangsta/martini/env_test.go
generated
vendored
22
Godeps/_workspace/src/github.com/codegangsta/martini/env_test.go
generated
vendored
@@ -1,22 +0,0 @@
|
||||
package martini
|
||||
|
||||
import (
|
||||
"testing"
|
||||
)
|
||||
|
||||
func Test_SetENV(t *testing.T) {
|
||||
tests := []struct {
|
||||
in string
|
||||
out string
|
||||
}{
|
||||
{"", "development"},
|
||||
{"not_development", "not_development"},
|
||||
}
|
||||
|
||||
for _, test := range tests {
|
||||
setENV(test.in)
|
||||
if Env != test.out {
|
||||
expect(t, Env, test.out)
|
||||
}
|
||||
}
|
||||
}
|
||||
7
Godeps/_workspace/src/github.com/codegangsta/martini/go_version.go
generated
vendored
7
Godeps/_workspace/src/github.com/codegangsta/martini/go_version.go
generated
vendored
@@ -1,7 +0,0 @@
|
||||
// +build !go1.1
|
||||
|
||||
package martini
|
||||
|
||||
func MartiniDoesNotSupportGo1Point0() {
|
||||
"Martini requires Go 1.1 or greater."
|
||||
}
|
||||
20
Godeps/_workspace/src/github.com/codegangsta/martini/logger.go
generated
vendored
20
Godeps/_workspace/src/github.com/codegangsta/martini/logger.go
generated
vendored
@@ -1,20 +0,0 @@
|
||||
package martini
|
||||
|
||||
import (
|
||||
"log"
|
||||
"net/http"
|
||||
"time"
|
||||
)
|
||||
|
||||
// Logger returns a middleware handler that logs the request as it goes in and the response as it goes out.
|
||||
func Logger() Handler {
|
||||
return func(res http.ResponseWriter, req *http.Request, c Context, log *log.Logger) {
|
||||
start := time.Now()
|
||||
log.Printf("Started %s %s", req.Method, req.URL.Path)
|
||||
|
||||
rw := res.(ResponseWriter)
|
||||
c.Next()
|
||||
|
||||
log.Printf("Completed %v %s in %v\n", rw.Status(), http.StatusText(rw.Status()), time.Since(start))
|
||||
}
|
||||
}
|
||||
31
Godeps/_workspace/src/github.com/codegangsta/martini/logger_test.go
generated
vendored
31
Godeps/_workspace/src/github.com/codegangsta/martini/logger_test.go
generated
vendored
@@ -1,31 +0,0 @@
|
||||
package martini
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"log"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func Test_Logger(t *testing.T) {
|
||||
buff := bytes.NewBufferString("")
|
||||
recorder := httptest.NewRecorder()
|
||||
|
||||
m := New()
|
||||
// replace log for testing
|
||||
m.Map(log.New(buff, "[martini] ", 0))
|
||||
m.Use(Logger())
|
||||
m.Use(func(res http.ResponseWriter) {
|
||||
res.WriteHeader(http.StatusNotFound)
|
||||
})
|
||||
|
||||
req, err := http.NewRequest("GET", "http://localhost:3000/foobar", nil)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
m.ServeHTTP(recorder, req)
|
||||
expect(t, recorder.Code, http.StatusNotFound)
|
||||
refute(t, len(buff.String()), 0)
|
||||
}
|
||||
173
Godeps/_workspace/src/github.com/codegangsta/martini/martini.go
generated
vendored
173
Godeps/_workspace/src/github.com/codegangsta/martini/martini.go
generated
vendored
@@ -1,173 +0,0 @@
|
||||
// Package martini is a powerful package for quickly writing modular web applications/services in Golang.
|
||||
//
|
||||
// For a full guide visit http://github.com/codegangsta/martini
|
||||
//
|
||||
// package main
|
||||
//
|
||||
// import "github.com/codegangsta/martini"
|
||||
//
|
||||
// func main() {
|
||||
// m := martini.Classic()
|
||||
//
|
||||
// m.Get("/", func() string {
|
||||
// return "Hello world!"
|
||||
// })
|
||||
//
|
||||
// m.Run()
|
||||
// }
|
||||
package martini
|
||||
|
||||
import (
|
||||
"log"
|
||||
"net/http"
|
||||
"os"
|
||||
"reflect"
|
||||
|
||||
"github.com/codegangsta/inject"
|
||||
)
|
||||
|
||||
// Martini represents the top level web application. inject.Injector methods can be invoked to map services on a global level.
|
||||
type Martini struct {
|
||||
inject.Injector
|
||||
handlers []Handler
|
||||
action Handler
|
||||
logger *log.Logger
|
||||
}
|
||||
|
||||
// New creates a bare bones Martini instance. Use this method if you want to have full control over the middleware that is used.
|
||||
func New() *Martini {
|
||||
m := &Martini{Injector: inject.New(), action: func() {}, logger: log.New(os.Stdout, "[martini] ", 0)}
|
||||
m.Map(m.logger)
|
||||
m.Map(defaultReturnHandler())
|
||||
return m
|
||||
}
|
||||
|
||||
// Handlers sets the entire middleware stack with the given Handlers. This will clear any current middleware handlers.
|
||||
// Will panic if any of the handlers is not a callable function
|
||||
func (m *Martini) Handlers(handlers ...Handler) {
|
||||
m.handlers = make([]Handler, 0)
|
||||
for _, handler := range handlers {
|
||||
m.Use(handler)
|
||||
}
|
||||
}
|
||||
|
||||
// Action sets the handler that will be called after all the middleware has been invoked. This is set to martini.Router in a martini.Classic().
|
||||
func (m *Martini) Action(handler Handler) {
|
||||
validateHandler(handler)
|
||||
m.action = handler
|
||||
}
|
||||
|
||||
// Use adds a middleware Handler to the stack. Will panic if the handler is not a callable func. Middleware Handlers are invoked in the order that they are added.
|
||||
func (m *Martini) Use(handler Handler) {
|
||||
validateHandler(handler)
|
||||
|
||||
m.handlers = append(m.handlers, handler)
|
||||
}
|
||||
|
||||
// ServeHTTP is the HTTP Entry point for a Martini instance. Useful if you want to control your own HTTP server.
|
||||
func (m *Martini) ServeHTTP(res http.ResponseWriter, req *http.Request) {
|
||||
m.createContext(res, req).run()
|
||||
}
|
||||
|
||||
// Run the http server. Listening on os.GetEnv("PORT") or 3000 by default.
|
||||
func (m *Martini) Run() {
|
||||
port := os.Getenv("PORT")
|
||||
if port == "" {
|
||||
port = "3000"
|
||||
}
|
||||
|
||||
host := os.Getenv("HOST")
|
||||
|
||||
m.logger.Println("listening on " + host + ":" + port)
|
||||
m.logger.Fatalln(http.ListenAndServe(host+":"+port, m))
|
||||
}
|
||||
|
||||
func (m *Martini) createContext(res http.ResponseWriter, req *http.Request) *context {
|
||||
c := &context{inject.New(), m.handlers, m.action, NewResponseWriter(res), 0}
|
||||
c.SetParent(m)
|
||||
c.MapTo(c, (*Context)(nil))
|
||||
c.MapTo(c.rw, (*http.ResponseWriter)(nil))
|
||||
c.Map(req)
|
||||
return c
|
||||
}
|
||||
|
||||
// ClassicMartini represents a Martini with some reasonable defaults. Embeds the router functions for convenience.
|
||||
type ClassicMartini struct {
|
||||
*Martini
|
||||
Router
|
||||
}
|
||||
|
||||
// Classic creates a classic Martini with some basic default middleware - martini.Logger, martini.Recovery and martini.Static.
|
||||
// Classic also maps martini.Routes as a service.
|
||||
func Classic() *ClassicMartini {
|
||||
r := NewRouter()
|
||||
m := New()
|
||||
m.Use(Logger())
|
||||
m.Use(Recovery())
|
||||
m.Use(Static("public"))
|
||||
m.MapTo(r, (*Routes)(nil))
|
||||
m.Action(r.Handle)
|
||||
return &ClassicMartini{m, r}
|
||||
}
|
||||
|
||||
// Handler can be any callable function. Martini attempts to inject services into the handler's argument list.
|
||||
// Martini will panic if an argument could not be fullfilled via dependency injection.
|
||||
type Handler interface{}
|
||||
|
||||
func validateHandler(handler Handler) {
|
||||
if reflect.TypeOf(handler).Kind() != reflect.Func {
|
||||
panic("martini handler must be a callable func")
|
||||
}
|
||||
}
|
||||
|
||||
// Context represents a request context. Services can be mapped on the request level from this interface.
|
||||
type Context interface {
|
||||
inject.Injector
|
||||
// Next is an optional function that Middleware Handlers can call to yield the until after
|
||||
// the other Handlers have been executed. This works really well for any operations that must
|
||||
// happen after an http request
|
||||
Next()
|
||||
// Written returns whether or not the response for this context has been written.
|
||||
Written() bool
|
||||
}
|
||||
|
||||
type context struct {
|
||||
inject.Injector
|
||||
handlers []Handler
|
||||
action Handler
|
||||
rw ResponseWriter
|
||||
index int
|
||||
}
|
||||
|
||||
func (c *context) handler() Handler {
|
||||
if c.index < len(c.handlers) {
|
||||
return c.handlers[c.index]
|
||||
}
|
||||
if c.index == len(c.handlers) {
|
||||
return c.action
|
||||
}
|
||||
panic("invalid index for context handler")
|
||||
}
|
||||
|
||||
func (c *context) Next() {
|
||||
c.index += 1
|
||||
c.run()
|
||||
}
|
||||
|
||||
func (c *context) Written() bool {
|
||||
return c.rw.Written()
|
||||
}
|
||||
|
||||
func (c *context) run() {
|
||||
for c.index <= len(c.handlers) {
|
||||
_, err := c.Invoke(c.handler())
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
c.index += 1
|
||||
|
||||
if c.Written() {
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
141
Godeps/_workspace/src/github.com/codegangsta/martini/martini_test.go
generated
vendored
141
Godeps/_workspace/src/github.com/codegangsta/martini/martini_test.go
generated
vendored
@@ -1,141 +0,0 @@
|
||||
package martini
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"reflect"
|
||||
"testing"
|
||||
)
|
||||
|
||||
/* Test Helpers */
|
||||
func expect(t *testing.T, a interface{}, b interface{}) {
|
||||
if a != b {
|
||||
t.Errorf("Expected %v (type %v) - Got %v (type %v)", b, reflect.TypeOf(b), a, reflect.TypeOf(a))
|
||||
}
|
||||
}
|
||||
|
||||
func refute(t *testing.T, a interface{}, b interface{}) {
|
||||
if a == b {
|
||||
t.Errorf("Did not expect %v (type %v) - Got %v (type %v)", b, reflect.TypeOf(b), a, reflect.TypeOf(a))
|
||||
}
|
||||
}
|
||||
|
||||
func Test_New(t *testing.T) {
|
||||
m := New()
|
||||
if m == nil {
|
||||
t.Error("martini.New() cannot return nil")
|
||||
}
|
||||
}
|
||||
|
||||
func Test_Martini_Run(t *testing.T) {
|
||||
// just test that Run doesn't bomb
|
||||
go New().Run()
|
||||
}
|
||||
|
||||
func Test_Martini_ServeHTTP(t *testing.T) {
|
||||
result := ""
|
||||
response := httptest.NewRecorder()
|
||||
|
||||
m := New()
|
||||
m.Use(func(c Context) {
|
||||
result += "foo"
|
||||
c.Next()
|
||||
result += "ban"
|
||||
})
|
||||
m.Use(func(c Context) {
|
||||
result += "bar"
|
||||
c.Next()
|
||||
result += "baz"
|
||||
})
|
||||
m.Action(func(res http.ResponseWriter, req *http.Request) {
|
||||
result += "bat"
|
||||
res.WriteHeader(http.StatusBadRequest)
|
||||
})
|
||||
|
||||
m.ServeHTTP(response, (*http.Request)(nil))
|
||||
|
||||
expect(t, result, "foobarbatbazban")
|
||||
expect(t, response.Code, http.StatusBadRequest)
|
||||
}
|
||||
|
||||
func Test_Martini_Handlers(t *testing.T) {
|
||||
result := ""
|
||||
response := httptest.NewRecorder()
|
||||
|
||||
batman := func(c Context) {
|
||||
result += "batman!"
|
||||
}
|
||||
|
||||
m := New()
|
||||
m.Use(func(c Context) {
|
||||
result += "foo"
|
||||
c.Next()
|
||||
result += "ban"
|
||||
})
|
||||
m.Handlers(
|
||||
batman,
|
||||
batman,
|
||||
batman,
|
||||
)
|
||||
m.Action(func(res http.ResponseWriter, req *http.Request) {
|
||||
result += "bat"
|
||||
res.WriteHeader(http.StatusBadRequest)
|
||||
})
|
||||
|
||||
m.ServeHTTP(response, (*http.Request)(nil))
|
||||
|
||||
expect(t, result, "batman!batman!batman!bat")
|
||||
expect(t, response.Code, http.StatusBadRequest)
|
||||
}
|
||||
|
||||
func Test_Martini_EarlyWrite(t *testing.T) {
|
||||
result := ""
|
||||
response := httptest.NewRecorder()
|
||||
|
||||
m := New()
|
||||
m.Use(func(res http.ResponseWriter) {
|
||||
result += "foobar"
|
||||
res.Write([]byte("Hello world"))
|
||||
})
|
||||
m.Use(func() {
|
||||
result += "bat"
|
||||
})
|
||||
m.Action(func(res http.ResponseWriter) {
|
||||
result += "baz"
|
||||
res.WriteHeader(http.StatusBadRequest)
|
||||
})
|
||||
|
||||
m.ServeHTTP(response, (*http.Request)(nil))
|
||||
|
||||
expect(t, result, "foobar")
|
||||
expect(t, response.Code, http.StatusOK)
|
||||
}
|
||||
|
||||
func Test_Martini_Written(t *testing.T) {
|
||||
response := httptest.NewRecorder()
|
||||
|
||||
m := New()
|
||||
m.Handlers(func(res http.ResponseWriter) {
|
||||
res.WriteHeader(http.StatusOK)
|
||||
})
|
||||
|
||||
ctx := m.createContext(response, (*http.Request)(nil))
|
||||
expect(t, ctx.Written(), false)
|
||||
|
||||
ctx.run()
|
||||
expect(t, ctx.Written(), true)
|
||||
}
|
||||
|
||||
func Test_Martini_Basic_NoRace(t *testing.T) {
|
||||
m := New()
|
||||
handlers := []Handler{func() {}, func() {}}
|
||||
// Ensure append will not realloc to trigger the race condition
|
||||
m.handlers = handlers[:1]
|
||||
req, _ := http.NewRequest("GET", "/", nil)
|
||||
for i := 0; i < 2; i++ {
|
||||
go func() {
|
||||
response := httptest.NewRecorder()
|
||||
m.ServeHTTP(response, req)
|
||||
}()
|
||||
}
|
||||
}
|
||||
142
Godeps/_workspace/src/github.com/codegangsta/martini/recovery.go
generated
vendored
142
Godeps/_workspace/src/github.com/codegangsta/martini/recovery.go
generated
vendored
@@ -1,142 +0,0 @@
|
||||
package martini
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"net/http"
|
||||
"runtime"
|
||||
|
||||
"github.com/codegangsta/inject"
|
||||
)
|
||||
|
||||
const (
|
||||
panicHtml = `<html>
|
||||
<head><title>PANIC: %s</title>
|
||||
<style type="text/css">
|
||||
html, body {
|
||||
font-family: "Roboto", sans-serif;
|
||||
color: #333333;
|
||||
background-color: #ea5343;
|
||||
margin: 0px;
|
||||
}
|
||||
h1 {
|
||||
color: #d04526;
|
||||
background-color: #ffffff;
|
||||
padding: 20px;
|
||||
border-bottom: 1px dashed #2b3848;
|
||||
}
|
||||
pre {
|
||||
margin: 20px;
|
||||
padding: 20px;
|
||||
border: 2px solid #2b3848;
|
||||
background-color: #ffffff;
|
||||
}
|
||||
</style>
|
||||
</head><body>
|
||||
<h1>PANIC</h1>
|
||||
<pre style="font-weight: bold;">%s</pre>
|
||||
<pre>%s</pre>
|
||||
</body>
|
||||
</html>`
|
||||
)
|
||||
|
||||
var (
|
||||
dunno = []byte("???")
|
||||
centerDot = []byte("·")
|
||||
dot = []byte(".")
|
||||
slash = []byte("/")
|
||||
)
|
||||
|
||||
// stack returns a nicely formated stack frame, skipping skip frames
|
||||
func stack(skip int) []byte {
|
||||
buf := new(bytes.Buffer) // the returned data
|
||||
// As we loop, we open files and read them. These variables record the currently
|
||||
// loaded file.
|
||||
var lines [][]byte
|
||||
var lastFile string
|
||||
for i := skip; ; i++ { // Skip the expected number of frames
|
||||
pc, file, line, ok := runtime.Caller(i)
|
||||
if !ok {
|
||||
break
|
||||
}
|
||||
// Print this much at least. If we can't find the source, it won't show.
|
||||
fmt.Fprintf(buf, "%s:%d (0x%x)\n", file, line, pc)
|
||||
if file != lastFile {
|
||||
data, err := ioutil.ReadFile(file)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
lines = bytes.Split(data, []byte{'\n'})
|
||||
lastFile = file
|
||||
}
|
||||
fmt.Fprintf(buf, "\t%s: %s\n", function(pc), source(lines, line))
|
||||
}
|
||||
return buf.Bytes()
|
||||
}
|
||||
|
||||
// source returns a space-trimmed slice of the n'th line.
|
||||
func source(lines [][]byte, n int) []byte {
|
||||
n-- // in stack trace, lines are 1-indexed but our array is 0-indexed
|
||||
if n < 0 || n >= len(lines) {
|
||||
return dunno
|
||||
}
|
||||
return bytes.TrimSpace(lines[n])
|
||||
}
|
||||
|
||||
// function returns, if possible, the name of the function containing the PC.
|
||||
func function(pc uintptr) []byte {
|
||||
fn := runtime.FuncForPC(pc)
|
||||
if fn == nil {
|
||||
return dunno
|
||||
}
|
||||
name := []byte(fn.Name())
|
||||
// The name includes the path name to the package, which is unnecessary
|
||||
// since the file name is already included. Plus, it has center dots.
|
||||
// That is, we see
|
||||
// runtime/debug.*T·ptrmethod
|
||||
// and want
|
||||
// *T.ptrmethod
|
||||
// Also the package path might contains dot (e.g. code.google.com/...),
|
||||
// so first eliminate the path prefix
|
||||
if lastslash := bytes.LastIndex(name, slash); lastslash >= 0 {
|
||||
name = name[lastslash+1:]
|
||||
}
|
||||
if period := bytes.Index(name, dot); period >= 0 {
|
||||
name = name[period+1:]
|
||||
}
|
||||
name = bytes.Replace(name, centerDot, dot, -1)
|
||||
return name
|
||||
}
|
||||
|
||||
// Recovery returns a middleware that recovers from any panics and writes a 500 if there was one.
|
||||
// While Martini is in development mode, Recovery will also output the panic as HTML.
|
||||
func Recovery() Handler {
|
||||
return func(c Context, log *log.Logger) {
|
||||
defer func() {
|
||||
if err := recover(); err != nil {
|
||||
stack := stack(3)
|
||||
log.Printf("PANIC: %s\n%s", err, stack)
|
||||
|
||||
// Lookup the current responsewriter
|
||||
val := c.Get(inject.InterfaceOf((*http.ResponseWriter)(nil)))
|
||||
res := val.Interface().(http.ResponseWriter)
|
||||
|
||||
// respond with panic message while in development mode
|
||||
var body []byte
|
||||
if Env == Dev {
|
||||
res.Header().Set("Content-Type", "text/html")
|
||||
body = []byte(fmt.Sprintf(panicHtml, err, err, stack))
|
||||
}
|
||||
|
||||
res.WriteHeader(http.StatusInternalServerError)
|
||||
if nil != body {
|
||||
res.Write(body)
|
||||
}
|
||||
}
|
||||
}()
|
||||
|
||||
c.Next()
|
||||
}
|
||||
}
|
||||
49
Godeps/_workspace/src/github.com/codegangsta/martini/recovery_test.go
generated
vendored
49
Godeps/_workspace/src/github.com/codegangsta/martini/recovery_test.go
generated
vendored
@@ -1,49 +0,0 @@
|
||||
package martini
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"log"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func Test_Recovery(t *testing.T) {
|
||||
buff := bytes.NewBufferString("")
|
||||
recorder := httptest.NewRecorder()
|
||||
|
||||
setENV(Dev)
|
||||
m := New()
|
||||
// replace log for testing
|
||||
m.Map(log.New(buff, "[martini] ", 0))
|
||||
m.Use(func(res http.ResponseWriter, req *http.Request) {
|
||||
res.Header().Set("Content-Type", "unpredictable")
|
||||
})
|
||||
m.Use(Recovery())
|
||||
m.Use(func(res http.ResponseWriter, req *http.Request) {
|
||||
panic("here is a panic!")
|
||||
})
|
||||
m.ServeHTTP(recorder, (*http.Request)(nil))
|
||||
expect(t, recorder.Code, http.StatusInternalServerError)
|
||||
expect(t, recorder.HeaderMap.Get("Content-Type"), "text/html")
|
||||
refute(t, recorder.Body.Len(), 0)
|
||||
refute(t, len(buff.String()), 0)
|
||||
}
|
||||
|
||||
func Test_Recovery_ResponseWriter(t *testing.T) {
|
||||
recorder := httptest.NewRecorder()
|
||||
recorder2 := httptest.NewRecorder()
|
||||
|
||||
setENV(Dev)
|
||||
m := New()
|
||||
m.Use(Recovery())
|
||||
m.Use(func(c Context) {
|
||||
c.MapTo(recorder2, (*http.ResponseWriter)(nil))
|
||||
panic("here is a panic!")
|
||||
})
|
||||
m.ServeHTTP(recorder, (*http.Request)(nil))
|
||||
|
||||
expect(t, recorder2.Code, http.StatusInternalServerError)
|
||||
expect(t, recorder2.HeaderMap.Get("Content-Type"), "text/html")
|
||||
refute(t, recorder2.Body.Len(), 0)
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user