mirror of
https://github.com/flyinghead/flycast.git
synced 2026-11-11 23:54:10 -10:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
22e95de2d1 | ||
|
|
d5ddad53d1 | ||
|
|
4500cfb1d3 | ||
|
|
63485e7a72 | ||
|
|
77390f861e | ||
|
|
000f432548 | ||
|
|
a4b3e8dc05 | ||
|
|
f13d12a0b3 | ||
|
|
e4025420af | ||
|
|
4aa0bee20e | ||
|
|
6ba58fd695 | ||
|
|
2c1b46dfd9 | ||
|
|
4b58c695fc | ||
|
|
159d554c7d | ||
|
|
612928fedf | ||
|
|
9b38bcf079 | ||
|
|
4bd74aeebe | ||
|
|
d26d4d4cfa | ||
|
|
c2d1fbfdc2 | ||
|
|
d1aa96d3e1 | ||
|
|
ff4f5c21a8 | ||
|
|
dc3575a2ef | ||
|
|
67b29e4923 | ||
|
|
dbc6f5a43c | ||
|
|
28e9b27ec1 | ||
|
|
c8540e5be9 | ||
|
|
bedb8564f2 | ||
|
|
5abd36612d | ||
|
|
49a44b3cb0 | ||
|
|
157c837ec0 | ||
|
|
2b1aaf061d | ||
|
|
e4844a37c3 | ||
|
|
468b0109c8 | ||
|
|
361e67e0a4 | ||
|
|
211fa6e3b1 | ||
|
|
7d87829171 | ||
|
|
da1a800797 | ||
|
|
22adcee052 | ||
|
|
88beeb147d | ||
|
|
f84d31d84a | ||
|
|
1aa50faadf | ||
|
|
b18350652a | ||
|
|
58d3c1a037 | ||
|
|
da03a6bbce | ||
|
|
81707ea383 | ||
|
|
af7fbf47c0 | ||
|
|
2280e67c44 | ||
|
|
151c754281 | ||
|
|
b1575350d1 | ||
|
|
6409215a1a | ||
|
|
cf57f7abb4 | ||
|
|
286d6372b5 | ||
|
|
26b669cc8d | ||
|
|
97c487b06d | ||
|
|
5156d04b76 | ||
|
|
9ccaf18304 | ||
|
|
0dba81b99a | ||
|
|
7b615ad37c | ||
|
|
25c334e067 | ||
|
|
846edc61d3 | ||
|
|
aa33d230e5 | ||
|
|
1623086a48 | ||
|
|
0b2494b568 | ||
|
|
f3fde06548 | ||
|
|
51946d606a | ||
|
|
a674e6d61a | ||
|
|
223f818a33 | ||
|
|
0825ca5a4b | ||
|
|
3f53172873 | ||
|
|
763e0948c0 | ||
|
|
2c651298d5 | ||
|
|
bbe745da49 | ||
|
|
3d8183bb86 | ||
|
|
0a17c4333a | ||
|
|
3da30ba555 | ||
|
|
4f3cee2d87 | ||
|
|
8ebe44ea85 | ||
|
|
a5ff5c9473 | ||
|
|
8c69e6142e | ||
|
|
c1537ca3c8 | ||
|
|
b55fbef3a6 | ||
|
|
1cf68c7b38 | ||
|
|
5e35e7f746 | ||
|
|
778efcdf19 | ||
|
|
a56538babc | ||
|
|
c4715150cc | ||
|
|
15708686b9 | ||
|
|
229fa41b30 | ||
|
|
b7afa6a498 | ||
|
|
6a9cdd7633 | ||
|
|
85d806c355 | ||
|
|
ae91ea63e7 | ||
|
|
b4cc42bd2e | ||
|
|
7e3ee8ca26 | ||
|
|
d31f324212 | ||
|
|
269ac637d3 | ||
|
|
bce423e877 | ||
|
|
2da588b7bb | ||
|
|
35b7ce464c | ||
|
|
b326bc2843 | ||
|
|
01c419c63a | ||
|
|
b5dcc93766 | ||
|
|
aa80f4a852 | ||
|
|
4d8d5f68fc | ||
|
|
9d6adf8221 | ||
|
|
4058ecc737 | ||
|
|
734db8a743 | ||
|
|
5de530d68e | ||
|
|
a711b4e0e3 | ||
|
|
1414176b08 | ||
|
|
546c010517 | ||
|
|
b5d2811de4 | ||
|
|
f5bfa82fbd | ||
|
|
d4b76ff9e1 | ||
|
|
b787f590d3 | ||
|
|
c2c7af68bf | ||
|
|
ea1686df08 | ||
|
|
78a8a70073 | ||
|
|
261cfb13f3 | ||
|
|
66d8b96ae3 | ||
|
|
e22fd18ff8 | ||
|
|
44e80be303 | ||
|
|
c4a32e73c4 | ||
|
|
9d438c3ff3 | ||
|
|
c332985bd1 | ||
|
|
3da4c2eab1 | ||
|
|
6676a3456f | ||
|
|
4490934188 | ||
|
|
5022831093 | ||
|
|
554c86522e | ||
|
|
4743d8d31f | ||
|
|
59fbb66a66 | ||
|
|
bcf299cfd4 | ||
|
|
7e1f639d6f | ||
|
|
7d35000c18 | ||
|
|
528d0c6d7a | ||
|
|
eb3f1ca687 | ||
|
|
1a063b8f0d | ||
|
|
5cccea4a71 | ||
|
|
7bc1d7cdac | ||
|
|
fec60d0546 | ||
|
|
7f7387cf18 | ||
|
|
66c1047427 | ||
|
|
cd06c05bef | ||
|
|
b66de11664 | ||
|
|
b0c222bdd6 | ||
|
|
c2b2c7146b | ||
|
|
5548a9b6f8 | ||
|
|
e512eca05b | ||
|
|
891c0011bb | ||
|
|
387bf0a960 | ||
|
|
99389db89c | ||
|
|
607b9c41a0 | ||
|
|
c74215f1e8 | ||
|
|
126f65ec7a | ||
|
|
80ff2c600a | ||
|
|
0f3c95df4c | ||
|
|
c398edf22c | ||
|
|
2f846e912c | ||
|
|
f468fb0405 | ||
|
|
cd4447dd4b | ||
|
|
21d787bdd0 | ||
|
|
9c7c2b8637 | ||
|
|
7c29dcc9af | ||
|
|
8dd98be0ee | ||
|
|
dd6e7fae46 | ||
|
|
b9690ae0be | ||
|
|
d9c8074026 | ||
|
|
e4f227f213 | ||
|
|
925535141a | ||
|
|
9aa3b4b468 | ||
|
|
2e8bb02fed | ||
|
|
ec218b5d60 | ||
|
|
54ba0a06bf | ||
|
|
a38c13c0da | ||
|
|
9c1532d45a | ||
|
|
1e7e66aaeb | ||
|
|
09949d8dda | ||
|
|
e8b30fb3d9 | ||
|
|
e1b8463f10 | ||
|
|
8e7904b94b | ||
|
|
8cfa6f856c | ||
|
|
8e77ebce53 | ||
|
|
31acabbc8d | ||
|
|
c6f955b6a6 | ||
|
|
038a310e7e | ||
|
|
5a3d19d743 | ||
|
|
0a98cb590a | ||
|
|
a3261aaa70 | ||
|
|
09a70971af | ||
|
|
26a35e4937 | ||
|
|
26b3ea0b1c | ||
|
|
9ef206b90b | ||
|
|
8ce9b2397f | ||
|
|
fc48044323 | ||
|
|
ee81dd881e | ||
|
|
903b7b0240 | ||
|
|
09f1805a9c | ||
|
|
80e42e6c25 | ||
|
|
58a27e21e0 | ||
|
|
9e2a116bfd | ||
|
|
f51a461234 | ||
|
|
acaaf41ad5 | ||
|
|
e9142787b8 | ||
|
|
88b56b02a6 | ||
|
|
03d4f59a02 | ||
|
|
437da8cd77 | ||
|
|
40a085b841 | ||
|
|
93c56d803c | ||
|
|
08b34969aa | ||
|
|
cfb74c4ebf | ||
|
|
32c0aa4ac3 | ||
|
|
8388210b2b | ||
|
|
8ebf06e0da | ||
|
|
115504ed50 | ||
|
|
04eb34adc6 | ||
|
|
fa1c8bdb1c | ||
|
|
bc6870a9ca | ||
|
|
dcc5c6dce6 | ||
|
|
8dfc8f45f8 | ||
|
|
5e66c99233 | ||
|
|
dada5fb520 | ||
|
|
e7037fe638 | ||
|
|
2cbf70b7c6 | ||
|
|
38fedcab5f | ||
|
|
3ba9170ec8 | ||
|
|
08bed69c95 | ||
|
|
a05760260e | ||
|
|
55cc9d28db | ||
|
|
7d2a1d9556 | ||
|
|
a3728d146f | ||
|
|
e2dc6725bb | ||
|
|
e0e25d0668 | ||
|
|
1095ffbcf1 | ||
|
|
307344a3ec | ||
|
|
e30f181628 | ||
|
|
823cd76345 | ||
|
|
3fbc58cf0f | ||
|
|
d405d8157f | ||
|
|
e4deef3da2 | ||
|
|
531863bca4 | ||
|
|
6d6cf7d055 | ||
|
|
a1dfeb19e1 | ||
|
|
43def486b3 | ||
|
|
ac31cced87 | ||
|
|
0ae8e0ebc8 | ||
|
|
4084fd1ced | ||
|
|
4c67940eb5 | ||
|
|
2079ba2558 | ||
|
|
0d3172fd69 | ||
|
|
e938844387 | ||
|
|
fa09664ce5 | ||
|
|
fed435b4fb | ||
|
|
314298a4d9 | ||
|
|
0ea8f2290a | ||
|
|
d59197f843 | ||
|
|
16bee22105 | ||
|
|
4fbfb3bed9 | ||
|
|
7916cd63f3 | ||
|
|
bf9275f3d0 | ||
|
|
101952c38b | ||
|
|
d73d899898 | ||
|
|
f1bdc306e6 | ||
|
|
2a8b099ac5 | ||
|
|
8194c1e24a | ||
|
|
248bea39a9 | ||
|
|
ae5fa8c0e1 | ||
|
|
5d9757ffef | ||
|
|
9de2393bc0 | ||
|
|
0b5c991f0e | ||
|
|
74ca093da3 | ||
|
|
4759b4fafb | ||
|
|
b6aa26f5c9 | ||
|
|
2bd1c4c976 | ||
|
|
8ffb16df2b | ||
|
|
c5549a6106 | ||
|
|
24e9658a53 | ||
|
|
ff65c9679c | ||
|
|
c6f62c66bd | ||
|
|
50b5fedc5f | ||
|
|
c3b1e1087e | ||
|
|
88d4e73f03 | ||
|
|
370fa02b5c | ||
|
|
9e76688a6c | ||
|
|
2113dc503f | ||
|
|
1d3a0a633b | ||
|
|
f993a1aea7 | ||
|
|
45a3cff0d5 | ||
|
|
07c8e60ad7 | ||
|
|
937e28e04d | ||
|
|
948a3afcf6 | ||
|
|
2530cd330e | ||
|
|
3445276c60 | ||
|
|
260d9f7f57 | ||
|
|
911bade123 | ||
|
|
aba6278213 | ||
|
|
724109d02f | ||
|
|
ebeef1ddaf | ||
|
|
f0b7d92262 | ||
|
|
ee2a1b7d20 | ||
|
|
5f72bb34df | ||
|
|
99e4f8b47f | ||
|
|
edfe1600ce | ||
|
|
ded16cf484 | ||
|
|
b099888f5d | ||
|
|
868d77bf14 | ||
|
|
6241300c8f | ||
|
|
aaf23eae46 | ||
|
|
6ad8c9ac11 | ||
|
|
c01fad3f61 | ||
|
|
9639e47802 | ||
|
|
64e50d0dab | ||
|
|
c5c57b77ec | ||
|
|
42f4085ed1 | ||
|
|
f1ef4877b8 | ||
|
|
2d8f2dd6b0 | ||
|
|
fee9e5123a | ||
|
|
150a129818 | ||
|
|
aca3da42ab | ||
|
|
933a36b5c4 | ||
|
|
411aade5e2 | ||
|
|
a937428115 | ||
|
|
4e40430a13 | ||
|
|
122f1bbcb7 | ||
|
|
8b76e84654 | ||
|
|
809a1afa28 | ||
|
|
5b94408a63 | ||
|
|
4c965b883c | ||
|
|
9de771f30e | ||
|
|
207a063fa1 | ||
|
|
4492654a52 | ||
|
|
35e357ad66 | ||
|
|
8081a3d06a | ||
|
|
5fee692c31 | ||
|
|
5e25bfd507 | ||
|
|
8b683a77a6 | ||
|
|
4596bcc11b | ||
|
|
2f5bec2304 | ||
|
|
62cc877d69 | ||
|
|
91800aec5e | ||
|
|
1e80306577 | ||
|
|
dafc502274 | ||
|
|
ea80157d2e | ||
|
|
7f2bf9432d | ||
|
|
014daafa2a | ||
|
|
0ba8350c3a | ||
|
|
04db66dc6e | ||
|
|
9594444129 | ||
|
|
9162a927c4 | ||
|
|
164b93be98 | ||
|
|
a1a3d02d2c | ||
|
|
f8a18c3abe | ||
|
|
9fbf7c972b | ||
|
|
71b5e7ae93 | ||
|
|
78f45da8da | ||
|
|
1d0a297a45 | ||
|
|
e356515198 | ||
|
|
a687285c81 | ||
|
|
ecbe828cfa | ||
|
|
6b4deb4b16 | ||
|
|
e6ac0e4918 | ||
|
|
5fd8eb8903 | ||
|
|
f2622f07bb | ||
|
|
fbf049cff1 | ||
|
|
b64dab5e01 | ||
|
|
6097b6f5b0 | ||
|
|
cc1fdb28db | ||
|
|
d2524dea99 | ||
|
|
35cd0e1d38 | ||
|
|
27ee791d71 | ||
|
|
2b9926d397 | ||
|
|
73c75b7a79 | ||
|
|
acd0c58979 | ||
|
|
3640293f40 | ||
|
|
c354e09676 | ||
|
|
8dc18039be | ||
|
|
db1f4d24c5 | ||
|
|
03231f51f2 | ||
|
|
c29dd5d60b | ||
|
|
e9891118f7 | ||
|
|
08d40fe44f | ||
|
|
4b98fe2cb5 | ||
|
|
6da7b865d9 | ||
|
|
d085678817 | ||
|
|
1439200253 | ||
|
|
a6bfd58a00 | ||
|
|
f7a651f2a7 | ||
|
|
d90243a2c9 | ||
|
|
7924f11284 | ||
|
|
0e7fb27a8d | ||
|
|
9937875d38 | ||
|
|
2e3bb791ab | ||
|
|
19b23a411f | ||
|
|
6e65e8d565 | ||
|
|
c2b4f6b799 | ||
|
|
ccea066331 | ||
|
|
586c30b383 | ||
|
|
a7df171c0c | ||
|
|
37eb9d26c8 | ||
|
|
6e3ab6d62c | ||
|
|
6c123ad04b | ||
|
|
72c40fa61a | ||
|
|
a147b1023d | ||
|
|
d19e258ba1 | ||
|
|
1c30ca0dbf | ||
|
|
20b9239602 | ||
|
|
c583c59073 | ||
|
|
0529078510 | ||
|
|
48522a747f | ||
|
|
b7e9802e06 | ||
|
|
ec08d462b5 | ||
|
|
ebe56d6778 | ||
|
|
7d32a66044 | ||
|
|
f2961bd779 | ||
|
|
39a0417d5b | ||
|
|
256347d947 | ||
|
|
3bb036741b | ||
|
|
8d8cf6da00 | ||
|
|
6a757bb43e | ||
|
|
0567e8a117 | ||
|
|
31d6b7e3f1 | ||
|
|
0847b8b7e6 | ||
|
|
0c012d4e8e | ||
|
|
788e48bde3 | ||
|
|
3954d719f5 | ||
|
|
ba9094747f | ||
|
|
a6407a52b4 | ||
|
|
f3f172c64d | ||
|
|
97fb628797 | ||
|
|
8a34119c5d | ||
|
|
deba6cbcd1 | ||
|
|
b14440970b | ||
|
|
20291c57e8 | ||
|
|
60df320f4c | ||
|
|
ad4ecbab0e | ||
|
|
78ad0d6044 | ||
|
|
ac2501549f | ||
|
|
9d248886ba | ||
|
|
504bf1b299 | ||
|
|
d6369f9d04 | ||
|
|
8047074982 | ||
|
|
ee88660820 | ||
|
|
843d667740 | ||
|
|
2f902ed5e2 | ||
|
|
4c034740ea | ||
|
|
a33eb1dc77 | ||
|
|
d320b4a82e | ||
|
|
cf7ccb77d4 | ||
|
|
65f967dc22 | ||
|
|
40c4570271 | ||
|
|
4b148a7055 | ||
|
|
34c9e6f6ea | ||
|
|
1698b21ac6 | ||
|
|
5438e15bf4 | ||
|
|
2a150ef61c | ||
|
|
54e3a0e4e0 | ||
|
|
ca3de641e2 | ||
|
|
1c813524b4 | ||
|
|
c806c30937 | ||
|
|
4719756522 | ||
|
|
93829978f2 | ||
|
|
839ddd0c40 | ||
|
|
1440b0ef6c | ||
|
|
4903152e18 | ||
|
|
ba6cb99c2e | ||
|
|
82de3d2249 | ||
|
|
386a28e79f | ||
|
|
d45603c2e0 | ||
|
|
4d3ccfe5bf | ||
|
|
6701025187 | ||
|
|
35840a1eda | ||
|
|
5eea059b09 | ||
|
|
ebeb0d0551 | ||
|
|
a75307240d | ||
|
|
b95826d4d3 | ||
|
|
f670a39787 | ||
|
|
21a8a54f88 | ||
|
|
bac4ee15ec | ||
|
|
4e92bfa5c1 | ||
|
|
44cffbb4c4 | ||
|
|
8ce6a9e539 | ||
|
|
7ec35ef3c2 | ||
|
|
ea329b064e | ||
|
|
da60601205 | ||
|
|
478f8586bb | ||
|
|
ef2fe430ff | ||
|
|
8249d2dc28 | ||
|
|
f1b384ac2e | ||
|
|
3f4a97ecc1 | ||
|
|
c013264a28 | ||
|
|
631c5bae5b | ||
|
|
9927a8dae0 | ||
|
|
7158b640c9 | ||
|
|
fa2b229c95 | ||
|
|
326fcec485 | ||
|
|
06c3ded68e | ||
|
|
0b7a2cfd86 | ||
|
|
0a95f966d5 | ||
|
|
6d82495ed5 | ||
|
|
5f9c75a414 | ||
|
|
b1bcef83ea | ||
|
|
3d7b8570b6 | ||
|
|
88eea7f0e9 | ||
|
|
f536c67f26 | ||
|
|
d53fb51d25 | ||
|
|
a2b8aba035 | ||
|
|
985297183a | ||
|
|
11cc6e6ccf | ||
|
|
5c0601dd2e | ||
|
|
339ed77516 | ||
|
|
02193e2441 | ||
|
|
04617a9b0c | ||
|
|
095841ff5b | ||
|
|
a9dc01de57 | ||
|
|
51e5db0d50 | ||
|
|
5e53dba12c | ||
|
|
47d8e667e7 | ||
|
|
c9a10451b7 | ||
|
|
eaac86808f | ||
|
|
eddea4395c | ||
|
|
0a45f17839 | ||
|
|
cdb5d004d1 | ||
|
|
948118b8de | ||
|
|
31bd0f5742 | ||
|
|
7ecf7d5727 | ||
|
|
be3ce5492d | ||
|
|
85367467d6 | ||
|
|
faa14cdfec | ||
|
|
a39eff8bd0 | ||
|
|
93f2ea362d | ||
|
|
f68fbef987 | ||
|
|
052fd88b32 | ||
|
|
b82b965a96 | ||
|
|
8655cae995 | ||
|
|
da4b94f787 | ||
|
|
7ac2698f70 | ||
|
|
7f1f97c68f | ||
|
|
0db807a17a | ||
|
|
93bbffadb6 | ||
|
|
44b8937a4f | ||
|
|
e5b9a879f5 | ||
|
|
ba6b83e824 | ||
|
|
b92d826284 | ||
|
|
818f58d07b | ||
|
|
8b8e36edf9 | ||
|
|
64108864a7 | ||
|
|
f599fcf2f4 | ||
|
|
be1c4374fa | ||
|
|
ccd4157aff | ||
|
|
65c1b947a4 | ||
|
|
da7c82c02d | ||
|
|
88f0b8b6c2 | ||
|
|
aa9f842110 | ||
|
|
0f96a5a47b | ||
|
|
c45eb4e8d0 | ||
|
|
a3d1a2a16e | ||
|
|
f8e23a2b1c | ||
|
|
ec13746af7 | ||
|
|
f5586ba47f | ||
|
|
17b1d51f4b | ||
|
|
7321808090 | ||
|
|
e7a0e78803 | ||
|
|
39ad0ac92d | ||
|
|
ffdf036684 | ||
|
|
540fd32089 | ||
|
|
10a8a15cd3 | ||
|
|
1ded3dffdd | ||
|
|
b5004bc5b5 | ||
|
|
3bdb4fafe9 | ||
|
|
14b4ed6bdf | ||
|
|
e700972350 | ||
|
|
6bc6328a25 | ||
|
|
b546e7a75d | ||
|
|
16702f9c38 | ||
|
|
d3d6c100dc | ||
|
|
90db7054a4 | ||
|
|
65db3bedf2 | ||
|
|
5a741af03d | ||
|
|
e308c0b5c7 | ||
|
|
b31297e452 | ||
|
|
c318eb8bda | ||
|
|
8469baa39e | ||
|
|
3ab88a71ab | ||
|
|
8a48d95370 | ||
|
|
30f06e699c | ||
|
|
875bd15750 | ||
|
|
fad989a19a | ||
|
|
98eec3e49f | ||
|
|
10b9df33ea | ||
|
|
3595152cc4 | ||
|
|
208aa20c18 | ||
|
|
ecc122f0c4 | ||
|
|
6b5c041725 | ||
|
|
da9faf7efb | ||
|
|
bf5f59833a | ||
|
|
734f03bfcd | ||
|
|
df50719777 | ||
|
|
b98b087435 | ||
|
|
ee254ea23d | ||
|
|
fd69686f78 | ||
|
|
b8335773d3 | ||
|
|
c3a7260dc1 | ||
|
|
52199df953 | ||
|
|
60d3521d47 | ||
|
|
9281d2f2ad | ||
|
|
4d322feacc | ||
|
|
d9233b3440 | ||
|
|
89ab2420c9 | ||
|
|
5485f2f16e | ||
|
|
188d7cbe4f | ||
|
|
3f62290596 | ||
|
|
bf6fd5fd09 | ||
|
|
dd78ed1c88 | ||
|
|
a28c50a13d | ||
|
|
4782c144f0 | ||
|
|
e4c0e8ec61 | ||
|
|
4368f327ae | ||
|
|
24c4c04945 | ||
|
|
1e798727d3 | ||
|
|
eb1772ec2c | ||
|
|
87e409b3cc | ||
|
|
853db5110e | ||
|
|
ec57499863 | ||
|
|
1e6c050d3d | ||
|
|
858bd2c40b | ||
|
|
f59da370b5 | ||
|
|
d68e72b37b | ||
|
|
147e948b37 | ||
|
|
e668e8068c | ||
|
|
20fb9db652 | ||
|
|
9af23e0276 | ||
|
|
4c6bc0349f | ||
|
|
37d9060b17 | ||
|
|
e46993f96c | ||
|
|
7f095cdb2d | ||
|
|
5511bee9ef | ||
|
|
af3e064269 | ||
|
|
8332d171da | ||
|
|
0ee5b52b52 | ||
|
|
cb522d8352 | ||
|
|
ae6d694c52 | ||
|
|
e70b71828c | ||
|
|
7cd08c13ed | ||
|
|
94879b0cac | ||
|
|
7a1323699a | ||
|
|
81466f1591 | ||
|
|
153af36869 | ||
|
|
66d0312f37 | ||
|
|
b728b0dfb5 | ||
|
|
631b4aaeea | ||
|
|
83b94874a3 | ||
|
|
5ca3b4e3dc | ||
|
|
8db0f80602 | ||
|
|
55d5e31a55 | ||
|
|
77bcb8de7f | ||
|
|
ed633dc37b | ||
|
|
61c0c39300 | ||
|
|
ddfa2ebbe3 | ||
|
|
ba8d7dbde6 | ||
|
|
a3ea5bfe31 | ||
|
|
6564f70cbc | ||
|
|
f69ced47e4 | ||
|
|
747652677f | ||
|
|
5e10391508 | ||
|
|
dc606a83a1 | ||
|
|
42019289c2 | ||
|
|
efd7183985 | ||
|
|
0915a12d72 | ||
|
|
b5684e9498 | ||
|
|
564bb6837f | ||
|
|
96c9a03374 | ||
|
|
436fd57609 | ||
|
|
04addad42d | ||
|
|
19dc9e2247 | ||
|
|
76852783a7 | ||
|
|
bf4e05391c | ||
|
|
92f6ad350f | ||
|
|
98bc58215d | ||
|
|
8bf4e150d3 | ||
|
|
de21b3d45c | ||
|
|
5536f580e4 | ||
|
|
7e43deb868 | ||
|
|
50844c5e4c | ||
|
|
96ffc3a524 | ||
|
|
4b32807c28 | ||
|
|
2e294c4642 | ||
|
|
d214a50905 | ||
|
|
2520685509 | ||
|
|
862aab542f | ||
|
|
46577c0957 | ||
|
|
67616a60ce | ||
|
|
310906d1b5 | ||
|
|
46a4312d73 | ||
|
|
d85de18b31 | ||
|
|
5ceb1cab7b | ||
|
|
5f8f4f9e3b | ||
|
|
362c652d6c | ||
|
|
7944355f10 | ||
|
|
e315c8c2ee | ||
|
|
a3c1734d94 | ||
|
|
7211873442 | ||
|
|
e6fb44fba4 | ||
|
|
896c5d79c7 | ||
|
|
e04e39fa90 | ||
|
|
c9c71028a9 | ||
|
|
15c6e731b5 | ||
|
|
1d9ec43b22 | ||
|
|
f571b187b0 | ||
|
|
5022ae4bd6 | ||
|
|
60de1f6c25 | ||
|
|
2716bdcee8 | ||
|
|
250443b172 | ||
|
|
ca49ddb369 | ||
|
|
4a89d5a75b | ||
|
|
754106a6f7 | ||
|
|
6dd721e97f | ||
|
|
a0ff5d68fd | ||
|
|
35ad9bfdee | ||
|
|
20422ef8c4 | ||
|
|
75c2ae1e55 | ||
|
|
4c0491552f | ||
|
|
6df7f8912c | ||
|
|
4045b9a15f | ||
|
|
3e33efa3ca | ||
|
|
5bc849f3f0 | ||
|
|
8a9a5af00d | ||
|
|
2403d13440 | ||
|
|
208bcc0d79 | ||
|
|
f3416fda81 | ||
|
|
036be4085a | ||
|
|
5b9dbd9fa3 | ||
|
|
191a5dfcdf | ||
|
|
7e8bc2972b | ||
|
|
0c11acb931 | ||
|
|
e1970cf01d | ||
|
|
800526ddcd | ||
|
|
d839e8d70d | ||
|
|
841ed659ae | ||
|
|
b24e401e2f | ||
|
|
18e5bd7c95 | ||
|
|
babaf41482 | ||
|
|
8284f55b68 | ||
|
|
1cb31dd932 | ||
|
|
252df2cc95 | ||
|
|
c4dc18f1c1 | ||
|
|
c94dd2e223 | ||
|
|
d6c8429446 | ||
|
|
79bca874b7 | ||
|
|
fd17b52792 | ||
|
|
14b5f9ef06 | ||
|
|
ae5394f6b6 | ||
|
|
3beb22b25c | ||
|
|
00f55b5b4b | ||
|
|
34ca48a484 | ||
|
|
50466eb9ec | ||
|
|
0d91b53706 | ||
|
|
57212196fb | ||
|
|
d032bc4a24 | ||
|
|
5771dedac8 | ||
|
|
4dac3a6800 | ||
|
|
84326bb12a | ||
|
|
1543474366 | ||
|
|
cbfda5a767 | ||
|
|
b41bb39c0e | ||
|
|
5a955dac3d | ||
|
|
c655c51da2 | ||
|
|
faaa8d3630 | ||
|
|
b7177e742a |
No files matched your search
+41
@@ -8,3 +8,44 @@ obj/
|
||||
|
||||
newdc/android/libnewdc/bin/libnewdc.jar
|
||||
newdc/android/libnewdc/bin/classes/com/example/newdc/JNIdc.class
|
||||
|
||||
shell/android/assets/build
|
||||
shell/android/tools
|
||||
|
||||
# iOS/Xcode general stuff
|
||||
.DS_Store
|
||||
*/build/*
|
||||
**/build/*
|
||||
*.pbxuser
|
||||
!default.pbxuser
|
||||
*.mode1v3
|
||||
!default.mode1v3
|
||||
*.mode2v3
|
||||
!default.mode2v3
|
||||
*.perspectivev3
|
||||
!default.perspectivev3
|
||||
xcuserdata
|
||||
profile
|
||||
*.moved-aside
|
||||
DerivedData
|
||||
.idea/
|
||||
*.hmap
|
||||
emulator.xccheckout
|
||||
reicast.xccheckout
|
||||
build/*
|
||||
*.so
|
||||
*Karen_angelXwind*
|
||||
local.properties
|
||||
ant.properties
|
||||
*build_obj
|
||||
Workdir/data
|
||||
Workdir/reicast*
|
||||
Workdir/vmu*
|
||||
Workdir/webui*
|
||||
Workdir/emu.cfg
|
||||
Workdir/lib*ant.properties
|
||||
|
||||
# Linux stuff
|
||||
shell/lin86/.map
|
||||
shell/lin86/nosym-reicast.elf
|
||||
shell/lin86/reicast.elf
|
||||
+55
@@ -0,0 +1,55 @@
|
||||
notifications:
|
||||
irc: chat.freenode.net#reicast
|
||||
language: cpp
|
||||
compiler: gcc
|
||||
before_install:
|
||||
- openssl aes-256-cbc -K $encrypted_c726d225a9d9_key -iv $encrypted_c726d225a9d9_iv
|
||||
-in debug.keystore.enc -out debug.keystore -d
|
||||
- sudo apt-get install aria2 -qq
|
||||
- download_extract() { aria2c -x 16 $1 -o $2 && tar -xf $2; }
|
||||
- download_extract_zip() { aria2c -x 16 $1 -o $2 && unzip -qq $2; }
|
||||
- sudo apt-get -qq update
|
||||
- sudo apt-get -qq -y install openjdk-7-jdk ant lib32z1-dev lib32stdc++6
|
||||
- GIT_HASH=`git log --pretty=format:'%h' -n 1`
|
||||
- GIT_BUILD=`git describe --all`-$GIT_HASH
|
||||
install:
|
||||
- download_extract http://dl.google.com/android/ndk/android-ndk-r9c-linux-x86_64.tar.bz2
|
||||
android-ndk-r9c-linux-x86_64.tar.bz2
|
||||
- download_extract_zip http://dl.google.com/android/adt/adt-bundle-linux-x86_64-20131030.zip
|
||||
adt-bundle-linux-x86_64-20131030.zip
|
||||
- mv android-ndk-r9c android-ndk
|
||||
- mv adt-bundle-linux-x86_64-20131030/sdk/ android-sdk
|
||||
- rm android-ndk-r9c-linux-x86_64.tar.bz2
|
||||
- rm adt-bundle-linux-x86_64-20131030.zip
|
||||
- export ANDROID_HOME=$(pwd)/android-sdk
|
||||
- export NDK=$(pwd)/android-ndk
|
||||
- export ANDROID_NDK=$(pwd)/android-ndk
|
||||
- export PATH=${PATH}:$ANDROID_HOME/tools
|
||||
- export PATH=${PATH}:$ANDROID_HOME/platform-tools
|
||||
- export PATH=${PATH}:$NDK
|
||||
- mkdir -p ~/.android
|
||||
- mv debug.keystore ~/.android/debug.keystore
|
||||
before_script:
|
||||
script:
|
||||
- cd shell/android
|
||||
- android update project -p . --target "android-19"
|
||||
- export NUMBER_OF_PROCESSORS=2
|
||||
- ant debug
|
||||
before_deploy:
|
||||
- cd ../../
|
||||
- mkdir -p artifacts/$GIT_BUILD/
|
||||
- cp shell/android/bin/reicast-debug.apk artifacts/$GIT_BUILD/reicast-android-debug-$GIT_HASH.apk
|
||||
deploy:
|
||||
provider: s3
|
||||
access_key_id: AKIAJR5J3OHAQUP5BHHQ
|
||||
secret_access_key:
|
||||
secure: dDmBiadS1cc2XCWWDZ1kwZGIoLkwEOLsdi5nzVdn1dHMsEKxN3u+3WFuuOfJHZYcdrtN7VhojCarPa+eGDDeiVme4m3y+QKMbI9lecHX9+t4jDNUyYep5TpeIVUkZ7fj4JsMi7U9/YFBTg7QnqvVsMAHE9vobkvjegjAYToBrlM=
|
||||
bucket: reicast-builds
|
||||
local-dir: artifacts
|
||||
upload-dir: builds
|
||||
skip_cleanup: true
|
||||
on:
|
||||
all_branches: true
|
||||
repo: reicast/reicast-emulator
|
||||
after_deploy:
|
||||
- echo "done"
|
||||
@@ -1,8 +1,8 @@
|
||||
reicast
|
||||
===========
|
||||
reicast is a sega dreamcast emulator
|
||||
reicast is a multi-platform Sega Dreamcast emulator.
|
||||
|
||||
This is developer oriented resource, if you just want bins head over to http://reicast.com
|
||||
This is a developer-oriented resource, if you just want bins head over to http://reicast.com/
|
||||
|
||||
Caution
|
||||
-------
|
||||
@@ -16,29 +16,91 @@ If you are interested into further porting/adapting/whatever, *please* don't for
|
||||
|
||||
Let's try to keep everything under a single project :)
|
||||
|
||||
To build for android
|
||||
Building for Android
|
||||
--------------------
|
||||
Tools required:
|
||||
* Latest Android SDK and NDK (duh)
|
||||
* Latest Android SDK
|
||||
- http://developer.android.com/sdk/index.html
|
||||
* NDK r8b or newer
|
||||
- https://developer.android.com/tools/sdk/ndk/index.html
|
||||
- If are not using r9c+, comment the "NDK_TOOLCHAIN_VERSION := 4.8" in shell/android/jni/Application.mk and shell/android/xperia/jni/Application.mk
|
||||
* Android 4.4 (API 19) & Android 2.3.1 (API 9)
|
||||
- http://developer.android.com/sdk/installing/adding-packages.html
|
||||
- note that API 9 is hidden (you must check to show obsolete in SDK manager)
|
||||
* Ant
|
||||
- http://ant.apache.org/
|
||||
|
||||
From project root directory:
|
||||
```
|
||||
cd shell\android
|
||||
android update project -p .
|
||||
export ANDROID_NDK=/ # Type the full path to your NDK here
|
||||
|
||||
ndk-build -j 4
|
||||
cd shell/android/
|
||||
|
||||
android update project -p . --target "android-19"
|
||||
|
||||
ant debug
|
||||
```
|
||||
|
||||
Building for iOS
|
||||
----------------
|
||||
Tools required:
|
||||
* Latest Xcode
|
||||
- https://developer.apple.com/xcode/downloads/
|
||||
* An iOS device (reicast will not compile for the iOS Simulator)
|
||||
* iOS 5.x ~ 7.x
|
||||
* iOSOpenDev if developing without an official Apple certificate
|
||||
- http://iosopendev.com/download/
|
||||
|
||||
From project root directory:
|
||||
|
||||
```
|
||||
cd shell/ios/
|
||||
|
||||
xcodebuild -configuration Release
|
||||
```
|
||||
|
||||
Building for Linux
|
||||
------------------
|
||||
|
||||
The code is only currently compatible with 32bit architectures so you will need
|
||||
to install 32bit libs to build reicast.
|
||||
|
||||
Requirements:
|
||||
* build-essential
|
||||
* libasound
|
||||
* libegl1-mesa-dev
|
||||
* libgles2-mesa-dev
|
||||
* libasound2-dev
|
||||
|
||||
To build the project, go to shell/lin86 and run make
|
||||
|
||||
|
||||
Translations
|
||||
------------
|
||||
New and updated translations are always appreciated!
|
||||
All we ask is that you not use “regional” phrases that may not be generally understood.
|
||||
|
||||
Translations can be submitted as a pull request
|
||||
|
||||
|
||||
Beta versions
|
||||
-------------
|
||||
[](https://travis-ci.org/reicast/reicast-emulator)
|
||||
|
||||
Official builds from the reicast ci service can be found at http://builds.reicast.com/
|
||||
|
||||
Additional builds (iOS & android) can be found at [angelxwind's](http://reicast.angelxwind.net/) buildbot
|
||||
|
||||
|
||||
Donations and stuff
|
||||
-------------------
|
||||
Well, glad you liked the project so far!
|
||||
|
||||
We're currently short on hardware
|
||||
We're currently short on hardware.
|
||||
|
||||
If you would like to donate some devices, get in touch at team@reicast.com. GLES3 capable stuff, some mainstream hardware and rarities would be extremely appreciated.
|
||||
If you would like to donate some devices, get in touch at team@reicast.com.
|
||||
GLES3 capable stuff, some mainstream hardware and rarities would be extremely
|
||||
appreciated.
|
||||
Keep in mind we're located in Greece for the most part
|
||||
|
||||
This has been tested/developed on
|
||||
@@ -48,33 +110,51 @@ This has been tested/developed on
|
||||
* Some Chinese tablet
|
||||
* OUYA
|
||||
* Various development boards
|
||||
* gcw zero
|
||||
* GCW Zero
|
||||
|
||||
We had to buy all of these, except the gcw zero and a beaglebone which were donated (thanks! You rock!)
|
||||
We had to buy all of these, except the GCW Zero and a BeagleBone which were
|
||||
donated (Thanks! You rock!)
|
||||
|
||||
Apart from that, we don't accept monetary donations right now.
|
||||
We also don't plan to be releasing a premium version at any store.
|
||||
Most of the project has been developed by drk||Raziel (aka, skmp, drk, Raz, etc) but it has been based on the
|
||||
works of multiple people. It would be extremely unfair to charge for it and get all the credit :)
|
||||
Most of the project has been developed by drk||Raziel (aka, skmp, drk, Raz,
|
||||
etc) but it has been based on the works of multiple people. It would be
|
||||
extremely unfair to charge for it and get all the credit :)
|
||||
|
||||
We're planning for an indiegogo campaign later on to help with sustained
|
||||
development and running costs, so follow @reicastdc on twitter for updates
|
||||
|
||||
We're planning for an indiegogo campaign later on to help with sustained development and running costs, so follow @reicastdc on twitter for updates
|
||||
Other Testing
|
||||
-------------
|
||||
These devices are tested by Karen/angelXwind:
|
||||
* Apple iPhone 4 GSM Rev0 (N90AP)
|
||||
* Apple iPhone 4 CDMA (N92AP)
|
||||
* Apple iPod touch 4 (N81AP)
|
||||
* Apple iPod touch 3G (N18AP)
|
||||
* Apple iPhone 3GS (N88AP)
|
||||
* Sony Xperia X10a (es209ra)
|
||||
* Amazon Kindle Fire HD 7 (tate-pvt-08)
|
||||
|
||||
These devices are tested by contributors regularly:
|
||||
* Nvidia Shield
|
||||
* Nexus 5 / 7
|
||||
* Xperia Play
|
||||
|
||||
Team
|
||||
----
|
||||
|
||||
You can check the currently active committers on [the pretty graphs page](https://github.com/reicast/reicast-emulator/graphs/contributors)
|
||||
|
||||
Chat on freenode #reicast.
|
||||
Our IRC channel is [#reicast @ chat.freenode.net](irc://chat.freenode.net/reicast).
|
||||
|
||||
The original reicast team consisted of drk||Raziel (mostly just writing code), PsyMan (debugging/testing and everything else) and a little bit of gb_away
|
||||
The original reicast team consisted of drk||Raziel (mostly just writing code),
|
||||
PsyMan (debugging/testing and everything else) and a little bit of gb_away
|
||||
|
||||
|
||||
Special thanks
|
||||
--------------
|
||||
In previous iterations a lot of people have worked on this, notably David Miller (aka, ZeZu), the nullDC team, friends from #pcsx2 and all over the world :)
|
||||
|
||||
In previous iterations a lot of people have worked on this, notably David
|
||||
Miller (aka, ZeZu), the nullDC team, friends from #pcsx2 and all over the world :)
|
||||
|
||||
[](https://bitdeli.com/free "Bitdeli Badge")
|
||||
|
||||
@@ -0,0 +1,398 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset=utf-8 http-equiv="Content-Language" content="en"/>
|
||||
<title>Minimal Websocket test app</title>
|
||||
<style type="text/css">
|
||||
div.title { font-size:18pt; font: Arial; font-weight:normal; text-align:center; color:#000000; }
|
||||
.browser { font-size:18pt; font: Arial; font-weight:normal; text-align:center; color:#ffff00; vertical-align:middle; text-align:center; background:#d0b070; padding:12px; -webkit-border-radius:10px; -moz-border-radius:10px; border-radius:10px;}
|
||||
.group2 { width:600px; vertical-align:middle; text-align:center; background:#f0f0e0; padding:12px; -webkit-border-radius:10px; -moz-border-radius:10px; border-radius:10px; }
|
||||
.explain { vertical-align:middle; text-align:center; background:#f0f0c0; padding:12px; -webkit-border-radius:10px; -moz-border-radius:10px; border-radius:10px; color:#404000; }
|
||||
.content { vertical-align:top; text-align:center; background:#fffff0; padding:12px; -webkit-border-radius:10px; -moz-border-radius:10px; border-radius:10px; }
|
||||
.canvas { vertical-align:top; text-align:center; background:#efefd0; padding:12px; -webkit-border-radius:10px; -moz-border-radius:10px; border-radius:10px; }
|
||||
</style>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<header></header>
|
||||
<article>
|
||||
|
||||
<table><tr><td>
|
||||
|
||||
<table width="100%"><tr><td valign=middle align=center><a href="http://libwebsockets.org"><img src="/libwebsockets.org-logo.png"></a></td><td>
|
||||
<section class="browser">Detected Browser: <div id=brow>...</div></section></td></tr></table>
|
||||
|
||||
</td></tr><tr><td>
|
||||
|
||||
<section id="increment" class="group2">
|
||||
<div class="title">libwebsockets "dumb-increment-protocol"</div>
|
||||
<table><tr><td>
|
||||
<table class="content" width="200px">
|
||||
<tr><td align=center><input type=button id=offset value="Reset counter" onclick="reset();" ></td></tr>
|
||||
<tr><td width=200px align=center><div id=number> </div></td></tr>
|
||||
<tr><td id=wsdi_statustd align=center class="explain"><div id=wsdi_status>Not initialized</div></td></tr>
|
||||
</tr>
|
||||
</table>
|
||||
</td><td class="explain">
|
||||
The incrementing number is coming from the server and is individual for
|
||||
each connection to the server... try opening a second browser window.
|
||||
<br/><br/>
|
||||
The button zeros just this connection's number.
|
||||
<br/><br/>
|
||||
|
||||
</td></tr></table>
|
||||
</section>
|
||||
<br>
|
||||
<section id="mirror" class="group2">
|
||||
<div class="title">libwebsockets "lws-mirror-protocol"</div>
|
||||
<div class="explain">
|
||||
Use the mouse to draw on the canvas below -- all other browser windows open
|
||||
on this page see your drawing in realtime and you can see any of theirs as
|
||||
well.
|
||||
<br/><br/>
|
||||
The lws-mirror protocol doesn't interpret what is being sent to it, it just
|
||||
re-sends it to every other websocket it has a connection with using that
|
||||
protocol, including the guy who sent the packet.
|
||||
<br/><br/>
|
||||
<b>libwebsockets-test-client</b> joins in by spamming circles on to this shared canvas when
|
||||
run.
|
||||
</div>
|
||||
<table class="content">
|
||||
<tr>
|
||||
<td>Drawing color:
|
||||
<select id="color" onchange="update_color();">
|
||||
<option value=#000000>Black</option>
|
||||
<option value=#0000ff>Blue</option>
|
||||
<option value=#20ff20>Green</option>
|
||||
<option value=#802020>Dark Red</option>
|
||||
</select>
|
||||
</td>
|
||||
<td id=wslm_statustd align=center class="explain"><div id=wslm_status>Not initialized</div></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colspan=2 width=500 class="content">
|
||||
<div id="wslm_drawing">
|
||||
</div></td>
|
||||
</tr>
|
||||
</table>
|
||||
</section>
|
||||
|
||||
</td></tr><tr><td>
|
||||
Looking for support? <a href="http://libwebsockets.org">http://libwebsockets.org</a><br/>
|
||||
Join the mailing list: <a href="http://ml.libwebsockets.org/mailman/listinfo/libwebsockets">http://ml.libwebsockets.org/mailman/listinfo/libwebsockets</a>
|
||||
|
||||
</td></tr></table>
|
||||
|
||||
</article>
|
||||
|
||||
<script>
|
||||
|
||||
/* BrowserDetect came from http://www.quirksmode.org/js/detect.html */
|
||||
|
||||
var BrowserDetect = {
|
||||
init: function () {
|
||||
this.browser = this.searchString(this.dataBrowser) || "An unknown browser";
|
||||
this.version = this.searchVersion(navigator.userAgent)
|
||||
|| this.searchVersion(navigator.appVersion)
|
||||
|| "an unknown version";
|
||||
this.OS = this.searchString(this.dataOS) || "an unknown OS";
|
||||
},
|
||||
searchString: function (data) {
|
||||
for (var i=0;i<data.length;i++) {
|
||||
var dataString = data[i].string;
|
||||
var dataProp = data[i].prop;
|
||||
this.versionSearchString = data[i].versionSearch || data[i].identity;
|
||||
if (dataString) {
|
||||
if (dataString.indexOf(data[i].subString) != -1)
|
||||
return data[i].identity;
|
||||
}
|
||||
else if (dataProp)
|
||||
return data[i].identity;
|
||||
}
|
||||
},
|
||||
searchVersion: function (dataString) {
|
||||
var index = dataString.indexOf(this.versionSearchString);
|
||||
if (index == -1) return;
|
||||
return parseFloat(dataString.substring(index+this.versionSearchString.length+1));
|
||||
},
|
||||
dataBrowser: [
|
||||
{
|
||||
string: navigator.userAgent,
|
||||
subString: "Chrome",
|
||||
identity: "Chrome"
|
||||
},
|
||||
{ string: navigator.userAgent,
|
||||
subString: "OmniWeb",
|
||||
versionSearch: "OmniWeb/",
|
||||
identity: "OmniWeb"
|
||||
},
|
||||
{
|
||||
string: navigator.vendor,
|
||||
subString: "Apple",
|
||||
identity: "Safari",
|
||||
versionSearch: "Version"
|
||||
},
|
||||
{
|
||||
prop: window.opera,
|
||||
identity: "Opera",
|
||||
versionSearch: "Version"
|
||||
},
|
||||
{
|
||||
string: navigator.vendor,
|
||||
subString: "iCab",
|
||||
identity: "iCab"
|
||||
},
|
||||
{
|
||||
string: navigator.vendor,
|
||||
subString: "KDE",
|
||||
identity: "Konqueror"
|
||||
},
|
||||
{
|
||||
string: navigator.userAgent,
|
||||
subString: "Firefox",
|
||||
identity: "Firefox"
|
||||
},
|
||||
{
|
||||
string: navigator.vendor,
|
||||
subString: "Camino",
|
||||
identity: "Camino"
|
||||
},
|
||||
{ // for newer Netscapes (6+)
|
||||
string: navigator.userAgent,
|
||||
subString: "Netscape",
|
||||
identity: "Netscape"
|
||||
},
|
||||
{
|
||||
string: navigator.userAgent,
|
||||
subString: "MSIE",
|
||||
identity: "Explorer",
|
||||
versionSearch: "MSIE"
|
||||
},
|
||||
{
|
||||
string: navigator.userAgent,
|
||||
subString: "Gecko",
|
||||
identity: "Mozilla",
|
||||
versionSearch: "rv"
|
||||
},
|
||||
{ // for older Netscapes (4-)
|
||||
string: navigator.userAgent,
|
||||
subString: "Mozilla",
|
||||
identity: "Netscape",
|
||||
versionSearch: "Mozilla"
|
||||
}
|
||||
],
|
||||
dataOS : [
|
||||
{
|
||||
string: navigator.platform,
|
||||
subString: "Win",
|
||||
identity: "Windows"
|
||||
},
|
||||
{
|
||||
string: navigator.platform,
|
||||
subString: "Mac",
|
||||
identity: "Mac"
|
||||
},
|
||||
{
|
||||
string: navigator.userAgent,
|
||||
subString: "iPhone",
|
||||
identity: "iPhone/iPod"
|
||||
},
|
||||
{
|
||||
string: navigator.platform,
|
||||
subString: "Linux",
|
||||
identity: "Linux"
|
||||
}
|
||||
]
|
||||
|
||||
};
|
||||
BrowserDetect.init();
|
||||
|
||||
document.getElementById("brow").textContent = " " + BrowserDetect.browser + " "
|
||||
+ BrowserDetect.version +" " + BrowserDetect.OS +" ";
|
||||
|
||||
var pos = 0;
|
||||
|
||||
function get_appropriate_ws_url()
|
||||
{
|
||||
var pcol;
|
||||
var u = document.URL;
|
||||
|
||||
/*
|
||||
* We open the websocket encrypted if this page came on an
|
||||
* https:// url itself, otherwise unencrypted
|
||||
*/
|
||||
|
||||
if (u.substring(0, 5) == "https") {
|
||||
pcol = "wss://";
|
||||
u = u.substr(8);
|
||||
} else {
|
||||
pcol = "ws://";
|
||||
if (u.substring(0, 4) == "http")
|
||||
u = u.substr(7);
|
||||
}
|
||||
|
||||
u = u.split('/');
|
||||
|
||||
/* + "/xxx" bit is for IE10 workaround */
|
||||
|
||||
return pcol + u[0] + "/xxx";
|
||||
}
|
||||
|
||||
|
||||
document.getElementById("number").textContent = get_appropriate_ws_url();
|
||||
|
||||
/* dumb increment protocol */
|
||||
|
||||
var socket_di;
|
||||
|
||||
if (typeof MozWebSocket != "undefined") {
|
||||
socket_di = new MozWebSocket(get_appropriate_ws_url(),
|
||||
"dumb-increment-protocol");
|
||||
} else {
|
||||
socket_di = new WebSocket(get_appropriate_ws_url(),
|
||||
"dumb-increment-protocol");
|
||||
}
|
||||
|
||||
|
||||
try {
|
||||
socket_di.onopen = function() {
|
||||
document.getElementById("wsdi_statustd").style.backgroundColor = "#40ff40";
|
||||
document.getElementById("wsdi_status").textContent = " websocket connection opened ";
|
||||
}
|
||||
|
||||
socket_di.onmessage =function got_packet(msg) {
|
||||
document.getElementById("number").textContent = msg.data + "\n";
|
||||
}
|
||||
|
||||
socket_di.onclose = function(){
|
||||
document.getElementById("wsdi_statustd").style.backgroundColor = "#ff4040";
|
||||
document.getElementById("wsdi_status").textContent = " websocket connection CLOSED ";
|
||||
}
|
||||
} catch(exception) {
|
||||
alert('<p>Error' + exception);
|
||||
}
|
||||
|
||||
function reset() {
|
||||
socket_di.send("reset\n");
|
||||
}
|
||||
|
||||
|
||||
/* lws-mirror protocol */
|
||||
|
||||
var down = 0;
|
||||
var no_last = 1;
|
||||
var last_x = 0, last_y = 0;
|
||||
var ctx;
|
||||
var socket_lm;
|
||||
var color = "#000000";
|
||||
|
||||
if (typeof MozWebSocket != "undefined") {
|
||||
socket_lm = new MozWebSocket(get_appropriate_ws_url(),
|
||||
"lws-mirror-protocol");
|
||||
} else {
|
||||
socket_lm = new WebSocket(get_appropriate_ws_url(),
|
||||
"lws-mirror-protocol");
|
||||
}
|
||||
|
||||
|
||||
try {
|
||||
socket_lm.onopen = function() {
|
||||
document.getElementById("wslm_statustd").style.backgroundColor = "#40ff40";
|
||||
document.getElementById("wslm_status").textContent = " websocket connection opened ";
|
||||
}
|
||||
|
||||
socket_lm.onmessage =function got_packet(msg) {
|
||||
j = msg.data.split(';');
|
||||
f = 0;
|
||||
while (f < j.length - 1) {
|
||||
i = j[f].split(' ');
|
||||
if (i[0] == 'd') {
|
||||
ctx.strokeStyle = i[1];
|
||||
ctx.beginPath();
|
||||
ctx.moveTo(+(i[2]), +(i[3]));
|
||||
ctx.lineTo(+(i[4]), +(i[5]));
|
||||
ctx.stroke();
|
||||
}
|
||||
if (i[0] == 'c') {
|
||||
ctx.strokeStyle = i[1];
|
||||
ctx.beginPath();
|
||||
ctx.arc(+(i[2]), +(i[3]), +(i[4]), 0, Math.PI*2, true);
|
||||
ctx.stroke();
|
||||
}
|
||||
|
||||
f++;
|
||||
}
|
||||
}
|
||||
|
||||
socket_lm.onclose = function(){
|
||||
document.getElementById("wslm_statustd").style.backgroundColor = "#ff4040";
|
||||
document.getElementById("wslm_status").textContent = " websocket connection CLOSED ";
|
||||
}
|
||||
} catch(exception) {
|
||||
alert('<p>Error' + exception);
|
||||
}
|
||||
|
||||
var canvas = document.createElement('canvas');
|
||||
canvas.height = 300;
|
||||
canvas.width = 480;
|
||||
ctx = canvas.getContext("2d");
|
||||
|
||||
document.getElementById('wslm_drawing').appendChild(canvas);
|
||||
|
||||
canvas.addEventListener('mousemove', ev_mousemove, false);
|
||||
canvas.addEventListener('mousedown', ev_mousedown, false);
|
||||
canvas.addEventListener('mouseup', ev_mouseup, false);
|
||||
|
||||
offsetX = offsetY = 0;
|
||||
element = canvas;
|
||||
if (element.offsetParent) {
|
||||
do {
|
||||
offsetX += element.offsetLeft;
|
||||
offsetY += element.offsetTop;
|
||||
} while ((element = element.offsetParent));
|
||||
}
|
||||
|
||||
function update_color() {
|
||||
color = document.getElementById("color").value;
|
||||
}
|
||||
|
||||
function ev_mousedown (ev) {
|
||||
down = 1;
|
||||
}
|
||||
|
||||
function ev_mouseup(ev) {
|
||||
down = 0;
|
||||
no_last = 1;
|
||||
}
|
||||
|
||||
function ev_mousemove (ev) {
|
||||
var x, y;
|
||||
|
||||
if (ev.offsetX) {
|
||||
x = ev.offsetX;
|
||||
y = ev.offsetY;
|
||||
} else {
|
||||
x = ev.layerX - offsetX;
|
||||
y = ev.layerY - offsetY;
|
||||
|
||||
}
|
||||
|
||||
if (!down)
|
||||
return;
|
||||
if (no_last) {
|
||||
no_last = 0;
|
||||
last_x = x;
|
||||
last_y = y;
|
||||
return;
|
||||
}
|
||||
socket_lm.send("d " + color + " " + last_x + " " + last_y + " " + x + ' ' + y + ';');
|
||||
|
||||
last_x = x;
|
||||
last_y = y;
|
||||
}
|
||||
|
||||
|
||||
</script>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 1.4 KiB |
+18
-8
@@ -34,6 +34,7 @@
|
||||
//HOST_OS
|
||||
#define OS_WINDOWS 0x10000001
|
||||
#define OS_LINUX 0x10000002
|
||||
#define OS_DARWIN 0x10000003
|
||||
|
||||
//HOST_CPU
|
||||
#define CPU_X86 0x20000001
|
||||
@@ -44,31 +45,40 @@
|
||||
#define COMPILER_VC 0x30000001
|
||||
#define COMPILER_GCC 0x30000002
|
||||
|
||||
///
|
||||
#if (!defined(TARGET_WIN86) && !defined(TARGET_BEAGLE) && !defined(TARGET_NACL32) && !defined(TARGET_GCW0) && !defined(TARGET_PANDORA))
|
||||
#if defined(_WIN32) && !defined(TARGET_WIN86)
|
||||
#define TARGET_WIN86
|
||||
#endif
|
||||
|
||||
#ifdef __GNUC__
|
||||
#define BUILD_COMPILER COMPILER_GCC
|
||||
#else
|
||||
#define BUILD_COMPILER COMPILER_VC
|
||||
#endif
|
||||
|
||||
#ifdef TARGET_WIN86
|
||||
#define HOST_OS OS_WINDOWS
|
||||
#define HOST_CPU CPU_X86
|
||||
#define BUILD_COMPILER COMPILER_VC
|
||||
#elif TARGET_PANDORA
|
||||
#define HOST_OS OS_LINUX
|
||||
#define HOST_CPU CPU_ARM
|
||||
#define BUILD_COMPILER COMPILER_GCC
|
||||
#elif TARGET_BEAGLE
|
||||
#elif TARGET_LINUX_ARMELv7
|
||||
#define HOST_OS OS_LINUX
|
||||
#define HOST_CPU CPU_ARM
|
||||
#define BUILD_COMPILER COMPILER_GCC
|
||||
#elif TARGET_LINUX_x86
|
||||
#define HOST_OS OS_LINUX
|
||||
#define HOST_CPU CPU_X86
|
||||
#elif TARGET_LINUX_MIPS
|
||||
#define HOST_OS OS_LINUX
|
||||
#define HOST_CPU CPU_MIPS
|
||||
#elif TARGET_GCW0
|
||||
#define HOST_OS OS_LINUX
|
||||
#define HOST_CPU CPU_MIPS
|
||||
#define BUILD_COMPILER COMPILER_GCC
|
||||
#elif TARGET_NACL32
|
||||
#define HOST_OS OS_LINUX
|
||||
#define HOST_CPU CPU_X86
|
||||
#define BUILD_COMPILER COMPILER_GCC
|
||||
#elif TARGET_IPHONE
|
||||
#define HOST_OS OS_DARWIN
|
||||
#define HOST_CPU CPU_ARM
|
||||
#else
|
||||
#error Invalid Target: TARGET_* not defined
|
||||
#endif
|
||||
|
||||
+40
-8
@@ -8,9 +8,19 @@ RZDCY_SRC_DIR ?= $(call my-dir)
|
||||
|
||||
RZDCY_MODULES := cfg/ hw/arm7/ hw/aica/ hw/holly/ hw/ hw/gdrom/ hw/maple/ \
|
||||
hw/mem/ hw/pvr/ hw/sh4/ hw/sh4/interpr/ hw/sh4/modules/ plugins/ profiler/ oslib/ \
|
||||
hw/extdev/ hw/arm/ imgread/ linux/ ./ deps/zlib/ deps/chdr/ deps/crypto/ deps/libelf/ deps/chdpsr/ arm_emitter/ \
|
||||
hw/extdev/ hw/arm/ imgread/ linux/ ./ deps/coreio/ deps/zlib/ deps/chdr/ deps/crypto/ deps/libelf/ deps/chdpsr/ arm_emitter/ \
|
||||
deps/libzip/ deps/libpng/ rend/
|
||||
|
||||
|
||||
ifdef WEBUI
|
||||
RZDCY_MODULES += webui/
|
||||
RZDCY_MODULES += deps/libwebsocket/
|
||||
|
||||
ifdef FOR_ANDROID
|
||||
RZDCY_MODULES += deps/ifaddrs/
|
||||
endif
|
||||
endif
|
||||
|
||||
ifndef NO_REC
|
||||
RZDCY_MODULES += hw/sh4/dyna/
|
||||
endif
|
||||
@@ -42,17 +52,39 @@ RZDCY_FILES += $(foreach dir,$(addprefix $(RZDCY_SRC_DIR)/,$(RZDCY_MODULES)),$(w
|
||||
RZDCY_FILES += $(foreach dir,$(addprefix $(RZDCY_SRC_DIR)/,$(RZDCY_MODULES)),$(wildcard $(dir)*.S))
|
||||
|
||||
ifdef FOR_PANDORA
|
||||
RZDCY_CXXFLAGS := \
|
||||
RZDCY_CFLAGS := \
|
||||
$(CFLAGS) -c -g -O3 -I$(RZDCY_SRC_DIR) -I$(RZDCY_SRC_DIR)/deps \
|
||||
-DRELEASE -DPANDORA\
|
||||
-march=armv7-a -mtune=cortex-a8 -mfpu=neon -mfloat-abi=softfp \
|
||||
-frename-registers -fsingle-precision-constant -ffast-math \
|
||||
-ftree-vectorize -fomit-frame-pointer -fno-exceptions -fno-rtti -std=gnu++11
|
||||
-ftree-vectorize -fomit-frame-pointer
|
||||
RZDCY_CFLAGS += -march=armv7-a -mtune=cortex-a8 -mfpu=neon
|
||||
RZDCY_CFLAGS += -DTARGET_LINUX_ARMELv7
|
||||
else
|
||||
RZDCY_CXXFLAGS := \
|
||||
RZDCY_CFLAGS := \
|
||||
$(CFLAGS) -c -g -O3 -I$(RZDCY_SRC_DIR) -I$(RZDCY_SRC_DIR)/deps \
|
||||
-D_ANDROID -DRELEASE -DTARGET_BEAGLE\
|
||||
-march=armv7-a -mtune=cortex-a9 -mfpu=vfpv3-d16 \
|
||||
-D_ANDROID -DRELEASE\
|
||||
-frename-registers -fsingle-precision-constant -ffast-math \
|
||||
-ftree-vectorize -fomit-frame-pointer -fno-exceptions -fno-rtti -std=gnu++11
|
||||
endif
|
||||
-ftree-vectorize -fomit-frame-pointer
|
||||
|
||||
ifndef NOT_ARM
|
||||
RZDCY_CFLAGS += -march=armv7-a -mtune=cortex-a9 -mfpu=vfpv3-d16
|
||||
RZDCY_CFLAGS += -DTARGET_LINUX_ARMELv7
|
||||
else
|
||||
ifndef ISMIPS
|
||||
RZDCY_CFLAGS += -DTARGET_LINUX_x86
|
||||
else
|
||||
RZDCY_CFLAGS += -DTARGET_LINUX_MIPS
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
|
||||
ifdef NO_REC
|
||||
RZDCY_CFLAGS += -DHOST_NO_REC
|
||||
endif
|
||||
|
||||
ifndef DESKTOPGL
|
||||
RZDCY_CFLAGS += -DGLES
|
||||
endif
|
||||
|
||||
RZDCY_CXXFLAGS := $(RZDCY_CFLAGS) -fno-exceptions -fno-rtti -std=gnu++11
|
||||
@@ -42,8 +42,8 @@ unsigned long track_mode;
|
||||
void CDI_read_track (FILE *fsource, image_s *image, track_s *track)
|
||||
{
|
||||
|
||||
char TRACK_START_MARK[10] = { 0, 0, 0x01, 0, 0, 0, 0xFF, 0xFF, 0xFF, 0xFF };
|
||||
char current_start_mark[10];
|
||||
unsigned char TRACK_START_MARK[10] = { 0, 0, 0x01, 0, 0, 0, 0xFF, 0xFF, 0xFF, 0xFF };
|
||||
unsigned char current_start_mark[10];
|
||||
|
||||
fread(&temp_value, 4, 1, fsource);
|
||||
if (temp_value != 0)
|
||||
|
||||
@@ -43,6 +43,7 @@
|
||||
#define __CHD_H__
|
||||
|
||||
#include "coretypes.h"
|
||||
#include "deps/coreio/coreio.h"
|
||||
|
||||
|
||||
/***************************************************************************
|
||||
|
||||
+4
-20
@@ -302,22 +302,6 @@ static const codec_interface codec_interfaces[] =
|
||||
},
|
||||
};
|
||||
|
||||
|
||||
|
||||
int core_fread(FILE* f, void* buff, size_t len)
|
||||
{
|
||||
return fread(buff,1,len,f);
|
||||
}
|
||||
|
||||
size_t core_fsize(FILE* f)
|
||||
{
|
||||
size_t p=ftell(f);
|
||||
fseek(f,0,SEEK_END);
|
||||
size_t rv=ftell(f);
|
||||
fseek(f,p,SEEK_SET);
|
||||
return rv;
|
||||
}
|
||||
#define core_fseek fseek
|
||||
#define MIN min
|
||||
#define MAX max
|
||||
/***************************************************************************
|
||||
@@ -593,7 +577,7 @@ chd_error chd_open(const wchar *filename, int mode, chd_file *parent, chd_file *
|
||||
}
|
||||
|
||||
/* open the file */
|
||||
file=fopen(filename, "rb");
|
||||
file=core_fopen(filename);
|
||||
if (file == 0)
|
||||
{
|
||||
err = CHDERR_FILE_NOT_FOUND;
|
||||
@@ -610,7 +594,7 @@ chd_error chd_open(const wchar *filename, int mode, chd_file *parent, chd_file *
|
||||
|
||||
cleanup:
|
||||
if ((err != CHDERR_NONE) && (file != NULL))
|
||||
fclose(file);
|
||||
core_fclose(file);
|
||||
return err;
|
||||
}
|
||||
|
||||
@@ -653,7 +637,7 @@ void chd_close(chd_file *chd)
|
||||
|
||||
/* close the file */
|
||||
if (chd->owns_file && chd->file != NULL)
|
||||
fclose(chd->file);
|
||||
core_fclose(chd->file);
|
||||
|
||||
if (PRINTF_MAX_HUNK) printf("Max hunk = %d/%d\n", chd->maxhunk, chd->header.totalhunks);
|
||||
|
||||
@@ -807,7 +791,7 @@ chd_error chd_get_metadata(chd_file *chd, UINT32 searchtag, UINT32 searchindex,
|
||||
|
||||
/* read the metadata */
|
||||
outputlen = min(outputlen, metaentry.length);
|
||||
fseek(chd->file, metaentry.offset + METADATA_HEADER_SIZE, SEEK_SET);
|
||||
core_fseek(chd->file, metaentry.offset + METADATA_HEADER_SIZE, SEEK_SET);
|
||||
count = core_fread(chd->file, output, outputlen);
|
||||
if (count != outputlen)
|
||||
return CHDERR_READ_ERROR;
|
||||
|
||||
@@ -15,6 +15,4 @@ typedef s8 INT8;
|
||||
#define INLINE inline
|
||||
#endif
|
||||
|
||||
#define core_file FILE
|
||||
|
||||
#define ARRAY_LENGTH(x) (sizeof(x)/sizeof(x[0]))
|
||||
@@ -0,0 +1,265 @@
|
||||
|
||||
#include "coreio.h"
|
||||
|
||||
#include <time.h>
|
||||
#include <stddef.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#define TRUE 1
|
||||
#define FALSE 0
|
||||
|
||||
#pragma comment (lib, "wsock32.lib")
|
||||
|
||||
#include <string>
|
||||
#include <sstream>
|
||||
|
||||
#if HOST_OS == OS_LINUX
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
#include <netinet/ip.h>
|
||||
#include <linux/tcp.h>
|
||||
#include <netdb.h>
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
size_t HTTP_GET(string host, int port,string path, size_t offs, size_t len, void* pdata){
|
||||
string request;
|
||||
string response;
|
||||
|
||||
struct sockaddr_in serveraddr;
|
||||
int sock;
|
||||
|
||||
std::stringstream request2;
|
||||
|
||||
if (len) {
|
||||
request2 << "GET " << path << " HTTP/1.1"<<endl;
|
||||
request2 << "User-Agent: reicastdc" << endl;
|
||||
//request2 << "" << endl;
|
||||
request2 << "Host: " << host << endl;
|
||||
request2 << "Accept: */*" << endl;
|
||||
request2 << "Range: bytes=" << offs << "-" << (offs + len-1) << endl;
|
||||
request2 << endl;
|
||||
}
|
||||
else {
|
||||
request2 << "HEAD " << path << " HTTP/1.1"<<endl;
|
||||
request2 << "User-Agent: reicastdc" << endl;
|
||||
//request2 << "" << endl;
|
||||
request2 << "Host: " << host << endl;
|
||||
request2 << endl;
|
||||
}
|
||||
|
||||
request = request2.str();
|
||||
//init winsock
|
||||
|
||||
static bool init = false;
|
||||
if (!init) {
|
||||
#if HOST_OS == OS_WINDOWS
|
||||
static WSADATA wsaData;
|
||||
if (WSAStartup(MAKEWORD(2, 0), &wsaData) != 0)
|
||||
die("WSAStartup fail");
|
||||
#endif
|
||||
init = true;
|
||||
}
|
||||
|
||||
//open socket
|
||||
if ((sock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0)
|
||||
return -1;
|
||||
|
||||
|
||||
//connect
|
||||
memset(&serveraddr, 0, sizeof(serveraddr));
|
||||
serveraddr.sin_family = AF_INET;
|
||||
serveraddr.sin_addr.s_addr = *(int*)gethostbyname( host.c_str() )->h_addr_list[0];
|
||||
serveraddr.sin_port = htons((unsigned short) port);
|
||||
if (connect(sock, (struct sockaddr *) &serveraddr, sizeof(serveraddr)) < 0)
|
||||
return -1;
|
||||
|
||||
#if HOST_OS == OS_WINDOWS
|
||||
BOOL v = TRUE;
|
||||
#else
|
||||
int v = 1;
|
||||
#endif
|
||||
|
||||
setsockopt(sock, IPPROTO_TCP, TCP_NODELAY, (const char*)&v, sizeof(v));
|
||||
//send request
|
||||
if (send(sock, request.c_str(), request.length(), 0) != request.length())
|
||||
return -1;
|
||||
|
||||
/*
|
||||
//get response
|
||||
response = "";
|
||||
resp_leng= BUFFERSIZE;
|
||||
|
||||
*/
|
||||
|
||||
/*
|
||||
parse headers ..
|
||||
*/
|
||||
size_t content_length = 0;
|
||||
|
||||
size_t rv = content_length;
|
||||
|
||||
for (;;) {
|
||||
stringstream ss;
|
||||
for (;;) {
|
||||
char t;
|
||||
if (recv(sock, &t, 1, 0) <= 0)
|
||||
goto _cleanup;
|
||||
|
||||
if (t != '\n'){
|
||||
ss << t;
|
||||
continue;
|
||||
}
|
||||
|
||||
string ln = ss.str();
|
||||
|
||||
if (ln.size() == 1)
|
||||
goto _data;
|
||||
string CL = "Content-Length:";
|
||||
|
||||
if (ln.substr(0, CL.size()) == CL) {
|
||||
sscanf(ln.substr(CL.size(), ln.npos).c_str(),"%d", &content_length);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
_data:
|
||||
|
||||
if (len == 0) {
|
||||
|
||||
}
|
||||
else {
|
||||
verify(len == content_length);
|
||||
u8* ptr = (u8*)pdata;
|
||||
do
|
||||
{
|
||||
int rcv = recv(sock, (char*)ptr, len, 0);
|
||||
verify(rcv > 0 && len>= rcv);
|
||||
len -= rcv;
|
||||
ptr += rcv;
|
||||
}
|
||||
while (len >0);
|
||||
}
|
||||
|
||||
_cleanup:
|
||||
//disconnect
|
||||
#if HOST_OS == OS_WINDOWS
|
||||
closesocket(sock);
|
||||
#else
|
||||
close(sock);
|
||||
#endif
|
||||
|
||||
/*
|
||||
//cleanup
|
||||
WSACleanup();
|
||||
*/
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
struct CORE_FILE {
|
||||
FILE* f;
|
||||
string path;
|
||||
size_t seek_ptr;
|
||||
|
||||
string host;
|
||||
int port;
|
||||
};
|
||||
|
||||
core_file* core_fopen(const char* filename)
|
||||
{
|
||||
string p = filename;
|
||||
|
||||
CORE_FILE* rv = new CORE_FILE();
|
||||
rv->f = 0;
|
||||
rv->path = p;
|
||||
|
||||
if (p.substr(0,7)=="http://") {
|
||||
rv->host = p.substr(7,p.npos);
|
||||
rv->host = rv->host.substr(0, rv->host.find_first_of("/"));
|
||||
|
||||
rv->path = p.substr(p.find("/", 7), p.npos);
|
||||
|
||||
rv->port = 80;
|
||||
size_t pos = rv->host.find_first_of(":");
|
||||
if (pos != rv->host.npos) {
|
||||
string port = rv->host.substr(pos, rv->host.npos );
|
||||
rv->host = rv->host.substr(0, rv->host.find_first_of(":"));
|
||||
sscanf(port.c_str(),"%d",&rv->port);
|
||||
}
|
||||
} else {
|
||||
rv->f = fopen(filename, "rb");
|
||||
|
||||
if (!rv->f) {
|
||||
delete rv;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
return (core_file*)rv;
|
||||
}
|
||||
|
||||
size_t core_fseek(core_file* fc, size_t offs, size_t origin) {
|
||||
CORE_FILE* f = (CORE_FILE*)fc;
|
||||
|
||||
if (origin == SEEK_SET)
|
||||
f->seek_ptr = offs;
|
||||
else if (origin == SEEK_CUR)
|
||||
f->seek_ptr += offs;
|
||||
else
|
||||
die("Invalid code path");
|
||||
|
||||
if (f->f)
|
||||
fseek(f->f, f->seek_ptr, SEEK_SET);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int core_fread(core_file* fc, void* buff, size_t len)
|
||||
{
|
||||
CORE_FILE* f = (CORE_FILE*)fc;
|
||||
|
||||
if (f->f) {
|
||||
fread(buff,1,len,f->f);
|
||||
} else {
|
||||
HTTP_GET(f->host, f->port, f->path, f->seek_ptr, len, buff);
|
||||
}
|
||||
|
||||
f->seek_ptr += len;
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
int core_fclose(core_file* fc)
|
||||
{
|
||||
CORE_FILE* f = (CORE_FILE*)fc;
|
||||
|
||||
if (f->f) {
|
||||
fclose(f->f);
|
||||
}
|
||||
else {
|
||||
|
||||
}
|
||||
|
||||
delete f;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
size_t core_fsize(core_file* fc)
|
||||
{
|
||||
CORE_FILE* f = (CORE_FILE*)fc;
|
||||
|
||||
if (f->f) {
|
||||
size_t p=ftell(f->f);
|
||||
fseek(f->f,0,SEEK_END);
|
||||
size_t rv=ftell(f->f);
|
||||
fseek(f->f,p,SEEK_SET);
|
||||
return rv;
|
||||
}
|
||||
else {
|
||||
return HTTP_GET(f->host, f->port, f->path, 0, 0,0);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
#pragma once
|
||||
#include "types.h"
|
||||
|
||||
//#define core_file FILE
|
||||
typedef void* core_file;
|
||||
|
||||
|
||||
core_file* core_fopen(const char* filename);
|
||||
size_t core_fseek(core_file* fc, size_t offs, size_t origin);
|
||||
int core_fread(core_file* fc, void* buff, size_t len);
|
||||
int core_fclose(core_file* fc);
|
||||
size_t core_fsize(core_file* fc);
|
||||
@@ -0,0 +1,161 @@
|
||||
/*********************************************************************
|
||||
* Filename: sha256.c
|
||||
* Author: Brad Conte (brad AT bradconte.com)
|
||||
* Copyright:
|
||||
* Disclaimer: This code is presented "as is" without any guarantees.
|
||||
* Details: Implementation of the SHA-256 hashing algorithm.
|
||||
SHA-256 is one of the three algorithms in the SHA2
|
||||
specification. The others, SHA-384 and SHA-512, are not
|
||||
offered in this implementation.
|
||||
Algorithm specification can be found here:
|
||||
* http://csrc.nist.gov/publications/fips/fips180-2/fips180-2withchangenotice.pdf
|
||||
This implementation uses little endian byte order.
|
||||
*********************************************************************/
|
||||
|
||||
/*************************** HEADER FILES ***************************/
|
||||
#include <stdlib.h>
|
||||
#include <memory.h>
|
||||
#include "sha256.h"
|
||||
|
||||
#define WORD uint32_t
|
||||
#define BYTE uint8_t
|
||||
|
||||
/****************************** MACROS ******************************/
|
||||
#define ROTLEFT(a,b) (((a) << (b)) | ((a) >> (32-(b))))
|
||||
#define ROTRIGHT(a,b) (((a) >> (b)) | ((a) << (32-(b))))
|
||||
|
||||
#define CH(x,y,z) (((x) & (y)) ^ (~(x) & (z)))
|
||||
#define MAJ(x,y,z) (((x) & (y)) ^ ((x) & (z)) ^ ((y) & (z)))
|
||||
#define EP0(x) (ROTRIGHT(x,2) ^ ROTRIGHT(x,13) ^ ROTRIGHT(x,22))
|
||||
#define EP1(x) (ROTRIGHT(x,6) ^ ROTRIGHT(x,11) ^ ROTRIGHT(x,25))
|
||||
#define SIG0(x) (ROTRIGHT(x,7) ^ ROTRIGHT(x,18) ^ ((x) >> 3))
|
||||
#define SIG1(x) (ROTRIGHT(x,17) ^ ROTRIGHT(x,19) ^ ((x) >> 10))
|
||||
|
||||
/**************************** VARIABLES *****************************/
|
||||
static const WORD k[64] = {
|
||||
0x428a2f98,0x71374491,0xb5c0fbcf,0xe9b5dba5,0x3956c25b,0x59f111f1,0x923f82a4,0xab1c5ed5,
|
||||
0xd807aa98,0x12835b01,0x243185be,0x550c7dc3,0x72be5d74,0x80deb1fe,0x9bdc06a7,0xc19bf174,
|
||||
0xe49b69c1,0xefbe4786,0x0fc19dc6,0x240ca1cc,0x2de92c6f,0x4a7484aa,0x5cb0a9dc,0x76f988da,
|
||||
0x983e5152,0xa831c66d,0xb00327c8,0xbf597fc7,0xc6e00bf3,0xd5a79147,0x06ca6351,0x14292967,
|
||||
0x27b70a85,0x2e1b2138,0x4d2c6dfc,0x53380d13,0x650a7354,0x766a0abb,0x81c2c92e,0x92722c85,
|
||||
0xa2bfe8a1,0xa81a664b,0xc24b8b70,0xc76c51a3,0xd192e819,0xd6990624,0xf40e3585,0x106aa070,
|
||||
0x19a4c116,0x1e376c08,0x2748774c,0x34b0bcb5,0x391c0cb3,0x4ed8aa4a,0x5b9cca4f,0x682e6ff3,
|
||||
0x748f82ee,0x78a5636f,0x84c87814,0x8cc70208,0x90befffa,0xa4506ceb,0xbef9a3f7,0xc67178f2
|
||||
};
|
||||
|
||||
/*********************** FUNCTION DEFINITIONS ***********************/
|
||||
void sha256_transform(SHA256_CTX *ctx, const BYTE data[])
|
||||
{
|
||||
WORD a, b, c, d, e, f, g, h, i, j, t1, t2, m[64];
|
||||
|
||||
for (i = 0, j = 0; i < 16; ++i, j += 4)
|
||||
m[i] = (data[j] << 24) | (data[j + 1] << 16) | (data[j + 2] << 8) | (data[j + 3]);
|
||||
for ( ; i < 64; ++i)
|
||||
m[i] = SIG1(m[i - 2]) + m[i - 7] + SIG0(m[i - 15]) + m[i - 16];
|
||||
|
||||
a = ctx->state[0];
|
||||
b = ctx->state[1];
|
||||
c = ctx->state[2];
|
||||
d = ctx->state[3];
|
||||
e = ctx->state[4];
|
||||
f = ctx->state[5];
|
||||
g = ctx->state[6];
|
||||
h = ctx->state[7];
|
||||
|
||||
for (i = 0; i < 64; ++i) {
|
||||
t1 = h + EP1(e) + CH(e,f,g) + k[i] + m[i];
|
||||
t2 = EP0(a) + MAJ(a,b,c);
|
||||
h = g;
|
||||
g = f;
|
||||
f = e;
|
||||
e = d + t1;
|
||||
d = c;
|
||||
c = b;
|
||||
b = a;
|
||||
a = t1 + t2;
|
||||
}
|
||||
|
||||
ctx->state[0] += a;
|
||||
ctx->state[1] += b;
|
||||
ctx->state[2] += c;
|
||||
ctx->state[3] += d;
|
||||
ctx->state[4] += e;
|
||||
ctx->state[5] += f;
|
||||
ctx->state[6] += g;
|
||||
ctx->state[7] += h;
|
||||
}
|
||||
|
||||
void sha256_init(SHA256_CTX *ctx)
|
||||
{
|
||||
ctx->datalen = 0;
|
||||
ctx->bitlen = 0;
|
||||
ctx->state[0] = 0x6a09e667;
|
||||
ctx->state[1] = 0xbb67ae85;
|
||||
ctx->state[2] = 0x3c6ef372;
|
||||
ctx->state[3] = 0xa54ff53a;
|
||||
ctx->state[4] = 0x510e527f;
|
||||
ctx->state[5] = 0x9b05688c;
|
||||
ctx->state[6] = 0x1f83d9ab;
|
||||
ctx->state[7] = 0x5be0cd19;
|
||||
}
|
||||
|
||||
void sha256_update(SHA256_CTX *ctx, const BYTE data[], size_t len)
|
||||
{
|
||||
WORD i;
|
||||
|
||||
for (i = 0; i < len; ++i) {
|
||||
ctx->data[ctx->datalen] = data[i];
|
||||
ctx->datalen++;
|
||||
if (ctx->datalen == 64) {
|
||||
sha256_transform(ctx, ctx->data);
|
||||
ctx->bitlen += 512;
|
||||
ctx->datalen = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void sha256_final(SHA256_CTX *ctx, BYTE hash[])
|
||||
{
|
||||
WORD i;
|
||||
|
||||
i = ctx->datalen;
|
||||
|
||||
// Pad whatever data is left in the buffer.
|
||||
if (ctx->datalen < 56) {
|
||||
ctx->data[i++] = 0x80;
|
||||
while (i < 56)
|
||||
ctx->data[i++] = 0x00;
|
||||
}
|
||||
else {
|
||||
ctx->data[i++] = 0x80;
|
||||
while (i < 64)
|
||||
ctx->data[i++] = 0x00;
|
||||
sha256_transform(ctx, ctx->data);
|
||||
memset(ctx->data, 0, 56);
|
||||
}
|
||||
|
||||
// Append to the padding the total message's length in bits and transform.
|
||||
ctx->bitlen += ctx->datalen * 8;
|
||||
ctx->data[63] = (BYTE)(ctx->bitlen);
|
||||
ctx->data[62] = (BYTE)(ctx->bitlen >> 8);
|
||||
ctx->data[61] = (BYTE)(ctx->bitlen >> 16);
|
||||
ctx->data[60] = (BYTE)(ctx->bitlen >> 24);
|
||||
ctx->data[59] = (BYTE)(ctx->bitlen >> 32);
|
||||
ctx->data[58] = (BYTE)(ctx->bitlen >> 40);
|
||||
ctx->data[57] = (BYTE)(ctx->bitlen >> 48);
|
||||
ctx->data[56] = (BYTE)(ctx->bitlen >> 56);
|
||||
sha256_transform(ctx, ctx->data);
|
||||
|
||||
// Since this implementation uses little endian byte ordering and SHA uses big endian,
|
||||
// reverse all the bytes when copying the final state to the output hash.
|
||||
for (i = 0; i < 4; ++i) {
|
||||
hash[i] = (ctx->state[0] >> (24 - i * 8)) & 0x000000ff;
|
||||
hash[i + 4] = (ctx->state[1] >> (24 - i * 8)) & 0x000000ff;
|
||||
hash[i + 8] = (ctx->state[2] >> (24 - i * 8)) & 0x000000ff;
|
||||
hash[i + 12] = (ctx->state[3] >> (24 - i * 8)) & 0x000000ff;
|
||||
hash[i + 16] = (ctx->state[4] >> (24 - i * 8)) & 0x000000ff;
|
||||
hash[i + 20] = (ctx->state[5] >> (24 - i * 8)) & 0x000000ff;
|
||||
hash[i + 24] = (ctx->state[6] >> (24 - i * 8)) & 0x000000ff;
|
||||
hash[i + 28] = (ctx->state[7] >> (24 - i * 8)) & 0x000000ff;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
/*********************************************************************
|
||||
* Filename: sha256.h
|
||||
* Author: Brad Conte (brad AT bradconte.com)
|
||||
* Copyright:
|
||||
* Disclaimer: This code is presented "as is" without any guarantees.
|
||||
* Details: Defines the API for the corresponding SHA1 implementation.
|
||||
*********************************************************************/
|
||||
|
||||
#ifndef SHA256_H
|
||||
#define SHA256_H
|
||||
|
||||
/*************************** HEADER FILES ***************************/
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
/****************************** MACROS ******************************/
|
||||
#define SHA256_BLOCK_SIZE 32 // SHA256 outputs a 32 byte digest
|
||||
|
||||
/**************************** DATA TYPES ****************************/
|
||||
/*
|
||||
typedef uint8_t BYTE; // 8-bit byte
|
||||
typedef uint32_t WORD; // 32-bit word, change to "long" for 16-bit machines
|
||||
*/
|
||||
|
||||
typedef struct {
|
||||
uint8_t data[64];
|
||||
uint32_t datalen;
|
||||
uint64_t bitlen;
|
||||
uint32_t state[8];
|
||||
} SHA256_CTX;
|
||||
|
||||
/*********************** FUNCTION DECLARATIONS **********************/
|
||||
void sha256_init(SHA256_CTX *ctx);
|
||||
void sha256_update(SHA256_CTX *ctx, const uint8_t data[], size_t len);
|
||||
void sha256_final(SHA256_CTX *ctx, uint8_t hash[]);
|
||||
|
||||
#endif // SHA256_H
|
||||
@@ -0,0 +1,6 @@
|
||||
android-ifaddrs
|
||||
===============
|
||||
|
||||
An implementation of getifaddrs() for Android, since the NDK does not natively support it.
|
||||
|
||||
Works just like you would expect on regular Linux. License information is present in each file (BSD license).
|
||||
@@ -0,0 +1,658 @@
|
||||
/*
|
||||
Copyright (c) 2013, Kenneth MacKay
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
* Redistributions of source code must retain the above copyright notice, this
|
||||
list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "ifaddrs.h"
|
||||
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <errno.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/socket.h>
|
||||
#include <net/if_arp.h>
|
||||
#include <netinet/in.h>
|
||||
#include <linux/netlink.h>
|
||||
#include <linux/rtnetlink.h>
|
||||
|
||||
typedef struct NetlinkList
|
||||
{
|
||||
struct NetlinkList *m_next;
|
||||
struct nlmsghdr *m_data;
|
||||
unsigned int m_size;
|
||||
} NetlinkList;
|
||||
|
||||
static int netlink_socket(void)
|
||||
{
|
||||
int l_socket = socket(PF_NETLINK, SOCK_RAW, NETLINK_ROUTE);
|
||||
if(l_socket < 0)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
struct sockaddr_nl l_addr;
|
||||
memset(&l_addr, 0, sizeof(l_addr));
|
||||
l_addr.nl_family = AF_NETLINK;
|
||||
if(bind(l_socket, (struct sockaddr *)&l_addr, sizeof(l_addr)) < 0)
|
||||
{
|
||||
close(l_socket);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return l_socket;
|
||||
}
|
||||
|
||||
static int netlink_send(int p_socket, int p_request)
|
||||
{
|
||||
char l_buffer[NLMSG_ALIGN(sizeof(struct nlmsghdr)) + NLMSG_ALIGN(sizeof(struct rtgenmsg))];
|
||||
memset(l_buffer, 0, sizeof(l_buffer));
|
||||
struct nlmsghdr *l_hdr = (struct nlmsghdr *)l_buffer;
|
||||
struct rtgenmsg *l_msg = (struct rtgenmsg *)NLMSG_DATA(l_hdr);
|
||||
|
||||
l_hdr->nlmsg_len = NLMSG_LENGTH(sizeof(*l_msg));
|
||||
l_hdr->nlmsg_type = p_request;
|
||||
l_hdr->nlmsg_flags = NLM_F_ROOT | NLM_F_MATCH | NLM_F_REQUEST;
|
||||
l_hdr->nlmsg_pid = 0;
|
||||
l_hdr->nlmsg_seq = p_socket;
|
||||
l_msg->rtgen_family = AF_UNSPEC;
|
||||
|
||||
struct sockaddr_nl l_addr;
|
||||
memset(&l_addr, 0, sizeof(l_addr));
|
||||
l_addr.nl_family = AF_NETLINK;
|
||||
return (sendto(p_socket, l_hdr, l_hdr->nlmsg_len, 0, (struct sockaddr *)&l_addr, sizeof(l_addr)));
|
||||
}
|
||||
|
||||
static int netlink_recv(int p_socket, void *p_buffer, size_t p_len)
|
||||
{
|
||||
struct msghdr l_msg;
|
||||
struct iovec l_iov = { p_buffer, p_len };
|
||||
struct sockaddr_nl l_addr;
|
||||
int l_result;
|
||||
|
||||
for(;;)
|
||||
{
|
||||
l_msg.msg_name = (void *)&l_addr;
|
||||
l_msg.msg_namelen = sizeof(l_addr);
|
||||
l_msg.msg_iov = &l_iov;
|
||||
l_msg.msg_iovlen = 1;
|
||||
l_msg.msg_control = NULL;
|
||||
l_msg.msg_controllen = 0;
|
||||
l_msg.msg_flags = 0;
|
||||
int l_result = recvmsg(p_socket, &l_msg, 0);
|
||||
|
||||
if(l_result < 0)
|
||||
{
|
||||
if(errno == EINTR)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
return -2;
|
||||
}
|
||||
|
||||
if(l_msg.msg_flags & MSG_TRUNC)
|
||||
{ // buffer was too small
|
||||
return -1;
|
||||
}
|
||||
return l_result;
|
||||
}
|
||||
}
|
||||
|
||||
static struct nlmsghdr *getNetlinkResponse(int p_socket, int *p_size, int *p_done)
|
||||
{
|
||||
size_t l_size = 4096;
|
||||
void *l_buffer = NULL;
|
||||
|
||||
for(;;)
|
||||
{
|
||||
free(l_buffer);
|
||||
l_buffer = malloc(l_size);
|
||||
if (l_buffer == NULL)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int l_read = netlink_recv(p_socket, l_buffer, l_size);
|
||||
*p_size = l_read;
|
||||
if(l_read == -2)
|
||||
{
|
||||
free(l_buffer);
|
||||
return NULL;
|
||||
}
|
||||
if(l_read >= 0)
|
||||
{
|
||||
pid_t l_pid = getpid();
|
||||
struct nlmsghdr *l_hdr;
|
||||
for(l_hdr = (struct nlmsghdr *)l_buffer; NLMSG_OK(l_hdr, (unsigned int)l_read); l_hdr = (struct nlmsghdr *)NLMSG_NEXT(l_hdr, l_read))
|
||||
{
|
||||
if((pid_t)l_hdr->nlmsg_pid != l_pid || (int)l_hdr->nlmsg_seq != p_socket)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if(l_hdr->nlmsg_type == NLMSG_DONE)
|
||||
{
|
||||
*p_done = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
if(l_hdr->nlmsg_type == NLMSG_ERROR)
|
||||
{
|
||||
free(l_buffer);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
return l_buffer;
|
||||
}
|
||||
|
||||
l_size *= 2;
|
||||
}
|
||||
}
|
||||
|
||||
static NetlinkList *newListItem(struct nlmsghdr *p_data, unsigned int p_size)
|
||||
{
|
||||
NetlinkList *l_item = malloc(sizeof(NetlinkList));
|
||||
if (l_item == NULL)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
l_item->m_next = NULL;
|
||||
l_item->m_data = p_data;
|
||||
l_item->m_size = p_size;
|
||||
return l_item;
|
||||
}
|
||||
|
||||
static void freeResultList(NetlinkList *p_list)
|
||||
{
|
||||
NetlinkList *l_cur;
|
||||
while(p_list)
|
||||
{
|
||||
l_cur = p_list;
|
||||
p_list = p_list->m_next;
|
||||
free(l_cur->m_data);
|
||||
free(l_cur);
|
||||
}
|
||||
}
|
||||
|
||||
static NetlinkList *getResultList(int p_socket, int p_request)
|
||||
{
|
||||
if(netlink_send(p_socket, p_request) < 0)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
NetlinkList *l_list = NULL;
|
||||
NetlinkList *l_end = NULL;
|
||||
int l_size;
|
||||
int l_done = 0;
|
||||
while(!l_done)
|
||||
{
|
||||
struct nlmsghdr *l_hdr = getNetlinkResponse(p_socket, &l_size, &l_done);
|
||||
if(!l_hdr)
|
||||
{ // error
|
||||
freeResultList(l_list);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
NetlinkList *l_item = newListItem(l_hdr, l_size);
|
||||
if (!l_item)
|
||||
{
|
||||
freeResultList(l_list);
|
||||
return NULL;
|
||||
}
|
||||
if(!l_list)
|
||||
{
|
||||
l_list = l_item;
|
||||
}
|
||||
else
|
||||
{
|
||||
l_end->m_next = l_item;
|
||||
}
|
||||
l_end = l_item;
|
||||
}
|
||||
return l_list;
|
||||
}
|
||||
|
||||
static size_t maxSize(size_t a, size_t b)
|
||||
{
|
||||
return (a > b ? a : b);
|
||||
}
|
||||
|
||||
static size_t calcAddrLen(sa_family_t p_family, int p_dataSize)
|
||||
{
|
||||
switch(p_family)
|
||||
{
|
||||
case AF_INET:
|
||||
return sizeof(struct sockaddr_in);
|
||||
case AF_INET6:
|
||||
return sizeof(struct sockaddr_in6);
|
||||
case AF_PACKET:
|
||||
return maxSize(sizeof(struct sockaddr_ll), offsetof(struct sockaddr_ll, sll_addr) + p_dataSize);
|
||||
default:
|
||||
return maxSize(sizeof(struct sockaddr), offsetof(struct sockaddr, sa_data) + p_dataSize);
|
||||
}
|
||||
}
|
||||
|
||||
static void makeSockaddr(sa_family_t p_family, struct sockaddr *p_dest, void *p_data, size_t p_size)
|
||||
{
|
||||
switch(p_family)
|
||||
{
|
||||
case AF_INET:
|
||||
memcpy(&((struct sockaddr_in*)p_dest)->sin_addr, p_data, p_size);
|
||||
break;
|
||||
case AF_INET6:
|
||||
memcpy(&((struct sockaddr_in6*)p_dest)->sin6_addr, p_data, p_size);
|
||||
break;
|
||||
case AF_PACKET:
|
||||
memcpy(((struct sockaddr_ll*)p_dest)->sll_addr, p_data, p_size);
|
||||
((struct sockaddr_ll*)p_dest)->sll_halen = p_size;
|
||||
break;
|
||||
default:
|
||||
memcpy(p_dest->sa_data, p_data, p_size);
|
||||
break;
|
||||
}
|
||||
p_dest->sa_family = p_family;
|
||||
}
|
||||
|
||||
static void addToEnd(struct ifaddrs **p_resultList, struct ifaddrs *p_entry)
|
||||
{
|
||||
if(!*p_resultList)
|
||||
{
|
||||
*p_resultList = p_entry;
|
||||
}
|
||||
else
|
||||
{
|
||||
struct ifaddrs *l_cur = *p_resultList;
|
||||
while(l_cur->ifa_next)
|
||||
{
|
||||
l_cur = l_cur->ifa_next;
|
||||
}
|
||||
l_cur->ifa_next = p_entry;
|
||||
}
|
||||
}
|
||||
|
||||
static int interpretLink(struct nlmsghdr *p_hdr, struct ifaddrs **p_resultList)
|
||||
{
|
||||
struct ifinfomsg *l_info = (struct ifinfomsg *)NLMSG_DATA(p_hdr);
|
||||
|
||||
size_t l_nameSize = 0;
|
||||
size_t l_addrSize = 0;
|
||||
size_t l_dataSize = 0;
|
||||
|
||||
size_t l_rtaSize = NLMSG_PAYLOAD(p_hdr, sizeof(struct ifinfomsg));
|
||||
struct rtattr *l_rta;
|
||||
for(l_rta = IFLA_RTA(l_info); RTA_OK(l_rta, l_rtaSize); l_rta = RTA_NEXT(l_rta, l_rtaSize))
|
||||
{
|
||||
void *l_rtaData = RTA_DATA(l_rta);
|
||||
size_t l_rtaDataSize = RTA_PAYLOAD(l_rta);
|
||||
switch(l_rta->rta_type)
|
||||
{
|
||||
case IFLA_ADDRESS:
|
||||
case IFLA_BROADCAST:
|
||||
l_addrSize += NLMSG_ALIGN(calcAddrLen(AF_PACKET, l_rtaDataSize));
|
||||
break;
|
||||
case IFLA_IFNAME:
|
||||
l_nameSize += NLMSG_ALIGN(l_rtaSize + 1);
|
||||
break;
|
||||
case IFLA_STATS:
|
||||
l_dataSize += NLMSG_ALIGN(l_rtaSize);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
struct ifaddrs *l_entry = malloc(sizeof(struct ifaddrs) + sizeof(int) + l_nameSize + l_addrSize + l_dataSize);
|
||||
if (l_entry == NULL)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
memset(l_entry, 0, sizeof(struct ifaddrs));
|
||||
l_entry->ifa_name = "";
|
||||
|
||||
char *l_index = ((char *)l_entry) + sizeof(struct ifaddrs);
|
||||
char *l_name = l_index + sizeof(int);
|
||||
char *l_addr = l_name + l_nameSize;
|
||||
char *l_data = l_addr + l_addrSize;
|
||||
|
||||
// save the interface index so we can look it up when handling the addresses.
|
||||
memcpy(l_index, &l_info->ifi_index, sizeof(int));
|
||||
|
||||
l_entry->ifa_flags = l_info->ifi_flags;
|
||||
|
||||
l_rtaSize = NLMSG_PAYLOAD(p_hdr, sizeof(struct ifinfomsg));
|
||||
for(l_rta = IFLA_RTA(l_info); RTA_OK(l_rta, l_rtaSize); l_rta = RTA_NEXT(l_rta, l_rtaSize))
|
||||
{
|
||||
void *l_rtaData = RTA_DATA(l_rta);
|
||||
size_t l_rtaDataSize = RTA_PAYLOAD(l_rta);
|
||||
switch(l_rta->rta_type)
|
||||
{
|
||||
case IFLA_ADDRESS:
|
||||
case IFLA_BROADCAST:
|
||||
{
|
||||
size_t l_addrLen = calcAddrLen(AF_PACKET, l_rtaDataSize);
|
||||
makeSockaddr(AF_PACKET, (struct sockaddr *)l_addr, l_rtaData, l_rtaDataSize);
|
||||
((struct sockaddr_ll *)l_addr)->sll_ifindex = l_info->ifi_index;
|
||||
((struct sockaddr_ll *)l_addr)->sll_hatype = l_info->ifi_type;
|
||||
if(l_rta->rta_type == IFLA_ADDRESS)
|
||||
{
|
||||
l_entry->ifa_addr = (struct sockaddr *)l_addr;
|
||||
}
|
||||
else
|
||||
{
|
||||
l_entry->ifa_broadaddr = (struct sockaddr *)l_addr;
|
||||
}
|
||||
l_addr += NLMSG_ALIGN(l_addrLen);
|
||||
break;
|
||||
}
|
||||
case IFLA_IFNAME:
|
||||
strncpy(l_name, l_rtaData, l_rtaDataSize);
|
||||
l_name[l_rtaDataSize] = '\0';
|
||||
l_entry->ifa_name = l_name;
|
||||
break;
|
||||
case IFLA_STATS:
|
||||
memcpy(l_data, l_rtaData, l_rtaDataSize);
|
||||
l_entry->ifa_data = l_data;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
addToEnd(p_resultList, l_entry);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct ifaddrs *findInterface(int p_index, struct ifaddrs **p_links, int p_numLinks)
|
||||
{
|
||||
int l_num = 0;
|
||||
struct ifaddrs *l_cur = *p_links;
|
||||
while(l_cur && l_num < p_numLinks)
|
||||
{
|
||||
char *l_indexPtr = ((char *)l_cur) + sizeof(struct ifaddrs);
|
||||
int l_index;
|
||||
memcpy(&l_index, l_indexPtr, sizeof(int));
|
||||
if(l_index == p_index)
|
||||
{
|
||||
return l_cur;
|
||||
}
|
||||
|
||||
l_cur = l_cur->ifa_next;
|
||||
++l_num;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static int interpretAddr(struct nlmsghdr *p_hdr, struct ifaddrs **p_resultList, int p_numLinks)
|
||||
{
|
||||
struct ifaddrmsg *l_info = (struct ifaddrmsg *)NLMSG_DATA(p_hdr);
|
||||
struct ifaddrs *l_interface = findInterface(l_info->ifa_index, p_resultList, p_numLinks);
|
||||
|
||||
size_t l_nameSize = 0;
|
||||
size_t l_addrSize = 0;
|
||||
|
||||
int l_addedNetmask = 0;
|
||||
|
||||
size_t l_rtaSize = NLMSG_PAYLOAD(p_hdr, sizeof(struct ifaddrmsg));
|
||||
struct rtattr *l_rta;
|
||||
for(l_rta = IFLA_RTA(l_info); RTA_OK(l_rta, l_rtaSize); l_rta = RTA_NEXT(l_rta, l_rtaSize))
|
||||
{
|
||||
void *l_rtaData = RTA_DATA(l_rta);
|
||||
size_t l_rtaDataSize = RTA_PAYLOAD(l_rta);
|
||||
if(l_info->ifa_family == AF_PACKET)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
switch(l_rta->rta_type)
|
||||
{
|
||||
case IFA_ADDRESS:
|
||||
case IFA_LOCAL:
|
||||
if((l_info->ifa_family == AF_INET || l_info->ifa_family == AF_INET6) && !l_addedNetmask)
|
||||
{ // make room for netmask
|
||||
l_addrSize += NLMSG_ALIGN(calcAddrLen(l_info->ifa_family, l_rtaDataSize));
|
||||
l_addedNetmask = 1;
|
||||
}
|
||||
case IFA_BROADCAST:
|
||||
l_addrSize += NLMSG_ALIGN(calcAddrLen(l_info->ifa_family, l_rtaDataSize));
|
||||
break;
|
||||
case IFA_LABEL:
|
||||
l_nameSize += NLMSG_ALIGN(l_rtaSize + 1);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
struct ifaddrs *l_entry = malloc(sizeof(struct ifaddrs) + l_nameSize + l_addrSize);
|
||||
if (l_entry == NULL)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
memset(l_entry, 0, sizeof(struct ifaddrs));
|
||||
l_entry->ifa_name = (l_interface ? l_interface->ifa_name : "");
|
||||
|
||||
char *l_name = ((char *)l_entry) + sizeof(struct ifaddrs);
|
||||
char *l_addr = l_name + l_nameSize;
|
||||
|
||||
l_entry->ifa_flags = l_info->ifa_flags;
|
||||
if(l_interface)
|
||||
{
|
||||
l_entry->ifa_flags |= l_interface->ifa_flags;
|
||||
}
|
||||
|
||||
l_rtaSize = NLMSG_PAYLOAD(p_hdr, sizeof(struct ifaddrmsg));
|
||||
for(l_rta = IFLA_RTA(l_info); RTA_OK(l_rta, l_rtaSize); l_rta = RTA_NEXT(l_rta, l_rtaSize))
|
||||
{
|
||||
void *l_rtaData = RTA_DATA(l_rta);
|
||||
size_t l_rtaDataSize = RTA_PAYLOAD(l_rta);
|
||||
switch(l_rta->rta_type)
|
||||
{
|
||||
case IFA_ADDRESS:
|
||||
case IFA_BROADCAST:
|
||||
case IFA_LOCAL:
|
||||
{
|
||||
size_t l_addrLen = calcAddrLen(l_info->ifa_family, l_rtaDataSize);
|
||||
makeSockaddr(l_info->ifa_family, (struct sockaddr *)l_addr, l_rtaData, l_rtaDataSize);
|
||||
if(l_info->ifa_family == AF_INET6)
|
||||
{
|
||||
if(IN6_IS_ADDR_LINKLOCAL((struct in6_addr *)l_rtaData) || IN6_IS_ADDR_MC_LINKLOCAL((struct in6_addr *)l_rtaData))
|
||||
{
|
||||
((struct sockaddr_in6 *)l_addr)->sin6_scope_id = l_info->ifa_index;
|
||||
}
|
||||
}
|
||||
|
||||
if(l_rta->rta_type == IFA_ADDRESS)
|
||||
{ // apparently in a point-to-point network IFA_ADDRESS contains the dest address and IFA_LOCAL contains the local address
|
||||
if(l_entry->ifa_addr)
|
||||
{
|
||||
l_entry->ifa_dstaddr = (struct sockaddr *)l_addr;
|
||||
}
|
||||
else
|
||||
{
|
||||
l_entry->ifa_addr = (struct sockaddr *)l_addr;
|
||||
}
|
||||
}
|
||||
else if(l_rta->rta_type == IFA_LOCAL)
|
||||
{
|
||||
if(l_entry->ifa_addr)
|
||||
{
|
||||
l_entry->ifa_dstaddr = l_entry->ifa_addr;
|
||||
}
|
||||
l_entry->ifa_addr = (struct sockaddr *)l_addr;
|
||||
}
|
||||
else
|
||||
{
|
||||
l_entry->ifa_broadaddr = (struct sockaddr *)l_addr;
|
||||
}
|
||||
l_addr += NLMSG_ALIGN(l_addrLen);
|
||||
break;
|
||||
}
|
||||
case IFA_LABEL:
|
||||
strncpy(l_name, l_rtaData, l_rtaDataSize);
|
||||
l_name[l_rtaDataSize] = '\0';
|
||||
l_entry->ifa_name = l_name;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(l_entry->ifa_addr && (l_entry->ifa_addr->sa_family == AF_INET || l_entry->ifa_addr->sa_family == AF_INET6))
|
||||
{
|
||||
unsigned l_maxPrefix = (l_entry->ifa_addr->sa_family == AF_INET ? 32 : 128);
|
||||
unsigned l_prefix = (l_info->ifa_prefixlen > l_maxPrefix ? l_maxPrefix : l_info->ifa_prefixlen);
|
||||
char l_mask[16] = {0};
|
||||
unsigned i;
|
||||
for(i=0; i<(l_prefix/8); ++i)
|
||||
{
|
||||
l_mask[i] = 0xff;
|
||||
}
|
||||
if(l_prefix % 8)
|
||||
{
|
||||
l_mask[i] = 0xff << (8 - (l_prefix % 8));
|
||||
}
|
||||
|
||||
makeSockaddr(l_entry->ifa_addr->sa_family, (struct sockaddr *)l_addr, l_mask, l_maxPrefix / 8);
|
||||
l_entry->ifa_netmask = (struct sockaddr *)l_addr;
|
||||
}
|
||||
|
||||
addToEnd(p_resultList, l_entry);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int interpretLinks(int p_socket, NetlinkList *p_netlinkList, struct ifaddrs **p_resultList)
|
||||
{
|
||||
int l_numLinks = 0;
|
||||
pid_t l_pid = getpid();
|
||||
for(; p_netlinkList; p_netlinkList = p_netlinkList->m_next)
|
||||
{
|
||||
unsigned int l_nlsize = p_netlinkList->m_size;
|
||||
struct nlmsghdr *l_hdr;
|
||||
for(l_hdr = p_netlinkList->m_data; NLMSG_OK(l_hdr, l_nlsize); l_hdr = NLMSG_NEXT(l_hdr, l_nlsize))
|
||||
{
|
||||
if((pid_t)l_hdr->nlmsg_pid != l_pid || (int)l_hdr->nlmsg_seq != p_socket)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if(l_hdr->nlmsg_type == NLMSG_DONE)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
if(l_hdr->nlmsg_type == RTM_NEWLINK)
|
||||
{
|
||||
if(interpretLink(l_hdr, p_resultList) == -1)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
++l_numLinks;
|
||||
}
|
||||
}
|
||||
}
|
||||
return l_numLinks;
|
||||
}
|
||||
|
||||
static int interpretAddrs(int p_socket, NetlinkList *p_netlinkList, struct ifaddrs **p_resultList, int p_numLinks)
|
||||
{
|
||||
pid_t l_pid = getpid();
|
||||
for(; p_netlinkList; p_netlinkList = p_netlinkList->m_next)
|
||||
{
|
||||
unsigned int l_nlsize = p_netlinkList->m_size;
|
||||
struct nlmsghdr *l_hdr;
|
||||
for(l_hdr = p_netlinkList->m_data; NLMSG_OK(l_hdr, l_nlsize); l_hdr = NLMSG_NEXT(l_hdr, l_nlsize))
|
||||
{
|
||||
if((pid_t)l_hdr->nlmsg_pid != l_pid || (int)l_hdr->nlmsg_seq != p_socket)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if(l_hdr->nlmsg_type == NLMSG_DONE)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
if(l_hdr->nlmsg_type == RTM_NEWADDR)
|
||||
{
|
||||
if (interpretAddr(l_hdr, p_resultList, p_numLinks) == -1)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int getifaddrs(struct ifaddrs **ifap)
|
||||
{
|
||||
if(!ifap)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
*ifap = NULL;
|
||||
|
||||
int l_socket = netlink_socket();
|
||||
if(l_socket < 0)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
NetlinkList *l_linkResults = getResultList(l_socket, RTM_GETLINK);
|
||||
if(!l_linkResults)
|
||||
{
|
||||
close(l_socket);
|
||||
return -1;
|
||||
}
|
||||
|
||||
NetlinkList *l_addrResults = getResultList(l_socket, RTM_GETADDR);
|
||||
if(!l_addrResults)
|
||||
{
|
||||
close(l_socket);
|
||||
freeResultList(l_linkResults);
|
||||
return -1;
|
||||
}
|
||||
|
||||
int l_result = 0;
|
||||
int l_numLinks = interpretLinks(l_socket, l_linkResults, ifap);
|
||||
if(l_numLinks == -1 || interpretAddrs(l_socket, l_addrResults, ifap, l_numLinks) == -1)
|
||||
{
|
||||
l_result = -1;
|
||||
}
|
||||
|
||||
freeResultList(l_linkResults);
|
||||
freeResultList(l_addrResults);
|
||||
close(l_socket);
|
||||
return l_result;
|
||||
}
|
||||
|
||||
void freeifaddrs(struct ifaddrs *ifa)
|
||||
{
|
||||
struct ifaddrs *l_cur;
|
||||
while(ifa)
|
||||
{
|
||||
l_cur = ifa;
|
||||
ifa = ifa->ifa_next;
|
||||
free(l_cur);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
/*
|
||||
* Copyright (c) 1995, 1999
|
||||
* Berkeley Software Design, Inc. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY Berkeley Software Design, Inc. ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL Berkeley Software Design, Inc. BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* BSDI ifaddrs.h,v 2.5 2000/02/23 14:51:59 dab Exp
|
||||
*/
|
||||
|
||||
#ifndef _IFADDRS_H_
|
||||
#define _IFADDRS_H_
|
||||
|
||||
struct ifaddrs {
|
||||
struct ifaddrs *ifa_next;
|
||||
char *ifa_name;
|
||||
unsigned int ifa_flags;
|
||||
struct sockaddr *ifa_addr;
|
||||
struct sockaddr *ifa_netmask;
|
||||
struct sockaddr *ifa_dstaddr;
|
||||
void *ifa_data;
|
||||
};
|
||||
|
||||
/*
|
||||
* This may have been defined in <net/if.h>. Note that if <net/if.h> is
|
||||
* to be included it must be included before this header file.
|
||||
*/
|
||||
#ifndef ifa_broadaddr
|
||||
#define ifa_broadaddr ifa_dstaddr /* broadcast address interface */
|
||||
#endif
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
|
||||
__BEGIN_DECLS
|
||||
extern int getifaddrs(struct ifaddrs **ifap);
|
||||
extern void freeifaddrs(struct ifaddrs *ifa);
|
||||
__END_DECLS
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,526 @@
|
||||
Libwebsockets and included programs are provided under the terms of the GNU
|
||||
Library General Public License (LGPL) 2.1, with the following exceptions:
|
||||
|
||||
1) Static linking of programs with the libwebsockets library does not
|
||||
constitute a derivative work and does not require the author to provide
|
||||
source code for the program, use the shared libwebsockets libraries, or
|
||||
link their program against a user-supplied version of libwebsockets.
|
||||
|
||||
If you link the program to a modified version of libwebsockets, then the
|
||||
changes to libwebsockets must be provided under the terms of the LGPL in
|
||||
sections 1, 2, and 4.
|
||||
|
||||
2) You do not have to provide a copy of the libwebsockets license with
|
||||
programs that are linked to the libwebsockets library, nor do you have to
|
||||
identify the libwebsockets license in your program or documentation as
|
||||
required by section 6 of the LGPL.
|
||||
|
||||
However, programs must still identify their use of libwebsockets. The
|
||||
following example statement can be included in user documentation to
|
||||
satisfy this requirement:
|
||||
|
||||
"[program] is based in part on the work of the libwebsockets project
|
||||
(http://libwebsockets.org)"
|
||||
|
||||
GNU LESSER GENERAL PUBLIC LICENSE
|
||||
Version 2.1, February 1999
|
||||
|
||||
Copyright (C) 1991, 1999 Free Software Foundation, Inc.
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
Everyone is permitted to copy and distribute verbatim copies
|
||||
of this license document, but changing it is not allowed.
|
||||
|
||||
[This is the first released version of the Lesser GPL. It also counts
|
||||
as the successor of the GNU Library Public License, version 2, hence
|
||||
the version number 2.1.]
|
||||
|
||||
Preamble
|
||||
|
||||
The licenses for most software are designed to take away your
|
||||
freedom to share and change it. By contrast, the GNU General Public
|
||||
Licenses are intended to guarantee your freedom to share and change
|
||||
free software--to make sure the software is free for all its users.
|
||||
|
||||
This license, the Lesser General Public License, applies to some
|
||||
specially designated software packages--typically libraries--of the
|
||||
Free Software Foundation and other authors who decide to use it. You
|
||||
can use it too, but we suggest you first think carefully about whether
|
||||
this license or the ordinary General Public License is the better
|
||||
strategy to use in any particular case, based on the explanations below.
|
||||
|
||||
When we speak of free software, we are referring to freedom of use,
|
||||
not price. Our General Public Licenses are designed to make sure that
|
||||
you have the freedom to distribute copies of free software (and charge
|
||||
for this service if you wish); that you receive source code or can get
|
||||
it if you want it; that you can change the software and use pieces of
|
||||
it in new free programs; and that you are informed that you can do
|
||||
these things.
|
||||
|
||||
To protect your rights, we need to make restrictions that forbid
|
||||
distributors to deny you these rights or to ask you to surrender these
|
||||
rights. These restrictions translate to certain responsibilities for
|
||||
you if you distribute copies of the library or if you modify it.
|
||||
|
||||
For example, if you distribute copies of the library, whether gratis
|
||||
or for a fee, you must give the recipients all the rights that we gave
|
||||
you. You must make sure that they, too, receive or can get the source
|
||||
code. If you link other code with the library, you must provide
|
||||
complete object files to the recipients, so that they can relink them
|
||||
with the library after making changes to the library and recompiling
|
||||
it. And you must show them these terms so they know their rights.
|
||||
|
||||
We protect your rights with a two-step method: (1) we copyright the
|
||||
library, and (2) we offer you this license, which gives you legal
|
||||
permission to copy, distribute and/or modify the library.
|
||||
|
||||
To protect each distributor, we want to make it very clear that
|
||||
there is no warranty for the free library. Also, if the library is
|
||||
modified by someone else and passed on, the recipients should know
|
||||
that what they have is not the original version, so that the original
|
||||
author's reputation will not be affected by problems that might be
|
||||
introduced by others.
|
||||
|
||||
Finally, software patents pose a constant threat to the existence of
|
||||
any free program. We wish to make sure that a company cannot
|
||||
effectively restrict the users of a free program by obtaining a
|
||||
restrictive license from a patent holder. Therefore, we insist that
|
||||
any patent license obtained for a version of the library must be
|
||||
consistent with the full freedom of use specified in this license.
|
||||
|
||||
Most GNU software, including some libraries, is covered by the
|
||||
ordinary GNU General Public License. This license, the GNU Lesser
|
||||
General Public License, applies to certain designated libraries, and
|
||||
is quite different from the ordinary General Public License. We use
|
||||
this license for certain libraries in order to permit linking those
|
||||
libraries into non-free programs.
|
||||
|
||||
When a program is linked with a library, whether statically or using
|
||||
a shared library, the combination of the two is legally speaking a
|
||||
combined work, a derivative of the original library. The ordinary
|
||||
General Public License therefore permits such linking only if the
|
||||
entire combination fits its criteria of freedom. The Lesser General
|
||||
Public License permits more lax criteria for linking other code with
|
||||
the library.
|
||||
|
||||
We call this license the "Lesser" General Public License because it
|
||||
does Less to protect the user's freedom than the ordinary General
|
||||
Public License. It also provides other free software developers Less
|
||||
of an advantage over competing non-free programs. These disadvantages
|
||||
are the reason we use the ordinary General Public License for many
|
||||
libraries. However, the Lesser license provides advantages in certain
|
||||
special circumstances.
|
||||
|
||||
For example, on rare occasions, there may be a special need to
|
||||
encourage the widest possible use of a certain library, so that it becomes
|
||||
a de-facto standard. To achieve this, non-free programs must be
|
||||
allowed to use the library. A more frequent case is that a free
|
||||
library does the same job as widely used non-free libraries. In this
|
||||
case, there is little to gain by limiting the free library to free
|
||||
software only, so we use the Lesser General Public License.
|
||||
|
||||
In other cases, permission to use a particular library in non-free
|
||||
programs enables a greater number of people to use a large body of
|
||||
free software. For example, permission to use the GNU C Library in
|
||||
non-free programs enables many more people to use the whole GNU
|
||||
operating system, as well as its variant, the GNU/Linux operating
|
||||
system.
|
||||
|
||||
Although the Lesser General Public License is Less protective of the
|
||||
users' freedom, it does ensure that the user of a program that is
|
||||
linked with the Library has the freedom and the wherewithal to run
|
||||
that program using a modified version of the Library.
|
||||
|
||||
The precise terms and conditions for copying, distribution and
|
||||
modification follow. Pay close attention to the difference between a
|
||||
"work based on the library" and a "work that uses the library". The
|
||||
former contains code derived from the library, whereas the latter must
|
||||
be combined with the library in order to run.
|
||||
|
||||
GNU LESSER GENERAL PUBLIC LICENSE
|
||||
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
||||
|
||||
0. This License Agreement applies to any software library or other
|
||||
program which contains a notice placed by the copyright holder or
|
||||
other authorized party saying it may be distributed under the terms of
|
||||
this Lesser General Public License (also called "this License").
|
||||
Each licensee is addressed as "you".
|
||||
|
||||
A "library" means a collection of software functions and/or data
|
||||
prepared so as to be conveniently linked with application programs
|
||||
(which use some of those functions and data) to form executables.
|
||||
|
||||
The "Library", below, refers to any such software library or work
|
||||
which has been distributed under these terms. A "work based on the
|
||||
Library" means either the Library or any derivative work under
|
||||
copyright law: that is to say, a work containing the Library or a
|
||||
portion of it, either verbatim or with modifications and/or translated
|
||||
straightforwardly into another language. (Hereinafter, translation is
|
||||
included without limitation in the term "modification".)
|
||||
|
||||
"Source code" for a work means the preferred form of the work for
|
||||
making modifications to it. For a library, complete source code means
|
||||
all the source code for all modules it contains, plus any associated
|
||||
interface definition files, plus the scripts used to control compilation
|
||||
and installation of the library.
|
||||
|
||||
Activities other than copying, distribution and modification are not
|
||||
covered by this License; they are outside its scope. The act of
|
||||
running a program using the Library is not restricted, and output from
|
||||
such a program is covered only if its contents constitute a work based
|
||||
on the Library (independent of the use of the Library in a tool for
|
||||
writing it). Whether that is true depends on what the Library does
|
||||
and what the program that uses the Library does.
|
||||
|
||||
1. You may copy and distribute verbatim copies of the Library's
|
||||
complete source code as you receive it, in any medium, provided that
|
||||
you conspicuously and appropriately publish on each copy an
|
||||
appropriate copyright notice and disclaimer of warranty; keep intact
|
||||
all the notices that refer to this License and to the absence of any
|
||||
warranty; and distribute a copy of this License along with the
|
||||
Library.
|
||||
|
||||
You may charge a fee for the physical act of transferring a copy,
|
||||
and you may at your option offer warranty protection in exchange for a
|
||||
fee.
|
||||
|
||||
2. You may modify your copy or copies of the Library or any portion
|
||||
of it, thus forming a work based on the Library, and copy and
|
||||
distribute such modifications or work under the terms of Section 1
|
||||
above, provided that you also meet all of these conditions:
|
||||
|
||||
a) The modified work must itself be a software library.
|
||||
|
||||
b) You must cause the files modified to carry prominent notices
|
||||
stating that you changed the files and the date of any change.
|
||||
|
||||
c) You must cause the whole of the work to be licensed at no
|
||||
charge to all third parties under the terms of this License.
|
||||
|
||||
d) If a facility in the modified Library refers to a function or a
|
||||
table of data to be supplied by an application program that uses
|
||||
the facility, other than as an argument passed when the facility
|
||||
is invoked, then you must make a good faith effort to ensure that,
|
||||
in the event an application does not supply such function or
|
||||
table, the facility still operates, and performs whatever part of
|
||||
its purpose remains meaningful.
|
||||
|
||||
(For example, a function in a library to compute square roots has
|
||||
a purpose that is entirely well-defined independent of the
|
||||
application. Therefore, Subsection 2d requires that any
|
||||
application-supplied function or table used by this function must
|
||||
be optional: if the application does not supply it, the square
|
||||
root function must still compute square roots.)
|
||||
|
||||
These requirements apply to the modified work as a whole. If
|
||||
identifiable sections of that work are not derived from the Library,
|
||||
and can be reasonably considered independent and separate works in
|
||||
themselves, then this License, and its terms, do not apply to those
|
||||
sections when you distribute them as separate works. But when you
|
||||
distribute the same sections as part of a whole which is a work based
|
||||
on the Library, the distribution of the whole must be on the terms of
|
||||
this License, whose permissions for other licensees extend to the
|
||||
entire whole, and thus to each and every part regardless of who wrote
|
||||
it.
|
||||
|
||||
Thus, it is not the intent of this section to claim rights or contest
|
||||
your rights to work written entirely by you; rather, the intent is to
|
||||
exercise the right to control the distribution of derivative or
|
||||
collective works based on the Library.
|
||||
|
||||
In addition, mere aggregation of another work not based on the Library
|
||||
with the Library (or with a work based on the Library) on a volume of
|
||||
a storage or distribution medium does not bring the other work under
|
||||
the scope of this License.
|
||||
|
||||
3. You may opt to apply the terms of the ordinary GNU General Public
|
||||
License instead of this License to a given copy of the Library. To do
|
||||
this, you must alter all the notices that refer to this License, so
|
||||
that they refer to the ordinary GNU General Public License, version 2,
|
||||
instead of to this License. (If a newer version than version 2 of the
|
||||
ordinary GNU General Public License has appeared, then you can specify
|
||||
that version instead if you wish.) Do not make any other change in
|
||||
these notices.
|
||||
|
||||
Once this change is made in a given copy, it is irreversible for
|
||||
that copy, so the ordinary GNU General Public License applies to all
|
||||
subsequent copies and derivative works made from that copy.
|
||||
|
||||
This option is useful when you wish to copy part of the code of
|
||||
the Library into a program that is not a library.
|
||||
|
||||
4. You may copy and distribute the Library (or a portion or
|
||||
derivative of it, under Section 2) in object code or executable form
|
||||
under the terms of Sections 1 and 2 above provided that you accompany
|
||||
it with the complete corresponding machine-readable source code, which
|
||||
must be distributed under the terms of Sections 1 and 2 above on a
|
||||
medium customarily used for software interchange.
|
||||
|
||||
If distribution of object code is made by offering access to copy
|
||||
from a designated place, then offering equivalent access to copy the
|
||||
source code from the same place satisfies the requirement to
|
||||
distribute the source code, even though third parties are not
|
||||
compelled to copy the source along with the object code.
|
||||
|
||||
5. A program that contains no derivative of any portion of the
|
||||
Library, but is designed to work with the Library by being compiled or
|
||||
linked with it, is called a "work that uses the Library". Such a
|
||||
work, in isolation, is not a derivative work of the Library, and
|
||||
therefore falls outside the scope of this License.
|
||||
|
||||
However, linking a "work that uses the Library" with the Library
|
||||
creates an executable that is a derivative of the Library (because it
|
||||
contains portions of the Library), rather than a "work that uses the
|
||||
library". The executable is therefore covered by this License.
|
||||
Section 6 states terms for distribution of such executables.
|
||||
|
||||
When a "work that uses the Library" uses material from a header file
|
||||
that is part of the Library, the object code for the work may be a
|
||||
derivative work of the Library even though the source code is not.
|
||||
Whether this is true is especially significant if the work can be
|
||||
linked without the Library, or if the work is itself a library. The
|
||||
threshold for this to be true is not precisely defined by law.
|
||||
|
||||
If such an object file uses only numerical parameters, data
|
||||
structure layouts and accessors, and small macros and small inline
|
||||
functions (ten lines or less in length), then the use of the object
|
||||
file is unrestricted, regardless of whether it is legally a derivative
|
||||
work. (Executables containing this object code plus portions of the
|
||||
Library will still fall under Section 6.)
|
||||
|
||||
Otherwise, if the work is a derivative of the Library, you may
|
||||
distribute the object code for the work under the terms of Section 6.
|
||||
Any executables containing that work also fall under Section 6,
|
||||
whether or not they are linked directly with the Library itself.
|
||||
|
||||
6. As an exception to the Sections above, you may also combine or
|
||||
link a "work that uses the Library" with the Library to produce a
|
||||
work containing portions of the Library, and distribute that work
|
||||
under terms of your choice, provided that the terms permit
|
||||
modification of the work for the customer's own use and reverse
|
||||
engineering for debugging such modifications.
|
||||
|
||||
You must give prominent notice with each copy of the work that the
|
||||
Library is used in it and that the Library and its use are covered by
|
||||
this License. You must supply a copy of this License. If the work
|
||||
during execution displays copyright notices, you must include the
|
||||
copyright notice for the Library among them, as well as a reference
|
||||
directing the user to the copy of this License. Also, you must do one
|
||||
of these things:
|
||||
|
||||
a) Accompany the work with the complete corresponding
|
||||
machine-readable source code for the Library including whatever
|
||||
changes were used in the work (which must be distributed under
|
||||
Sections 1 and 2 above); and, if the work is an executable linked
|
||||
with the Library, with the complete machine-readable "work that
|
||||
uses the Library", as object code and/or source code, so that the
|
||||
user can modify the Library and then relink to produce a modified
|
||||
executable containing the modified Library. (It is understood
|
||||
that the user who changes the contents of definitions files in the
|
||||
Library will not necessarily be able to recompile the application
|
||||
to use the modified definitions.)
|
||||
|
||||
b) Use a suitable shared library mechanism for linking with the
|
||||
Library. A suitable mechanism is one that (1) uses at run time a
|
||||
copy of the library already present on the user's computer system,
|
||||
rather than copying library functions into the executable, and (2)
|
||||
will operate properly with a modified version of the library, if
|
||||
the user installs one, as long as the modified version is
|
||||
interface-compatible with the version that the work was made with.
|
||||
|
||||
c) Accompany the work with a written offer, valid for at
|
||||
least three years, to give the same user the materials
|
||||
specified in Subsection 6a, above, for a charge no more
|
||||
than the cost of performing this distribution.
|
||||
|
||||
d) If distribution of the work is made by offering access to copy
|
||||
from a designated place, offer equivalent access to copy the above
|
||||
specified materials from the same place.
|
||||
|
||||
e) Verify that the user has already received a copy of these
|
||||
materials or that you have already sent this user a copy.
|
||||
|
||||
For an executable, the required form of the "work that uses the
|
||||
Library" must include any data and utility programs needed for
|
||||
reproducing the executable from it. However, as a special exception,
|
||||
the materials to be distributed need not include anything that is
|
||||
normally distributed (in either source or binary form) with the major
|
||||
components (compiler, kernel, and so on) of the operating system on
|
||||
which the executable runs, unless that component itself accompanies
|
||||
the executable.
|
||||
|
||||
It may happen that this requirement contradicts the license
|
||||
restrictions of other proprietary libraries that do not normally
|
||||
accompany the operating system. Such a contradiction means you cannot
|
||||
use both them and the Library together in an executable that you
|
||||
distribute.
|
||||
|
||||
7. You may place library facilities that are a work based on the
|
||||
Library side-by-side in a single library together with other library
|
||||
facilities not covered by this License, and distribute such a combined
|
||||
library, provided that the separate distribution of the work based on
|
||||
the Library and of the other library facilities is otherwise
|
||||
permitted, and provided that you do these two things:
|
||||
|
||||
a) Accompany the combined library with a copy of the same work
|
||||
based on the Library, uncombined with any other library
|
||||
facilities. This must be distributed under the terms of the
|
||||
Sections above.
|
||||
|
||||
b) Give prominent notice with the combined library of the fact
|
||||
that part of it is a work based on the Library, and explaining
|
||||
where to find the accompanying uncombined form of the same work.
|
||||
|
||||
8. You may not copy, modify, sublicense, link with, or distribute
|
||||
the Library except as expressly provided under this License. Any
|
||||
attempt otherwise to copy, modify, sublicense, link with, or
|
||||
distribute the Library is void, and will automatically terminate your
|
||||
rights under this License. However, parties who have received copies,
|
||||
or rights, from you under this License will not have their licenses
|
||||
terminated so long as such parties remain in full compliance.
|
||||
|
||||
9. You are not required to accept this License, since you have not
|
||||
signed it. However, nothing else grants you permission to modify or
|
||||
distribute the Library or its derivative works. These actions are
|
||||
prohibited by law if you do not accept this License. Therefore, by
|
||||
modifying or distributing the Library (or any work based on the
|
||||
Library), you indicate your acceptance of this License to do so, and
|
||||
all its terms and conditions for copying, distributing or modifying
|
||||
the Library or works based on it.
|
||||
|
||||
10. Each time you redistribute the Library (or any work based on the
|
||||
Library), the recipient automatically receives a license from the
|
||||
original licensor to copy, distribute, link with or modify the Library
|
||||
subject to these terms and conditions. You may not impose any further
|
||||
restrictions on the recipients' exercise of the rights granted herein.
|
||||
You are not responsible for enforcing compliance by third parties with
|
||||
this License.
|
||||
|
||||
11. If, as a consequence of a court judgment or allegation of patent
|
||||
infringement or for any other reason (not limited to patent issues),
|
||||
conditions are imposed on you (whether by court order, agreement or
|
||||
otherwise) that contradict the conditions of this License, they do not
|
||||
excuse you from the conditions of this License. If you cannot
|
||||
distribute so as to satisfy simultaneously your obligations under this
|
||||
License and any other pertinent obligations, then as a consequence you
|
||||
may not distribute the Library at all. For example, if a patent
|
||||
license would not permit royalty-free redistribution of the Library by
|
||||
all those who receive copies directly or indirectly through you, then
|
||||
the only way you could satisfy both it and this License would be to
|
||||
refrain entirely from distribution of the Library.
|
||||
|
||||
If any portion of this section is held invalid or unenforceable under any
|
||||
particular circumstance, the balance of the section is intended to apply,
|
||||
and the section as a whole is intended to apply in other circumstances.
|
||||
|
||||
It is not the purpose of this section to induce you to infringe any
|
||||
patents or other property right claims or to contest validity of any
|
||||
such claims; this section has the sole purpose of protecting the
|
||||
integrity of the free software distribution system which is
|
||||
implemented by public license practices. Many people have made
|
||||
generous contributions to the wide range of software distributed
|
||||
through that system in reliance on consistent application of that
|
||||
system; it is up to the author/donor to decide if he or she is willing
|
||||
to distribute software through any other system and a licensee cannot
|
||||
impose that choice.
|
||||
|
||||
This section is intended to make thoroughly clear what is believed to
|
||||
be a consequence of the rest of this License.
|
||||
|
||||
12. If the distribution and/or use of the Library is restricted in
|
||||
certain countries either by patents or by copyrighted interfaces, the
|
||||
original copyright holder who places the Library under this License may add
|
||||
an explicit geographical distribution limitation excluding those countries,
|
||||
so that distribution is permitted only in or among countries not thus
|
||||
excluded. In such case, this License incorporates the limitation as if
|
||||
written in the body of this License.
|
||||
|
||||
13. The Free Software Foundation may publish revised and/or new
|
||||
versions of the Lesser General Public License from time to time.
|
||||
Such new versions will be similar in spirit to the present version,
|
||||
but may differ in detail to address new problems or concerns.
|
||||
|
||||
Each version is given a distinguishing version number. If the Library
|
||||
specifies a version number of this License which applies to it and
|
||||
"any later version", you have the option of following the terms and
|
||||
conditions either of that version or of any later version published by
|
||||
the Free Software Foundation. If the Library does not specify a
|
||||
license version number, you may choose any version ever published by
|
||||
the Free Software Foundation.
|
||||
|
||||
14. If you wish to incorporate parts of the Library into other free
|
||||
programs whose distribution conditions are incompatible with these,
|
||||
write to the author to ask for permission. For software which is
|
||||
copyrighted by the Free Software Foundation, write to the Free
|
||||
Software Foundation; we sometimes make exceptions for this. Our
|
||||
decision will be guided by the two goals of preserving the free status
|
||||
of all derivatives of our free software and of promoting the sharing
|
||||
and reuse of software generally.
|
||||
|
||||
NO WARRANTY
|
||||
|
||||
15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
|
||||
WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
|
||||
EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
|
||||
OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
|
||||
KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
|
||||
LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
|
||||
THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
|
||||
|
||||
16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
|
||||
WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
|
||||
AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
|
||||
FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
|
||||
CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
|
||||
LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
|
||||
RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
|
||||
FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
|
||||
SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
|
||||
DAMAGES.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
How to Apply These Terms to Your New Libraries
|
||||
|
||||
If you develop a new library, and you want it to be of the greatest
|
||||
possible use to the public, we recommend making it free software that
|
||||
everyone can redistribute and change. You can do so by permitting
|
||||
redistribution under these terms (or, alternatively, under the terms of the
|
||||
ordinary General Public License).
|
||||
|
||||
To apply these terms, attach the following notices to the library. It is
|
||||
safest to attach them to the start of each source file to most effectively
|
||||
convey the exclusion of warranty; and each file should have at least the
|
||||
"copyright" line and a pointer to where the full notice is found.
|
||||
|
||||
<one line to give the library's name and a brief idea of what it does.>
|
||||
Copyright (C) <year> <name of author>
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
Also add information on how to contact you by electronic and paper mail.
|
||||
|
||||
You should also get your employer (if you work as a programmer) or your
|
||||
school, if any, to sign a "copyright disclaimer" for the library, if
|
||||
necessary. Here is a sample; alter the names:
|
||||
|
||||
Yoyodyne, Inc., hereby disclaims all copyright interest in the
|
||||
library `Frob' (a library for tweaking knobs) written by James Random Hacker.
|
||||
|
||||
<signature of Ty Coon>, 1 April 1990
|
||||
Ty Coon, President of Vice
|
||||
|
||||
That's all there is to it!
|
||||
@@ -0,0 +1,20 @@
|
||||
This is the libwebsockets C library for lightweight websocket clients and
|
||||
servers. For support, visit
|
||||
|
||||
http://libwebsockets.org
|
||||
|
||||
and consider joining the project mailing list at
|
||||
|
||||
http://ml.libwebsockets.org/mailman/listinfo/libwebsockets
|
||||
|
||||
You can get the latest version of the library from git
|
||||
|
||||
http://git.libwebsockets.org
|
||||
https://github.com/warmcat/libwebsockets
|
||||
|
||||
for more information:
|
||||
|
||||
README.build - information on building the library
|
||||
README.coding - information for writing code using the library
|
||||
README.test-apps - information about the test apps built with the library
|
||||
|
||||
@@ -0,0 +1,93 @@
|
||||
/*
|
||||
* This code originally came from here
|
||||
*
|
||||
* http://base64.sourceforge.net/b64.c
|
||||
*
|
||||
* with the following license:
|
||||
*
|
||||
* LICENCE: Copyright (c) 2001 Bob Trower, Trantor Standard Systems Inc.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person
|
||||
* obtaining a copy of this software and associated
|
||||
* documentation files (the "Software"), to deal in the
|
||||
* Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute,
|
||||
* sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall
|
||||
* be included in all copies or substantial portions of the
|
||||
* Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
|
||||
* KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
|
||||
* WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
|
||||
* PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS
|
||||
* OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
|
||||
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
|
||||
* OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
* VERSION HISTORY:
|
||||
* Bob Trower 08/04/01 -- Create Version 0.00.00B
|
||||
*
|
||||
* I cleaned it up quite a bit to match the (linux kernel) style of the rest
|
||||
* of libwebsockets; this version is under LGPL2 like the rest of libwebsockets
|
||||
* since he explictly allows sublicensing, but I give the URL above so you can
|
||||
* get the original with Bob's super-liberal terms directly if you prefer.
|
||||
*/
|
||||
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include "private-libwebsockets.h"
|
||||
|
||||
static const char encode[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
|
||||
"abcdefghijklmnopqrstuvwxyz0123456789+/";
|
||||
static const char decode[] = "|$$$}rstuvwxyz{$$$$$$$>?@ABCDEFGHIJKLMNOPQRSTUVW"
|
||||
"$$$$$$XYZ[\\]^_`abcdefghijklmnopq";
|
||||
|
||||
LWS_VISIBLE int
|
||||
lws_b64_encode_string(const char *in, int in_len, char *out, int out_size)
|
||||
{
|
||||
unsigned char triple[3];
|
||||
int i;
|
||||
int len;
|
||||
int line = 0;
|
||||
int done = 0;
|
||||
|
||||
while (in_len) {
|
||||
len = 0;
|
||||
for (i = 0; i < 3; i++) {
|
||||
if (in_len) {
|
||||
triple[i] = *in++;
|
||||
len++;
|
||||
in_len--;
|
||||
} else
|
||||
triple[i] = 0;
|
||||
}
|
||||
if (!len)
|
||||
continue;
|
||||
|
||||
if (done + 4 >= out_size)
|
||||
return -1;
|
||||
|
||||
*out++ = encode[triple[0] >> 2];
|
||||
*out++ = encode[((triple[0] & 0x03) << 4) |
|
||||
((triple[1] & 0xf0) >> 4)];
|
||||
*out++ = (len > 1 ? encode[((triple[1] & 0x0f) << 2) |
|
||||
((triple[2] & 0xc0) >> 6)] : '=');
|
||||
*out++ = (len > 2 ? encode[triple[2] & 0x3f] : '=');
|
||||
|
||||
done += 4;
|
||||
line += 4;
|
||||
}
|
||||
|
||||
if (done + 1 >= out_size)
|
||||
return -1;
|
||||
|
||||
*out++ = '\0';
|
||||
|
||||
return done;
|
||||
}
|
||||
@@ -0,0 +1,441 @@
|
||||
#include "private-libwebsockets.h"
|
||||
|
||||
struct libwebsocket *libwebsocket_client_connect_2(
|
||||
struct libwebsocket_context *context,
|
||||
struct libwebsocket *wsi
|
||||
) {
|
||||
struct libwebsocket_pollfd pfd;
|
||||
#ifdef LWS_USE_IPV6
|
||||
struct sockaddr_in6 server_addr6;
|
||||
struct sockaddr_in6 client_addr6;
|
||||
struct addrinfo hints, *result;
|
||||
#endif
|
||||
struct sockaddr_in server_addr4;
|
||||
struct sockaddr_in client_addr4;
|
||||
struct hostent *server_hostent;
|
||||
|
||||
struct sockaddr *v;
|
||||
int n;
|
||||
int plen = 0;
|
||||
const char *ads;
|
||||
|
||||
lwsl_client("libwebsocket_client_connect_2\n");
|
||||
|
||||
/*
|
||||
* proxy?
|
||||
*/
|
||||
|
||||
if (context->http_proxy_port) {
|
||||
plen = sprintf((char *)context->service_buffer,
|
||||
"CONNECT %s:%u HTTP/1.0\x0d\x0a"
|
||||
"User-agent: libwebsockets\x0d\x0a"
|
||||
/*Proxy-authorization: basic aGVsbG86d29ybGQ= */
|
||||
"\x0d\x0a",
|
||||
lws_hdr_simple_ptr(wsi, _WSI_TOKEN_CLIENT_PEER_ADDRESS),
|
||||
wsi->u.hdr.ah->c_port);
|
||||
ads = context->http_proxy_address;
|
||||
|
||||
#ifdef LWS_USE_IPV6
|
||||
if (LWS_IPV6_ENABLED(context))
|
||||
server_addr6.sin6_port = htons(context->http_proxy_port);
|
||||
else
|
||||
#endif
|
||||
server_addr4.sin_port = htons(context->http_proxy_port);
|
||||
|
||||
} else {
|
||||
ads = lws_hdr_simple_ptr(wsi, _WSI_TOKEN_CLIENT_PEER_ADDRESS);
|
||||
#ifdef LWS_USE_IPV6
|
||||
if (LWS_IPV6_ENABLED(context))
|
||||
server_addr6.sin6_port = htons(wsi->u.hdr.ah->c_port);
|
||||
else
|
||||
#endif
|
||||
server_addr4.sin_port = htons(wsi->u.hdr.ah->c_port);
|
||||
}
|
||||
|
||||
/*
|
||||
* prepare the actual connection (to the proxy, if any)
|
||||
*/
|
||||
lwsl_client("libwebsocket_client_connect_2: address %s\n", ads);
|
||||
|
||||
#ifdef LWS_USE_IPV6
|
||||
if (LWS_IPV6_ENABLED(context)) {
|
||||
memset(&hints, 0, sizeof(struct addrinfo));
|
||||
n = getaddrinfo(ads, NULL, &hints, &result);
|
||||
if (n) {
|
||||
#ifdef _WIN32
|
||||
lwsl_err("getaddrinfo: %ls\n", gai_strerrorW(n));
|
||||
#else
|
||||
lwsl_err("getaddrinfo: %s\n", gai_strerror(n));
|
||||
#endif
|
||||
goto oom4;
|
||||
}
|
||||
|
||||
server_addr6.sin6_family = AF_INET6;
|
||||
switch (result->ai_family) {
|
||||
case AF_INET:
|
||||
/* map IPv4 to IPv6 */
|
||||
bzero((char *)&server_addr6.sin6_addr,
|
||||
sizeof(struct in6_addr));
|
||||
server_addr6.sin6_addr.s6_addr[10] = 0xff;
|
||||
server_addr6.sin6_addr.s6_addr[11] = 0xff;
|
||||
memcpy(&server_addr6.sin6_addr.s6_addr[12],
|
||||
&((struct sockaddr_in *)result->ai_addr)->sin_addr,
|
||||
sizeof(struct in_addr));
|
||||
break;
|
||||
case AF_INET6:
|
||||
memcpy(&server_addr6.sin6_addr,
|
||||
&((struct sockaddr_in6 *)result->ai_addr)->sin6_addr,
|
||||
sizeof(struct in6_addr));
|
||||
break;
|
||||
default:
|
||||
lwsl_err("Unknown address family\n");
|
||||
freeaddrinfo(result);
|
||||
goto oom4;
|
||||
}
|
||||
|
||||
freeaddrinfo(result);
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
server_hostent = gethostbyname(ads);
|
||||
if (!server_hostent) {
|
||||
lwsl_err("Unable to get host name from %s\n", ads);
|
||||
goto oom4;
|
||||
}
|
||||
|
||||
server_addr4.sin_family = AF_INET;
|
||||
server_addr4.sin_addr =
|
||||
*((struct in_addr *)server_hostent->h_addr);
|
||||
bzero(&server_addr4.sin_zero, 8);
|
||||
}
|
||||
|
||||
if (wsi->sock < 0) {
|
||||
|
||||
#ifdef LWS_USE_IPV6
|
||||
if (LWS_IPV6_ENABLED(context))
|
||||
wsi->sock = socket(AF_INET6, SOCK_STREAM, 0);
|
||||
else
|
||||
#endif
|
||||
wsi->sock = socket(AF_INET, SOCK_STREAM, 0);
|
||||
|
||||
if (wsi->sock < 0) {
|
||||
lwsl_warn("Unable to open socket\n");
|
||||
goto oom4;
|
||||
}
|
||||
|
||||
if (lws_plat_set_socket_options(context, wsi->sock)) {
|
||||
lwsl_err("Failed to set wsi socket options\n");
|
||||
compatible_close(wsi->sock);
|
||||
goto oom4;
|
||||
}
|
||||
|
||||
wsi->mode = LWS_CONNMODE_WS_CLIENT_WAITING_CONNECT;
|
||||
|
||||
insert_wsi_socket_into_fds(context, wsi);
|
||||
|
||||
libwebsocket_set_timeout(wsi,
|
||||
PENDING_TIMEOUT_AWAITING_CONNECT_RESPONSE,
|
||||
AWAITING_TIMEOUT);
|
||||
#ifdef LWS_USE_IPV6
|
||||
if (LWS_IPV6_ENABLED(context)) {
|
||||
v = (struct sockaddr *)&client_addr6;
|
||||
n = sizeof(client_addr6);
|
||||
bzero((char *)v, n);
|
||||
client_addr6.sin6_family = AF_INET6;
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
v = (struct sockaddr *)&client_addr4;
|
||||
n = sizeof(client_addr4);
|
||||
bzero((char *)v, n);
|
||||
client_addr4.sin_family = AF_INET;
|
||||
}
|
||||
|
||||
if (context->iface) {
|
||||
if (interface_to_sa(context, context->iface,
|
||||
(struct sockaddr_in *)v, n) < 0) {
|
||||
lwsl_err("Unable to find interface %s\n",
|
||||
context->iface);
|
||||
compatible_close(wsi->sock);
|
||||
goto failed;
|
||||
}
|
||||
|
||||
if (bind(wsi->sock, v, n) < 0) {
|
||||
lwsl_err("Error binding to interface %s",
|
||||
context->iface);
|
||||
compatible_close(wsi->sock);
|
||||
goto failed;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef LWS_USE_IPV6
|
||||
if (LWS_IPV6_ENABLED(context)) {
|
||||
v = (struct sockaddr *)&server_addr6;
|
||||
n = sizeof(struct sockaddr_in6);
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
v = (struct sockaddr *)&server_addr4;
|
||||
n = sizeof(struct sockaddr);
|
||||
}
|
||||
|
||||
if (connect(wsi->sock, v, n) == -1 || LWS_ERRNO == LWS_EISCONN) {
|
||||
|
||||
if (LWS_ERRNO == LWS_EALREADY || LWS_ERRNO == LWS_EINPROGRESS
|
||||
|| LWS_ERRNO == LWS_EWOULDBLOCK) {
|
||||
lwsl_client("nonblocking connect retry\n");
|
||||
|
||||
/*
|
||||
* must do specifically a POLLOUT poll to hear
|
||||
* about the connect completion
|
||||
*/
|
||||
if (lws_change_pollfd(wsi, 0, LWS_POLLOUT))
|
||||
goto oom4;
|
||||
|
||||
return wsi;
|
||||
}
|
||||
|
||||
if (LWS_ERRNO != LWS_EISCONN) {
|
||||
lwsl_debug("Connect failed errno=%d\n", LWS_ERRNO);
|
||||
goto failed;
|
||||
}
|
||||
}
|
||||
|
||||
lwsl_client("connected\n");
|
||||
|
||||
/* we are connected to server, or proxy */
|
||||
|
||||
if (context->http_proxy_port) {
|
||||
|
||||
/* OK from now on we talk via the proxy, so connect to that */
|
||||
|
||||
/*
|
||||
* (will overwrite existing pointer,
|
||||
* leaving old string/frag there but unreferenced)
|
||||
*/
|
||||
if (lws_hdr_simple_create(wsi, _WSI_TOKEN_CLIENT_PEER_ADDRESS,
|
||||
context->http_proxy_address))
|
||||
goto failed;
|
||||
wsi->u.hdr.ah->c_port = context->http_proxy_port;
|
||||
|
||||
n = send(wsi->sock, context->service_buffer, plen, MSG_NOSIGNAL);
|
||||
if (n < 0) {
|
||||
lwsl_debug("ERROR writing to proxy socket\n");
|
||||
goto failed;
|
||||
}
|
||||
|
||||
libwebsocket_set_timeout(wsi,
|
||||
PENDING_TIMEOUT_AWAITING_PROXY_RESPONSE,
|
||||
AWAITING_TIMEOUT);
|
||||
|
||||
wsi->mode = LWS_CONNMODE_WS_CLIENT_WAITING_PROXY_REPLY;
|
||||
|
||||
return wsi;
|
||||
}
|
||||
|
||||
/*
|
||||
* provoke service to issue the handshake directly
|
||||
* we need to do it this way because in the proxy case, this is the
|
||||
* next state and executed only if and when we get a good proxy
|
||||
* response inside the state machine... but notice in SSL case this
|
||||
* may not have sent anything yet with 0 return, and won't until some
|
||||
* many retries from main loop. To stop that becoming endless,
|
||||
* cover with a timeout.
|
||||
*/
|
||||
|
||||
libwebsocket_set_timeout(wsi,
|
||||
PENDING_TIMEOUT_SENT_CLIENT_HANDSHAKE, AWAITING_TIMEOUT);
|
||||
|
||||
wsi->mode = LWS_CONNMODE_WS_CLIENT_ISSUE_HANDSHAKE;
|
||||
pfd.fd = wsi->sock;
|
||||
pfd.revents = LWS_POLLIN;
|
||||
|
||||
n = libwebsocket_service_fd(context, &pfd);
|
||||
|
||||
if (n < 0)
|
||||
goto failed;
|
||||
|
||||
if (n) /* returns 1 on failure after closing wsi */
|
||||
return NULL;
|
||||
|
||||
return wsi;
|
||||
|
||||
oom4:
|
||||
free(wsi->u.hdr.ah);
|
||||
free(wsi);
|
||||
return NULL;
|
||||
|
||||
failed:
|
||||
libwebsocket_close_and_free_session(context, wsi,
|
||||
LWS_CLOSE_STATUS_NOSTATUS);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* libwebsocket_client_connect() - Connect to another websocket server
|
||||
* @context: Websocket context
|
||||
* @address: Remote server address, eg, "myserver.com"
|
||||
* @port: Port to connect to on the remote server, eg, 80
|
||||
* @ssl_connection: 0 = ws://, 1 = wss:// encrypted, 2 = wss:// allow self
|
||||
* signed certs
|
||||
* @path: Websocket path on server
|
||||
* @host: Hostname on server
|
||||
* @origin: Socket origin name
|
||||
* @protocol: Comma-separated list of protocols being asked for from
|
||||
* the server, or just one. The server will pick the one it
|
||||
* likes best.
|
||||
* @ietf_version_or_minus_one: -1 to ask to connect using the default, latest
|
||||
* protocol supported, or the specific protocol ordinal
|
||||
*
|
||||
* This function creates a connection to a remote server
|
||||
*/
|
||||
|
||||
LWS_VISIBLE struct libwebsocket *
|
||||
libwebsocket_client_connect(struct libwebsocket_context *context,
|
||||
const char *address,
|
||||
int port,
|
||||
int ssl_connection,
|
||||
const char *path,
|
||||
const char *host,
|
||||
const char *origin,
|
||||
const char *protocol,
|
||||
int ietf_version_or_minus_one)
|
||||
{
|
||||
struct libwebsocket *wsi;
|
||||
|
||||
wsi = (struct libwebsocket *) malloc(sizeof(struct libwebsocket));
|
||||
if (wsi == NULL)
|
||||
goto bail;
|
||||
|
||||
memset(wsi, 0, sizeof(*wsi));
|
||||
wsi->sock = -1;
|
||||
|
||||
/* -1 means just use latest supported */
|
||||
|
||||
if (ietf_version_or_minus_one == -1)
|
||||
ietf_version_or_minus_one = SPEC_LATEST_SUPPORTED;
|
||||
|
||||
wsi->ietf_spec_revision = ietf_version_or_minus_one;
|
||||
wsi->user_space = NULL;
|
||||
wsi->state = WSI_STATE_CLIENT_UNCONNECTED;
|
||||
wsi->protocol = NULL;
|
||||
wsi->pending_timeout = NO_PENDING_TIMEOUT;
|
||||
|
||||
#ifdef LWS_OPENSSL_SUPPORT
|
||||
wsi->use_ssl = ssl_connection;
|
||||
#else
|
||||
if (ssl_connection) {
|
||||
lwsl_err("libwebsockets not configured for ssl\n");
|
||||
goto bail;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (lws_allocate_header_table(wsi))
|
||||
goto bail;
|
||||
|
||||
/*
|
||||
* we're not necessarily in a position to action these right away,
|
||||
* stash them... we only need during connect phase so u.hdr is fine
|
||||
*/
|
||||
wsi->u.hdr.ah->c_port = port;
|
||||
if (lws_hdr_simple_create(wsi, _WSI_TOKEN_CLIENT_PEER_ADDRESS, address))
|
||||
goto bail1;
|
||||
|
||||
/* these only need u.hdr lifetime as well */
|
||||
|
||||
if (lws_hdr_simple_create(wsi, _WSI_TOKEN_CLIENT_URI, path))
|
||||
goto bail1;
|
||||
|
||||
if (lws_hdr_simple_create(wsi, _WSI_TOKEN_CLIENT_HOST, host))
|
||||
goto bail1;
|
||||
|
||||
if (origin)
|
||||
if (lws_hdr_simple_create(wsi,
|
||||
_WSI_TOKEN_CLIENT_ORIGIN, origin))
|
||||
goto bail1;
|
||||
/*
|
||||
* this is a list of protocols we tell the server we're okay with
|
||||
* stash it for later when we compare server response with it
|
||||
*/
|
||||
if (protocol)
|
||||
if (lws_hdr_simple_create(wsi,
|
||||
_WSI_TOKEN_CLIENT_SENT_PROTOCOLS, protocol))
|
||||
goto bail1;
|
||||
|
||||
wsi->protocol = &context->protocols[0];
|
||||
|
||||
/*
|
||||
* Check with each extension if it is able to route and proxy this
|
||||
* connection for us. For example, an extension like x-google-mux
|
||||
* can handle this and then we don't need an actual socket for this
|
||||
* connection.
|
||||
*/
|
||||
|
||||
if (lws_ext_callback_for_each_extension_type(context, wsi,
|
||||
LWS_EXT_CALLBACK_CAN_PROXY_CLIENT_CONNECTION,
|
||||
(void *)address, port) > 0) {
|
||||
lwsl_client("libwebsocket_client_connect: ext handling conn\n");
|
||||
|
||||
libwebsocket_set_timeout(wsi,
|
||||
PENDING_TIMEOUT_AWAITING_EXTENSION_CONNECT_RESPONSE,
|
||||
AWAITING_TIMEOUT);
|
||||
|
||||
wsi->mode = LWS_CONNMODE_WS_CLIENT_WAITING_EXTENSION_CONNECT;
|
||||
return wsi;
|
||||
}
|
||||
lwsl_client("libwebsocket_client_connect: direct conn\n");
|
||||
|
||||
return libwebsocket_client_connect_2(context, wsi);
|
||||
|
||||
bail1:
|
||||
free(wsi->u.hdr.ah);
|
||||
bail:
|
||||
free(wsi);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* libwebsocket_client_connect_extended() - Connect to another websocket server
|
||||
* @context: Websocket context
|
||||
* @address: Remote server address, eg, "myserver.com"
|
||||
* @port: Port to connect to on the remote server, eg, 80
|
||||
* @ssl_connection: 0 = ws://, 1 = wss:// encrypted, 2 = wss:// allow self
|
||||
* signed certs
|
||||
* @path: Websocket path on server
|
||||
* @host: Hostname on server
|
||||
* @origin: Socket origin name
|
||||
* @protocol: Comma-separated list of protocols being asked for from
|
||||
* the server, or just one. The server will pick the one it
|
||||
* likes best.
|
||||
* @ietf_version_or_minus_one: -1 to ask to connect using the default, latest
|
||||
* protocol supported, or the specific protocol ordinal
|
||||
* @userdata: Pre-allocated user data
|
||||
*
|
||||
* This function creates a connection to a remote server
|
||||
*/
|
||||
|
||||
LWS_VISIBLE struct libwebsocket *
|
||||
libwebsocket_client_connect_extended(struct libwebsocket_context *context,
|
||||
const char *address,
|
||||
int port,
|
||||
int ssl_connection,
|
||||
const char *path,
|
||||
const char *host,
|
||||
const char *origin,
|
||||
const char *protocol,
|
||||
int ietf_version_or_minus_one,
|
||||
void *userdata)
|
||||
{
|
||||
struct libwebsocket *ws =
|
||||
libwebsocket_client_connect(context, address, port,
|
||||
ssl_connection, path, host, origin, protocol,
|
||||
ietf_version_or_minus_one);
|
||||
|
||||
if (ws && !ws->user_space && userdata)
|
||||
ws->user_space = userdata ;
|
||||
|
||||
return ws ;
|
||||
}
|
||||
@@ -0,0 +1,402 @@
|
||||
/*
|
||||
* libwebsockets - small server side websockets and web server implementation
|
||||
*
|
||||
* Copyright (C) 2010-2014 Andy Green <[email protected]>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation:
|
||||
* version 2.1 of the License.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
||||
* MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#include "private-libwebsockets.h"
|
||||
|
||||
int libwebsocket_client_rx_sm(struct libwebsocket *wsi, unsigned char c)
|
||||
{
|
||||
int callback_action = LWS_CALLBACK_CLIENT_RECEIVE;
|
||||
int handled;
|
||||
struct lws_tokens eff_buf;
|
||||
int m;
|
||||
|
||||
switch (wsi->lws_rx_parse_state) {
|
||||
case LWS_RXPS_NEW:
|
||||
|
||||
switch (wsi->ietf_spec_revision) {
|
||||
|
||||
case 13:
|
||||
wsi->u.ws.opcode = c & 0xf;
|
||||
wsi->u.ws.rsv = (c & 0x70);
|
||||
wsi->u.ws.final = !!((c >> 7) & 1);
|
||||
switch (wsi->u.ws.opcode) {
|
||||
case LWS_WS_OPCODE_07__TEXT_FRAME:
|
||||
case LWS_WS_OPCODE_07__BINARY_FRAME:
|
||||
wsi->u.ws.frame_is_binary = wsi->u.ws.opcode ==
|
||||
LWS_WS_OPCODE_07__BINARY_FRAME;
|
||||
break;
|
||||
}
|
||||
wsi->lws_rx_parse_state = LWS_RXPS_04_FRAME_HDR_LEN;
|
||||
break;
|
||||
|
||||
default:
|
||||
lwsl_err("unknown spec version %02d\n",
|
||||
wsi->ietf_spec_revision);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
|
||||
case LWS_RXPS_04_FRAME_HDR_LEN:
|
||||
|
||||
wsi->u.ws.this_frame_masked = !!(c & 0x80);
|
||||
|
||||
switch (c & 0x7f) {
|
||||
case 126:
|
||||
/* control frames are not allowed to have big lengths */
|
||||
if (wsi->u.ws.opcode & 8)
|
||||
goto illegal_ctl_length;
|
||||
wsi->lws_rx_parse_state = LWS_RXPS_04_FRAME_HDR_LEN16_2;
|
||||
break;
|
||||
case 127:
|
||||
/* control frames are not allowed to have big lengths */
|
||||
if (wsi->u.ws.opcode & 8)
|
||||
goto illegal_ctl_length;
|
||||
wsi->lws_rx_parse_state = LWS_RXPS_04_FRAME_HDR_LEN64_8;
|
||||
break;
|
||||
default:
|
||||
wsi->u.ws.rx_packet_length = c;
|
||||
if (wsi->u.ws.this_frame_masked)
|
||||
wsi->lws_rx_parse_state =
|
||||
LWS_RXPS_07_COLLECT_FRAME_KEY_1;
|
||||
else {
|
||||
if (c)
|
||||
wsi->lws_rx_parse_state =
|
||||
LWS_RXPS_PAYLOAD_UNTIL_LENGTH_EXHAUSTED;
|
||||
else {
|
||||
wsi->lws_rx_parse_state = LWS_RXPS_NEW;
|
||||
goto spill;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case LWS_RXPS_04_FRAME_HDR_LEN16_2:
|
||||
wsi->u.ws.rx_packet_length = c << 8;
|
||||
wsi->lws_rx_parse_state = LWS_RXPS_04_FRAME_HDR_LEN16_1;
|
||||
break;
|
||||
|
||||
case LWS_RXPS_04_FRAME_HDR_LEN16_1:
|
||||
wsi->u.ws.rx_packet_length |= c;
|
||||
if (wsi->u.ws.this_frame_masked)
|
||||
wsi->lws_rx_parse_state =
|
||||
LWS_RXPS_07_COLLECT_FRAME_KEY_1;
|
||||
else {
|
||||
if (wsi->u.ws.rx_packet_length)
|
||||
wsi->lws_rx_parse_state =
|
||||
LWS_RXPS_PAYLOAD_UNTIL_LENGTH_EXHAUSTED;
|
||||
else {
|
||||
wsi->lws_rx_parse_state = LWS_RXPS_NEW;
|
||||
goto spill;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case LWS_RXPS_04_FRAME_HDR_LEN64_8:
|
||||
if (c & 0x80) {
|
||||
lwsl_warn("b63 of length must be zero\n");
|
||||
/* kill the connection */
|
||||
return -1;
|
||||
}
|
||||
#if defined __LP64__
|
||||
wsi->u.ws.rx_packet_length = ((size_t)c) << 56;
|
||||
#else
|
||||
wsi->u.ws.rx_packet_length = 0;
|
||||
#endif
|
||||
wsi->lws_rx_parse_state = LWS_RXPS_04_FRAME_HDR_LEN64_7;
|
||||
break;
|
||||
|
||||
case LWS_RXPS_04_FRAME_HDR_LEN64_7:
|
||||
#if defined __LP64__
|
||||
wsi->u.ws.rx_packet_length |= ((size_t)c) << 48;
|
||||
#endif
|
||||
wsi->lws_rx_parse_state = LWS_RXPS_04_FRAME_HDR_LEN64_6;
|
||||
break;
|
||||
|
||||
case LWS_RXPS_04_FRAME_HDR_LEN64_6:
|
||||
#if defined __LP64__
|
||||
wsi->u.ws.rx_packet_length |= ((size_t)c) << 40;
|
||||
#endif
|
||||
wsi->lws_rx_parse_state = LWS_RXPS_04_FRAME_HDR_LEN64_5;
|
||||
break;
|
||||
|
||||
case LWS_RXPS_04_FRAME_HDR_LEN64_5:
|
||||
#if defined __LP64__
|
||||
wsi->u.ws.rx_packet_length |= ((size_t)c) << 32;
|
||||
#endif
|
||||
wsi->lws_rx_parse_state = LWS_RXPS_04_FRAME_HDR_LEN64_4;
|
||||
break;
|
||||
|
||||
case LWS_RXPS_04_FRAME_HDR_LEN64_4:
|
||||
wsi->u.ws.rx_packet_length |= ((size_t)c) << 24;
|
||||
wsi->lws_rx_parse_state = LWS_RXPS_04_FRAME_HDR_LEN64_3;
|
||||
break;
|
||||
|
||||
case LWS_RXPS_04_FRAME_HDR_LEN64_3:
|
||||
wsi->u.ws.rx_packet_length |= ((size_t)c) << 16;
|
||||
wsi->lws_rx_parse_state = LWS_RXPS_04_FRAME_HDR_LEN64_2;
|
||||
break;
|
||||
|
||||
case LWS_RXPS_04_FRAME_HDR_LEN64_2:
|
||||
wsi->u.ws.rx_packet_length |= ((size_t)c) << 8;
|
||||
wsi->lws_rx_parse_state = LWS_RXPS_04_FRAME_HDR_LEN64_1;
|
||||
break;
|
||||
|
||||
case LWS_RXPS_04_FRAME_HDR_LEN64_1:
|
||||
wsi->u.ws.rx_packet_length |= (size_t)c;
|
||||
if (wsi->u.ws.this_frame_masked)
|
||||
wsi->lws_rx_parse_state =
|
||||
LWS_RXPS_07_COLLECT_FRAME_KEY_1;
|
||||
else {
|
||||
if (wsi->u.ws.rx_packet_length)
|
||||
wsi->lws_rx_parse_state =
|
||||
LWS_RXPS_PAYLOAD_UNTIL_LENGTH_EXHAUSTED;
|
||||
else {
|
||||
wsi->lws_rx_parse_state = LWS_RXPS_NEW;
|
||||
goto spill;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case LWS_RXPS_07_COLLECT_FRAME_KEY_1:
|
||||
wsi->u.ws.frame_masking_nonce_04[0] = c;
|
||||
if (c)
|
||||
wsi->u.ws.all_zero_nonce = 0;
|
||||
wsi->lws_rx_parse_state = LWS_RXPS_07_COLLECT_FRAME_KEY_2;
|
||||
break;
|
||||
|
||||
case LWS_RXPS_07_COLLECT_FRAME_KEY_2:
|
||||
wsi->u.ws.frame_masking_nonce_04[1] = c;
|
||||
if (c)
|
||||
wsi->u.ws.all_zero_nonce = 0;
|
||||
wsi->lws_rx_parse_state = LWS_RXPS_07_COLLECT_FRAME_KEY_3;
|
||||
break;
|
||||
|
||||
case LWS_RXPS_07_COLLECT_FRAME_KEY_3:
|
||||
wsi->u.ws.frame_masking_nonce_04[2] = c;
|
||||
if (c)
|
||||
wsi->u.ws.all_zero_nonce = 0;
|
||||
wsi->lws_rx_parse_state = LWS_RXPS_07_COLLECT_FRAME_KEY_4;
|
||||
break;
|
||||
|
||||
case LWS_RXPS_07_COLLECT_FRAME_KEY_4:
|
||||
wsi->u.ws.frame_masking_nonce_04[3] = c;
|
||||
if (c)
|
||||
wsi->u.ws.all_zero_nonce = 0;
|
||||
|
||||
if (wsi->u.ws.rx_packet_length)
|
||||
wsi->lws_rx_parse_state =
|
||||
LWS_RXPS_PAYLOAD_UNTIL_LENGTH_EXHAUSTED;
|
||||
else {
|
||||
wsi->lws_rx_parse_state = LWS_RXPS_NEW;
|
||||
goto spill;
|
||||
}
|
||||
break;
|
||||
|
||||
case LWS_RXPS_PAYLOAD_UNTIL_LENGTH_EXHAUSTED:
|
||||
|
||||
if (!wsi->u.ws.rx_user_buffer)
|
||||
lwsl_err("NULL client rx_user_buffer\n");
|
||||
|
||||
if ((!wsi->u.ws.this_frame_masked) || wsi->u.ws.all_zero_nonce)
|
||||
wsi->u.ws.rx_user_buffer[LWS_SEND_BUFFER_PRE_PADDING +
|
||||
(wsi->u.ws.rx_user_buffer_head++)] = c;
|
||||
else
|
||||
wsi->u.ws.rx_user_buffer[LWS_SEND_BUFFER_PRE_PADDING +
|
||||
(wsi->u.ws.rx_user_buffer_head++)] =
|
||||
c ^ wsi->u.ws.frame_masking_nonce_04[
|
||||
(wsi->u.ws.frame_mask_index++) & 3];
|
||||
|
||||
if (--wsi->u.ws.rx_packet_length == 0) {
|
||||
/* spill because we have the whole frame */
|
||||
wsi->lws_rx_parse_state = LWS_RXPS_NEW;
|
||||
goto spill;
|
||||
}
|
||||
|
||||
/*
|
||||
* if there's no protocol max frame size given, we are
|
||||
* supposed to default to LWS_MAX_SOCKET_IO_BUF
|
||||
*/
|
||||
|
||||
if (!wsi->protocol->rx_buffer_size &&
|
||||
wsi->u.ws.rx_user_buffer_head !=
|
||||
LWS_MAX_SOCKET_IO_BUF)
|
||||
break;
|
||||
else
|
||||
if (wsi->protocol->rx_buffer_size &&
|
||||
wsi->u.ws.rx_user_buffer_head !=
|
||||
wsi->protocol->rx_buffer_size)
|
||||
break;
|
||||
|
||||
/* spill because we filled our rx buffer */
|
||||
spill:
|
||||
|
||||
handled = 0;
|
||||
|
||||
/*
|
||||
* is this frame a control packet we should take care of at this
|
||||
* layer? If so service it and hide it from the user callback
|
||||
*/
|
||||
|
||||
switch (wsi->u.ws.opcode) {
|
||||
case LWS_WS_OPCODE_07__CLOSE:
|
||||
/* is this an acknowledgement of our close? */
|
||||
if (wsi->state == WSI_STATE_AWAITING_CLOSE_ACK) {
|
||||
/*
|
||||
* fine he has told us he is closing too, let's
|
||||
* finish our close
|
||||
*/
|
||||
lwsl_parser("seen server's close ack\n");
|
||||
return -1;
|
||||
}
|
||||
lwsl_parser("client sees server close len = %d\n",
|
||||
wsi->u.ws.rx_user_buffer_head);
|
||||
/*
|
||||
* parrot the close packet payload back
|
||||
* we do not care about how it went, we are closing
|
||||
* immediately afterwards
|
||||
*/
|
||||
libwebsocket_write(wsi, (unsigned char *)
|
||||
&wsi->u.ws.rx_user_buffer[
|
||||
LWS_SEND_BUFFER_PRE_PADDING],
|
||||
wsi->u.ws.rx_user_buffer_head, LWS_WRITE_CLOSE);
|
||||
wsi->state = WSI_STATE_RETURNED_CLOSE_ALREADY;
|
||||
/* close the connection */
|
||||
return -1;
|
||||
|
||||
case LWS_WS_OPCODE_07__PING:
|
||||
lwsl_info("client received ping, doing pong\n");
|
||||
/*
|
||||
* parrot the ping packet payload back as a pong
|
||||
* !!! this may block or have partial write or fail
|
||||
* !!! very unlikely if the ping size is small
|
||||
*/
|
||||
libwebsocket_write(wsi, (unsigned char *)
|
||||
&wsi->u.ws.rx_user_buffer[
|
||||
LWS_SEND_BUFFER_PRE_PADDING],
|
||||
wsi->u.ws.rx_user_buffer_head,
|
||||
LWS_WRITE_PONG);
|
||||
handled = 1;
|
||||
break;
|
||||
|
||||
case LWS_WS_OPCODE_07__PONG:
|
||||
lwsl_info("client receied pong\n");
|
||||
lwsl_hexdump(&wsi->u.ws.rx_user_buffer[
|
||||
LWS_SEND_BUFFER_PRE_PADDING],
|
||||
wsi->u.ws.rx_user_buffer_head);
|
||||
|
||||
/* issue it */
|
||||
callback_action = LWS_CALLBACK_CLIENT_RECEIVE_PONG;
|
||||
break;
|
||||
|
||||
case LWS_WS_OPCODE_07__CONTINUATION:
|
||||
case LWS_WS_OPCODE_07__TEXT_FRAME:
|
||||
case LWS_WS_OPCODE_07__BINARY_FRAME:
|
||||
break;
|
||||
|
||||
default:
|
||||
|
||||
lwsl_parser("Reserved opc 0x%2X\n", wsi->u.ws.opcode);
|
||||
|
||||
/*
|
||||
* It's something special we can't understand here.
|
||||
* Pass the payload up to the extension's parsing
|
||||
* state machine.
|
||||
*/
|
||||
|
||||
eff_buf.token = &wsi->u.ws.rx_user_buffer[
|
||||
LWS_SEND_BUFFER_PRE_PADDING];
|
||||
eff_buf.token_len = wsi->u.ws.rx_user_buffer_head;
|
||||
|
||||
if (lws_ext_callback_for_each_active(wsi,
|
||||
LWS_EXT_CALLBACK_EXTENDED_PAYLOAD_RX,
|
||||
&eff_buf, 0) <= 0) { /* not handle or fail */
|
||||
|
||||
lwsl_ext("Unhandled ext opc 0x%x\n",
|
||||
wsi->u.ws.opcode);
|
||||
wsi->u.ws.rx_user_buffer_head = 0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
handled = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
* No it's real payload, pass it up to the user callback.
|
||||
* It's nicely buffered with the pre-padding taken care of
|
||||
* so it can be sent straight out again using libwebsocket_write
|
||||
*/
|
||||
if (handled)
|
||||
goto already_done;
|
||||
|
||||
eff_buf.token = &wsi->u.ws.rx_user_buffer[
|
||||
LWS_SEND_BUFFER_PRE_PADDING];
|
||||
eff_buf.token_len = wsi->u.ws.rx_user_buffer_head;
|
||||
|
||||
if (lws_ext_callback_for_each_active(wsi,
|
||||
LWS_EXT_CALLBACK_PAYLOAD_RX,
|
||||
&eff_buf, 0) < 0) /* fail */
|
||||
return -1;
|
||||
|
||||
if (eff_buf.token_len <= 0 &&
|
||||
callback_action != LWS_CALLBACK_CLIENT_RECEIVE_PONG)
|
||||
goto already_done;
|
||||
|
||||
eff_buf.token[eff_buf.token_len] = '\0';
|
||||
|
||||
if (!wsi->protocol->callback)
|
||||
goto already_done;
|
||||
|
||||
if (callback_action == LWS_CALLBACK_CLIENT_RECEIVE_PONG)
|
||||
lwsl_info("Client doing pong callback\n");
|
||||
|
||||
m = wsi->protocol->callback(
|
||||
wsi->protocol->owning_server,
|
||||
wsi,
|
||||
(enum libwebsocket_callback_reasons)callback_action,
|
||||
wsi->user_space,
|
||||
eff_buf.token,
|
||||
eff_buf.token_len);
|
||||
|
||||
/* if user code wants to close, let caller know */
|
||||
if (m)
|
||||
return 1;
|
||||
|
||||
already_done:
|
||||
wsi->u.ws.rx_user_buffer_head = 0;
|
||||
break;
|
||||
default:
|
||||
lwsl_err("client rx illegal state\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
illegal_ctl_length:
|
||||
|
||||
lwsl_warn("Control frame asking for extended length is illegal\n");
|
||||
/* kill the connection */
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,954 @@
|
||||
/*
|
||||
* libwebsockets - small server side websockets and web server implementation
|
||||
*
|
||||
* Copyright (C) 2010-2014 Andy Green <[email protected]>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation:
|
||||
* version 2.1 of the License.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
||||
* MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#include "private-libwebsockets.h"
|
||||
|
||||
int lws_handshake_client(struct libwebsocket *wsi, unsigned char **buf, size_t len)
|
||||
{
|
||||
int n;
|
||||
|
||||
switch (wsi->mode) {
|
||||
case LWS_CONNMODE_WS_CLIENT_WAITING_PROXY_REPLY:
|
||||
case LWS_CONNMODE_WS_CLIENT_ISSUE_HANDSHAKE:
|
||||
case LWS_CONNMODE_WS_CLIENT_WAITING_SERVER_REPLY:
|
||||
case LWS_CONNMODE_WS_CLIENT_WAITING_EXTENSION_CONNECT:
|
||||
case LWS_CONNMODE_WS_CLIENT:
|
||||
for (n = 0; n < len; n++)
|
||||
if (libwebsocket_client_rx_sm(wsi, *(*buf)++)) {
|
||||
lwsl_debug("client_rx_sm failed\n");
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int lws_client_socket_service(struct libwebsocket_context *context,
|
||||
struct libwebsocket *wsi, struct libwebsocket_pollfd *pollfd)
|
||||
{
|
||||
int n;
|
||||
char *p = (char *)&context->service_buffer[0];
|
||||
int len;
|
||||
unsigned char c;
|
||||
|
||||
switch (wsi->mode) {
|
||||
|
||||
case LWS_CONNMODE_WS_CLIENT_WAITING_CONNECT:
|
||||
|
||||
/*
|
||||
* we are under PENDING_TIMEOUT_SENT_CLIENT_HANDSHAKE
|
||||
* timeout protection set in client-handshake.c
|
||||
*/
|
||||
|
||||
if (libwebsocket_client_connect_2(context, wsi) == NULL) {
|
||||
/* closed */
|
||||
lwsl_client("closed\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* either still pending connection, or changed mode */
|
||||
return 0;
|
||||
|
||||
case LWS_CONNMODE_WS_CLIENT_WAITING_PROXY_REPLY:
|
||||
|
||||
/* handle proxy hung up on us */
|
||||
|
||||
if (pollfd->revents & LWS_POLLHUP) {
|
||||
|
||||
lwsl_warn("Proxy connection %p (fd=%d) dead\n",
|
||||
(void *)wsi, pollfd->fd);
|
||||
|
||||
libwebsocket_close_and_free_session(context, wsi,
|
||||
LWS_CLOSE_STATUS_NOSTATUS);
|
||||
return 0;
|
||||
}
|
||||
|
||||
n = recv(wsi->sock, context->service_buffer,
|
||||
sizeof(context->service_buffer), 0);
|
||||
if (n < 0) {
|
||||
|
||||
if (LWS_ERRNO == LWS_EAGAIN) {
|
||||
lwsl_debug(
|
||||
"Proxy read returned EAGAIN... retrying\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
libwebsocket_close_and_free_session(context, wsi,
|
||||
LWS_CLOSE_STATUS_NOSTATUS);
|
||||
lwsl_err("ERROR reading from proxy socket\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
context->service_buffer[13] = '\0';
|
||||
if (strcmp((char *)context->service_buffer, "HTTP/1.0 200 ")) {
|
||||
libwebsocket_close_and_free_session(context, wsi,
|
||||
LWS_CLOSE_STATUS_NOSTATUS);
|
||||
lwsl_err("ERROR proxy: %s\n", context->service_buffer);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* clear his proxy connection timeout */
|
||||
|
||||
libwebsocket_set_timeout(wsi, NO_PENDING_TIMEOUT, 0);
|
||||
|
||||
/* fallthru */
|
||||
|
||||
case LWS_CONNMODE_WS_CLIENT_ISSUE_HANDSHAKE:
|
||||
|
||||
/*
|
||||
* we are under PENDING_TIMEOUT_SENT_CLIENT_HANDSHAKE
|
||||
* timeout protection set in client-handshake.c
|
||||
*/
|
||||
|
||||
/*
|
||||
* take care of our libwebsocket_callback_on_writable
|
||||
* happening at a time when there's no real connection yet
|
||||
*/
|
||||
if (lws_change_pollfd(wsi, LWS_POLLOUT, 0))
|
||||
return -1;
|
||||
|
||||
#ifdef LWS_OPENSSL_SUPPORT
|
||||
/* we can retry this... just cook the SSL BIO the first time */
|
||||
|
||||
if (wsi->use_ssl && !wsi->ssl) {
|
||||
const char *hostname = lws_hdr_simple_ptr(wsi,
|
||||
_WSI_TOKEN_CLIENT_PEER_ADDRESS);
|
||||
|
||||
wsi->ssl = SSL_new(context->ssl_client_ctx);
|
||||
#ifndef USE_CYASSL
|
||||
SSL_set_mode(wsi->ssl,
|
||||
SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER);
|
||||
#endif
|
||||
/*
|
||||
* use server name indication (SNI), if supported,
|
||||
* when establishing connection
|
||||
*/
|
||||
#ifdef USE_CYASSL
|
||||
#ifdef CYASSL_SNI_HOST_NAME
|
||||
CyaSSL_UseSNI(wsi->ssl, CYASSL_SNI_HOST_NAME,
|
||||
hostname, strlen(hostname));
|
||||
#endif
|
||||
#else
|
||||
SSL_set_tlsext_host_name(wsi->ssl, hostname);
|
||||
#endif
|
||||
|
||||
#ifdef USE_CYASSL
|
||||
/*
|
||||
* CyaSSL does certificate verification differently
|
||||
* from OpenSSL.
|
||||
* If we should ignore the certificate, we need to set
|
||||
* this before SSL_new and SSL_connect is called.
|
||||
* Otherwise the connect will simply fail with error
|
||||
* code -155
|
||||
*/
|
||||
if (wsi->use_ssl == 2)
|
||||
CyaSSL_set_verify(wsi->ssl,
|
||||
SSL_VERIFY_NONE, NULL);
|
||||
#endif /* USE_CYASSL */
|
||||
|
||||
wsi->client_bio =
|
||||
BIO_new_socket(wsi->sock, BIO_NOCLOSE);
|
||||
SSL_set_bio(wsi->ssl, wsi->client_bio, wsi->client_bio);
|
||||
|
||||
#ifdef USE_CYASSL
|
||||
CyaSSL_set_using_nonblock(wsi->ssl, 1);
|
||||
#else
|
||||
BIO_set_nbio(wsi->client_bio, 1); /* nonblocking */
|
||||
#endif
|
||||
|
||||
SSL_set_ex_data(wsi->ssl,
|
||||
openssl_websocket_private_data_index,
|
||||
context);
|
||||
}
|
||||
|
||||
if (wsi->use_ssl) {
|
||||
lws_latency_pre(context, wsi);
|
||||
n = SSL_connect(wsi->ssl);
|
||||
lws_latency(context, wsi,
|
||||
"SSL_connect LWS_CONNMODE_WS_CLIENT_ISSUE_HANDSHAKE",
|
||||
n, n > 0);
|
||||
|
||||
if (n < 0) {
|
||||
n = SSL_get_error(wsi->ssl, n);
|
||||
|
||||
if (n == SSL_ERROR_WANT_READ ||
|
||||
n == SSL_ERROR_WANT_WRITE) {
|
||||
/*
|
||||
* wants us to retry connect due to
|
||||
* state of the underlying ssl layer...
|
||||
* but since it may be stalled on
|
||||
* blocked write, no incoming data may
|
||||
* arrive to trigger the retry.
|
||||
* Force (possibly many times if the SSL
|
||||
* state persists in returning the
|
||||
* condition code, but other sockets
|
||||
* are getting serviced inbetweentimes)
|
||||
* us to get called back when writable.
|
||||
*/
|
||||
|
||||
lwsl_info(
|
||||
"SSL_connect WANT_... retrying\n");
|
||||
libwebsocket_callback_on_writable(
|
||||
context, wsi);
|
||||
|
||||
wsi->mode = LWS_CONNMODE_WS_CLIENT_WAITING_SSL;
|
||||
|
||||
return 0; /* no error */
|
||||
}
|
||||
n = -1;
|
||||
}
|
||||
|
||||
if (n <= 0) {
|
||||
/*
|
||||
* retry if new data comes until we
|
||||
* run into the connection timeout or win
|
||||
*/
|
||||
|
||||
n = ERR_get_error();
|
||||
if (n != SSL_ERROR_NONE) {
|
||||
lwsl_err("SSL connect error %lu: %s\n",
|
||||
n,
|
||||
ERR_error_string(n,
|
||||
(char *)context->service_buffer));
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
} else
|
||||
wsi->ssl = NULL;
|
||||
|
||||
/* fallthru */
|
||||
|
||||
case LWS_CONNMODE_WS_CLIENT_WAITING_SSL:
|
||||
|
||||
if (wsi->use_ssl) {
|
||||
|
||||
if (wsi->mode == LWS_CONNMODE_WS_CLIENT_WAITING_SSL) {
|
||||
lws_latency_pre(context, wsi);
|
||||
n = SSL_connect(wsi->ssl);
|
||||
lws_latency(context, wsi,
|
||||
"SSL_connect LWS_CONNMODE_WS_CLIENT_WAITING_SSL",
|
||||
n, n > 0);
|
||||
|
||||
if (n < 0) {
|
||||
n = SSL_get_error(wsi->ssl, n);
|
||||
|
||||
if (n == SSL_ERROR_WANT_READ ||
|
||||
n == SSL_ERROR_WANT_WRITE) {
|
||||
/*
|
||||
* wants us to retry connect due to
|
||||
* state of the underlying ssl layer...
|
||||
* but since it may be stalled on
|
||||
* blocked write, no incoming data may
|
||||
* arrive to trigger the retry.
|
||||
* Force (possibly many times if the SSL
|
||||
* state persists in returning the
|
||||
* condition code, but other sockets
|
||||
* are getting serviced inbetweentimes)
|
||||
* us to get called back when writable.
|
||||
*/
|
||||
|
||||
lwsl_info(
|
||||
"SSL_connect WANT_... retrying\n");
|
||||
libwebsocket_callback_on_writable(
|
||||
context, wsi);
|
||||
|
||||
wsi->mode = LWS_CONNMODE_WS_CLIENT_WAITING_SSL;
|
||||
|
||||
return 0; /* no error */
|
||||
}
|
||||
n = -1;
|
||||
}
|
||||
|
||||
if (n <= 0) {
|
||||
/*
|
||||
* retry if new data comes until we
|
||||
* run into the connection timeout or win
|
||||
*/
|
||||
n = ERR_get_error();
|
||||
if (n != SSL_ERROR_NONE) {
|
||||
lwsl_err("SSL connect error %lu: %s\n",
|
||||
n,
|
||||
ERR_error_string(n,
|
||||
(char *)context->service_buffer));
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#ifndef USE_CYASSL
|
||||
/*
|
||||
* See comment above about CyaSSL certificate
|
||||
* verification
|
||||
*/
|
||||
lws_latency_pre(context, wsi);
|
||||
n = SSL_get_verify_result(wsi->ssl);
|
||||
lws_latency(context, wsi,
|
||||
"SSL_get_verify_result LWS_CONNMODE..HANDSHAKE",
|
||||
n, n > 0);
|
||||
if ((n != X509_V_OK) && (
|
||||
n != X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT ||
|
||||
wsi->use_ssl != 2)) {
|
||||
|
||||
lwsl_err(
|
||||
"server's cert didn't look good %d\n", n);
|
||||
libwebsocket_close_and_free_session(context,
|
||||
wsi, LWS_CLOSE_STATUS_NOSTATUS);
|
||||
return 0;
|
||||
}
|
||||
#endif /* USE_CYASSL */
|
||||
} else
|
||||
wsi->ssl = NULL;
|
||||
#endif
|
||||
|
||||
wsi->mode = LWS_CONNMODE_WS_CLIENT_ISSUE_HANDSHAKE2;
|
||||
libwebsocket_set_timeout(wsi,
|
||||
PENDING_TIMEOUT_AWAITING_CLIENT_HS_SEND,
|
||||
AWAITING_TIMEOUT);
|
||||
|
||||
/* fallthru */
|
||||
|
||||
case LWS_CONNMODE_WS_CLIENT_ISSUE_HANDSHAKE2:
|
||||
p = libwebsockets_generate_client_handshake(context, wsi, p);
|
||||
if (p == NULL) {
|
||||
lwsl_err("Failed to generate handshake for client\n");
|
||||
libwebsocket_close_and_free_session(context, wsi,
|
||||
LWS_CLOSE_STATUS_NOSTATUS);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* send our request to the server */
|
||||
|
||||
lws_latency_pre(context, wsi);
|
||||
|
||||
n = lws_ssl_capable_write(wsi, context->service_buffer, p - (char *)context->service_buffer);
|
||||
lws_latency(context, wsi, "send lws_issue_raw", n, n == p - (char *)context->service_buffer);
|
||||
switch (n) {
|
||||
case LWS_SSL_CAPABLE_ERROR:
|
||||
lwsl_debug("ERROR writing to client socket\n");
|
||||
libwebsocket_close_and_free_session(context, wsi,
|
||||
LWS_CLOSE_STATUS_NOSTATUS);
|
||||
return 0;
|
||||
case LWS_SSL_CAPABLE_MORE_SERVICE:
|
||||
libwebsocket_callback_on_writable(context, wsi);
|
||||
break;
|
||||
}
|
||||
|
||||
wsi->u.hdr.parser_state = WSI_TOKEN_NAME_PART;
|
||||
wsi->u.hdr.lextable_pos = 0;
|
||||
wsi->mode = LWS_CONNMODE_WS_CLIENT_WAITING_SERVER_REPLY;
|
||||
libwebsocket_set_timeout(wsi,
|
||||
PENDING_TIMEOUT_AWAITING_SERVER_RESPONSE,
|
||||
AWAITING_TIMEOUT);
|
||||
break;
|
||||
|
||||
case LWS_CONNMODE_WS_CLIENT_WAITING_SERVER_REPLY:
|
||||
|
||||
/* handle server hung up on us */
|
||||
|
||||
if (pollfd->revents & LWS_POLLHUP) {
|
||||
|
||||
lwsl_debug("Server connection %p (fd=%d) dead\n",
|
||||
(void *)wsi, pollfd->fd);
|
||||
|
||||
goto bail3;
|
||||
}
|
||||
|
||||
if (!(pollfd->revents & LWS_POLLIN))
|
||||
break;
|
||||
|
||||
/* interpret the server response */
|
||||
|
||||
/*
|
||||
* HTTP/1.1 101 Switching Protocols
|
||||
* Upgrade: websocket
|
||||
* Connection: Upgrade
|
||||
* Sec-WebSocket-Accept: me89jWimTRKTWwrS3aRrL53YZSo=
|
||||
* Sec-WebSocket-Nonce: AQIDBAUGBwgJCgsMDQ4PEC==
|
||||
* Sec-WebSocket-Protocol: chat
|
||||
*/
|
||||
|
||||
/*
|
||||
* we have to take some care here to only take from the
|
||||
* socket bytewise. The browser may (and has been seen to
|
||||
* in the case that onopen() performs websocket traffic)
|
||||
* coalesce both handshake response and websocket traffic
|
||||
* in one packet, since at that point the connection is
|
||||
* definitively ready from browser pov.
|
||||
*/
|
||||
len = 1;
|
||||
while (wsi->u.hdr.parser_state != WSI_PARSING_COMPLETE &&
|
||||
len > 0) {
|
||||
n = lws_ssl_capable_read(wsi, &c, 1);
|
||||
lws_latency(context, wsi, "send lws_issue_raw", n, n == 1);
|
||||
switch (n) {
|
||||
case LWS_SSL_CAPABLE_ERROR:
|
||||
goto bail3;
|
||||
case LWS_SSL_CAPABLE_MORE_SERVICE:
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (libwebsocket_parse(wsi, c)) {
|
||||
lwsl_warn("problems parsing header\n");
|
||||
goto bail3;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* hs may also be coming in multiple packets, there is a 5-sec
|
||||
* libwebsocket timeout still active here too, so if parsing did
|
||||
* not complete just wait for next packet coming in this state
|
||||
*/
|
||||
|
||||
if (wsi->u.hdr.parser_state != WSI_PARSING_COMPLETE)
|
||||
break;
|
||||
|
||||
/*
|
||||
* otherwise deal with the handshake. If there's any
|
||||
* packet traffic already arrived we'll trigger poll() again
|
||||
* right away and deal with it that way
|
||||
*/
|
||||
|
||||
return lws_client_interpret_server_handshake(context, wsi);
|
||||
|
||||
bail3:
|
||||
lwsl_info(
|
||||
"closing connection at LWS_CONNMODE...SERVER_REPLY\n");
|
||||
libwebsocket_close_and_free_session(context, wsi,
|
||||
LWS_CLOSE_STATUS_NOSTATUS);
|
||||
return -1;
|
||||
|
||||
case LWS_CONNMODE_WS_CLIENT_WAITING_EXTENSION_CONNECT:
|
||||
lwsl_ext("LWS_CONNMODE_WS_CLIENT_WAITING_EXTENSION_CONNECT\n");
|
||||
break;
|
||||
|
||||
case LWS_CONNMODE_WS_CLIENT_PENDING_CANDIDATE_CHILD:
|
||||
lwsl_ext("LWS_CONNMODE_WS_CLIENT_PENDING_CANDIDATE_CHILD\n");
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* In-place str to lower case
|
||||
*/
|
||||
|
||||
static void
|
||||
strtolower(char *s)
|
||||
{
|
||||
while (*s) {
|
||||
*s = tolower((int)*s);
|
||||
s++;
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
lws_client_interpret_server_handshake(struct libwebsocket_context *context,
|
||||
struct libwebsocket *wsi)
|
||||
{
|
||||
const char *pc;
|
||||
int okay = 0;
|
||||
char *p;
|
||||
int len;
|
||||
#ifndef LWS_NO_EXTENSIONS
|
||||
char ext_name[128];
|
||||
struct libwebsocket_extension *ext;
|
||||
void *v;
|
||||
int more = 1;
|
||||
const char *c;
|
||||
#endif
|
||||
int n;
|
||||
int close_reason = LWS_CLOSE_STATUS_PROTOCOL_ERR;
|
||||
|
||||
/*
|
||||
* well, what the server sent looked reasonable for syntax.
|
||||
* Now let's confirm it sent all the necessary headers
|
||||
*/
|
||||
|
||||
if (lws_hdr_total_length(wsi, WSI_TOKEN_ACCEPT) == 0) {
|
||||
lwsl_info("no ACCEPT\n");
|
||||
goto bail3;
|
||||
}
|
||||
|
||||
p = lws_hdr_simple_ptr(wsi, WSI_TOKEN_HTTP);
|
||||
if (!p) {
|
||||
lwsl_info("no URI\n");
|
||||
goto bail3;
|
||||
}
|
||||
if (p && strncmp(p, "101", 3)) {
|
||||
lwsl_warn(
|
||||
"lws_client_handshake: got bad HTTP response '%s'\n", p);
|
||||
goto bail3;
|
||||
}
|
||||
|
||||
p = lws_hdr_simple_ptr(wsi, WSI_TOKEN_UPGRADE);
|
||||
if (!p) {
|
||||
lwsl_info("no UPGRADE\n");
|
||||
goto bail3;
|
||||
}
|
||||
strtolower(p);
|
||||
if (strcmp(p, "websocket")) {
|
||||
lwsl_warn(
|
||||
"lws_client_handshake: got bad Upgrade header '%s'\n", p);
|
||||
goto bail3;
|
||||
}
|
||||
|
||||
p = lws_hdr_simple_ptr(wsi, WSI_TOKEN_CONNECTION);
|
||||
if (!p) {
|
||||
lwsl_info("no Connection hdr\n");
|
||||
goto bail3;
|
||||
}
|
||||
strtolower(p);
|
||||
if (strcmp(p, "upgrade")) {
|
||||
lwsl_warn("lws_client_int_s_hs: bad header %s\n", p);
|
||||
goto bail3;
|
||||
}
|
||||
|
||||
pc = lws_hdr_simple_ptr(wsi, _WSI_TOKEN_CLIENT_SENT_PROTOCOLS);
|
||||
if (pc == NULL)
|
||||
lwsl_parser("lws_client_int_s_hs: no protocol list\n");
|
||||
else
|
||||
lwsl_parser("lws_client_int_s_hs: protocol list '%s'\n", pc);
|
||||
|
||||
/*
|
||||
* confirm the protocol the server wants to talk was in the list
|
||||
* of protocols we offered
|
||||
*/
|
||||
|
||||
len = lws_hdr_total_length(wsi, WSI_TOKEN_PROTOCOL);
|
||||
if (!len) {
|
||||
|
||||
lwsl_info("lws_client_int_s_hs: WSI_TOKEN_PROTOCOL is null\n");
|
||||
/*
|
||||
* no protocol name to work from,
|
||||
* default to first protocol
|
||||
*/
|
||||
wsi->protocol = &context->protocols[0];
|
||||
goto check_extensions;
|
||||
}
|
||||
|
||||
p = lws_hdr_simple_ptr(wsi, WSI_TOKEN_PROTOCOL);
|
||||
len = strlen(p);
|
||||
|
||||
while (*pc && !okay) {
|
||||
if (!strncmp(pc, p, len) &&
|
||||
(pc[len] == ',' || pc[len] == '\0')) {
|
||||
okay = 1;
|
||||
continue;
|
||||
}
|
||||
while (*pc && *pc != ',')
|
||||
pc++;
|
||||
while (*pc && *pc != ' ')
|
||||
pc++;
|
||||
}
|
||||
|
||||
if (!okay) {
|
||||
lwsl_err("lws_client_int_s_hs: got bad protocol %s\n", p);
|
||||
goto bail2;
|
||||
}
|
||||
|
||||
/*
|
||||
* identify the selected protocol struct and set it
|
||||
*/
|
||||
n = 0;
|
||||
wsi->protocol = NULL;
|
||||
while (context->protocols[n].callback && !wsi->protocol) {
|
||||
if (strcmp(p, context->protocols[n].name) == 0) {
|
||||
wsi->protocol = &context->protocols[n];
|
||||
break;
|
||||
}
|
||||
n++;
|
||||
}
|
||||
|
||||
if (wsi->protocol == NULL) {
|
||||
lwsl_err("lws_client_int_s_hs: fail protocol %s\n", p);
|
||||
goto bail2;
|
||||
}
|
||||
|
||||
|
||||
check_extensions:
|
||||
#ifndef LWS_NO_EXTENSIONS
|
||||
/* instantiate the accepted extensions */
|
||||
|
||||
if (!lws_hdr_total_length(wsi, WSI_TOKEN_EXTENSIONS)) {
|
||||
lwsl_ext("no client extenstions allowed by server\n");
|
||||
goto check_accept;
|
||||
}
|
||||
|
||||
/*
|
||||
* break down the list of server accepted extensions
|
||||
* and go through matching them or identifying bogons
|
||||
*/
|
||||
|
||||
if (lws_hdr_copy(wsi, (char *)context->service_buffer,
|
||||
sizeof(context->service_buffer), WSI_TOKEN_EXTENSIONS) < 0) {
|
||||
lwsl_warn("ext list from server failed to copy\n");
|
||||
goto bail2;
|
||||
}
|
||||
|
||||
c = (char *)context->service_buffer;
|
||||
n = 0;
|
||||
while (more) {
|
||||
|
||||
if (*c && (*c != ',' && *c != ' ' && *c != '\t')) {
|
||||
ext_name[n] = *c++;
|
||||
if (n < sizeof(ext_name) - 1)
|
||||
n++;
|
||||
continue;
|
||||
}
|
||||
ext_name[n] = '\0';
|
||||
if (!*c)
|
||||
more = 0;
|
||||
else {
|
||||
c++;
|
||||
if (!n)
|
||||
continue;
|
||||
}
|
||||
|
||||
/* check we actually support it */
|
||||
|
||||
lwsl_ext("checking client ext %s\n", ext_name);
|
||||
|
||||
n = 0;
|
||||
ext = wsi->protocol->owning_server->extensions;
|
||||
while (ext && ext->callback) {
|
||||
|
||||
if (strcmp(ext_name, ext->name)) {
|
||||
ext++;
|
||||
continue;
|
||||
}
|
||||
|
||||
n = 1;
|
||||
|
||||
lwsl_ext("instantiating client ext %s\n", ext_name);
|
||||
|
||||
/* instantiate the extension on this conn */
|
||||
|
||||
wsi->active_extensions_user[
|
||||
wsi->count_active_extensions] =
|
||||
malloc(ext->per_session_data_size);
|
||||
if (wsi->active_extensions_user[
|
||||
wsi->count_active_extensions] == NULL) {
|
||||
lwsl_err("Out of mem\n");
|
||||
goto bail2;
|
||||
}
|
||||
memset(wsi->active_extensions_user[
|
||||
wsi->count_active_extensions], 0,
|
||||
ext->per_session_data_size);
|
||||
wsi->active_extensions[
|
||||
wsi->count_active_extensions] = ext;
|
||||
|
||||
/* allow him to construct his context */
|
||||
|
||||
ext->callback(wsi->protocol->owning_server,
|
||||
ext, wsi,
|
||||
LWS_EXT_CALLBACK_CLIENT_CONSTRUCT,
|
||||
wsi->active_extensions_user[
|
||||
wsi->count_active_extensions],
|
||||
NULL, 0);
|
||||
|
||||
wsi->count_active_extensions++;
|
||||
|
||||
ext++;
|
||||
}
|
||||
|
||||
if (n == 0) {
|
||||
lwsl_warn("Unknown ext '%s'!\n", ext_name);
|
||||
goto bail2;
|
||||
}
|
||||
|
||||
n = 0;
|
||||
}
|
||||
|
||||
check_accept:
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Confirm his accept token is the one we precomputed
|
||||
*/
|
||||
|
||||
p = lws_hdr_simple_ptr(wsi, WSI_TOKEN_ACCEPT);
|
||||
if (strcmp(p, wsi->u.hdr.ah->initial_handshake_hash_base64)) {
|
||||
lwsl_warn("lws_client_int_s_hs: accept %s wrong vs %s\n", p,
|
||||
wsi->u.hdr.ah->initial_handshake_hash_base64);
|
||||
goto bail2;
|
||||
}
|
||||
|
||||
/* allocate the per-connection user memory (if any) */
|
||||
if (libwebsocket_ensure_user_space(wsi)) {
|
||||
lwsl_err("Problem allocating wsi user mem\n");
|
||||
goto bail2;
|
||||
}
|
||||
|
||||
/*
|
||||
* we seem to be good to go, give client last chance to check
|
||||
* headers and OK it
|
||||
*/
|
||||
|
||||
wsi->protocol->callback(context, wsi,
|
||||
LWS_CALLBACK_CLIENT_FILTER_PRE_ESTABLISH,
|
||||
wsi->user_space, NULL, 0);
|
||||
|
||||
/* clear his proxy connection timeout */
|
||||
|
||||
libwebsocket_set_timeout(wsi, NO_PENDING_TIMEOUT, 0);
|
||||
|
||||
/* free up his parsing allocations */
|
||||
if (wsi->u.hdr.ah)
|
||||
free(wsi->u.hdr.ah);
|
||||
|
||||
/* mark him as being alive */
|
||||
|
||||
wsi->state = WSI_STATE_ESTABLISHED;
|
||||
wsi->mode = LWS_CONNMODE_WS_CLIENT;
|
||||
|
||||
/* union transition */
|
||||
|
||||
memset(&wsi->u, 0, sizeof(wsi->u));
|
||||
|
||||
wsi->u.ws.rxflow_change_to = LWS_RXFLOW_ALLOW;
|
||||
|
||||
/*
|
||||
* create the frame buffer for this connection according to the
|
||||
* size mentioned in the protocol definition. If 0 there, then
|
||||
* use a big default for compatibility
|
||||
*/
|
||||
|
||||
n = wsi->protocol->rx_buffer_size;
|
||||
if (!n)
|
||||
n = LWS_MAX_SOCKET_IO_BUF;
|
||||
n += LWS_SEND_BUFFER_PRE_PADDING + LWS_SEND_BUFFER_POST_PADDING;
|
||||
wsi->u.ws.rx_user_buffer = malloc(n);
|
||||
if (!wsi->u.ws.rx_user_buffer) {
|
||||
lwsl_err("Out of Mem allocating rx buffer %d\n", n);
|
||||
goto bail2;
|
||||
}
|
||||
lwsl_info("Allocating client RX buffer %d\n", n);
|
||||
|
||||
if (setsockopt(wsi->sock, SOL_SOCKET, SO_SNDBUF, (const char *)&n, sizeof n)) {
|
||||
lwsl_warn("Failed to set SNDBUF to %d", n);
|
||||
goto bail3;
|
||||
}
|
||||
|
||||
lwsl_debug("handshake OK for protocol %s\n", wsi->protocol->name);
|
||||
|
||||
/* call him back to inform him he is up */
|
||||
|
||||
wsi->protocol->callback(context, wsi,
|
||||
LWS_CALLBACK_CLIENT_ESTABLISHED,
|
||||
wsi->user_space, NULL, 0);
|
||||
#ifndef LWS_NO_EXTENSIONS
|
||||
/*
|
||||
* inform all extensions, not just active ones since they
|
||||
* already know
|
||||
*/
|
||||
|
||||
ext = context->extensions;
|
||||
|
||||
while (ext && ext->callback) {
|
||||
v = NULL;
|
||||
for (n = 0; n < wsi->count_active_extensions; n++)
|
||||
if (wsi->active_extensions[n] == ext)
|
||||
v = wsi->active_extensions_user[n];
|
||||
|
||||
ext->callback(context, ext, wsi,
|
||||
LWS_EXT_CALLBACK_ANY_WSI_ESTABLISHED, v, NULL, 0);
|
||||
ext++;
|
||||
}
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
|
||||
bail3:
|
||||
free(wsi->u.ws.rx_user_buffer);
|
||||
wsi->u.ws.rx_user_buffer = NULL;
|
||||
close_reason = LWS_CLOSE_STATUS_NOSTATUS;
|
||||
|
||||
bail2:
|
||||
if (wsi->protocol)
|
||||
wsi->protocol->callback(context, wsi,
|
||||
LWS_CALLBACK_CLIENT_CONNECTION_ERROR,
|
||||
wsi->user_space, NULL, 0);
|
||||
|
||||
lwsl_info("closing connection due to bail2 connection error\n");
|
||||
|
||||
/* free up his parsing allocations */
|
||||
|
||||
if (wsi->u.hdr.ah)
|
||||
free(wsi->u.hdr.ah);
|
||||
|
||||
libwebsocket_close_and_free_session(context, wsi, close_reason);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
char *
|
||||
libwebsockets_generate_client_handshake(struct libwebsocket_context *context,
|
||||
struct libwebsocket *wsi, char *pkt)
|
||||
{
|
||||
char buf[128];
|
||||
char hash[20];
|
||||
char key_b64[40];
|
||||
char *p = pkt;
|
||||
int n;
|
||||
#ifndef LWS_NO_EXTENSIONS
|
||||
struct libwebsocket_extension *ext;
|
||||
int ext_count = 0;
|
||||
#endif
|
||||
|
||||
/*
|
||||
* create the random key
|
||||
*/
|
||||
|
||||
n = libwebsockets_get_random(context, hash, 16);
|
||||
if (n != 16) {
|
||||
lwsl_err("Unable to read from random dev %s\n",
|
||||
SYSTEM_RANDOM_FILEPATH);
|
||||
libwebsocket_close_and_free_session(context, wsi,
|
||||
LWS_CLOSE_STATUS_NOSTATUS);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
lws_b64_encode_string(hash, 16, key_b64, sizeof(key_b64));
|
||||
|
||||
/*
|
||||
* 00 example client handshake
|
||||
*
|
||||
* GET /socket.io/websocket HTTP/1.1
|
||||
* Upgrade: WebSocket
|
||||
* Connection: Upgrade
|
||||
* Host: 127.0.0.1:9999
|
||||
* Origin: http://127.0.0.1
|
||||
* Sec-WebSocket-Key1: 1 0 2#0W 9 89 7 92 ^
|
||||
* Sec-WebSocket-Key2: 7 7Y 4328 B2v[8(z1
|
||||
* Cookie: socketio=websocket
|
||||
*
|
||||
* (Á®Ä0¶†≥
|
||||
*
|
||||
* 04 example client handshake
|
||||
*
|
||||
* GET /chat HTTP/1.1
|
||||
* Host: server.example.com
|
||||
* Upgrade: websocket
|
||||
* Connection: Upgrade
|
||||
* Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==
|
||||
* Sec-WebSocket-Origin: http://example.com
|
||||
* Sec-WebSocket-Protocol: chat, superchat
|
||||
* Sec-WebSocket-Version: 4
|
||||
*/
|
||||
|
||||
p += sprintf(p, "GET %s HTTP/1.1\x0d\x0a",
|
||||
lws_hdr_simple_ptr(wsi, _WSI_TOKEN_CLIENT_URI));
|
||||
|
||||
p += sprintf(p,
|
||||
"Pragma: no-cache\x0d\x0a""Cache-Control: no-cache\x0d\x0a");
|
||||
|
||||
p += sprintf(p, "Host: %s\x0d\x0a",
|
||||
lws_hdr_simple_ptr(wsi, _WSI_TOKEN_CLIENT_HOST));
|
||||
p += sprintf(p,
|
||||
"Upgrade: websocket\x0d\x0a""Connection: Upgrade\x0d\x0a""Sec-WebSocket-Key: ");
|
||||
strcpy(p, key_b64);
|
||||
p += strlen(key_b64);
|
||||
p += sprintf(p, "\x0d\x0a");
|
||||
if (lws_hdr_simple_ptr(wsi, _WSI_TOKEN_CLIENT_ORIGIN))
|
||||
p += sprintf(p, "Origin: http://%s\x0d\x0a",
|
||||
lws_hdr_simple_ptr(wsi, _WSI_TOKEN_CLIENT_ORIGIN));
|
||||
|
||||
if (lws_hdr_simple_ptr(wsi, _WSI_TOKEN_CLIENT_SENT_PROTOCOLS))
|
||||
p += sprintf(p, "Sec-WebSocket-Protocol: %s\x0d\x0a",
|
||||
lws_hdr_simple_ptr(wsi, _WSI_TOKEN_CLIENT_SENT_PROTOCOLS));
|
||||
|
||||
/* tell the server what extensions we could support */
|
||||
|
||||
p += sprintf(p, "Sec-WebSocket-Extensions: ");
|
||||
#ifndef LWS_NO_EXTENSIONS
|
||||
ext = context->extensions;
|
||||
while (ext && ext->callback) {
|
||||
|
||||
n = lws_ext_callback_for_each_extension_type(context, wsi,
|
||||
LWS_EXT_CALLBACK_CHECK_OK_TO_PROPOSE_EXTENSION,
|
||||
(char *)ext->name, 0);
|
||||
if (n) { /* an extension vetos us */
|
||||
lwsl_ext("ext %s vetoed\n", (char *)ext->name);
|
||||
ext++;
|
||||
continue;
|
||||
}
|
||||
|
||||
n = context->protocols[0].callback(context, wsi,
|
||||
LWS_CALLBACK_CLIENT_CONFIRM_EXTENSION_SUPPORTED,
|
||||
wsi->user_space, (char *)ext->name, 0);
|
||||
|
||||
/*
|
||||
* zero return from callback means
|
||||
* go ahead and allow the extension,
|
||||
* it's what we get if the callback is
|
||||
* unhandled
|
||||
*/
|
||||
|
||||
if (n) {
|
||||
ext++;
|
||||
continue;
|
||||
}
|
||||
|
||||
/* apply it */
|
||||
|
||||
if (ext_count)
|
||||
*p++ = ',';
|
||||
p += sprintf(p, "%s", ext->name);
|
||||
ext_count++;
|
||||
|
||||
ext++;
|
||||
}
|
||||
#endif
|
||||
p += sprintf(p, "\x0d\x0a");
|
||||
|
||||
if (wsi->ietf_spec_revision)
|
||||
p += sprintf(p, "Sec-WebSocket-Version: %d\x0d\x0a",
|
||||
wsi->ietf_spec_revision);
|
||||
|
||||
/* give userland a chance to append, eg, cookies */
|
||||
|
||||
context->protocols[0].callback(context, wsi,
|
||||
LWS_CALLBACK_CLIENT_APPEND_HANDSHAKE_HEADER,
|
||||
NULL, &p, (pkt + sizeof(context->service_buffer)) - p - 12);
|
||||
|
||||
p += sprintf(p, "\x0d\x0a");
|
||||
|
||||
/* prepare the expected server accept response */
|
||||
|
||||
key_b64[39] = '\0'; /* enforce composed length below buf sizeof */
|
||||
n = sprintf(buf, "%s258EAFA5-E914-47DA-95CA-C5AB0DC85B11", key_b64);
|
||||
|
||||
SHA1((unsigned char *)buf, n, (unsigned char *)hash);
|
||||
|
||||
lws_b64_encode_string(hash, 20,
|
||||
wsi->u.hdr.ah->initial_handshake_hash_base64,
|
||||
sizeof(wsi->u.hdr.ah->initial_handshake_hash_base64));
|
||||
|
||||
return p;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
#include "build.h"
|
||||
|
||||
#define LWS_BUILTIN_GETIFADDRS
|
||||
#define LWS_NO_DAEMONIZE
|
||||
@@ -0,0 +1,340 @@
|
||||
/*
|
||||
* libwebsockets - small server side websockets and web server implementation
|
||||
*
|
||||
* Copyright (C) 2010-2014 Andy Green <[email protected]>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation:
|
||||
* version 2.1 of the License.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
||||
* MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#include "private-libwebsockets.h"
|
||||
|
||||
#ifndef LWS_BUILD_HASH
|
||||
#define LWS_BUILD_HASH "unknown-build-hash"
|
||||
#endif
|
||||
|
||||
static const char *library_version = LWS_LIBRARY_VERSION " " LWS_BUILD_HASH;
|
||||
|
||||
/**
|
||||
* lws_get_library_version: get version and git hash library built from
|
||||
*
|
||||
* returns a const char * to a string like "1.1 178d78c"
|
||||
* representing the library version followed by the git head hash it
|
||||
* was built from
|
||||
*/
|
||||
|
||||
LWS_VISIBLE const char *
|
||||
lws_get_library_version(void)
|
||||
{
|
||||
return library_version;
|
||||
}
|
||||
|
||||
/**
|
||||
* libwebsocket_create_context() - Create the websocket handler
|
||||
* @info: pointer to struct with parameters
|
||||
*
|
||||
* This function creates the listening socket (if serving) and takes care
|
||||
* of all initialization in one step.
|
||||
*
|
||||
* After initialization, it returns a struct libwebsocket_context * that
|
||||
* represents this server. After calling, user code needs to take care
|
||||
* of calling libwebsocket_service() with the context pointer to get the
|
||||
* server's sockets serviced. This must be done in the same process
|
||||
* context as the initialization call.
|
||||
*
|
||||
* The protocol callback functions are called for a handful of events
|
||||
* including http requests coming in, websocket connections becoming
|
||||
* established, and data arriving; it's also called periodically to allow
|
||||
* async transmission.
|
||||
*
|
||||
* HTTP requests are sent always to the FIRST protocol in @protocol, since
|
||||
* at that time websocket protocol has not been negotiated. Other
|
||||
* protocols after the first one never see any HTTP callack activity.
|
||||
*
|
||||
* The server created is a simple http server by default; part of the
|
||||
* websocket standard is upgrading this http connection to a websocket one.
|
||||
*
|
||||
* This allows the same server to provide files like scripts and favicon /
|
||||
* images or whatever over http and dynamic data over websockets all in
|
||||
* one place; they're all handled in the user callback.
|
||||
*/
|
||||
|
||||
LWS_VISIBLE struct libwebsocket_context *
|
||||
libwebsocket_create_context(struct lws_context_creation_info *info)
|
||||
{
|
||||
struct libwebsocket_context *context = NULL;
|
||||
char *p;
|
||||
|
||||
int pid_daemon = get_daemonize_pid();
|
||||
|
||||
lwsl_notice("Initial logging level %d\n", log_level);
|
||||
lwsl_notice("Library version: %s\n", library_version);
|
||||
#ifdef LWS_USE_IPV6
|
||||
if (!(info->options & LWS_SERVER_OPTION_DISABLE_IPV6))
|
||||
lwsl_notice("IPV6 compiled in and enabled\n");
|
||||
else
|
||||
lwsl_notice("IPV6 compiled in but disabled\n");
|
||||
#else
|
||||
lwsl_notice("IPV6 not compiled in\n");
|
||||
#endif
|
||||
lws_feature_status_libev(info);
|
||||
lwsl_info(" LWS_MAX_HEADER_LEN: %u\n", LWS_MAX_HEADER_LEN);
|
||||
lwsl_info(" LWS_MAX_PROTOCOLS: %u\n", LWS_MAX_PROTOCOLS);
|
||||
|
||||
lwsl_info(" SPEC_LATEST_SUPPORTED: %u\n", SPEC_LATEST_SUPPORTED);
|
||||
lwsl_info(" AWAITING_TIMEOUT: %u\n", AWAITING_TIMEOUT);
|
||||
lwsl_info(" SYSTEM_RANDOM_FILEPATH: '%s'\n", SYSTEM_RANDOM_FILEPATH);
|
||||
lwsl_info(" LWS_MAX_ZLIB_CONN_BUFFER: %u\n", LWS_MAX_ZLIB_CONN_BUFFER);
|
||||
|
||||
if (lws_plat_context_early_init())
|
||||
return NULL;
|
||||
|
||||
context = (struct libwebsocket_context *)
|
||||
malloc(sizeof(struct libwebsocket_context));
|
||||
if (!context) {
|
||||
lwsl_err("No memory for websocket context\n");
|
||||
return NULL;
|
||||
}
|
||||
memset(context, 0, sizeof(*context));
|
||||
|
||||
if (pid_daemon) {
|
||||
context->started_with_parent = pid_daemon;
|
||||
lwsl_notice(" Started with daemon pid %d\n", pid_daemon);
|
||||
}
|
||||
|
||||
context->listen_service_extraseen = 0;
|
||||
context->protocols = info->protocols;
|
||||
context->listen_port = info->port;
|
||||
context->http_proxy_port = 0;
|
||||
context->http_proxy_address[0] = '\0';
|
||||
context->options = info->options;
|
||||
context->iface = info->iface;
|
||||
/* to reduce this allocation, */
|
||||
context->max_fds = getdtablesize();
|
||||
lwsl_notice(" static allocation: %u + (%u x %u fds) = %u bytes\n",
|
||||
sizeof(struct libwebsocket_context),
|
||||
sizeof(struct libwebsocket_pollfd) +
|
||||
sizeof(struct libwebsocket *),
|
||||
context->max_fds,
|
||||
sizeof(struct libwebsocket_context) +
|
||||
((sizeof(struct libwebsocket_pollfd) +
|
||||
sizeof(struct libwebsocket *)) *
|
||||
context->max_fds));
|
||||
|
||||
context->fds = (struct libwebsocket_pollfd *)
|
||||
malloc(sizeof(struct libwebsocket_pollfd) *
|
||||
context->max_fds);
|
||||
if (context->fds == NULL) {
|
||||
lwsl_err("Unable to allocate fds array for %d connections\n",
|
||||
context->max_fds);
|
||||
free(context);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
context->lws_lookup = (struct libwebsocket **)
|
||||
malloc(sizeof(struct libwebsocket *) * context->max_fds);
|
||||
if (context->lws_lookup == NULL) {
|
||||
lwsl_err(
|
||||
"Unable to allocate lws_lookup array for %d connections\n",
|
||||
context->max_fds);
|
||||
free(context->fds);
|
||||
free(context);
|
||||
return NULL;
|
||||
}
|
||||
memset(context->lws_lookup, 0, sizeof(struct libwebsocket *) *
|
||||
context->max_fds);
|
||||
|
||||
if (lws_plat_init_fd_tables(context)) {
|
||||
free(context->lws_lookup);
|
||||
free(context->fds);
|
||||
free(context);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
lws_context_init_extensions(info, context);
|
||||
|
||||
context->user_space = info->user;
|
||||
|
||||
strcpy(context->canonical_hostname, "unknown");
|
||||
|
||||
lws_server_get_canonical_hostname(context, info);
|
||||
|
||||
/* split the proxy ads:port if given */
|
||||
|
||||
if (info->http_proxy_address) {
|
||||
strncpy(context->http_proxy_address, info->http_proxy_address,
|
||||
sizeof(context->http_proxy_address) - 1);
|
||||
context->http_proxy_address[
|
||||
sizeof(context->http_proxy_address) - 1] = '\0';
|
||||
context->http_proxy_port = info->http_proxy_port;
|
||||
} else {
|
||||
#ifdef HAVE_GETENV
|
||||
p = getenv("http_proxy");
|
||||
if (p) {
|
||||
strncpy(context->http_proxy_address, p,
|
||||
sizeof(context->http_proxy_address) - 1);
|
||||
context->http_proxy_address[
|
||||
sizeof(context->http_proxy_address) - 1] = '\0';
|
||||
|
||||
p = strchr(context->http_proxy_address, ':');
|
||||
if (p == NULL) {
|
||||
lwsl_err("http_proxy needs to be ads:port\n");
|
||||
goto bail;
|
||||
}
|
||||
*p = '\0';
|
||||
context->http_proxy_port = atoi(p + 1);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
if (context->http_proxy_address[0])
|
||||
lwsl_notice(" Proxy %s:%u\n",
|
||||
context->http_proxy_address,
|
||||
context->http_proxy_port);
|
||||
|
||||
lwsl_notice(
|
||||
" per-conn mem: %u + %u headers + protocol rx buf\n",
|
||||
sizeof(struct libwebsocket),
|
||||
sizeof(struct allocated_headers));
|
||||
|
||||
if (lws_context_init_server_ssl(info, context))
|
||||
goto bail;
|
||||
|
||||
if (lws_context_init_client_ssl(info, context))
|
||||
goto bail;
|
||||
|
||||
if (lws_context_init_server(info, context))
|
||||
goto bail;
|
||||
|
||||
/*
|
||||
* drop any root privs for this process
|
||||
* to listen on port < 1023 we would have needed root, but now we are
|
||||
* listening, we don't want the power for anything else
|
||||
*/
|
||||
lws_plat_drop_app_privileges(info);
|
||||
|
||||
/* initialize supported protocols */
|
||||
|
||||
for (context->count_protocols = 0;
|
||||
info->protocols[context->count_protocols].callback;
|
||||
context->count_protocols++) {
|
||||
|
||||
lwsl_parser(" Protocol: %s\n",
|
||||
info->protocols[context->count_protocols].name);
|
||||
|
||||
info->protocols[context->count_protocols].owning_server =
|
||||
context;
|
||||
info->protocols[context->count_protocols].protocol_index =
|
||||
context->count_protocols;
|
||||
|
||||
/*
|
||||
* inform all the protocols that they are doing their one-time
|
||||
* initialization if they want to
|
||||
*/
|
||||
info->protocols[context->count_protocols].callback(context,
|
||||
NULL, LWS_CALLBACK_PROTOCOL_INIT, NULL, NULL, 0);
|
||||
}
|
||||
|
||||
/*
|
||||
* give all extensions a chance to create any per-context
|
||||
* allocations they need
|
||||
*/
|
||||
|
||||
if (info->port != CONTEXT_PORT_NO_LISTEN) {
|
||||
if (lws_ext_callback_for_each_extension_type(context, NULL,
|
||||
LWS_EXT_CALLBACK_SERVER_CONTEXT_CONSTRUCT,
|
||||
NULL, 0) < 0)
|
||||
goto bail;
|
||||
} else
|
||||
if (lws_ext_callback_for_each_extension_type(context, NULL,
|
||||
LWS_EXT_CALLBACK_CLIENT_CONTEXT_CONSTRUCT,
|
||||
NULL, 0) < 0)
|
||||
goto bail;
|
||||
|
||||
return context;
|
||||
|
||||
bail:
|
||||
libwebsocket_context_destroy(context);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* libwebsocket_context_destroy() - Destroy the websocket context
|
||||
* @context: Websocket context
|
||||
*
|
||||
* This function closes any active connections and then frees the
|
||||
* context. After calling this, any further use of the context is
|
||||
* undefined.
|
||||
*/
|
||||
LWS_VISIBLE void
|
||||
libwebsocket_context_destroy(struct libwebsocket_context *context)
|
||||
{
|
||||
int n;
|
||||
struct libwebsocket_protocols *protocol = context->protocols;
|
||||
|
||||
lwsl_notice("%s\n", __func__);
|
||||
|
||||
#ifdef LWS_LATENCY
|
||||
if (context->worst_latency_info[0])
|
||||
lwsl_notice("Worst latency: %s\n", context->worst_latency_info);
|
||||
#endif
|
||||
|
||||
for (n = 0; n < context->fds_count; n++) {
|
||||
struct libwebsocket *wsi =
|
||||
context->lws_lookup[context->fds[n].fd];
|
||||
if (!wsi)
|
||||
continue;
|
||||
libwebsocket_close_and_free_session(context,
|
||||
wsi, LWS_CLOSE_STATUS_NOSTATUS /* no protocol close */);
|
||||
n--;
|
||||
}
|
||||
|
||||
/*
|
||||
* give all extensions a chance to clean up any per-context
|
||||
* allocations they might have made
|
||||
*/
|
||||
if (context->listen_port) {
|
||||
if (lws_ext_callback_for_each_extension_type(context, NULL,
|
||||
LWS_EXT_CALLBACK_SERVER_CONTEXT_DESTRUCT, NULL, 0) < 0)
|
||||
return;
|
||||
} else
|
||||
if (lws_ext_callback_for_each_extension_type(context, NULL,
|
||||
LWS_EXT_CALLBACK_CLIENT_CONTEXT_DESTRUCT, NULL, 0) < 0)
|
||||
return;
|
||||
|
||||
/*
|
||||
* inform all the protocols that they are done and will have no more
|
||||
* callbacks
|
||||
*/
|
||||
|
||||
while (protocol->callback) {
|
||||
protocol->callback(context, NULL, LWS_CALLBACK_PROTOCOL_DESTROY,
|
||||
NULL, NULL, 0);
|
||||
protocol++;
|
||||
}
|
||||
|
||||
lws_plat_context_early_destroy(context);
|
||||
|
||||
lws_ssl_context_destroy(context);
|
||||
|
||||
if (context->fds)
|
||||
free(context->fds);
|
||||
if (context->lws_lookup)
|
||||
free(context->lws_lookup);
|
||||
|
||||
lws_plat_context_late_destroy(context);
|
||||
|
||||
free(context);
|
||||
}
|
||||
@@ -0,0 +1,294 @@
|
||||
#include "private-libwebsockets.h"
|
||||
#include "extension-deflate-frame.h"
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
|
||||
#define LWS_ZLIB_WINDOW_BITS 15
|
||||
#define LWS_ZLIB_MEMLEVEL 8
|
||||
|
||||
int lws_extension_callback_deflate_frame(
|
||||
struct libwebsocket_context *context,
|
||||
struct libwebsocket_extension *ext,
|
||||
struct libwebsocket *wsi,
|
||||
enum libwebsocket_extension_callback_reasons reason,
|
||||
void *user, void *in, size_t len)
|
||||
{
|
||||
struct lws_ext_deflate_frame_conn *conn =
|
||||
(struct lws_ext_deflate_frame_conn *)user;
|
||||
struct lws_tokens *eff_buf = (struct lws_tokens *)in;
|
||||
size_t current_payload, remaining_payload, total_payload;
|
||||
int n;
|
||||
size_t len_so_far;
|
||||
|
||||
switch (reason) {
|
||||
|
||||
/*
|
||||
* for deflate-frame, both client and server sides act the same
|
||||
*/
|
||||
|
||||
case LWS_EXT_CALLBACK_CLIENT_CONSTRUCT:
|
||||
case LWS_EXT_CALLBACK_CONSTRUCT:
|
||||
conn->zs_in.zalloc = conn->zs_out.zalloc = Z_NULL;
|
||||
conn->zs_in.zfree = conn->zs_out.zfree = Z_NULL;
|
||||
conn->zs_in.opaque = conn->zs_out.opaque = Z_NULL;
|
||||
n = inflateInit2(&conn->zs_in, -LWS_ZLIB_WINDOW_BITS);
|
||||
if (n != Z_OK) {
|
||||
lwsl_ext("deflateInit returned %d\n", n);
|
||||
return 1;
|
||||
}
|
||||
n = deflateInit2(&conn->zs_out,
|
||||
(context->listen_port ?
|
||||
DEFLATE_FRAME_COMPRESSION_LEVEL_SERVER :
|
||||
DEFLATE_FRAME_COMPRESSION_LEVEL_CLIENT),
|
||||
Z_DEFLATED,
|
||||
-LWS_ZLIB_WINDOW_BITS, LWS_ZLIB_MEMLEVEL,
|
||||
Z_DEFAULT_STRATEGY);
|
||||
if (n != Z_OK) {
|
||||
lwsl_ext("deflateInit2 returned %d\n", n);
|
||||
return 1;
|
||||
}
|
||||
conn->buf_pre_used = 0;
|
||||
conn->buf_pre_length = 0;
|
||||
conn->buf_in_length = sizeof(conn->buf_in);
|
||||
conn->buf_out_length = sizeof(conn->buf_out);
|
||||
conn->compressed_out = 0;
|
||||
conn->buf_pre = NULL;
|
||||
conn->buf_in = (unsigned char *)
|
||||
malloc(LWS_SEND_BUFFER_PRE_PADDING +
|
||||
conn->buf_in_length +
|
||||
LWS_SEND_BUFFER_POST_PADDING);
|
||||
if (!conn->buf_in)
|
||||
goto bail;
|
||||
conn->buf_out = (unsigned char *)
|
||||
malloc(LWS_SEND_BUFFER_PRE_PADDING +
|
||||
conn->buf_out_length +
|
||||
LWS_SEND_BUFFER_POST_PADDING);
|
||||
if (!conn->buf_out)
|
||||
goto bail;
|
||||
lwsl_ext("zlibs constructed\n");
|
||||
break;
|
||||
bail:
|
||||
lwsl_err("Out of mem\n");
|
||||
(void)inflateEnd(&conn->zs_in);
|
||||
(void)deflateEnd(&conn->zs_out);
|
||||
return -1;
|
||||
|
||||
case LWS_EXT_CALLBACK_DESTROY:
|
||||
if (conn->buf_pre)
|
||||
free(conn->buf_pre);
|
||||
free(conn->buf_in);
|
||||
free(conn->buf_out);
|
||||
conn->buf_pre_used = 0;
|
||||
conn->buf_pre_length = 0;
|
||||
conn->buf_in_length = 0;
|
||||
conn->buf_out_length = 0;
|
||||
conn->compressed_out = 0;
|
||||
(void)inflateEnd(&conn->zs_in);
|
||||
(void)deflateEnd(&conn->zs_out);
|
||||
lwsl_ext("zlibs destructed\n");
|
||||
break;
|
||||
|
||||
case LWS_EXT_CALLBACK_PAYLOAD_RX:
|
||||
if (!(wsi->u.ws.rsv & 0x40))
|
||||
return 0;
|
||||
|
||||
/*
|
||||
* inflate the incoming payload
|
||||
*/
|
||||
current_payload = eff_buf->token_len;
|
||||
|
||||
remaining_payload = wsi->u.ws.rx_packet_length;
|
||||
if (remaining_payload) {
|
||||
total_payload = conn->buf_pre_used +
|
||||
current_payload +
|
||||
remaining_payload;
|
||||
|
||||
if (conn->buf_pre_length < total_payload) {
|
||||
conn->buf_pre_length = total_payload;
|
||||
if (conn->buf_pre)
|
||||
free(conn->buf_pre);
|
||||
conn->buf_pre =
|
||||
(unsigned char *)malloc(total_payload + 4);
|
||||
if (!conn->buf_pre) {
|
||||
lwsl_err("Out of memory\n");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
memcpy(conn->buf_pre + conn->buf_pre_used,
|
||||
eff_buf->token, current_payload);
|
||||
conn->buf_pre_used += current_payload;
|
||||
|
||||
eff_buf->token = NULL;
|
||||
eff_buf->token_len = 0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
if (conn->buf_pre_used) {
|
||||
total_payload = conn->buf_pre_used +
|
||||
current_payload;
|
||||
|
||||
memcpy(conn->buf_pre + conn->buf_pre_used,
|
||||
eff_buf->token, current_payload);
|
||||
conn->buf_pre_used = 0;
|
||||
|
||||
conn->zs_in.next_in = conn->buf_pre;
|
||||
} else {
|
||||
total_payload = current_payload;
|
||||
|
||||
conn->zs_in.next_in = (unsigned char *)eff_buf->token;
|
||||
}
|
||||
|
||||
conn->zs_in.next_in[total_payload + 0] = 0;
|
||||
conn->zs_in.next_in[total_payload + 1] = 0;
|
||||
conn->zs_in.next_in[total_payload + 2] = 0xff;
|
||||
conn->zs_in.next_in[total_payload + 3] = 0xff;
|
||||
|
||||
conn->zs_in.avail_in = total_payload + 4;
|
||||
|
||||
conn->zs_in.next_out =
|
||||
conn->buf_in + LWS_SEND_BUFFER_PRE_PADDING;
|
||||
conn->zs_in.avail_out = conn->buf_in_length;
|
||||
|
||||
while (1) {
|
||||
n = inflate(&conn->zs_in, Z_SYNC_FLUSH);
|
||||
switch (n) {
|
||||
case Z_NEED_DICT:
|
||||
case Z_STREAM_ERROR:
|
||||
case Z_DATA_ERROR:
|
||||
case Z_MEM_ERROR:
|
||||
/*
|
||||
* screwed.. close the connection...
|
||||
* we will get a destroy callback to take care
|
||||
* of closing nicely
|
||||
*/
|
||||
lwsl_info("zlib error inflate %d: %s\n",
|
||||
n, conn->zs_in.msg);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (conn->zs_in.avail_out)
|
||||
break;
|
||||
|
||||
len_so_far = conn->zs_in.next_out -
|
||||
(conn->buf_in + LWS_SEND_BUFFER_PRE_PADDING);
|
||||
|
||||
conn->buf_in_length *= 2;
|
||||
if (conn->buf_in_length > LWS_MAX_ZLIB_CONN_BUFFER) {
|
||||
lwsl_ext("zlib in buffer hit limit %u\n",
|
||||
LWS_MAX_ZLIB_CONN_BUFFER);
|
||||
return -1;
|
||||
}
|
||||
conn->buf_in = (unsigned char *)realloc(conn->buf_in,
|
||||
LWS_SEND_BUFFER_PRE_PADDING +
|
||||
conn->buf_in_length +
|
||||
LWS_SEND_BUFFER_POST_PADDING);
|
||||
if (!conn->buf_in) {
|
||||
lwsl_err("Out of memory\n");
|
||||
return -1;
|
||||
}
|
||||
lwsl_debug(
|
||||
"deflate-frame ext RX did realloc to %ld\n",
|
||||
conn->buf_in_length);
|
||||
conn->zs_in.next_out = conn->buf_in +
|
||||
LWS_SEND_BUFFER_PRE_PADDING + len_so_far;
|
||||
conn->zs_in.avail_out =
|
||||
conn->buf_in_length - len_so_far;
|
||||
}
|
||||
|
||||
/* rewrite the buffer pointers and length */
|
||||
eff_buf->token =
|
||||
(char *)(conn->buf_in + LWS_SEND_BUFFER_PRE_PADDING);
|
||||
eff_buf->token_len = (int)(conn->zs_in.next_out -
|
||||
(conn->buf_in + LWS_SEND_BUFFER_PRE_PADDING));
|
||||
|
||||
return 0;
|
||||
|
||||
case LWS_EXT_CALLBACK_PAYLOAD_TX:
|
||||
/*
|
||||
* deflate the outgoing payload
|
||||
*/
|
||||
current_payload = eff_buf->token_len;
|
||||
|
||||
conn->zs_out.next_in = (unsigned char *)eff_buf->token;
|
||||
conn->zs_out.avail_in = current_payload;
|
||||
|
||||
conn->zs_out.next_out =
|
||||
conn->buf_out + LWS_SEND_BUFFER_PRE_PADDING;
|
||||
conn->zs_out.avail_out = conn->buf_out_length;
|
||||
|
||||
while (1) {
|
||||
n = deflate(&conn->zs_out, Z_SYNC_FLUSH);
|
||||
if (n == Z_STREAM_ERROR) {
|
||||
/*
|
||||
* screwed.. close the connection... we will
|
||||
* get a destroy callback to take care of
|
||||
* closing nicely
|
||||
*/
|
||||
lwsl_ext("zlib error deflate\n");
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (conn->zs_out.avail_out)
|
||||
break;
|
||||
|
||||
len_so_far = (conn->zs_out.next_out -
|
||||
(conn->buf_out +
|
||||
LWS_SEND_BUFFER_PRE_PADDING));
|
||||
conn->buf_out_length *= 2;
|
||||
if (conn->buf_out_length > LWS_MAX_ZLIB_CONN_BUFFER) {
|
||||
lwsl_ext("zlib out hit limit %u\n",
|
||||
LWS_MAX_ZLIB_CONN_BUFFER);
|
||||
return -1;
|
||||
}
|
||||
conn->buf_out = (unsigned char *)realloc(
|
||||
conn->buf_out,
|
||||
LWS_SEND_BUFFER_PRE_PADDING +
|
||||
conn->buf_out_length +
|
||||
LWS_SEND_BUFFER_POST_PADDING);
|
||||
if (!conn->buf_out) {
|
||||
lwsl_err("Out of memory\n");
|
||||
return -1;
|
||||
}
|
||||
lwsl_debug(
|
||||
"deflate-frame ext TX did realloc to %ld\n",
|
||||
conn->buf_in_length);
|
||||
|
||||
conn->zs_out.next_out = (conn->buf_out +
|
||||
LWS_SEND_BUFFER_PRE_PADDING + len_so_far);
|
||||
conn->zs_out.avail_out =
|
||||
(conn->buf_out_length - len_so_far);
|
||||
}
|
||||
|
||||
conn->compressed_out = 1;
|
||||
|
||||
/* rewrite the buffer pointers and length */
|
||||
eff_buf->token = (char *)(conn->buf_out +
|
||||
LWS_SEND_BUFFER_PRE_PADDING);
|
||||
eff_buf->token_len = (int)(conn->zs_out.next_out -
|
||||
(conn->buf_out + LWS_SEND_BUFFER_PRE_PADDING)) - 4;
|
||||
|
||||
return 0;
|
||||
|
||||
case LWS_EXT_CALLBACK_PACKET_TX_PRESEND:
|
||||
if (conn->compressed_out) {
|
||||
conn->compressed_out = 0;
|
||||
*((unsigned char *)eff_buf->token) |= 0x40;
|
||||
}
|
||||
break;
|
||||
|
||||
case LWS_EXT_CALLBACK_CHECK_OK_TO_PROPOSE_EXTENSION:
|
||||
/* Avoid x-webkit-deflate-frame extension on client */
|
||||
if (!strcmp((char *)in, "x-webkit-deflate-frame"))
|
||||
return 1;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
|
||||
#include "deps/zlib/zlib.h"
|
||||
|
||||
#define DEFLATE_FRAME_COMPRESSION_LEVEL_SERVER 1
|
||||
#define DEFLATE_FRAME_COMPRESSION_LEVEL_CLIENT Z_DEFAULT_COMPRESSION
|
||||
|
||||
struct lws_ext_deflate_frame_conn {
|
||||
z_stream zs_in;
|
||||
z_stream zs_out;
|
||||
size_t buf_pre_used;
|
||||
size_t buf_pre_length;
|
||||
size_t buf_in_length;
|
||||
size_t buf_out_length;
|
||||
int compressed_out;
|
||||
unsigned char *buf_pre;
|
||||
unsigned char *buf_in;
|
||||
unsigned char *buf_out;
|
||||
};
|
||||
|
||||
extern int lws_extension_callback_deflate_frame(
|
||||
struct libwebsocket_context *context,
|
||||
struct libwebsocket_extension *ext,
|
||||
struct libwebsocket *wsi,
|
||||
enum libwebsocket_extension_callback_reasons reason,
|
||||
void *user, void *in, size_t len);
|
||||
@@ -0,0 +1,166 @@
|
||||
#include "private-libwebsockets.h"
|
||||
#include "extension-deflate-stream.h"
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
|
||||
#define LWS_ZLIB_WINDOW_BITS 15
|
||||
#define LWS_ZLIB_MEMLEVEL 8
|
||||
|
||||
int lws_extension_callback_deflate_stream(
|
||||
struct libwebsocket_context *context,
|
||||
struct libwebsocket_extension *ext,
|
||||
struct libwebsocket *wsi,
|
||||
enum libwebsocket_extension_callback_reasons reason,
|
||||
void *user, void *in, size_t len)
|
||||
{
|
||||
struct lws_ext_deflate_stream_conn *conn =
|
||||
(struct lws_ext_deflate_stream_conn *)user;
|
||||
int n;
|
||||
struct lws_tokens *eff_buf = (struct lws_tokens *)in;
|
||||
|
||||
switch (reason) {
|
||||
|
||||
/*
|
||||
* for deflate-stream, both client and server sides act the same
|
||||
*/
|
||||
|
||||
case LWS_EXT_CALLBACK_CLIENT_CONSTRUCT:
|
||||
case LWS_EXT_CALLBACK_CONSTRUCT:
|
||||
conn->zs_in.zalloc = conn->zs_out.zalloc = Z_NULL;
|
||||
conn->zs_in.zfree = conn->zs_out.zfree = Z_NULL;
|
||||
conn->zs_in.opaque = conn->zs_out.opaque = Z_NULL;
|
||||
n = inflateInit2(&conn->zs_in, -LWS_ZLIB_WINDOW_BITS);
|
||||
if (n != Z_OK) {
|
||||
lwsl_err("deflateInit returned %d\n", n);
|
||||
return 1;
|
||||
}
|
||||
n = deflateInit2(&conn->zs_out,
|
||||
DEFLATE_STREAM_COMPRESSION_LEVEL, Z_DEFLATED,
|
||||
-LWS_ZLIB_WINDOW_BITS, LWS_ZLIB_MEMLEVEL,
|
||||
Z_DEFAULT_STRATEGY);
|
||||
if (n != Z_OK) {
|
||||
lwsl_err("deflateInit returned %d\n", n);
|
||||
return 1;
|
||||
}
|
||||
lwsl_ext("zlibs constructed\n");
|
||||
conn->remaining_in = 0;
|
||||
break;
|
||||
|
||||
case LWS_EXT_CALLBACK_DESTROY:
|
||||
(void)inflateEnd(&conn->zs_in);
|
||||
(void)deflateEnd(&conn->zs_out);
|
||||
lwsl_ext("zlibs destructed\n");
|
||||
break;
|
||||
|
||||
case LWS_EXT_CALLBACK_PACKET_RX_PREPARSE:
|
||||
|
||||
/*
|
||||
* inflate the incoming compressed data
|
||||
* Notice, length may be 0 and pointer NULL
|
||||
* in the case we are flushing with nothing new coming in
|
||||
*/
|
||||
if (conn->remaining_in) {
|
||||
conn->zs_in.next_in = conn->buf_in;
|
||||
conn->zs_in.avail_in = conn->remaining_in;
|
||||
conn->remaining_in = 0;
|
||||
} else {
|
||||
conn->zs_in.next_in = (unsigned char *)eff_buf->token;
|
||||
conn->zs_in.avail_in = eff_buf->token_len;
|
||||
}
|
||||
|
||||
conn->zs_in.next_out = conn->buf_out;
|
||||
conn->zs_in.avail_out = sizeof(conn->buf_out);
|
||||
|
||||
n = inflate(&conn->zs_in, Z_SYNC_FLUSH);
|
||||
switch (n) {
|
||||
case Z_NEED_DICT:
|
||||
case Z_DATA_ERROR:
|
||||
case Z_MEM_ERROR:
|
||||
/*
|
||||
* screwed.. close the connection... we will get a
|
||||
* destroy callback to take care of closing nicely
|
||||
*/
|
||||
lwsl_err("zlib error inflate %d\n", n);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* rewrite the buffer pointers and length */
|
||||
|
||||
eff_buf->token = (char *)conn->buf_out;
|
||||
eff_buf->token_len =
|
||||
sizeof(conn->buf_out) - conn->zs_in.avail_out;
|
||||
|
||||
/* copy avail data if not consumed */
|
||||
if (conn->zs_in.avail_in > 0) {
|
||||
conn->remaining_in = conn->zs_in.avail_in;
|
||||
memcpy(conn->buf_in, conn->zs_in.next_in,
|
||||
conn->zs_in.avail_in);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* if we filled the output buffer, signal that we likely have
|
||||
* more and need to be called again
|
||||
*/
|
||||
|
||||
if (eff_buf->token_len == sizeof(conn->buf_out))
|
||||
return 1;
|
||||
|
||||
/* we don't need calling again until new input data comes */
|
||||
|
||||
return 0;
|
||||
|
||||
case LWS_EXT_CALLBACK_FLUSH_PENDING_TX:
|
||||
case LWS_EXT_CALLBACK_PACKET_TX_PRESEND:
|
||||
|
||||
/*
|
||||
* deflate the outgoing compressed data
|
||||
*/
|
||||
|
||||
conn->zs_out.next_in = (unsigned char *)eff_buf->token;
|
||||
conn->zs_out.avail_in = eff_buf->token_len;
|
||||
|
||||
conn->zs_out.next_out = conn->buf_out;
|
||||
conn->zs_out.avail_out = sizeof(conn->buf_out);
|
||||
|
||||
n = Z_PARTIAL_FLUSH;
|
||||
if (reason == LWS_EXT_CALLBACK_FLUSH_PENDING_TX)
|
||||
n = Z_FULL_FLUSH;
|
||||
|
||||
n = deflate(&conn->zs_out, n);
|
||||
if (n == Z_STREAM_ERROR) {
|
||||
/*
|
||||
* screwed.. close the connection... we will get a
|
||||
* destroy callback to take care of closing nicely
|
||||
*/
|
||||
lwsl_ext("zlib error deflate\n");
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* rewrite the buffer pointers and length */
|
||||
|
||||
eff_buf->token = (char *)conn->buf_out;
|
||||
eff_buf->token_len =
|
||||
sizeof(conn->buf_out) - conn->zs_out.avail_out;
|
||||
|
||||
/*
|
||||
* if we filled the output buffer, signal that we likely have
|
||||
* more and need to be called again... even in deflate case
|
||||
* we might sometimes need to spill more than came in
|
||||
*/
|
||||
|
||||
if (eff_buf->token_len == sizeof(conn->buf_out))
|
||||
return 1;
|
||||
|
||||
/* we don't need calling again until new input data comes */
|
||||
|
||||
return 0;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
|
||||
#include "deps/zlib/zlib.h"
|
||||
|
||||
#define DEFLATE_STREAM_CHUNK 128
|
||||
#define DEFLATE_STREAM_COMPRESSION_LEVEL 1
|
||||
|
||||
struct lws_ext_deflate_stream_conn {
|
||||
z_stream zs_in;
|
||||
z_stream zs_out;
|
||||
int remaining_in;
|
||||
unsigned char buf_in[LWS_MAX_SOCKET_IO_BUF];
|
||||
unsigned char buf_out[LWS_MAX_SOCKET_IO_BUF];
|
||||
};
|
||||
|
||||
extern int lws_extension_callback_deflate_stream(
|
||||
struct libwebsocket_context *context,
|
||||
struct libwebsocket_extension *ext,
|
||||
struct libwebsocket *wsi,
|
||||
enum libwebsocket_extension_callback_reasons reason,
|
||||
void *user, void *in, size_t len);
|
||||
@@ -0,0 +1,206 @@
|
||||
#include "private-libwebsockets.h"
|
||||
|
||||
#include "extension-deflate-frame.h"
|
||||
#include "extension-deflate-stream.h"
|
||||
|
||||
struct libwebsocket_extension libwebsocket_internal_extensions[] = {
|
||||
#ifdef LWS_EXT_DEFLATE_STREAM
|
||||
{
|
||||
"deflate-stream",
|
||||
lws_extension_callback_deflate_stream,
|
||||
sizeof(struct lws_ext_deflate_stream_conn)
|
||||
},
|
||||
#else
|
||||
{
|
||||
"x-webkit-deflate-frame",
|
||||
lws_extension_callback_deflate_frame,
|
||||
sizeof(struct lws_ext_deflate_frame_conn)
|
||||
},
|
||||
{
|
||||
"deflate-frame",
|
||||
lws_extension_callback_deflate_frame,
|
||||
sizeof(struct lws_ext_deflate_frame_conn)
|
||||
},
|
||||
#endif
|
||||
{ /* terminator */
|
||||
NULL, NULL, 0
|
||||
}
|
||||
};
|
||||
|
||||
LWS_VISIBLE void
|
||||
lws_context_init_extensions(struct lws_context_creation_info *info,
|
||||
struct libwebsocket_context *context)
|
||||
{
|
||||
context->extensions = info->extensions;
|
||||
lwsl_info(" LWS_MAX_EXTENSIONS_ACTIVE: %u\n", LWS_MAX_EXTENSIONS_ACTIVE);
|
||||
}
|
||||
|
||||
LWS_VISIBLE struct libwebsocket_extension *libwebsocket_get_internal_extensions()
|
||||
{
|
||||
return libwebsocket_internal_extensions;
|
||||
}
|
||||
|
||||
|
||||
/* 0 = nobody had nonzero return, 1 = somebody had positive return, -1 = fail */
|
||||
|
||||
int lws_ext_callback_for_each_active(struct libwebsocket *wsi, int reason,
|
||||
void *arg, int len)
|
||||
{
|
||||
int n, m, handled = 0;
|
||||
|
||||
for (n = 0; n < wsi->count_active_extensions; n++) {
|
||||
m = wsi->active_extensions[n]->callback(
|
||||
wsi->protocol->owning_server,
|
||||
wsi->active_extensions[n], wsi,
|
||||
reason,
|
||||
wsi->active_extensions_user[n],
|
||||
arg, len);
|
||||
if (m < 0) {
|
||||
lwsl_ext(
|
||||
"Extension '%s' failed to handle callback %d!\n",
|
||||
wsi->active_extensions[n]->name, reason);
|
||||
return -1;
|
||||
}
|
||||
if (m > handled)
|
||||
handled = m;
|
||||
}
|
||||
|
||||
return handled;
|
||||
}
|
||||
|
||||
int lws_ext_callback_for_each_extension_type(
|
||||
struct libwebsocket_context *context, struct libwebsocket *wsi,
|
||||
int reason, void *arg, int len)
|
||||
{
|
||||
int n = 0, m, handled = 0;
|
||||
struct libwebsocket_extension *ext = context->extensions;
|
||||
|
||||
while (ext && ext->callback && !handled) {
|
||||
m = ext->callback(context, ext, wsi, reason,
|
||||
(void *)(long)n, arg, len);
|
||||
if (m < 0) {
|
||||
lwsl_ext(
|
||||
"Extension '%s' failed to handle callback %d!\n",
|
||||
wsi->active_extensions[n]->name, reason);
|
||||
return -1;
|
||||
}
|
||||
if (m)
|
||||
handled = 1;
|
||||
|
||||
ext++;
|
||||
n++;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
lws_issue_raw_ext_access(struct libwebsocket *wsi,
|
||||
unsigned char *buf, size_t len)
|
||||
{
|
||||
int ret;
|
||||
struct lws_tokens eff_buf;
|
||||
int m;
|
||||
int n;
|
||||
|
||||
eff_buf.token = (char *)buf;
|
||||
eff_buf.token_len = len;
|
||||
|
||||
/*
|
||||
* while we have original buf to spill ourselves, or extensions report
|
||||
* more in their pipeline
|
||||
*/
|
||||
|
||||
ret = 1;
|
||||
while (ret == 1) {
|
||||
|
||||
/* default to nobody has more to spill */
|
||||
|
||||
ret = 0;
|
||||
|
||||
/* show every extension the new incoming data */
|
||||
m = lws_ext_callback_for_each_active(wsi,
|
||||
LWS_EXT_CALLBACK_PACKET_TX_PRESEND, &eff_buf, 0);
|
||||
if (m < 0)
|
||||
return -1;
|
||||
if (m) /* handled */
|
||||
ret = 1;
|
||||
|
||||
if ((char *)buf != eff_buf.token)
|
||||
/*
|
||||
* extension recreated it:
|
||||
* need to buffer this if not all sent
|
||||
*/
|
||||
wsi->u.ws.clean_buffer = 0;
|
||||
|
||||
/* assuming they left us something to send, send it */
|
||||
|
||||
if (eff_buf.token_len) {
|
||||
n = lws_issue_raw(wsi, (unsigned char *)eff_buf.token,
|
||||
eff_buf.token_len);
|
||||
if (n < 0) {
|
||||
lwsl_info("closing from ext access\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* always either sent it all or privately buffered */
|
||||
}
|
||||
|
||||
lwsl_parser("written %d bytes to client\n", eff_buf.token_len);
|
||||
|
||||
/* no extension has more to spill? Then we can go */
|
||||
|
||||
if (!ret)
|
||||
break;
|
||||
|
||||
/* we used up what we had */
|
||||
|
||||
eff_buf.token = NULL;
|
||||
eff_buf.token_len = 0;
|
||||
|
||||
/*
|
||||
* Did that leave the pipe choked?
|
||||
* Or we had to hold on to some of it?
|
||||
*/
|
||||
|
||||
if (!lws_send_pipe_choked(wsi) && !wsi->truncated_send_len)
|
||||
/* no we could add more, lets's do that */
|
||||
continue;
|
||||
|
||||
lwsl_debug("choked\n");
|
||||
|
||||
/*
|
||||
* Yes, he's choked. Don't spill the rest now get a callback
|
||||
* when he is ready to send and take care of it there
|
||||
*/
|
||||
libwebsocket_callback_on_writable(
|
||||
wsi->protocol->owning_server, wsi);
|
||||
wsi->extension_data_pending = 1;
|
||||
ret = 0;
|
||||
}
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
int
|
||||
lws_any_extension_handled(struct libwebsocket_context *context,
|
||||
struct libwebsocket *wsi,
|
||||
enum libwebsocket_extension_callback_reasons r,
|
||||
void *v, size_t len)
|
||||
{
|
||||
int n;
|
||||
int handled = 0;
|
||||
|
||||
/* maybe an extension will take care of it for us */
|
||||
|
||||
for (n = 0; n < wsi->count_active_extensions && !handled; n++) {
|
||||
if (!wsi->active_extensions[n]->callback)
|
||||
continue;
|
||||
|
||||
handled |= wsi->active_extensions[n]->callback(context,
|
||||
wsi->active_extensions[n], wsi,
|
||||
r, wsi->active_extensions_user[n], v, len);
|
||||
}
|
||||
|
||||
return handled;
|
||||
}
|
||||
@@ -0,0 +1,171 @@
|
||||
/*
|
||||
* libwebsockets - small server side websockets and web server implementation
|
||||
*
|
||||
* Copyright (C) 2010-2013 Andy Green <[email protected]>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation:
|
||||
* version 2.1 of the License.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
||||
* MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#include "private-libwebsockets.h"
|
||||
|
||||
/*
|
||||
* -04 of the protocol (actually the 80th version) has a radically different
|
||||
* handshake. The 04 spec gives the following idea
|
||||
*
|
||||
* The handshake from the client looks as follows:
|
||||
*
|
||||
* GET /chat HTTP/1.1
|
||||
* Host: server.example.com
|
||||
* Upgrade: websocket
|
||||
* Connection: Upgrade
|
||||
* Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==
|
||||
* Sec-WebSocket-Origin: http://example.com
|
||||
* Sec-WebSocket-Protocol: chat, superchat
|
||||
* Sec-WebSocket-Version: 4
|
||||
*
|
||||
* The handshake from the server looks as follows:
|
||||
*
|
||||
* HTTP/1.1 101 Switching Protocols
|
||||
* Upgrade: websocket
|
||||
* Connection: Upgrade
|
||||
* Sec-WebSocket-Accept: me89jWimTRKTWwrS3aRrL53YZSo=
|
||||
* Sec-WebSocket-Nonce: AQIDBAUGBwgJCgsMDQ4PEC==
|
||||
* Sec-WebSocket-Protocol: chat
|
||||
*/
|
||||
|
||||
/*
|
||||
* We have to take care about parsing because the headers may be split
|
||||
* into multiple fragments. They may contain unknown headers with arbitrary
|
||||
* argument lengths. So, we parse using a single-character at a time state
|
||||
* machine that is completely independent of packet size.
|
||||
*/
|
||||
|
||||
LWS_VISIBLE int
|
||||
libwebsocket_read(struct libwebsocket_context *context,
|
||||
struct libwebsocket *wsi, unsigned char *buf, size_t len)
|
||||
{
|
||||
size_t n;
|
||||
|
||||
switch (wsi->state) {
|
||||
|
||||
case WSI_STATE_HTTP_BODY:
|
||||
http_postbody:
|
||||
while (len--) {
|
||||
|
||||
if (wsi->u.http.content_length_seen >= wsi->u.http.content_length)
|
||||
break;
|
||||
|
||||
wsi->u.http.post_buffer[wsi->u.http.body_index++] = *buf++;
|
||||
wsi->u.http.content_length_seen++;
|
||||
n = wsi->protocol->rx_buffer_size;
|
||||
if (!n)
|
||||
n = LWS_MAX_SOCKET_IO_BUF;
|
||||
|
||||
if (wsi->u.http.body_index != n &&
|
||||
wsi->u.http.content_length_seen != wsi->u.http.content_length)
|
||||
continue;
|
||||
|
||||
if (wsi->protocol->callback) {
|
||||
n = wsi->protocol->callback(
|
||||
wsi->protocol->owning_server, wsi,
|
||||
LWS_CALLBACK_HTTP_BODY,
|
||||
wsi->user_space, wsi->u.http.post_buffer,
|
||||
wsi->u.http.body_index);
|
||||
wsi->u.http.body_index = 0;
|
||||
if (n)
|
||||
goto bail;
|
||||
}
|
||||
|
||||
if (wsi->u.http.content_length_seen == wsi->u.http.content_length) {
|
||||
/* he sent the content in time */
|
||||
libwebsocket_set_timeout(wsi, NO_PENDING_TIMEOUT, 0);
|
||||
n = wsi->protocol->callback(
|
||||
wsi->protocol->owning_server, wsi,
|
||||
LWS_CALLBACK_HTTP_BODY_COMPLETION,
|
||||
wsi->user_space, NULL, 0);
|
||||
wsi->u.http.body_index = 0;
|
||||
if (n)
|
||||
goto bail;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
* we need to spill here so everything is seen in the case
|
||||
* there is no content-length
|
||||
*/
|
||||
if (wsi->u.http.body_index && wsi->protocol->callback) {
|
||||
n = wsi->protocol->callback(
|
||||
wsi->protocol->owning_server, wsi,
|
||||
LWS_CALLBACK_HTTP_BODY,
|
||||
wsi->user_space, wsi->u.http.post_buffer,
|
||||
wsi->u.http.body_index);
|
||||
wsi->u.http.body_index = 0;
|
||||
if (n)
|
||||
goto bail;
|
||||
}
|
||||
break;
|
||||
|
||||
case WSI_STATE_HTTP_ISSUING_FILE:
|
||||
case WSI_STATE_HTTP:
|
||||
wsi->state = WSI_STATE_HTTP_HEADERS;
|
||||
wsi->u.hdr.parser_state = WSI_TOKEN_NAME_PART;
|
||||
wsi->u.hdr.lextable_pos = 0;
|
||||
/* fallthru */
|
||||
case WSI_STATE_HTTP_HEADERS:
|
||||
|
||||
lwsl_parser("issuing %d bytes to parser\n", (int)len);
|
||||
|
||||
if (lws_handshake_client(wsi, &buf, len))
|
||||
goto bail;
|
||||
|
||||
switch (lws_handshake_server(context, wsi, &buf, len)) {
|
||||
case 1:
|
||||
goto bail;
|
||||
case 2:
|
||||
goto http_postbody;
|
||||
}
|
||||
break;
|
||||
|
||||
case WSI_STATE_AWAITING_CLOSE_ACK:
|
||||
case WSI_STATE_ESTABLISHED:
|
||||
if (lws_handshake_client(wsi, &buf, len))
|
||||
goto bail;
|
||||
switch (wsi->mode) {
|
||||
case LWS_CONNMODE_WS_SERVING:
|
||||
|
||||
if (libwebsocket_interpret_incoming_packet(wsi, buf, len) < 0) {
|
||||
lwsl_info("interpret_incoming_packet has bailed\n");
|
||||
goto bail;
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
lwsl_err("libwebsocket_read: Unhandled state\n");
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
bail:
|
||||
lwsl_debug("closing connection at libwebsocket_read bail:\n");
|
||||
|
||||
libwebsocket_close_and_free_session(context, wsi,
|
||||
LWS_CLOSE_STATUS_NOSTATUS);
|
||||
|
||||
return -1;
|
||||
}
|
||||
@@ -0,0 +1,287 @@
|
||||
/* pos 0000: 0 */ 0x67 /* 'g' */, 0x25, 0x00 /* (to 0x0025 state 1) */,
|
||||
0x70 /* 'p' */, 0x27, 0x00 /* (to 0x002A state 5) */,
|
||||
0x68 /* 'h' */, 0x30, 0x00 /* (to 0x0036 state 10) */,
|
||||
0x63 /* 'c' */, 0x39, 0x00 /* (to 0x0042 state 15) */,
|
||||
0x73 /* 's' */, 0x54, 0x00 /* (to 0x0060 state 26) */,
|
||||
0x75 /* 'u' */, 0x93, 0x00 /* (to 0x00A2 state 56) */,
|
||||
0x6F /* 'o' */, 0x99, 0x00 /* (to 0x00AB state 64) */,
|
||||
0x0D /* '.' */, 0xA5, 0x00 /* (to 0x00BA state 77) */,
|
||||
0x61 /* 'a' */, 0xDC, 0x00 /* (to 0x00F4 state 127) */,
|
||||
0x69 /* 'i' */, 0xED, 0x00 /* (to 0x0108 state 134) */,
|
||||
0x64 /* 'd' */, 0x5A, 0x01 /* (to 0x0178 state 225) */,
|
||||
0x72 /* 'r' */, 0x5D, 0x01 /* (to 0x017E state 230) */,
|
||||
0x08, /* fail */
|
||||
/* pos 0025: 1 */ 0xE5 /* 'e' -> */,
|
||||
/* pos 0026: 2 */ 0xF4 /* 't' -> */,
|
||||
/* pos 0027: 3 */ 0xA0 /* ' ' -> */,
|
||||
/* pos 0028: 4 */ 0x00, 0x00 /* - terminal marker 0 - */,
|
||||
/* pos 002a: 5 */ 0x6F /* 'o' */, 0x07, 0x00 /* (to 0x0031 state 6) */,
|
||||
0x72 /* 'r' */, 0x09, 0x01 /* (to 0x0136 state 171) */,
|
||||
0x08, /* fail */
|
||||
/* pos 0031: 6 */ 0xF3 /* 's' -> */,
|
||||
/* pos 0032: 7 */ 0xF4 /* 't' -> */,
|
||||
/* pos 0033: 8 */ 0xA0 /* ' ' -> */,
|
||||
/* pos 0034: 9 */ 0x00, 0x01 /* - terminal marker 1 - */,
|
||||
/* pos 0036: 10 */ 0x6F /* 'o' */, 0x07, 0x00 /* (to 0x003D state 11) */,
|
||||
0x74 /* 't' */, 0xB2, 0x00 /* (to 0x00EB state 119) */,
|
||||
0x08, /* fail */
|
||||
/* pos 003d: 11 */ 0xF3 /* 's' -> */,
|
||||
/* pos 003e: 12 */ 0xF4 /* 't' -> */,
|
||||
/* pos 003f: 13 */ 0xBA /* ':' -> */,
|
||||
/* pos 0040: 14 */ 0x00, 0x02 /* - terminal marker 2 - */,
|
||||
/* pos 0042: 15 */ 0x6F /* 'o' */, 0x07, 0x00 /* (to 0x0049 state 16) */,
|
||||
0x61 /* 'a' */, 0xF8, 0x00 /* (to 0x013D state 177) */,
|
||||
0x08, /* fail */
|
||||
/* pos 0049: 16 */ 0x6E /* 'n' */, 0x07, 0x00 /* (to 0x0050 state 17) */,
|
||||
0x6F /* 'o' */, 0x0D, 0x01 /* (to 0x0159 state 203) */,
|
||||
0x08, /* fail */
|
||||
/* pos 0050: 17 */ 0x6E /* 'n' */, 0x07, 0x00 /* (to 0x0057 state 18) */,
|
||||
0x74 /* 't' */, 0x0C, 0x01 /* (to 0x015F state 208) */,
|
||||
0x08, /* fail */
|
||||
/* pos 0057: 18 */ 0xE5 /* 'e' -> */,
|
||||
/* pos 0058: 19 */ 0xE3 /* 'c' -> */,
|
||||
/* pos 0059: 20 */ 0xF4 /* 't' -> */,
|
||||
/* pos 005a: 21 */ 0xE9 /* 'i' -> */,
|
||||
/* pos 005b: 22 */ 0xEF /* 'o' -> */,
|
||||
/* pos 005c: 23 */ 0xEE /* 'n' -> */,
|
||||
/* pos 005d: 24 */ 0xBA /* ':' -> */,
|
||||
/* pos 005e: 25 */ 0x00, 0x03 /* - terminal marker 3 - */,
|
||||
/* pos 0060: 26 */ 0xE5 /* 'e' -> */,
|
||||
/* pos 0061: 27 */ 0xE3 /* 'c' -> */,
|
||||
/* pos 0062: 28 */ 0xAD /* '-' -> */,
|
||||
/* pos 0063: 29 */ 0xF7 /* 'w' -> */,
|
||||
/* pos 0064: 30 */ 0xE5 /* 'e' -> */,
|
||||
/* pos 0065: 31 */ 0xE2 /* 'b' -> */,
|
||||
/* pos 0066: 32 */ 0xF3 /* 's' -> */,
|
||||
/* pos 0067: 33 */ 0xEF /* 'o' -> */,
|
||||
/* pos 0068: 34 */ 0xE3 /* 'c' -> */,
|
||||
/* pos 0069: 35 */ 0xEB /* 'k' -> */,
|
||||
/* pos 006a: 36 */ 0xE5 /* 'e' -> */,
|
||||
/* pos 006b: 37 */ 0xF4 /* 't' -> */,
|
||||
/* pos 006c: 38 */ 0xAD /* '-' -> */,
|
||||
/* pos 006d: 39 */ 0x6B /* 'k' */, 0x19, 0x00 /* (to 0x0086 state 40) */,
|
||||
0x70 /* 'p' */, 0x28, 0x00 /* (to 0x0098 state 47) */,
|
||||
0x64 /* 'd' */, 0x40, 0x00 /* (to 0x00B3 state 71) */,
|
||||
0x76 /* 'v' */, 0x49, 0x00 /* (to 0x00BF state 80) */,
|
||||
0x6F /* 'o' */, 0x4F, 0x00 /* (to 0x00C8 state 88) */,
|
||||
0x65 /* 'e' */, 0x54, 0x00 /* (to 0x00D0 state 95) */,
|
||||
0x61 /* 'a' */, 0x5D, 0x00 /* (to 0x00DC state 106) */,
|
||||
0x6E /* 'n' */, 0x62, 0x00 /* (to 0x00E4 state 113) */,
|
||||
0x08, /* fail */
|
||||
/* pos 0086: 40 */ 0xE5 /* 'e' -> */,
|
||||
/* pos 0087: 41 */ 0xF9 /* 'y' -> */,
|
||||
/* pos 0088: 42 */ 0x31 /* '1' */, 0x0A, 0x00 /* (to 0x0092 state 43) */,
|
||||
0x32 /* '2' */, 0x0A, 0x00 /* (to 0x0095 state 45) */,
|
||||
0x3A /* ':' */, 0x2F, 0x00 /* (to 0x00BD state 79) */,
|
||||
0x08, /* fail */
|
||||
/* pos 0092: 43 */ 0xBA /* ':' -> */,
|
||||
/* pos 0093: 44 */ 0x00, 0x04 /* - terminal marker 4 - */,
|
||||
/* pos 0095: 45 */ 0xBA /* ':' -> */,
|
||||
/* pos 0096: 46 */ 0x00, 0x05 /* - terminal marker 5 - */,
|
||||
/* pos 0098: 47 */ 0xF2 /* 'r' -> */,
|
||||
/* pos 0099: 48 */ 0xEF /* 'o' -> */,
|
||||
/* pos 009a: 49 */ 0xF4 /* 't' -> */,
|
||||
/* pos 009b: 50 */ 0xEF /* 'o' -> */,
|
||||
/* pos 009c: 51 */ 0xE3 /* 'c' -> */,
|
||||
/* pos 009d: 52 */ 0xEF /* 'o' -> */,
|
||||
/* pos 009e: 53 */ 0xEC /* 'l' -> */,
|
||||
/* pos 009f: 54 */ 0xBA /* ':' -> */,
|
||||
/* pos 00a0: 55 */ 0x00, 0x06 /* - terminal marker 6 - */,
|
||||
/* pos 00a2: 56 */ 0xF0 /* 'p' -> */,
|
||||
/* pos 00a3: 57 */ 0xE7 /* 'g' -> */,
|
||||
/* pos 00a4: 58 */ 0xF2 /* 'r' -> */,
|
||||
/* pos 00a5: 59 */ 0xE1 /* 'a' -> */,
|
||||
/* pos 00a6: 60 */ 0xE4 /* 'd' -> */,
|
||||
/* pos 00a7: 61 */ 0xE5 /* 'e' -> */,
|
||||
/* pos 00a8: 62 */ 0xBA /* ':' -> */,
|
||||
/* pos 00a9: 63 */ 0x00, 0x07 /* - terminal marker 7 - */,
|
||||
/* pos 00ab: 64 */ 0xF2 /* 'r' -> */,
|
||||
/* pos 00ac: 65 */ 0xE9 /* 'i' -> */,
|
||||
/* pos 00ad: 66 */ 0xE7 /* 'g' -> */,
|
||||
/* pos 00ae: 67 */ 0xE9 /* 'i' -> */,
|
||||
/* pos 00af: 68 */ 0xEE /* 'n' -> */,
|
||||
/* pos 00b0: 69 */ 0xBA /* ':' -> */,
|
||||
/* pos 00b1: 70 */ 0x00, 0x08 /* - terminal marker 8 - */,
|
||||
/* pos 00b3: 71 */ 0xF2 /* 'r' -> */,
|
||||
/* pos 00b4: 72 */ 0xE1 /* 'a' -> */,
|
||||
/* pos 00b5: 73 */ 0xE6 /* 'f' -> */,
|
||||
/* pos 00b6: 74 */ 0xF4 /* 't' -> */,
|
||||
/* pos 00b7: 75 */ 0xBA /* ':' -> */,
|
||||
/* pos 00b8: 76 */ 0x00, 0x09 /* - terminal marker 9 - */,
|
||||
/* pos 00ba: 77 */ 0x8A /* '.' -> */,
|
||||
/* pos 00bb: 78 */ 0x00, 0x0A /* - terminal marker 10 - */,
|
||||
/* pos 00bd: 79 */ 0x00, 0x0B /* - terminal marker 11 - */,
|
||||
/* pos 00bf: 80 */ 0xE5 /* 'e' -> */,
|
||||
/* pos 00c0: 81 */ 0xF2 /* 'r' -> */,
|
||||
/* pos 00c1: 82 */ 0xF3 /* 's' -> */,
|
||||
/* pos 00c2: 83 */ 0xE9 /* 'i' -> */,
|
||||
/* pos 00c3: 84 */ 0xEF /* 'o' -> */,
|
||||
/* pos 00c4: 85 */ 0xEE /* 'n' -> */,
|
||||
/* pos 00c5: 86 */ 0xBA /* ':' -> */,
|
||||
/* pos 00c6: 87 */ 0x00, 0x0C /* - terminal marker 12 - */,
|
||||
/* pos 00c8: 88 */ 0xF2 /* 'r' -> */,
|
||||
/* pos 00c9: 89 */ 0xE9 /* 'i' -> */,
|
||||
/* pos 00ca: 90 */ 0xE7 /* 'g' -> */,
|
||||
/* pos 00cb: 91 */ 0xE9 /* 'i' -> */,
|
||||
/* pos 00cc: 92 */ 0xEE /* 'n' -> */,
|
||||
/* pos 00cd: 93 */ 0xBA /* ':' -> */,
|
||||
/* pos 00ce: 94 */ 0x00, 0x0D /* - terminal marker 13 - */,
|
||||
/* pos 00d0: 95 */ 0xF8 /* 'x' -> */,
|
||||
/* pos 00d1: 96 */ 0xF4 /* 't' -> */,
|
||||
/* pos 00d2: 97 */ 0xE5 /* 'e' -> */,
|
||||
/* pos 00d3: 98 */ 0xEE /* 'n' -> */,
|
||||
/* pos 00d4: 99 */ 0xF3 /* 's' -> */,
|
||||
/* pos 00d5: 100 */ 0xE9 /* 'i' -> */,
|
||||
/* pos 00d6: 101 */ 0xEF /* 'o' -> */,
|
||||
/* pos 00d7: 102 */ 0xEE /* 'n' -> */,
|
||||
/* pos 00d8: 103 */ 0xF3 /* 's' -> */,
|
||||
/* pos 00d9: 104 */ 0xBA /* ':' -> */,
|
||||
/* pos 00da: 105 */ 0x00, 0x0E /* - terminal marker 14 - */,
|
||||
/* pos 00dc: 106 */ 0xE3 /* 'c' -> */,
|
||||
/* pos 00dd: 107 */ 0xE3 /* 'c' -> */,
|
||||
/* pos 00de: 108 */ 0xE5 /* 'e' -> */,
|
||||
/* pos 00df: 109 */ 0xF0 /* 'p' -> */,
|
||||
/* pos 00e0: 110 */ 0xF4 /* 't' -> */,
|
||||
/* pos 00e1: 111 */ 0xBA /* ':' -> */,
|
||||
/* pos 00e2: 112 */ 0x00, 0x0F /* - terminal marker 15 - */,
|
||||
/* pos 00e4: 113 */ 0xEF /* 'o' -> */,
|
||||
/* pos 00e5: 114 */ 0xEE /* 'n' -> */,
|
||||
/* pos 00e6: 115 */ 0xE3 /* 'c' -> */,
|
||||
/* pos 00e7: 116 */ 0xE5 /* 'e' -> */,
|
||||
/* pos 00e8: 117 */ 0xBA /* ':' -> */,
|
||||
/* pos 00e9: 118 */ 0x00, 0x10 /* - terminal marker 16 - */,
|
||||
/* pos 00eb: 119 */ 0xF4 /* 't' -> */,
|
||||
/* pos 00ec: 120 */ 0xF0 /* 'p' -> */,
|
||||
/* pos 00ed: 121 */ 0xAF /* '/' -> */,
|
||||
/* pos 00ee: 122 */ 0xB1 /* '1' -> */,
|
||||
/* pos 00ef: 123 */ 0xAE /* '.' -> */,
|
||||
/* pos 00f0: 124 */ 0xB1 /* '1' -> */,
|
||||
/* pos 00f1: 125 */ 0xA0 /* ' ' -> */,
|
||||
/* pos 00f2: 126 */ 0x00, 0x11 /* - terminal marker 17 - */,
|
||||
/* pos 00f4: 127 */ 0x63 /* 'c' */, 0x07, 0x00 /* (to 0x00FB state 128) */,
|
||||
0x75 /* 'u' */, 0x54, 0x00 /* (to 0x014B state 190) */,
|
||||
0x08, /* fail */
|
||||
/* pos 00fb: 128 */ 0xE3 /* 'c' -> */,
|
||||
/* pos 00fc: 129 */ 0xE5 /* 'e' -> */,
|
||||
/* pos 00fd: 130 */ 0xF0 /* 'p' -> */,
|
||||
/* pos 00fe: 131 */ 0xF4 /* 't' -> */,
|
||||
/* pos 00ff: 132 */ 0x3A /* ':' */, 0x07, 0x00 /* (to 0x0106 state 133) */,
|
||||
0x2D /* '-' */, 0x19, 0x00 /* (to 0x011B state 152) */,
|
||||
0x08, /* fail */
|
||||
/* pos 0106: 133 */ 0x00, 0x12 /* - terminal marker 18 - */,
|
||||
/* pos 0108: 134 */ 0xE6 /* 'f' -> */,
|
||||
/* pos 0109: 135 */ 0xAD /* '-' -> */,
|
||||
/* pos 010a: 136 */ 0xED /* 'm' -> */,
|
||||
/* pos 010b: 137 */ 0xEF /* 'o' -> */,
|
||||
/* pos 010c: 138 */ 0xE4 /* 'd' -> */,
|
||||
/* pos 010d: 139 */ 0xE9 /* 'i' -> */,
|
||||
/* pos 010e: 140 */ 0xE6 /* 'f' -> */,
|
||||
/* pos 010f: 141 */ 0xE9 /* 'i' -> */,
|
||||
/* pos 0110: 142 */ 0xE5 /* 'e' -> */,
|
||||
/* pos 0111: 143 */ 0xE4 /* 'd' -> */,
|
||||
/* pos 0112: 144 */ 0xAD /* '-' -> */,
|
||||
/* pos 0113: 145 */ 0xF3 /* 's' -> */,
|
||||
/* pos 0114: 146 */ 0xE9 /* 'i' -> */,
|
||||
/* pos 0115: 147 */ 0xEE /* 'n' -> */,
|
||||
/* pos 0116: 148 */ 0xE3 /* 'c' -> */,
|
||||
/* pos 0117: 149 */ 0xE5 /* 'e' -> */,
|
||||
/* pos 0118: 150 */ 0xBA /* ':' -> */,
|
||||
/* pos 0119: 151 */ 0x00, 0x13 /* - terminal marker 19 - */,
|
||||
/* pos 011b: 152 */ 0x65 /* 'e' */, 0x07, 0x00 /* (to 0x0122 state 153) */,
|
||||
0x6C /* 'l' */, 0x0E, 0x00 /* (to 0x012C state 162) */,
|
||||
0x08, /* fail */
|
||||
/* pos 0122: 153 */ 0xEE /* 'n' -> */,
|
||||
/* pos 0123: 154 */ 0xE3 /* 'c' -> */,
|
||||
/* pos 0124: 155 */ 0xEF /* 'o' -> */,
|
||||
/* pos 0125: 156 */ 0xE4 /* 'd' -> */,
|
||||
/* pos 0126: 157 */ 0xE9 /* 'i' -> */,
|
||||
/* pos 0127: 158 */ 0xEE /* 'n' -> */,
|
||||
/* pos 0128: 159 */ 0xE7 /* 'g' -> */,
|
||||
/* pos 0129: 160 */ 0xBA /* ':' -> */,
|
||||
/* pos 012a: 161 */ 0x00, 0x14 /* - terminal marker 20 - */,
|
||||
/* pos 012c: 162 */ 0xE1 /* 'a' -> */,
|
||||
/* pos 012d: 163 */ 0xEE /* 'n' -> */,
|
||||
/* pos 012e: 164 */ 0xE7 /* 'g' -> */,
|
||||
/* pos 012f: 165 */ 0xF5 /* 'u' -> */,
|
||||
/* pos 0130: 166 */ 0xE1 /* 'a' -> */,
|
||||
/* pos 0131: 167 */ 0xE7 /* 'g' -> */,
|
||||
/* pos 0132: 168 */ 0xE5 /* 'e' -> */,
|
||||
/* pos 0133: 169 */ 0xBA /* ':' -> */,
|
||||
/* pos 0134: 170 */ 0x00, 0x15 /* - terminal marker 21 - */,
|
||||
/* pos 0136: 171 */ 0xE1 /* 'a' -> */,
|
||||
/* pos 0137: 172 */ 0xE7 /* 'g' -> */,
|
||||
/* pos 0138: 173 */ 0xED /* 'm' -> */,
|
||||
/* pos 0139: 174 */ 0xE1 /* 'a' -> */,
|
||||
/* pos 013a: 175 */ 0xBA /* ':' -> */,
|
||||
/* pos 013b: 176 */ 0x00, 0x16 /* - terminal marker 22 - */,
|
||||
/* pos 013d: 177 */ 0xE3 /* 'c' -> */,
|
||||
/* pos 013e: 178 */ 0xE8 /* 'h' -> */,
|
||||
/* pos 013f: 179 */ 0xE5 /* 'e' -> */,
|
||||
/* pos 0140: 180 */ 0xAD /* '-' -> */,
|
||||
/* pos 0141: 181 */ 0xE3 /* 'c' -> */,
|
||||
/* pos 0142: 182 */ 0xEF /* 'o' -> */,
|
||||
/* pos 0143: 183 */ 0xEE /* 'n' -> */,
|
||||
/* pos 0144: 184 */ 0xF4 /* 't' -> */,
|
||||
/* pos 0145: 185 */ 0xF2 /* 'r' -> */,
|
||||
/* pos 0146: 186 */ 0xEF /* 'o' -> */,
|
||||
/* pos 0147: 187 */ 0xEC /* 'l' -> */,
|
||||
/* pos 0148: 188 */ 0xBA /* ':' -> */,
|
||||
/* pos 0149: 189 */ 0x00, 0x17 /* - terminal marker 23 - */,
|
||||
/* pos 014b: 190 */ 0xF4 /* 't' -> */,
|
||||
/* pos 014c: 191 */ 0xE8 /* 'h' -> */,
|
||||
/* pos 014d: 192 */ 0xEF /* 'o' -> */,
|
||||
/* pos 014e: 193 */ 0xF2 /* 'r' -> */,
|
||||
/* pos 014f: 194 */ 0xE9 /* 'i' -> */,
|
||||
/* pos 0150: 195 */ 0xFA /* 'z' -> */,
|
||||
/* pos 0151: 196 */ 0xE1 /* 'a' -> */,
|
||||
/* pos 0152: 197 */ 0xF4 /* 't' -> */,
|
||||
/* pos 0153: 198 */ 0xE9 /* 'i' -> */,
|
||||
/* pos 0154: 199 */ 0xEF /* 'o' -> */,
|
||||
/* pos 0155: 200 */ 0xEE /* 'n' -> */,
|
||||
/* pos 0156: 201 */ 0xBA /* ':' -> */,
|
||||
/* pos 0157: 202 */ 0x00, 0x18 /* - terminal marker 24 - */,
|
||||
/* pos 0159: 203 */ 0xEB /* 'k' -> */,
|
||||
/* pos 015a: 204 */ 0xE9 /* 'i' -> */,
|
||||
/* pos 015b: 205 */ 0xE5 /* 'e' -> */,
|
||||
/* pos 015c: 206 */ 0xBA /* ':' -> */,
|
||||
/* pos 015d: 207 */ 0x00, 0x19 /* - terminal marker 25 - */,
|
||||
/* pos 015f: 208 */ 0xE5 /* 'e' -> */,
|
||||
/* pos 0160: 209 */ 0xEE /* 'n' -> */,
|
||||
/* pos 0161: 210 */ 0xF4 /* 't' -> */,
|
||||
/* pos 0162: 211 */ 0xAD /* '-' -> */,
|
||||
/* pos 0163: 212 */ 0x6C /* 'l' */, 0x07, 0x00 /* (to 0x016A state 213) */,
|
||||
0x74 /* 't' */, 0x0C, 0x00 /* (to 0x0172 state 220) */,
|
||||
0x08, /* fail */
|
||||
/* pos 016a: 213 */ 0xE5 /* 'e' -> */,
|
||||
/* pos 016b: 214 */ 0xEE /* 'n' -> */,
|
||||
/* pos 016c: 215 */ 0xE7 /* 'g' -> */,
|
||||
/* pos 016d: 216 */ 0xF4 /* 't' -> */,
|
||||
/* pos 016e: 217 */ 0xE8 /* 'h' -> */,
|
||||
/* pos 016f: 218 */ 0xBA /* ':' -> */,
|
||||
/* pos 0170: 219 */ 0x00, 0x1A /* - terminal marker 26 - */,
|
||||
/* pos 0172: 220 */ 0xF9 /* 'y' -> */,
|
||||
/* pos 0173: 221 */ 0xF0 /* 'p' -> */,
|
||||
/* pos 0174: 222 */ 0xE5 /* 'e' -> */,
|
||||
/* pos 0175: 223 */ 0xBA /* ':' -> */,
|
||||
/* pos 0176: 224 */ 0x00, 0x1B /* - terminal marker 27 - */,
|
||||
/* pos 0178: 225 */ 0xE1 /* 'a' -> */,
|
||||
/* pos 0179: 226 */ 0xF4 /* 't' -> */,
|
||||
/* pos 017a: 227 */ 0xE5 /* 'e' -> */,
|
||||
/* pos 017b: 228 */ 0xBA /* ':' -> */,
|
||||
/* pos 017c: 229 */ 0x00, 0x1C /* - terminal marker 28 - */,
|
||||
/* pos 017e: 230 */ 0x61 /* 'a' */, 0x07, 0x00 /* (to 0x0185 state 231) */,
|
||||
0x65 /* 'e' */, 0x0A, 0x00 /* (to 0x018B state 236) */,
|
||||
0x08, /* fail */
|
||||
/* pos 0185: 231 */ 0xEE /* 'n' -> */,
|
||||
/* pos 0186: 232 */ 0xE7 /* 'g' -> */,
|
||||
/* pos 0187: 233 */ 0xE5 /* 'e' -> */,
|
||||
/* pos 0188: 234 */ 0xBA /* ':' -> */,
|
||||
/* pos 0189: 235 */ 0x00, 0x1D /* - terminal marker 29 - */,
|
||||
/* pos 018b: 236 */ 0xE6 /* 'f' -> */,
|
||||
/* pos 018c: 237 */ 0xE5 /* 'e' -> */,
|
||||
/* pos 018d: 238 */ 0xF2 /* 'r' -> */,
|
||||
/* pos 018e: 239 */ 0xE5 /* 'e' -> */,
|
||||
/* pos 018f: 240 */ 0xF2 /* 'r' -> */,
|
||||
/* pos 0190: 241 */ 0xBA /* ':' -> */,
|
||||
/* pos 0191: 242 */ 0x00, 0x1E /* - terminal marker 30 - */,
|
||||
/* total size 403 bytes */
|
||||
@@ -0,0 +1,766 @@
|
||||
/*
|
||||
* libwebsockets - small server side websockets and web server implementation
|
||||
*
|
||||
* Copyright (C) 2010-2014 Andy Green <[email protected]>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation:
|
||||
* version 2.1 of the License.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
||||
* MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
|
||||
#include "private-libwebsockets.h"
|
||||
|
||||
#if HOST_OS == OS_WINDOWS
|
||||
#pragma comment(lib, "Ws2_32.lib")
|
||||
#endif
|
||||
|
||||
int log_level = LLL_ERR | LLL_WARN | LLL_NOTICE;
|
||||
static void (*lwsl_emit)(int level, const char *line) = lwsl_emit_stderr;
|
||||
|
||||
static const char * const log_level_names[] = {
|
||||
"ERR",
|
||||
"WARN",
|
||||
"NOTICE",
|
||||
"INFO",
|
||||
"DEBUG",
|
||||
"PARSER",
|
||||
"HEADER",
|
||||
"EXTENSION",
|
||||
"CLIENT",
|
||||
"LATENCY",
|
||||
};
|
||||
|
||||
|
||||
void
|
||||
libwebsocket_close_and_free_session(struct libwebsocket_context *context,
|
||||
struct libwebsocket *wsi, enum lws_close_status reason)
|
||||
{
|
||||
int n, m, ret;
|
||||
int old_state;
|
||||
unsigned char buf[LWS_SEND_BUFFER_PRE_PADDING + 2 +
|
||||
LWS_SEND_BUFFER_POST_PADDING];
|
||||
struct lws_tokens eff_buf;
|
||||
|
||||
if (!wsi)
|
||||
return;
|
||||
|
||||
old_state = wsi->state;
|
||||
|
||||
switch (old_state) {
|
||||
case WSI_STATE_DEAD_SOCKET:
|
||||
return;
|
||||
|
||||
/* we tried the polite way... */
|
||||
case WSI_STATE_AWAITING_CLOSE_ACK:
|
||||
goto just_kill_connection;
|
||||
|
||||
case WSI_STATE_FLUSHING_STORED_SEND_BEFORE_CLOSE:
|
||||
if (wsi->truncated_send_len) {
|
||||
libwebsocket_callback_on_writable(context, wsi);
|
||||
return;
|
||||
}
|
||||
lwsl_info("wsi %p completed WSI_STATE_FLUSHING_STORED_SEND_BEFORE_CLOSE\n", wsi);
|
||||
goto just_kill_connection;
|
||||
default:
|
||||
if (wsi->truncated_send_len) {
|
||||
lwsl_info("wsi %p entering WSI_STATE_FLUSHING_STORED_SEND_BEFORE_CLOSE\n", wsi);
|
||||
wsi->state = WSI_STATE_FLUSHING_STORED_SEND_BEFORE_CLOSE;
|
||||
return;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
wsi->u.ws.close_reason = reason;
|
||||
|
||||
if (wsi->mode == LWS_CONNMODE_WS_CLIENT_WAITING_CONNECT ||
|
||||
wsi->mode == LWS_CONNMODE_WS_CLIENT_ISSUE_HANDSHAKE) {
|
||||
|
||||
context->protocols[0].callback(context, wsi,
|
||||
LWS_CALLBACK_CLIENT_CONNECTION_ERROR, NULL, NULL, 0);
|
||||
|
||||
free(wsi->u.hdr.ah);
|
||||
goto just_kill_connection;
|
||||
}
|
||||
|
||||
if (wsi->mode == LWS_CONNMODE_HTTP_SERVING_ACCEPTED) {
|
||||
if (wsi->u.http.post_buffer) {
|
||||
free(wsi->u.http.post_buffer);
|
||||
wsi->u.http.post_buffer = NULL;
|
||||
}
|
||||
if (wsi->u.http.fd != LWS_INVALID_FILE) {
|
||||
lwsl_debug("closing http file\n");
|
||||
compatible_file_close(wsi->u.http.fd);
|
||||
wsi->u.http.fd = LWS_INVALID_FILE;
|
||||
context->protocols[0].callback(context, wsi,
|
||||
LWS_CALLBACK_CLOSED_HTTP, wsi->user_space, NULL, 0);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* are his extensions okay with him closing? Eg he might be a mux
|
||||
* parent and just his ch1 aspect is closing?
|
||||
*/
|
||||
|
||||
if (lws_ext_callback_for_each_active(wsi,
|
||||
LWS_EXT_CALLBACK_CHECK_OK_TO_REALLY_CLOSE, NULL, 0) > 0) {
|
||||
lwsl_ext("extension vetoed close\n");
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* flush any tx pending from extensions, since we may send close packet
|
||||
* if there are problems with send, just nuke the connection
|
||||
*/
|
||||
|
||||
do {
|
||||
ret = 0;
|
||||
eff_buf.token = NULL;
|
||||
eff_buf.token_len = 0;
|
||||
|
||||
/* show every extension the new incoming data */
|
||||
|
||||
m = lws_ext_callback_for_each_active(wsi,
|
||||
LWS_EXT_CALLBACK_FLUSH_PENDING_TX, &eff_buf, 0);
|
||||
if (m < 0) {
|
||||
lwsl_ext("Extension reports fatal error\n");
|
||||
goto just_kill_connection;
|
||||
}
|
||||
if (m)
|
||||
/*
|
||||
* at least one extension told us he has more
|
||||
* to spill, so we will go around again after
|
||||
*/
|
||||
ret = 1;
|
||||
|
||||
/* assuming they left us something to send, send it */
|
||||
|
||||
if (eff_buf.token_len)
|
||||
if (lws_issue_raw(wsi, (unsigned char *)eff_buf.token,
|
||||
eff_buf.token_len) != eff_buf.token_len) {
|
||||
lwsl_debug("close: ext spill failed\n");
|
||||
goto just_kill_connection;
|
||||
}
|
||||
} while (ret);
|
||||
|
||||
/*
|
||||
* signal we are closing, libsocket_write will
|
||||
* add any necessary version-specific stuff. If the write fails,
|
||||
* no worries we are closing anyway. If we didn't initiate this
|
||||
* close, then our state has been changed to
|
||||
* WSI_STATE_RETURNED_CLOSE_ALREADY and we will skip this.
|
||||
*
|
||||
* Likewise if it's a second call to close this connection after we
|
||||
* sent the close indication to the peer already, we are in state
|
||||
* WSI_STATE_AWAITING_CLOSE_ACK and will skip doing this a second time.
|
||||
*/
|
||||
|
||||
if (old_state == WSI_STATE_ESTABLISHED &&
|
||||
reason != LWS_CLOSE_STATUS_NOSTATUS) {
|
||||
|
||||
lwsl_debug("sending close indication...\n");
|
||||
|
||||
/* make valgrind happy */
|
||||
memset(buf, 0, sizeof(buf));
|
||||
n = libwebsocket_write(wsi,
|
||||
&buf[LWS_SEND_BUFFER_PRE_PADDING + 2],
|
||||
0, LWS_WRITE_CLOSE);
|
||||
if (n >= 0) {
|
||||
/*
|
||||
* we have sent a nice protocol level indication we
|
||||
* now wish to close, we should not send anything more
|
||||
*/
|
||||
|
||||
wsi->state = WSI_STATE_AWAITING_CLOSE_ACK;
|
||||
|
||||
/*
|
||||
* ...and we should wait for a reply for a bit
|
||||
* out of politeness
|
||||
*/
|
||||
|
||||
libwebsocket_set_timeout(wsi,
|
||||
PENDING_TIMEOUT_CLOSE_ACK, 1);
|
||||
|
||||
lwsl_debug("sent close indication, awaiting ack\n");
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
lwsl_info("close: sending close packet failed, hanging up\n");
|
||||
|
||||
/* else, the send failed and we should just hang up */
|
||||
}
|
||||
|
||||
just_kill_connection:
|
||||
|
||||
lwsl_debug("close: just_kill_connection\n");
|
||||
|
||||
/*
|
||||
* we won't be servicing or receiving anything further from this guy
|
||||
* delete socket from the internal poll list if still present
|
||||
*/
|
||||
|
||||
remove_wsi_socket_from_fds(context, wsi);
|
||||
|
||||
wsi->state = WSI_STATE_DEAD_SOCKET;
|
||||
|
||||
if ((old_state == WSI_STATE_ESTABLISHED ||
|
||||
wsi->mode == LWS_CONNMODE_WS_SERVING ||
|
||||
wsi->mode == LWS_CONNMODE_WS_CLIENT)) {
|
||||
|
||||
if (wsi->u.ws.rx_user_buffer) {
|
||||
free(wsi->u.ws.rx_user_buffer);
|
||||
wsi->u.ws.rx_user_buffer = NULL;
|
||||
}
|
||||
if (wsi->u.ws.rxflow_buffer) {
|
||||
free(wsi->u.ws.rxflow_buffer);
|
||||
wsi->u.ws.rxflow_buffer = NULL;
|
||||
}
|
||||
if (wsi->truncated_send_malloc) {
|
||||
/* not going to be completed... nuke it */
|
||||
free(wsi->truncated_send_malloc);
|
||||
wsi->truncated_send_malloc = NULL;
|
||||
wsi->truncated_send_len = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* tell the user it's all over for this guy */
|
||||
|
||||
if (wsi->protocol && wsi->protocol->callback &&
|
||||
((old_state == WSI_STATE_ESTABLISHED) ||
|
||||
(old_state == WSI_STATE_RETURNED_CLOSE_ALREADY) ||
|
||||
(old_state == WSI_STATE_AWAITING_CLOSE_ACK))) {
|
||||
lwsl_debug("calling back CLOSED\n");
|
||||
wsi->protocol->callback(context, wsi, LWS_CALLBACK_CLOSED,
|
||||
wsi->user_space, NULL, 0);
|
||||
} else if (wsi->mode == LWS_CONNMODE_HTTP_SERVING_ACCEPTED) {
|
||||
lwsl_debug("calling back CLOSED_HTTP\n");
|
||||
context->protocols[0].callback(context, wsi,
|
||||
LWS_CALLBACK_CLOSED_HTTP, wsi->user_space, NULL, 0 );
|
||||
} else
|
||||
lwsl_debug("not calling back closed\n");
|
||||
|
||||
/* deallocate any active extension contexts */
|
||||
|
||||
if (lws_ext_callback_for_each_active(wsi, LWS_EXT_CALLBACK_DESTROY, NULL, 0) < 0)
|
||||
lwsl_warn("extension destruction failed\n");
|
||||
#ifndef LWS_NO_EXTENSIONS
|
||||
for (n = 0; n < wsi->count_active_extensions; n++)
|
||||
free(wsi->active_extensions_user[n]);
|
||||
#endif
|
||||
/*
|
||||
* inform all extensions in case they tracked this guy out of band
|
||||
* even though not active on him specifically
|
||||
*/
|
||||
if (lws_ext_callback_for_each_extension_type(context, wsi,
|
||||
LWS_EXT_CALLBACK_DESTROY_ANY_WSI_CLOSING, NULL, 0) < 0)
|
||||
lwsl_warn("ext destroy wsi failed\n");
|
||||
|
||||
/* lwsl_info("closing fd=%d\n", wsi->sock); */
|
||||
|
||||
if (!lws_ssl_close(wsi) && wsi->sock >= 0) {
|
||||
n = shutdown(wsi->sock, SHUT_RDWR);
|
||||
if (n)
|
||||
lwsl_debug("closing: shutdown ret %d\n", LWS_ERRNO);
|
||||
|
||||
n = compatible_close(wsi->sock);
|
||||
if (n)
|
||||
lwsl_debug("closing: close ret %d\n", LWS_ERRNO);
|
||||
}
|
||||
|
||||
/* outermost destroy notification for wsi (user_space still intact) */
|
||||
context->protocols[0].callback(context, wsi,
|
||||
LWS_CALLBACK_WSI_DESTROY, wsi->user_space, NULL, 0);
|
||||
|
||||
if (wsi->protocol && wsi->protocol->per_session_data_size &&
|
||||
wsi->user_space) /* user code may own */
|
||||
free(wsi->user_space);
|
||||
|
||||
free(wsi);
|
||||
}
|
||||
|
||||
/**
|
||||
* libwebsockets_get_peer_addresses() - Get client address information
|
||||
* @context: Libwebsockets context
|
||||
* @wsi: Local struct libwebsocket associated with
|
||||
* @fd: Connection socket descriptor
|
||||
* @name: Buffer to take client address name
|
||||
* @name_len: Length of client address name buffer
|
||||
* @rip: Buffer to take client address IP qotted quad
|
||||
* @rip_len: Length of client address IP buffer
|
||||
*
|
||||
* This function fills in @name and @rip with the name and IP of
|
||||
* the client connected with socket descriptor @fd. Names may be
|
||||
* truncated if there is not enough room. If either cannot be
|
||||
* determined, they will be returned as valid zero-length strings.
|
||||
*/
|
||||
|
||||
LWS_VISIBLE void
|
||||
libwebsockets_get_peer_addresses(struct libwebsocket_context *context,
|
||||
struct libwebsocket *wsi, int fd, char *name, int name_len,
|
||||
char *rip, int rip_len)
|
||||
{
|
||||
socklen_t len;
|
||||
#ifdef LWS_USE_IPV6
|
||||
struct sockaddr_in6 sin6;
|
||||
#endif
|
||||
struct sockaddr_in sin4;
|
||||
struct hostent *host;
|
||||
struct hostent *host1;
|
||||
char ip[128];
|
||||
unsigned char *p;
|
||||
int n;
|
||||
#ifdef AF_LOCAL
|
||||
struct sockaddr_un *un;
|
||||
#endif
|
||||
int ret = -1;
|
||||
|
||||
rip[0] = '\0';
|
||||
name[0] = '\0';
|
||||
|
||||
lws_latency_pre(context, wsi);
|
||||
|
||||
#ifdef LWS_USE_IPV6
|
||||
if (LWS_IPV6_ENABLED(context)) {
|
||||
|
||||
len = sizeof(sin6);
|
||||
if (getpeername(fd, (struct sockaddr *) &sin6, &len) < 0) {
|
||||
lwsl_warn("getpeername: %s\n", strerror(LWS_ERRNO));
|
||||
goto bail;
|
||||
}
|
||||
|
||||
if (!lws_plat_inet_ntop(AF_INET6, &sin6.sin6_addr, rip, rip_len)) {
|
||||
lwsl_err("inet_ntop", strerror(LWS_ERRNO));
|
||||
goto bail;
|
||||
}
|
||||
|
||||
// Strip off the IPv4 to IPv6 header if one exists
|
||||
if (strncmp(rip, "::ffff:", 7) == 0)
|
||||
memmove(rip, rip + 7, strlen(rip) - 6);
|
||||
|
||||
getnameinfo((struct sockaddr *)&sin6,
|
||||
sizeof(struct sockaddr_in6), name,
|
||||
name_len, NULL, 0, 0);
|
||||
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
len = sizeof(sin4);
|
||||
if (getpeername(fd, (struct sockaddr *) &sin4, &len) < 0) {
|
||||
lwsl_warn("getpeername: %s\n", strerror(LWS_ERRNO));
|
||||
goto bail;
|
||||
}
|
||||
host = gethostbyaddr((char *) &sin4.sin_addr,
|
||||
sizeof(sin4.sin_addr), AF_INET);
|
||||
if (host == NULL) {
|
||||
lwsl_warn("gethostbyaddr: %s\n", strerror(LWS_ERRNO));
|
||||
goto bail;
|
||||
}
|
||||
|
||||
strncpy(name, host->h_name, name_len);
|
||||
name[name_len - 1] = '\0';
|
||||
|
||||
host1 = gethostbyname(host->h_name);
|
||||
if (host1 == NULL)
|
||||
goto bail;
|
||||
p = (unsigned char *)host1;
|
||||
n = 0;
|
||||
while (p != NULL) {
|
||||
p = (unsigned char *)host1->h_addr_list[n++];
|
||||
if (p == NULL)
|
||||
continue;
|
||||
if ((host1->h_addrtype != AF_INET)
|
||||
#ifdef AF_LOCAL
|
||||
&& (host1->h_addrtype != AF_LOCAL)
|
||||
#endif
|
||||
)
|
||||
continue;
|
||||
|
||||
if (host1->h_addrtype == AF_INET)
|
||||
sprintf(ip, "%u.%u.%u.%u",
|
||||
p[0], p[1], p[2], p[3]);
|
||||
#ifdef AF_LOCAL
|
||||
else {
|
||||
un = (struct sockaddr_un *)p;
|
||||
strncpy(ip, un->sun_path, sizeof(ip) - 1);
|
||||
ip[sizeof(ip) - 1] = '\0';
|
||||
}
|
||||
#endif
|
||||
p = NULL;
|
||||
strncpy(rip, ip, rip_len);
|
||||
rip[rip_len - 1] = '\0';
|
||||
}
|
||||
}
|
||||
|
||||
ret = 0;
|
||||
bail:
|
||||
lws_latency(context, wsi, "libwebsockets_get_peer_addresses", ret, 1);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* libwebsocket_context_user() - get the user data associated with the context
|
||||
* @context: Websocket context
|
||||
*
|
||||
* This returns the optional user allocation that can be attached to
|
||||
* the context the sockets live in at context_create time. It's a way
|
||||
* to let all sockets serviced in the same context share data without
|
||||
* using globals statics in the user code.
|
||||
*/
|
||||
LWS_EXTERN void *
|
||||
libwebsocket_context_user(struct libwebsocket_context *context)
|
||||
{
|
||||
return context->user_space;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* libwebsocket_callback_all_protocol() - Callback all connections using
|
||||
* the given protocol with the given reason
|
||||
*
|
||||
* @protocol: Protocol whose connections will get callbacks
|
||||
* @reason: Callback reason index
|
||||
*/
|
||||
|
||||
LWS_VISIBLE int
|
||||
libwebsocket_callback_all_protocol(
|
||||
const struct libwebsocket_protocols *protocol, int reason)
|
||||
{
|
||||
struct libwebsocket_context *context = protocol->owning_server;
|
||||
int n;
|
||||
struct libwebsocket *wsi;
|
||||
|
||||
for (n = 0; n < context->fds_count; n++) {
|
||||
wsi = context->lws_lookup[context->fds[n].fd];
|
||||
if (!wsi)
|
||||
continue;
|
||||
if (wsi->protocol == protocol)
|
||||
protocol->callback(context, wsi,
|
||||
reason, wsi->user_space, NULL, 0);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* libwebsocket_set_timeout() - marks the wsi as subject to a timeout
|
||||
*
|
||||
* You will not need this unless you are doing something special
|
||||
*
|
||||
* @wsi: Websocket connection instance
|
||||
* @reason: timeout reason
|
||||
* @secs: how many seconds
|
||||
*/
|
||||
|
||||
LWS_VISIBLE void
|
||||
libwebsocket_set_timeout(struct libwebsocket *wsi,
|
||||
enum pending_timeout reason, int secs)
|
||||
{
|
||||
time_t now;
|
||||
|
||||
time(&now);
|
||||
|
||||
wsi->pending_timeout_limit = now + secs;
|
||||
wsi->pending_timeout = reason;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* libwebsocket_get_socket_fd() - returns the socket file descriptor
|
||||
*
|
||||
* You will not need this unless you are doing something special
|
||||
*
|
||||
* @wsi: Websocket connection instance
|
||||
*/
|
||||
|
||||
LWS_VISIBLE int
|
||||
libwebsocket_get_socket_fd(struct libwebsocket *wsi)
|
||||
{
|
||||
return wsi->sock;
|
||||
}
|
||||
|
||||
#ifdef LWS_LATENCY
|
||||
void
|
||||
lws_latency(struct libwebsocket_context *context, struct libwebsocket *wsi,
|
||||
const char *action, int ret, int completed)
|
||||
{
|
||||
unsigned long long u;
|
||||
char buf[256];
|
||||
|
||||
u = time_in_microseconds();
|
||||
|
||||
if (!action) {
|
||||
wsi->latency_start = u;
|
||||
if (!wsi->action_start)
|
||||
wsi->action_start = u;
|
||||
return;
|
||||
}
|
||||
if (completed) {
|
||||
if (wsi->action_start == wsi->latency_start)
|
||||
sprintf(buf,
|
||||
"Completion first try lat %luus: %p: ret %d: %s\n",
|
||||
u - wsi->latency_start,
|
||||
(void *)wsi, ret, action);
|
||||
else
|
||||
sprintf(buf,
|
||||
"Completion %luus: lat %luus: %p: ret %d: %s\n",
|
||||
u - wsi->action_start,
|
||||
u - wsi->latency_start,
|
||||
(void *)wsi, ret, action);
|
||||
wsi->action_start = 0;
|
||||
} else
|
||||
sprintf(buf, "lat %luus: %p: ret %d: %s\n",
|
||||
u - wsi->latency_start, (void *)wsi, ret, action);
|
||||
|
||||
if (u - wsi->latency_start > context->worst_latency) {
|
||||
context->worst_latency = u - wsi->latency_start;
|
||||
strcpy(context->worst_latency_info, buf);
|
||||
}
|
||||
lwsl_latency("%s", buf);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* libwebsocket_rx_flow_control() - Enable and disable socket servicing for
|
||||
* receieved packets.
|
||||
*
|
||||
* If the output side of a server process becomes choked, this allows flow
|
||||
* control for the input side.
|
||||
*
|
||||
* @wsi: Websocket connection instance to get callback for
|
||||
* @enable: 0 = disable read servicing for this connection, 1 = enable
|
||||
*/
|
||||
|
||||
LWS_VISIBLE int
|
||||
libwebsocket_rx_flow_control(struct libwebsocket *wsi, int enable)
|
||||
{
|
||||
if (enable == (wsi->u.ws.rxflow_change_to & LWS_RXFLOW_ALLOW))
|
||||
return 0;
|
||||
|
||||
lwsl_info("libwebsocket_rx_flow_control(0x%p, %d)\n", wsi, enable);
|
||||
wsi->u.ws.rxflow_change_to = LWS_RXFLOW_PENDING_CHANGE | !!enable;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* libwebsocket_rx_flow_allow_all_protocol() - Allow all connections with this protocol to receive
|
||||
*
|
||||
* When the user server code realizes it can accept more input, it can
|
||||
* call this to have the RX flow restriction removed from all connections using
|
||||
* the given protocol.
|
||||
*
|
||||
* @protocol: all connections using this protocol will be allowed to receive
|
||||
*/
|
||||
|
||||
LWS_VISIBLE void
|
||||
libwebsocket_rx_flow_allow_all_protocol(
|
||||
const struct libwebsocket_protocols *protocol)
|
||||
{
|
||||
struct libwebsocket_context *context = protocol->owning_server;
|
||||
int n;
|
||||
struct libwebsocket *wsi;
|
||||
|
||||
for (n = 0; n < context->fds_count; n++) {
|
||||
wsi = context->lws_lookup[context->fds[n].fd];
|
||||
if (!wsi)
|
||||
continue;
|
||||
if (wsi->protocol == protocol)
|
||||
libwebsocket_rx_flow_control(wsi, LWS_RXFLOW_ALLOW);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* libwebsocket_canonical_hostname() - returns this host's hostname
|
||||
*
|
||||
* This is typically used by client code to fill in the host parameter
|
||||
* when making a client connection. You can only call it after the context
|
||||
* has been created.
|
||||
*
|
||||
* @context: Websocket context
|
||||
*/
|
||||
LWS_VISIBLE extern const char *
|
||||
libwebsocket_canonical_hostname(struct libwebsocket_context *context)
|
||||
{
|
||||
return (const char *)context->canonical_hostname;
|
||||
}
|
||||
|
||||
int user_callback_handle_rxflow(callback_function callback_function,
|
||||
struct libwebsocket_context *context,
|
||||
struct libwebsocket *wsi,
|
||||
enum libwebsocket_callback_reasons reason, void *user,
|
||||
void *in, size_t len)
|
||||
{
|
||||
int n;
|
||||
|
||||
n = callback_function(context, wsi, reason, user, in, len);
|
||||
if (!n)
|
||||
n = _libwebsocket_rx_flow_control(wsi);
|
||||
|
||||
return n;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* libwebsocket_set_proxy() - Setups proxy to libwebsocket_context.
|
||||
* @context: pointer to struct libwebsocket_context you want set proxy to
|
||||
* @proxy: pointer to c string containing proxy in format address:port
|
||||
*
|
||||
* Returns 0 if proxy string was parsed and proxy was setup.
|
||||
* Returns -1 if @proxy is NULL or has incorrect format.
|
||||
*
|
||||
* This is only required if your OS does not provide the http_proxy
|
||||
* enviroment variable (eg, OSX)
|
||||
*
|
||||
* IMPORTANT! You should call this function right after creation of the
|
||||
* libwebsocket_context and before call to connect. If you call this
|
||||
* function after connect behavior is undefined.
|
||||
* This function will override proxy settings made on libwebsocket_context
|
||||
* creation with genenv() call.
|
||||
*/
|
||||
|
||||
LWS_VISIBLE int
|
||||
libwebsocket_set_proxy(struct libwebsocket_context *context, const char *proxy)
|
||||
{
|
||||
char *p;
|
||||
|
||||
if (!proxy)
|
||||
return -1;
|
||||
|
||||
strncpy(context->http_proxy_address, proxy,
|
||||
sizeof(context->http_proxy_address) - 1);
|
||||
context->http_proxy_address[
|
||||
sizeof(context->http_proxy_address) - 1] = '\0';
|
||||
|
||||
p = strchr(context->http_proxy_address, ':');
|
||||
if (!p) {
|
||||
lwsl_err("http_proxy needs to be ads:port\n");
|
||||
|
||||
return -1;
|
||||
}
|
||||
*p = '\0';
|
||||
context->http_proxy_port = atoi(p + 1);
|
||||
|
||||
lwsl_notice(" Proxy %s:%u\n", context->http_proxy_address,
|
||||
context->http_proxy_port);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* libwebsockets_get_protocol() - Returns a protocol pointer from a websocket
|
||||
* connection.
|
||||
* @wsi: pointer to struct websocket you want to know the protocol of
|
||||
*
|
||||
*
|
||||
* Some apis can act on all live connections of a given protocol,
|
||||
* this is how you can get a pointer to the active protocol if needed.
|
||||
*/
|
||||
|
||||
LWS_VISIBLE const struct libwebsocket_protocols *
|
||||
libwebsockets_get_protocol(struct libwebsocket *wsi)
|
||||
{
|
||||
return wsi->protocol;
|
||||
}
|
||||
|
||||
LWS_VISIBLE int
|
||||
libwebsocket_is_final_fragment(struct libwebsocket *wsi)
|
||||
{
|
||||
return wsi->u.ws.final;
|
||||
}
|
||||
|
||||
LWS_VISIBLE unsigned char
|
||||
libwebsocket_get_reserved_bits(struct libwebsocket *wsi)
|
||||
{
|
||||
return wsi->u.ws.rsv;
|
||||
}
|
||||
|
||||
int
|
||||
libwebsocket_ensure_user_space(struct libwebsocket *wsi)
|
||||
{
|
||||
if (!wsi->protocol)
|
||||
return 1;
|
||||
|
||||
/* allocate the per-connection user memory (if any) */
|
||||
|
||||
if (wsi->protocol->per_session_data_size && !wsi->user_space) {
|
||||
wsi->user_space = malloc(
|
||||
wsi->protocol->per_session_data_size);
|
||||
if (wsi->user_space == NULL) {
|
||||
lwsl_err("Out of memory for conn user space\n");
|
||||
return 1;
|
||||
}
|
||||
memset(wsi->user_space, 0,
|
||||
wsi->protocol->per_session_data_size);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
LWS_VISIBLE void lwsl_emit_stderr(int level, const char *line)
|
||||
{
|
||||
char buf[300];
|
||||
unsigned long long now;
|
||||
int n;
|
||||
|
||||
buf[0] = '\0';
|
||||
for (n = 0; n < LLL_COUNT; n++)
|
||||
if (level == (1 << n)) {
|
||||
now = time_in_microseconds() / 100;
|
||||
sprintf(buf, "[%lu:%04d] %s: ", (unsigned long) now / 10000,
|
||||
(int)(now % 10000), log_level_names[n]);
|
||||
break;
|
||||
}
|
||||
|
||||
fprintf(stderr, "%s%s", buf, line);
|
||||
}
|
||||
|
||||
|
||||
LWS_VISIBLE void _lws_log(int filter, const char *format, ...)
|
||||
{
|
||||
char buf[256];
|
||||
va_list ap;
|
||||
|
||||
if (!(log_level & filter))
|
||||
return;
|
||||
|
||||
va_start(ap, format);
|
||||
vsnprintf(buf, sizeof(buf), format, ap);
|
||||
buf[sizeof(buf) - 1] = '\0';
|
||||
va_end(ap);
|
||||
|
||||
lwsl_emit(filter, buf);
|
||||
}
|
||||
|
||||
/**
|
||||
* lws_set_log_level() - Set the logging bitfield
|
||||
* @level: OR together the LLL_ debug contexts you want output from
|
||||
* @log_emit_function: NULL to leave it as it is, or a user-supplied
|
||||
* function to perform log string emission instead of
|
||||
* the default stderr one.
|
||||
*
|
||||
* log level defaults to "err", "warn" and "notice" contexts enabled and
|
||||
* emission on stderr.
|
||||
*/
|
||||
|
||||
LWS_VISIBLE void lws_set_log_level(int level, void (*log_emit_function)(int level,
|
||||
const char *line))
|
||||
{
|
||||
log_level = level;
|
||||
if (log_emit_function)
|
||||
lwsl_emit = log_emit_function;
|
||||
}
|
||||
File diff suppressed because it is too large.
Load diff
@@ -0,0 +1,396 @@
|
||||
#include "private-libwebsockets.h"
|
||||
|
||||
#include "build.h"
|
||||
|
||||
#if HOST_OS != OS_WINDOWS
|
||||
/*
|
||||
* included from libwebsockets.c for unix builds
|
||||
*/
|
||||
|
||||
unsigned long long time_in_microseconds(void)
|
||||
{
|
||||
struct timeval tv;
|
||||
gettimeofday(&tv, NULL);
|
||||
return (tv.tv_sec * 1000000) + tv.tv_usec;
|
||||
}
|
||||
|
||||
LWS_VISIBLE int libwebsockets_get_random(struct libwebsocket_context *context,
|
||||
void *buf, int len)
|
||||
{
|
||||
return read(context->fd_random, (char *)buf, len);
|
||||
}
|
||||
|
||||
LWS_VISIBLE int lws_send_pipe_choked(struct libwebsocket *wsi)
|
||||
{
|
||||
struct libwebsocket_pollfd fds;
|
||||
|
||||
/* treat the fact we got a truncated send pending as if we're choked */
|
||||
if (wsi->truncated_send_len)
|
||||
return 1;
|
||||
|
||||
fds.fd = wsi->sock;
|
||||
fds.events = POLLOUT;
|
||||
fds.revents = 0;
|
||||
|
||||
if (poll(&fds, 1, 0) != 1)
|
||||
return 1;
|
||||
|
||||
if ((fds.revents & POLLOUT) == 0)
|
||||
return 1;
|
||||
|
||||
/* okay to send another packet without blocking */
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
LWS_VISIBLE int
|
||||
lws_poll_listen_fd(struct libwebsocket_pollfd *fd)
|
||||
{
|
||||
return poll(fd, 1, 0);
|
||||
}
|
||||
|
||||
/*
|
||||
* This is just used to interrupt poll waiting
|
||||
* we don't have to do anything with it.
|
||||
*/
|
||||
static void lws_sigusr2(int sig)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* libwebsocket_cancel_service() - Cancel servicing of pending websocket activity
|
||||
* @context: Websocket context
|
||||
*
|
||||
* This function let a call to libwebsocket_service() waiting for a timeout
|
||||
* immediately return.
|
||||
*/
|
||||
LWS_VISIBLE void
|
||||
libwebsocket_cancel_service(struct libwebsocket_context *context)
|
||||
{
|
||||
char buf = 0;
|
||||
|
||||
if (write(context->dummy_pipe_fds[1], &buf, sizeof(buf)) != 1)
|
||||
lwsl_err("Cannot write to dummy pipe");
|
||||
}
|
||||
|
||||
LWS_VISIBLE void lwsl_emit_syslog(int level, const char *line)
|
||||
{
|
||||
/*
|
||||
int syslog_level = LOG_DEBUG;
|
||||
|
||||
switch (level) {
|
||||
case LLL_ERR:
|
||||
syslog_level = LOG_ERR;
|
||||
break;
|
||||
case LLL_WARN:
|
||||
syslog_level = LOG_WARNING;
|
||||
break;
|
||||
case LLL_NOTICE:
|
||||
syslog_level = LOG_NOTICE;
|
||||
break;
|
||||
case LLL_INFO:
|
||||
syslog_level = LOG_INFO;
|
||||
break;
|
||||
}
|
||||
*/
|
||||
printf("%s", line);
|
||||
}
|
||||
|
||||
LWS_VISIBLE int
|
||||
lws_plat_service(struct libwebsocket_context *context, int timeout_ms)
|
||||
{
|
||||
int n;
|
||||
int m;
|
||||
char buf;
|
||||
|
||||
/* stay dead once we are dead */
|
||||
|
||||
if (!context)
|
||||
return 1;
|
||||
|
||||
lws_libev_run(context);
|
||||
|
||||
context->service_tid = context->protocols[0].callback(context, NULL,
|
||||
LWS_CALLBACK_GET_THREAD_ID, NULL, NULL, 0);
|
||||
|
||||
n = poll(context->fds, context->fds_count, timeout_ms);
|
||||
context->service_tid = 0;
|
||||
|
||||
if (n == 0) /* poll timeout */ {
|
||||
libwebsocket_service_fd(context, NULL);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (n < 0) {
|
||||
if (LWS_ERRNO != LWS_EINTR)
|
||||
return -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* any socket with events to service? */
|
||||
|
||||
for (n = 0; n < context->fds_count; n++) {
|
||||
if (!context->fds[n].revents)
|
||||
continue;
|
||||
|
||||
if (context->fds[n].fd == context->dummy_pipe_fds[0]) {
|
||||
if (read(context->fds[n].fd, &buf, 1) != 1)
|
||||
lwsl_err("Cannot read from dummy pipe.");
|
||||
continue;
|
||||
}
|
||||
|
||||
m = libwebsocket_service_fd(context, &context->fds[n]);
|
||||
if (m < 0)
|
||||
return -1;
|
||||
/* if something closed, retry this slot */
|
||||
if (m)
|
||||
n--;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
LWS_VISIBLE int
|
||||
lws_plat_set_socket_options(struct libwebsocket_context *context, int fd)
|
||||
{
|
||||
int optval = 1;
|
||||
socklen_t optlen = sizeof(optval);
|
||||
|
||||
#if defined(__APPLE__) || defined(__FreeBSD__) || defined(__NetBSD__)
|
||||
struct protoent *tcp_proto;
|
||||
#endif
|
||||
|
||||
if (context->ka_time) {
|
||||
/* enable keepalive on this socket */
|
||||
optval = 1;
|
||||
if (setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE,
|
||||
(const void *)&optval, optlen) < 0)
|
||||
return 1;
|
||||
|
||||
#if defined(__APPLE__) || defined(__FreeBSD__) || defined(__NetBSD__) || defined(__CYGWIN__)
|
||||
|
||||
/*
|
||||
* didn't find a way to set these per-socket, need to
|
||||
* tune kernel systemwide values
|
||||
*/
|
||||
#else
|
||||
/* set the keepalive conditions we want on it too */
|
||||
optval = context->ka_time;
|
||||
if (setsockopt(fd, IPPROTO_IP, TCP_KEEPIDLE,
|
||||
(const void *)&optval, optlen) < 0)
|
||||
return 1;
|
||||
|
||||
optval = context->ka_interval;
|
||||
if (setsockopt(fd, IPPROTO_IP, TCP_KEEPINTVL,
|
||||
(const void *)&optval, optlen) < 0)
|
||||
return 1;
|
||||
|
||||
optval = context->ka_probes;
|
||||
if (setsockopt(fd, IPPROTO_IP, TCP_KEEPCNT,
|
||||
(const void *)&optval, optlen) < 0)
|
||||
return 1;
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Disable Nagle */
|
||||
optval = 1;
|
||||
#if !defined(__APPLE__) && !defined(__FreeBSD__) && !defined(__NetBSD__)
|
||||
setsockopt(fd, SOL_TCP, TCP_NODELAY, (const void *)&optval, optlen);
|
||||
#else
|
||||
tcp_proto = getprotobyname("TCP");
|
||||
setsockopt(fd, tcp_proto->p_proto, TCP_NODELAY, &optval, optlen);
|
||||
#endif
|
||||
|
||||
/* We are nonblocking... */
|
||||
fcntl(fd, F_SETFL, O_NONBLOCK);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
LWS_VISIBLE void
|
||||
lws_plat_drop_app_privileges(struct lws_context_creation_info *info)
|
||||
{
|
||||
if (info->gid != -1)
|
||||
if (setgid(info->gid))
|
||||
lwsl_warn("setgid: %s\n", strerror(LWS_ERRNO));
|
||||
if (info->uid != -1)
|
||||
if (setuid(info->uid))
|
||||
lwsl_warn("setuid: %s\n", strerror(LWS_ERRNO));
|
||||
}
|
||||
|
||||
LWS_VISIBLE int
|
||||
lws_plat_init_fd_tables(struct libwebsocket_context *context)
|
||||
{
|
||||
if (lws_libev_init_fd_table(context))
|
||||
/* libev handled it instead */
|
||||
return 0;
|
||||
|
||||
if (pipe(context->dummy_pipe_fds)) {
|
||||
lwsl_err("Unable to create pipe\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* use the read end of pipe as first item */
|
||||
context->fds[0].fd = context->dummy_pipe_fds[0];
|
||||
context->fds[0].events = LWS_POLLIN;
|
||||
context->fds[0].revents = 0;
|
||||
context->fds_count = 1;
|
||||
|
||||
context->fd_random = open(SYSTEM_RANDOM_FILEPATH, O_RDONLY);
|
||||
if (context->fd_random < 0) {
|
||||
lwsl_err("Unable to open random device %s %d\n",
|
||||
SYSTEM_RANDOM_FILEPATH, context->fd_random);
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void sigpipe_handler(int x)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
LWS_VISIBLE int
|
||||
lws_plat_context_early_init(void)
|
||||
{
|
||||
sigset_t mask;
|
||||
|
||||
signal(SIGUSR2, lws_sigusr2);
|
||||
sigemptyset(&mask);
|
||||
sigaddset(&mask, SIGUSR2);
|
||||
|
||||
sigprocmask(SIG_BLOCK, &mask, NULL);
|
||||
|
||||
signal(SIGPIPE, sigpipe_handler);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
LWS_VISIBLE void
|
||||
lws_plat_context_early_destroy(struct libwebsocket_context *context)
|
||||
{
|
||||
}
|
||||
|
||||
LWS_VISIBLE void
|
||||
lws_plat_context_late_destroy(struct libwebsocket_context *context)
|
||||
{
|
||||
close(context->dummy_pipe_fds[0]);
|
||||
close(context->dummy_pipe_fds[1]);
|
||||
close(context->fd_random);
|
||||
}
|
||||
|
||||
/* cast a struct sockaddr_in6 * into addr for ipv6 */
|
||||
|
||||
LWS_VISIBLE int
|
||||
interface_to_sa(struct libwebsocket_context *context,
|
||||
const char *ifname, struct sockaddr_in *addr, size_t addrlen)
|
||||
{
|
||||
int rc = -1;
|
||||
|
||||
struct ifaddrs *ifr;
|
||||
struct ifaddrs *ifc;
|
||||
#ifdef LWS_USE_IPV6
|
||||
struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *)addr;
|
||||
#endif
|
||||
|
||||
getifaddrs(&ifr);
|
||||
for (ifc = ifr; ifc != NULL && rc; ifc = ifc->ifa_next) {
|
||||
if (!ifc->ifa_addr)
|
||||
continue;
|
||||
|
||||
lwsl_info(" interface %s vs %s\n", ifc->ifa_name, ifname);
|
||||
|
||||
if (strcmp(ifc->ifa_name, ifname))
|
||||
continue;
|
||||
|
||||
switch (ifc->ifa_addr->sa_family) {
|
||||
case AF_INET:
|
||||
#ifdef LWS_USE_IPV6
|
||||
if (LWS_IPV6_ENABLED(context)) {
|
||||
/* map IPv4 to IPv6 */
|
||||
bzero((char *)&addr6->sin6_addr,
|
||||
sizeof(struct in6_addr));
|
||||
addr6->sin6_addr.s6_addr[10] = 0xff;
|
||||
addr6->sin6_addr.s6_addr[11] = 0xff;
|
||||
memcpy(&addr6->sin6_addr.s6_addr[12],
|
||||
&((struct sockaddr_in *)ifc->ifa_addr)->sin_addr,
|
||||
sizeof(struct in_addr));
|
||||
} else
|
||||
#endif
|
||||
memcpy(addr,
|
||||
(struct sockaddr_in *)ifc->ifa_addr,
|
||||
sizeof(struct sockaddr_in));
|
||||
break;
|
||||
#ifdef LWS_USE_IPV6
|
||||
case AF_INET6:
|
||||
if (rc >= 0)
|
||||
break;
|
||||
memcpy(&addr6->sin6_addr,
|
||||
&((struct sockaddr_in6 *)ifc->ifa_addr)->sin6_addr,
|
||||
sizeof(struct in6_addr));
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
continue;
|
||||
}
|
||||
rc = 0;
|
||||
}
|
||||
|
||||
freeifaddrs(ifr);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
LWS_VISIBLE void
|
||||
lws_plat_insert_socket_into_fds(struct libwebsocket_context *context,
|
||||
struct libwebsocket *wsi)
|
||||
{
|
||||
lws_libev_io(context, wsi, LWS_EV_START | LWS_EV_READ);
|
||||
context->fds[context->fds_count++].revents = 0;
|
||||
}
|
||||
|
||||
LWS_VISIBLE void
|
||||
lws_plat_delete_socket_from_fds(struct libwebsocket_context *context,
|
||||
struct libwebsocket *wsi, int m)
|
||||
{
|
||||
}
|
||||
|
||||
LWS_VISIBLE void
|
||||
lws_plat_service_periodic(struct libwebsocket_context *context)
|
||||
{
|
||||
/* if our parent went down, don't linger around */
|
||||
if (context->started_with_parent &&
|
||||
kill(context->started_with_parent, 0) < 0)
|
||||
kill(getpid(), SIGTERM);
|
||||
}
|
||||
|
||||
LWS_VISIBLE int
|
||||
lws_plat_change_pollfd(struct libwebsocket_context *context,
|
||||
struct libwebsocket *wsi, struct libwebsocket_pollfd *pfd)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
LWS_VISIBLE int
|
||||
lws_plat_open_file(const char* filename, unsigned long* filelen)
|
||||
{
|
||||
struct stat stat_buf;
|
||||
int ret = open(filename, O_RDONLY);
|
||||
|
||||
if (ret < 0)
|
||||
return LWS_INVALID_FILE;
|
||||
|
||||
fstat(ret, &stat_buf);
|
||||
*filelen = stat_buf.st_size;
|
||||
return ret;
|
||||
}
|
||||
|
||||
#ifdef LWS_USE_IPV6
|
||||
LWS_VISIBLE const char *
|
||||
lws_plat_inet_ntop(int af, const void *src, char *dst, int cnt)
|
||||
{
|
||||
return inet_ntop(af, src, dst, cnt);
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
@@ -0,0 +1,365 @@
|
||||
#include "private-libwebsockets.h"
|
||||
|
||||
|
||||
#include "build.h"
|
||||
|
||||
#if HOST_OS == OS_WINDOWS
|
||||
|
||||
unsigned long long
|
||||
time_in_microseconds()
|
||||
{
|
||||
#define DELTA_EPOCH_IN_MICROSECS 11644473600000000ULL
|
||||
FILETIME filetime;
|
||||
ULARGE_INTEGER datetime;
|
||||
|
||||
#ifdef _WIN32_WCE
|
||||
GetCurrentFT(&filetime);
|
||||
#else
|
||||
GetSystemTimeAsFileTime(&filetime);
|
||||
#endif
|
||||
|
||||
/*
|
||||
* As per Windows documentation for FILETIME, copy the resulting FILETIME structure to a
|
||||
* ULARGE_INTEGER structure using memcpy (using memcpy instead of direct assignment can
|
||||
* prevent alignment faults on 64-bit Windows).
|
||||
*/
|
||||
memcpy(&datetime, &filetime, sizeof(datetime));
|
||||
|
||||
/* Windows file times are in 100s of nanoseconds. */
|
||||
return (datetime.QuadPart - DELTA_EPOCH_IN_MICROSECS) / 10;
|
||||
}
|
||||
|
||||
#ifdef _WIN32_WCE
|
||||
time_t time(time_t *t)
|
||||
{
|
||||
time_t ret = time_in_microseconds() / 1000000;
|
||||
*t = ret;
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
|
||||
LWS_VISIBLE int libwebsockets_get_random(struct libwebsocket_context *context,
|
||||
void *buf, int len)
|
||||
{
|
||||
int n;
|
||||
char *p = (char *)buf;
|
||||
|
||||
for (n = 0; n < len; n++)
|
||||
p[n] = (unsigned char)rand();
|
||||
|
||||
return n;
|
||||
}
|
||||
|
||||
LWS_VISIBLE int lws_send_pipe_choked(struct libwebsocket *wsi)
|
||||
{
|
||||
return wsi->sock_send_blocking;
|
||||
}
|
||||
|
||||
LWS_VISIBLE int lws_poll_listen_fd(struct libwebsocket_pollfd *fd)
|
||||
{
|
||||
fd_set readfds;
|
||||
struct timeval tv = { 0, 0 };
|
||||
|
||||
assert(fd->events == LWS_POLLIN);
|
||||
|
||||
FD_ZERO(&readfds);
|
||||
FD_SET(fd->fd, &readfds);
|
||||
|
||||
return select(fd->fd + 1, &readfds, NULL, NULL, &tv);
|
||||
}
|
||||
|
||||
/**
|
||||
* libwebsocket_cancel_service() - Cancel servicing of pending websocket activity
|
||||
* @context: Websocket context
|
||||
*
|
||||
* This function let a call to libwebsocket_service() waiting for a timeout
|
||||
* immediately return.
|
||||
*/
|
||||
LWS_VISIBLE void
|
||||
libwebsocket_cancel_service(struct libwebsocket_context *context)
|
||||
{
|
||||
WSASetEvent(context->events[0]);
|
||||
}
|
||||
|
||||
LWS_VISIBLE void lwsl_emit_syslog(int level, const char *line)
|
||||
{
|
||||
lwsl_emit_stderr(level, line);
|
||||
}
|
||||
|
||||
LWS_VISIBLE int
|
||||
lws_plat_service(struct libwebsocket_context *context, int timeout_ms)
|
||||
{
|
||||
int n;
|
||||
int i;
|
||||
DWORD ev;
|
||||
WSANETWORKEVENTS networkevents;
|
||||
struct libwebsocket_pollfd *pfd;
|
||||
|
||||
/* stay dead once we are dead */
|
||||
|
||||
if (context == NULL)
|
||||
return 1;
|
||||
|
||||
context->service_tid = context->protocols[0].callback(context, NULL,
|
||||
LWS_CALLBACK_GET_THREAD_ID, NULL, NULL, 0);
|
||||
|
||||
for (i = 0; i < context->fds_count; ++i) {
|
||||
pfd = &context->fds[i];
|
||||
if (pfd->fd == context->listen_service_fd)
|
||||
continue;
|
||||
|
||||
if (pfd->events & LWS_POLLOUT) {
|
||||
if (context->lws_lookup[pfd->fd]->sock_send_blocking)
|
||||
continue;
|
||||
pfd->revents = LWS_POLLOUT;
|
||||
n = libwebsocket_service_fd(context, pfd);
|
||||
if (n < 0)
|
||||
return n;
|
||||
}
|
||||
}
|
||||
|
||||
ev = WSAWaitForMultipleEvents(context->fds_count + 1,
|
||||
context->events, FALSE, timeout_ms, FALSE);
|
||||
context->service_tid = 0;
|
||||
|
||||
if (ev == WSA_WAIT_TIMEOUT) {
|
||||
libwebsocket_service_fd(context, NULL);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (ev == WSA_WAIT_EVENT_0) {
|
||||
WSAResetEvent(context->events[0]);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (ev < WSA_WAIT_EVENT_0 || ev > WSA_WAIT_EVENT_0 + context->fds_count)
|
||||
return -1;
|
||||
|
||||
pfd = &context->fds[ev - WSA_WAIT_EVENT_0 - 1];
|
||||
|
||||
if (WSAEnumNetworkEvents(pfd->fd,
|
||||
context->events[ev - WSA_WAIT_EVENT_0],
|
||||
&networkevents) == SOCKET_ERROR) {
|
||||
lwsl_err("WSAEnumNetworkEvents() failed with error %d\n",
|
||||
LWS_ERRNO);
|
||||
return -1;
|
||||
}
|
||||
|
||||
pfd->revents = networkevents.lNetworkEvents;
|
||||
|
||||
if (pfd->revents & LWS_POLLOUT)
|
||||
context->lws_lookup[pfd->fd]->sock_send_blocking = FALSE;
|
||||
|
||||
return libwebsocket_service_fd(context, pfd);
|
||||
}
|
||||
|
||||
LWS_VISIBLE int
|
||||
lws_plat_set_socket_options(struct libwebsocket_context *context, int fd)
|
||||
{
|
||||
int optval = 1;
|
||||
int optlen = sizeof(optval);
|
||||
u_long optl = 1;
|
||||
DWORD dwBytesRet;
|
||||
struct tcp_keepalive alive;
|
||||
struct protoent *tcp_proto;
|
||||
|
||||
if (context->ka_time) {
|
||||
/* enable keepalive on this socket */
|
||||
optval = 1;
|
||||
if (setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE,
|
||||
(const char *)&optval, optlen) < 0)
|
||||
return 1;
|
||||
|
||||
alive.onoff = TRUE;
|
||||
alive.keepalivetime = context->ka_time;
|
||||
alive.keepaliveinterval = context->ka_interval;
|
||||
|
||||
if (WSAIoctl(fd, SIO_KEEPALIVE_VALS, &alive, sizeof(alive),
|
||||
NULL, 0, &dwBytesRet, NULL, NULL))
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Disable Nagle */
|
||||
optval = 1;
|
||||
tcp_proto = getprotobyname("TCP");
|
||||
setsockopt(fd, tcp_proto->p_proto, TCP_NODELAY, (const char *)&optval, optlen);
|
||||
|
||||
/* We are nonblocking... */
|
||||
ioctlsocket(fd, FIONBIO, &optl);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
LWS_VISIBLE void
|
||||
lws_plat_drop_app_privileges(struct lws_context_creation_info *info)
|
||||
{
|
||||
}
|
||||
|
||||
LWS_VISIBLE int
|
||||
lws_plat_init_fd_tables(struct libwebsocket_context *context)
|
||||
{
|
||||
context->events = (WSAEVENT *)malloc(sizeof(WSAEVENT) *
|
||||
(context->max_fds + 1));
|
||||
if (context->events == NULL) {
|
||||
lwsl_err("Unable to allocate events array for %d connections\n",
|
||||
context->max_fds);
|
||||
return 1;
|
||||
}
|
||||
|
||||
context->fds_count = 0;
|
||||
context->events[0] = WSACreateEvent();
|
||||
|
||||
context->fd_random = 0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
LWS_VISIBLE int
|
||||
lws_plat_context_early_init(void)
|
||||
{
|
||||
WORD wVersionRequested;
|
||||
WSADATA wsaData;
|
||||
int err;
|
||||
|
||||
/* Use the MAKEWORD(lowbyte, highbyte) macro from Windef.h */
|
||||
wVersionRequested = MAKEWORD(2, 2);
|
||||
|
||||
err = WSAStartup(wVersionRequested, &wsaData);
|
||||
if (!err)
|
||||
return 0;
|
||||
/*
|
||||
* Tell the user that we could not find a usable
|
||||
* Winsock DLL
|
||||
*/
|
||||
lwsl_err("WSAStartup failed with error: %d\n", err);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
LWS_VISIBLE void
|
||||
lws_plat_context_early_destroy(struct libwebsocket_context *context)
|
||||
{
|
||||
if (context->events) {
|
||||
WSACloseEvent(context->events[0]);
|
||||
free(context->events);
|
||||
}
|
||||
}
|
||||
|
||||
LWS_VISIBLE void
|
||||
lws_plat_context_late_destroy(struct libwebsocket_context *context)
|
||||
{
|
||||
WSACleanup();
|
||||
}
|
||||
|
||||
LWS_VISIBLE int
|
||||
interface_to_sa(struct libwebsocket_context *context,
|
||||
const char *ifname, struct sockaddr_in *addr, size_t addrlen)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
LWS_VISIBLE void
|
||||
lws_plat_insert_socket_into_fds(struct libwebsocket_context *context,
|
||||
struct libwebsocket *wsi)
|
||||
{
|
||||
context->fds[context->fds_count++].revents = 0;
|
||||
context->events[context->fds_count] = WSACreateEvent();
|
||||
WSAEventSelect(wsi->sock, context->events[context->fds_count], LWS_POLLIN);
|
||||
}
|
||||
|
||||
LWS_VISIBLE void
|
||||
lws_plat_delete_socket_from_fds(struct libwebsocket_context *context,
|
||||
struct libwebsocket *wsi, int m)
|
||||
{
|
||||
WSACloseEvent(context->events[m + 1]);
|
||||
context->events[m + 1] = context->events[context->fds_count + 1];
|
||||
}
|
||||
|
||||
LWS_VISIBLE void
|
||||
lws_plat_service_periodic(struct libwebsocket_context *context)
|
||||
{
|
||||
}
|
||||
|
||||
LWS_VISIBLE int
|
||||
lws_plat_change_pollfd(struct libwebsocket_context *context,
|
||||
struct libwebsocket *wsi, struct libwebsocket_pollfd *pfd)
|
||||
{
|
||||
long networkevents = LWS_POLLOUT | LWS_POLLHUP;
|
||||
|
||||
if ((pfd->events & LWS_POLLIN))
|
||||
networkevents |= LWS_POLLIN;
|
||||
|
||||
if (WSAEventSelect(wsi->sock,
|
||||
context->events[wsi->position_in_fds_table + 1],
|
||||
networkevents) != SOCKET_ERROR)
|
||||
return 0;
|
||||
|
||||
lwsl_err("WSAEventSelect() failed with error %d\n", LWS_ERRNO);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
LWS_VISIBLE HANDLE
|
||||
lws_plat_open_file(const char* filename, unsigned long* filelen)
|
||||
{
|
||||
HANDLE ret;
|
||||
WCHAR buffer[MAX_PATH];
|
||||
|
||||
MultiByteToWideChar(CP_UTF8, 0, filename, -1, buffer,
|
||||
sizeof(buffer) / sizeof(buffer[0]));
|
||||
ret = CreateFileW(buffer, GENERIC_READ, FILE_SHARE_READ,
|
||||
NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
|
||||
|
||||
if (ret != LWS_INVALID_FILE)
|
||||
*filelen = GetFileSize(ret, NULL);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
LWS_VISIBLE const char *
|
||||
lws_plat_inet_ntop(int af, const void *src, char *dst, int cnt)
|
||||
{
|
||||
WCHAR *buffer;
|
||||
DWORD bufferlen = cnt;
|
||||
BOOL ok = FALSE;
|
||||
|
||||
buffer = malloc(bufferlen);
|
||||
if (!buffer) {
|
||||
lwsl_err("Out of memory\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (af == AF_INET) {
|
||||
struct sockaddr_in srcaddr;
|
||||
bzero(&srcaddr, sizeof(srcaddr));
|
||||
srcaddr.sin_family = AF_INET;
|
||||
memcpy(&(srcaddr.sin_addr), src, sizeof(srcaddr.sin_addr));
|
||||
|
||||
if (!WSAAddressToStringW((struct sockaddr*)&srcaddr, sizeof(srcaddr), 0, buffer, &bufferlen))
|
||||
ok = TRUE;
|
||||
#ifdef LWS_USE_IPV6
|
||||
} else if (af == AF_INET6) {
|
||||
struct sockaddr_in6 srcaddr;
|
||||
bzero(&srcaddr, sizeof(srcaddr));
|
||||
srcaddr.sin6_family = AF_INET6;
|
||||
memcpy(&(srcaddr.sin6_addr), src, sizeof(srcaddr.sin6_addr));
|
||||
|
||||
if (!WSAAddressToStringW((struct sockaddr*)&srcaddr, sizeof(srcaddr), 0, buffer, &bufferlen))
|
||||
ok = TRUE;
|
||||
#endif
|
||||
} else
|
||||
lwsl_err("Unsupported type\n");
|
||||
|
||||
if (!ok) {
|
||||
int rv = WSAGetLastError();
|
||||
lwsl_err("WSAAddressToString() : %d\n", rv);
|
||||
} else {
|
||||
if (WideCharToMultiByte(CP_ACP, 0, buffer, bufferlen, dst, cnt, 0, NULL) <= 0)
|
||||
ok = FALSE;
|
||||
}
|
||||
|
||||
free(buffer);
|
||||
return ok ? dst : NULL;
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,174 @@
|
||||
/* config.h.in. Generated from configure.ac by autoheader. */
|
||||
|
||||
#ifndef WIN32
|
||||
#define _DEBUG
|
||||
#endif
|
||||
|
||||
/* Define to 1 to use CyaSSL as a replacement for OpenSSL.
|
||||
* LWS_OPENSSL_SUPPORT needs to be set also for this to work. */
|
||||
/* #undef USE_CYASSL */
|
||||
|
||||
/* The Libwebsocket version */
|
||||
#define LWS_LIBRARY_VERSION "1.3"
|
||||
|
||||
/* The current git commit hash that we're building from */
|
||||
#define LWS_BUILD_HASH "c11b847"
|
||||
|
||||
/* Build with OpenSSL support */
|
||||
/* #undef LWS_OPENSSL_SUPPORT */
|
||||
|
||||
/* The client should load and trust CA root certs it finds in the OS */
|
||||
/* #undef LWS_SSL_CLIENT_USE_OS_CA_CERTS */
|
||||
|
||||
/* Sets the path where the client certs should be installed. */
|
||||
#define LWS_OPENSSL_CLIENT_CERTS "../share"
|
||||
|
||||
/* Turn off websocket extensions */
|
||||
/* #undef LWS_NO_EXTENSIONS */
|
||||
|
||||
/* Enable libev io loop */
|
||||
/* #undef LWS_USE_LIBEV */
|
||||
|
||||
/* Build with support for ipv6 */
|
||||
/* #undef LWS_USE_IPV6 */
|
||||
|
||||
/* Build with support for HTTP2 */
|
||||
/* #undef LWS_USE_HTTP2 */
|
||||
|
||||
/* Turn on latency measuring code */
|
||||
/* #undef LWS_LATENCY */
|
||||
|
||||
/* Don't build the daemonizeation api */
|
||||
#define LWS_NO_DAEMONIZE
|
||||
|
||||
/* Build without server support */
|
||||
/* #undef LWS_NO_SERVER */
|
||||
|
||||
/* Build without client support */
|
||||
/* #undef LWS_NO_CLIENT */
|
||||
|
||||
/* If we should compile with MinGW support */
|
||||
/* #undef LWS_MINGW_SUPPORT */
|
||||
|
||||
/* Use the BSD getifaddrs that comes with libwebsocket, for uclibc support */
|
||||
#define LWS_BUILTIN_GETIFADDRS
|
||||
|
||||
/* Define to 1 if you have the `bzero' function. */
|
||||
/* #undef HAVE_BZERO */
|
||||
|
||||
/* Define to 1 if you have the <dlfcn.h> header file. */
|
||||
/* #undef HAVE_DLFCN_H */
|
||||
|
||||
/* Define to 1 if you have the <fcntl.h> header file. */
|
||||
#define HAVE_FCNTL_H
|
||||
|
||||
/* Define to 1 if you have the `fork' function. */
|
||||
/* #undef HAVE_FORK */
|
||||
|
||||
/* Define to 1 if you have the `getenv’ function. */
|
||||
#define HAVE_GETENV
|
||||
|
||||
/* Define to 1 if you have the <in6addr.h> header file. */
|
||||
/* #undef HAVE_IN6ADDR_H */
|
||||
|
||||
/* Define to 1 if you have the <inttypes.h> header file. */
|
||||
/* #undef HAVE_INTTYPES_H */
|
||||
|
||||
/* Define to 1 if you have the `ssl' library (-lssl). */
|
||||
/* #undef HAVE_LIBSSL */
|
||||
|
||||
/* Define to 1 if your system has a GNU libc compatible `malloc' function, and
|
||||
to 0 otherwise. */
|
||||
#define HAVE_MALLOC
|
||||
|
||||
/* Define to 1 if you have the <memory.h> header file. */
|
||||
#define HAVE_MEMORY_H
|
||||
|
||||
/* Define to 1 if you have the `memset' function. */
|
||||
#define HAVE_MEMSET
|
||||
|
||||
/* Define to 1 if you have the <netinet/in.h> header file. */
|
||||
/* #undef HAVE_NETINET_IN_H */
|
||||
|
||||
/* Define to 1 if your system has a GNU libc compatible `realloc' function,
|
||||
and to 0 otherwise. */
|
||||
#define HAVE_REALLOC
|
||||
|
||||
/* Define to 1 if you have the `socket' function. */
|
||||
/* #undef HAVE_SOCKET */
|
||||
|
||||
/* Define to 1 if you have the <stdint.h> header file. */
|
||||
#define HAVE_STDINT_H
|
||||
|
||||
/* Define to 1 if you have the <stdlib.h> header file. */
|
||||
#define HAVE_STDLIB_H
|
||||
|
||||
/* Define to 1 if you have the `strerror' function. */
|
||||
#define HAVE_STRERROR
|
||||
|
||||
/* Define to 1 if you have the <strings.h> header file. */
|
||||
/* #undef HAVE_STRINGS_H */
|
||||
|
||||
/* Define to 1 if you have the <string.h> header file. */
|
||||
#define HAVE_STRING_H
|
||||
|
||||
/* Define to 1 if you have the <sys/prctl.h> header file. */
|
||||
/* #undef HAVE_SYS_PRCTL_H */
|
||||
|
||||
/* Define to 1 if you have the <sys/socket.h> header file. */
|
||||
/* #undef HAVE_SYS_SOCKET_H */
|
||||
|
||||
/* Define to 1 if you have the <sys/stat.h> header file. */
|
||||
#define HAVE_SYS_STAT_H
|
||||
|
||||
/* Define to 1 if you have the <sys/types.h> header file. */
|
||||
#define HAVE_SYS_TYPES_H
|
||||
|
||||
/* Define to 1 if you have the <unistd.h> header file. */
|
||||
/* #undef HAVE_UNISTD_H */
|
||||
|
||||
/* Define to 1 if you have the `vfork' function. */
|
||||
/* #undef HAVE_VFORK */
|
||||
|
||||
/* Define to 1 if you have the <vfork.h> header file. */
|
||||
/* #undef HAVE_VFORK_H */
|
||||
|
||||
/* Define to 1 if `fork' works. */
|
||||
#define HAVE_WORKING_FORK
|
||||
|
||||
/* Define to 1 if `vfork' works. */
|
||||
#define HAVE_WORKING_VFORK
|
||||
|
||||
/* Define to 1 if you have the <zlib.h> header file. */
|
||||
/* #undef HAVE_ZLIB_H */
|
||||
|
||||
/* Define to the sub-directory in which libtool stores uninstalled libraries.
|
||||
*/
|
||||
#undef LT_OBJDIR // We're not using libtool
|
||||
|
||||
/* Define to 1 if you have the ANSI C header files. */
|
||||
#define STDC_HEADERS
|
||||
|
||||
/* Version number of package */
|
||||
#define VERSION
|
||||
|
||||
/* Define to rpl_malloc if the replacement function should be used. */
|
||||
/* #undef malloc */
|
||||
|
||||
/* Define to `int' if <sys/types.h> does not define. */
|
||||
#define pid_t
|
||||
|
||||
/* Define to rpl_realloc if the replacement function should be used. */
|
||||
/* #undef realloc */
|
||||
|
||||
/* Define to `unsigned int' if <sys/types.h> does not define. */
|
||||
/* #undef size_t */
|
||||
|
||||
/* Define to 1 if we have getifaddrs */
|
||||
/* #undef HAVE_GETIFADDRS */
|
||||
|
||||
/* Define as `fork' if `vfork' does not work. */
|
||||
/* #undef vfork */
|
||||
|
||||
/* Define if the inline keyword doesn't exist. */
|
||||
#define inline
|
||||
@@ -0,0 +1,571 @@
|
||||
/*
|
||||
* libwebsockets - small server side websockets and web server implementation
|
||||
*
|
||||
* Copyright (C) 2010-2014 Andy Green <[email protected]>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation:
|
||||
* version 2.1 of the License.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
||||
* MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#include "private-libwebsockets.h"
|
||||
|
||||
static int
|
||||
libwebsocket_0405_frame_mask_generate(struct libwebsocket *wsi)
|
||||
{
|
||||
int n;
|
||||
|
||||
/* fetch the per-frame nonce */
|
||||
|
||||
n = libwebsockets_get_random(wsi->protocol->owning_server,
|
||||
wsi->u.ws.frame_masking_nonce_04, 4);
|
||||
if (n != 4) {
|
||||
lwsl_parser("Unable to read from random device %s %d\n",
|
||||
SYSTEM_RANDOM_FILEPATH, n);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* start masking from first byte of masking key buffer */
|
||||
wsi->u.ws.frame_mask_index = 0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef _DEBUG
|
||||
|
||||
LWS_VISIBLE void lwsl_hexdump(void *vbuf, size_t len)
|
||||
{
|
||||
int n;
|
||||
int m;
|
||||
int start;
|
||||
unsigned char *buf = (unsigned char *)vbuf;
|
||||
char line[80];
|
||||
char *p;
|
||||
|
||||
lwsl_parser("\n");
|
||||
|
||||
for (n = 0; n < len;) {
|
||||
start = n;
|
||||
p = line;
|
||||
|
||||
p += sprintf(p, "%04X: ", start);
|
||||
|
||||
for (m = 0; m < 16 && n < len; m++)
|
||||
p += sprintf(p, "%02X ", buf[n++]);
|
||||
while (m++ < 16)
|
||||
p += sprintf(p, " ");
|
||||
|
||||
p += sprintf(p, " ");
|
||||
|
||||
for (m = 0; m < 16 && (start + m) < len; m++) {
|
||||
if (buf[start + m] >= ' ' && buf[start + m] < 127)
|
||||
*p++ = buf[start + m];
|
||||
else
|
||||
*p++ = '.';
|
||||
}
|
||||
while (m++ < 16)
|
||||
*p++ = ' ';
|
||||
|
||||
*p++ = '\n';
|
||||
*p = '\0';
|
||||
lwsl_debug("%s", line);
|
||||
}
|
||||
lwsl_debug("\n");
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/*
|
||||
* notice this returns number of bytes consumed, or -1
|
||||
*/
|
||||
|
||||
int lws_issue_raw(struct libwebsocket *wsi, unsigned char *buf, size_t len)
|
||||
{
|
||||
struct libwebsocket_context *context = wsi->protocol->owning_server;
|
||||
int n;
|
||||
size_t real_len = len;
|
||||
int m;
|
||||
|
||||
if (!len)
|
||||
return 0;
|
||||
/* just ignore sends after we cleared the truncation buffer */
|
||||
if (wsi->state == WSI_STATE_FLUSHING_STORED_SEND_BEFORE_CLOSE &&
|
||||
!wsi->truncated_send_len)
|
||||
return len;
|
||||
|
||||
if (wsi->truncated_send_len && (buf < wsi->truncated_send_malloc ||
|
||||
buf > (wsi->truncated_send_malloc +
|
||||
wsi->truncated_send_len +
|
||||
wsi->truncated_send_offset))) {
|
||||
lwsl_err("****** %x Sending new, pending truncated ...\n", wsi);
|
||||
assert(0);
|
||||
}
|
||||
|
||||
m = lws_ext_callback_for_each_active(wsi,
|
||||
LWS_EXT_CALLBACK_PACKET_TX_DO_SEND, &buf, len);
|
||||
if (m < 0)
|
||||
return -1;
|
||||
if (m) /* handled */ {
|
||||
n = m;
|
||||
goto handle_truncated_send;
|
||||
}
|
||||
if (wsi->sock < 0)
|
||||
lwsl_warn("** error invalid sock but expected to send\n");
|
||||
|
||||
/*
|
||||
* nope, send it on the socket directly
|
||||
*/
|
||||
lws_latency_pre(context, wsi);
|
||||
n = lws_ssl_capable_write(wsi, buf, len);
|
||||
lws_latency(context, wsi, "send lws_issue_raw", n, n == len);
|
||||
|
||||
switch (n) {
|
||||
case LWS_SSL_CAPABLE_ERROR:
|
||||
return -1;
|
||||
case LWS_SSL_CAPABLE_MORE_SERVICE:
|
||||
/* nothing got sent, not fatal, retry the whole thing later */
|
||||
n = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
handle_truncated_send:
|
||||
/*
|
||||
* we were already handling a truncated send?
|
||||
*/
|
||||
if (wsi->truncated_send_len) {
|
||||
lwsl_info("***** %x partial send moved on by %d (vs %d)\n",
|
||||
wsi, n, real_len);
|
||||
wsi->truncated_send_offset += n;
|
||||
wsi->truncated_send_len -= n;
|
||||
|
||||
if (!wsi->truncated_send_len) {
|
||||
lwsl_info("***** %x partial send completed\n", wsi);
|
||||
/* done with it, but don't free it */
|
||||
n = real_len;
|
||||
if (wsi->state == WSI_STATE_FLUSHING_STORED_SEND_BEFORE_CLOSE) {
|
||||
lwsl_info("***** %x signalling to close now\n", wsi);
|
||||
return -1; /* retry closing now */
|
||||
}
|
||||
}
|
||||
/* always callback on writeable */
|
||||
libwebsocket_callback_on_writable(
|
||||
wsi->protocol->owning_server, wsi);
|
||||
|
||||
return n;
|
||||
}
|
||||
|
||||
if (n == real_len)
|
||||
/* what we just sent went out cleanly */
|
||||
return n;
|
||||
|
||||
if (n && wsi->u.ws.clean_buffer)
|
||||
/*
|
||||
* This buffer unaffected by extension rewriting.
|
||||
* It means the user code is expected to deal with
|
||||
* partial sends. (lws knows the header was already
|
||||
* sent, so on next send will just resume sending
|
||||
* payload)
|
||||
*/
|
||||
return n;
|
||||
|
||||
/*
|
||||
* Newly truncated send. Buffer the remainder (it will get
|
||||
* first priority next time the socket is writable)
|
||||
*/
|
||||
lwsl_info("***** %x new partial sent %d from %d total\n",
|
||||
wsi, n, real_len);
|
||||
|
||||
/*
|
||||
* - if we still have a suitable malloc lying around, use it
|
||||
* - or, if too small, reallocate it
|
||||
* - or, if no buffer, create it
|
||||
*/
|
||||
if (!wsi->truncated_send_malloc ||
|
||||
real_len - n > wsi->truncated_send_allocation) {
|
||||
if (wsi->truncated_send_malloc)
|
||||
free(wsi->truncated_send_malloc);
|
||||
|
||||
wsi->truncated_send_allocation = real_len - n;
|
||||
wsi->truncated_send_malloc = malloc(real_len - n);
|
||||
if (!wsi->truncated_send_malloc) {
|
||||
lwsl_err("truncated send: unable to malloc %d\n",
|
||||
real_len - n);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
wsi->truncated_send_offset = 0;
|
||||
wsi->truncated_send_len = real_len - n;
|
||||
memcpy(wsi->truncated_send_malloc, buf + n, real_len - n);
|
||||
|
||||
/* since something buffered, force it to get another chance to send */
|
||||
libwebsocket_callback_on_writable(wsi->protocol->owning_server, wsi);
|
||||
|
||||
return real_len;
|
||||
}
|
||||
|
||||
/**
|
||||
* libwebsocket_write() - Apply protocol then write data to client
|
||||
* @wsi: Websocket instance (available from user callback)
|
||||
* @buf: The data to send. For data being sent on a websocket
|
||||
* connection (ie, not default http), this buffer MUST have
|
||||
* LWS_SEND_BUFFER_PRE_PADDING bytes valid BEFORE the pointer
|
||||
* and an additional LWS_SEND_BUFFER_POST_PADDING bytes valid
|
||||
* in the buffer after (buf + len). This is so the protocol
|
||||
* header and trailer data can be added in-situ.
|
||||
* @len: Count of the data bytes in the payload starting from buf
|
||||
* @protocol: Use LWS_WRITE_HTTP to reply to an http connection, and one
|
||||
* of LWS_WRITE_BINARY or LWS_WRITE_TEXT to send appropriate
|
||||
* data on a websockets connection. Remember to allow the extra
|
||||
* bytes before and after buf if LWS_WRITE_BINARY or LWS_WRITE_TEXT
|
||||
* are used.
|
||||
*
|
||||
* This function provides the way to issue data back to the client
|
||||
* for both http and websocket protocols.
|
||||
*
|
||||
* In the case of sending using websocket protocol, be sure to allocate
|
||||
* valid storage before and after buf as explained above. This scheme
|
||||
* allows maximum efficiency of sending data and protocol in a single
|
||||
* packet while not burdening the user code with any protocol knowledge.
|
||||
*
|
||||
* Return may be -1 for a fatal error needing connection close, or a
|
||||
* positive number reflecting the amount of bytes actually sent. This
|
||||
* can be less than the requested number of bytes due to OS memory
|
||||
* pressure at any given time.
|
||||
*/
|
||||
|
||||
LWS_VISIBLE int libwebsocket_write(struct libwebsocket *wsi, unsigned char *buf,
|
||||
size_t len, enum libwebsocket_write_protocol protocol)
|
||||
{
|
||||
int n;
|
||||
int pre = 0;
|
||||
int post = 0;
|
||||
int masked7 = wsi->mode == LWS_CONNMODE_WS_CLIENT;
|
||||
unsigned char *dropmask = NULL;
|
||||
unsigned char is_masked_bit = 0;
|
||||
size_t orig_len = len;
|
||||
struct lws_tokens eff_buf;
|
||||
|
||||
if (len == 0 && protocol != LWS_WRITE_CLOSE &&
|
||||
protocol != LWS_WRITE_PING && protocol != LWS_WRITE_PONG) {
|
||||
lwsl_warn("zero length libwebsocket_write attempt\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (protocol == LWS_WRITE_HTTP)
|
||||
goto send_raw;
|
||||
|
||||
/* websocket protocol, either binary or text */
|
||||
|
||||
if (wsi->state != WSI_STATE_ESTABLISHED)
|
||||
return -1;
|
||||
|
||||
/* if we are continuing a frame that already had its header done */
|
||||
|
||||
if (wsi->u.ws.inside_frame)
|
||||
goto do_more_inside_frame;
|
||||
|
||||
/* if he wants all partials buffered, never have a clean_buffer */
|
||||
wsi->u.ws.clean_buffer = !wsi->protocol->no_buffer_all_partial_tx;
|
||||
|
||||
/*
|
||||
* give a chance to the extensions to modify payload
|
||||
* pre-TX mangling is not allowed to truncate
|
||||
*/
|
||||
eff_buf.token = (char *)buf;
|
||||
eff_buf.token_len = len;
|
||||
|
||||
switch (protocol) {
|
||||
case LWS_WRITE_PING:
|
||||
case LWS_WRITE_PONG:
|
||||
case LWS_WRITE_CLOSE:
|
||||
break;
|
||||
default:
|
||||
if (lws_ext_callback_for_each_active(wsi,
|
||||
LWS_EXT_CALLBACK_PAYLOAD_TX, &eff_buf, 0) < 0)
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*
|
||||
* an extension did something we need to keep... for example, if
|
||||
* compression extension, it has already updated its state according
|
||||
* to this being issued
|
||||
*/
|
||||
if ((char *)buf != eff_buf.token)
|
||||
/*
|
||||
* extension recreated it:
|
||||
* need to buffer this if not all sent
|
||||
*/
|
||||
wsi->u.ws.clean_buffer = 0;
|
||||
|
||||
buf = (unsigned char *)eff_buf.token;
|
||||
len = eff_buf.token_len;
|
||||
|
||||
switch (wsi->ietf_spec_revision) {
|
||||
case 13:
|
||||
|
||||
if (masked7) {
|
||||
pre += 4;
|
||||
dropmask = &buf[0 - pre];
|
||||
is_masked_bit = 0x80;
|
||||
}
|
||||
|
||||
switch (protocol & 0xf) {
|
||||
case LWS_WRITE_TEXT:
|
||||
n = LWS_WS_OPCODE_07__TEXT_FRAME;
|
||||
break;
|
||||
case LWS_WRITE_BINARY:
|
||||
n = LWS_WS_OPCODE_07__BINARY_FRAME;
|
||||
break;
|
||||
case LWS_WRITE_CONTINUATION:
|
||||
n = LWS_WS_OPCODE_07__CONTINUATION;
|
||||
break;
|
||||
|
||||
case LWS_WRITE_CLOSE:
|
||||
n = LWS_WS_OPCODE_07__CLOSE;
|
||||
|
||||
/*
|
||||
* 06+ has a 2-byte status code in network order
|
||||
* we can do this because we demand post-buf
|
||||
*/
|
||||
|
||||
if (wsi->u.ws.close_reason) {
|
||||
/* reason codes count as data bytes */
|
||||
buf -= 2;
|
||||
buf[0] = wsi->u.ws.close_reason >> 8;
|
||||
buf[1] = wsi->u.ws.close_reason;
|
||||
len += 2;
|
||||
}
|
||||
break;
|
||||
case LWS_WRITE_PING:
|
||||
n = LWS_WS_OPCODE_07__PING;
|
||||
break;
|
||||
case LWS_WRITE_PONG:
|
||||
n = LWS_WS_OPCODE_07__PONG;
|
||||
break;
|
||||
default:
|
||||
lwsl_warn("lws_write: unknown write opc / protocol\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!(protocol & LWS_WRITE_NO_FIN))
|
||||
n |= 1 << 7;
|
||||
|
||||
if (len < 126) {
|
||||
pre += 2;
|
||||
buf[-pre] = n;
|
||||
buf[-pre + 1] = len | is_masked_bit;
|
||||
} else {
|
||||
if (len < 65536) {
|
||||
pre += 4;
|
||||
buf[-pre] = n;
|
||||
buf[-pre + 1] = 126 | is_masked_bit;
|
||||
buf[-pre + 2] = len >> 8;
|
||||
buf[-pre + 3] = len;
|
||||
} else {
|
||||
pre += 10;
|
||||
buf[-pre] = n;
|
||||
buf[-pre + 1] = 127 | is_masked_bit;
|
||||
#if defined __LP64__
|
||||
buf[-pre + 2] = (len >> 56) & 0x7f;
|
||||
buf[-pre + 3] = len >> 48;
|
||||
buf[-pre + 4] = len >> 40;
|
||||
buf[-pre + 5] = len >> 32;
|
||||
#else
|
||||
buf[-pre + 2] = 0;
|
||||
buf[-pre + 3] = 0;
|
||||
buf[-pre + 4] = 0;
|
||||
buf[-pre + 5] = 0;
|
||||
#endif
|
||||
buf[-pre + 6] = len >> 24;
|
||||
buf[-pre + 7] = len >> 16;
|
||||
buf[-pre + 8] = len >> 8;
|
||||
buf[-pre + 9] = len;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
do_more_inside_frame:
|
||||
|
||||
/*
|
||||
* Deal with masking if we are in client -> server direction and
|
||||
* the protocol demands it
|
||||
*/
|
||||
|
||||
if (wsi->mode == LWS_CONNMODE_WS_CLIENT) {
|
||||
|
||||
if (!wsi->u.ws.inside_frame)
|
||||
if (libwebsocket_0405_frame_mask_generate(wsi)) {
|
||||
lwsl_err("frame mask generation failed\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*
|
||||
* in v7, just mask the payload
|
||||
*/
|
||||
if (dropmask) { /* never set if already inside frame */
|
||||
for (n = 4; n < (int)len + 4; n++)
|
||||
dropmask[n] = dropmask[n] ^
|
||||
wsi->u.ws.frame_masking_nonce_04[
|
||||
(wsi->u.ws.frame_mask_index++) & 3];
|
||||
|
||||
/* copy the frame nonce into place */
|
||||
memcpy(dropmask, wsi->u.ws.frame_masking_nonce_04, 4);
|
||||
}
|
||||
}
|
||||
|
||||
send_raw:
|
||||
switch (protocol) {
|
||||
case LWS_WRITE_CLOSE:
|
||||
/* lwsl_hexdump(&buf[-pre], len + post); */
|
||||
case LWS_WRITE_HTTP:
|
||||
case LWS_WRITE_PONG:
|
||||
case LWS_WRITE_PING:
|
||||
return lws_issue_raw(wsi, (unsigned char *)buf - pre,
|
||||
len + pre + post);
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
wsi->u.ws.inside_frame = 1;
|
||||
|
||||
/*
|
||||
* give any active extensions a chance to munge the buffer
|
||||
* before send. We pass in a pointer to an lws_tokens struct
|
||||
* prepared with the default buffer and content length that's in
|
||||
* there. Rather than rewrite the default buffer, extensions
|
||||
* that expect to grow the buffer can adapt .token to
|
||||
* point to their own per-connection buffer in the extension
|
||||
* user allocation. By default with no extensions or no
|
||||
* extension callback handling, just the normal input buffer is
|
||||
* used then so it is efficient.
|
||||
*
|
||||
* callback returns 1 in case it wants to spill more buffers
|
||||
*
|
||||
* This takes care of holding the buffer if send is incomplete, ie,
|
||||
* if wsi->u.ws.clean_buffer is 0 (meaning an extension meddled with
|
||||
* the buffer). If wsi->u.ws.clean_buffer is 1, it will instead
|
||||
* return to the user code how much OF THE USER BUFFER was consumed.
|
||||
*/
|
||||
|
||||
n = lws_issue_raw_ext_access(wsi, buf - pre, len + pre + post);
|
||||
if (n <= 0)
|
||||
return n;
|
||||
|
||||
if (n == len + pre + post) {
|
||||
/* everything in the buffer was handled (or rebuffered...) */
|
||||
wsi->u.ws.inside_frame = 0;
|
||||
return orig_len;
|
||||
}
|
||||
|
||||
/*
|
||||
* it is how many bytes of user buffer got sent... may be < orig_len
|
||||
* in which case callback when writable has already been arranged
|
||||
* and user code can call libwebsocket_write() again with the rest
|
||||
* later.
|
||||
*/
|
||||
|
||||
return n - (pre + post);
|
||||
}
|
||||
|
||||
LWS_VISIBLE int libwebsockets_serve_http_file_fragment(
|
||||
struct libwebsocket_context *context, struct libwebsocket *wsi)
|
||||
{
|
||||
int n;
|
||||
int m;
|
||||
|
||||
while (!lws_send_pipe_choked(wsi)) {
|
||||
|
||||
if (wsi->truncated_send_len) {
|
||||
if (lws_issue_raw(wsi, wsi->truncated_send_malloc +
|
||||
wsi->truncated_send_offset,
|
||||
wsi->truncated_send_len) < 0) {
|
||||
lwsl_info("closing from libwebsockets_serve_http_file_fragment\n");
|
||||
return -1;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
if (wsi->u.http.filepos == wsi->u.http.filelen)
|
||||
goto all_sent;
|
||||
|
||||
compatible_file_read(n, wsi->u.http.fd, context->service_buffer,
|
||||
sizeof(context->service_buffer));
|
||||
if (n < 0)
|
||||
return -1; /* caller will close */
|
||||
if (n) {
|
||||
m = libwebsocket_write(wsi, context->service_buffer, n,
|
||||
LWS_WRITE_HTTP);
|
||||
if (m < 0)
|
||||
return -1;
|
||||
|
||||
wsi->u.http.filepos += m;
|
||||
if (m != n)
|
||||
/* adjust for what was not sent */
|
||||
compatible_file_seek_cur(wsi->u.http.fd, m - n);
|
||||
}
|
||||
all_sent:
|
||||
if (!wsi->truncated_send_len &&
|
||||
wsi->u.http.filepos == wsi->u.http.filelen) {
|
||||
wsi->state = WSI_STATE_HTTP;
|
||||
|
||||
if (wsi->protocol->callback)
|
||||
/* ignore callback returned value */
|
||||
user_callback_handle_rxflow(
|
||||
wsi->protocol->callback, context, wsi,
|
||||
LWS_CALLBACK_HTTP_FILE_COMPLETION,
|
||||
wsi->user_space, NULL, 0);
|
||||
return 1; /* >0 indicates completed */
|
||||
}
|
||||
}
|
||||
|
||||
lwsl_info("choked before able to send whole file (post)\n");
|
||||
libwebsocket_callback_on_writable(context, wsi);
|
||||
|
||||
return 0; /* indicates further processing must be done */
|
||||
}
|
||||
|
||||
LWS_VISIBLE int
|
||||
lws_ssl_capable_read_no_ssl(struct libwebsocket *wsi, unsigned char *buf, int len)
|
||||
{
|
||||
int n;
|
||||
|
||||
n = recv(wsi->sock, buf, len, 0);
|
||||
if (n >= 0)
|
||||
return n;
|
||||
|
||||
lwsl_warn("error on reading from skt\n");
|
||||
return LWS_SSL_CAPABLE_ERROR;
|
||||
}
|
||||
|
||||
LWS_VISIBLE int
|
||||
lws_ssl_capable_write_no_ssl(struct libwebsocket *wsi, unsigned char *buf, int len)
|
||||
{
|
||||
int n;
|
||||
|
||||
n = send(wsi->sock, buf, len, 0);
|
||||
if (n >= 0)
|
||||
return n;
|
||||
|
||||
if (LWS_ERRNO == LWS_EAGAIN ||
|
||||
LWS_ERRNO == LWS_EWOULDBLOCK ||
|
||||
LWS_ERRNO == LWS_EINTR) {
|
||||
if (LWS_ERRNO == LWS_EWOULDBLOCK)
|
||||
lws_set_blocking_send(wsi);
|
||||
|
||||
return LWS_SSL_CAPABLE_MORE_SERVICE;
|
||||
}
|
||||
lwsl_debug("ERROR writing len %d to skt %d\n", len, n);
|
||||
return LWS_SSL_CAPABLE_ERROR;
|
||||
}
|
||||
@@ -0,0 +1,973 @@
|
||||
/*
|
||||
* libwebsockets - small server side websockets and web server implementation
|
||||
*
|
||||
* Copyright (C) 2010-2013 Andy Green <[email protected]>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation:
|
||||
* version 2.1 of the License.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
||||
* MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#include "private-libwebsockets.h"
|
||||
|
||||
unsigned char lextable[] = {
|
||||
#include "lextable.h"
|
||||
};
|
||||
|
||||
#define FAIL_CHAR 0x08
|
||||
|
||||
int lextable_decode(int pos, char c)
|
||||
{
|
||||
|
||||
c = tolower(c);
|
||||
|
||||
while (1) {
|
||||
if (lextable[pos] & (1 << 7)) { /* 1-byte, fail on mismatch */
|
||||
if ((lextable[pos] & 0x7f) != c)
|
||||
return -1;
|
||||
/* fall thru */
|
||||
pos++;
|
||||
if (lextable[pos] == FAIL_CHAR)
|
||||
return -1;
|
||||
return pos;
|
||||
}
|
||||
/* b7 = 0, end or 3-byte */
|
||||
if (lextable[pos] < FAIL_CHAR) /* terminal marker */
|
||||
return pos;
|
||||
|
||||
if (lextable[pos] == c) /* goto */
|
||||
return pos + (lextable[pos + 1]) +
|
||||
(lextable[pos + 2] << 8);
|
||||
/* fall thru goto */
|
||||
pos += 3;
|
||||
/* continue */
|
||||
}
|
||||
}
|
||||
|
||||
int lws_allocate_header_table(struct libwebsocket *wsi)
|
||||
{
|
||||
wsi->u.hdr.ah = malloc(sizeof(*wsi->u.hdr.ah));
|
||||
if (wsi->u.hdr.ah == NULL) {
|
||||
lwsl_err("Out of memory\n");
|
||||
return -1;
|
||||
}
|
||||
memset(wsi->u.hdr.ah->frag_index, 0, sizeof(wsi->u.hdr.ah->frag_index));
|
||||
wsi->u.hdr.ah->next_frag_index = 0;
|
||||
wsi->u.hdr.ah->pos = 0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
LWS_VISIBLE int lws_hdr_total_length(struct libwebsocket *wsi, enum lws_token_indexes h)
|
||||
{
|
||||
int n;
|
||||
int len = 0;
|
||||
|
||||
n = wsi->u.hdr.ah->frag_index[h];
|
||||
if (!n)
|
||||
return 0;
|
||||
do {
|
||||
len += wsi->u.hdr.ah->frags[n].len;
|
||||
n = wsi->u.hdr.ah->frags[n].next_frag_index;
|
||||
} while (n);
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
LWS_VISIBLE int lws_hdr_copy(struct libwebsocket *wsi, char *dest, int len,
|
||||
enum lws_token_indexes h)
|
||||
{
|
||||
int toklen = lws_hdr_total_length(wsi, h);
|
||||
int n;
|
||||
|
||||
if (toklen >= len)
|
||||
return -1;
|
||||
|
||||
n = wsi->u.hdr.ah->frag_index[h];
|
||||
if (!n)
|
||||
return 0;
|
||||
|
||||
do {
|
||||
strcpy(dest,
|
||||
&wsi->u.hdr.ah->data[wsi->u.hdr.ah->frags[n].offset]);
|
||||
dest += wsi->u.hdr.ah->frags[n].len;
|
||||
n = wsi->u.hdr.ah->frags[n].next_frag_index;
|
||||
} while (n);
|
||||
|
||||
return toklen;
|
||||
}
|
||||
|
||||
char *lws_hdr_simple_ptr(struct libwebsocket *wsi, enum lws_token_indexes h)
|
||||
{
|
||||
int n;
|
||||
|
||||
n = wsi->u.hdr.ah->frag_index[h];
|
||||
if (!n)
|
||||
return NULL;
|
||||
|
||||
return &wsi->u.hdr.ah->data[wsi->u.hdr.ah->frags[n].offset];
|
||||
}
|
||||
|
||||
int lws_hdr_simple_create(struct libwebsocket *wsi,
|
||||
enum lws_token_indexes h, const char *s)
|
||||
{
|
||||
wsi->u.hdr.ah->next_frag_index++;
|
||||
if (wsi->u.hdr.ah->next_frag_index ==
|
||||
sizeof(wsi->u.hdr.ah->frags) / sizeof(wsi->u.hdr.ah->frags[0])) {
|
||||
lwsl_warn("More hdr frags than we can deal with, dropping\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
wsi->u.hdr.ah->frag_index[h] = wsi->u.hdr.ah->next_frag_index;
|
||||
|
||||
wsi->u.hdr.ah->frags[wsi->u.hdr.ah->next_frag_index].offset =
|
||||
wsi->u.hdr.ah->pos;
|
||||
wsi->u.hdr.ah->frags[wsi->u.hdr.ah->next_frag_index].len = 0;
|
||||
wsi->u.hdr.ah->frags[wsi->u.hdr.ah->next_frag_index].next_frag_index =
|
||||
0;
|
||||
|
||||
do {
|
||||
if (wsi->u.hdr.ah->pos == sizeof(wsi->u.hdr.ah->data)) {
|
||||
lwsl_err("Ran out of header data space\n");
|
||||
return -1;
|
||||
}
|
||||
wsi->u.hdr.ah->data[wsi->u.hdr.ah->pos++] = *s;
|
||||
if (*s)
|
||||
wsi->u.hdr.ah->frags[
|
||||
wsi->u.hdr.ah->next_frag_index].len++;
|
||||
} while (*s++);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static char char_to_hex(const char c)
|
||||
{
|
||||
if (c >= '0' && c <= '9')
|
||||
return c - '0';
|
||||
|
||||
if (c >= 'a' && c <= 'f')
|
||||
return c - 'a' + 10;
|
||||
|
||||
if (c >= 'A' && c <= 'F')
|
||||
return c - 'A' + 10;
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int issue_char(struct libwebsocket *wsi, unsigned char c)
|
||||
{
|
||||
if (wsi->u.hdr.ah->pos == sizeof(wsi->u.hdr.ah->data)) {
|
||||
lwsl_warn("excessive header content\n");
|
||||
return -1;
|
||||
}
|
||||
wsi->u.hdr.ah->data[wsi->u.hdr.ah->pos++] = c;
|
||||
if (c)
|
||||
wsi->u.hdr.ah->frags[wsi->u.hdr.ah->next_frag_index].len++;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int libwebsocket_parse(struct libwebsocket *wsi, unsigned char c)
|
||||
{
|
||||
int n;
|
||||
|
||||
switch (wsi->u.hdr.parser_state) {
|
||||
case WSI_TOKEN_GET_URI:
|
||||
case WSI_TOKEN_POST_URI:
|
||||
case WSI_TOKEN_HOST:
|
||||
case WSI_TOKEN_CONNECTION:
|
||||
case WSI_TOKEN_KEY1:
|
||||
case WSI_TOKEN_KEY2:
|
||||
case WSI_TOKEN_PROTOCOL:
|
||||
case WSI_TOKEN_UPGRADE:
|
||||
case WSI_TOKEN_ORIGIN:
|
||||
case WSI_TOKEN_SWORIGIN:
|
||||
case WSI_TOKEN_DRAFT:
|
||||
case WSI_TOKEN_CHALLENGE:
|
||||
case WSI_TOKEN_KEY:
|
||||
case WSI_TOKEN_VERSION:
|
||||
case WSI_TOKEN_ACCEPT:
|
||||
case WSI_TOKEN_NONCE:
|
||||
case WSI_TOKEN_EXTENSIONS:
|
||||
case WSI_TOKEN_HTTP:
|
||||
case WSI_TOKEN_HTTP_ACCEPT:
|
||||
case WSI_TOKEN_HTTP_IF_MODIFIED_SINCE:
|
||||
case WSI_TOKEN_HTTP_ACCEPT_ENCODING:
|
||||
case WSI_TOKEN_HTTP_ACCEPT_LANGUAGE:
|
||||
case WSI_TOKEN_HTTP_PRAGMA:
|
||||
case WSI_TOKEN_HTTP_CACHE_CONTROL:
|
||||
case WSI_TOKEN_HTTP_AUTHORIZATION:
|
||||
case WSI_TOKEN_HTTP_COOKIE:
|
||||
case WSI_TOKEN_HTTP_CONTENT_LENGTH:
|
||||
case WSI_TOKEN_HTTP_CONTENT_TYPE:
|
||||
case WSI_TOKEN_HTTP_DATE:
|
||||
case WSI_TOKEN_HTTP_RANGE:
|
||||
case WSI_TOKEN_HTTP_REFERER:
|
||||
|
||||
|
||||
lwsl_parser("WSI_TOK_(%d) '%c'\n", wsi->u.hdr.parser_state, c);
|
||||
|
||||
/* collect into malloc'd buffers */
|
||||
/* optional initial space swallow */
|
||||
if (!wsi->u.hdr.ah->frags[wsi->u.hdr.ah->frag_index[
|
||||
wsi->u.hdr.parser_state]].len && c == ' ')
|
||||
break;
|
||||
|
||||
if ((wsi->u.hdr.parser_state != WSI_TOKEN_GET_URI) && (wsi->u.hdr.parser_state != WSI_TOKEN_POST_URI))
|
||||
goto check_eol;
|
||||
|
||||
/* special URI processing... end at space */
|
||||
|
||||
if (c == ' ') {
|
||||
/* enforce starting with / */
|
||||
if (!wsi->u.hdr.ah->frags[wsi->u.hdr.ah->next_frag_index].len)
|
||||
if (issue_char(wsi, '/') < 0)
|
||||
return -1;
|
||||
c = '\0';
|
||||
wsi->u.hdr.parser_state = WSI_TOKEN_SKIPPING;
|
||||
goto spill;
|
||||
}
|
||||
|
||||
/* special URI processing... convert %xx */
|
||||
|
||||
switch (wsi->u.hdr.ues) {
|
||||
case URIES_IDLE:
|
||||
if (c == '%') {
|
||||
wsi->u.hdr.ues = URIES_SEEN_PERCENT;
|
||||
goto swallow;
|
||||
}
|
||||
break;
|
||||
case URIES_SEEN_PERCENT:
|
||||
if (char_to_hex(c) < 0) {
|
||||
/* regurgitate */
|
||||
if (issue_char(wsi, '%') < 0)
|
||||
return -1;
|
||||
wsi->u.hdr.ues = URIES_IDLE;
|
||||
/* continue on to assess c */
|
||||
break;
|
||||
}
|
||||
wsi->u.hdr.esc_stash = c;
|
||||
wsi->u.hdr.ues = URIES_SEEN_PERCENT_H1;
|
||||
goto swallow;
|
||||
|
||||
case URIES_SEEN_PERCENT_H1:
|
||||
if (char_to_hex(c) < 0) {
|
||||
/* regurgitate */
|
||||
issue_char(wsi, '%');
|
||||
wsi->u.hdr.ues = URIES_IDLE;
|
||||
/* regurgitate + assess */
|
||||
if (libwebsocket_parse(wsi, wsi->u.hdr.esc_stash) < 0)
|
||||
return -1;
|
||||
/* continue on to assess c */
|
||||
break;
|
||||
}
|
||||
c = (char_to_hex(wsi->u.hdr.esc_stash) << 4) |
|
||||
char_to_hex(c);
|
||||
wsi->u.hdr.ues = URIES_IDLE;
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
* special URI processing...
|
||||
* convert /.. or /... or /../ etc to /
|
||||
* convert /./ to /
|
||||
* convert // or /// etc to /
|
||||
* leave /.dir or whatever alone
|
||||
*/
|
||||
|
||||
switch (wsi->u.hdr.ups) {
|
||||
case URIPS_IDLE:
|
||||
/* issue the first / always */
|
||||
if (c == '/')
|
||||
wsi->u.hdr.ups = URIPS_SEEN_SLASH;
|
||||
break;
|
||||
case URIPS_SEEN_SLASH:
|
||||
/* swallow subsequent slashes */
|
||||
if (c == '/')
|
||||
goto swallow;
|
||||
/* track and swallow the first . after / */
|
||||
if (c == '.') {
|
||||
wsi->u.hdr.ups = URIPS_SEEN_SLASH_DOT;
|
||||
goto swallow;
|
||||
} else
|
||||
wsi->u.hdr.ups = URIPS_IDLE;
|
||||
break;
|
||||
case URIPS_SEEN_SLASH_DOT:
|
||||
/* swallow second . */
|
||||
if (c == '.') {
|
||||
/*
|
||||
* back up one dir level if possible
|
||||
* safe against header fragmentation because
|
||||
* the method URI can only be in 1 fragment
|
||||
*/
|
||||
if (wsi->u.hdr.ah->frags[wsi->u.hdr.ah->next_frag_index].len > 2) {
|
||||
wsi->u.hdr.ah->pos--;
|
||||
wsi->u.hdr.ah->frags[wsi->u.hdr.ah->next_frag_index].len--;
|
||||
do {
|
||||
wsi->u.hdr.ah->pos--;
|
||||
wsi->u.hdr.ah->frags[wsi->u.hdr.ah->next_frag_index].len--;
|
||||
} while (wsi->u.hdr.ah->frags[wsi->u.hdr.ah->next_frag_index].len > 1 &&
|
||||
wsi->u.hdr.ah->data[wsi->u.hdr.ah->pos] != '/');
|
||||
}
|
||||
wsi->u.hdr.ups = URIPS_SEEN_SLASH_DOT_DOT;
|
||||
goto swallow;
|
||||
}
|
||||
/* change /./ to / */
|
||||
if (c == '/') {
|
||||
wsi->u.hdr.ups = URIPS_SEEN_SLASH;
|
||||
goto swallow;
|
||||
}
|
||||
/* it was like /.dir ... regurgitate the . */
|
||||
wsi->u.hdr.ups = URIPS_IDLE;
|
||||
issue_char(wsi, '.');
|
||||
break;
|
||||
|
||||
case URIPS_SEEN_SLASH_DOT_DOT:
|
||||
/* swallow prior .. chars and any subsequent . */
|
||||
if (c == '.')
|
||||
goto swallow;
|
||||
/* last issued was /, so another / == // */
|
||||
if (c == '/')
|
||||
goto swallow;
|
||||
else /* last we issued was / so SEEN_SLASH */
|
||||
wsi->u.hdr.ups = URIPS_SEEN_SLASH;
|
||||
break;
|
||||
case URIPS_ARGUMENTS:
|
||||
/* leave them alone */
|
||||
break;
|
||||
}
|
||||
|
||||
check_eol:
|
||||
|
||||
/* bail at EOL */
|
||||
if (wsi->u.hdr.parser_state != WSI_TOKEN_CHALLENGE &&
|
||||
c == '\x0d') {
|
||||
c = '\0';
|
||||
wsi->u.hdr.parser_state = WSI_TOKEN_SKIPPING_SAW_CR;
|
||||
lwsl_parser("*\n");
|
||||
}
|
||||
|
||||
if (c == '?') { /* start of URI arguments */
|
||||
/* seal off uri header */
|
||||
wsi->u.hdr.ah->data[wsi->u.hdr.ah->pos++] = '\0';
|
||||
|
||||
/* move to using WSI_TOKEN_HTTP_URI_ARGS */
|
||||
wsi->u.hdr.ah->next_frag_index++;
|
||||
wsi->u.hdr.ah->frags[
|
||||
wsi->u.hdr.ah->next_frag_index].offset =
|
||||
wsi->u.hdr.ah->pos;
|
||||
wsi->u.hdr.ah->frags[
|
||||
wsi->u.hdr.ah->next_frag_index].len = 0;
|
||||
wsi->u.hdr.ah->frags[
|
||||
wsi->u.hdr.ah->next_frag_index].next_frag_index = 0;
|
||||
|
||||
wsi->u.hdr.ah->frag_index[WSI_TOKEN_HTTP_URI_ARGS] =
|
||||
wsi->u.hdr.ah->next_frag_index;
|
||||
|
||||
/* defeat normal uri path processing */
|
||||
wsi->u.hdr.ups = URIPS_ARGUMENTS;
|
||||
goto swallow;
|
||||
}
|
||||
|
||||
spill:
|
||||
if (issue_char(wsi, c) < 0)
|
||||
return -1;
|
||||
swallow:
|
||||
/* per-protocol end of headers management */
|
||||
|
||||
if (wsi->u.hdr.parser_state == WSI_TOKEN_CHALLENGE)
|
||||
goto set_parsing_complete;
|
||||
break;
|
||||
|
||||
/* collecting and checking a name part */
|
||||
case WSI_TOKEN_NAME_PART:
|
||||
lwsl_parser("WSI_TOKEN_NAME_PART '%c'\n", c);
|
||||
|
||||
wsi->u.hdr.lextable_pos =
|
||||
lextable_decode(wsi->u.hdr.lextable_pos, c);
|
||||
|
||||
if (wsi->u.hdr.lextable_pos < 0) {
|
||||
/* this is not a header we know about */
|
||||
if (wsi->u.hdr.ah->frag_index[WSI_TOKEN_GET_URI] || wsi->u.hdr.ah->frag_index[WSI_TOKEN_POST_URI] ||
|
||||
wsi->u.hdr.ah->frag_index[WSI_TOKEN_HTTP]) {
|
||||
/*
|
||||
* altready had the method, no idea what
|
||||
* this crap is, ignore
|
||||
*/
|
||||
wsi->u.hdr.parser_state = WSI_TOKEN_SKIPPING;
|
||||
break;
|
||||
}
|
||||
/*
|
||||
* hm it's an unknown http method in fact,
|
||||
* treat as dangerous
|
||||
*/
|
||||
|
||||
lwsl_info("Unknown method - dropping\n");
|
||||
return -1;
|
||||
}
|
||||
if (lextable[wsi->u.hdr.lextable_pos] < FAIL_CHAR) {
|
||||
|
||||
/* terminal state */
|
||||
|
||||
n = (lextable[wsi->u.hdr.lextable_pos] << 8) | lextable[wsi->u.hdr.lextable_pos + 1];
|
||||
|
||||
lwsl_parser("known hdr %d\n", n);
|
||||
|
||||
if (n == WSI_TOKEN_GET_URI &&
|
||||
wsi->u.hdr.ah->frag_index[WSI_TOKEN_GET_URI]) {
|
||||
lwsl_warn("Duplicated GET\n");
|
||||
return -1;
|
||||
} else if (n == WSI_TOKEN_POST_URI &&
|
||||
wsi->u.hdr.ah->frag_index[WSI_TOKEN_POST_URI]) {
|
||||
lwsl_warn("Duplicated POST\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*
|
||||
* WSORIGIN is protocol equiv to ORIGIN,
|
||||
* JWebSocket likes to send it, map to ORIGIN
|
||||
*/
|
||||
if (n == WSI_TOKEN_SWORIGIN)
|
||||
n = WSI_TOKEN_ORIGIN;
|
||||
|
||||
wsi->u.hdr.parser_state = (enum lws_token_indexes)
|
||||
(WSI_TOKEN_GET_URI + n);
|
||||
if (wsi->u.hdr.parser_state == WSI_TOKEN_CHALLENGE)
|
||||
goto set_parsing_complete;
|
||||
|
||||
goto start_fragment;
|
||||
}
|
||||
break;
|
||||
|
||||
start_fragment:
|
||||
wsi->u.hdr.ah->next_frag_index++;
|
||||
if (wsi->u.hdr.ah->next_frag_index ==
|
||||
sizeof(wsi->u.hdr.ah->frags) /
|
||||
sizeof(wsi->u.hdr.ah->frags[0])) {
|
||||
lwsl_warn("More hdr frags than we can deal with\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
wsi->u.hdr.ah->frags[wsi->u.hdr.ah->next_frag_index].offset =
|
||||
wsi->u.hdr.ah->pos;
|
||||
wsi->u.hdr.ah->frags[wsi->u.hdr.ah->next_frag_index].len = 0;
|
||||
wsi->u.hdr.ah->frags[
|
||||
wsi->u.hdr.ah->next_frag_index].next_frag_index = 0;
|
||||
|
||||
n = wsi->u.hdr.ah->frag_index[wsi->u.hdr.parser_state];
|
||||
if (!n) { /* first fragment */
|
||||
wsi->u.hdr.ah->frag_index[wsi->u.hdr.parser_state] =
|
||||
wsi->u.hdr.ah->next_frag_index;
|
||||
break;
|
||||
}
|
||||
/* continuation */
|
||||
while (wsi->u.hdr.ah->frags[n].next_frag_index)
|
||||
n = wsi->u.hdr.ah->frags[n].next_frag_index;
|
||||
wsi->u.hdr.ah->frags[n].next_frag_index =
|
||||
wsi->u.hdr.ah->next_frag_index;
|
||||
|
||||
if (wsi->u.hdr.ah->pos == sizeof(wsi->u.hdr.ah->data)) {
|
||||
lwsl_warn("excessive header content\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
wsi->u.hdr.ah->data[wsi->u.hdr.ah->pos++] = ' ';
|
||||
wsi->u.hdr.ah->frags[wsi->u.hdr.ah->next_frag_index].len++;
|
||||
break;
|
||||
|
||||
/* skipping arg part of a name we didn't recognize */
|
||||
case WSI_TOKEN_SKIPPING:
|
||||
lwsl_parser("WSI_TOKEN_SKIPPING '%c'\n", c);
|
||||
|
||||
if (c == '\x0d')
|
||||
wsi->u.hdr.parser_state = WSI_TOKEN_SKIPPING_SAW_CR;
|
||||
break;
|
||||
|
||||
case WSI_TOKEN_SKIPPING_SAW_CR:
|
||||
lwsl_parser("WSI_TOKEN_SKIPPING_SAW_CR '%c'\n", c);
|
||||
if (c == '\x0a') {
|
||||
wsi->u.hdr.parser_state = WSI_TOKEN_NAME_PART;
|
||||
wsi->u.hdr.lextable_pos = 0;
|
||||
} else
|
||||
wsi->u.hdr.parser_state = WSI_TOKEN_SKIPPING;
|
||||
break;
|
||||
/* we're done, ignore anything else */
|
||||
|
||||
case WSI_PARSING_COMPLETE:
|
||||
lwsl_parser("WSI_PARSING_COMPLETE '%c'\n", c);
|
||||
break;
|
||||
|
||||
default: /* keep gcc happy */
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
set_parsing_complete:
|
||||
|
||||
if (lws_hdr_total_length(wsi, WSI_TOKEN_UPGRADE)) {
|
||||
if (lws_hdr_total_length(wsi, WSI_TOKEN_VERSION))
|
||||
wsi->ietf_spec_revision =
|
||||
atoi(lws_hdr_simple_ptr(wsi, WSI_TOKEN_VERSION));
|
||||
|
||||
lwsl_parser("v%02d hdrs completed\n", wsi->ietf_spec_revision);
|
||||
}
|
||||
wsi->u.hdr.parser_state = WSI_PARSING_COMPLETE;
|
||||
wsi->hdr_parsing_completed = 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* lws_frame_is_binary: true if the current frame was sent in binary mode
|
||||
*
|
||||
* @wsi: the connection we are inquiring about
|
||||
*
|
||||
* This is intended to be called from the LWS_CALLBACK_RECEIVE callback if
|
||||
* it's interested to see if the frame it's dealing with was sent in binary
|
||||
* mode.
|
||||
*/
|
||||
|
||||
LWS_VISIBLE int lws_frame_is_binary(struct libwebsocket *wsi)
|
||||
{
|
||||
return wsi->u.ws.frame_is_binary;
|
||||
}
|
||||
|
||||
int
|
||||
libwebsocket_rx_sm(struct libwebsocket *wsi, unsigned char c)
|
||||
{
|
||||
int n;
|
||||
struct lws_tokens eff_buf;
|
||||
int ret = 0;
|
||||
|
||||
switch (wsi->lws_rx_parse_state) {
|
||||
case LWS_RXPS_NEW:
|
||||
|
||||
switch (wsi->ietf_spec_revision) {
|
||||
case 13:
|
||||
/*
|
||||
* no prepended frame key any more
|
||||
*/
|
||||
wsi->u.ws.all_zero_nonce = 1;
|
||||
goto handle_first;
|
||||
|
||||
default:
|
||||
lwsl_warn("lws_rx_sm: unknown spec version %d\n",
|
||||
wsi->ietf_spec_revision);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case LWS_RXPS_04_MASK_NONCE_1:
|
||||
wsi->u.ws.frame_masking_nonce_04[1] = c;
|
||||
if (c)
|
||||
wsi->u.ws.all_zero_nonce = 0;
|
||||
wsi->lws_rx_parse_state = LWS_RXPS_04_MASK_NONCE_2;
|
||||
break;
|
||||
case LWS_RXPS_04_MASK_NONCE_2:
|
||||
wsi->u.ws.frame_masking_nonce_04[2] = c;
|
||||
if (c)
|
||||
wsi->u.ws.all_zero_nonce = 0;
|
||||
wsi->lws_rx_parse_state = LWS_RXPS_04_MASK_NONCE_3;
|
||||
break;
|
||||
case LWS_RXPS_04_MASK_NONCE_3:
|
||||
wsi->u.ws.frame_masking_nonce_04[3] = c;
|
||||
if (c)
|
||||
wsi->u.ws.all_zero_nonce = 0;
|
||||
|
||||
/*
|
||||
* start from the zero'th byte in the XOR key buffer since
|
||||
* this is the start of a frame with a new key
|
||||
*/
|
||||
|
||||
wsi->u.ws.frame_mask_index = 0;
|
||||
|
||||
wsi->lws_rx_parse_state = LWS_RXPS_04_FRAME_HDR_1;
|
||||
break;
|
||||
|
||||
/*
|
||||
* 04 logical framing from the spec (all this is masked when incoming
|
||||
* and has to be unmasked)
|
||||
*
|
||||
* We ignore the possibility of extension data because we don't
|
||||
* negotiate any extensions at the moment.
|
||||
*
|
||||
* 0 1 2 3
|
||||
* 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
|
||||
* +-+-+-+-+-------+-+-------------+-------------------------------+
|
||||
* |F|R|R|R| opcode|R| Payload len | Extended payload length |
|
||||
* |I|S|S|S| (4) |S| (7) | (16/63) |
|
||||
* |N|V|V|V| |V| | (if payload len==126/127) |
|
||||
* | |1|2|3| |4| | |
|
||||
* +-+-+-+-+-------+-+-------------+ - - - - - - - - - - - - - - - +
|
||||
* | Extended payload length continued, if payload len == 127 |
|
||||
* + - - - - - - - - - - - - - - - +-------------------------------+
|
||||
* | | Extension data |
|
||||
* +-------------------------------+ - - - - - - - - - - - - - - - +
|
||||
* : :
|
||||
* +---------------------------------------------------------------+
|
||||
* : Application data :
|
||||
* +---------------------------------------------------------------+
|
||||
*
|
||||
* We pass payload through to userland as soon as we get it, ignoring
|
||||
* FIN. It's up to userland to buffer it up if it wants to see a
|
||||
* whole unfragmented block of the original size (which may be up to
|
||||
* 2^63 long!)
|
||||
*/
|
||||
|
||||
case LWS_RXPS_04_FRAME_HDR_1:
|
||||
handle_first:
|
||||
|
||||
wsi->u.ws.opcode = c & 0xf;
|
||||
wsi->u.ws.rsv = c & 0x70;
|
||||
wsi->u.ws.final = !!((c >> 7) & 1);
|
||||
|
||||
switch (wsi->u.ws.opcode) {
|
||||
case LWS_WS_OPCODE_07__TEXT_FRAME:
|
||||
case LWS_WS_OPCODE_07__BINARY_FRAME:
|
||||
wsi->u.ws.frame_is_binary =
|
||||
wsi->u.ws.opcode == LWS_WS_OPCODE_07__BINARY_FRAME;
|
||||
break;
|
||||
}
|
||||
wsi->lws_rx_parse_state = LWS_RXPS_04_FRAME_HDR_LEN;
|
||||
break;
|
||||
|
||||
case LWS_RXPS_04_FRAME_HDR_LEN:
|
||||
|
||||
wsi->u.ws.this_frame_masked = !!(c & 0x80);
|
||||
|
||||
switch (c & 0x7f) {
|
||||
case 126:
|
||||
/* control frames are not allowed to have big lengths */
|
||||
if (wsi->u.ws.opcode & 8)
|
||||
goto illegal_ctl_length;
|
||||
|
||||
wsi->lws_rx_parse_state = LWS_RXPS_04_FRAME_HDR_LEN16_2;
|
||||
break;
|
||||
case 127:
|
||||
/* control frames are not allowed to have big lengths */
|
||||
if (wsi->u.ws.opcode & 8)
|
||||
goto illegal_ctl_length;
|
||||
|
||||
wsi->lws_rx_parse_state = LWS_RXPS_04_FRAME_HDR_LEN64_8;
|
||||
break;
|
||||
default:
|
||||
wsi->u.ws.rx_packet_length = c & 0x7f;
|
||||
if (wsi->u.ws.this_frame_masked)
|
||||
wsi->lws_rx_parse_state =
|
||||
LWS_RXPS_07_COLLECT_FRAME_KEY_1;
|
||||
else
|
||||
if (wsi->u.ws.rx_packet_length)
|
||||
wsi->lws_rx_parse_state =
|
||||
LWS_RXPS_PAYLOAD_UNTIL_LENGTH_EXHAUSTED;
|
||||
else {
|
||||
wsi->lws_rx_parse_state = LWS_RXPS_NEW;
|
||||
goto spill;
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case LWS_RXPS_04_FRAME_HDR_LEN16_2:
|
||||
wsi->u.ws.rx_packet_length = c << 8;
|
||||
wsi->lws_rx_parse_state = LWS_RXPS_04_FRAME_HDR_LEN16_1;
|
||||
break;
|
||||
|
||||
case LWS_RXPS_04_FRAME_HDR_LEN16_1:
|
||||
wsi->u.ws.rx_packet_length |= c;
|
||||
if (wsi->u.ws.this_frame_masked)
|
||||
wsi->lws_rx_parse_state =
|
||||
LWS_RXPS_07_COLLECT_FRAME_KEY_1;
|
||||
else
|
||||
wsi->lws_rx_parse_state =
|
||||
LWS_RXPS_PAYLOAD_UNTIL_LENGTH_EXHAUSTED;
|
||||
break;
|
||||
|
||||
case LWS_RXPS_04_FRAME_HDR_LEN64_8:
|
||||
if (c & 0x80) {
|
||||
lwsl_warn("b63 of length must be zero\n");
|
||||
/* kill the connection */
|
||||
return -1;
|
||||
}
|
||||
#if defined __LP64__
|
||||
wsi->u.ws.rx_packet_length = ((size_t)c) << 56;
|
||||
#else
|
||||
wsi->u.ws.rx_packet_length = 0;
|
||||
#endif
|
||||
wsi->lws_rx_parse_state = LWS_RXPS_04_FRAME_HDR_LEN64_7;
|
||||
break;
|
||||
|
||||
case LWS_RXPS_04_FRAME_HDR_LEN64_7:
|
||||
#if defined __LP64__
|
||||
wsi->u.ws.rx_packet_length |= ((size_t)c) << 48;
|
||||
#endif
|
||||
wsi->lws_rx_parse_state = LWS_RXPS_04_FRAME_HDR_LEN64_6;
|
||||
break;
|
||||
|
||||
case LWS_RXPS_04_FRAME_HDR_LEN64_6:
|
||||
#if defined __LP64__
|
||||
wsi->u.ws.rx_packet_length |= ((size_t)c) << 40;
|
||||
#endif
|
||||
wsi->lws_rx_parse_state = LWS_RXPS_04_FRAME_HDR_LEN64_5;
|
||||
break;
|
||||
|
||||
case LWS_RXPS_04_FRAME_HDR_LEN64_5:
|
||||
#if defined __LP64__
|
||||
wsi->u.ws.rx_packet_length |= ((size_t)c) << 32;
|
||||
#endif
|
||||
wsi->lws_rx_parse_state = LWS_RXPS_04_FRAME_HDR_LEN64_4;
|
||||
break;
|
||||
|
||||
case LWS_RXPS_04_FRAME_HDR_LEN64_4:
|
||||
wsi->u.ws.rx_packet_length |= ((size_t)c) << 24;
|
||||
wsi->lws_rx_parse_state = LWS_RXPS_04_FRAME_HDR_LEN64_3;
|
||||
break;
|
||||
|
||||
case LWS_RXPS_04_FRAME_HDR_LEN64_3:
|
||||
wsi->u.ws.rx_packet_length |= ((size_t)c) << 16;
|
||||
wsi->lws_rx_parse_state = LWS_RXPS_04_FRAME_HDR_LEN64_2;
|
||||
break;
|
||||
|
||||
case LWS_RXPS_04_FRAME_HDR_LEN64_2:
|
||||
wsi->u.ws.rx_packet_length |= ((size_t)c) << 8;
|
||||
wsi->lws_rx_parse_state = LWS_RXPS_04_FRAME_HDR_LEN64_1;
|
||||
break;
|
||||
|
||||
case LWS_RXPS_04_FRAME_HDR_LEN64_1:
|
||||
wsi->u.ws.rx_packet_length |= ((size_t)c);
|
||||
if (wsi->u.ws.this_frame_masked)
|
||||
wsi->lws_rx_parse_state =
|
||||
LWS_RXPS_07_COLLECT_FRAME_KEY_1;
|
||||
else
|
||||
wsi->lws_rx_parse_state =
|
||||
LWS_RXPS_PAYLOAD_UNTIL_LENGTH_EXHAUSTED;
|
||||
break;
|
||||
|
||||
case LWS_RXPS_07_COLLECT_FRAME_KEY_1:
|
||||
wsi->u.ws.frame_masking_nonce_04[0] = c;
|
||||
if (c)
|
||||
wsi->u.ws.all_zero_nonce = 0;
|
||||
wsi->lws_rx_parse_state = LWS_RXPS_07_COLLECT_FRAME_KEY_2;
|
||||
break;
|
||||
|
||||
case LWS_RXPS_07_COLLECT_FRAME_KEY_2:
|
||||
wsi->u.ws.frame_masking_nonce_04[1] = c;
|
||||
if (c)
|
||||
wsi->u.ws.all_zero_nonce = 0;
|
||||
wsi->lws_rx_parse_state = LWS_RXPS_07_COLLECT_FRAME_KEY_3;
|
||||
break;
|
||||
|
||||
case LWS_RXPS_07_COLLECT_FRAME_KEY_3:
|
||||
wsi->u.ws.frame_masking_nonce_04[2] = c;
|
||||
if (c)
|
||||
wsi->u.ws.all_zero_nonce = 0;
|
||||
wsi->lws_rx_parse_state = LWS_RXPS_07_COLLECT_FRAME_KEY_4;
|
||||
break;
|
||||
|
||||
case LWS_RXPS_07_COLLECT_FRAME_KEY_4:
|
||||
wsi->u.ws.frame_masking_nonce_04[3] = c;
|
||||
if (c)
|
||||
wsi->u.ws.all_zero_nonce = 0;
|
||||
wsi->lws_rx_parse_state =
|
||||
LWS_RXPS_PAYLOAD_UNTIL_LENGTH_EXHAUSTED;
|
||||
wsi->u.ws.frame_mask_index = 0;
|
||||
if (wsi->u.ws.rx_packet_length == 0) {
|
||||
wsi->lws_rx_parse_state = LWS_RXPS_NEW;
|
||||
goto spill;
|
||||
}
|
||||
break;
|
||||
|
||||
|
||||
case LWS_RXPS_PAYLOAD_UNTIL_LENGTH_EXHAUSTED:
|
||||
|
||||
if (!wsi->u.ws.rx_user_buffer)
|
||||
lwsl_err("NULL user buffer...\n");
|
||||
|
||||
if (wsi->u.ws.all_zero_nonce)
|
||||
wsi->u.ws.rx_user_buffer[LWS_SEND_BUFFER_PRE_PADDING +
|
||||
(wsi->u.ws.rx_user_buffer_head++)] = c;
|
||||
else
|
||||
wsi->u.ws.rx_user_buffer[LWS_SEND_BUFFER_PRE_PADDING +
|
||||
(wsi->u.ws.rx_user_buffer_head++)] =
|
||||
c ^ wsi->u.ws.frame_masking_nonce_04[
|
||||
(wsi->u.ws.frame_mask_index++) & 3];
|
||||
|
||||
if (--wsi->u.ws.rx_packet_length == 0) {
|
||||
/* spill because we have the whole frame */
|
||||
wsi->lws_rx_parse_state = LWS_RXPS_NEW;
|
||||
goto spill;
|
||||
}
|
||||
|
||||
/*
|
||||
* if there's no protocol max frame size given, we are
|
||||
* supposed to default to LWS_MAX_SOCKET_IO_BUF
|
||||
*/
|
||||
|
||||
if (!wsi->protocol->rx_buffer_size &&
|
||||
wsi->u.ws.rx_user_buffer_head !=
|
||||
LWS_MAX_SOCKET_IO_BUF)
|
||||
break;
|
||||
else
|
||||
if (wsi->protocol->rx_buffer_size &&
|
||||
wsi->u.ws.rx_user_buffer_head !=
|
||||
wsi->protocol->rx_buffer_size)
|
||||
break;
|
||||
|
||||
/* spill because we filled our rx buffer */
|
||||
spill:
|
||||
/*
|
||||
* is this frame a control packet we should take care of at this
|
||||
* layer? If so service it and hide it from the user callback
|
||||
*/
|
||||
|
||||
lwsl_parser("spill on %s\n", wsi->protocol->name);
|
||||
|
||||
switch (wsi->u.ws.opcode) {
|
||||
case LWS_WS_OPCODE_07__CLOSE:
|
||||
/* is this an acknowledgement of our close? */
|
||||
if (wsi->state == WSI_STATE_AWAITING_CLOSE_ACK) {
|
||||
/*
|
||||
* fine he has told us he is closing too, let's
|
||||
* finish our close
|
||||
*/
|
||||
lwsl_parser("seen client close ack\n");
|
||||
return -1;
|
||||
}
|
||||
lwsl_parser("server sees client close packet\n");
|
||||
/* parrot the close packet payload back */
|
||||
n = libwebsocket_write(wsi, (unsigned char *)
|
||||
&wsi->u.ws.rx_user_buffer[
|
||||
LWS_SEND_BUFFER_PRE_PADDING],
|
||||
wsi->u.ws.rx_user_buffer_head,
|
||||
LWS_WRITE_CLOSE);
|
||||
if (n < 0)
|
||||
lwsl_info("write of close ack failed %d\n", n);
|
||||
wsi->state = WSI_STATE_RETURNED_CLOSE_ALREADY;
|
||||
/* close the connection */
|
||||
return -1;
|
||||
|
||||
case LWS_WS_OPCODE_07__PING:
|
||||
lwsl_info("received %d byte ping, sending pong\n",
|
||||
wsi->u.ws.rx_user_buffer_head);
|
||||
lwsl_hexdump(&wsi->u.ws.rx_user_buffer[
|
||||
LWS_SEND_BUFFER_PRE_PADDING],
|
||||
wsi->u.ws.rx_user_buffer_head);
|
||||
/* parrot the ping packet payload back as a pong */
|
||||
n = libwebsocket_write(wsi, (unsigned char *)
|
||||
&wsi->u.ws.rx_user_buffer[LWS_SEND_BUFFER_PRE_PADDING],
|
||||
wsi->u.ws.rx_user_buffer_head, LWS_WRITE_PONG);
|
||||
if (n < 0)
|
||||
return -1;
|
||||
/* ... then just drop it */
|
||||
wsi->u.ws.rx_user_buffer_head = 0;
|
||||
return 0;
|
||||
|
||||
case LWS_WS_OPCODE_07__PONG:
|
||||
/* ... then just drop it */
|
||||
wsi->u.ws.rx_user_buffer_head = 0;
|
||||
return 0;
|
||||
|
||||
case LWS_WS_OPCODE_07__TEXT_FRAME:
|
||||
case LWS_WS_OPCODE_07__BINARY_FRAME:
|
||||
case LWS_WS_OPCODE_07__CONTINUATION:
|
||||
break;
|
||||
|
||||
default:
|
||||
lwsl_parser("passing opc %x up to exts\n",
|
||||
wsi->u.ws.opcode);
|
||||
/*
|
||||
* It's something special we can't understand here.
|
||||
* Pass the payload up to the extension's parsing
|
||||
* state machine.
|
||||
*/
|
||||
|
||||
eff_buf.token = &wsi->u.ws.rx_user_buffer[
|
||||
LWS_SEND_BUFFER_PRE_PADDING];
|
||||
eff_buf.token_len = wsi->u.ws.rx_user_buffer_head;
|
||||
|
||||
if (lws_ext_callback_for_each_active(wsi,
|
||||
LWS_EXT_CALLBACK_EXTENDED_PAYLOAD_RX,
|
||||
&eff_buf, 0) <= 0) /* not handle or fail */
|
||||
lwsl_ext("ext opc opcode 0x%x unknown\n",
|
||||
wsi->u.ws.opcode);
|
||||
|
||||
wsi->u.ws.rx_user_buffer_head = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* No it's real payload, pass it up to the user callback.
|
||||
* It's nicely buffered with the pre-padding taken care of
|
||||
* so it can be sent straight out again using libwebsocket_write
|
||||
*/
|
||||
|
||||
eff_buf.token = &wsi->u.ws.rx_user_buffer[
|
||||
LWS_SEND_BUFFER_PRE_PADDING];
|
||||
eff_buf.token_len = wsi->u.ws.rx_user_buffer_head;
|
||||
|
||||
if (lws_ext_callback_for_each_active(wsi,
|
||||
LWS_EXT_CALLBACK_PAYLOAD_RX, &eff_buf, 0) < 0)
|
||||
return -1;
|
||||
|
||||
if (eff_buf.token_len > 0) {
|
||||
eff_buf.token[eff_buf.token_len] = '\0';
|
||||
|
||||
if (wsi->protocol->callback)
|
||||
ret = user_callback_handle_rxflow(
|
||||
wsi->protocol->callback,
|
||||
wsi->protocol->owning_server,
|
||||
wsi, LWS_CALLBACK_RECEIVE,
|
||||
wsi->user_space,
|
||||
eff_buf.token,
|
||||
eff_buf.token_len);
|
||||
else
|
||||
lwsl_err("No callback on payload spill!\n");
|
||||
}
|
||||
|
||||
wsi->u.ws.rx_user_buffer_head = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
return ret;
|
||||
|
||||
illegal_ctl_length:
|
||||
|
||||
lwsl_warn("Control frame with xtended length is illegal\n");
|
||||
/* kill the connection */
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* libwebsockets_remaining_packet_payload() - Bytes to come before "overall"
|
||||
* rx packet is complete
|
||||
* @wsi: Websocket instance (available from user callback)
|
||||
*
|
||||
* This function is intended to be called from the callback if the
|
||||
* user code is interested in "complete packets" from the client.
|
||||
* libwebsockets just passes through payload as it comes and issues a buffer
|
||||
* additionally when it hits a built-in limit. The LWS_CALLBACK_RECEIVE
|
||||
* callback handler can use this API to find out if the buffer it has just
|
||||
* been given is the last piece of a "complete packet" from the client --
|
||||
* when that is the case libwebsockets_remaining_packet_payload() will return
|
||||
* 0.
|
||||
*
|
||||
* Many protocols won't care becuse their packets are always small.
|
||||
*/
|
||||
|
||||
LWS_VISIBLE size_t
|
||||
libwebsockets_remaining_packet_payload(struct libwebsocket *wsi)
|
||||
{
|
||||
return wsi->u.ws.rx_packet_length;
|
||||
}
|
||||
@@ -0,0 +1,239 @@
|
||||
/*
|
||||
* libwebsockets - small server side websockets and web server implementation
|
||||
*
|
||||
* Copyright (C) 2010-2014 Andy Green <[email protected]>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation:
|
||||
* version 2.1 of the License.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
||||
* MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#include "private-libwebsockets.h"
|
||||
|
||||
int
|
||||
insert_wsi_socket_into_fds(struct libwebsocket_context *context,
|
||||
struct libwebsocket *wsi)
|
||||
{
|
||||
struct libwebsocket_pollargs pa = { wsi->sock, LWS_POLLIN, 0 };
|
||||
|
||||
if (context->fds_count >= context->max_fds) {
|
||||
lwsl_err("Too many fds (%d)\n", context->max_fds);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (wsi->sock >= context->max_fds) {
|
||||
lwsl_err("Socket fd %d is too high (%d)\n",
|
||||
wsi->sock, context->max_fds);
|
||||
return 1;
|
||||
}
|
||||
|
||||
assert(wsi);
|
||||
assert(wsi->sock >= 0);
|
||||
|
||||
lwsl_info("insert_wsi_socket_into_fds: wsi=%p, sock=%d, fds pos=%d\n",
|
||||
wsi, wsi->sock, context->fds_count);
|
||||
|
||||
context->protocols[0].callback(context, wsi,
|
||||
LWS_CALLBACK_LOCK_POLL,
|
||||
wsi->user_space, (void *) &pa, 0);
|
||||
|
||||
context->lws_lookup[wsi->sock] = wsi;
|
||||
wsi->position_in_fds_table = context->fds_count;
|
||||
context->fds[context->fds_count].fd = wsi->sock;
|
||||
context->fds[context->fds_count].events = LWS_POLLIN;
|
||||
|
||||
lws_plat_insert_socket_into_fds(context, wsi);
|
||||
|
||||
/* external POLL support via protocol 0 */
|
||||
context->protocols[0].callback(context, wsi,
|
||||
LWS_CALLBACK_ADD_POLL_FD,
|
||||
wsi->user_space, (void *) &pa, 0);
|
||||
|
||||
context->protocols[0].callback(context, wsi,
|
||||
LWS_CALLBACK_UNLOCK_POLL,
|
||||
wsi->user_space, (void *)&pa, 0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
remove_wsi_socket_from_fds(struct libwebsocket_context *context,
|
||||
struct libwebsocket *wsi)
|
||||
{
|
||||
int m;
|
||||
struct libwebsocket_pollargs pa = { wsi->sock, 0, 0 };
|
||||
|
||||
lws_libev_io(context, wsi, LWS_EV_STOP | LWS_EV_READ | LWS_EV_WRITE);
|
||||
|
||||
if (!--context->fds_count) {
|
||||
context->protocols[0].callback(context, wsi,
|
||||
LWS_CALLBACK_LOCK_POLL,
|
||||
wsi->user_space, (void *) &pa, 0);
|
||||
goto do_ext;
|
||||
}
|
||||
|
||||
if (wsi->sock > context->max_fds) {
|
||||
lwsl_err("Socket fd %d too high (%d)\n",
|
||||
wsi->sock, context->max_fds);
|
||||
return 1;
|
||||
}
|
||||
|
||||
lwsl_info("%s: wsi=%p, sock=%d, fds pos=%d\n", __func__,
|
||||
wsi, wsi->sock, wsi->position_in_fds_table);
|
||||
|
||||
context->protocols[0].callback(context, wsi,
|
||||
LWS_CALLBACK_LOCK_POLL,
|
||||
wsi->user_space, (void *)&pa, 0);
|
||||
|
||||
m = wsi->position_in_fds_table; /* replace the contents for this */
|
||||
|
||||
/* have the last guy take up the vacant slot */
|
||||
context->fds[m] = context->fds[context->fds_count];
|
||||
|
||||
lws_plat_delete_socket_from_fds(context, wsi, m);
|
||||
|
||||
/*
|
||||
* end guy's fds_lookup entry remains unchanged
|
||||
* (still same fd pointing to same wsi)
|
||||
*/
|
||||
/* end guy's "position in fds table" changed */
|
||||
context->lws_lookup[context->fds[context->fds_count].fd]->
|
||||
position_in_fds_table = m;
|
||||
/* deletion guy's lws_lookup entry needs nuking */
|
||||
context->lws_lookup[wsi->sock] = NULL;
|
||||
/* removed wsi has no position any more */
|
||||
wsi->position_in_fds_table = -1;
|
||||
|
||||
do_ext:
|
||||
/* remove also from external POLL support via protocol 0 */
|
||||
if (wsi->sock) {
|
||||
context->protocols[0].callback(context, wsi,
|
||||
LWS_CALLBACK_DEL_POLL_FD, wsi->user_space,
|
||||
(void *) &pa, 0);
|
||||
}
|
||||
context->protocols[0].callback(context, wsi,
|
||||
LWS_CALLBACK_UNLOCK_POLL,
|
||||
wsi->user_space, (void *) &pa, 0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
lws_change_pollfd(struct libwebsocket *wsi, int _and, int _or)
|
||||
{
|
||||
struct libwebsocket_context *context = wsi->protocol->owning_server;
|
||||
int tid;
|
||||
int sampled_tid;
|
||||
struct libwebsocket_pollfd *pfd;
|
||||
struct libwebsocket_pollargs pa;
|
||||
|
||||
pfd = &context->fds[wsi->position_in_fds_table];
|
||||
pa.fd = wsi->sock;
|
||||
|
||||
context->protocols[0].callback(context, wsi,
|
||||
LWS_CALLBACK_LOCK_POLL, wsi->user_space, (void *) &pa, 0);
|
||||
|
||||
pa.prev_events = pfd->events;
|
||||
pa.events = pfd->events = (pfd->events & ~_and) | _or;
|
||||
|
||||
context->protocols[0].callback(context, wsi,
|
||||
LWS_CALLBACK_CHANGE_MODE_POLL_FD,
|
||||
wsi->user_space, (void *) &pa, 0);
|
||||
|
||||
/*
|
||||
* if we changed something in this pollfd...
|
||||
* ... and we're running in a different thread context
|
||||
* than the service thread...
|
||||
* ... and the service thread is waiting ...
|
||||
* then cancel it to force a restart with our changed events
|
||||
*/
|
||||
if (pa.prev_events != pa.events) {
|
||||
|
||||
if (lws_plat_change_pollfd(context, wsi, pfd)) {
|
||||
lwsl_info("%s failed\n", __func__);
|
||||
return 1;
|
||||
}
|
||||
|
||||
sampled_tid = context->service_tid;
|
||||
if (sampled_tid) {
|
||||
tid = context->protocols[0].callback(context, NULL,
|
||||
LWS_CALLBACK_GET_THREAD_ID, NULL, NULL, 0);
|
||||
if (tid != sampled_tid)
|
||||
libwebsocket_cancel_service(context);
|
||||
}
|
||||
}
|
||||
|
||||
context->protocols[0].callback(context, wsi,
|
||||
LWS_CALLBACK_UNLOCK_POLL, wsi->user_space, (void *) &pa, 0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* libwebsocket_callback_on_writable() - Request a callback when this socket
|
||||
* becomes able to be written to without
|
||||
* blocking
|
||||
*
|
||||
* @context: libwebsockets context
|
||||
* @wsi: Websocket connection instance to get callback for
|
||||
*/
|
||||
|
||||
LWS_VISIBLE int
|
||||
libwebsocket_callback_on_writable(struct libwebsocket_context *context,
|
||||
struct libwebsocket *wsi)
|
||||
{
|
||||
if (lws_ext_callback_for_each_active(wsi,
|
||||
LWS_EXT_CALLBACK_REQUEST_ON_WRITEABLE, NULL, 0))
|
||||
return 1;
|
||||
|
||||
if (wsi->position_in_fds_table < 0) {
|
||||
lwsl_err("%s: failed to find socket %d\n", __func__, wsi->sock);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (lws_change_pollfd(wsi, 0, LWS_POLLOUT))
|
||||
return -1;
|
||||
|
||||
lws_libev_io(context, wsi, LWS_EV_START | LWS_EV_WRITE);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* libwebsocket_callback_on_writable_all_protocol() - Request a callback for
|
||||
* all connections using the given protocol when it
|
||||
* becomes possible to write to each socket without
|
||||
* blocking in turn.
|
||||
*
|
||||
* @protocol: Protocol whose connections will get callbacks
|
||||
*/
|
||||
|
||||
LWS_VISIBLE int
|
||||
libwebsocket_callback_on_writable_all_protocol(
|
||||
const struct libwebsocket_protocols *protocol)
|
||||
{
|
||||
struct libwebsocket_context *context = protocol->owning_server;
|
||||
int n;
|
||||
struct libwebsocket *wsi;
|
||||
|
||||
for (n = 0; n < context->fds_count; n++) {
|
||||
wsi = context->lws_lookup[context->fds[n].fd];
|
||||
if (!wsi)
|
||||
continue;
|
||||
if (wsi->protocol == protocol)
|
||||
libwebsocket_callback_on_writable(context, wsi);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,917 @@
|
||||
/*
|
||||
* libwebsockets - small server side websockets and web server implementation
|
||||
*
|
||||
* Copyright (C) 2010 - 2013 Andy Green <[email protected]>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation:
|
||||
* version 2.1 of the License.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
||||
* MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#include "build.h"
|
||||
|
||||
/* The Libwebsocket version */
|
||||
#define LWS_LIBRARY_VERSION "1.3"
|
||||
|
||||
/* The current git commit hash that we're building from */
|
||||
#define LWS_BUILD_HASH "c11b847"
|
||||
|
||||
|
||||
/* System introspection configs */
|
||||
#ifdef CMAKE_BUILD
|
||||
#include "lws_config.h"
|
||||
#else
|
||||
#if HOST_OS == OS_WINDOWS
|
||||
#define inline __inline
|
||||
#else /* not WIN32 */
|
||||
#include "config.h"
|
||||
|
||||
#endif /* not WIN32 */
|
||||
#endif /* not CMAKE */
|
||||
|
||||
#ifdef HAVE_SYS_TYPES_H
|
||||
#include <sys/types.h>
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
#include <ctype.h>
|
||||
#include <limits.h>
|
||||
#include <stdarg.h>
|
||||
|
||||
#ifdef HAVE_SYS_STAT_H
|
||||
#include <sys/stat.h>
|
||||
#endif
|
||||
|
||||
#if defined(WIN32) || defined(_WIN32)
|
||||
#define LWS_NO_DAEMONIZE
|
||||
#define LWS_ERRNO WSAGetLastError()
|
||||
#define LWS_EAGAIN WSAEWOULDBLOCK
|
||||
#define LWS_EALREADY WSAEALREADY
|
||||
#define LWS_EINPROGRESS WSAEINPROGRESS
|
||||
#define LWS_EINTR WSAEINTR
|
||||
#define LWS_EISCONN WSAEISCONN
|
||||
#define LWS_EWOULDBLOCK WSAEWOULDBLOCK
|
||||
#define LWS_POLLHUP (FD_CLOSE)
|
||||
#define LWS_POLLIN (FD_READ | FD_ACCEPT)
|
||||
#define LWS_POLLOUT (FD_WRITE)
|
||||
#define MSG_NOSIGNAL 0
|
||||
#define SHUT_RDWR SD_BOTH
|
||||
#define SOL_TCP IPPROTO_TCP
|
||||
|
||||
#define compatible_close(fd) closesocket(fd)
|
||||
#define compatible_file_close(fd) CloseHandle(fd)
|
||||
#define compatible_file_seek_cur(fd, offset) SetFilePointer(fd, offset, NULL, FILE_CURRENT)
|
||||
#define compatible_file_read(amount, fd, buf, len) {\
|
||||
DWORD _amount; \
|
||||
if (!ReadFile(fd, buf, len, &_amount, NULL)) \
|
||||
amount = -1; \
|
||||
else \
|
||||
amount = _amount; \
|
||||
}
|
||||
#define lws_set_blocking_send(wsi) wsi->sock_send_blocking = TRUE
|
||||
#include <winsock2.h>
|
||||
#include <windows.h>
|
||||
#include <tchar.h>
|
||||
#ifdef HAVE_IN6ADDR_H
|
||||
#include <in6addr.h>
|
||||
#endif
|
||||
#include <mstcpip.h>
|
||||
|
||||
#ifndef __func__
|
||||
#define __func__ __FUNCTION__
|
||||
#endif
|
||||
|
||||
#ifdef _WIN32_WCE
|
||||
#define vsnprintf _vsnprintf
|
||||
#endif
|
||||
|
||||
#define LWS_INVALID_FILE INVALID_HANDLE_VALUE
|
||||
#else /* not windows --> */
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <netdb.h>
|
||||
#include <signal.h>
|
||||
#include <strings.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#ifdef LWS_BUILTIN_GETIFADDRS
|
||||
#include "deps/ifaddrs/ifaddrs.h"
|
||||
#else
|
||||
#include <ifaddrs.h>
|
||||
#endif
|
||||
//#include <sys/syslog.h>
|
||||
#include <sys/un.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netdb.h>
|
||||
#ifndef LWS_NO_FORK
|
||||
#ifdef HAVE_SYS_PRCTL_H
|
||||
#include <sys/prctl.h>
|
||||
#endif
|
||||
#endif
|
||||
#include <netinet/in.h>
|
||||
#include <netinet/tcp.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <poll.h>
|
||||
#ifdef LWS_USE_LIBEV
|
||||
#include <ev.h>
|
||||
#endif /* LWS_USE_LIBEV */
|
||||
|
||||
#include <sys/mman.h>
|
||||
#include <sys/time.h>
|
||||
|
||||
#define LWS_ERRNO errno
|
||||
#define LWS_EAGAIN EAGAIN
|
||||
#define LWS_EALREADY EALREADY
|
||||
#define LWS_EINPROGRESS EINPROGRESS
|
||||
#define LWS_EINTR EINTR
|
||||
#define LWS_EISCONN EISCONN
|
||||
#define LWS_EWOULDBLOCK EWOULDBLOCK
|
||||
#define LWS_INVALID_FILE -1
|
||||
#define LWS_POLLHUP (POLLHUP|POLLERR)
|
||||
#define LWS_POLLIN (POLLIN)
|
||||
#define LWS_POLLOUT (POLLOUT)
|
||||
#define compatible_close(fd) close(fd)
|
||||
#define compatible_file_close(fd) close(fd)
|
||||
#define compatible_file_seek_cur(fd, offset) lseek(fd, offset, SEEK_CUR)
|
||||
#define compatible_file_read(amount, fd, buf, len) \
|
||||
amount = read(fd, buf, len);
|
||||
#define lws_set_blocking_send(wsi)
|
||||
#endif
|
||||
|
||||
#ifndef HAVE_BZERO
|
||||
#define bzero(b, len) (memset((b), '\0', (len)), (void) 0)
|
||||
#endif
|
||||
|
||||
#ifndef HAVE_STRERROR
|
||||
#define strerror(x) ""
|
||||
#endif
|
||||
|
||||
#ifdef LWS_OPENSSL_SUPPORT
|
||||
#ifdef USE_CYASSL
|
||||
#include <cyassl/openssl/ssl.h>
|
||||
#include <cyassl/error.h>
|
||||
unsigned char *
|
||||
SHA1(const unsigned char *d, size_t n, unsigned char *md);
|
||||
#else
|
||||
#include <openssl/ssl.h>
|
||||
#include <openssl/evp.h>
|
||||
#include <openssl/err.h>
|
||||
#include <openssl/md5.h>
|
||||
#include <openssl/sha.h>
|
||||
#endif /* not USE_CYASSL */
|
||||
#endif
|
||||
|
||||
#include "libwebsockets.h"
|
||||
|
||||
#if defined(WIN32) || defined(_WIN32)
|
||||
|
||||
#ifndef BIG_ENDIAN
|
||||
#define BIG_ENDIAN 4321 /* to show byte order (taken from gcc) */
|
||||
#endif
|
||||
#ifndef LITTLE_ENDIAN
|
||||
#define LITTLE_ENDIAN 1234
|
||||
#endif
|
||||
#ifndef BYTE_ORDER
|
||||
#define BYTE_ORDER LITTLE_ENDIAN
|
||||
#endif
|
||||
typedef unsigned __int64 u_int64_t;
|
||||
|
||||
#undef __P
|
||||
#ifndef __P
|
||||
#if __STDC__
|
||||
#define __P(protos) protos
|
||||
#else
|
||||
#define __P(protos) ()
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#else
|
||||
|
||||
#include <sys/stat.h>
|
||||
#include <sys/cdefs.h>
|
||||
#include <sys/time.h>
|
||||
|
||||
#if defined(__APPLE__)
|
||||
#include <machine/endian.h>
|
||||
#elif defined(__FreeBSD__)
|
||||
#include <sys/endian.h>
|
||||
#elif defined(__linux__)
|
||||
#include <endian.h>
|
||||
#endif
|
||||
|
||||
#if !defined(BYTE_ORDER)
|
||||
# define BYTE_ORDER __BYTE_ORDER
|
||||
#endif
|
||||
#if !defined(LITTLE_ENDIAN)
|
||||
# define LITTLE_ENDIAN __LITTLE_ENDIAN
|
||||
#endif
|
||||
#if !defined(BIG_ENDIAN)
|
||||
# define BIG_ENDIAN __BIG_ENDIAN
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Mac OSX as well as iOS do not define the MSG_NOSIGNAL flag,
|
||||
* but happily have something equivalent in the SO_NOSIGPIPE flag.
|
||||
*/
|
||||
#ifdef __APPLE__
|
||||
#define MSG_NOSIGNAL SO_NOSIGPIPE
|
||||
#endif
|
||||
|
||||
#ifndef LWS_MAX_HEADER_LEN
|
||||
#define LWS_MAX_HEADER_LEN 1024
|
||||
#endif
|
||||
#ifndef LWS_MAX_PROTOCOLS
|
||||
#define LWS_MAX_PROTOCOLS 5
|
||||
#endif
|
||||
#ifndef LWS_MAX_EXTENSIONS_ACTIVE
|
||||
#define LWS_MAX_EXTENSIONS_ACTIVE 3
|
||||
#endif
|
||||
#ifndef SPEC_LATEST_SUPPORTED
|
||||
#define SPEC_LATEST_SUPPORTED 13
|
||||
#endif
|
||||
#ifndef AWAITING_TIMEOUT
|
||||
#define AWAITING_TIMEOUT 5
|
||||
#endif
|
||||
#ifndef CIPHERS_LIST_STRING
|
||||
#define CIPHERS_LIST_STRING "DEFAULT"
|
||||
#endif
|
||||
#ifndef LWS_SOMAXCONN
|
||||
#define LWS_SOMAXCONN SOMAXCONN
|
||||
#endif
|
||||
|
||||
#define MAX_WEBSOCKET_04_KEY_LEN 128
|
||||
#define LWS_MAX_SOCKET_IO_BUF 4096
|
||||
|
||||
#ifndef SYSTEM_RANDOM_FILEPATH
|
||||
#define SYSTEM_RANDOM_FILEPATH "/dev/urandom"
|
||||
#endif
|
||||
#ifndef LWS_MAX_ZLIB_CONN_BUFFER
|
||||
#define LWS_MAX_ZLIB_CONN_BUFFER (64 * 1024)
|
||||
#endif
|
||||
|
||||
/*
|
||||
* if not in a connection storm, check for incoming
|
||||
* connections this many normal connection services
|
||||
*/
|
||||
#define LWS_LISTEN_SERVICE_MODULO 10
|
||||
|
||||
enum lws_websocket_opcodes_07 {
|
||||
LWS_WS_OPCODE_07__CONTINUATION = 0,
|
||||
LWS_WS_OPCODE_07__TEXT_FRAME = 1,
|
||||
LWS_WS_OPCODE_07__BINARY_FRAME = 2,
|
||||
|
||||
LWS_WS_OPCODE_07__NOSPEC__MUX = 7,
|
||||
|
||||
/* control extensions 8+ */
|
||||
|
||||
LWS_WS_OPCODE_07__CLOSE = 8,
|
||||
LWS_WS_OPCODE_07__PING = 9,
|
||||
LWS_WS_OPCODE_07__PONG = 0xa,
|
||||
};
|
||||
|
||||
|
||||
enum lws_connection_states {
|
||||
WSI_STATE_HTTP,
|
||||
WSI_STATE_HTTP_ISSUING_FILE,
|
||||
WSI_STATE_HTTP_HEADERS,
|
||||
WSI_STATE_HTTP_BODY,
|
||||
WSI_STATE_DEAD_SOCKET,
|
||||
WSI_STATE_ESTABLISHED,
|
||||
WSI_STATE_CLIENT_UNCONNECTED,
|
||||
WSI_STATE_RETURNED_CLOSE_ALREADY,
|
||||
WSI_STATE_AWAITING_CLOSE_ACK,
|
||||
WSI_STATE_FLUSHING_STORED_SEND_BEFORE_CLOSE,
|
||||
};
|
||||
|
||||
enum lws_rx_parse_state {
|
||||
LWS_RXPS_NEW,
|
||||
|
||||
LWS_RXPS_04_MASK_NONCE_1,
|
||||
LWS_RXPS_04_MASK_NONCE_2,
|
||||
LWS_RXPS_04_MASK_NONCE_3,
|
||||
|
||||
LWS_RXPS_04_FRAME_HDR_1,
|
||||
LWS_RXPS_04_FRAME_HDR_LEN,
|
||||
LWS_RXPS_04_FRAME_HDR_LEN16_2,
|
||||
LWS_RXPS_04_FRAME_HDR_LEN16_1,
|
||||
LWS_RXPS_04_FRAME_HDR_LEN64_8,
|
||||
LWS_RXPS_04_FRAME_HDR_LEN64_7,
|
||||
LWS_RXPS_04_FRAME_HDR_LEN64_6,
|
||||
LWS_RXPS_04_FRAME_HDR_LEN64_5,
|
||||
LWS_RXPS_04_FRAME_HDR_LEN64_4,
|
||||
LWS_RXPS_04_FRAME_HDR_LEN64_3,
|
||||
LWS_RXPS_04_FRAME_HDR_LEN64_2,
|
||||
LWS_RXPS_04_FRAME_HDR_LEN64_1,
|
||||
|
||||
LWS_RXPS_07_COLLECT_FRAME_KEY_1,
|
||||
LWS_RXPS_07_COLLECT_FRAME_KEY_2,
|
||||
LWS_RXPS_07_COLLECT_FRAME_KEY_3,
|
||||
LWS_RXPS_07_COLLECT_FRAME_KEY_4,
|
||||
|
||||
LWS_RXPS_PAYLOAD_UNTIL_LENGTH_EXHAUSTED
|
||||
};
|
||||
|
||||
|
||||
enum connection_mode {
|
||||
LWS_CONNMODE_HTTP_SERVING,
|
||||
LWS_CONNMODE_HTTP_SERVING_ACCEPTED, /* actual HTTP service going on */
|
||||
LWS_CONNMODE_PRE_WS_SERVING_ACCEPT,
|
||||
|
||||
LWS_CONNMODE_WS_SERVING,
|
||||
LWS_CONNMODE_WS_CLIENT,
|
||||
|
||||
/* transient, ssl delay hiding */
|
||||
LWS_CONNMODE_SSL_ACK_PENDING,
|
||||
|
||||
/* transient modes */
|
||||
LWS_CONNMODE_WS_CLIENT_WAITING_CONNECT,
|
||||
LWS_CONNMODE_WS_CLIENT_WAITING_PROXY_REPLY,
|
||||
LWS_CONNMODE_WS_CLIENT_ISSUE_HANDSHAKE,
|
||||
LWS_CONNMODE_WS_CLIENT_ISSUE_HANDSHAKE2,
|
||||
LWS_CONNMODE_WS_CLIENT_WAITING_SSL,
|
||||
LWS_CONNMODE_WS_CLIENT_WAITING_SERVER_REPLY,
|
||||
LWS_CONNMODE_WS_CLIENT_WAITING_EXTENSION_CONNECT,
|
||||
LWS_CONNMODE_WS_CLIENT_PENDING_CANDIDATE_CHILD,
|
||||
|
||||
/* special internal types */
|
||||
LWS_CONNMODE_SERVER_LISTENER,
|
||||
};
|
||||
|
||||
enum {
|
||||
LWS_RXFLOW_ALLOW = (1 << 0),
|
||||
LWS_RXFLOW_PENDING_CHANGE = (1 << 1),
|
||||
};
|
||||
|
||||
struct libwebsocket_protocols;
|
||||
struct libwebsocket;
|
||||
|
||||
#ifdef LWS_USE_LIBEV
|
||||
struct lws_io_watcher {
|
||||
struct ev_io watcher;
|
||||
struct libwebsocket_context* context;
|
||||
};
|
||||
|
||||
struct lws_signal_watcher {
|
||||
struct ev_signal watcher;
|
||||
struct libwebsocket_context* context;
|
||||
};
|
||||
#endif /* LWS_USE_LIBEV */
|
||||
|
||||
struct libwebsocket_context {
|
||||
#ifdef _WIN32
|
||||
WSAEVENT *events;
|
||||
#endif
|
||||
struct libwebsocket_pollfd *fds;
|
||||
struct libwebsocket **lws_lookup; /* fd to wsi */
|
||||
int fds_count;
|
||||
#ifdef LWS_USE_LIBEV
|
||||
struct ev_loop* io_loop;
|
||||
struct lws_io_watcher w_accept;
|
||||
struct lws_signal_watcher w_sigint;
|
||||
#endif /* LWS_USE_LIBEV */
|
||||
int max_fds;
|
||||
int listen_port;
|
||||
const char *iface;
|
||||
char http_proxy_address[128];
|
||||
char canonical_hostname[128];
|
||||
unsigned int http_proxy_port;
|
||||
unsigned int options;
|
||||
time_t last_timeout_check_s;
|
||||
|
||||
/*
|
||||
* usable by anything in the service code, but only if the scope
|
||||
* does not last longer than the service action (since next service
|
||||
* of any socket can likewise use it and overwrite)
|
||||
*/
|
||||
unsigned char service_buffer[LWS_MAX_SOCKET_IO_BUF];
|
||||
|
||||
int started_with_parent;
|
||||
|
||||
int fd_random;
|
||||
int listen_service_modulo;
|
||||
int listen_service_count;
|
||||
int listen_service_fd;
|
||||
int listen_service_extraseen;
|
||||
|
||||
/*
|
||||
* set to the Thread ID that's doing the service loop just before entry
|
||||
* to poll indicates service thread likely idling in poll()
|
||||
* volatile because other threads may check it as part of processing
|
||||
* for pollfd event change.
|
||||
*/
|
||||
volatile int service_tid;
|
||||
#ifndef _WIN32
|
||||
int dummy_pipe_fds[2];
|
||||
#endif
|
||||
|
||||
int ka_time;
|
||||
int ka_probes;
|
||||
int ka_interval;
|
||||
|
||||
#ifdef LWS_LATENCY
|
||||
unsigned long worst_latency;
|
||||
char worst_latency_info[256];
|
||||
#endif
|
||||
|
||||
#ifdef LWS_OPENSSL_SUPPORT
|
||||
int use_ssl;
|
||||
int allow_non_ssl_on_ssl_port;
|
||||
SSL_CTX *ssl_ctx;
|
||||
SSL_CTX *ssl_client_ctx;
|
||||
#endif
|
||||
struct libwebsocket_protocols *protocols;
|
||||
int count_protocols;
|
||||
#ifndef LWS_NO_EXTENSIONS
|
||||
struct libwebsocket_extension *extensions;
|
||||
#endif
|
||||
void *user_space;
|
||||
};
|
||||
|
||||
enum {
|
||||
LWS_EV_READ = (1 << 0),
|
||||
LWS_EV_WRITE = (1 << 1),
|
||||
LWS_EV_START = (1 << 2),
|
||||
LWS_EV_STOP = (1 << 3),
|
||||
};
|
||||
|
||||
#ifdef LWS_USE_LIBEV
|
||||
#define LWS_LIBEV_ENABLED(context) (context->options & LWS_SERVER_OPTION_LIBEV)
|
||||
LWS_EXTERN void lws_feature_status_libev(struct lws_context_creation_info *info);
|
||||
LWS_EXTERN void
|
||||
lws_libev_accept(struct libwebsocket_context *context,
|
||||
struct libwebsocket *new_wsi, int accept_fd);
|
||||
LWS_EXTERN void
|
||||
lws_libev_io(struct libwebsocket_context *context,
|
||||
struct libwebsocket *wsi, int flags);
|
||||
LWS_EXTERN int
|
||||
lws_libev_init_fd_table(struct libwebsocket_context *context);
|
||||
LWS_EXTERN void
|
||||
lws_libev_run(struct libwebsocket_context *context);
|
||||
#else
|
||||
#define LWS_LIBEV_ENABLED(context) (0)
|
||||
#define lws_feature_status_libev(_a) \
|
||||
lwsl_notice("libev support not compiled in\n")
|
||||
#define lws_libev_accept(_a, _b, _c) (0)
|
||||
#define lws_libev_io(_a, _b, _c) (0)
|
||||
#define lws_libev_init_fd_table(_a) (0)
|
||||
#define lws_libev_run(_a) (0)
|
||||
#endif
|
||||
|
||||
#ifdef LWS_USE_IPV6
|
||||
#define LWS_IPV6_ENABLED(context) (!(context->options & LWS_SERVER_OPTION_DISABLE_IPV6))
|
||||
#else
|
||||
#define LWS_IPV6_ENABLED(context) (0)
|
||||
#endif
|
||||
|
||||
enum uri_path_states {
|
||||
URIPS_IDLE,
|
||||
URIPS_SEEN_SLASH,
|
||||
URIPS_SEEN_SLASH_DOT,
|
||||
URIPS_SEEN_SLASH_DOT_DOT,
|
||||
URIPS_ARGUMENTS,
|
||||
};
|
||||
|
||||
enum uri_esc_states {
|
||||
URIES_IDLE,
|
||||
URIES_SEEN_PERCENT,
|
||||
URIES_SEEN_PERCENT_H1,
|
||||
};
|
||||
|
||||
/*
|
||||
* This is totally opaque to code using the library. It's exported as a
|
||||
* forward-reference pointer-only declaration; the user can use the pointer with
|
||||
* other APIs to get information out of it.
|
||||
*/
|
||||
|
||||
struct lws_fragments {
|
||||
unsigned short offset;
|
||||
unsigned short len;
|
||||
unsigned char next_frag_index;
|
||||
};
|
||||
|
||||
struct allocated_headers {
|
||||
unsigned short next_frag_index;
|
||||
unsigned short pos;
|
||||
unsigned char frag_index[WSI_TOKEN_COUNT];
|
||||
struct lws_fragments frags[WSI_TOKEN_COUNT * 2];
|
||||
char data[LWS_MAX_HEADER_LEN];
|
||||
#ifndef LWS_NO_CLIENT
|
||||
char initial_handshake_hash_base64[30];
|
||||
unsigned short c_port;
|
||||
#endif
|
||||
};
|
||||
|
||||
struct _lws_http_mode_related {
|
||||
struct allocated_headers *ah; /* mirroring _lws_header_related */
|
||||
#if defined(WIN32) || defined(_WIN32)
|
||||
HANDLE fd;
|
||||
#else
|
||||
int fd;
|
||||
#endif
|
||||
unsigned long filepos;
|
||||
unsigned long filelen;
|
||||
|
||||
int content_length;
|
||||
int content_length_seen;
|
||||
int body_index;
|
||||
unsigned char *post_buffer;
|
||||
};
|
||||
|
||||
struct _lws_header_related {
|
||||
struct allocated_headers *ah;
|
||||
short lextable_pos;
|
||||
unsigned char parser_state; /* enum lws_token_indexes */
|
||||
enum uri_path_states ups;
|
||||
enum uri_esc_states ues;
|
||||
char esc_stash;
|
||||
};
|
||||
|
||||
struct _lws_websocket_related {
|
||||
char *rx_user_buffer;
|
||||
int rx_user_buffer_head;
|
||||
unsigned char frame_masking_nonce_04[4];
|
||||
unsigned char frame_mask_index;
|
||||
size_t rx_packet_length;
|
||||
unsigned char opcode;
|
||||
unsigned int final:1;
|
||||
unsigned char rsv;
|
||||
unsigned int frame_is_binary:1;
|
||||
unsigned int all_zero_nonce:1;
|
||||
short close_reason; /* enum lws_close_status */
|
||||
unsigned char *rxflow_buffer;
|
||||
int rxflow_len;
|
||||
int rxflow_pos;
|
||||
unsigned int rxflow_change_to:2;
|
||||
unsigned int this_frame_masked:1;
|
||||
unsigned int inside_frame:1; /* next write will be more of frame */
|
||||
unsigned int clean_buffer:1; /* buffer not rewritten by extension */
|
||||
};
|
||||
|
||||
struct libwebsocket {
|
||||
|
||||
/* lifetime members */
|
||||
|
||||
#ifdef LWS_USE_LIBEV
|
||||
struct lws_io_watcher w_read;
|
||||
struct lws_io_watcher w_write;
|
||||
#endif /* LWS_USE_LIBEV */
|
||||
const struct libwebsocket_protocols *protocol;
|
||||
#ifndef LWS_NO_EXTENSIONS
|
||||
struct libwebsocket_extension *
|
||||
active_extensions[LWS_MAX_EXTENSIONS_ACTIVE];
|
||||
void *active_extensions_user[LWS_MAX_EXTENSIONS_ACTIVE];
|
||||
unsigned char count_active_extensions;
|
||||
unsigned int extension_data_pending:1;
|
||||
#endif
|
||||
unsigned char ietf_spec_revision;
|
||||
|
||||
char mode; /* enum connection_mode */
|
||||
char state; /* enum lws_connection_states */
|
||||
char lws_rx_parse_state; /* enum lws_rx_parse_state */
|
||||
char rx_frame_type; /* enum libwebsocket_write_protocol */
|
||||
|
||||
unsigned int hdr_parsing_completed:1;
|
||||
|
||||
char pending_timeout; /* enum pending_timeout */
|
||||
time_t pending_timeout_limit;
|
||||
|
||||
int sock;
|
||||
int position_in_fds_table;
|
||||
#ifdef LWS_LATENCY
|
||||
unsigned long action_start;
|
||||
unsigned long latency_start;
|
||||
#endif
|
||||
|
||||
/* truncated send handling */
|
||||
unsigned char *truncated_send_malloc; /* non-NULL means buffering in progress */
|
||||
unsigned int truncated_send_allocation; /* size of malloc */
|
||||
unsigned int truncated_send_offset; /* where we are in terms of spilling */
|
||||
unsigned int truncated_send_len; /* how much is buffered */
|
||||
|
||||
void *user_space;
|
||||
|
||||
/* members with mutually exclusive lifetimes are unionized */
|
||||
|
||||
union u {
|
||||
struct _lws_http_mode_related http;
|
||||
struct _lws_header_related hdr;
|
||||
struct _lws_websocket_related ws;
|
||||
} u;
|
||||
|
||||
#ifdef LWS_OPENSSL_SUPPORT
|
||||
SSL *ssl;
|
||||
BIO *client_bio;
|
||||
unsigned int use_ssl:2;
|
||||
#endif
|
||||
|
||||
#ifdef _WIN32
|
||||
BOOL sock_send_blocking;
|
||||
#endif
|
||||
};
|
||||
|
||||
LWS_EXTERN int log_level;
|
||||
|
||||
LWS_EXTERN void
|
||||
libwebsocket_close_and_free_session(struct libwebsocket_context *context,
|
||||
struct libwebsocket *wsi, enum lws_close_status);
|
||||
|
||||
LWS_EXTERN int
|
||||
remove_wsi_socket_from_fds(struct libwebsocket_context *context,
|
||||
struct libwebsocket *wsi);
|
||||
|
||||
#ifndef LWS_LATENCY
|
||||
static inline void lws_latency(struct libwebsocket_context *context,
|
||||
struct libwebsocket *wsi, const char *action,
|
||||
int ret, int completion) { while (0); }
|
||||
static inline void lws_latency_pre(struct libwebsocket_context *context,
|
||||
struct libwebsocket *wsi) { while (0); }
|
||||
#else
|
||||
#define lws_latency_pre(_context, _wsi) lws_latency(_context, _wsi, NULL, 0, 0)
|
||||
extern void
|
||||
lws_latency(struct libwebsocket_context *context,
|
||||
struct libwebsocket *wsi, const char *action,
|
||||
int ret, int completion);
|
||||
#endif
|
||||
|
||||
LWS_EXTERN int
|
||||
libwebsocket_client_rx_sm(struct libwebsocket *wsi, unsigned char c);
|
||||
|
||||
LWS_EXTERN int
|
||||
libwebsocket_parse(struct libwebsocket *wsi, unsigned char c);
|
||||
|
||||
LWS_EXTERN int
|
||||
lws_b64_selftest(void);
|
||||
|
||||
LWS_EXTERN struct libwebsocket *
|
||||
wsi_from_fd(struct libwebsocket_context *context, int fd);
|
||||
|
||||
LWS_EXTERN int
|
||||
insert_wsi_socket_into_fds(struct libwebsocket_context *context,
|
||||
struct libwebsocket *wsi);
|
||||
|
||||
LWS_EXTERN int
|
||||
lws_issue_raw(struct libwebsocket *wsi, unsigned char *buf, size_t len);
|
||||
|
||||
|
||||
LWS_EXTERN int
|
||||
libwebsocket_service_timeout_check(struct libwebsocket_context *context,
|
||||
struct libwebsocket *wsi, unsigned int sec);
|
||||
|
||||
LWS_EXTERN struct libwebsocket *
|
||||
libwebsocket_client_connect_2(struct libwebsocket_context *context,
|
||||
struct libwebsocket *wsi);
|
||||
|
||||
LWS_EXTERN struct libwebsocket *
|
||||
libwebsocket_create_new_server_wsi(struct libwebsocket_context *context);
|
||||
|
||||
LWS_EXTERN char *
|
||||
libwebsockets_generate_client_handshake(struct libwebsocket_context *context,
|
||||
struct libwebsocket *wsi, char *pkt);
|
||||
|
||||
LWS_EXTERN int
|
||||
lws_handle_POLLOUT_event(struct libwebsocket_context *context,
|
||||
struct libwebsocket *wsi, struct libwebsocket_pollfd *pollfd);
|
||||
/*
|
||||
* EXTENSIONS
|
||||
*/
|
||||
|
||||
#ifndef LWS_NO_EXTENSIONS
|
||||
LWS_VISIBLE void
|
||||
lws_context_init_extensions(struct lws_context_creation_info *info,
|
||||
struct libwebsocket_context *context);
|
||||
LWS_EXTERN int
|
||||
lws_any_extension_handled(struct libwebsocket_context *context,
|
||||
struct libwebsocket *wsi,
|
||||
enum libwebsocket_extension_callback_reasons r,
|
||||
void *v, size_t len);
|
||||
|
||||
LWS_EXTERN int
|
||||
lws_ext_callback_for_each_active(struct libwebsocket *wsi, int reason,
|
||||
void *buf, int len);
|
||||
LWS_EXTERN int
|
||||
lws_ext_callback_for_each_extension_type(
|
||||
struct libwebsocket_context *context, struct libwebsocket *wsi,
|
||||
int reason, void *arg, int len);
|
||||
#else
|
||||
#define lws_any_extension_handled(_a, _b, _c, _d, _e) (0)
|
||||
#define lws_ext_callback_for_each_active(_a, _b, _c, _d) (0)
|
||||
#define lws_ext_callback_for_each_extension_type(_a, _b, _c, _d, _e) (0)
|
||||
#define lws_issue_raw_ext_access lws_issue_raw
|
||||
#define lws_context_init_extensions(_a, _b)
|
||||
#endif
|
||||
|
||||
LWS_EXTERN int
|
||||
lws_client_interpret_server_handshake(struct libwebsocket_context *context,
|
||||
struct libwebsocket *wsi);
|
||||
|
||||
LWS_EXTERN int
|
||||
libwebsocket_rx_sm(struct libwebsocket *wsi, unsigned char c);
|
||||
|
||||
LWS_EXTERN int
|
||||
lws_issue_raw_ext_access(struct libwebsocket *wsi,
|
||||
unsigned char *buf, size_t len);
|
||||
|
||||
LWS_EXTERN int
|
||||
_libwebsocket_rx_flow_control(struct libwebsocket *wsi);
|
||||
|
||||
LWS_EXTERN int
|
||||
user_callback_handle_rxflow(callback_function,
|
||||
struct libwebsocket_context *context,
|
||||
struct libwebsocket *wsi,
|
||||
enum libwebsocket_callback_reasons reason, void *user,
|
||||
void *in, size_t len);
|
||||
|
||||
LWS_EXTERN int
|
||||
lws_plat_set_socket_options(struct libwebsocket_context *context, int fd);
|
||||
|
||||
LWS_EXTERN int
|
||||
lws_allocate_header_table(struct libwebsocket *wsi);
|
||||
|
||||
LWS_EXTERN char *
|
||||
lws_hdr_simple_ptr(struct libwebsocket *wsi, enum lws_token_indexes h);
|
||||
|
||||
LWS_EXTERN int
|
||||
lws_hdr_simple_create(struct libwebsocket *wsi,
|
||||
enum lws_token_indexes h, const char *s);
|
||||
|
||||
LWS_EXTERN int
|
||||
libwebsocket_ensure_user_space(struct libwebsocket *wsi);
|
||||
|
||||
LWS_EXTERN int
|
||||
lws_change_pollfd(struct libwebsocket *wsi, int _and, int _or);
|
||||
|
||||
#ifndef LWS_NO_SERVER
|
||||
int lws_context_init_server(struct lws_context_creation_info *info,
|
||||
struct libwebsocket_context *context);
|
||||
LWS_EXTERN int handshake_0405(struct libwebsocket_context *context,
|
||||
struct libwebsocket *wsi);
|
||||
LWS_EXTERN int
|
||||
libwebsocket_interpret_incoming_packet(struct libwebsocket *wsi,
|
||||
unsigned char *buf, size_t len);
|
||||
LWS_EXTERN void
|
||||
lws_server_get_canonical_hostname(struct libwebsocket_context *context,
|
||||
struct lws_context_creation_info *info);
|
||||
#else
|
||||
#define lws_context_init_server(_a, _b) (0)
|
||||
#define libwebsocket_interpret_incoming_packet(_a, _b, _c) (0)
|
||||
#define lws_server_get_canonical_hostname(_a, _b)
|
||||
#endif
|
||||
|
||||
#ifndef LWS_NO_DAEMONIZE
|
||||
LWS_EXTERN int get_daemonize_pid();
|
||||
#else
|
||||
#define get_daemonize_pid() (0)
|
||||
#endif
|
||||
|
||||
LWS_EXTERN int interface_to_sa(struct libwebsocket_context *context,
|
||||
const char *ifname, struct sockaddr_in *addr, size_t addrlen);
|
||||
|
||||
LWS_EXTERN void lwsl_emit_stderr(int level, const char *line);
|
||||
|
||||
#ifdef _WIN32
|
||||
LWS_EXTERN HANDLE lws_plat_open_file(const char* filename, unsigned long* filelen);
|
||||
#else
|
||||
LWS_EXTERN int lws_plat_open_file(const char* filename, unsigned long* filelen);
|
||||
#endif
|
||||
|
||||
enum lws_ssl_capable_status {
|
||||
LWS_SSL_CAPABLE_ERROR = -1,
|
||||
LWS_SSL_CAPABLE_MORE_SERVICE = -2,
|
||||
};
|
||||
|
||||
#ifndef LWS_OPENSSL_SUPPORT
|
||||
#define LWS_SSL_ENABLED(context) (0)
|
||||
unsigned char *
|
||||
SHA1(const unsigned char *d, size_t n, unsigned char *md);
|
||||
#define lws_context_init_server_ssl(_a, _b) (0)
|
||||
#define lws_ssl_destroy(_a)
|
||||
#define lws_context_init_http2_ssl(_a)
|
||||
#define lws_ssl_pending(_a) (0)
|
||||
#define lws_ssl_capable_read lws_ssl_capable_read_no_ssl
|
||||
#define lws_ssl_capable_write lws_ssl_capable_write_no_ssl
|
||||
#define lws_server_socket_service_ssl(_a, _b, _c, _d, _e) (0)
|
||||
#define lws_ssl_close(_a) (0)
|
||||
#define lws_ssl_context_destroy(_a)
|
||||
#else
|
||||
#define LWS_SSL_ENABLED(context) (context->use_ssl)
|
||||
LWS_EXTERN int lws_ssl_pending(struct libwebsocket *wsi);
|
||||
LWS_EXTERN int openssl_websocket_private_data_index;
|
||||
LWS_EXTERN int
|
||||
lws_ssl_capable_read(struct libwebsocket *wsi, unsigned char *buf, int len);
|
||||
|
||||
LWS_EXTERN int
|
||||
lws_ssl_capable_write(struct libwebsocket *wsi, unsigned char *buf, int len);
|
||||
LWS_EXTERN int
|
||||
lws_server_socket_service_ssl(struct libwebsocket_context *context,
|
||||
struct libwebsocket **wsi, struct libwebsocket *new_wsi,
|
||||
int accept_fd, struct libwebsocket_pollfd *pollfd);
|
||||
LWS_EXTERN int
|
||||
lws_ssl_close(struct libwebsocket *wsi);
|
||||
LWS_EXTERN void
|
||||
lws_ssl_context_destroy(struct libwebsocket_context *context);
|
||||
#ifndef LWS_NO_SERVER
|
||||
LWS_EXTERN int
|
||||
lws_context_init_server_ssl(struct lws_context_creation_info *info,
|
||||
struct libwebsocket_context *context);
|
||||
#else
|
||||
#define lws_context_init_server_ssl(_a, _b) (0)
|
||||
#endif
|
||||
LWS_EXTERN void
|
||||
lws_ssl_destroy(struct libwebsocket_context *context);
|
||||
|
||||
/* HTTP2-related */
|
||||
|
||||
#ifdef LWS_USE_HTTP2
|
||||
LWS_EXTERN void
|
||||
lws_context_init_http2_ssl(struct libwebsocket_context *context);
|
||||
#else
|
||||
#define lws_context_init_http2_ssl(_a)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
LWS_EXTERN int
|
||||
lws_ssl_capable_read_no_ssl(struct libwebsocket *wsi, unsigned char *buf, int len);
|
||||
|
||||
LWS_EXTERN int
|
||||
lws_ssl_capable_write_no_ssl(struct libwebsocket *wsi, unsigned char *buf, int len);
|
||||
|
||||
#ifndef LWS_NO_CLIENT
|
||||
LWS_EXTERN int lws_client_socket_service(
|
||||
struct libwebsocket_context *context,
|
||||
struct libwebsocket *wsi, struct libwebsocket_pollfd *pollfd);
|
||||
#ifdef LWS_OPENSSL_SUPPORT
|
||||
LWS_EXTERN int lws_context_init_client_ssl(struct lws_context_creation_info *info,
|
||||
struct libwebsocket_context *context);
|
||||
#else
|
||||
#define lws_context_init_client_ssl(_a, _b) (0)
|
||||
#endif
|
||||
LWS_EXTERN int lws_handshake_client(struct libwebsocket *wsi, unsigned char **buf, size_t len);
|
||||
LWS_EXTERN void
|
||||
libwebsockets_decode_ssl_error(void);
|
||||
#else
|
||||
#define lws_context_init_client_ssl(_a, _b) (0)
|
||||
#define lws_handshake_client(_a, _b, _c) (0)
|
||||
#endif
|
||||
#ifndef LWS_NO_SERVER
|
||||
LWS_EXTERN int lws_server_socket_service(
|
||||
struct libwebsocket_context *context,
|
||||
struct libwebsocket *wsi, struct libwebsocket_pollfd *pollfd);
|
||||
LWS_EXTERN int _libwebsocket_rx_flow_control(struct libwebsocket *wsi);
|
||||
LWS_EXTERN int lws_handshake_server(struct libwebsocket_context *context,
|
||||
struct libwebsocket *wsi, unsigned char **buf, size_t len);
|
||||
#else
|
||||
#define lws_server_socket_service(_a, _b, _c) (0)
|
||||
#define _libwebsocket_rx_flow_control(_a) (0)
|
||||
#define lws_handshake_server(_a, _b, _c, _d) (0)
|
||||
#endif
|
||||
|
||||
/*
|
||||
* lws_plat_
|
||||
*/
|
||||
LWS_EXTERN void
|
||||
lws_plat_delete_socket_from_fds(struct libwebsocket_context *context,
|
||||
struct libwebsocket *wsi, int m);
|
||||
LWS_EXTERN void
|
||||
lws_plat_insert_socket_into_fds(struct libwebsocket_context *context,
|
||||
struct libwebsocket *wsi);
|
||||
LWS_EXTERN void
|
||||
lws_plat_service_periodic(struct libwebsocket_context *context);
|
||||
|
||||
LWS_EXTERN int
|
||||
lws_plat_change_pollfd(struct libwebsocket_context *context,
|
||||
struct libwebsocket *wsi, struct libwebsocket_pollfd *pfd);
|
||||
LWS_EXTERN int
|
||||
lws_plat_context_early_init(void);
|
||||
LWS_EXTERN void
|
||||
lws_plat_context_early_destroy(struct libwebsocket_context *context);
|
||||
LWS_EXTERN void
|
||||
lws_plat_context_late_destroy(struct libwebsocket_context *context);
|
||||
LWS_EXTERN int
|
||||
lws_poll_listen_fd(struct libwebsocket_pollfd *fd);
|
||||
LWS_EXTERN int
|
||||
lws_plat_service(struct libwebsocket_context *context, int timeout_ms);
|
||||
LWS_EXTERN int
|
||||
lws_plat_init_fd_tables(struct libwebsocket_context *context);
|
||||
LWS_EXTERN void
|
||||
lws_plat_drop_app_privileges(struct lws_context_creation_info *info);
|
||||
LWS_EXTERN unsigned long long
|
||||
time_in_microseconds(void);
|
||||
LWS_EXTERN const char *
|
||||
lws_plat_inet_ntop(int af, const void *src, char *dst, int cnt);
|
||||
@@ -0,0 +1,280 @@
|
||||
/*
|
||||
* libwebsockets - small server side websockets and web server implementation
|
||||
*
|
||||
* Copyright (C) 2010-2013 Andy Green <[email protected]>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation:
|
||||
* version 2.1 of the License.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
||||
* MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#include "private-libwebsockets.h"
|
||||
|
||||
#define LWS_CPYAPP(ptr, str) { strcpy(ptr, str); ptr += strlen(str); }
|
||||
#ifndef LWS_NO_EXTENSIONS
|
||||
LWS_VISIBLE int
|
||||
lws_extension_server_handshake(struct libwebsocket_context *context,
|
||||
struct libwebsocket *wsi, char **p)
|
||||
{
|
||||
int n;
|
||||
char *c;
|
||||
char ext_name[128];
|
||||
struct libwebsocket_extension *ext;
|
||||
int ext_count = 0;
|
||||
int more = 1;
|
||||
|
||||
/*
|
||||
* Figure out which extensions the client has that we want to
|
||||
* enable on this connection, and give him back the list
|
||||
*/
|
||||
|
||||
if (!lws_hdr_total_length(wsi, WSI_TOKEN_EXTENSIONS))
|
||||
return 0;
|
||||
|
||||
/*
|
||||
* break down the list of client extensions
|
||||
* and go through them
|
||||
*/
|
||||
|
||||
if (lws_hdr_copy(wsi, (char *)context->service_buffer,
|
||||
sizeof(context->service_buffer),
|
||||
WSI_TOKEN_EXTENSIONS) < 0)
|
||||
return 1;
|
||||
|
||||
c = (char *)context->service_buffer;
|
||||
lwsl_parser("WSI_TOKEN_EXTENSIONS = '%s'\n", c);
|
||||
wsi->count_active_extensions = 0;
|
||||
n = 0;
|
||||
while (more) {
|
||||
|
||||
if (*c && (*c != ',' && *c != ' ' && *c != '\t')) {
|
||||
ext_name[n] = *c++;
|
||||
if (n < sizeof(ext_name) - 1)
|
||||
n++;
|
||||
continue;
|
||||
}
|
||||
ext_name[n] = '\0';
|
||||
if (!*c)
|
||||
more = 0;
|
||||
else {
|
||||
c++;
|
||||
if (!n)
|
||||
continue;
|
||||
}
|
||||
|
||||
/* check a client's extension against our support */
|
||||
|
||||
ext = wsi->protocol->owning_server->extensions;
|
||||
|
||||
while (ext && ext->callback) {
|
||||
|
||||
if (strcmp(ext_name, ext->name)) {
|
||||
ext++;
|
||||
continue;
|
||||
}
|
||||
|
||||
/*
|
||||
* oh, we do support this one he
|
||||
* asked for... but let's ask user
|
||||
* code if it's OK to apply it on this
|
||||
* particular connection + protocol
|
||||
*/
|
||||
|
||||
n = wsi->protocol->owning_server->
|
||||
protocols[0].callback(
|
||||
wsi->protocol->owning_server,
|
||||
wsi,
|
||||
LWS_CALLBACK_CONFIRM_EXTENSION_OKAY,
|
||||
wsi->user_space, ext_name, 0);
|
||||
|
||||
/*
|
||||
* zero return from callback means
|
||||
* go ahead and allow the extension,
|
||||
* it's what we get if the callback is
|
||||
* unhandled
|
||||
*/
|
||||
|
||||
if (n) {
|
||||
ext++;
|
||||
continue;
|
||||
}
|
||||
|
||||
/* apply it */
|
||||
|
||||
if (ext_count)
|
||||
*(*p)++ = ',';
|
||||
else
|
||||
LWS_CPYAPP(*p,
|
||||
"\x0d\x0aSec-WebSocket-Extensions: ");
|
||||
*p += sprintf(*p, "%s", ext_name);
|
||||
ext_count++;
|
||||
|
||||
/* instantiate the extension on this conn */
|
||||
|
||||
wsi->active_extensions_user[
|
||||
wsi->count_active_extensions] =
|
||||
malloc(ext->per_session_data_size);
|
||||
if (wsi->active_extensions_user[
|
||||
wsi->count_active_extensions] == NULL) {
|
||||
lwsl_err("Out of mem\n");
|
||||
return 1;
|
||||
}
|
||||
memset(wsi->active_extensions_user[
|
||||
wsi->count_active_extensions], 0,
|
||||
ext->per_session_data_size);
|
||||
|
||||
wsi->active_extensions[
|
||||
wsi->count_active_extensions] = ext;
|
||||
|
||||
/* allow him to construct his context */
|
||||
|
||||
ext->callback(wsi->protocol->owning_server,
|
||||
ext, wsi,
|
||||
LWS_EXT_CALLBACK_CONSTRUCT,
|
||||
wsi->active_extensions_user[
|
||||
wsi->count_active_extensions], NULL, 0);
|
||||
|
||||
wsi->count_active_extensions++;
|
||||
lwsl_parser("count_active_extensions <- %d\n",
|
||||
wsi->count_active_extensions);
|
||||
|
||||
ext++;
|
||||
}
|
||||
|
||||
n = 0;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
int
|
||||
handshake_0405(struct libwebsocket_context *context, struct libwebsocket *wsi)
|
||||
{
|
||||
unsigned char hash[20];
|
||||
int n;
|
||||
char *response;
|
||||
char *p;
|
||||
int accept_len;
|
||||
|
||||
if (!lws_hdr_total_length(wsi, WSI_TOKEN_HOST) ||
|
||||
!lws_hdr_total_length(wsi, WSI_TOKEN_KEY)) {
|
||||
lwsl_parser("handshake_04 missing pieces\n");
|
||||
/* completed header processing, but missing some bits */
|
||||
goto bail;
|
||||
}
|
||||
|
||||
if (lws_hdr_total_length(wsi, WSI_TOKEN_KEY) >=
|
||||
MAX_WEBSOCKET_04_KEY_LEN) {
|
||||
lwsl_warn("Client key too long %d\n", MAX_WEBSOCKET_04_KEY_LEN);
|
||||
goto bail;
|
||||
}
|
||||
|
||||
/*
|
||||
* since key length is restricted above (currently 128), cannot
|
||||
* overflow
|
||||
*/
|
||||
n = sprintf((char *)context->service_buffer,
|
||||
"%s258EAFA5-E914-47DA-95CA-C5AB0DC85B11",
|
||||
lws_hdr_simple_ptr(wsi, WSI_TOKEN_KEY));
|
||||
|
||||
SHA1(context->service_buffer, n, hash);
|
||||
|
||||
accept_len = lws_b64_encode_string((char *)hash, 20,
|
||||
(char *)context->service_buffer,
|
||||
sizeof(context->service_buffer));
|
||||
if (accept_len < 0) {
|
||||
lwsl_warn("Base64 encoded hash too long\n");
|
||||
goto bail;
|
||||
}
|
||||
|
||||
/* allocate the per-connection user memory (if any) */
|
||||
if (libwebsocket_ensure_user_space(wsi))
|
||||
goto bail;
|
||||
|
||||
/* create the response packet */
|
||||
|
||||
/* make a buffer big enough for everything */
|
||||
|
||||
response = (char *)context->service_buffer + MAX_WEBSOCKET_04_KEY_LEN;
|
||||
p = response;
|
||||
LWS_CPYAPP(p, "HTTP/1.1 101 Switching Protocols\x0d\x0a"
|
||||
"Upgrade: WebSocket\x0d\x0a"
|
||||
"Connection: Upgrade\x0d\x0a"
|
||||
"Sec-WebSocket-Accept: ");
|
||||
strcpy(p, (char *)context->service_buffer);
|
||||
p += accept_len;
|
||||
|
||||
if (lws_hdr_total_length(wsi, WSI_TOKEN_PROTOCOL)) {
|
||||
LWS_CPYAPP(p, "\x0d\x0aSec-WebSocket-Protocol: ");
|
||||
n = lws_hdr_copy(wsi, p, 128, WSI_TOKEN_PROTOCOL);
|
||||
if (n < 0)
|
||||
goto bail;
|
||||
p += n;
|
||||
}
|
||||
|
||||
#ifndef LWS_NO_EXTENSIONS
|
||||
/*
|
||||
* Figure out which extensions the client has that we want to
|
||||
* enable on this connection, and give him back the list
|
||||
*/
|
||||
if (lws_extension_server_handshake(context, wsi, &p))
|
||||
goto bail;
|
||||
#endif
|
||||
/* end of response packet */
|
||||
|
||||
LWS_CPYAPP(p, "\x0d\x0a\x0d\x0a");
|
||||
|
||||
if (!lws_any_extension_handled(context, wsi,
|
||||
LWS_EXT_CALLBACK_HANDSHAKE_REPLY_TX,
|
||||
response, p - response)) {
|
||||
|
||||
/* okay send the handshake response accepting the connection */
|
||||
|
||||
lwsl_parser("issuing resp pkt %d len\n", (int)(p - response));
|
||||
#ifdef DEBUG
|
||||
fwrite(response, 1, p - response, stderr);
|
||||
#endif
|
||||
n = libwebsocket_write(wsi, (unsigned char *)response,
|
||||
p - response, LWS_WRITE_HTTP);
|
||||
if (n != (p - response)) {
|
||||
lwsl_debug("handshake_0405: ERROR writing to socket\n");
|
||||
goto bail;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/* alright clean up and set ourselves into established state */
|
||||
|
||||
wsi->state = WSI_STATE_ESTABLISHED;
|
||||
wsi->lws_rx_parse_state = LWS_RXPS_NEW;
|
||||
|
||||
/* notify user code that we're ready to roll */
|
||||
|
||||
if (wsi->protocol->callback)
|
||||
wsi->protocol->callback(wsi->protocol->owning_server,
|
||||
wsi, LWS_CALLBACK_ESTABLISHED,
|
||||
wsi->user_space, NULL, 0);
|
||||
|
||||
return 0;
|
||||
|
||||
|
||||
bail:
|
||||
/* free up his parsing allocations */
|
||||
|
||||
if (wsi->u.hdr.ah)
|
||||
free(wsi->u.hdr.ah);
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,868 @@
|
||||
/*
|
||||
* libwebsockets - small server side websockets and web server implementation
|
||||
*
|
||||
* Copyright (C) 2010-2013 Andy Green <[email protected]>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation:
|
||||
* version 2.1 of the License.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
||||
* MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
|
||||
#include "private-libwebsockets.h"
|
||||
|
||||
int lws_context_init_server(struct lws_context_creation_info *info,
|
||||
struct libwebsocket_context *context)
|
||||
{
|
||||
int n;
|
||||
int sockfd;
|
||||
struct sockaddr_in sin;
|
||||
socklen_t len = sizeof(sin);
|
||||
int opt = 1;
|
||||
struct libwebsocket *wsi;
|
||||
#ifdef LWS_USE_IPV6
|
||||
struct sockaddr_in6 serv_addr6;
|
||||
#endif
|
||||
struct sockaddr_in serv_addr4;
|
||||
struct sockaddr *v;
|
||||
|
||||
/* set up our external listening socket we serve on */
|
||||
|
||||
if (info->port == CONTEXT_PORT_NO_LISTEN)
|
||||
return 0;
|
||||
|
||||
#ifdef LWS_USE_IPV6
|
||||
if (LWS_IPV6_ENABLED(context))
|
||||
sockfd = socket(AF_INET6, SOCK_STREAM, 0);
|
||||
else
|
||||
#endif
|
||||
sockfd = socket(AF_INET, SOCK_STREAM, 0);
|
||||
|
||||
if (sockfd < 0) {
|
||||
lwsl_err("ERROR opening socket\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* allow us to restart even if old sockets in TIME_WAIT
|
||||
*/
|
||||
setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR,
|
||||
(const void *)&opt, sizeof(opt));
|
||||
|
||||
lws_plat_set_socket_options(context, sockfd);
|
||||
|
||||
#ifdef LWS_USE_IPV6
|
||||
if (LWS_IPV6_ENABLED(context)) {
|
||||
v = (struct sockaddr *)&serv_addr6;
|
||||
n = sizeof(struct sockaddr_in6);
|
||||
bzero((char *) &serv_addr6, sizeof(serv_addr6));
|
||||
serv_addr6.sin6_addr = in6addr_any;
|
||||
serv_addr6.sin6_family = AF_INET6;
|
||||
serv_addr6.sin6_port = htons(info->port);
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
v = (struct sockaddr *)&serv_addr4;
|
||||
n = sizeof(serv_addr4);
|
||||
bzero((char *) &serv_addr4, sizeof(serv_addr4));
|
||||
serv_addr4.sin_addr.s_addr = INADDR_ANY;
|
||||
serv_addr4.sin_family = AF_INET;
|
||||
serv_addr4.sin_port = htons(info->port);
|
||||
|
||||
if (info->iface) {
|
||||
if (interface_to_sa(context, info->iface,
|
||||
(struct sockaddr_in *)v, n) < 0) {
|
||||
lwsl_err("Unable to find interface %s\n",
|
||||
info->iface);
|
||||
compatible_close(sockfd);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
} /* ipv4 */
|
||||
|
||||
n = bind(sockfd, v, n);
|
||||
if (n < 0) {
|
||||
lwsl_err("ERROR on binding to port %d (%d %d)\n",
|
||||
info->port, n, LWS_ERRNO);
|
||||
compatible_close(sockfd);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (getsockname(sockfd, (struct sockaddr *)&sin, &len) == -1)
|
||||
lwsl_warn("getsockname: %s\n", strerror(LWS_ERRNO));
|
||||
else
|
||||
info->port = ntohs(sin.sin_port);
|
||||
|
||||
context->listen_port = info->port;
|
||||
|
||||
wsi = (struct libwebsocket *)malloc(sizeof(struct libwebsocket));
|
||||
if (wsi == NULL) {
|
||||
lwsl_err("Out of mem\n");
|
||||
compatible_close(sockfd);
|
||||
return 1;
|
||||
}
|
||||
memset(wsi, 0, sizeof(struct libwebsocket));
|
||||
wsi->sock = sockfd;
|
||||
wsi->mode = LWS_CONNMODE_SERVER_LISTENER;
|
||||
|
||||
insert_wsi_socket_into_fds(context, wsi);
|
||||
|
||||
context->listen_service_modulo = LWS_LISTEN_SERVICE_MODULO;
|
||||
context->listen_service_count = 0;
|
||||
context->listen_service_fd = sockfd;
|
||||
|
||||
listen(sockfd, LWS_SOMAXCONN);
|
||||
lwsl_notice(" Listening on port %d\n", info->port);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
_libwebsocket_rx_flow_control(struct libwebsocket *wsi)
|
||||
{
|
||||
struct libwebsocket_context *context = wsi->protocol->owning_server;
|
||||
|
||||
/* there is no pending change */
|
||||
if (!(wsi->u.ws.rxflow_change_to & LWS_RXFLOW_PENDING_CHANGE))
|
||||
return 0;
|
||||
|
||||
/* stuff is still buffered, not ready to really accept new input */
|
||||
if (wsi->u.ws.rxflow_buffer) {
|
||||
/* get ourselves called back to deal with stashed buffer */
|
||||
libwebsocket_callback_on_writable(context, wsi);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* pending is cleared, we can change rxflow state */
|
||||
|
||||
wsi->u.ws.rxflow_change_to &= ~LWS_RXFLOW_PENDING_CHANGE;
|
||||
|
||||
lwsl_info("rxflow: wsi %p change_to %d\n", wsi,
|
||||
wsi->u.ws.rxflow_change_to & LWS_RXFLOW_ALLOW);
|
||||
|
||||
/* adjust the pollfd for this wsi */
|
||||
|
||||
if (wsi->u.ws.rxflow_change_to & LWS_RXFLOW_ALLOW) {
|
||||
if (lws_change_pollfd(wsi, 0, LWS_POLLIN)) {
|
||||
lwsl_info("%s: fail\n", __func__);
|
||||
return -1;
|
||||
}
|
||||
} else
|
||||
if (lws_change_pollfd(wsi, LWS_POLLIN, 0))
|
||||
return -1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int lws_handshake_server(struct libwebsocket_context *context,
|
||||
struct libwebsocket *wsi, unsigned char **buf, size_t len)
|
||||
{
|
||||
struct allocated_headers *ah;
|
||||
char *uri_ptr = NULL;
|
||||
int uri_len = 0;
|
||||
char content_length_str[32];
|
||||
int n;
|
||||
|
||||
/* LWS_CONNMODE_WS_SERVING */
|
||||
|
||||
while (len--) {
|
||||
if (libwebsocket_parse(wsi, *(*buf)++)) {
|
||||
lwsl_info("libwebsocket_parse failed\n");
|
||||
goto bail_nuke_ah;
|
||||
}
|
||||
|
||||
if (wsi->u.hdr.parser_state != WSI_PARSING_COMPLETE)
|
||||
continue;
|
||||
|
||||
lwsl_parser("libwebsocket_parse sees parsing complete\n");
|
||||
|
||||
wsi->mode = LWS_CONNMODE_PRE_WS_SERVING_ACCEPT;
|
||||
libwebsocket_set_timeout(wsi, NO_PENDING_TIMEOUT, 0);
|
||||
|
||||
/* is this websocket protocol or normal http 1.0? */
|
||||
|
||||
if (!lws_hdr_total_length(wsi, WSI_TOKEN_UPGRADE) ||
|
||||
!lws_hdr_total_length(wsi, WSI_TOKEN_CONNECTION)) {
|
||||
|
||||
/* it's not websocket.... shall we accept it as http? */
|
||||
|
||||
if (!lws_hdr_total_length(wsi, WSI_TOKEN_GET_URI) &&
|
||||
!lws_hdr_total_length(wsi, WSI_TOKEN_POST_URI)) {
|
||||
lwsl_warn("Missing URI in HTTP request\n");
|
||||
goto bail_nuke_ah;
|
||||
}
|
||||
|
||||
if (lws_hdr_total_length(wsi, WSI_TOKEN_GET_URI) &&
|
||||
lws_hdr_total_length(wsi, WSI_TOKEN_POST_URI)) {
|
||||
lwsl_warn("GET and POST methods?\n");
|
||||
goto bail_nuke_ah;
|
||||
}
|
||||
|
||||
if (libwebsocket_ensure_user_space(wsi))
|
||||
goto bail_nuke_ah;
|
||||
|
||||
if (lws_hdr_total_length(wsi, WSI_TOKEN_GET_URI)) {
|
||||
uri_ptr = lws_hdr_simple_ptr(wsi, WSI_TOKEN_GET_URI);
|
||||
uri_len = lws_hdr_total_length(wsi, WSI_TOKEN_GET_URI);
|
||||
lwsl_info("HTTP GET request for '%s'\n",
|
||||
lws_hdr_simple_ptr(wsi, WSI_TOKEN_GET_URI));
|
||||
|
||||
}
|
||||
if (lws_hdr_total_length(wsi, WSI_TOKEN_POST_URI)) {
|
||||
lwsl_info("HTTP POST request for '%s'\n",
|
||||
lws_hdr_simple_ptr(wsi, WSI_TOKEN_POST_URI));
|
||||
uri_ptr = lws_hdr_simple_ptr(wsi, WSI_TOKEN_POST_URI);
|
||||
uri_len = lws_hdr_total_length(wsi, WSI_TOKEN_POST_URI);
|
||||
}
|
||||
|
||||
/*
|
||||
* Hm we still need the headers so the
|
||||
* callback can look at leaders like the URI, but we
|
||||
* need to transition to http union state.... hold a
|
||||
* copy of u.hdr.ah and deallocate afterwards
|
||||
*/
|
||||
ah = wsi->u.hdr.ah;
|
||||
|
||||
/* union transition */
|
||||
memset(&wsi->u, 0, sizeof(wsi->u));
|
||||
wsi->mode = LWS_CONNMODE_HTTP_SERVING_ACCEPTED;
|
||||
wsi->state = WSI_STATE_HTTP;
|
||||
wsi->u.http.fd = LWS_INVALID_FILE;
|
||||
|
||||
/* expose it at the same offset as u.hdr */
|
||||
wsi->u.http.ah = ah;
|
||||
|
||||
/* HTTP header had a content length? */
|
||||
|
||||
wsi->u.http.content_length = 0;
|
||||
if (lws_hdr_total_length(wsi, WSI_TOKEN_POST_URI))
|
||||
wsi->u.http.content_length = 100 * 1024 * 1024;
|
||||
|
||||
if (lws_hdr_total_length(wsi, WSI_TOKEN_HTTP_CONTENT_LENGTH)) {
|
||||
lws_hdr_copy(wsi, content_length_str,
|
||||
sizeof(content_length_str) - 1,
|
||||
WSI_TOKEN_HTTP_CONTENT_LENGTH);
|
||||
wsi->u.http.content_length = atoi(content_length_str);
|
||||
}
|
||||
|
||||
if (wsi->u.http.content_length > 0) {
|
||||
wsi->u.http.body_index = 0;
|
||||
n = wsi->protocol->rx_buffer_size;
|
||||
if (!n)
|
||||
n = LWS_MAX_SOCKET_IO_BUF;
|
||||
wsi->u.http.post_buffer = malloc(n);
|
||||
if (!wsi->u.http.post_buffer) {
|
||||
lwsl_err("Unable to allocate post buffer\n");
|
||||
n = -1;
|
||||
goto cleanup;
|
||||
}
|
||||
}
|
||||
|
||||
n = 0;
|
||||
if (wsi->protocol->callback)
|
||||
n = wsi->protocol->callback(context, wsi,
|
||||
LWS_CALLBACK_FILTER_HTTP_CONNECTION,
|
||||
wsi->user_space, uri_ptr, uri_len);
|
||||
|
||||
if (!n) {
|
||||
/*
|
||||
* if there is content supposed to be coming,
|
||||
* put a timeout on it having arrived
|
||||
*/
|
||||
libwebsocket_set_timeout(wsi,
|
||||
PENDING_TIMEOUT_HTTP_CONTENT,
|
||||
AWAITING_TIMEOUT);
|
||||
|
||||
if (wsi->protocol->callback)
|
||||
n = wsi->protocol->callback(context, wsi,
|
||||
LWS_CALLBACK_HTTP,
|
||||
wsi->user_space, uri_ptr, uri_len);
|
||||
}
|
||||
|
||||
cleanup:
|
||||
/* now drop the header info we kept a pointer to */
|
||||
if (ah)
|
||||
free(ah);
|
||||
/* not possible to continue to use past here */
|
||||
wsi->u.http.ah = NULL;
|
||||
|
||||
if (n) {
|
||||
lwsl_info("LWS_CALLBACK_HTTP closing\n");
|
||||
return 1; /* struct ah ptr already nuked */
|
||||
}
|
||||
|
||||
/*
|
||||
* (if callback didn't start sending a file)
|
||||
* deal with anything else as body, whether
|
||||
* there was a content-length or not
|
||||
*/
|
||||
|
||||
if (wsi->state != WSI_STATE_HTTP_ISSUING_FILE)
|
||||
wsi->state = WSI_STATE_HTTP_BODY;
|
||||
return 2; /* goto http_postbody; */
|
||||
}
|
||||
|
||||
if (!wsi->protocol)
|
||||
lwsl_err("NULL protocol at libwebsocket_read\n");
|
||||
|
||||
/*
|
||||
* It's websocket
|
||||
*
|
||||
* Make sure user side is happy about protocol
|
||||
*/
|
||||
|
||||
while (wsi->protocol->callback) {
|
||||
|
||||
if (!lws_hdr_total_length(wsi, WSI_TOKEN_PROTOCOL)) {
|
||||
if (wsi->protocol->name == NULL)
|
||||
break;
|
||||
} else
|
||||
if (wsi->protocol->name && strcmp(
|
||||
lws_hdr_simple_ptr(wsi,
|
||||
WSI_TOKEN_PROTOCOL),
|
||||
wsi->protocol->name) == 0)
|
||||
break;
|
||||
|
||||
wsi->protocol++;
|
||||
}
|
||||
|
||||
/* we didn't find a protocol he wanted? */
|
||||
|
||||
if (wsi->protocol->callback == NULL) {
|
||||
if (lws_hdr_simple_ptr(wsi, WSI_TOKEN_PROTOCOL) ==
|
||||
NULL) {
|
||||
lwsl_info("no protocol -> prot 0 handler\n");
|
||||
wsi->protocol = &context->protocols[0];
|
||||
} else {
|
||||
lwsl_err("Req protocol %s not supported\n",
|
||||
lws_hdr_simple_ptr(wsi, WSI_TOKEN_PROTOCOL));
|
||||
goto bail_nuke_ah;
|
||||
}
|
||||
}
|
||||
|
||||
/* allocate wsi->user storage */
|
||||
if (libwebsocket_ensure_user_space(wsi))
|
||||
goto bail_nuke_ah;
|
||||
|
||||
/*
|
||||
* Give the user code a chance to study the request and
|
||||
* have the opportunity to deny it
|
||||
*/
|
||||
|
||||
if ((wsi->protocol->callback)(wsi->protocol->owning_server, wsi,
|
||||
LWS_CALLBACK_FILTER_PROTOCOL_CONNECTION,
|
||||
wsi->user_space,
|
||||
lws_hdr_simple_ptr(wsi, WSI_TOKEN_PROTOCOL), 0)) {
|
||||
lwsl_warn("User code denied connection\n");
|
||||
goto bail_nuke_ah;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Perform the handshake according to the protocol version the
|
||||
* client announced
|
||||
*/
|
||||
|
||||
switch (wsi->ietf_spec_revision) {
|
||||
case 13:
|
||||
lwsl_parser("lws_parse calling handshake_04\n");
|
||||
if (handshake_0405(context, wsi)) {
|
||||
lwsl_info("hs0405 has failed the connection\n");
|
||||
goto bail_nuke_ah;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
lwsl_warn("Unknown client spec version %d\n",
|
||||
wsi->ietf_spec_revision);
|
||||
goto bail_nuke_ah;
|
||||
}
|
||||
|
||||
/* drop the header info -- no bail_nuke_ah after this */
|
||||
|
||||
if (wsi->u.hdr.ah)
|
||||
free(wsi->u.hdr.ah);
|
||||
|
||||
wsi->mode = LWS_CONNMODE_WS_SERVING;
|
||||
|
||||
/* union transition */
|
||||
memset(&wsi->u, 0, sizeof(wsi->u));
|
||||
wsi->u.ws.rxflow_change_to = LWS_RXFLOW_ALLOW;
|
||||
|
||||
/*
|
||||
* create the frame buffer for this connection according to the
|
||||
* size mentioned in the protocol definition. If 0 there, use
|
||||
* a big default for compatibility
|
||||
*/
|
||||
|
||||
n = wsi->protocol->rx_buffer_size;
|
||||
if (!n)
|
||||
n = LWS_MAX_SOCKET_IO_BUF;
|
||||
n += LWS_SEND_BUFFER_PRE_PADDING + LWS_SEND_BUFFER_POST_PADDING;
|
||||
wsi->u.ws.rx_user_buffer = malloc(n);
|
||||
if (!wsi->u.ws.rx_user_buffer) {
|
||||
lwsl_err("Out of Mem allocating rx buffer %d\n", n);
|
||||
return 1;
|
||||
}
|
||||
lwsl_info("Allocating RX buffer %d\n", n);
|
||||
|
||||
if (setsockopt(wsi->sock, SOL_SOCKET, SO_SNDBUF, (const char *)&n, sizeof n)) {
|
||||
lwsl_warn("Failed to set SNDBUF to %d", n);
|
||||
return 1;
|
||||
}
|
||||
|
||||
lwsl_parser("accepted v%02d connection\n",
|
||||
wsi->ietf_spec_revision);
|
||||
} /* while all chars are handled */
|
||||
|
||||
return 0;
|
||||
|
||||
bail_nuke_ah:
|
||||
/* drop the header info */
|
||||
if (wsi->u.hdr.ah)
|
||||
free(wsi->u.hdr.ah);
|
||||
return 1;
|
||||
}
|
||||
|
||||
struct libwebsocket *
|
||||
libwebsocket_create_new_server_wsi(struct libwebsocket_context *context)
|
||||
{
|
||||
struct libwebsocket *new_wsi;
|
||||
|
||||
new_wsi = (struct libwebsocket *)malloc(sizeof(struct libwebsocket));
|
||||
if (new_wsi == NULL) {
|
||||
lwsl_err("Out of memory for new connection\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
memset(new_wsi, 0, sizeof(struct libwebsocket));
|
||||
new_wsi->pending_timeout = NO_PENDING_TIMEOUT;
|
||||
|
||||
/* intialize the instance struct */
|
||||
|
||||
new_wsi->state = WSI_STATE_HTTP;
|
||||
new_wsi->mode = LWS_CONNMODE_HTTP_SERVING;
|
||||
new_wsi->hdr_parsing_completed = 0;
|
||||
|
||||
if (lws_allocate_header_table(new_wsi)) {
|
||||
free(new_wsi);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* these can only be set once the protocol is known
|
||||
* we set an unestablished connection's protocol pointer
|
||||
* to the start of the supported list, so it can look
|
||||
* for matching ones during the handshake
|
||||
*/
|
||||
new_wsi->protocol = context->protocols;
|
||||
new_wsi->user_space = NULL;
|
||||
new_wsi->ietf_spec_revision = 0;
|
||||
|
||||
/*
|
||||
* outermost create notification for wsi
|
||||
* no user_space because no protocol selection
|
||||
*/
|
||||
context->protocols[0].callback(context, new_wsi,
|
||||
LWS_CALLBACK_WSI_CREATE, NULL, NULL, 0);
|
||||
|
||||
return new_wsi;
|
||||
}
|
||||
|
||||
int lws_server_socket_service(struct libwebsocket_context *context,
|
||||
struct libwebsocket *wsi, struct libwebsocket_pollfd *pollfd)
|
||||
{
|
||||
struct libwebsocket *new_wsi = NULL;
|
||||
int accept_fd = 0;
|
||||
socklen_t clilen;
|
||||
struct sockaddr_in cli_addr;
|
||||
int n;
|
||||
int len;
|
||||
|
||||
switch (wsi->mode) {
|
||||
|
||||
case LWS_CONNMODE_HTTP_SERVING:
|
||||
case LWS_CONNMODE_HTTP_SERVING_ACCEPTED:
|
||||
|
||||
/* handle http headers coming in */
|
||||
|
||||
/* pending truncated sends have uber priority */
|
||||
|
||||
if (wsi->truncated_send_malloc) {
|
||||
if (pollfd->revents & LWS_POLLOUT)
|
||||
if (lws_issue_raw(wsi, wsi->truncated_send_malloc +
|
||||
wsi->truncated_send_offset,
|
||||
wsi->truncated_send_len) < 0) {
|
||||
lwsl_info("closing from socket service\n");
|
||||
return -1;
|
||||
}
|
||||
/*
|
||||
* we can't afford to allow input processing send
|
||||
* something new, so spin around he event loop until
|
||||
* he doesn't have any partials
|
||||
*/
|
||||
break;
|
||||
}
|
||||
|
||||
/* any incoming data ready? */
|
||||
|
||||
if (pollfd->revents & LWS_POLLIN) {
|
||||
len = lws_ssl_capable_read(wsi,
|
||||
context->service_buffer,
|
||||
sizeof(context->service_buffer));
|
||||
switch (len) {
|
||||
case 0:
|
||||
lwsl_info("lws_server_skt_srv: read 0 len\n");
|
||||
/* lwsl_info(" state=%d\n", wsi->state); */
|
||||
if (!wsi->hdr_parsing_completed)
|
||||
free(wsi->u.hdr.ah);
|
||||
/* fallthru */
|
||||
case LWS_SSL_CAPABLE_ERROR:
|
||||
libwebsocket_close_and_free_session(
|
||||
context, wsi,
|
||||
LWS_CLOSE_STATUS_NOSTATUS);
|
||||
return 0;
|
||||
case LWS_SSL_CAPABLE_MORE_SERVICE:
|
||||
break;
|
||||
}
|
||||
|
||||
/* just ignore incoming if waiting for close */
|
||||
if (wsi->state != WSI_STATE_FLUSHING_STORED_SEND_BEFORE_CLOSE) {
|
||||
|
||||
/* hm this may want to send (via HTTP callback for example) */
|
||||
|
||||
n = libwebsocket_read(context, wsi,
|
||||
context->service_buffer, len);
|
||||
if (n < 0)
|
||||
/* we closed wsi */
|
||||
return 0;
|
||||
|
||||
/* hum he may have used up the writability above */
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* this handles POLLOUT for http serving fragments */
|
||||
|
||||
if (!(pollfd->revents & LWS_POLLOUT))
|
||||
break;
|
||||
|
||||
/* one shot */
|
||||
if (lws_change_pollfd(wsi, LWS_POLLOUT, 0))
|
||||
goto fail;
|
||||
|
||||
lws_libev_io(context, wsi, LWS_EV_STOP | LWS_EV_WRITE);
|
||||
|
||||
if (wsi->state != WSI_STATE_HTTP_ISSUING_FILE) {
|
||||
n = user_callback_handle_rxflow(
|
||||
wsi->protocol->callback,
|
||||
wsi->protocol->owning_server,
|
||||
wsi, LWS_CALLBACK_HTTP_WRITEABLE,
|
||||
wsi->user_space,
|
||||
NULL,
|
||||
0);
|
||||
if (n < 0)
|
||||
libwebsocket_close_and_free_session(
|
||||
context, wsi, LWS_CLOSE_STATUS_NOSTATUS);
|
||||
break;
|
||||
}
|
||||
|
||||
/* nonzero for completion or error */
|
||||
if (libwebsockets_serve_http_file_fragment(context, wsi))
|
||||
libwebsocket_close_and_free_session(context, wsi,
|
||||
LWS_CLOSE_STATUS_NOSTATUS);
|
||||
break;
|
||||
|
||||
case LWS_CONNMODE_SERVER_LISTENER:
|
||||
|
||||
/* pollin means a client has connected to us then */
|
||||
|
||||
if (!(pollfd->revents & LWS_POLLIN))
|
||||
break;
|
||||
|
||||
/* listen socket got an unencrypted connection... */
|
||||
|
||||
clilen = sizeof(cli_addr);
|
||||
lws_latency_pre(context, wsi);
|
||||
accept_fd = accept(pollfd->fd, (struct sockaddr *)&cli_addr,
|
||||
&clilen);
|
||||
lws_latency(context, wsi,
|
||||
"unencrypted accept LWS_CONNMODE_SERVER_LISTENER",
|
||||
accept_fd, accept_fd >= 0);
|
||||
if (accept_fd < 0) {
|
||||
if (LWS_ERRNO == LWS_EAGAIN || LWS_ERRNO == LWS_EWOULDBLOCK) {
|
||||
lwsl_debug("accept asks to try again\n");
|
||||
break;
|
||||
}
|
||||
lwsl_warn("ERROR on accept: %s\n", strerror(LWS_ERRNO));
|
||||
break;
|
||||
}
|
||||
|
||||
lws_plat_set_socket_options(context, accept_fd);
|
||||
|
||||
/*
|
||||
* look at who we connected to and give user code a chance
|
||||
* to reject based on client IP. There's no protocol selected
|
||||
* yet so we issue this to protocols[0]
|
||||
*/
|
||||
|
||||
if ((context->protocols[0].callback)(context, wsi,
|
||||
LWS_CALLBACK_FILTER_NETWORK_CONNECTION,
|
||||
NULL, (void *)(long)accept_fd, 0)) {
|
||||
lwsl_debug("Callback denied network connection\n");
|
||||
compatible_close(accept_fd);
|
||||
break;
|
||||
}
|
||||
|
||||
new_wsi = libwebsocket_create_new_server_wsi(context);
|
||||
if (new_wsi == NULL) {
|
||||
compatible_close(accept_fd);
|
||||
break;
|
||||
}
|
||||
|
||||
new_wsi->sock = accept_fd;
|
||||
|
||||
/* the transport is accepted... give him time to negotiate */
|
||||
libwebsocket_set_timeout(new_wsi,
|
||||
PENDING_TIMEOUT_ESTABLISH_WITH_SERVER,
|
||||
AWAITING_TIMEOUT);
|
||||
|
||||
/*
|
||||
* A new connection was accepted. Give the user a chance to
|
||||
* set properties of the newly created wsi. There's no protocol
|
||||
* selected yet so we issue this to protocols[0]
|
||||
*/
|
||||
|
||||
(context->protocols[0].callback)(context, new_wsi,
|
||||
LWS_CALLBACK_SERVER_NEW_CLIENT_INSTANTIATED, NULL, NULL, 0);
|
||||
|
||||
lws_libev_accept(context, new_wsi, accept_fd);
|
||||
|
||||
if (!LWS_SSL_ENABLED(context)) {
|
||||
lwsl_debug("accepted new conn port %u on fd=%d\n",
|
||||
ntohs(cli_addr.sin_port), accept_fd);
|
||||
|
||||
insert_wsi_socket_into_fds(context, new_wsi);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (lws_server_socket_service_ssl(context, &wsi, new_wsi, accept_fd, pollfd))
|
||||
goto fail;
|
||||
|
||||
return 0;
|
||||
|
||||
fail:
|
||||
libwebsocket_close_and_free_session(context, wsi,
|
||||
LWS_CLOSE_STATUS_NOSTATUS);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
static const char *err400[] = {
|
||||
"Bad Request",
|
||||
"Unauthorized",
|
||||
"Payment Required",
|
||||
"Forbidden",
|
||||
"Not Found",
|
||||
"Method Not Allowed",
|
||||
"Not Acceptable",
|
||||
"Proxy Auth Required",
|
||||
"Request Timeout",
|
||||
"Conflict",
|
||||
"Gone",
|
||||
"Length Required",
|
||||
"Precondition Failed",
|
||||
"Request Entity Too Large",
|
||||
"Request URI too Long",
|
||||
"Unsupported Media Type",
|
||||
"Requested Range Not Satisfiable",
|
||||
"Expectation Failed"
|
||||
};
|
||||
|
||||
static const char *err500[] = {
|
||||
"Internal Server Error",
|
||||
"Not Implemented",
|
||||
"Bad Gateway",
|
||||
"Service Unavailable",
|
||||
"Gateway Timeout",
|
||||
"HTTP Version Not Supported"
|
||||
};
|
||||
|
||||
/**
|
||||
* libwebsockets_return_http_status() - Return simple http status
|
||||
* @context: libwebsockets context
|
||||
* @wsi: Websocket instance (available from user callback)
|
||||
* @code: Status index, eg, 404
|
||||
* @html_body: User-readable HTML description, or NULL
|
||||
*
|
||||
* Helper to report HTTP errors back to the client cleanly and
|
||||
* consistently
|
||||
*/
|
||||
LWS_VISIBLE int libwebsockets_return_http_status(
|
||||
struct libwebsocket_context *context, struct libwebsocket *wsi,
|
||||
unsigned int code, const char *html_body)
|
||||
{
|
||||
int n, m;
|
||||
const char *description = "";
|
||||
|
||||
if (!html_body)
|
||||
html_body = "";
|
||||
|
||||
if (code >= 400 && code < (400 + ARRAY_SIZE(err400)))
|
||||
description = err400[code - 400];
|
||||
if (code >= 500 && code < (500 + ARRAY_SIZE(err500)))
|
||||
description = err500[code - 500];
|
||||
|
||||
n = sprintf((char *)context->service_buffer,
|
||||
"HTTP/1.0 %u %s\x0d\x0a"
|
||||
"Server: libwebsockets\x0d\x0a"
|
||||
"Content-Type: text/html\x0d\x0a\x0d\x0a"
|
||||
"<h1>%u %s</h1>%s",
|
||||
code, description, code, description, html_body);
|
||||
|
||||
lwsl_info((const char *)context->service_buffer);
|
||||
|
||||
m = libwebsocket_write(wsi, context->service_buffer, n, LWS_WRITE_HTTP);
|
||||
|
||||
return m;
|
||||
}
|
||||
|
||||
/**
|
||||
* libwebsockets_serve_http_file() - Send a file back to the client using http
|
||||
* @context: libwebsockets context
|
||||
* @wsi: Websocket instance (available from user callback)
|
||||
* @file: The file to issue over http
|
||||
* @content_type: The http content type, eg, text/html
|
||||
* @other_headers: NULL or pointer to \0-terminated other header string
|
||||
*
|
||||
* This function is intended to be called from the callback in response
|
||||
* to http requests from the client. It allows the callback to issue
|
||||
* local files down the http link in a single step.
|
||||
*
|
||||
* Returning <0 indicates error and the wsi should be closed. Returning
|
||||
* >0 indicates the file was completely sent and the wsi should be closed.
|
||||
* ==0 indicates the file transfer is started and needs more service later,
|
||||
* the wsi should be left alone.
|
||||
*/
|
||||
|
||||
LWS_VISIBLE int libwebsockets_serve_http_file(
|
||||
struct libwebsocket_context *context,
|
||||
struct libwebsocket *wsi, const char *file,
|
||||
const char *content_type, const char *other_headers)
|
||||
{
|
||||
unsigned char *p = context->service_buffer;
|
||||
int ret = 0;
|
||||
int n;
|
||||
|
||||
wsi->u.http.fd = lws_plat_open_file(file, &wsi->u.http.filelen);
|
||||
|
||||
if (wsi->u.http.fd == LWS_INVALID_FILE) {
|
||||
lwsl_err("Unable to open '%s'\n", file);
|
||||
libwebsockets_return_http_status(context, wsi,
|
||||
HTTP_STATUS_NOT_FOUND, NULL);
|
||||
return -1;
|
||||
}
|
||||
|
||||
p += sprintf((char *)p,
|
||||
"HTTP/1.0 200 OK\x0d\x0aServer: libwebsockets\x0d\x0a""Content-Type: %s\x0d\x0a",
|
||||
content_type);
|
||||
if (other_headers) {
|
||||
n = strlen(other_headers);
|
||||
memcpy(p, other_headers, n);
|
||||
p += n;
|
||||
}
|
||||
p += sprintf((char *)p,
|
||||
"Content-Length: %lu\x0d\x0a\x0d\x0a", wsi->u.http.filelen);
|
||||
|
||||
ret = libwebsocket_write(wsi, context->service_buffer,
|
||||
p - context->service_buffer, LWS_WRITE_HTTP);
|
||||
if (ret != (p - context->service_buffer)) {
|
||||
lwsl_err("_write returned %d from %d\n", ret, (p - context->service_buffer));
|
||||
return -1;
|
||||
}
|
||||
|
||||
wsi->u.http.filepos = 0;
|
||||
wsi->state = WSI_STATE_HTTP_ISSUING_FILE;
|
||||
|
||||
return libwebsockets_serve_http_file_fragment(context, wsi);
|
||||
}
|
||||
|
||||
|
||||
int libwebsocket_interpret_incoming_packet(struct libwebsocket *wsi,
|
||||
unsigned char *buf, size_t len)
|
||||
{
|
||||
size_t n = 0;
|
||||
int m;
|
||||
|
||||
#if 0
|
||||
lwsl_parser("received %d byte packet\n", (int)len);
|
||||
lwsl_hexdump(buf, len);
|
||||
#endif
|
||||
|
||||
/* let the rx protocol state machine have as much as it needs */
|
||||
|
||||
while (n < len) {
|
||||
/*
|
||||
* we were accepting input but now we stopped doing so
|
||||
*/
|
||||
if (!(wsi->u.ws.rxflow_change_to & LWS_RXFLOW_ALLOW)) {
|
||||
/* his RX is flowcontrolled, don't send remaining now */
|
||||
if (!wsi->u.ws.rxflow_buffer) {
|
||||
/* a new rxflow, buffer it and warn caller */
|
||||
lwsl_info("new rxflow input buffer len %d\n",
|
||||
len - n);
|
||||
wsi->u.ws.rxflow_buffer =
|
||||
(unsigned char *)malloc(len - n);
|
||||
wsi->u.ws.rxflow_len = len - n;
|
||||
wsi->u.ws.rxflow_pos = 0;
|
||||
memcpy(wsi->u.ws.rxflow_buffer,
|
||||
buf + n, len - n);
|
||||
} else
|
||||
/* rxflow while we were spilling prev rxflow */
|
||||
lwsl_info("stalling in existing rxflow buf\n");
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* account for what we're using in rxflow buffer */
|
||||
if (wsi->u.ws.rxflow_buffer)
|
||||
wsi->u.ws.rxflow_pos++;
|
||||
|
||||
/* process the byte */
|
||||
m = libwebsocket_rx_sm(wsi, buf[n++]);
|
||||
if (m < 0)
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
LWS_VISIBLE void
|
||||
lws_server_get_canonical_hostname(struct libwebsocket_context *context,
|
||||
struct lws_context_creation_info *info)
|
||||
{
|
||||
if (info->options & LWS_SERVER_OPTION_SKIP_SERVER_CANONICAL_NAME)
|
||||
return;
|
||||
|
||||
/* find canonical hostname */
|
||||
gethostname((char *)context->canonical_hostname,
|
||||
sizeof(context->canonical_hostname) - 1);
|
||||
|
||||
lwsl_notice(" canonical_hostname = %s\n", context->canonical_hostname);
|
||||
}
|
||||
@@ -0,0 +1,514 @@
|
||||
/*
|
||||
* libwebsockets - small server side websockets and web server implementation
|
||||
*
|
||||
* Copyright (C) 2010-2014 Andy Green <[email protected]>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation:
|
||||
* version 2.1 of the License.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
||||
* MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#include "private-libwebsockets.h"
|
||||
|
||||
int
|
||||
lws_handle_POLLOUT_event(struct libwebsocket_context *context,
|
||||
struct libwebsocket *wsi, struct libwebsocket_pollfd *pollfd)
|
||||
{
|
||||
int n;
|
||||
struct lws_tokens eff_buf;
|
||||
int ret;
|
||||
int m;
|
||||
int handled = 0;
|
||||
|
||||
/* pending truncated sends have uber priority */
|
||||
|
||||
if (wsi->truncated_send_len) {
|
||||
if (lws_issue_raw(wsi, wsi->truncated_send_malloc +
|
||||
wsi->truncated_send_offset,
|
||||
wsi->truncated_send_len) < 0) {
|
||||
lwsl_info("lws_handle_POLLOUT_event signalling to close\n");
|
||||
return -1;
|
||||
}
|
||||
/* leave POLLOUT active either way */
|
||||
return 0;
|
||||
} else
|
||||
if (wsi->state == WSI_STATE_FLUSHING_STORED_SEND_BEFORE_CLOSE) {
|
||||
lwsl_info("***** %x signalling to close in POLLOUT handler\n", wsi);
|
||||
return -1; /* retry closing now */
|
||||
}
|
||||
|
||||
|
||||
m = lws_ext_callback_for_each_active(wsi, LWS_EXT_CALLBACK_IS_WRITEABLE,
|
||||
NULL, 0);
|
||||
if (handled == 1)
|
||||
goto notify_action;
|
||||
#ifndef LWS_NO_EXTENSIONS
|
||||
if (!wsi->extension_data_pending || handled == 2)
|
||||
goto user_service;
|
||||
#endif
|
||||
/*
|
||||
* check in on the active extensions, see if they
|
||||
* had pending stuff to spill... they need to get the
|
||||
* first look-in otherwise sequence will be disordered
|
||||
*
|
||||
* NULL, zero-length eff_buf means just spill pending
|
||||
*/
|
||||
|
||||
ret = 1;
|
||||
while (ret == 1) {
|
||||
|
||||
/* default to nobody has more to spill */
|
||||
|
||||
ret = 0;
|
||||
eff_buf.token = NULL;
|
||||
eff_buf.token_len = 0;
|
||||
|
||||
/* give every extension a chance to spill */
|
||||
|
||||
m = lws_ext_callback_for_each_active(wsi,
|
||||
LWS_EXT_CALLBACK_PACKET_TX_PRESEND,
|
||||
&eff_buf, 0);
|
||||
if (m < 0) {
|
||||
lwsl_err("ext reports fatal error\n");
|
||||
return -1;
|
||||
}
|
||||
if (m)
|
||||
/*
|
||||
* at least one extension told us he has more
|
||||
* to spill, so we will go around again after
|
||||
*/
|
||||
ret = 1;
|
||||
|
||||
/* assuming they gave us something to send, send it */
|
||||
|
||||
if (eff_buf.token_len) {
|
||||
n = lws_issue_raw(wsi, (unsigned char *)eff_buf.token,
|
||||
eff_buf.token_len);
|
||||
if (n < 0) {
|
||||
lwsl_info("closing from POLLOUT spill\n");
|
||||
return -1;
|
||||
}
|
||||
/*
|
||||
* Keep amount spilled small to minimize chance of this
|
||||
*/
|
||||
if (n != eff_buf.token_len) {
|
||||
lwsl_err("Unable to spill ext %d vs %s\n",
|
||||
eff_buf.token_len, n);
|
||||
return -1;
|
||||
}
|
||||
} else
|
||||
continue;
|
||||
|
||||
/* no extension has more to spill */
|
||||
|
||||
if (!ret)
|
||||
continue;
|
||||
|
||||
/*
|
||||
* There's more to spill from an extension, but we just sent
|
||||
* something... did that leave the pipe choked?
|
||||
*/
|
||||
|
||||
if (!lws_send_pipe_choked(wsi))
|
||||
/* no we could add more */
|
||||
continue;
|
||||
|
||||
lwsl_info("choked in POLLOUT service\n");
|
||||
|
||||
/*
|
||||
* Yes, he's choked. Leave the POLLOUT masked on so we will
|
||||
* come back here when he is unchoked. Don't call the user
|
||||
* callback to enforce ordering of spilling, he'll get called
|
||||
* when we come back here and there's nothing more to spill.
|
||||
*/
|
||||
|
||||
return 0;
|
||||
}
|
||||
#ifndef LWS_NO_EXTENSIONS
|
||||
wsi->extension_data_pending = 0;
|
||||
|
||||
user_service:
|
||||
#endif
|
||||
/* one shot */
|
||||
|
||||
if (pollfd) {
|
||||
if (lws_change_pollfd(wsi, LWS_POLLOUT, 0))
|
||||
return 1;
|
||||
|
||||
lws_libev_io(context, wsi, LWS_EV_STOP | LWS_EV_WRITE);
|
||||
}
|
||||
|
||||
notify_action:
|
||||
if (wsi->mode == LWS_CONNMODE_WS_CLIENT)
|
||||
n = LWS_CALLBACK_CLIENT_WRITEABLE;
|
||||
else
|
||||
n = LWS_CALLBACK_SERVER_WRITEABLE;
|
||||
|
||||
return user_callback_handle_rxflow(wsi->protocol->callback, context,
|
||||
wsi, (enum libwebsocket_callback_reasons) n,
|
||||
wsi->user_space, NULL, 0);
|
||||
}
|
||||
|
||||
|
||||
|
||||
int
|
||||
libwebsocket_service_timeout_check(struct libwebsocket_context *context,
|
||||
struct libwebsocket *wsi, unsigned int sec)
|
||||
{
|
||||
/*
|
||||
* if extensions want in on it (eg, we are a mux parent)
|
||||
* give them a chance to service child timeouts
|
||||
*/
|
||||
if (lws_ext_callback_for_each_active(wsi, LWS_EXT_CALLBACK_1HZ, NULL, sec) < 0)
|
||||
return 0;
|
||||
|
||||
if (!wsi->pending_timeout)
|
||||
return 0;
|
||||
|
||||
/*
|
||||
* if we went beyond the allowed time, kill the
|
||||
* connection
|
||||
*/
|
||||
if (sec > wsi->pending_timeout_limit) {
|
||||
lwsl_info("TIMEDOUT WAITING on %d\n", wsi->pending_timeout);
|
||||
libwebsocket_close_and_free_session(context,
|
||||
wsi, LWS_CLOSE_STATUS_NOSTATUS);
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* libwebsocket_service_fd() - Service polled socket with something waiting
|
||||
* @context: Websocket context
|
||||
* @pollfd: The pollfd entry describing the socket fd and which events
|
||||
* happened.
|
||||
*
|
||||
* This function takes a pollfd that has POLLIN or POLLOUT activity and
|
||||
* services it according to the state of the associated
|
||||
* struct libwebsocket.
|
||||
*
|
||||
* The one call deals with all "service" that might happen on a socket
|
||||
* including listen accepts, http files as well as websocket protocol.
|
||||
*
|
||||
* If a pollfd says it has something, you can just pass it to
|
||||
* libwebsocket_serice_fd() whether it is a socket handled by lws or not.
|
||||
* If it sees it is a lws socket, the traffic will be handled and
|
||||
* pollfd->revents will be zeroed now.
|
||||
*
|
||||
* If the socket is foreign to lws, it leaves revents alone. So you can
|
||||
* see if you should service yourself by checking the pollfd revents
|
||||
* after letting lws try to service it.
|
||||
*/
|
||||
|
||||
LWS_VISIBLE int
|
||||
libwebsocket_service_fd(struct libwebsocket_context *context,
|
||||
struct libwebsocket_pollfd *pollfd)
|
||||
{
|
||||
struct libwebsocket *wsi;
|
||||
int n;
|
||||
int m;
|
||||
int listen_socket_fds_index = 0;
|
||||
time_t now;
|
||||
int timed_out = 0;
|
||||
int our_fd = 0;
|
||||
char draining_flow = 0;
|
||||
int more;
|
||||
struct lws_tokens eff_buf;
|
||||
|
||||
if (context->listen_service_fd)
|
||||
listen_socket_fds_index = context->lws_lookup[
|
||||
context->listen_service_fd]->position_in_fds_table;
|
||||
|
||||
/*
|
||||
* you can call us with pollfd = NULL to just allow the once-per-second
|
||||
* global timeout checks; if less than a second since the last check
|
||||
* it returns immediately then.
|
||||
*/
|
||||
|
||||
time(&now);
|
||||
|
||||
/* TODO: if using libev, we should probably use timeout watchers... */
|
||||
if (context->last_timeout_check_s != now) {
|
||||
context->last_timeout_check_s = now;
|
||||
|
||||
lws_plat_service_periodic(context);
|
||||
|
||||
/* global timeout check once per second */
|
||||
|
||||
if (pollfd)
|
||||
our_fd = pollfd->fd;
|
||||
|
||||
for (n = 0; n < context->fds_count; n++) {
|
||||
m = context->fds[n].fd;
|
||||
wsi = context->lws_lookup[m];
|
||||
if (!wsi)
|
||||
continue;
|
||||
|
||||
if (libwebsocket_service_timeout_check(context, wsi, now))
|
||||
/* he did time out... */
|
||||
if (m == our_fd) {
|
||||
/* it was the guy we came to service! */
|
||||
timed_out = 1;
|
||||
/* mark as handled */
|
||||
pollfd->revents = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* the socket we came to service timed out, nothing to do */
|
||||
if (timed_out)
|
||||
return 0;
|
||||
|
||||
/* just here for timeout management? */
|
||||
if (pollfd == NULL)
|
||||
return 0;
|
||||
|
||||
/* no, here to service a socket descriptor */
|
||||
wsi = context->lws_lookup[pollfd->fd];
|
||||
if (wsi == NULL)
|
||||
/* not lws connection ... leave revents alone and return */
|
||||
return 0;
|
||||
|
||||
/*
|
||||
* so that caller can tell we handled, past here we need to
|
||||
* zero down pollfd->revents after handling
|
||||
*/
|
||||
|
||||
/*
|
||||
* deal with listen service piggybacking
|
||||
* every listen_service_modulo services of other fds, we
|
||||
* sneak one in to service the listen socket if there's anything waiting
|
||||
*
|
||||
* To handle connection storms, as found in ab, if we previously saw a
|
||||
* pending connection here, it causes us to check again next time.
|
||||
*/
|
||||
|
||||
if (context->listen_service_fd && pollfd !=
|
||||
&context->fds[listen_socket_fds_index]) {
|
||||
context->listen_service_count++;
|
||||
if (context->listen_service_extraseen ||
|
||||
context->listen_service_count ==
|
||||
context->listen_service_modulo) {
|
||||
context->listen_service_count = 0;
|
||||
m = 1;
|
||||
if (context->listen_service_extraseen > 5)
|
||||
m = 2;
|
||||
while (m--) {
|
||||
/*
|
||||
* even with extpoll, we prepared this
|
||||
* internal fds for listen
|
||||
*/
|
||||
n = lws_poll_listen_fd(&context->fds[listen_socket_fds_index]);
|
||||
if (n > 0) { /* there's a conn waiting for us */
|
||||
libwebsocket_service_fd(context,
|
||||
&context->
|
||||
fds[listen_socket_fds_index]);
|
||||
context->listen_service_extraseen++;
|
||||
} else {
|
||||
if (context->listen_service_extraseen)
|
||||
context->
|
||||
listen_service_extraseen--;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/* handle session socket closed */
|
||||
|
||||
if ((!(pollfd->revents & LWS_POLLIN)) &&
|
||||
(pollfd->revents & LWS_POLLHUP)) {
|
||||
|
||||
lwsl_debug("Session Socket %p (fd=%d) dead\n",
|
||||
(void *)wsi, pollfd->fd);
|
||||
|
||||
goto close_and_handled;
|
||||
}
|
||||
|
||||
/* okay, what we came here to do... */
|
||||
|
||||
switch (wsi->mode) {
|
||||
case LWS_CONNMODE_HTTP_SERVING:
|
||||
case LWS_CONNMODE_HTTP_SERVING_ACCEPTED:
|
||||
case LWS_CONNMODE_SERVER_LISTENER:
|
||||
case LWS_CONNMODE_SSL_ACK_PENDING:
|
||||
n = lws_server_socket_service(context, wsi, pollfd);
|
||||
if (n < 0)
|
||||
goto close_and_handled;
|
||||
goto handled;
|
||||
|
||||
case LWS_CONNMODE_WS_SERVING:
|
||||
case LWS_CONNMODE_WS_CLIENT:
|
||||
|
||||
/* the guy requested a callback when it was OK to write */
|
||||
|
||||
if ((pollfd->revents & LWS_POLLOUT) &&
|
||||
(wsi->state == WSI_STATE_ESTABLISHED ||
|
||||
wsi->state == WSI_STATE_FLUSHING_STORED_SEND_BEFORE_CLOSE) &&
|
||||
lws_handle_POLLOUT_event(context, wsi, pollfd)) {
|
||||
lwsl_info("libwebsocket_service_fd: closing\n");
|
||||
goto close_and_handled;
|
||||
}
|
||||
|
||||
if (wsi->u.ws.rxflow_buffer &&
|
||||
(wsi->u.ws.rxflow_change_to & LWS_RXFLOW_ALLOW)) {
|
||||
lwsl_info("draining rxflow\n");
|
||||
/* well, drain it */
|
||||
eff_buf.token = (char *)wsi->u.ws.rxflow_buffer +
|
||||
wsi->u.ws.rxflow_pos;
|
||||
eff_buf.token_len = wsi->u.ws.rxflow_len -
|
||||
wsi->u.ws.rxflow_pos;
|
||||
draining_flow = 1;
|
||||
goto drain;
|
||||
}
|
||||
|
||||
/* any incoming data ready? */
|
||||
|
||||
if (!(pollfd->revents & LWS_POLLIN))
|
||||
break;
|
||||
|
||||
read_pending:
|
||||
eff_buf.token_len = lws_ssl_capable_read(wsi,
|
||||
context->service_buffer,
|
||||
sizeof(context->service_buffer));
|
||||
switch (eff_buf.token_len) {
|
||||
case 0:
|
||||
lwsl_info("service_fd: closing due to 0 length read\n");
|
||||
goto close_and_handled;
|
||||
case LWS_SSL_CAPABLE_ERROR:
|
||||
n = 0;
|
||||
goto handled;
|
||||
case LWS_SSL_CAPABLE_MORE_SERVICE:
|
||||
goto close_and_handled;
|
||||
}
|
||||
|
||||
/*
|
||||
* give any active extensions a chance to munge the buffer
|
||||
* before parse. We pass in a pointer to an lws_tokens struct
|
||||
* prepared with the default buffer and content length that's in
|
||||
* there. Rather than rewrite the default buffer, extensions
|
||||
* that expect to grow the buffer can adapt .token to
|
||||
* point to their own per-connection buffer in the extension
|
||||
* user allocation. By default with no extensions or no
|
||||
* extension callback handling, just the normal input buffer is
|
||||
* used then so it is efficient.
|
||||
*/
|
||||
|
||||
eff_buf.token = (char *)context->service_buffer;
|
||||
drain:
|
||||
|
||||
do {
|
||||
|
||||
more = 0;
|
||||
|
||||
m = lws_ext_callback_for_each_active(wsi,
|
||||
LWS_EXT_CALLBACK_PACKET_RX_PREPARSE, &eff_buf, 0);
|
||||
if (m < 0)
|
||||
goto close_and_handled;
|
||||
if (m)
|
||||
more = 1;
|
||||
|
||||
/* service incoming data */
|
||||
|
||||
if (eff_buf.token_len) {
|
||||
n = libwebsocket_read(context, wsi,
|
||||
(unsigned char *)eff_buf.token,
|
||||
eff_buf.token_len);
|
||||
if (n < 0) {
|
||||
/* we closed wsi */
|
||||
n = 0;
|
||||
goto handled;
|
||||
}
|
||||
}
|
||||
|
||||
eff_buf.token = NULL;
|
||||
eff_buf.token_len = 0;
|
||||
} while (more);
|
||||
|
||||
if (draining_flow && wsi->u.ws.rxflow_buffer &&
|
||||
wsi->u.ws.rxflow_pos == wsi->u.ws.rxflow_len) {
|
||||
lwsl_info("flow buffer: drained\n");
|
||||
free(wsi->u.ws.rxflow_buffer);
|
||||
wsi->u.ws.rxflow_buffer = NULL;
|
||||
/* having drained the rxflow buffer, can rearm POLLIN */
|
||||
n = _libwebsocket_rx_flow_control(wsi); /* n ignored, needed for NO_SERVER case */
|
||||
}
|
||||
|
||||
if (lws_ssl_pending(wsi))
|
||||
goto read_pending;
|
||||
break;
|
||||
|
||||
default:
|
||||
#ifdef LWS_NO_CLIENT
|
||||
break;
|
||||
#else
|
||||
n = lws_client_socket_service(context, wsi, pollfd);
|
||||
goto handled;
|
||||
#endif
|
||||
}
|
||||
|
||||
n = 0;
|
||||
goto handled;
|
||||
|
||||
close_and_handled:
|
||||
libwebsocket_close_and_free_session(context, wsi,
|
||||
LWS_CLOSE_STATUS_NOSTATUS);
|
||||
n = 1;
|
||||
|
||||
handled:
|
||||
pollfd->revents = 0;
|
||||
return n;
|
||||
}
|
||||
|
||||
/**
|
||||
* libwebsocket_service() - Service any pending websocket activity
|
||||
* @context: Websocket context
|
||||
* @timeout_ms: Timeout for poll; 0 means return immediately if nothing needed
|
||||
* service otherwise block and service immediately, returning
|
||||
* after the timeout if nothing needed service.
|
||||
*
|
||||
* This function deals with any pending websocket traffic, for three
|
||||
* kinds of event. It handles these events on both server and client
|
||||
* types of connection the same.
|
||||
*
|
||||
* 1) Accept new connections to our context's server
|
||||
*
|
||||
* 2) Call the receive callback for incoming frame data received by
|
||||
* server or client connections.
|
||||
*
|
||||
* You need to call this service function periodically to all the above
|
||||
* functions to happen; if your application is single-threaded you can
|
||||
* just call it in your main event loop.
|
||||
*
|
||||
* Alternatively you can fork a new process that asynchronously handles
|
||||
* calling this service in a loop. In that case you are happy if this
|
||||
* call blocks your thread until it needs to take care of something and
|
||||
* would call it with a large nonzero timeout. Your loop then takes no
|
||||
* CPU while there is nothing happening.
|
||||
*
|
||||
* If you are calling it in a single-threaded app, you don't want it to
|
||||
* wait around blocking other things in your loop from happening, so you
|
||||
* would call it with a timeout_ms of 0, so it returns immediately if
|
||||
* nothing is pending, or as soon as it services whatever was pending.
|
||||
*/
|
||||
|
||||
LWS_VISIBLE int
|
||||
libwebsocket_service(struct libwebsocket_context *context, int timeout_ms)
|
||||
{
|
||||
return lws_plat_service(context, timeout_ms);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,301 @@
|
||||
/*
|
||||
* Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the project nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
/*
|
||||
* FIPS pub 180-1: Secure Hash Algorithm (SHA-1)
|
||||
* based on: http://csrc.nist.gov/fips/fip180-1.txt
|
||||
* implemented by Jun-ichiro itojun Itoh <[email protected]>
|
||||
*/
|
||||
|
||||
#include "private-libwebsockets.h"
|
||||
|
||||
#ifdef HAVE_SYS_TYPES_H
|
||||
#include <sys/types.h>
|
||||
#endif
|
||||
|
||||
struct sha1_ctxt {
|
||||
union {
|
||||
unsigned char b8[20];
|
||||
unsigned int b32[5];
|
||||
} h;
|
||||
union {
|
||||
unsigned char b8[8];
|
||||
u_int64_t b64[1];
|
||||
} c;
|
||||
union {
|
||||
unsigned char b8[64];
|
||||
unsigned int b32[16];
|
||||
} m;
|
||||
unsigned char count;
|
||||
};
|
||||
|
||||
/* sanity check */
|
||||
#if !defined(BYTE_ORDER) || !defined(LITTLE_ENDIAN) || !defined(BIG_ENDIAN)
|
||||
# define unsupported 1
|
||||
#elif BYTE_ORDER != BIG_ENDIAN
|
||||
# if BYTE_ORDER != LITTLE_ENDIAN
|
||||
# define unsupported 1
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifndef unsupported
|
||||
|
||||
/* constant table */
|
||||
static const unsigned int _K[] =
|
||||
{ 0x5a827999, 0x6ed9eba1, 0x8f1bbcdc, 0xca62c1d6 };
|
||||
#define K(t) _K[(t) / 20]
|
||||
|
||||
#define F0(b, c, d) (((b) & (c)) | ((~(b)) & (d)))
|
||||
#define F1(b, c, d) (((b) ^ (c)) ^ (d))
|
||||
#define F2(b, c, d) (((b) & (c)) | ((b) & (d)) | ((c) & (d)))
|
||||
#define F3(b, c, d) (((b) ^ (c)) ^ (d))
|
||||
|
||||
#define S(n, x) (((x) << (n)) | ((x) >> (32 - n)))
|
||||
|
||||
#define H(n) (ctxt->h.b32[(n)])
|
||||
#define COUNT (ctxt->count)
|
||||
#define BCOUNT (ctxt->c.b64[0] / 8)
|
||||
#define W(n) (ctxt->m.b32[(n)])
|
||||
|
||||
#define PUTBYTE(x) { \
|
||||
ctxt->m.b8[(COUNT % 64)] = (x); \
|
||||
COUNT++; \
|
||||
COUNT %= 64; \
|
||||
ctxt->c.b64[0] += 8; \
|
||||
if (COUNT % 64 == 0) \
|
||||
sha1_step(ctxt); \
|
||||
}
|
||||
|
||||
#define PUTPAD(x) { \
|
||||
ctxt->m.b8[(COUNT % 64)] = (x); \
|
||||
COUNT++; \
|
||||
COUNT %= 64; \
|
||||
if (COUNT % 64 == 0) \
|
||||
sha1_step(ctxt); \
|
||||
}
|
||||
|
||||
static void sha1_step __P((struct sha1_ctxt *));
|
||||
|
||||
static void
|
||||
sha1_step(struct sha1_ctxt *ctxt)
|
||||
{
|
||||
unsigned int a, b, c, d, e, tmp;
|
||||
size_t t, s;
|
||||
|
||||
#if BYTE_ORDER == LITTLE_ENDIAN
|
||||
struct sha1_ctxt tctxt;
|
||||
|
||||
memcpy(&tctxt.m.b8[0], &ctxt->m.b8[0], 64);
|
||||
ctxt->m.b8[0] = tctxt.m.b8[3]; ctxt->m.b8[1] = tctxt.m.b8[2];
|
||||
ctxt->m.b8[2] = tctxt.m.b8[1]; ctxt->m.b8[3] = tctxt.m.b8[0];
|
||||
ctxt->m.b8[4] = tctxt.m.b8[7]; ctxt->m.b8[5] = tctxt.m.b8[6];
|
||||
ctxt->m.b8[6] = tctxt.m.b8[5]; ctxt->m.b8[7] = tctxt.m.b8[4];
|
||||
ctxt->m.b8[8] = tctxt.m.b8[11]; ctxt->m.b8[9] = tctxt.m.b8[10];
|
||||
ctxt->m.b8[10] = tctxt.m.b8[9]; ctxt->m.b8[11] = tctxt.m.b8[8];
|
||||
ctxt->m.b8[12] = tctxt.m.b8[15]; ctxt->m.b8[13] = tctxt.m.b8[14];
|
||||
ctxt->m.b8[14] = tctxt.m.b8[13]; ctxt->m.b8[15] = tctxt.m.b8[12];
|
||||
ctxt->m.b8[16] = tctxt.m.b8[19]; ctxt->m.b8[17] = tctxt.m.b8[18];
|
||||
ctxt->m.b8[18] = tctxt.m.b8[17]; ctxt->m.b8[19] = tctxt.m.b8[16];
|
||||
ctxt->m.b8[20] = tctxt.m.b8[23]; ctxt->m.b8[21] = tctxt.m.b8[22];
|
||||
ctxt->m.b8[22] = tctxt.m.b8[21]; ctxt->m.b8[23] = tctxt.m.b8[20];
|
||||
ctxt->m.b8[24] = tctxt.m.b8[27]; ctxt->m.b8[25] = tctxt.m.b8[26];
|
||||
ctxt->m.b8[26] = tctxt.m.b8[25]; ctxt->m.b8[27] = tctxt.m.b8[24];
|
||||
ctxt->m.b8[28] = tctxt.m.b8[31]; ctxt->m.b8[29] = tctxt.m.b8[30];
|
||||
ctxt->m.b8[30] = tctxt.m.b8[29]; ctxt->m.b8[31] = tctxt.m.b8[28];
|
||||
ctxt->m.b8[32] = tctxt.m.b8[35]; ctxt->m.b8[33] = tctxt.m.b8[34];
|
||||
ctxt->m.b8[34] = tctxt.m.b8[33]; ctxt->m.b8[35] = tctxt.m.b8[32];
|
||||
ctxt->m.b8[36] = tctxt.m.b8[39]; ctxt->m.b8[37] = tctxt.m.b8[38];
|
||||
ctxt->m.b8[38] = tctxt.m.b8[37]; ctxt->m.b8[39] = tctxt.m.b8[36];
|
||||
ctxt->m.b8[40] = tctxt.m.b8[43]; ctxt->m.b8[41] = tctxt.m.b8[42];
|
||||
ctxt->m.b8[42] = tctxt.m.b8[41]; ctxt->m.b8[43] = tctxt.m.b8[40];
|
||||
ctxt->m.b8[44] = tctxt.m.b8[47]; ctxt->m.b8[45] = tctxt.m.b8[46];
|
||||
ctxt->m.b8[46] = tctxt.m.b8[45]; ctxt->m.b8[47] = tctxt.m.b8[44];
|
||||
ctxt->m.b8[48] = tctxt.m.b8[51]; ctxt->m.b8[49] = tctxt.m.b8[50];
|
||||
ctxt->m.b8[50] = tctxt.m.b8[49]; ctxt->m.b8[51] = tctxt.m.b8[48];
|
||||
ctxt->m.b8[52] = tctxt.m.b8[55]; ctxt->m.b8[53] = tctxt.m.b8[54];
|
||||
ctxt->m.b8[54] = tctxt.m.b8[53]; ctxt->m.b8[55] = tctxt.m.b8[52];
|
||||
ctxt->m.b8[56] = tctxt.m.b8[59]; ctxt->m.b8[57] = tctxt.m.b8[58];
|
||||
ctxt->m.b8[58] = tctxt.m.b8[57]; ctxt->m.b8[59] = tctxt.m.b8[56];
|
||||
ctxt->m.b8[60] = tctxt.m.b8[63]; ctxt->m.b8[61] = tctxt.m.b8[62];
|
||||
ctxt->m.b8[62] = tctxt.m.b8[61]; ctxt->m.b8[63] = tctxt.m.b8[60];
|
||||
#endif
|
||||
|
||||
a = H(0); b = H(1); c = H(2); d = H(3); e = H(4);
|
||||
|
||||
for (t = 0; t < 20; t++) {
|
||||
s = t & 0x0f;
|
||||
if (t >= 16)
|
||||
W(s) = S(1, W((s+13) & 0x0f) ^ W((s+8) & 0x0f) ^
|
||||
W((s+2) & 0x0f) ^ W(s));
|
||||
|
||||
tmp = S(5, a) + F0(b, c, d) + e + W(s) + K(t);
|
||||
e = d; d = c; c = S(30, b); b = a; a = tmp;
|
||||
}
|
||||
for (t = 20; t < 40; t++) {
|
||||
s = t & 0x0f;
|
||||
W(s) = S(1, W((s+13) & 0x0f) ^ W((s+8) & 0x0f) ^
|
||||
W((s+2) & 0x0f) ^ W(s));
|
||||
tmp = S(5, a) + F1(b, c, d) + e + W(s) + K(t);
|
||||
e = d; d = c; c = S(30, b); b = a; a = tmp;
|
||||
}
|
||||
for (t = 40; t < 60; t++) {
|
||||
s = t & 0x0f;
|
||||
W(s) = S(1, W((s+13) & 0x0f) ^ W((s+8) & 0x0f) ^
|
||||
W((s+2) & 0x0f) ^ W(s));
|
||||
tmp = S(5, a) + F2(b, c, d) + e + W(s) + K(t);
|
||||
e = d; d = c; c = S(30, b); b = a; a = tmp;
|
||||
}
|
||||
for (t = 60; t < 80; t++) {
|
||||
s = t & 0x0f;
|
||||
W(s) = S(1, W((s+13) & 0x0f) ^ W((s+8) & 0x0f) ^
|
||||
W((s+2) & 0x0f) ^ W(s));
|
||||
tmp = S(5, a) + F3(b, c, d) + e + W(s) + K(t);
|
||||
e = d; d = c; c = S(30, b); b = a; a = tmp;
|
||||
}
|
||||
|
||||
H(0) = H(0) + a;
|
||||
H(1) = H(1) + b;
|
||||
H(2) = H(2) + c;
|
||||
H(3) = H(3) + d;
|
||||
H(4) = H(4) + e;
|
||||
|
||||
bzero(&ctxt->m.b8[0], 64);
|
||||
}
|
||||
|
||||
/*------------------------------------------------------------*/
|
||||
|
||||
static void
|
||||
sha1_init(struct sha1_ctxt *ctxt)
|
||||
{
|
||||
bzero(ctxt, sizeof(struct sha1_ctxt));
|
||||
H(0) = 0x67452301;
|
||||
H(1) = 0xefcdab89;
|
||||
H(2) = 0x98badcfe;
|
||||
H(3) = 0x10325476;
|
||||
H(4) = 0xc3d2e1f0;
|
||||
}
|
||||
|
||||
void
|
||||
sha1_pad(struct sha1_ctxt *ctxt)
|
||||
{
|
||||
size_t padlen; /*pad length in bytes*/
|
||||
size_t padstart;
|
||||
|
||||
PUTPAD(0x80);
|
||||
|
||||
padstart = COUNT % 64;
|
||||
padlen = 64 - padstart;
|
||||
if (padlen < 8) {
|
||||
bzero(&ctxt->m.b8[padstart], padlen);
|
||||
COUNT += padlen;
|
||||
COUNT %= 64;
|
||||
sha1_step(ctxt);
|
||||
padstart = COUNT % 64; /* should be 0 */
|
||||
padlen = 64 - padstart; /* should be 64 */
|
||||
}
|
||||
bzero(&ctxt->m.b8[padstart], padlen - 8);
|
||||
COUNT += (padlen - 8);
|
||||
COUNT %= 64;
|
||||
#if BYTE_ORDER == BIG_ENDIAN
|
||||
PUTPAD(ctxt->c.b8[0]); PUTPAD(ctxt->c.b8[1]);
|
||||
PUTPAD(ctxt->c.b8[2]); PUTPAD(ctxt->c.b8[3]);
|
||||
PUTPAD(ctxt->c.b8[4]); PUTPAD(ctxt->c.b8[5]);
|
||||
PUTPAD(ctxt->c.b8[6]); PUTPAD(ctxt->c.b8[7]);
|
||||
#else
|
||||
PUTPAD(ctxt->c.b8[7]); PUTPAD(ctxt->c.b8[6]);
|
||||
PUTPAD(ctxt->c.b8[5]); PUTPAD(ctxt->c.b8[4]);
|
||||
PUTPAD(ctxt->c.b8[3]); PUTPAD(ctxt->c.b8[2]);
|
||||
PUTPAD(ctxt->c.b8[1]); PUTPAD(ctxt->c.b8[0]);
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
sha1_loop(struct sha1_ctxt *ctxt, const unsigned char *input, size_t len)
|
||||
{
|
||||
size_t gaplen;
|
||||
size_t gapstart;
|
||||
size_t off;
|
||||
size_t copysiz;
|
||||
|
||||
off = 0;
|
||||
|
||||
while (off < len) {
|
||||
gapstart = COUNT % 64;
|
||||
gaplen = 64 - gapstart;
|
||||
|
||||
copysiz = (gaplen < len - off) ? gaplen : len - off;
|
||||
memcpy(&ctxt->m.b8[gapstart], &input[off], copysiz);
|
||||
COUNT += copysiz;
|
||||
COUNT %= 64;
|
||||
ctxt->c.b64[0] += copysiz * 8;
|
||||
if (COUNT % 64 == 0)
|
||||
sha1_step(ctxt);
|
||||
off += copysiz;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
sha1_result(struct sha1_ctxt *ctxt, void *digest0)
|
||||
{
|
||||
unsigned char *digest;
|
||||
|
||||
digest = (unsigned char *)digest0;
|
||||
sha1_pad(ctxt);
|
||||
#if BYTE_ORDER == BIG_ENDIAN
|
||||
memcpy(digest, &ctxt->h.b8[0], 20);
|
||||
#else
|
||||
digest[0] = ctxt->h.b8[3]; digest[1] = ctxt->h.b8[2];
|
||||
digest[2] = ctxt->h.b8[1]; digest[3] = ctxt->h.b8[0];
|
||||
digest[4] = ctxt->h.b8[7]; digest[5] = ctxt->h.b8[6];
|
||||
digest[6] = ctxt->h.b8[5]; digest[7] = ctxt->h.b8[4];
|
||||
digest[8] = ctxt->h.b8[11]; digest[9] = ctxt->h.b8[10];
|
||||
digest[10] = ctxt->h.b8[9]; digest[11] = ctxt->h.b8[8];
|
||||
digest[12] = ctxt->h.b8[15]; digest[13] = ctxt->h.b8[14];
|
||||
digest[14] = ctxt->h.b8[13]; digest[15] = ctxt->h.b8[12];
|
||||
digest[16] = ctxt->h.b8[19]; digest[17] = ctxt->h.b8[18];
|
||||
digest[18] = ctxt->h.b8[17]; digest[19] = ctxt->h.b8[16];
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
* This should look and work like the libcrypto implementation
|
||||
*/
|
||||
|
||||
unsigned char *
|
||||
SHA1(const unsigned char *d, size_t n, unsigned char *md)
|
||||
{
|
||||
struct sha1_ctxt ctx;
|
||||
|
||||
sha1_init(&ctx);
|
||||
sha1_loop(&ctx, d, n);
|
||||
sha1_result(&ctx, (void *)md);
|
||||
|
||||
return md;
|
||||
}
|
||||
|
||||
#endif /*unsupported*/
|
||||
@@ -475,7 +475,7 @@ _zip_d2u_time(int dtime, int ddate)
|
||||
{
|
||||
struct tm tm;
|
||||
|
||||
memset(&tm, sizeof(tm), 0);
|
||||
memset(&tm, 0, sizeof(tm));
|
||||
|
||||
/* let mktime decide if DST is in effect */
|
||||
tm.tm_isdst = -1;
|
||||
|
||||
@@ -232,7 +232,7 @@ void x86_block::ApplyPatches(u8* base)
|
||||
x86_block::x86_block()
|
||||
{
|
||||
_patches=new vector<code_patch>;
|
||||
_labels=new vector<code_patch>;
|
||||
_labels=new vector<x86_Label*>;
|
||||
opcode_count=0;
|
||||
}
|
||||
x86_block::~x86_block()
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
|
||||
ALIGN(4096) dsp_t dsp;
|
||||
|
||||
#if HOST_OS==OS_WINDOWS
|
||||
#if HOST_OS==OS_WINDOWS && !defined(HOST_NO_REC)
|
||||
#include "emitter/x86_emitter.h"
|
||||
|
||||
const bool SUPPORT_NOFL=false;
|
||||
|
||||
Regular → Executable
+6
-2
@@ -17,7 +17,6 @@
|
||||
#endif
|
||||
|
||||
//Sound generation, mixin, and channel regs emulation
|
||||
|
||||
//x.15
|
||||
s32 volume_lut[16];
|
||||
//255 -> mute
|
||||
@@ -1289,7 +1288,7 @@ void AICA_Sample32()
|
||||
pl=mixl;
|
||||
pr=mixr;
|
||||
|
||||
WriteSample(mixr,mixl);
|
||||
if (!settings.aica.NoSound) WriteSample(mixr,mixl);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1335,6 +1334,11 @@ void AICA_Sample()
|
||||
}
|
||||
}
|
||||
|
||||
if (settings.aica.NoSound)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
//Mono !
|
||||
if (CommonData->Mono)
|
||||
{
|
||||
|
||||
@@ -789,7 +789,7 @@ u32 DYNACALL DoMemOp(u32 addr,u32 data)
|
||||
{
|
||||
u32 rv=0;
|
||||
|
||||
#if HOST_CPU==CPU_X86
|
||||
#if HOST_CPU==CPU_X86 && !defined(HOST_NO_REC)
|
||||
addr=virt_arm_reg(0);
|
||||
data=virt_arm_reg(1);
|
||||
#endif
|
||||
@@ -809,7 +809,7 @@ u32 DYNACALL DoMemOp(u32 addr,u32 data)
|
||||
arm_WriteMem32(addr,data);
|
||||
}
|
||||
|
||||
#if HOST_CPU==CPU_X86
|
||||
#if HOST_CPU==CPU_X86 && !defined(HOST_NO_REC)
|
||||
virt_arm_reg(0)=rv;
|
||||
#endif
|
||||
|
||||
@@ -817,7 +817,7 @@ u32 DYNACALL DoMemOp(u32 addr,u32 data)
|
||||
}
|
||||
|
||||
//findfirstset -- used in LDM/STM handling
|
||||
#if HOST_CPU==CPU_X86
|
||||
#if HOST_CPU==CPU_X86 && BUILD_COMPILER != COMPILER_GCC
|
||||
#include <intrin.h>
|
||||
|
||||
u32 findfirstset(u32 v)
|
||||
@@ -2086,7 +2086,7 @@ void FlushCache()
|
||||
|
||||
|
||||
|
||||
#if HOST_CPU==CPU_X86
|
||||
#if HOST_CPU==CPU_X86 && HOST_OS == OS_WINDOWS
|
||||
|
||||
#include <Windows.h>
|
||||
|
||||
|
||||
+32
-12
@@ -19,6 +19,11 @@
|
||||
|
||||
int gdrom_schid;
|
||||
|
||||
//Sense: ASC - ASCQ - Key
|
||||
signed int sns_asc=0;
|
||||
signed int sns_ascq=0;
|
||||
signed int sns_key=0;
|
||||
|
||||
enum gd_states
|
||||
{
|
||||
//Generic
|
||||
@@ -447,7 +452,11 @@ void gd_process_ata_cmd()
|
||||
{
|
||||
//Any ATA command clears these bits, unless aborted/error :p
|
||||
Error.ABRT=0;
|
||||
GDStatus.CHECK=0;
|
||||
|
||||
if (sns_key==0x0 || sns_key==0xB)
|
||||
GDStatus.CHECK=0;
|
||||
else
|
||||
GDStatus.CHECK=1;
|
||||
|
||||
switch(ata_cmd.command)
|
||||
{
|
||||
@@ -464,7 +473,7 @@ void gd_process_ata_cmd()
|
||||
//the above comment is from a wrong place in the docs ...
|
||||
|
||||
Error.ABRT=1;
|
||||
//Error.Sense=0x00; //fixme ?
|
||||
Error.Sense=sns_key;
|
||||
GDStatus.BSY=0;
|
||||
GDStatus.CHECK=1;
|
||||
|
||||
@@ -519,12 +528,18 @@ void gd_process_ata_cmd()
|
||||
|
||||
void gd_process_spi_cmd()
|
||||
{
|
||||
|
||||
printf_spi("Sense: %02x %02x %02x \n", sns_asc, sns_ascq, sns_key);
|
||||
|
||||
printf_spi("SPI command %02x;",packet_cmd.data_8[0]);
|
||||
printf_spi("Params: %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x \n",
|
||||
packet_cmd.data_8[0], packet_cmd.data_8[1], packet_cmd.data_8[2], packet_cmd.data_8[3], packet_cmd.data_8[4], packet_cmd.data_8[5],
|
||||
packet_cmd.data_8[6], packet_cmd.data_8[7], packet_cmd.data_8[8], packet_cmd.data_8[9], packet_cmd.data_8[10], packet_cmd.data_8[11] );
|
||||
|
||||
GDStatus.CHECK=0;
|
||||
if (sns_key==0x0 || sns_key==0xB)
|
||||
GDStatus.CHECK=0;
|
||||
else
|
||||
GDStatus.CHECK=1;
|
||||
|
||||
switch(packet_cmd.data_8[0])
|
||||
{
|
||||
@@ -672,18 +687,22 @@ void gd_process_spi_cmd()
|
||||
|
||||
case SPI_REQ_ERROR:
|
||||
printf_spicmd("SPI_REQ_ERROR\n");
|
||||
printf("GDROM: Unhandled Sega SPI frame: SPI_REQ_ERROR\n");
|
||||
//printf("GDROM: Unhandled Sega SPI frame: SPI_REQ_ERROR\n");
|
||||
|
||||
u8 resp[10];
|
||||
resp[0]=0xF0;
|
||||
resp[1]=0;
|
||||
resp[2]= SecNumber.Status==GD_BUSY ? 2:0;//sense
|
||||
resp[2]=sns_key;//sense
|
||||
resp[3]=0;
|
||||
resp[4]=resp[5]=resp[6]=resp[7]=0; //Command Specific Information
|
||||
resp[8]=0;//Additional Sense Code
|
||||
resp[9]=0;//Additional Sense Code Qualifier
|
||||
resp[8]=sns_asc;//Additional Sense Code
|
||||
resp[9]=sns_ascq;//Additional Sense Code Qualifier
|
||||
|
||||
gd_spi_pio_end(resp,packet_cmd.data_8[4]);
|
||||
sns_key=0;
|
||||
sns_asc=0;
|
||||
sns_ascq=0;
|
||||
//GDStatus.CHECK=0;
|
||||
break;
|
||||
|
||||
case SPI_REQ_SES:
|
||||
@@ -915,8 +934,8 @@ u32 ReadMem_gdrom(u32 Addr, u32 sz)
|
||||
if(2!=sz)
|
||||
printf("GDROM: Bad size on DATA REG Read\n");
|
||||
|
||||
if (gd_state == gds_pio_send_data)
|
||||
{
|
||||
//if (gd_state == gds_pio_send_data)
|
||||
//{
|
||||
if (pio_buff.index == pio_buff.size)
|
||||
{
|
||||
printf("GDROM: Illegal Read From DATA (underflow)\n");
|
||||
@@ -935,9 +954,9 @@ u32 ReadMem_gdrom(u32 Addr, u32 sz)
|
||||
return rv;
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
printf("GDROM: Illegal Read From DATA (wrong mode)\n");
|
||||
//}
|
||||
//else
|
||||
// printf("GDROM: Illegal Read From DATA (wrong mode)\n");
|
||||
|
||||
return 0;
|
||||
|
||||
@@ -947,6 +966,7 @@ u32 ReadMem_gdrom(u32 Addr, u32 sz)
|
||||
|
||||
case GD_ERROR_Read:
|
||||
printf_rm("GDROM: Read from ERROR Register\n");
|
||||
Error.Sense=sns_key;
|
||||
return Error.full;
|
||||
|
||||
case GD_IREASON_Read:
|
||||
|
||||
@@ -5,6 +5,14 @@
|
||||
#include "maple_cfg.h"
|
||||
#include <time.h>
|
||||
|
||||
#if _ANDROID
|
||||
#include <android/log.h>
|
||||
#include <jni.h>
|
||||
#else
|
||||
#define LOGW printf
|
||||
#define LOGI printf
|
||||
#endif
|
||||
|
||||
#include "deps/zlib/zlib.h"
|
||||
|
||||
const char* maple_sega_controller_name = "Dreamcast Controller";
|
||||
@@ -225,7 +233,7 @@ struct maple_sega_controller: maple_base
|
||||
return MDRS_DataTransfer;
|
||||
|
||||
default:
|
||||
printf("UNKOWN MAPLE COMMAND %d\n",cmd);
|
||||
//printf("UNKOWN MAPLE COMMAND %d\n",cmd);
|
||||
return MDRE_UnknownFunction;
|
||||
}
|
||||
}
|
||||
@@ -539,6 +547,9 @@ struct maple_sega_vmu: maple_base
|
||||
}
|
||||
}
|
||||
config->SetImage(lcd_data_decoded);
|
||||
#ifndef TARGET_PANDORA
|
||||
push_vmu_screen(lcd_data_decoded);
|
||||
#endif
|
||||
#if 0
|
||||
// Update LCD window
|
||||
if (!dev->lcd.visible)
|
||||
@@ -644,13 +655,193 @@ struct maple_sega_vmu: maple_base
|
||||
|
||||
|
||||
default:
|
||||
printf("Unknown MAPLE COMMAND %d\n",cmd);
|
||||
//printf("Unknown MAPLE COMMAND %d\n",cmd);
|
||||
return MDRE_UnknownCmd;
|
||||
}
|
||||
}
|
||||
};
|
||||
#endif
|
||||
|
||||
struct maple_microphone: maple_base
|
||||
{
|
||||
u8 micdata[SIZE_OF_MIC_DATA];
|
||||
|
||||
virtual void OnSetup()
|
||||
{
|
||||
memset(micdata,0,sizeof(micdata));
|
||||
}
|
||||
|
||||
virtual u32 dma(u32 cmd)
|
||||
{
|
||||
//printf("maple_microphone::dma Called 0x%X;Command %d\n",this->maple_port,cmd);
|
||||
//LOGD("maple_microphone::dma Called 0x%X;Command %d\n",this->maple_port,cmd);
|
||||
|
||||
switch (cmd)
|
||||
{
|
||||
case MDC_DeviceRequest:
|
||||
LOGI("maple_microphone::dma MDC_DeviceRequest");
|
||||
//this was copied from the controller case with just the id and name replaced!
|
||||
|
||||
//caps
|
||||
//4
|
||||
w32(MFID_4_Mic);
|
||||
|
||||
//struct data
|
||||
//3*4
|
||||
w32( 0xfe060f00);
|
||||
w32( 0);
|
||||
w32( 0);
|
||||
|
||||
//1 area code
|
||||
w8(0xFF);
|
||||
|
||||
//1 direction
|
||||
w8(0);
|
||||
|
||||
//30
|
||||
wstr(maple_sega_mic_name,30);
|
||||
|
||||
//60
|
||||
wstr(maple_sega_brand,60);
|
||||
|
||||
//2
|
||||
w16(0x01AE);
|
||||
|
||||
//2
|
||||
w16(0x01F4);
|
||||
|
||||
return MDRS_DeviceStatus;
|
||||
|
||||
case MDCF_GetCondition:
|
||||
{
|
||||
LOGI("maple_microphone::dma MDCF_GetCondition");
|
||||
//this was copied from the controller case with just the id replaced!
|
||||
|
||||
//PlainJoystickState pjs;
|
||||
//config->GetInput(&pjs);
|
||||
//caps
|
||||
//4
|
||||
w32(MFID_4_Mic);
|
||||
|
||||
//state data
|
||||
//2 key code
|
||||
//w16(pjs.kcode);
|
||||
|
||||
//triggers
|
||||
//1 R
|
||||
//w8(pjs.trigger[PJTI_R]);
|
||||
//1 L
|
||||
//w8(pjs.trigger[PJTI_L]);
|
||||
|
||||
//joyx
|
||||
//1
|
||||
//w8(pjs.joy[PJAI_X1]);
|
||||
//joyy
|
||||
//1
|
||||
//w8(pjs.joy[PJAI_Y1]);
|
||||
|
||||
//not used
|
||||
//1
|
||||
w8(0x80);
|
||||
//1
|
||||
w8(0x80);
|
||||
}
|
||||
|
||||
return MDRS_DataTransfer;
|
||||
|
||||
case MDC_DeviceReset:
|
||||
//uhhh do nothing?
|
||||
LOGI("maple_microphone::dma MDC_DeviceReset");
|
||||
return MDRS_DeviceReply;
|
||||
|
||||
case MDCF_MICControl:
|
||||
{
|
||||
//LOGD("maple_microphone::dma handling MDCF_MICControl %d\n",cmd);
|
||||
//MONEY
|
||||
u32 function=r32();
|
||||
//LOGD("maple_microphone::dma MDCF_MICControl function (1st word) %#010x\n", function);
|
||||
//LOGD("maple_microphone::dma MDCF_MICControl words: %d\n", dma_count_in);
|
||||
|
||||
switch(function)
|
||||
{
|
||||
case MFID_4_Mic:
|
||||
{
|
||||
//MAGIC HERE
|
||||
//http://dcemulation.org/phpBB/viewtopic.php?f=34&t=69600
|
||||
// <3 <3 BlueCrab <3 <3
|
||||
/*
|
||||
2nd word What it does:
|
||||
0x0000??03 Sets the amplifier gain, ?? can be from 00 to 1F
|
||||
0x0f = default
|
||||
0x00008002 Enables recording
|
||||
0x00000001 Returns sampled data while recording is enabled
|
||||
While not enabled, returns status of the mic.
|
||||
0x00000002 Disables recording
|
||||
*
|
||||
*/
|
||||
u32 secondword=r32();
|
||||
//LOGD("maple_microphone::dma MDCF_MICControl subcommand (2nd word) %#010x\n", subcommand);
|
||||
|
||||
u32 subcommand = secondword & 0xFF; //just get last byte for now, deal with params later
|
||||
|
||||
//LOGD("maple_microphone::dma MDCF_MICControl (3rd word) %#010x\n", r32());
|
||||
//LOGD("maple_microphone::dma MDCF_MICControl (4th word) %#010x\n", r32());
|
||||
switch(subcommand)
|
||||
{
|
||||
case 0x01:
|
||||
{
|
||||
//LOGI("maple_microphone::dma MDCF_MICControl someone wants some data! (2nd word) %#010x\n", secondword);
|
||||
|
||||
w32(MFID_4_Mic);
|
||||
|
||||
//from what i can tell this is up to spec but results in transmit again
|
||||
//w32(secondword);
|
||||
|
||||
//32 bit header
|
||||
w8(0x04);//status (just the bit for recording)
|
||||
w8(0x0f);//gain (default)
|
||||
w8(0);//exp ?
|
||||
#ifndef TARGET_PANDORA
|
||||
if(get_mic_data(micdata)){
|
||||
w8(240);//ct (240 samples)
|
||||
wptr(micdata, SIZE_OF_MIC_DATA);
|
||||
}else
|
||||
#endif
|
||||
{
|
||||
w8(0);
|
||||
}
|
||||
|
||||
return MDRS_DataTransfer;
|
||||
}
|
||||
case 0x02:
|
||||
LOGI("maple_microphone::dma MDCF_MICControl toggle recording %#010x\n",secondword);
|
||||
return MDRS_DeviceReply;
|
||||
case 0x03:
|
||||
LOGI("maple_microphone::dma MDCF_MICControl set gain %#010x\n",secondword);
|
||||
return MDRS_DeviceReply;
|
||||
case MDRE_TransminAgain:
|
||||
LOGW("maple_microphone::dma MDCF_MICControl MDRE_TransminAgain");
|
||||
//apparently this doesnt matter
|
||||
//wptr(micdata, SIZE_OF_MIC_DATA);
|
||||
return MDRS_DeviceReply;//MDRS_DataTransfer;
|
||||
default:
|
||||
LOGW("maple_microphone::dma UNHANDLED secondword %#010x\n",secondword);
|
||||
break;
|
||||
}
|
||||
}
|
||||
default:
|
||||
LOGW("maple_microphone::dma UNHANDLED function %#010x\n",function);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
default:
|
||||
LOGW("maple_microphone::dma UNHANDLED MAPLE COMMAND %d\n",cmd);
|
||||
return MDRE_UnknownFunction;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
maple_device* maple_Create(MapleDeviceType type)
|
||||
{
|
||||
maple_device* rv=0;
|
||||
@@ -659,6 +850,9 @@ maple_device* maple_Create(MapleDeviceType type)
|
||||
case MDT_SegaController:
|
||||
rv=new maple_sega_controller();
|
||||
break;
|
||||
case MDT_Microphone:
|
||||
rv=new maple_microphone();
|
||||
break;
|
||||
#ifdef HAS_VMU
|
||||
case MDT_SegaVMU:
|
||||
rv = new maple_sega_vmu();
|
||||
@@ -670,4 +864,4 @@ maple_device* maple_Create(MapleDeviceType type)
|
||||
}
|
||||
|
||||
return rv;
|
||||
}
|
||||
}
|
||||
Regular → Executable
+7
-1
@@ -5,6 +5,7 @@ enum MapleDeviceType
|
||||
{
|
||||
MDT_SegaController,
|
||||
MDT_SegaVMU,
|
||||
MDT_Microphone,
|
||||
|
||||
MDT_Count
|
||||
};
|
||||
@@ -27,4 +28,9 @@ struct maple_device
|
||||
virtual u32 Dma(u32 Command,u32* buffer_in,u32 buffer_in_len,u32* buffer_out,u32& buffer_out_len)=0;
|
||||
};
|
||||
|
||||
maple_device* maple_Create(MapleDeviceType type);
|
||||
maple_device* maple_Create(MapleDeviceType type);
|
||||
#define SIZE_OF_MIC_DATA 480 //ALSO DEFINED IN SipEmulator.java
|
||||
#ifndef TARGET_PANDORA
|
||||
int get_mic_data(u8* buffer); //implemented in Android.cpp
|
||||
int push_vmu_screen(u8* buffer); //implemented in Android.cpp
|
||||
#endif
|
||||
@@ -561,8 +561,8 @@ error:
|
||||
fd = ashmem_create_region(0,RAM_SIZE + VRAM_SIZE +ARAM_SIZE);
|
||||
if (false)//this causes writebacks to flash -> slow and stuttery
|
||||
{
|
||||
fd = open("/data/data/com.example.droidcast/dcnzorz_mem",O_CREAT|O_RDWR|O_TRUNC,S_IRWXU|S_IRWXG|S_IRWXO);
|
||||
unlink("/data/data/com.example.droidcast/dcnzorz_mem");
|
||||
fd = open("/data/data/com.reicast.emulator/files/dcnzorz_mem",O_CREAT|O_RDWR|O_TRUNC,S_IRWXU|S_IRWXG|S_IRWXO);
|
||||
unlink("/data/data/com.reicast.emulator/files/dcnzorz_mem");
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -571,7 +571,7 @@ error:
|
||||
u32 sz= 512*1024*1024 + sizeof(Sh4RCB) + ARAM_SIZE + 0x10000;
|
||||
void* rv=mmap(0, sz, PROT_NONE, MAP_PRIVATE | MAP_ANON, -1, 0);
|
||||
munmap(rv,sz);
|
||||
return (u8*)rv + 0x10000 - u32(rv)%0x10000;//align to 64 KB (Needed for linaro mmap not to extend to next region)
|
||||
return (u8*)rv + 0x10000 - unat(rv)%0x10000;//align to 64 KB (Needed for linaro mmap not to extend to next region)
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
+77
-17
@@ -2,12 +2,69 @@
|
||||
#include "ta.h"
|
||||
#include "hw/pvr/pvr_mem.h"
|
||||
|
||||
/*
|
||||
|
||||
rendv3 ideas
|
||||
- multiple backends
|
||||
- ESish
|
||||
- OpenGL ES2.0
|
||||
- OpenGL ES3.0
|
||||
- OpenGL 3.1
|
||||
- OpenGL 4.x
|
||||
- Direct3D 10+ ?
|
||||
- correct memory ordering model
|
||||
- resource pools
|
||||
- threaded ta
|
||||
- threaded rendering
|
||||
- rtts
|
||||
- framebuffers
|
||||
- overlays
|
||||
|
||||
|
||||
PHASES
|
||||
- TA submition (memops, dma)
|
||||
|
||||
- TA parsing (defered, rend thread)
|
||||
|
||||
- CORE render (in-order, defered, rend thread)
|
||||
|
||||
|
||||
submition is done in-order
|
||||
- Partial handling of TA values
|
||||
- Gotchas with TA contexts
|
||||
|
||||
parsing is done on demand and out-of-order, and might be skipped
|
||||
- output is only consumed by renderer
|
||||
|
||||
render is queued on RENDER_START, and won't stall the emulation or might be skipped
|
||||
- VRAM integrity is an issue with out-of-order or delayed rendering.
|
||||
- selective vram snapshots require ta parsing to complete in order with REND_START / REND_END
|
||||
|
||||
|
||||
Complications
|
||||
- For some apis (gles2, maybe gl31) texture allocation needs to happen on the gpu thread
|
||||
- multiple versions of different time snapshots of the same texture are required
|
||||
- ta parsing vs frameskip logic
|
||||
|
||||
|
||||
Texture versioning and staging
|
||||
A memory copy of the texture can be used to temporary store the texture before upload to vram
|
||||
This can be moved to another thread
|
||||
If the api supports async resource creation, we don't need the extra copy
|
||||
Texcache lookups need to be versioned
|
||||
|
||||
|
||||
rendv2x hacks
|
||||
- Only a single pending render. Any renders while still pending are dropped (before parsing)
|
||||
- wait and block for parse/texcache. Render is async
|
||||
*/
|
||||
|
||||
u32 VertexCount=0;
|
||||
u32 FrameCount=0;
|
||||
u32 FrameCount=1;
|
||||
|
||||
Renderer* rend;
|
||||
cResetEvent rs(false,true);
|
||||
cResetEvent re(false,true);
|
||||
|
||||
int max_idx,max_mvo,max_op,max_pt,max_tr,max_vtx,max_modt, ovrn;
|
||||
|
||||
@@ -19,26 +76,23 @@ void SetREP(TA_context* cntx);
|
||||
bool rend_single_frame()
|
||||
{
|
||||
//wait render start only if no frame pending
|
||||
_pvrrc = DequeueRender();
|
||||
|
||||
while (!_pvrrc)
|
||||
do
|
||||
{
|
||||
rs.Wait();
|
||||
_pvrrc = DequeueRender();
|
||||
}
|
||||
while (!_pvrrc);
|
||||
|
||||
bool do_swp=false;
|
||||
bool proc = rend->Process(_pvrrc);
|
||||
re.Set();
|
||||
|
||||
do_swp=rend->Render();
|
||||
|
||||
|
||||
bool do_swp = proc && rend->Render();
|
||||
|
||||
if (do_swp)
|
||||
{
|
||||
//OSD_DRAW();
|
||||
}
|
||||
rend->DrawOSD();
|
||||
|
||||
//clear up & free data ..
|
||||
tactx_Recycle(_pvrrc);
|
||||
FinishRender(_pvrrc);
|
||||
_pvrrc=0;
|
||||
|
||||
return do_swp;
|
||||
@@ -89,9 +143,11 @@ void* rend_thread(void* p)
|
||||
cThread rthd(rend_thread,0);
|
||||
|
||||
|
||||
bool pend_rend = false;
|
||||
|
||||
void rend_start_render()
|
||||
{
|
||||
pend_rend = false;
|
||||
bool is_rtt=(FB_W_SOF1& 0x1000000)!=0;
|
||||
TA_context* ctx = tactx_Pop(CORE_CURRENT_CTX);
|
||||
|
||||
@@ -122,8 +178,10 @@ void rend_start_render()
|
||||
#if HOST_OS==OS_WINDOWS && 0
|
||||
printf("max: idx: %d, vtx: %d, op: %d, pt: %d, tr: %d, mvo: %d, modt: %d, ov: %d\n", max_idx, max_vtx, max_op, max_pt, max_tr, max_mvo, max_modt, ovrn);
|
||||
#endif
|
||||
QueueRender(ctx);
|
||||
rs.Set();
|
||||
if (QueueRender(ctx)) {
|
||||
rs.Set();
|
||||
pend_rend = true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -137,12 +195,14 @@ void rend_start_render()
|
||||
|
||||
void rend_end_render()
|
||||
{
|
||||
#if 0 //also disabled the printf, it takes quite some time ...
|
||||
#if HOST_OS!=OS_WINDOWS && !defined(_ANDROID)
|
||||
#if 1 //also disabled the printf, it takes quite some time ...
|
||||
#if HOST_OS!=OS_WINDOWS && !(defined(_ANDROID) || defined(TARGET_PANDORA))
|
||||
if (!re.state) printf("Render > Extended time slice ...\n");
|
||||
#endif
|
||||
rend_end_wait();
|
||||
#endif
|
||||
|
||||
if (pend_rend)
|
||||
re.Wait();
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
@@ -32,9 +32,12 @@ struct Renderer
|
||||
|
||||
virtual void Term()=0;
|
||||
|
||||
virtual bool Process(TA_context* ctx)=0;
|
||||
virtual bool Render()=0;
|
||||
|
||||
virtual void Present()=0;
|
||||
|
||||
virtual void DrawOSD() { }
|
||||
};
|
||||
|
||||
|
||||
|
||||
Regular → Executable
+8
-1
@@ -179,12 +179,19 @@ int spg_line_sched(int tag, int cycl, int jit)
|
||||
|
||||
full_rps=(spd_fps+fskip/ts);
|
||||
|
||||
#ifdef TARGET_PANDORA
|
||||
sprintf(fpsStr,"CPU: %4.2f V: %4.2f (%s%s%4.2f) R: %4.2f+%4.2f",
|
||||
spd_cpu*100/200,spd_vbs,
|
||||
mode,res,fullvbs,
|
||||
spd_fps,fskip/ts);
|
||||
#else
|
||||
sprintf(fpsStr,"%s/%c - %4.2f (%4.2f) - %4.2f - V: %4.2f (%.2f, %s%s%4.2f) R: %4.2f+%4.2f VTX: %4.2f%c",
|
||||
VER_SHORTNAME,'n',mspdf,speed_load_mspdf,spd_cpu*100/200,spd_vbs,
|
||||
spd_vbs/full_rps,mode,res,fullvbs,
|
||||
spd_fps,fskip/ts
|
||||
,mv,mv_c);
|
||||
|
||||
#endif
|
||||
|
||||
fskip=0;
|
||||
os_SetWindowText(fpsStr);
|
||||
|
||||
|
||||
+1
-1
@@ -264,7 +264,7 @@ void ta_vtx_ListCont()
|
||||
void ta_vtx_ListInit()
|
||||
{
|
||||
SetCurrentTARC(TA_ISP_BASE);
|
||||
ta_tad.Clear();
|
||||
ta_tad.ClearPartial();
|
||||
|
||||
ta_cur_state=TAS_NS;
|
||||
}
|
||||
|
||||
+34
-12
@@ -4,6 +4,9 @@
|
||||
extern u32 fskip;
|
||||
extern u32 FrameCount;
|
||||
|
||||
int frameskip=0;
|
||||
bool FrameSkipping=false; // global switch to enable/disable frameskip
|
||||
|
||||
TA_context* ta_ctx;
|
||||
tad_context ta_tad;
|
||||
|
||||
@@ -32,14 +35,13 @@ void SetCurrentTARC(u32 addr)
|
||||
|
||||
//clear context
|
||||
ta_ctx=0;
|
||||
ta_tad.thd_data=0;
|
||||
ta_tad.thd_root=0;
|
||||
ta_tad.Reset(0);
|
||||
}
|
||||
}
|
||||
|
||||
bool TryDecodeTARC()
|
||||
{
|
||||
verify(ta_ctx);
|
||||
verify((int)ta_ctx);
|
||||
|
||||
if (vd_ctx == 0)
|
||||
{
|
||||
@@ -47,7 +49,7 @@ bool TryDecodeTARC()
|
||||
|
||||
vd_ctx->rend.proc_start = vd_ctx->rend.proc_end + 32;
|
||||
vd_ctx->rend.proc_end = vd_ctx->tad.thd_data;
|
||||
|
||||
|
||||
vd_ctx->rend_inuse.Lock();
|
||||
vd_rc = vd_ctx->rend;
|
||||
|
||||
@@ -60,7 +62,7 @@ bool TryDecodeTARC()
|
||||
|
||||
void VDecEnd()
|
||||
{
|
||||
verify(vd_ctx);
|
||||
verify((int)vd_ctx);
|
||||
|
||||
vd_ctx->rend = vd_rc;
|
||||
|
||||
@@ -72,27 +74,37 @@ void VDecEnd()
|
||||
cMutex mtx_rqueue;
|
||||
TA_context* rqueue;
|
||||
|
||||
void QueueRender(TA_context* ctx)
|
||||
bool QueueRender(TA_context* ctx)
|
||||
{
|
||||
verify(ctx != 0);
|
||||
|
||||
if (FrameSkipping && frameskip) {
|
||||
frameskip=1-frameskip;
|
||||
tactx_Recycle(ctx);
|
||||
fskip++;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (rqueue) {
|
||||
tactx_Recycle(ctx);
|
||||
fskip++;
|
||||
return false;
|
||||
}
|
||||
|
||||
mtx_rqueue.Lock();
|
||||
TA_context* old = rqueue;
|
||||
rqueue=ctx;
|
||||
mtx_rqueue.Unlock();
|
||||
|
||||
if (old)
|
||||
{
|
||||
tactx_Recycle(old);
|
||||
fskip++;
|
||||
}
|
||||
verify(!old);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
TA_context* DequeueRender()
|
||||
{
|
||||
mtx_rqueue.Lock();
|
||||
TA_context* rv = rqueue;
|
||||
rqueue = 0;
|
||||
mtx_rqueue.Unlock();
|
||||
|
||||
if (rv)
|
||||
@@ -101,6 +113,16 @@ TA_context* DequeueRender()
|
||||
return rv;
|
||||
}
|
||||
|
||||
void FinishRender(TA_context* ctx)
|
||||
{
|
||||
verify(rqueue == ctx);
|
||||
mtx_rqueue.Lock();
|
||||
rqueue = 0;
|
||||
mtx_rqueue.Unlock();
|
||||
|
||||
tactx_Recycle(ctx);
|
||||
}
|
||||
|
||||
cMutex mtx_pool;
|
||||
|
||||
vector<TA_context*> ctx_pool;
|
||||
|
||||
+27
-6
@@ -20,6 +20,8 @@ struct PolyParam
|
||||
|
||||
//lets see what more :)
|
||||
|
||||
u32 texid;
|
||||
|
||||
TSP tsp;
|
||||
TCW tcw;
|
||||
PCW pcw;
|
||||
@@ -46,11 +48,29 @@ struct tad_context
|
||||
{
|
||||
u8* thd_data;
|
||||
u8* thd_root;
|
||||
u8* thd_old_data;
|
||||
|
||||
void Clear()
|
||||
{
|
||||
thd_data=thd_root;
|
||||
thd_old_data = thd_data = thd_root;
|
||||
}
|
||||
|
||||
void ClearPartial()
|
||||
{
|
||||
thd_old_data = thd_data;
|
||||
thd_data = thd_root;
|
||||
}
|
||||
|
||||
u8* End()
|
||||
{
|
||||
return thd_data == thd_root ? thd_old_data : thd_data;
|
||||
}
|
||||
|
||||
void Reset(u8* ptr)
|
||||
{
|
||||
thd_data = thd_root = thd_old_data = ptr;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
struct rend_context
|
||||
@@ -126,12 +146,12 @@ struct TA_context
|
||||
|
||||
void MarkRend()
|
||||
{
|
||||
rend.proc_start = rend.proc_end;
|
||||
rend.proc_end = tad.thd_data;
|
||||
rend.proc_start = tad.thd_root;
|
||||
rend.proc_end = tad.End();
|
||||
}
|
||||
void Alloc()
|
||||
{
|
||||
tad.thd_root=tad.thd_data=(u8*)malloc(2*1024*1024);
|
||||
tad.Reset((u8*)malloc(2*1024*1024));
|
||||
|
||||
rend.verts.InitBytes(1024*1024,&rend.Overrun); //up to 1 mb of vtx data/frame = ~ 38k vtx/frame
|
||||
rend.idx.Init(60*1024,&rend.Overrun); //up to 60K indexes ( idx have stripification overhead )
|
||||
@@ -150,7 +170,7 @@ struct TA_context
|
||||
tad.Clear();
|
||||
rend_inuse.Lock();
|
||||
rend.Clear();
|
||||
rend.proc_end = rend.proc_start = tad.thd_data;
|
||||
rend.proc_end = rend.proc_start = tad.thd_root;
|
||||
rend_inuse.Unlock();
|
||||
}
|
||||
|
||||
@@ -188,8 +208,9 @@ void tactx_Recycle(TA_context* poped_ctx);
|
||||
#define TACTX_NONE (0xFFFFFFFF)
|
||||
|
||||
void SetCurrentTARC(u32 addr);
|
||||
void QueueRender(TA_context* ctx);
|
||||
bool QueueRender(TA_context* ctx);
|
||||
TA_context* DequeueRender();
|
||||
void FinishRender(TA_context* ctx);
|
||||
bool TryDecodeTARC();
|
||||
void VDecEnd();
|
||||
|
||||
|
||||
+29
-8
@@ -8,6 +8,7 @@
|
||||
#include "ta.h"
|
||||
#include "ta_ctx.h"
|
||||
#include "pvr_mem.h"
|
||||
#include "rend/gles/gles.h"
|
||||
#include "Renderer_if.h"
|
||||
|
||||
u32 ta_type_lut[256];
|
||||
@@ -376,7 +377,9 @@ strip_end:
|
||||
}
|
||||
|
||||
public:
|
||||
#define group_EN() if (data->pcw.Group_En){ TileClipMode(data->pcw.User_Clip);}
|
||||
|
||||
//Group_En bit seems ignored, thanks p1pkin
|
||||
#define group_EN() /*if (data->pcw.Group_En) */{ TileClipMode(data->pcw.User_Clip);}
|
||||
static Ta_Dma* TACALL ta_main(Ta_Dma* data,Ta_Dma* data_end)
|
||||
{
|
||||
do
|
||||
@@ -786,11 +789,18 @@ public:
|
||||
}
|
||||
d_pp->first=vdrc.idx.used();
|
||||
d_pp->count=0;
|
||||
|
||||
d_pp->isp=pp->isp;
|
||||
d_pp->tsp=pp->tsp;
|
||||
d_pp->tcw=pp->tcw;
|
||||
d_pp->pcw=pp->pcw;
|
||||
d_pp->tileclip=tileclip_val;
|
||||
|
||||
d_pp->texid = -1;
|
||||
|
||||
if (d_pp->pcw.Texture) {
|
||||
d_pp->texid = GetTexture(d_pp->tsp,d_pp->tcw);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1181,6 +1191,12 @@ public:
|
||||
d_pp->pcw=spr->pcw;
|
||||
d_pp->tileclip=tileclip_val;
|
||||
|
||||
d_pp->texid = -1;
|
||||
|
||||
if (d_pp->pcw.Texture) {
|
||||
d_pp->texid = GetTexture(d_pp->tsp,d_pp->tcw);
|
||||
}
|
||||
|
||||
SFaceBaseColor=spr->BaseCol;
|
||||
SFaceOffsColor=spr->OffsCol;
|
||||
}
|
||||
@@ -1392,6 +1408,9 @@ FifoSplitter<0> TAFifo0;
|
||||
|
||||
int ta_parse_cnt = 0;
|
||||
|
||||
/*
|
||||
Also: gotta stage textures here
|
||||
*/
|
||||
bool ta_parse_vdrc(TA_context* ctx)
|
||||
{
|
||||
bool rv=false;
|
||||
@@ -1539,6 +1558,8 @@ void FillBGP(TA_context* ctx)
|
||||
u32 vertex_ptr=strip_vert_num*strip_vs+strip_base +3*4;
|
||||
//now , all the info is ready :p
|
||||
|
||||
bgpp->texid = -1;
|
||||
|
||||
bgpp->isp.full=vri(strip_base);
|
||||
bgpp->tsp.full=vri(strip_base+4);
|
||||
bgpp->tcw.full=vri(strip_base+8);
|
||||
@@ -1564,21 +1585,21 @@ void FillBGP(TA_context* ctx)
|
||||
|
||||
float ZV=0;
|
||||
|
||||
cv[0].x=0;
|
||||
cv[0].y=0;
|
||||
cv[0].x=-2000;
|
||||
cv[0].y=-2000;
|
||||
cv[0].z=ISP_BACKGND_D.f;
|
||||
|
||||
cv[1].x=640*scale_x;
|
||||
cv[1].x=640*scale_x + 2000;
|
||||
cv[1].y=0;
|
||||
cv[1].z=ISP_BACKGND_D.f;
|
||||
|
||||
cv[2].x=0;
|
||||
cv[2].y=480;
|
||||
cv[2].x=-2000;
|
||||
cv[2].y=480+2000;
|
||||
cv[2].z=ISP_BACKGND_D.f;
|
||||
|
||||
cv[3]=cv[2];
|
||||
cv[3].x=640*scale_x;
|
||||
cv[3].y=480;
|
||||
cv[3].x=640*scale_x+2000;
|
||||
cv[3].y=480+2000;
|
||||
cv[3].z=ISP_BACKGND_D.f;
|
||||
}
|
||||
|
||||
|
||||
@@ -1169,7 +1169,7 @@ _end:
|
||||
//Small-n-simple idle loop detector :p
|
||||
if (state.info.has_readm && !state.info.has_writem && !state.info.has_fpu && blk->guest_opcodes<6)
|
||||
{
|
||||
if ((blk->BlockType==BET_Cond_0 || blk->BlockType==BET_Cond_1) && blk->BranchBlock<=blk->addr)
|
||||
if (blk->BlockType==BET_Cond_0 || blk->BlockType==BET_Cond_1 && blk->BranchBlock<=blk->addr)
|
||||
{
|
||||
blk->guest_cycles*=3;
|
||||
}
|
||||
|
||||
@@ -304,7 +304,7 @@ void* DYNACALL rdv_LinkBlock(u8* code,u32 dpc)
|
||||
rbi=bm_GetStaleBlock(code);
|
||||
}
|
||||
|
||||
verify(rbi);
|
||||
verify((int)rbi);
|
||||
|
||||
u32 bcls=BET_GET_CLS(rbi->BlockType);
|
||||
|
||||
|
||||
@@ -68,7 +68,7 @@ struct RegAlloc
|
||||
|
||||
nreg=(nreg_t)-1;
|
||||
nregf=(nregf_t)-1;
|
||||
RegAccess ra={pos,mode};
|
||||
RegAccess ra={static_cast<u32>(pos),mode};
|
||||
accesses.push_back(ra);
|
||||
}
|
||||
|
||||
@@ -87,7 +87,7 @@ struct RegAlloc
|
||||
end=pos;
|
||||
if (mode&AM_WRITE)
|
||||
writeback=true;
|
||||
RegAccess ra={pos,mode};
|
||||
RegAccess ra={static_cast<u32>(pos),mode};
|
||||
accesses.push_back(ra);
|
||||
}
|
||||
|
||||
|
||||
@@ -75,17 +75,21 @@ void SetFloatStatusReg()
|
||||
|
||||
|
||||
//TODO: Implement this (needed for SOTB)
|
||||
#if HOST_CPU==CPU_X86 && HOST_OS==OS_WINDOWS
|
||||
#if HOST_CPU==CPU_X86
|
||||
if (fpscr.RM==1) //if round to 0 , set the flag
|
||||
temp|=(3<<13);
|
||||
|
||||
if (fpscr.DN) //denormals are considered 0
|
||||
temp|=(1<<15);
|
||||
|
||||
_asm
|
||||
{
|
||||
ldmxcsr temp; //load the float status :)
|
||||
}
|
||||
#if BUILD_COMPILER == COMPILER_VC
|
||||
_asm
|
||||
{
|
||||
ldmxcsr temp; //load the float status :)
|
||||
}
|
||||
#else
|
||||
asm("ldmxcsr %0" : : "m"(temp));
|
||||
#endif
|
||||
#elif HOST_CPU==CPU_ARM
|
||||
static const unsigned int x = 0x04086060;
|
||||
unsigned int y = 0x02000000;
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
#pragma once
|
||||
#include "types.h"
|
||||
#include "sh4_rom.h"
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
|
||||
#include "deps/chdpsr/cdipsr.h"
|
||||
|
||||
Disc* cdi_parse(wchar* file)
|
||||
Disc* cdi_parse(const wchar* file)
|
||||
{
|
||||
FILE* fsource=fopen(file,"rb");
|
||||
|
||||
|
||||
@@ -17,7 +17,7 @@ struct CHDDisc : Disc
|
||||
hunk_mem=0;
|
||||
}
|
||||
|
||||
bool TryOpen(wchar* file);
|
||||
bool TryOpen(const wchar* file);
|
||||
|
||||
~CHDDisc()
|
||||
{
|
||||
@@ -64,7 +64,7 @@ struct CHDTrack : TrackFile
|
||||
}
|
||||
};
|
||||
|
||||
bool CHDDisc::TryOpen(wchar* file)
|
||||
bool CHDDisc::TryOpen(const wchar* file)
|
||||
{
|
||||
chd_error err=chd_open(file,CHD_OPEN_READ,0,&chd);
|
||||
|
||||
@@ -141,7 +141,9 @@ bool CHDDisc::TryOpen(wchar* file)
|
||||
if (total_frames!=549300 || tracks.size()<3)
|
||||
{
|
||||
printf("WARNING: chd: Total frames is wrong: %d frames in %d tracks\n",total_frames,tracks.size());
|
||||
#ifndef NOT_REICAST
|
||||
msgboxf("This is an improper dump!",MBX_ICONEXCLAMATION);
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -151,7 +153,7 @@ bool CHDDisc::TryOpen(wchar* file)
|
||||
}
|
||||
|
||||
|
||||
Disc* chd_parse(wchar* file)
|
||||
Disc* chd_parse(const wchar* file)
|
||||
{
|
||||
CHDDisc* rv = new CHDDisc();
|
||||
|
||||
|
||||
+96
-7
@@ -1,17 +1,16 @@
|
||||
#include "common.h"
|
||||
|
||||
|
||||
Disc* chd_parse(wchar* file);
|
||||
Disc* gdi_parse(wchar* file);
|
||||
Disc* cdi_parse(wchar* file);
|
||||
Disc* chd_parse(const wchar* file);
|
||||
Disc* gdi_parse(const wchar* file);
|
||||
Disc* cdi_parse(const wchar* file);
|
||||
#if HOST_OS==OS_WINDOWS
|
||||
Disc* ioctl_parse(wchar* file);
|
||||
Disc* ioctl_parse(const wchar* file);
|
||||
#endif
|
||||
|
||||
u32 NullDriveDiscType;
|
||||
Disc* disc;
|
||||
|
||||
Disc*(*drivers[])(wchar* path)=
|
||||
Disc*(*drivers[])(const wchar* path)=
|
||||
{
|
||||
chd_parse,
|
||||
gdi_parse,
|
||||
@@ -26,8 +25,12 @@ u8 q_subchannel[96];
|
||||
|
||||
void PatchRegion_0(u8* sector,int size)
|
||||
{
|
||||
#ifndef NOT_REICAST
|
||||
if (settings.imgread.PatchRegion==0)
|
||||
return;
|
||||
#else
|
||||
return;
|
||||
#endif
|
||||
|
||||
u8* usersect=sector;
|
||||
|
||||
@@ -42,8 +45,12 @@ void PatchRegion_0(u8* sector,int size)
|
||||
}
|
||||
void PatchRegion_6(u8* sector,int size)
|
||||
{
|
||||
#ifndef NOT_REICAST
|
||||
if (settings.imgread.PatchRegion==0)
|
||||
return;
|
||||
#else
|
||||
return;
|
||||
#endif
|
||||
|
||||
u8* usersect=sector;
|
||||
|
||||
@@ -122,18 +129,29 @@ bool ConvertSector(u8* in_buff , u8* out_buff , int from , int to,int sector)
|
||||
return true;
|
||||
}
|
||||
|
||||
Disc* OpenDisc(const wchar* fn)
|
||||
{
|
||||
Disc* rv;
|
||||
|
||||
for (int i=0;drivers[i] && !(rv=drivers[i](fn));i++) ;
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
bool InitDrive_(wchar* fn)
|
||||
{
|
||||
TermDrive();
|
||||
|
||||
//try all drivers
|
||||
for (int i=0;drivers[i] && !(disc=drivers[i](fn));i++) ;
|
||||
disc = OpenDisc(fn);
|
||||
|
||||
if (disc!=0)
|
||||
{
|
||||
printf("gdrom: Opened image \"%s\"\n",fn);
|
||||
NullDriveDiscType=Busy;
|
||||
#ifndef NOT_REICAST
|
||||
libCore_gdrom_disc_change();
|
||||
#endif
|
||||
// Sleep(400); //busy for a bit // what, really ?
|
||||
return true;
|
||||
}
|
||||
@@ -145,6 +163,7 @@ bool InitDrive_(wchar* fn)
|
||||
return false;
|
||||
}
|
||||
|
||||
#ifndef NOT_REICAST
|
||||
bool InitDrive(u32 fileflags)
|
||||
{
|
||||
if (settings.imgread.LoadDefaultImage)
|
||||
@@ -169,6 +188,10 @@ bool InitDrive(u32 fileflags)
|
||||
if (gfrv == 0)
|
||||
{
|
||||
NullDriveDiscType=NoDisk;
|
||||
gd_setdisc();
|
||||
sns_asc=0x29;
|
||||
sns_ascq=0x00;
|
||||
sns_key=0x6;
|
||||
return true;
|
||||
}
|
||||
else if (gfrv == -1)
|
||||
@@ -182,6 +205,11 @@ bool InitDrive(u32 fileflags)
|
||||
if (!InitDrive_(fn))
|
||||
{
|
||||
//msgboxf("Selected image failed to load",MBX_ICONERROR);
|
||||
NullDriveDiscType=NoDisk;
|
||||
gd_setdisc();
|
||||
sns_asc=0x29;
|
||||
sns_ascq=0x00;
|
||||
sns_key=0x6;
|
||||
return true;
|
||||
}
|
||||
else
|
||||
@@ -190,6 +218,67 @@ bool InitDrive(u32 fileflags)
|
||||
}
|
||||
}
|
||||
|
||||
bool DiscSwap(u32 fileflags)
|
||||
{
|
||||
if (settings.imgread.LoadDefaultImage)
|
||||
{
|
||||
printf("Loading default image \"%s\"\n",settings.imgread.DefaultImage);
|
||||
if (!InitDrive_(settings.imgread.DefaultImage))
|
||||
{
|
||||
msgboxf("Default image \"%s\" failed to load",MBX_ICONERROR);
|
||||
return false;
|
||||
}
|
||||
else
|
||||
return true;
|
||||
}
|
||||
|
||||
wchar fn[512];
|
||||
strcpy(fn,settings.imgread.LastImage);
|
||||
#ifdef BUILD_DREAMCAST
|
||||
int gfrv=GetFile(fn,0,fileflags);
|
||||
#else
|
||||
int gfrv=0;
|
||||
#endif
|
||||
if (gfrv == 0)
|
||||
{
|
||||
NullDriveDiscType=Open;
|
||||
gd_setdisc();
|
||||
sns_asc=0x28;
|
||||
sns_ascq=0x00;
|
||||
sns_key=0x6;
|
||||
return true;
|
||||
}
|
||||
else if (gfrv == -1)
|
||||
{
|
||||
sns_asc=0x28;
|
||||
sns_ascq=0x00;
|
||||
sns_key=0x6;
|
||||
return false;
|
||||
}
|
||||
|
||||
strcpy(settings.imgread.LastImage,fn);
|
||||
SaveSettings();
|
||||
|
||||
if (!InitDrive_(fn))
|
||||
{
|
||||
//msgboxf("Selected image failed to load",MBX_ICONERROR);
|
||||
NullDriveDiscType=Open;
|
||||
gd_setdisc();
|
||||
sns_asc=0x28;
|
||||
sns_ascq=0x00;
|
||||
sns_key=0x6;
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
sns_asc=0x28;
|
||||
sns_ascq=0x00;
|
||||
sns_key=0x6;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
void TermDrive()
|
||||
{
|
||||
if (disc!=0)
|
||||
|
||||
+11
-2
@@ -82,6 +82,11 @@ bool ConvertSector(u8* in_buff , u8* out_buff , int from , int to,int sector);
|
||||
|
||||
bool InitDrive(u32 fileflags=0);
|
||||
void TermDrive();
|
||||
bool DiscSwap(u32 fileflags=0);
|
||||
extern signed int sns_asc;
|
||||
extern signed int sns_ascq;
|
||||
extern signed int sns_key;
|
||||
|
||||
|
||||
void PatchRegion_0(u8* sector,int size);
|
||||
void PatchRegion_6(u8* sector,int size);
|
||||
@@ -235,7 +240,7 @@ struct Disc
|
||||
{
|
||||
u32 fmt=tracks[i].CTRL==4?2048:2352;
|
||||
char fsto[1024];
|
||||
sprintf(fsto,"%s%s%d.img",path.c_str(),"track",i);
|
||||
sprintf(fsto,"%s%s%d.img",path.c_str(),".track",i);
|
||||
|
||||
FILE* fo=fopen(fsto,"wb");
|
||||
|
||||
@@ -252,6 +257,8 @@ struct Disc
|
||||
|
||||
extern Disc* disc;
|
||||
|
||||
Disc* OpenDisc(const wchar* fn);
|
||||
|
||||
struct RawTrackFile : TrackFile
|
||||
{
|
||||
FILE* file;
|
||||
@@ -292,4 +299,6 @@ struct RawTrackFile : TrackFile
|
||||
}
|
||||
};
|
||||
|
||||
DiscType GuessDiscType(bool m1, bool m2, bool da);
|
||||
DiscType GuessDiscType(bool m1, bool m2, bool da);
|
||||
|
||||
extern void gd_setdisc();
|
||||
@@ -1,7 +1,7 @@
|
||||
#include "common.h"
|
||||
#include <ctype.h>
|
||||
|
||||
Disc* load_gdi(char* file)
|
||||
Disc* load_gdi(const char* file)
|
||||
{
|
||||
u32 iso_tc;
|
||||
Disc* disc = new Disc();
|
||||
@@ -75,7 +75,7 @@ Disc* load_gdi(char* file)
|
||||
}
|
||||
|
||||
|
||||
Disc* gdi_parse(char* file)
|
||||
Disc* gdi_parse(const char* file)
|
||||
{
|
||||
size_t len=strlen(file);
|
||||
if (len>4)
|
||||
|
||||
@@ -363,7 +363,7 @@ void PhysicalTrack::Read(u32 FAD,u8* dst,SectorFormat* sector_type,u8* subcode,S
|
||||
}
|
||||
|
||||
|
||||
Disc* ioctl_parse(wchar* file)
|
||||
Disc* ioctl_parse(const wchar* file)
|
||||
{
|
||||
|
||||
if (strlen(file)==3 && GetDriveType(file)==DRIVE_CDROM)
|
||||
|
||||
@@ -0,0 +1,329 @@
|
||||
/* -*- mode: c; tab-width: 8; -*- */
|
||||
/* vi: set sw=4 ts=8: */
|
||||
/* Reference version of egl.h for EGL 1.4.
|
||||
* $Revision: 9356 $ on $Date: 2009-10-21 02:52:25 -0700 (Wed, 21 Oct 2009) $
|
||||
*/
|
||||
|
||||
/*
|
||||
** Copyright (c) 2007-2009 The Khronos Group Inc.
|
||||
**
|
||||
** Permission is hereby granted, free of charge, to any person obtaining a
|
||||
** copy of this software and/or associated documentation files (the
|
||||
** "Materials"), to deal in the Materials without restriction, including
|
||||
** without limitation the rights to use, copy, modify, merge, publish,
|
||||
** distribute, sublicense, and/or sell copies of the Materials, and to
|
||||
** permit persons to whom the Materials are 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 Materials.
|
||||
**
|
||||
** THE MATERIALS ARE 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
|
||||
** MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
|
||||
*/
|
||||
|
||||
#ifndef __egl_h_
|
||||
#define __egl_h_
|
||||
|
||||
/* All platform-dependent types and macro boilerplate (such as EGLAPI
|
||||
* and EGLAPIENTRY) should go in eglplatform.h.
|
||||
*/
|
||||
#include <APPLE/eglplatform.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* EGL Types */
|
||||
/* EGLint is defined in eglplatform.h */
|
||||
typedef unsigned int EGLBoolean;
|
||||
typedef unsigned int EGLenum;
|
||||
typedef void *EGLConfig;
|
||||
typedef void *EGLContext;
|
||||
typedef void *EGLDisplay;
|
||||
typedef void *EGLSurface;
|
||||
typedef void *EGLClientBuffer;
|
||||
|
||||
/* EGL Versioning */
|
||||
#define EGL_VERSION_1_0 1
|
||||
#define EGL_VERSION_1_1 1
|
||||
#define EGL_VERSION_1_2 1
|
||||
#define EGL_VERSION_1_3 1
|
||||
#define EGL_VERSION_1_4 1
|
||||
|
||||
/* EGL Enumerants. Bitmasks and other exceptional cases aside, most
|
||||
* enums are assigned unique values starting at 0x3000.
|
||||
*/
|
||||
|
||||
/* EGL aliases */
|
||||
#define EGL_FALSE 0
|
||||
#define EGL_TRUE 1
|
||||
|
||||
/* Out-of-band handle values */
|
||||
#define EGL_DEFAULT_DISPLAY ((EGLNativeDisplayType)0)
|
||||
#define EGL_NO_CONTEXT ((EGLContext)0)
|
||||
#define EGL_NO_DISPLAY ((EGLDisplay)0)
|
||||
#define EGL_NO_SURFACE ((EGLSurface)0)
|
||||
|
||||
/* Out-of-band attribute value */
|
||||
#define EGL_DONT_CARE ((EGLint)-1)
|
||||
|
||||
/* Errors / GetError return values */
|
||||
#define EGL_SUCCESS 0x3000
|
||||
#define EGL_NOT_INITIALIZED 0x3001
|
||||
#define EGL_BAD_ACCESS 0x3002
|
||||
#define EGL_BAD_ALLOC 0x3003
|
||||
#define EGL_BAD_ATTRIBUTE 0x3004
|
||||
#define EGL_BAD_CONFIG 0x3005
|
||||
#define EGL_BAD_CONTEXT 0x3006
|
||||
#define EGL_BAD_CURRENT_SURFACE 0x3007
|
||||
#define EGL_BAD_DISPLAY 0x3008
|
||||
#define EGL_BAD_MATCH 0x3009
|
||||
#define EGL_BAD_NATIVE_PIXMAP 0x300A
|
||||
#define EGL_BAD_NATIVE_WINDOW 0x300B
|
||||
#define EGL_BAD_PARAMETER 0x300C
|
||||
#define EGL_BAD_SURFACE 0x300D
|
||||
#define EGL_CONTEXT_LOST 0x300E /* EGL 1.1 - IMG_power_management */
|
||||
|
||||
/* Reserved 0x300F-0x301F for additional errors */
|
||||
|
||||
/* Config attributes */
|
||||
#define EGL_BUFFER_SIZE 0x3020
|
||||
#define EGL_ALPHA_SIZE 0x3021
|
||||
#define EGL_BLUE_SIZE 0x3022
|
||||
#define EGL_GREEN_SIZE 0x3023
|
||||
#define EGL_RED_SIZE 0x3024
|
||||
#define EGL_DEPTH_SIZE 0x3025
|
||||
#define EGL_STENCIL_SIZE 0x3026
|
||||
#define EGL_CONFIG_CAVEAT 0x3027
|
||||
#define EGL_CONFIG_ID 0x3028
|
||||
#define EGL_LEVEL 0x3029
|
||||
#define EGL_MAX_PBUFFER_HEIGHT 0x302A
|
||||
#define EGL_MAX_PBUFFER_PIXELS 0x302B
|
||||
#define EGL_MAX_PBUFFER_WIDTH 0x302C
|
||||
#define EGL_NATIVE_RENDERABLE 0x302D
|
||||
#define EGL_NATIVE_VISUAL_ID 0x302E
|
||||
#define EGL_NATIVE_VISUAL_TYPE 0x302F
|
||||
#define EGL_SAMPLES 0x3031
|
||||
#define EGL_SAMPLE_BUFFERS 0x3032
|
||||
#define EGL_SURFACE_TYPE 0x3033
|
||||
#define EGL_TRANSPARENT_TYPE 0x3034
|
||||
#define EGL_TRANSPARENT_BLUE_VALUE 0x3035
|
||||
#define EGL_TRANSPARENT_GREEN_VALUE 0x3036
|
||||
#define EGL_TRANSPARENT_RED_VALUE 0x3037
|
||||
#define EGL_NONE 0x3038 /* Attrib list terminator */
|
||||
#define EGL_BIND_TO_TEXTURE_RGB 0x3039
|
||||
#define EGL_BIND_TO_TEXTURE_RGBA 0x303A
|
||||
#define EGL_MIN_SWAP_INTERVAL 0x303B
|
||||
#define EGL_MAX_SWAP_INTERVAL 0x303C
|
||||
#define EGL_LUMINANCE_SIZE 0x303D
|
||||
#define EGL_ALPHA_MASK_SIZE 0x303E
|
||||
#define EGL_COLOR_BUFFER_TYPE 0x303F
|
||||
#define EGL_RENDERABLE_TYPE 0x3040
|
||||
#define EGL_MATCH_NATIVE_PIXMAP 0x3041 /* Pseudo-attribute (not queryable) */
|
||||
#define EGL_CONFORMANT 0x3042
|
||||
|
||||
/* Reserved 0x3041-0x304F for additional config attributes */
|
||||
|
||||
/* Config attribute values */
|
||||
#define EGL_SLOW_CONFIG 0x3050 /* EGL_CONFIG_CAVEAT value */
|
||||
#define EGL_NON_CONFORMANT_CONFIG 0x3051 /* EGL_CONFIG_CAVEAT value */
|
||||
#define EGL_TRANSPARENT_RGB 0x3052 /* EGL_TRANSPARENT_TYPE value */
|
||||
#define EGL_RGB_BUFFER 0x308E /* EGL_COLOR_BUFFER_TYPE value */
|
||||
#define EGL_LUMINANCE_BUFFER 0x308F /* EGL_COLOR_BUFFER_TYPE value */
|
||||
|
||||
/* More config attribute values, for EGL_TEXTURE_FORMAT */
|
||||
#define EGL_NO_TEXTURE 0x305C
|
||||
#define EGL_TEXTURE_RGB 0x305D
|
||||
#define EGL_TEXTURE_RGBA 0x305E
|
||||
#define EGL_TEXTURE_2D 0x305F
|
||||
|
||||
/* Config attribute mask bits */
|
||||
#define EGL_PBUFFER_BIT 0x0001 /* EGL_SURFACE_TYPE mask bits */
|
||||
#define EGL_PIXMAP_BIT 0x0002 /* EGL_SURFACE_TYPE mask bits */
|
||||
#define EGL_WINDOW_BIT 0x0004 /* EGL_SURFACE_TYPE mask bits */
|
||||
#define EGL_VG_COLORSPACE_LINEAR_BIT 0x0020 /* EGL_SURFACE_TYPE mask bits */
|
||||
#define EGL_VG_ALPHA_FORMAT_PRE_BIT 0x0040 /* EGL_SURFACE_TYPE mask bits */
|
||||
#define EGL_MULTISAMPLE_RESOLVE_BOX_BIT 0x0200 /* EGL_SURFACE_TYPE mask bits */
|
||||
#define EGL_SWAP_BEHAVIOR_PRESERVED_BIT 0x0400 /* EGL_SURFACE_TYPE mask bits */
|
||||
|
||||
#define EGL_OPENGL_ES_BIT 0x0001 /* EGL_RENDERABLE_TYPE mask bits */
|
||||
#define EGL_OPENVG_BIT 0x0002 /* EGL_RENDERABLE_TYPE mask bits */
|
||||
#define EGL_OPENGL_ES2_BIT 0x0004 /* EGL_RENDERABLE_TYPE mask bits */
|
||||
#define EGL_OPENGL_BIT 0x0008 /* EGL_RENDERABLE_TYPE mask bits */
|
||||
|
||||
/* QueryString targets */
|
||||
#define EGL_VENDOR 0x3053
|
||||
#define EGL_VERSION 0x3054
|
||||
#define EGL_EXTENSIONS 0x3055
|
||||
#define EGL_CLIENT_APIS 0x308D
|
||||
|
||||
/* QuerySurface / SurfaceAttrib / CreatePbufferSurface targets */
|
||||
#define EGL_HEIGHT 0x3056
|
||||
#define EGL_WIDTH 0x3057
|
||||
#define EGL_LARGEST_PBUFFER 0x3058
|
||||
#define EGL_TEXTURE_FORMAT 0x3080
|
||||
#define EGL_TEXTURE_TARGET 0x3081
|
||||
#define EGL_MIPMAP_TEXTURE 0x3082
|
||||
#define EGL_MIPMAP_LEVEL 0x3083
|
||||
#define EGL_RENDER_BUFFER 0x3086
|
||||
#define EGL_VG_COLORSPACE 0x3087
|
||||
#define EGL_VG_ALPHA_FORMAT 0x3088
|
||||
#define EGL_HORIZONTAL_RESOLUTION 0x3090
|
||||
#define EGL_VERTICAL_RESOLUTION 0x3091
|
||||
#define EGL_PIXEL_ASPECT_RATIO 0x3092
|
||||
#define EGL_SWAP_BEHAVIOR 0x3093
|
||||
#define EGL_MULTISAMPLE_RESOLVE 0x3099
|
||||
|
||||
/* EGL_RENDER_BUFFER values / BindTexImage / ReleaseTexImage buffer targets */
|
||||
#define EGL_BACK_BUFFER 0x3084
|
||||
#define EGL_SINGLE_BUFFER 0x3085
|
||||
|
||||
/* OpenVG color spaces */
|
||||
#define EGL_VG_COLORSPACE_sRGB 0x3089 /* EGL_VG_COLORSPACE value */
|
||||
#define EGL_VG_COLORSPACE_LINEAR 0x308A /* EGL_VG_COLORSPACE value */
|
||||
|
||||
/* OpenVG alpha formats */
|
||||
#define EGL_VG_ALPHA_FORMAT_NONPRE 0x308B /* EGL_ALPHA_FORMAT value */
|
||||
#define EGL_VG_ALPHA_FORMAT_PRE 0x308C /* EGL_ALPHA_FORMAT value */
|
||||
|
||||
/* Constant scale factor by which fractional display resolutions &
|
||||
* aspect ratio are scaled when queried as integer values.
|
||||
*/
|
||||
#define EGL_DISPLAY_SCALING 10000
|
||||
|
||||
/* Unknown display resolution/aspect ratio */
|
||||
#define EGL_UNKNOWN ((EGLint)-1)
|
||||
|
||||
/* Back buffer swap behaviors */
|
||||
#define EGL_BUFFER_PRESERVED 0x3094 /* EGL_SWAP_BEHAVIOR value */
|
||||
#define EGL_BUFFER_DESTROYED 0x3095 /* EGL_SWAP_BEHAVIOR value */
|
||||
|
||||
/* CreatePbufferFromClientBuffer buffer types */
|
||||
#define EGL_OPENVG_IMAGE 0x3096
|
||||
|
||||
/* QueryContext targets */
|
||||
#define EGL_CONTEXT_CLIENT_TYPE 0x3097
|
||||
|
||||
/* CreateContext attributes */
|
||||
#define EGL_CONTEXT_CLIENT_VERSION 0x3098
|
||||
|
||||
/* Multisample resolution behaviors */
|
||||
#define EGL_MULTISAMPLE_RESOLVE_DEFAULT 0x309A /* EGL_MULTISAMPLE_RESOLVE value */
|
||||
#define EGL_MULTISAMPLE_RESOLVE_BOX 0x309B /* EGL_MULTISAMPLE_RESOLVE value */
|
||||
|
||||
/* BindAPI/QueryAPI targets */
|
||||
#define EGL_OPENGL_ES_API 0x30A0
|
||||
#define EGL_OPENVG_API 0x30A1
|
||||
#define EGL_OPENGL_API 0x30A2
|
||||
|
||||
/* GetCurrentSurface targets */
|
||||
#define EGL_DRAW 0x3059
|
||||
#define EGL_READ 0x305A
|
||||
|
||||
/* WaitNative engines */
|
||||
#define EGL_CORE_NATIVE_ENGINE 0x305B
|
||||
|
||||
/* EGL 1.2 tokens renamed for consistency in EGL 1.3 */
|
||||
#define EGL_COLORSPACE EGL_VG_COLORSPACE
|
||||
#define EGL_ALPHA_FORMAT EGL_VG_ALPHA_FORMAT
|
||||
#define EGL_COLORSPACE_sRGB EGL_VG_COLORSPACE_sRGB
|
||||
#define EGL_COLORSPACE_LINEAR EGL_VG_COLORSPACE_LINEAR
|
||||
#define EGL_ALPHA_FORMAT_NONPRE EGL_VG_ALPHA_FORMAT_NONPRE
|
||||
#define EGL_ALPHA_FORMAT_PRE EGL_VG_ALPHA_FORMAT_PRE
|
||||
|
||||
/* EGL extensions must request enum blocks from the Khronos
|
||||
* API Registrar, who maintains the enumerant registry. Submit
|
||||
* a bug in Khronos Bugzilla against task "Registry".
|
||||
*/
|
||||
|
||||
|
||||
|
||||
/* EGL Functions */
|
||||
|
||||
EGLAPI EGLint EGLAPIENTRY eglGetError(void);
|
||||
|
||||
EGLAPI EGLDisplay EGLAPIENTRY eglGetDisplay(EGLNativeDisplayType display_id);
|
||||
EGLAPI EGLBoolean EGLAPIENTRY eglInitialize(EGLDisplay dpy, EGLint *major, EGLint *minor);
|
||||
EGLAPI EGLBoolean EGLAPIENTRY eglTerminate(EGLDisplay dpy);
|
||||
|
||||
EGLAPI const char * EGLAPIENTRY eglQueryString(EGLDisplay dpy, EGLint name);
|
||||
|
||||
EGLAPI EGLBoolean EGLAPIENTRY eglGetConfigs(EGLDisplay dpy, EGLConfig *configs,
|
||||
EGLint config_size, EGLint *num_config);
|
||||
EGLAPI EGLBoolean EGLAPIENTRY eglChooseConfig(EGLDisplay dpy, const EGLint *attrib_list,
|
||||
EGLConfig *configs, EGLint config_size,
|
||||
EGLint *num_config);
|
||||
EGLAPI EGLBoolean EGLAPIENTRY eglGetConfigAttrib(EGLDisplay dpy, EGLConfig config,
|
||||
EGLint attribute, EGLint *value);
|
||||
|
||||
EGLAPI EGLSurface EGLAPIENTRY eglCreateWindowSurface(EGLDisplay dpy, EGLConfig config,
|
||||
EGLNativeWindowType win,
|
||||
const EGLint *attrib_list);
|
||||
EGLAPI EGLSurface EGLAPIENTRY eglCreatePbufferSurface(EGLDisplay dpy, EGLConfig config,
|
||||
const EGLint *attrib_list);
|
||||
EGLAPI EGLSurface EGLAPIENTRY eglCreatePixmapSurface(EGLDisplay dpy, EGLConfig config,
|
||||
EGLNativePixmapType pixmap,
|
||||
const EGLint *attrib_list);
|
||||
EGLAPI EGLBoolean EGLAPIENTRY eglDestroySurface(EGLDisplay dpy, EGLSurface surface);
|
||||
EGLAPI EGLBoolean EGLAPIENTRY eglQuerySurface(EGLDisplay dpy, EGLSurface surface,
|
||||
EGLint attribute, EGLint *value);
|
||||
|
||||
EGLAPI EGLBoolean EGLAPIENTRY eglBindAPI(EGLenum api);
|
||||
EGLAPI EGLenum EGLAPIENTRY eglQueryAPI(void);
|
||||
|
||||
EGLAPI EGLBoolean EGLAPIENTRY eglWaitClient(void);
|
||||
|
||||
EGLAPI EGLBoolean EGLAPIENTRY eglReleaseThread(void);
|
||||
|
||||
EGLAPI EGLSurface EGLAPIENTRY eglCreatePbufferFromClientBuffer(
|
||||
EGLDisplay dpy, EGLenum buftype, EGLClientBuffer buffer,
|
||||
EGLConfig config, const EGLint *attrib_list);
|
||||
|
||||
EGLAPI EGLBoolean EGLAPIENTRY eglSurfaceAttrib(EGLDisplay dpy, EGLSurface surface,
|
||||
EGLint attribute, EGLint value);
|
||||
EGLAPI EGLBoolean EGLAPIENTRY eglBindTexImage(EGLDisplay dpy, EGLSurface surface, EGLint buffer);
|
||||
EGLAPI EGLBoolean EGLAPIENTRY eglReleaseTexImage(EGLDisplay dpy, EGLSurface surface, EGLint buffer);
|
||||
|
||||
|
||||
EGLAPI EGLBoolean EGLAPIENTRY eglSwapInterval(EGLDisplay dpy, EGLint interval);
|
||||
|
||||
|
||||
EGLAPI EGLContext EGLAPIENTRY eglCreateContext(EGLDisplay dpy, EGLConfig config,
|
||||
EGLContext share_context,
|
||||
const EGLint *attrib_list);
|
||||
EGLAPI EGLBoolean EGLAPIENTRY eglDestroyContext(EGLDisplay dpy, EGLContext ctx);
|
||||
EGLAPI EGLBoolean EGLAPIENTRY eglMakeCurrent(EGLDisplay dpy, EGLSurface draw,
|
||||
EGLSurface read, EGLContext ctx);
|
||||
|
||||
EGLAPI EGLContext EGLAPIENTRY eglGetCurrentContext(void);
|
||||
EGLAPI EGLSurface EGLAPIENTRY eglGetCurrentSurface(EGLint readdraw);
|
||||
EGLAPI EGLDisplay EGLAPIENTRY eglGetCurrentDisplay(void);
|
||||
EGLAPI EGLBoolean EGLAPIENTRY eglQueryContext(EGLDisplay dpy, EGLContext ctx,
|
||||
EGLint attribute, EGLint *value);
|
||||
|
||||
EGLAPI EGLBoolean EGLAPIENTRY eglWaitGL(void);
|
||||
EGLAPI EGLBoolean EGLAPIENTRY eglWaitNative(EGLint engine);
|
||||
EGLAPI EGLBoolean EGLAPIENTRY eglSwapBuffers(EGLDisplay dpy, EGLSurface surface);
|
||||
EGLAPI EGLBoolean EGLAPIENTRY eglCopyBuffers(EGLDisplay dpy, EGLSurface surface,
|
||||
EGLNativePixmapType target);
|
||||
|
||||
/* This is a generic function pointer type, whose name indicates it must
|
||||
* be cast to the proper type *and calling convention* before use.
|
||||
*/
|
||||
typedef void (*__eglMustCastToProperFunctionPointerType)(void);
|
||||
|
||||
/* Now, define eglGetProcAddress using the generic function ptr. type */
|
||||
EGLAPI __eglMustCastToProperFunctionPointerType EGLAPIENTRY
|
||||
eglGetProcAddress(const char *procname);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __egl_h_ */
|
||||
@@ -0,0 +1,124 @@
|
||||
#ifndef __eglplatform_h_
|
||||
#define __eglplatform_h_
|
||||
|
||||
/*
|
||||
** Copyright (c) 2007-2009 The Khronos Group Inc.
|
||||
**
|
||||
** Permission is hereby granted, free of charge, to any person obtaining a
|
||||
** copy of this software and/or associated documentation files (the
|
||||
** "Materials"), to deal in the Materials without restriction, including
|
||||
** without limitation the rights to use, copy, modify, merge, publish,
|
||||
** distribute, sublicense, and/or sell copies of the Materials, and to
|
||||
** permit persons to whom the Materials are 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 Materials.
|
||||
**
|
||||
** THE MATERIALS ARE 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
|
||||
** MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
|
||||
*/
|
||||
|
||||
/* Platform-specific types and definitions for egl.h
|
||||
* $Revision: 12306 $ on $Date: 2010-08-25 09:51:28 -0700 (Wed, 25 Aug 2010) $
|
||||
*
|
||||
* Adopters may modify khrplatform.h and this file to suit their platform.
|
||||
* You are encouraged to submit all modifications to the Khronos group so that
|
||||
* they can be included in future versions of this file. Please submit changes
|
||||
* by sending them to the public Khronos Bugzilla (http://khronos.org/bugzilla)
|
||||
* by filing a bug against product "EGL" component "Registry".
|
||||
*/
|
||||
|
||||
#include <APPLE/khrplatform.h>
|
||||
|
||||
/* Macros used in EGL function prototype declarations.
|
||||
*
|
||||
* EGL functions should be prototyped as:
|
||||
*
|
||||
* EGLAPI return-type EGLAPIENTRY eglFunction(arguments);
|
||||
* typedef return-type (EXPAPIENTRYP PFNEGLFUNCTIONPROC) (arguments);
|
||||
*
|
||||
* KHRONOS_APICALL and KHRONOS_APIENTRY are defined in KHR/khrplatform.h
|
||||
*/
|
||||
|
||||
#ifndef EGLAPI
|
||||
#define EGLAPI KHRONOS_APICALL
|
||||
#endif
|
||||
|
||||
#ifndef EGLAPIENTRY
|
||||
#define EGLAPIENTRY KHRONOS_APIENTRY
|
||||
#endif
|
||||
#define EGLAPIENTRYP EGLAPIENTRY*
|
||||
|
||||
/* The types NativeDisplayType, NativeWindowType, and NativePixmapType
|
||||
* are aliases of window-system-dependent types, such as X Display * or
|
||||
* Windows Device Context. They must be defined in platform-specific
|
||||
* code below. The EGL-prefixed versions of Native*Type are the same
|
||||
* types, renamed in EGL 1.3 so all types in the API start with "EGL".
|
||||
*
|
||||
* Khronos STRONGLY RECOMMENDS that you use the default definitions
|
||||
* provided below, since these changes affect both binary and source
|
||||
* portability of applications using EGL running on different EGL
|
||||
* implementations.
|
||||
*/
|
||||
|
||||
#if defined(_WIN32) || defined(__VC32__) && !defined(__CYGWIN__) && !defined(__SCITECH_SNAP__) /* Win32 and WinCE */
|
||||
#ifndef WIN32_LEAN_AND_MEAN
|
||||
#define WIN32_LEAN_AND_MEAN 1
|
||||
#endif
|
||||
#include <windows.h>
|
||||
|
||||
typedef HDC EGLNativeDisplayType;
|
||||
typedef HBITMAP EGLNativePixmapType;
|
||||
typedef HWND EGLNativeWindowType;
|
||||
|
||||
#elif defined(__WINSCW__) || defined(__SYMBIAN32__) /* Symbian */
|
||||
|
||||
typedef int EGLNativeDisplayType;
|
||||
typedef void *EGLNativeWindowType;
|
||||
typedef void *EGLNativePixmapType;
|
||||
|
||||
#elif defined(__unix__)
|
||||
|
||||
/* X11 (tentative) */
|
||||
#include <X11/Xlib.h>
|
||||
#include <X11/Xutil.h>
|
||||
|
||||
typedef Display *EGLNativeDisplayType;
|
||||
typedef Pixmap EGLNativePixmapType;
|
||||
typedef Window EGLNativeWindowType;
|
||||
|
||||
#elif defined(__GNUC__) && ( defined(__APPLE_CPP__) || defined(__APPLE_CC__) || defined(__MACOS_CLASSIC__) )
|
||||
// this line is taken from the TargetConditionals.h file in any on the iOS or Mac OS X platforms
|
||||
|
||||
struct appleEGLWindow;
|
||||
|
||||
typedef int EGLNativeDisplayType;
|
||||
typedef void *EGLNativePixmapType;
|
||||
typedef struct appleEGLWindow *EGLNativeWindowType;
|
||||
|
||||
#else
|
||||
#error "Platform not recognized"
|
||||
#endif
|
||||
|
||||
/* EGL 1.2 types, renamed for consistency in EGL 1.3 */
|
||||
typedef EGLNativeDisplayType NativeDisplayType;
|
||||
typedef EGLNativePixmapType NativePixmapType;
|
||||
typedef EGLNativeWindowType NativeWindowType;
|
||||
|
||||
|
||||
/* Define EGLint. This must be a signed integral type large enough to contain
|
||||
* all legal attribute names and values passed into and out of EGL, whether
|
||||
* their type is boolean, bitmask, enumerant (symbolic constant), integer,
|
||||
* handle, or other. While in general a 32-bit integer will suffice, if
|
||||
* handles are 64 bit types, then EGLint should be defined as a signed 64-bit
|
||||
* integer type.
|
||||
*/
|
||||
typedef khronos_int32_t EGLint;
|
||||
|
||||
#endif /* __eglplatform_h */
|
||||
@@ -0,0 +1,269 @@
|
||||
#ifndef __khrplatform_h_
|
||||
#define __khrplatform_h_
|
||||
|
||||
/*
|
||||
** Copyright (c) 2008-2009 The Khronos Group Inc.
|
||||
**
|
||||
** Permission is hereby granted, free of charge, to any person obtaining a
|
||||
** copy of this software and/or associated documentation files (the
|
||||
** "Materials"), to deal in the Materials without restriction, including
|
||||
** without limitation the rights to use, copy, modify, merge, publish,
|
||||
** distribute, sublicense, and/or sell copies of the Materials, and to
|
||||
** permit persons to whom the Materials are 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 Materials.
|
||||
**
|
||||
** THE MATERIALS ARE 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
|
||||
** MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
|
||||
*/
|
||||
|
||||
/* Khronos platform-specific types and definitions.
|
||||
*
|
||||
* $Revision: 9356 $ on $Date: 2009-10-21 02:52:25 -0700 (Wed, 21 Oct 2009) $
|
||||
*
|
||||
* Adopters may modify this file to suit their platform. Adopters are
|
||||
* encouraged to submit platform specific modifications to the Khronos
|
||||
* group so that they can be included in future versions of this file.
|
||||
* Please submit changes by sending them to the public Khronos Bugzilla
|
||||
* (http://khronos.org/bugzilla) by filing a bug against product
|
||||
* "Khronos (general)" component "Registry".
|
||||
*
|
||||
* A predefined template which fills in some of the bug fields can be
|
||||
* reached using http://tinyurl.com/khrplatform-h-bugreport, but you
|
||||
* must create a Bugzilla login first.
|
||||
*
|
||||
*
|
||||
* See the Implementer's Guidelines for information about where this file
|
||||
* should be located on your system and for more details of its use:
|
||||
* http://www.khronos.org/registry/implementers_guide.pdf
|
||||
*
|
||||
* This file should be included as
|
||||
* #include <KHR/khrplatform.h>
|
||||
* by Khronos client API header files that use its types and defines.
|
||||
*
|
||||
* The types in khrplatform.h should only be used to define API-specific types.
|
||||
*
|
||||
* Types defined in khrplatform.h:
|
||||
* khronos_int8_t signed 8 bit
|
||||
* khronos_uint8_t unsigned 8 bit
|
||||
* khronos_int16_t signed 16 bit
|
||||
* khronos_uint16_t unsigned 16 bit
|
||||
* khronos_int32_t signed 32 bit
|
||||
* khronos_uint32_t unsigned 32 bit
|
||||
* khronos_int64_t signed 64 bit
|
||||
* khronos_uint64_t unsigned 64 bit
|
||||
* khronos_intptr_t signed same number of bits as a pointer
|
||||
* khronos_uintptr_t unsigned same number of bits as a pointer
|
||||
* khronos_ssize_t signed size
|
||||
* khronos_usize_t unsigned size
|
||||
* khronos_float_t signed 32 bit floating point
|
||||
* khronos_time_ns_t unsigned 64 bit time in nanoseconds
|
||||
* khronos_utime_nanoseconds_t unsigned time interval or absolute time in
|
||||
* nanoseconds
|
||||
* khronos_stime_nanoseconds_t signed time interval in nanoseconds
|
||||
* khronos_boolean_enum_t enumerated boolean type. This should
|
||||
* only be used as a base type when a client API's boolean type is
|
||||
* an enum. Client APIs which use an integer or other type for
|
||||
* booleans cannot use this as the base type for their boolean.
|
||||
*
|
||||
* Tokens defined in khrplatform.h:
|
||||
*
|
||||
* KHRONOS_FALSE, KHRONOS_TRUE Enumerated boolean false/true values.
|
||||
*
|
||||
* KHRONOS_SUPPORT_INT64 is 1 if 64 bit integers are supported; otherwise 0.
|
||||
* KHRONOS_SUPPORT_FLOAT is 1 if floats are supported; otherwise 0.
|
||||
*
|
||||
* Calling convention macros defined in this file:
|
||||
* KHRONOS_APICALL
|
||||
* KHRONOS_APIENTRY
|
||||
* KHRONOS_APIATTRIBUTES
|
||||
*
|
||||
* These may be used in function prototypes as:
|
||||
*
|
||||
* KHRONOS_APICALL void KHRONOS_APIENTRY funcname(
|
||||
* int arg1,
|
||||
* int arg2) KHRONOS_APIATTRIBUTES;
|
||||
*/
|
||||
|
||||
/*-------------------------------------------------------------------------
|
||||
* Definition of KHRONOS_APICALL
|
||||
*-------------------------------------------------------------------------
|
||||
* This precedes the return type of the function in the function prototype.
|
||||
*/
|
||||
#if defined(_WIN32) && !defined(__SCITECH_SNAP__)
|
||||
# define KHRONOS_APICALL __declspec(dllimport)
|
||||
#elif defined (__SYMBIAN32__)
|
||||
# define KHRONOS_APICALL IMPORT_C
|
||||
#else
|
||||
# define KHRONOS_APICALL
|
||||
#endif
|
||||
|
||||
/*-------------------------------------------------------------------------
|
||||
* Definition of KHRONOS_APIENTRY
|
||||
*-------------------------------------------------------------------------
|
||||
* This follows the return type of the function and precedes the function
|
||||
* name in the function prototype.
|
||||
*/
|
||||
#if defined(_WIN32) && !defined(_WIN32_WCE) && !defined(__SCITECH_SNAP__)
|
||||
/* Win32 but not WinCE */
|
||||
# define KHRONOS_APIENTRY __stdcall
|
||||
#else
|
||||
# define KHRONOS_APIENTRY
|
||||
#endif
|
||||
|
||||
/*-------------------------------------------------------------------------
|
||||
* Definition of KHRONOS_APIATTRIBUTES
|
||||
*-------------------------------------------------------------------------
|
||||
* This follows the closing parenthesis of the function prototype arguments.
|
||||
*/
|
||||
#if defined (__ARMCC_2__)
|
||||
#define KHRONOS_APIATTRIBUTES __softfp
|
||||
#else
|
||||
#define KHRONOS_APIATTRIBUTES
|
||||
#endif
|
||||
|
||||
/*-------------------------------------------------------------------------
|
||||
* basic type definitions
|
||||
*-----------------------------------------------------------------------*/
|
||||
#if (defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L) || defined(__GNUC__) || defined(__SCO__) || defined(__USLC__)
|
||||
|
||||
|
||||
/*
|
||||
* Using <stdint.h>
|
||||
*/
|
||||
#include <stdint.h>
|
||||
typedef int32_t khronos_int32_t;
|
||||
typedef uint32_t khronos_uint32_t;
|
||||
typedef int64_t khronos_int64_t;
|
||||
typedef uint64_t khronos_uint64_t;
|
||||
#define KHRONOS_SUPPORT_INT64 1
|
||||
#define KHRONOS_SUPPORT_FLOAT 1
|
||||
|
||||
#elif defined(__VMS ) || defined(__sgi)
|
||||
|
||||
/*
|
||||
* Using <inttypes.h>
|
||||
*/
|
||||
#include <inttypes.h>
|
||||
typedef int32_t khronos_int32_t;
|
||||
typedef uint32_t khronos_uint32_t;
|
||||
typedef int64_t khronos_int64_t;
|
||||
typedef uint64_t khronos_uint64_t;
|
||||
#define KHRONOS_SUPPORT_INT64 1
|
||||
#define KHRONOS_SUPPORT_FLOAT 1
|
||||
|
||||
#elif defined(_WIN32) && !defined(__SCITECH_SNAP__)
|
||||
|
||||
/*
|
||||
* Win32
|
||||
*/
|
||||
typedef __int32 khronos_int32_t;
|
||||
typedef unsigned __int32 khronos_uint32_t;
|
||||
typedef __int64 khronos_int64_t;
|
||||
typedef unsigned __int64 khronos_uint64_t;
|
||||
#define KHRONOS_SUPPORT_INT64 1
|
||||
#define KHRONOS_SUPPORT_FLOAT 1
|
||||
|
||||
#elif defined(__sun__) || defined(__digital__)
|
||||
|
||||
/*
|
||||
* Sun or Digital
|
||||
*/
|
||||
typedef int khronos_int32_t;
|
||||
typedef unsigned int khronos_uint32_t;
|
||||
#if defined(__arch64__) || defined(_LP64)
|
||||
typedef long int khronos_int64_t;
|
||||
typedef unsigned long int khronos_uint64_t;
|
||||
#else
|
||||
typedef long long int khronos_int64_t;
|
||||
typedef unsigned long long int khronos_uint64_t;
|
||||
#endif /* __arch64__ */
|
||||
#define KHRONOS_SUPPORT_INT64 1
|
||||
#define KHRONOS_SUPPORT_FLOAT 1
|
||||
|
||||
#elif 0
|
||||
|
||||
/*
|
||||
* Hypothetical platform with no float or int64 support
|
||||
*/
|
||||
typedef int khronos_int32_t;
|
||||
typedef unsigned int khronos_uint32_t;
|
||||
#define KHRONOS_SUPPORT_INT64 0
|
||||
#define KHRONOS_SUPPORT_FLOAT 0
|
||||
|
||||
#else
|
||||
|
||||
/*
|
||||
* Generic fallback
|
||||
*/
|
||||
#include <stdint.h>
|
||||
typedef int32_t khronos_int32_t;
|
||||
typedef uint32_t khronos_uint32_t;
|
||||
typedef int64_t khronos_int64_t;
|
||||
typedef uint64_t khronos_uint64_t;
|
||||
#define KHRONOS_SUPPORT_INT64 1
|
||||
#define KHRONOS_SUPPORT_FLOAT 1
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
* Types that are (so far) the same on all platforms
|
||||
*/
|
||||
typedef signed char khronos_int8_t;
|
||||
typedef unsigned char khronos_uint8_t;
|
||||
typedef signed short int khronos_int16_t;
|
||||
typedef unsigned short int khronos_uint16_t;
|
||||
typedef signed long int khronos_intptr_t;
|
||||
typedef unsigned long int khronos_uintptr_t;
|
||||
typedef signed long int khronos_ssize_t;
|
||||
typedef unsigned long int khronos_usize_t;
|
||||
|
||||
#if KHRONOS_SUPPORT_FLOAT
|
||||
/*
|
||||
* Float type
|
||||
*/
|
||||
typedef float khronos_float_t;
|
||||
#endif
|
||||
|
||||
#if KHRONOS_SUPPORT_INT64
|
||||
/* Time types
|
||||
*
|
||||
* These types can be used to represent a time interval in nanoseconds or
|
||||
* an absolute Unadjusted System Time. Unadjusted System Time is the number
|
||||
* of nanoseconds since some arbitrary system event (e.g. since the last
|
||||
* time the system booted). The Unadjusted System Time is an unsigned
|
||||
* 64 bit value that wraps back to 0 every 584 years. Time intervals
|
||||
* may be either signed or unsigned.
|
||||
*/
|
||||
typedef khronos_uint64_t khronos_utime_nanoseconds_t;
|
||||
typedef khronos_int64_t khronos_stime_nanoseconds_t;
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Dummy value used to pad enum types to 32 bits.
|
||||
*/
|
||||
#ifndef KHRONOS_MAX_ENUM
|
||||
#define KHRONOS_MAX_ENUM 0x7FFFFFFF
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Enumerated boolean type
|
||||
*
|
||||
* Values other than zero should be considered to be true. Therefore
|
||||
* comparisons should not be made against KHRONOS_TRUE.
|
||||
*/
|
||||
typedef enum {
|
||||
KHRONOS_FALSE = 0,
|
||||
KHRONOS_TRUE = 1,
|
||||
KHRONOS_BOOLEAN_ENUM_FORCE_SIZE = KHRONOS_MAX_ENUM
|
||||
} khronos_boolean_enum_t;
|
||||
|
||||
#endif /* __khrplatform_h_ */
|
||||
+131
-131
@@ -5,27 +5,27 @@
|
||||
*/
|
||||
|
||||
/*
|
||||
** Copyright (c) 2007-2009 The Khronos Group Inc.
|
||||
**
|
||||
** Permission is hereby granted, free of charge, to any person obtaining a
|
||||
** copy of this software and/or associated documentation files (the
|
||||
** "Materials"), to deal in the Materials without restriction, including
|
||||
** without limitation the rights to use, copy, modify, merge, publish,
|
||||
** distribute, sublicense, and/or sell copies of the Materials, and to
|
||||
** permit persons to whom the Materials are 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 Materials.
|
||||
**
|
||||
** THE MATERIALS ARE 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
|
||||
** MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
|
||||
*/
|
||||
** Copyright (c) 2007-2009 The Khronos Group Inc.
|
||||
**
|
||||
** Permission is hereby granted, free of charge, to any person obtaining a
|
||||
** copy of this software and/or associated documentation files (the
|
||||
** "Materials"), to deal in the Materials without restriction, including
|
||||
** without limitation the rights to use, copy, modify, merge, publish,
|
||||
** distribute, sublicense, and/or sell copies of the Materials, and to
|
||||
** permit persons to whom the Materials are 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 Materials.
|
||||
**
|
||||
** THE MATERIALS ARE 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
|
||||
** MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
|
||||
*/
|
||||
|
||||
#ifndef __egl_h_
|
||||
#define __egl_h_
|
||||
@@ -39,41 +39,41 @@
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* EGL Types */
|
||||
/* EGLint is defined in eglplatform.h */
|
||||
typedef unsigned int EGLBoolean;
|
||||
typedef unsigned int EGLenum;
|
||||
typedef void *EGLConfig;
|
||||
typedef void *EGLContext;
|
||||
typedef void *EGLDisplay;
|
||||
typedef void *EGLSurface;
|
||||
typedef void *EGLClientBuffer;
|
||||
/* EGL Types */
|
||||
/* EGLint is defined in eglplatform.h */
|
||||
typedef unsigned int EGLBoolean;
|
||||
typedef unsigned int EGLenum;
|
||||
typedef void *EGLConfig;
|
||||
typedef void *EGLContext;
|
||||
typedef void *EGLDisplay;
|
||||
typedef void *EGLSurface;
|
||||
typedef void *EGLClientBuffer;
|
||||
|
||||
/* EGL Versioning */
|
||||
/* EGL Versioning */
|
||||
#define EGL_VERSION_1_0 1
|
||||
#define EGL_VERSION_1_1 1
|
||||
#define EGL_VERSION_1_2 1
|
||||
#define EGL_VERSION_1_3 1
|
||||
#define EGL_VERSION_1_4 1
|
||||
|
||||
/* EGL Enumerants. Bitmasks and other exceptional cases aside, most
|
||||
* enums are assigned unique values starting at 0x3000.
|
||||
*/
|
||||
/* EGL Enumerants. Bitmasks and other exceptional cases aside, most
|
||||
* enums are assigned unique values starting at 0x3000.
|
||||
*/
|
||||
|
||||
/* EGL aliases */
|
||||
/* EGL aliases */
|
||||
#define EGL_FALSE 0
|
||||
#define EGL_TRUE 1
|
||||
|
||||
/* Out-of-band handle values */
|
||||
/* Out-of-band handle values */
|
||||
#define EGL_DEFAULT_DISPLAY ((EGLNativeDisplayType)0)
|
||||
#define EGL_NO_CONTEXT ((EGLContext)0)
|
||||
#define EGL_NO_DISPLAY ((EGLDisplay)0)
|
||||
#define EGL_NO_SURFACE ((EGLSurface)0)
|
||||
|
||||
/* Out-of-band attribute value */
|
||||
/* Out-of-band attribute value */
|
||||
#define EGL_DONT_CARE ((EGLint)-1)
|
||||
|
||||
/* Errors / GetError return values */
|
||||
/* Errors / GetError return values */
|
||||
#define EGL_SUCCESS 0x3000
|
||||
#define EGL_NOT_INITIALIZED 0x3001
|
||||
#define EGL_BAD_ACCESS 0x3002
|
||||
@@ -90,9 +90,9 @@ typedef void *EGLClientBuffer;
|
||||
#define EGL_BAD_SURFACE 0x300D
|
||||
#define EGL_CONTEXT_LOST 0x300E /* EGL 1.1 - IMG_power_management */
|
||||
|
||||
/* Reserved 0x300F-0x301F for additional errors */
|
||||
/* Reserved 0x300F-0x301F for additional errors */
|
||||
|
||||
/* Config attributes */
|
||||
/* Config attributes */
|
||||
#define EGL_BUFFER_SIZE 0x3020
|
||||
#define EGL_ALPHA_SIZE 0x3021
|
||||
#define EGL_BLUE_SIZE 0x3022
|
||||
@@ -128,22 +128,22 @@ typedef void *EGLClientBuffer;
|
||||
#define EGL_MATCH_NATIVE_PIXMAP 0x3041 /* Pseudo-attribute (not queryable) */
|
||||
#define EGL_CONFORMANT 0x3042
|
||||
|
||||
/* Reserved 0x3041-0x304F for additional config attributes */
|
||||
/* Reserved 0x3041-0x304F for additional config attributes */
|
||||
|
||||
/* Config attribute values */
|
||||
/* Config attribute values */
|
||||
#define EGL_SLOW_CONFIG 0x3050 /* EGL_CONFIG_CAVEAT value */
|
||||
#define EGL_NON_CONFORMANT_CONFIG 0x3051 /* EGL_CONFIG_CAVEAT value */
|
||||
#define EGL_TRANSPARENT_RGB 0x3052 /* EGL_TRANSPARENT_TYPE value */
|
||||
#define EGL_RGB_BUFFER 0x308E /* EGL_COLOR_BUFFER_TYPE value */
|
||||
#define EGL_LUMINANCE_BUFFER 0x308F /* EGL_COLOR_BUFFER_TYPE value */
|
||||
|
||||
/* More config attribute values, for EGL_TEXTURE_FORMAT */
|
||||
/* More config attribute values, for EGL_TEXTURE_FORMAT */
|
||||
#define EGL_NO_TEXTURE 0x305C
|
||||
#define EGL_TEXTURE_RGB 0x305D
|
||||
#define EGL_TEXTURE_RGBA 0x305E
|
||||
#define EGL_TEXTURE_2D 0x305F
|
||||
|
||||
/* Config attribute mask bits */
|
||||
/* Config attribute mask bits */
|
||||
#define EGL_PBUFFER_BIT 0x0001 /* EGL_SURFACE_TYPE mask bits */
|
||||
#define EGL_PIXMAP_BIT 0x0002 /* EGL_SURFACE_TYPE mask bits */
|
||||
#define EGL_WINDOW_BIT 0x0004 /* EGL_SURFACE_TYPE mask bits */
|
||||
@@ -157,13 +157,13 @@ typedef void *EGLClientBuffer;
|
||||
#define EGL_OPENGL_ES2_BIT 0x0004 /* EGL_RENDERABLE_TYPE mask bits */
|
||||
#define EGL_OPENGL_BIT 0x0008 /* EGL_RENDERABLE_TYPE mask bits */
|
||||
|
||||
/* QueryString targets */
|
||||
/* QueryString targets */
|
||||
#define EGL_VENDOR 0x3053
|
||||
#define EGL_VERSION 0x3054
|
||||
#define EGL_EXTENSIONS 0x3055
|
||||
#define EGL_CLIENT_APIS 0x308D
|
||||
|
||||
/* QuerySurface / SurfaceAttrib / CreatePbufferSurface targets */
|
||||
/* QuerySurface / SurfaceAttrib / CreatePbufferSurface targets */
|
||||
#define EGL_HEIGHT 0x3056
|
||||
#define EGL_WIDTH 0x3057
|
||||
#define EGL_LARGEST_PBUFFER 0x3058
|
||||
@@ -180,56 +180,56 @@ typedef void *EGLClientBuffer;
|
||||
#define EGL_SWAP_BEHAVIOR 0x3093
|
||||
#define EGL_MULTISAMPLE_RESOLVE 0x3099
|
||||
|
||||
/* EGL_RENDER_BUFFER values / BindTexImage / ReleaseTexImage buffer targets */
|
||||
/* EGL_RENDER_BUFFER values / BindTexImage / ReleaseTexImage buffer targets */
|
||||
#define EGL_BACK_BUFFER 0x3084
|
||||
#define EGL_SINGLE_BUFFER 0x3085
|
||||
|
||||
/* OpenVG color spaces */
|
||||
/* OpenVG color spaces */
|
||||
#define EGL_VG_COLORSPACE_sRGB 0x3089 /* EGL_VG_COLORSPACE value */
|
||||
#define EGL_VG_COLORSPACE_LINEAR 0x308A /* EGL_VG_COLORSPACE value */
|
||||
|
||||
/* OpenVG alpha formats */
|
||||
/* OpenVG alpha formats */
|
||||
#define EGL_VG_ALPHA_FORMAT_NONPRE 0x308B /* EGL_ALPHA_FORMAT value */
|
||||
#define EGL_VG_ALPHA_FORMAT_PRE 0x308C /* EGL_ALPHA_FORMAT value */
|
||||
|
||||
/* Constant scale factor by which fractional display resolutions &
|
||||
* aspect ratio are scaled when queried as integer values.
|
||||
*/
|
||||
/* Constant scale factor by which fractional display resolutions &
|
||||
* aspect ratio are scaled when queried as integer values.
|
||||
*/
|
||||
#define EGL_DISPLAY_SCALING 10000
|
||||
|
||||
/* Unknown display resolution/aspect ratio */
|
||||
/* Unknown display resolution/aspect ratio */
|
||||
#define EGL_UNKNOWN ((EGLint)-1)
|
||||
|
||||
/* Back buffer swap behaviors */
|
||||
/* Back buffer swap behaviors */
|
||||
#define EGL_BUFFER_PRESERVED 0x3094 /* EGL_SWAP_BEHAVIOR value */
|
||||
#define EGL_BUFFER_DESTROYED 0x3095 /* EGL_SWAP_BEHAVIOR value */
|
||||
|
||||
/* CreatePbufferFromClientBuffer buffer types */
|
||||
/* CreatePbufferFromClientBuffer buffer types */
|
||||
#define EGL_OPENVG_IMAGE 0x3096
|
||||
|
||||
/* QueryContext targets */
|
||||
/* QueryContext targets */
|
||||
#define EGL_CONTEXT_CLIENT_TYPE 0x3097
|
||||
|
||||
/* CreateContext attributes */
|
||||
/* CreateContext attributes */
|
||||
#define EGL_CONTEXT_CLIENT_VERSION 0x3098
|
||||
|
||||
/* Multisample resolution behaviors */
|
||||
/* Multisample resolution behaviors */
|
||||
#define EGL_MULTISAMPLE_RESOLVE_DEFAULT 0x309A /* EGL_MULTISAMPLE_RESOLVE value */
|
||||
#define EGL_MULTISAMPLE_RESOLVE_BOX 0x309B /* EGL_MULTISAMPLE_RESOLVE value */
|
||||
|
||||
/* BindAPI/QueryAPI targets */
|
||||
/* BindAPI/QueryAPI targets */
|
||||
#define EGL_OPENGL_ES_API 0x30A0
|
||||
#define EGL_OPENVG_API 0x30A1
|
||||
#define EGL_OPENGL_API 0x30A2
|
||||
|
||||
/* GetCurrentSurface targets */
|
||||
/* GetCurrentSurface targets */
|
||||
#define EGL_DRAW 0x3059
|
||||
#define EGL_READ 0x305A
|
||||
|
||||
/* WaitNative engines */
|
||||
/* WaitNative engines */
|
||||
#define EGL_CORE_NATIVE_ENGINE 0x305B
|
||||
|
||||
/* EGL 1.2 tokens renamed for consistency in EGL 1.3 */
|
||||
/* EGL 1.2 tokens renamed for consistency in EGL 1.3 */
|
||||
#define EGL_COLORSPACE EGL_VG_COLORSPACE
|
||||
#define EGL_ALPHA_FORMAT EGL_VG_ALPHA_FORMAT
|
||||
#define EGL_COLORSPACE_sRGB EGL_VG_COLORSPACE_sRGB
|
||||
@@ -237,93 +237,93 @@ typedef void *EGLClientBuffer;
|
||||
#define EGL_ALPHA_FORMAT_NONPRE EGL_VG_ALPHA_FORMAT_NONPRE
|
||||
#define EGL_ALPHA_FORMAT_PRE EGL_VG_ALPHA_FORMAT_PRE
|
||||
|
||||
/* EGL extensions must request enum blocks from the Khronos
|
||||
* API Registrar, who maintains the enumerant registry. Submit
|
||||
* a bug in Khronos Bugzilla against task "Registry".
|
||||
*/
|
||||
/* EGL extensions must request enum blocks from the Khronos
|
||||
* API Registrar, who maintains the enumerant registry. Submit
|
||||
* a bug in Khronos Bugzilla against task "Registry".
|
||||
*/
|
||||
|
||||
|
||||
|
||||
/* EGL Functions */
|
||||
/* EGL Functions */
|
||||
|
||||
EGLAPI EGLint EGLAPIENTRY eglGetError(void);
|
||||
EGLAPI EGLint EGLAPIENTRY eglGetError(void);
|
||||
|
||||
EGLAPI EGLDisplay EGLAPIENTRY eglGetDisplay(EGLNativeDisplayType display_id);
|
||||
EGLAPI EGLBoolean EGLAPIENTRY eglInitialize(EGLDisplay dpy, EGLint *major, EGLint *minor);
|
||||
EGLAPI EGLBoolean EGLAPIENTRY eglTerminate(EGLDisplay dpy);
|
||||
EGLAPI EGLDisplay EGLAPIENTRY eglGetDisplay(EGLNativeDisplayType display_id);
|
||||
EGLAPI EGLBoolean EGLAPIENTRY eglInitialize(EGLDisplay dpy, EGLint *major, EGLint *minor);
|
||||
EGLAPI EGLBoolean EGLAPIENTRY eglTerminate(EGLDisplay dpy);
|
||||
|
||||
EGLAPI const char * EGLAPIENTRY eglQueryString(EGLDisplay dpy, EGLint name);
|
||||
EGLAPI const char * EGLAPIENTRY eglQueryString(EGLDisplay dpy, EGLint name);
|
||||
|
||||
EGLAPI EGLBoolean EGLAPIENTRY eglGetConfigs(EGLDisplay dpy, EGLConfig *configs,
|
||||
EGLint config_size, EGLint *num_config);
|
||||
EGLAPI EGLBoolean EGLAPIENTRY eglChooseConfig(EGLDisplay dpy, const EGLint *attrib_list,
|
||||
EGLConfig *configs, EGLint config_size,
|
||||
EGLint *num_config);
|
||||
EGLAPI EGLBoolean EGLAPIENTRY eglGetConfigAttrib(EGLDisplay dpy, EGLConfig config,
|
||||
EGLint attribute, EGLint *value);
|
||||
EGLAPI EGLBoolean EGLAPIENTRY eglGetConfigs(EGLDisplay dpy, EGLConfig *configs,
|
||||
EGLint config_size, EGLint *num_config);
|
||||
EGLAPI EGLBoolean EGLAPIENTRY eglChooseConfig(EGLDisplay dpy, const EGLint *attrib_list,
|
||||
EGLConfig *configs, EGLint config_size,
|
||||
EGLint *num_config);
|
||||
EGLAPI EGLBoolean EGLAPIENTRY eglGetConfigAttrib(EGLDisplay dpy, EGLConfig config,
|
||||
EGLint attribute, EGLint *value);
|
||||
|
||||
EGLAPI EGLSurface EGLAPIENTRY eglCreateWindowSurface(EGLDisplay dpy, EGLConfig config,
|
||||
EGLNativeWindowType win,
|
||||
const EGLint *attrib_list);
|
||||
EGLAPI EGLSurface EGLAPIENTRY eglCreatePbufferSurface(EGLDisplay dpy, EGLConfig config,
|
||||
const EGLint *attrib_list);
|
||||
EGLAPI EGLSurface EGLAPIENTRY eglCreatePixmapSurface(EGLDisplay dpy, EGLConfig config,
|
||||
EGLNativePixmapType pixmap,
|
||||
const EGLint *attrib_list);
|
||||
EGLAPI EGLBoolean EGLAPIENTRY eglDestroySurface(EGLDisplay dpy, EGLSurface surface);
|
||||
EGLAPI EGLBoolean EGLAPIENTRY eglQuerySurface(EGLDisplay dpy, EGLSurface surface,
|
||||
EGLint attribute, EGLint *value);
|
||||
EGLAPI EGLSurface EGLAPIENTRY eglCreateWindowSurface(EGLDisplay dpy, EGLConfig config,
|
||||
EGLNativeWindowType win,
|
||||
const EGLint *attrib_list);
|
||||
EGLAPI EGLSurface EGLAPIENTRY eglCreatePbufferSurface(EGLDisplay dpy, EGLConfig config,
|
||||
const EGLint *attrib_list);
|
||||
EGLAPI EGLSurface EGLAPIENTRY eglCreatePixmapSurface(EGLDisplay dpy, EGLConfig config,
|
||||
EGLNativePixmapType pixmap,
|
||||
const EGLint *attrib_list);
|
||||
EGLAPI EGLBoolean EGLAPIENTRY eglDestroySurface(EGLDisplay dpy, EGLSurface surface);
|
||||
EGLAPI EGLBoolean EGLAPIENTRY eglQuerySurface(EGLDisplay dpy, EGLSurface surface,
|
||||
EGLint attribute, EGLint *value);
|
||||
|
||||
EGLAPI EGLBoolean EGLAPIENTRY eglBindAPI(EGLenum api);
|
||||
EGLAPI EGLenum EGLAPIENTRY eglQueryAPI(void);
|
||||
EGLAPI EGLBoolean EGLAPIENTRY eglBindAPI(EGLenum api);
|
||||
EGLAPI EGLenum EGLAPIENTRY eglQueryAPI(void);
|
||||
|
||||
EGLAPI EGLBoolean EGLAPIENTRY eglWaitClient(void);
|
||||
EGLAPI EGLBoolean EGLAPIENTRY eglWaitClient(void);
|
||||
|
||||
EGLAPI EGLBoolean EGLAPIENTRY eglReleaseThread(void);
|
||||
EGLAPI EGLBoolean EGLAPIENTRY eglReleaseThread(void);
|
||||
|
||||
EGLAPI EGLSurface EGLAPIENTRY eglCreatePbufferFromClientBuffer(
|
||||
EGLDisplay dpy, EGLenum buftype, EGLClientBuffer buffer,
|
||||
EGLConfig config, const EGLint *attrib_list);
|
||||
EGLAPI EGLSurface EGLAPIENTRY eglCreatePbufferFromClientBuffer(
|
||||
EGLDisplay dpy, EGLenum buftype, EGLClientBuffer buffer,
|
||||
EGLConfig config, const EGLint *attrib_list);
|
||||
|
||||
EGLAPI EGLBoolean EGLAPIENTRY eglSurfaceAttrib(EGLDisplay dpy, EGLSurface surface,
|
||||
EGLint attribute, EGLint value);
|
||||
EGLAPI EGLBoolean EGLAPIENTRY eglBindTexImage(EGLDisplay dpy, EGLSurface surface, EGLint buffer);
|
||||
EGLAPI EGLBoolean EGLAPIENTRY eglReleaseTexImage(EGLDisplay dpy, EGLSurface surface, EGLint buffer);
|
||||
EGLAPI EGLBoolean EGLAPIENTRY eglSurfaceAttrib(EGLDisplay dpy, EGLSurface surface,
|
||||
EGLint attribute, EGLint value);
|
||||
EGLAPI EGLBoolean EGLAPIENTRY eglBindTexImage(EGLDisplay dpy, EGLSurface surface, EGLint buffer);
|
||||
EGLAPI EGLBoolean EGLAPIENTRY eglReleaseTexImage(EGLDisplay dpy, EGLSurface surface, EGLint buffer);
|
||||
|
||||
|
||||
EGLAPI EGLBoolean EGLAPIENTRY eglSwapInterval(EGLDisplay dpy, EGLint interval);
|
||||
EGLAPI EGLBoolean EGLAPIENTRY eglSwapInterval(EGLDisplay dpy, EGLint interval);
|
||||
|
||||
|
||||
EGLAPI EGLContext EGLAPIENTRY eglCreateContext(EGLDisplay dpy, EGLConfig config,
|
||||
EGLContext share_context,
|
||||
const EGLint *attrib_list);
|
||||
EGLAPI EGLBoolean EGLAPIENTRY eglDestroyContext(EGLDisplay dpy, EGLContext ctx);
|
||||
EGLAPI EGLBoolean EGLAPIENTRY eglMakeCurrent(EGLDisplay dpy, EGLSurface draw,
|
||||
EGLSurface read, EGLContext ctx);
|
||||
|
||||
EGLAPI EGLContext EGLAPIENTRY eglGetCurrentContext(void);
|
||||
EGLAPI EGLSurface EGLAPIENTRY eglGetCurrentSurface(EGLint readdraw);
|
||||
EGLAPI EGLDisplay EGLAPIENTRY eglGetCurrentDisplay(void);
|
||||
EGLAPI EGLBoolean EGLAPIENTRY eglQueryContext(EGLDisplay dpy, EGLContext ctx,
|
||||
EGLint attribute, EGLint *value);
|
||||
|
||||
EGLAPI EGLBoolean EGLAPIENTRY eglWaitGL(void);
|
||||
EGLAPI EGLBoolean EGLAPIENTRY eglWaitNative(EGLint engine);
|
||||
EGLAPI EGLBoolean EGLAPIENTRY eglSwapBuffers(EGLDisplay dpy, EGLSurface surface);
|
||||
EGLAPI EGLBoolean EGLAPIENTRY eglCopyBuffers(EGLDisplay dpy, EGLSurface surface,
|
||||
EGLNativePixmapType target);
|
||||
|
||||
/* This is a generic function pointer type, whose name indicates it must
|
||||
* be cast to the proper type *and calling convention* before use.
|
||||
*/
|
||||
typedef void (*__eglMustCastToProperFunctionPointerType)(void);
|
||||
|
||||
/* Now, define eglGetProcAddress using the generic function ptr. type */
|
||||
EGLAPI __eglMustCastToProperFunctionPointerType EGLAPIENTRY
|
||||
eglGetProcAddress(const char *procname);
|
||||
|
||||
EGLAPI EGLContext EGLAPIENTRY eglCreateContext(EGLDisplay dpy, EGLConfig config,
|
||||
EGLContext share_context,
|
||||
const EGLint *attrib_list);
|
||||
EGLAPI EGLBoolean EGLAPIENTRY eglDestroyContext(EGLDisplay dpy, EGLContext ctx);
|
||||
EGLAPI EGLBoolean EGLAPIENTRY eglMakeCurrent(EGLDisplay dpy, EGLSurface draw,
|
||||
EGLSurface read, EGLContext ctx);
|
||||
|
||||
EGLAPI EGLContext EGLAPIENTRY eglGetCurrentContext(void);
|
||||
EGLAPI EGLSurface EGLAPIENTRY eglGetCurrentSurface(EGLint readdraw);
|
||||
EGLAPI EGLDisplay EGLAPIENTRY eglGetCurrentDisplay(void);
|
||||
EGLAPI EGLBoolean EGLAPIENTRY eglQueryContext(EGLDisplay dpy, EGLContext ctx,
|
||||
EGLint attribute, EGLint *value);
|
||||
|
||||
EGLAPI EGLBoolean EGLAPIENTRY eglWaitGL(void);
|
||||
EGLAPI EGLBoolean EGLAPIENTRY eglWaitNative(EGLint engine);
|
||||
EGLAPI EGLBoolean EGLAPIENTRY eglSwapBuffers(EGLDisplay dpy, EGLSurface surface);
|
||||
EGLAPI EGLBoolean EGLAPIENTRY eglCopyBuffers(EGLDisplay dpy, EGLSurface surface,
|
||||
EGLNativePixmapType target);
|
||||
|
||||
/* This is a generic function pointer type, whose name indicates it must
|
||||
* be cast to the proper type *and calling convention* before use.
|
||||
*/
|
||||
typedef void (*__eglMustCastToProperFunctionPointerType)(void);
|
||||
|
||||
/* Now, define eglGetProcAddress using the generic function ptr. type */
|
||||
EGLAPI __eglMustCastToProperFunctionPointerType EGLAPIENTRY
|
||||
eglGetProcAddress(const char *procname);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __egl_h_ */
|
||||
#endif /* __egl_h_ */
|
||||
+590
-268
@@ -5,331 +5,653 @@
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*
|
||||
** Copyright (c) 2007-2010 The Khronos Group Inc.
|
||||
**
|
||||
** Permission is hereby granted, free of charge, to any person obtaining a
|
||||
** copy of this software and/or associated documentation files (the
|
||||
** "Materials"), to deal in the Materials without restriction, including
|
||||
** without limitation the rights to use, copy, modify, merge, publish,
|
||||
** distribute, sublicense, and/or sell copies of the Materials, and to
|
||||
** permit persons to whom the Materials are 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 Materials.
|
||||
**
|
||||
** THE MATERIALS ARE 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
|
||||
** MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
|
||||
*/
|
||||
/*
|
||||
** Copyright (c) 2013 The Khronos Group Inc.
|
||||
**
|
||||
** Permission is hereby granted, free of charge, to any person obtaining a
|
||||
** copy of this software and/or associated documentation files (the
|
||||
** "Materials"), to deal in the Materials without restriction, including
|
||||
** without limitation the rights to use, copy, modify, merge, publish,
|
||||
** distribute, sublicense, and/or sell copies of the Materials, and to
|
||||
** permit persons to whom the Materials are 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 Materials.
|
||||
**
|
||||
** THE MATERIALS ARE 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
|
||||
** MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
|
||||
*/
|
||||
/*
|
||||
** This header is generated from the Khronos OpenGL / OpenGL ES XML
|
||||
** API Registry. The current version of the Registry, generator scripts
|
||||
** used to make the header, and the header can be found at
|
||||
** http://www.opengl.org/registry/
|
||||
**
|
||||
** Khronos $Revision: 24902 $ on $Date: 2014-01-20 15:18:48 -0800 (Mon, 20 Jan 2014) $
|
||||
*/
|
||||
|
||||
#include <EGL/eglplatform.h>
|
||||
|
||||
/*************************************************************/
|
||||
#define EGL_EGLEXT_VERSION 20140120
|
||||
|
||||
/* Header file version number */
|
||||
/* Current version at http://www.khronos.org/registry/egl/ */
|
||||
/* $Revision: 15052 $ on $Date: 2011-07-06 17:43:46 -0700 (Wed, 06 Jul 2011) $ */
|
||||
#define EGL_EGLEXT_VERSION 10
|
||||
/* Generated C header for:
|
||||
* API: egl
|
||||
* Versions considered: .*
|
||||
* Versions emitted: _nomatch_^
|
||||
* Default extensions included: egl
|
||||
* Additional extensions included: _nomatch_^
|
||||
* Extensions removed: _nomatch_^
|
||||
*/
|
||||
|
||||
#ifndef EGL_KHR_cl_event
|
||||
#define EGL_KHR_cl_event 1
|
||||
#define EGL_CL_EVENT_HANDLE_KHR 0x309C
|
||||
#define EGL_SYNC_CL_EVENT_KHR 0x30FE
|
||||
#define EGL_SYNC_CL_EVENT_COMPLETE_KHR 0x30FF
|
||||
#endif /* EGL_KHR_cl_event */
|
||||
|
||||
#ifndef EGL_KHR_cl_event2
|
||||
#define EGL_KHR_cl_event2 1
|
||||
typedef void *EGLSyncKHR;
|
||||
typedef intptr_t EGLAttribKHR;
|
||||
typedef EGLSyncKHR (EGLAPIENTRYP PFNEGLCREATESYNC64KHRPROC) (EGLDisplay dpy, EGLenum type, const EGLAttribKHR *attrib_list);
|
||||
#ifdef EGL_EGLEXT_PROTOTYPES
|
||||
EGLAPI EGLSyncKHR EGLAPIENTRY eglCreateSync64KHR (EGLDisplay dpy, EGLenum type, const EGLAttribKHR *attrib_list);
|
||||
#endif
|
||||
#endif /* EGL_KHR_cl_event2 */
|
||||
|
||||
#ifndef EGL_KHR_client_get_all_proc_addresses
|
||||
#define EGL_KHR_client_get_all_proc_addresses 1
|
||||
#endif /* EGL_KHR_client_get_all_proc_addresses */
|
||||
|
||||
#ifndef EGL_KHR_config_attribs
|
||||
#define EGL_KHR_config_attribs 1
|
||||
#define EGL_CONFORMANT_KHR 0x3042 /* EGLConfig attribute */
|
||||
#define EGL_VG_COLORSPACE_LINEAR_BIT_KHR 0x0020 /* EGL_SURFACE_TYPE bitfield */
|
||||
#define EGL_VG_ALPHA_FORMAT_PRE_BIT_KHR 0x0040 /* EGL_SURFACE_TYPE bitfield */
|
||||
#endif
|
||||
#define EGL_CONFORMANT_KHR 0x3042
|
||||
#define EGL_VG_COLORSPACE_LINEAR_BIT_KHR 0x0020
|
||||
#define EGL_VG_ALPHA_FORMAT_PRE_BIT_KHR 0x0040
|
||||
#endif /* EGL_KHR_config_attribs */
|
||||
|
||||
#ifndef EGL_KHR_lock_surface
|
||||
#define EGL_KHR_lock_surface 1
|
||||
#define EGL_READ_SURFACE_BIT_KHR 0x0001 /* EGL_LOCK_USAGE_HINT_KHR bitfield */
|
||||
#define EGL_WRITE_SURFACE_BIT_KHR 0x0002 /* EGL_LOCK_USAGE_HINT_KHR bitfield */
|
||||
#define EGL_LOCK_SURFACE_BIT_KHR 0x0080 /* EGL_SURFACE_TYPE bitfield */
|
||||
#define EGL_OPTIMAL_FORMAT_BIT_KHR 0x0100 /* EGL_SURFACE_TYPE bitfield */
|
||||
#define EGL_MATCH_FORMAT_KHR 0x3043 /* EGLConfig attribute */
|
||||
#define EGL_FORMAT_RGB_565_EXACT_KHR 0x30C0 /* EGL_MATCH_FORMAT_KHR value */
|
||||
#define EGL_FORMAT_RGB_565_KHR 0x30C1 /* EGL_MATCH_FORMAT_KHR value */
|
||||
#define EGL_FORMAT_RGBA_8888_EXACT_KHR 0x30C2 /* EGL_MATCH_FORMAT_KHR value */
|
||||
#define EGL_FORMAT_RGBA_8888_KHR 0x30C3 /* EGL_MATCH_FORMAT_KHR value */
|
||||
#define EGL_MAP_PRESERVE_PIXELS_KHR 0x30C4 /* eglLockSurfaceKHR attribute */
|
||||
#define EGL_LOCK_USAGE_HINT_KHR 0x30C5 /* eglLockSurfaceKHR attribute */
|
||||
#define EGL_BITMAP_POINTER_KHR 0x30C6 /* eglQuerySurface attribute */
|
||||
#define EGL_BITMAP_PITCH_KHR 0x30C7 /* eglQuerySurface attribute */
|
||||
#define EGL_BITMAP_ORIGIN_KHR 0x30C8 /* eglQuerySurface attribute */
|
||||
#define EGL_BITMAP_PIXEL_RED_OFFSET_KHR 0x30C9 /* eglQuerySurface attribute */
|
||||
#define EGL_BITMAP_PIXEL_GREEN_OFFSET_KHR 0x30CA /* eglQuerySurface attribute */
|
||||
#define EGL_BITMAP_PIXEL_BLUE_OFFSET_KHR 0x30CB /* eglQuerySurface attribute */
|
||||
#define EGL_BITMAP_PIXEL_ALPHA_OFFSET_KHR 0x30CC /* eglQuerySurface attribute */
|
||||
#define EGL_BITMAP_PIXEL_LUMINANCE_OFFSET_KHR 0x30CD /* eglQuerySurface attribute */
|
||||
#define EGL_LOWER_LEFT_KHR 0x30CE /* EGL_BITMAP_ORIGIN_KHR value */
|
||||
#define EGL_UPPER_LEFT_KHR 0x30CF /* EGL_BITMAP_ORIGIN_KHR value */
|
||||
#ifdef EGL_EGLEXT_PROTOTYPES
|
||||
EGLAPI EGLBoolean EGLAPIENTRY eglLockSurfaceKHR (EGLDisplay display, EGLSurface surface, const EGLint *attrib_list);
|
||||
EGLAPI EGLBoolean EGLAPIENTRY eglUnlockSurfaceKHR (EGLDisplay display, EGLSurface surface);
|
||||
#endif /* EGL_EGLEXT_PROTOTYPES */
|
||||
typedef EGLBoolean (EGLAPIENTRYP PFNEGLLOCKSURFACEKHRPROC) (EGLDisplay display, EGLSurface surface, const EGLint *attrib_list);
|
||||
typedef EGLBoolean (EGLAPIENTRYP PFNEGLUNLOCKSURFACEKHRPROC) (EGLDisplay display, EGLSurface surface);
|
||||
#endif
|
||||
#ifndef EGL_KHR_create_context
|
||||
#define EGL_KHR_create_context 1
|
||||
#define EGL_CONTEXT_MAJOR_VERSION_KHR 0x3098
|
||||
#define EGL_CONTEXT_MINOR_VERSION_KHR 0x30FB
|
||||
#define EGL_CONTEXT_FLAGS_KHR 0x30FC
|
||||
#define EGL_CONTEXT_OPENGL_PROFILE_MASK_KHR 0x30FD
|
||||
#define EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_KHR 0x31BD
|
||||
#define EGL_NO_RESET_NOTIFICATION_KHR 0x31BE
|
||||
#define EGL_LOSE_CONTEXT_ON_RESET_KHR 0x31BF
|
||||
#define EGL_CONTEXT_OPENGL_DEBUG_BIT_KHR 0x00000001
|
||||
#define EGL_CONTEXT_OPENGL_FORWARD_COMPATIBLE_BIT_KHR 0x00000002
|
||||
#define EGL_CONTEXT_OPENGL_ROBUST_ACCESS_BIT_KHR 0x00000004
|
||||
#define EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT_KHR 0x00000001
|
||||
#define EGL_CONTEXT_OPENGL_COMPATIBILITY_PROFILE_BIT_KHR 0x00000002
|
||||
#define EGL_OPENGL_ES3_BIT_KHR 0x00000040
|
||||
#endif /* EGL_KHR_create_context */
|
||||
|
||||
#ifndef EGL_KHR_image
|
||||
#define EGL_KHR_image 1
|
||||
#define EGL_NATIVE_PIXMAP_KHR 0x30B0 /* eglCreateImageKHR target */
|
||||
typedef void *EGLImageKHR;
|
||||
#define EGL_NO_IMAGE_KHR ((EGLImageKHR)0)
|
||||
#ifdef EGL_EGLEXT_PROTOTYPES
|
||||
EGLAPI EGLImageKHR EGLAPIENTRY eglCreateImageKHR (EGLDisplay dpy, EGLContext ctx, EGLenum target, EGLClientBuffer buffer, const EGLint *attrib_list);
|
||||
EGLAPI EGLBoolean EGLAPIENTRY eglDestroyImageKHR (EGLDisplay dpy, EGLImageKHR image);
|
||||
#endif /* EGL_EGLEXT_PROTOTYPES */
|
||||
typedef EGLImageKHR (EGLAPIENTRYP PFNEGLCREATEIMAGEKHRPROC) (EGLDisplay dpy, EGLContext ctx, EGLenum target, EGLClientBuffer buffer, const EGLint *attrib_list);
|
||||
typedef EGLBoolean (EGLAPIENTRYP PFNEGLDESTROYIMAGEKHRPROC) (EGLDisplay dpy, EGLImageKHR image);
|
||||
#endif
|
||||
#ifndef EGL_KHR_fence_sync
|
||||
#define EGL_KHR_fence_sync 1
|
||||
#ifdef KHRONOS_SUPPORT_INT64
|
||||
#define EGL_SYNC_PRIOR_COMMANDS_COMPLETE_KHR 0x30F0
|
||||
#define EGL_SYNC_CONDITION_KHR 0x30F8
|
||||
#define EGL_SYNC_FENCE_KHR 0x30F9
|
||||
#endif /* KHRONOS_SUPPORT_INT64 */
|
||||
#endif /* EGL_KHR_fence_sync */
|
||||
|
||||
#ifndef EGL_KHR_vg_parent_image
|
||||
#define EGL_KHR_vg_parent_image 1
|
||||
#define EGL_VG_PARENT_IMAGE_KHR 0x30BA /* eglCreateImageKHR target */
|
||||
#endif
|
||||
#ifndef EGL_KHR_get_all_proc_addresses
|
||||
#define EGL_KHR_get_all_proc_addresses 1
|
||||
#endif /* EGL_KHR_get_all_proc_addresses */
|
||||
|
||||
#ifndef EGL_KHR_gl_texture_2D_image
|
||||
#define EGL_KHR_gl_texture_2D_image 1
|
||||
#define EGL_GL_TEXTURE_2D_KHR 0x30B1 /* eglCreateImageKHR target */
|
||||
#define EGL_GL_TEXTURE_LEVEL_KHR 0x30BC /* eglCreateImageKHR attribute */
|
||||
#endif
|
||||
|
||||
#ifndef EGL_KHR_gl_texture_cubemap_image
|
||||
#define EGL_KHR_gl_texture_cubemap_image 1
|
||||
#define EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_X_KHR 0x30B3 /* eglCreateImageKHR target */
|
||||
#define EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_X_KHR 0x30B4 /* eglCreateImageKHR target */
|
||||
#define EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_Y_KHR 0x30B5 /* eglCreateImageKHR target */
|
||||
#define EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_KHR 0x30B6 /* eglCreateImageKHR target */
|
||||
#define EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_Z_KHR 0x30B7 /* eglCreateImageKHR target */
|
||||
#define EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_KHR 0x30B8 /* eglCreateImageKHR target */
|
||||
#endif
|
||||
|
||||
#ifndef EGL_KHR_gl_texture_3D_image
|
||||
#define EGL_KHR_gl_texture_3D_image 1
|
||||
#define EGL_GL_TEXTURE_3D_KHR 0x30B2 /* eglCreateImageKHR target */
|
||||
#define EGL_GL_TEXTURE_ZOFFSET_KHR 0x30BD /* eglCreateImageKHR attribute */
|
||||
#endif
|
||||
#ifndef EGL_KHR_gl_colorspace
|
||||
#define EGL_KHR_gl_colorspace 1
|
||||
#define EGL_GL_COLORSPACE_KHR 0x309D
|
||||
#define EGL_GL_COLORSPACE_SRGB_KHR 0x3089
|
||||
#define EGL_GL_COLORSPACE_LINEAR_KHR 0x308A
|
||||
#endif /* EGL_KHR_gl_colorspace */
|
||||
|
||||
#ifndef EGL_KHR_gl_renderbuffer_image
|
||||
#define EGL_KHR_gl_renderbuffer_image 1
|
||||
#define EGL_GL_RENDERBUFFER_KHR 0x30B9 /* eglCreateImageKHR target */
|
||||
#endif
|
||||
#define EGL_GL_RENDERBUFFER_KHR 0x30B9
|
||||
#endif /* EGL_KHR_gl_renderbuffer_image */
|
||||
|
||||
#if KHRONOS_SUPPORT_INT64 /* EGLTimeKHR requires 64-bit uint support */
|
||||
#ifndef EGL_KHR_reusable_sync
|
||||
#define EGL_KHR_reusable_sync 1
|
||||
#ifndef EGL_KHR_gl_texture_2D_image
|
||||
#define EGL_KHR_gl_texture_2D_image 1
|
||||
#define EGL_GL_TEXTURE_2D_KHR 0x30B1
|
||||
#define EGL_GL_TEXTURE_LEVEL_KHR 0x30BC
|
||||
#endif /* EGL_KHR_gl_texture_2D_image */
|
||||
|
||||
typedef void* EGLSyncKHR;
|
||||
typedef khronos_utime_nanoseconds_t EGLTimeKHR;
|
||||
#ifndef EGL_KHR_gl_texture_3D_image
|
||||
#define EGL_KHR_gl_texture_3D_image 1
|
||||
#define EGL_GL_TEXTURE_3D_KHR 0x30B2
|
||||
#define EGL_GL_TEXTURE_ZOFFSET_KHR 0x30BD
|
||||
#endif /* EGL_KHR_gl_texture_3D_image */
|
||||
|
||||
#define EGL_SYNC_STATUS_KHR 0x30F1
|
||||
#define EGL_SIGNALED_KHR 0x30F2
|
||||
#define EGL_UNSIGNALED_KHR 0x30F3
|
||||
#define EGL_TIMEOUT_EXPIRED_KHR 0x30F5
|
||||
#define EGL_CONDITION_SATISFIED_KHR 0x30F6
|
||||
#define EGL_SYNC_TYPE_KHR 0x30F7
|
||||
#define EGL_SYNC_REUSABLE_KHR 0x30FA
|
||||
#define EGL_SYNC_FLUSH_COMMANDS_BIT_KHR 0x0001 /* eglClientWaitSyncKHR <flags> bitfield */
|
||||
#define EGL_FOREVER_KHR 0xFFFFFFFFFFFFFFFFull
|
||||
#define EGL_NO_SYNC_KHR ((EGLSyncKHR)0)
|
||||
#ifndef EGL_KHR_gl_texture_cubemap_image
|
||||
#define EGL_KHR_gl_texture_cubemap_image 1
|
||||
#define EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_X_KHR 0x30B3
|
||||
#define EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_X_KHR 0x30B4
|
||||
#define EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_Y_KHR 0x30B5
|
||||
#define EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_KHR 0x30B6
|
||||
#define EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_Z_KHR 0x30B7
|
||||
#define EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_KHR 0x30B8
|
||||
#endif /* EGL_KHR_gl_texture_cubemap_image */
|
||||
|
||||
#ifndef EGL_KHR_image
|
||||
#define EGL_KHR_image 1
|
||||
typedef void *EGLImageKHR;
|
||||
#define EGL_NATIVE_PIXMAP_KHR 0x30B0
|
||||
#define EGL_NO_IMAGE_KHR ((EGLImageKHR)0)
|
||||
typedef EGLImageKHR (EGLAPIENTRYP PFNEGLCREATEIMAGEKHRPROC) (EGLDisplay dpy, EGLContext ctx, EGLenum target, EGLClientBuffer buffer, const EGLint *attrib_list);
|
||||
typedef EGLBoolean (EGLAPIENTRYP PFNEGLDESTROYIMAGEKHRPROC) (EGLDisplay dpy, EGLImageKHR image);
|
||||
#ifdef EGL_EGLEXT_PROTOTYPES
|
||||
EGLAPI EGLSyncKHR EGLAPIENTRY eglCreateSyncKHR(EGLDisplay dpy, EGLenum type, const EGLint *attrib_list);
|
||||
EGLAPI EGLBoolean EGLAPIENTRY eglDestroySyncKHR(EGLDisplay dpy, EGLSyncKHR sync);
|
||||
EGLAPI EGLint EGLAPIENTRY eglClientWaitSyncKHR(EGLDisplay dpy, EGLSyncKHR sync, EGLint flags, EGLTimeKHR timeout);
|
||||
EGLAPI EGLBoolean EGLAPIENTRY eglSignalSyncKHR(EGLDisplay dpy, EGLSyncKHR sync, EGLenum mode);
|
||||
EGLAPI EGLBoolean EGLAPIENTRY eglGetSyncAttribKHR(EGLDisplay dpy, EGLSyncKHR sync, EGLint attribute, EGLint *value);
|
||||
#endif /* EGL_EGLEXT_PROTOTYPES */
|
||||
typedef EGLSyncKHR (EGLAPIENTRYP PFNEGLCREATESYNCKHRPROC) (EGLDisplay dpy, EGLenum type, const EGLint *attrib_list);
|
||||
typedef EGLBoolean (EGLAPIENTRYP PFNEGLDESTROYSYNCKHRPROC) (EGLDisplay dpy, EGLSyncKHR sync);
|
||||
typedef EGLint (EGLAPIENTRYP PFNEGLCLIENTWAITSYNCKHRPROC) (EGLDisplay dpy, EGLSyncKHR sync, EGLint flags, EGLTimeKHR timeout);
|
||||
typedef EGLBoolean (EGLAPIENTRYP PFNEGLSIGNALSYNCKHRPROC) (EGLDisplay dpy, EGLSyncKHR sync, EGLenum mode);
|
||||
typedef EGLBoolean (EGLAPIENTRYP PFNEGLGETSYNCATTRIBKHRPROC) (EGLDisplay dpy, EGLSyncKHR sync, EGLint attribute, EGLint *value);
|
||||
#endif
|
||||
EGLAPI EGLImageKHR EGLAPIENTRY eglCreateImageKHR (EGLDisplay dpy, EGLContext ctx, EGLenum target, EGLClientBuffer buffer, const EGLint *attrib_list);
|
||||
EGLAPI EGLBoolean EGLAPIENTRY eglDestroyImageKHR (EGLDisplay dpy, EGLImageKHR image);
|
||||
#endif
|
||||
#endif /* EGL_KHR_image */
|
||||
|
||||
#ifndef EGL_KHR_image_base
|
||||
#define EGL_KHR_image_base 1
|
||||
/* Most interfaces defined by EGL_KHR_image_pixmap above */
|
||||
#define EGL_IMAGE_PRESERVED_KHR 0x30D2 /* eglCreateImageKHR attribute */
|
||||
#endif
|
||||
#define EGL_IMAGE_PRESERVED_KHR 0x30D2
|
||||
#endif /* EGL_KHR_image_base */
|
||||
|
||||
#ifndef EGL_KHR_image_pixmap
|
||||
#define EGL_KHR_image_pixmap 1
|
||||
/* Interfaces defined by EGL_KHR_image above */
|
||||
#endif
|
||||
#endif /* EGL_KHR_image_pixmap */
|
||||
|
||||
#ifndef EGL_IMG_context_priority
|
||||
#define EGL_IMG_context_priority 1
|
||||
#define EGL_CONTEXT_PRIORITY_LEVEL_IMG 0x3100
|
||||
#define EGL_CONTEXT_PRIORITY_HIGH_IMG 0x3101
|
||||
#define EGL_CONTEXT_PRIORITY_MEDIUM_IMG 0x3102
|
||||
#define EGL_CONTEXT_PRIORITY_LOW_IMG 0x3103
|
||||
#ifndef EGL_KHR_lock_surface
|
||||
#define EGL_KHR_lock_surface 1
|
||||
#define EGL_READ_SURFACE_BIT_KHR 0x0001
|
||||
#define EGL_WRITE_SURFACE_BIT_KHR 0x0002
|
||||
#define EGL_LOCK_SURFACE_BIT_KHR 0x0080
|
||||
#define EGL_OPTIMAL_FORMAT_BIT_KHR 0x0100
|
||||
#define EGL_MATCH_FORMAT_KHR 0x3043
|
||||
#define EGL_FORMAT_RGB_565_EXACT_KHR 0x30C0
|
||||
#define EGL_FORMAT_RGB_565_KHR 0x30C1
|
||||
#define EGL_FORMAT_RGBA_8888_EXACT_KHR 0x30C2
|
||||
#define EGL_FORMAT_RGBA_8888_KHR 0x30C3
|
||||
#define EGL_MAP_PRESERVE_PIXELS_KHR 0x30C4
|
||||
#define EGL_LOCK_USAGE_HINT_KHR 0x30C5
|
||||
#define EGL_BITMAP_POINTER_KHR 0x30C6
|
||||
#define EGL_BITMAP_PITCH_KHR 0x30C7
|
||||
#define EGL_BITMAP_ORIGIN_KHR 0x30C8
|
||||
#define EGL_BITMAP_PIXEL_RED_OFFSET_KHR 0x30C9
|
||||
#define EGL_BITMAP_PIXEL_GREEN_OFFSET_KHR 0x30CA
|
||||
#define EGL_BITMAP_PIXEL_BLUE_OFFSET_KHR 0x30CB
|
||||
#define EGL_BITMAP_PIXEL_ALPHA_OFFSET_KHR 0x30CC
|
||||
#define EGL_BITMAP_PIXEL_LUMINANCE_OFFSET_KHR 0x30CD
|
||||
#define EGL_LOWER_LEFT_KHR 0x30CE
|
||||
#define EGL_UPPER_LEFT_KHR 0x30CF
|
||||
typedef EGLBoolean (EGLAPIENTRYP PFNEGLLOCKSURFACEKHRPROC) (EGLDisplay dpy, EGLSurface surface, const EGLint *attrib_list);
|
||||
typedef EGLBoolean (EGLAPIENTRYP PFNEGLUNLOCKSURFACEKHRPROC) (EGLDisplay dpy, EGLSurface surface);
|
||||
#ifdef EGL_EGLEXT_PROTOTYPES
|
||||
EGLAPI EGLBoolean EGLAPIENTRY eglLockSurfaceKHR (EGLDisplay dpy, EGLSurface surface, const EGLint *attrib_list);
|
||||
EGLAPI EGLBoolean EGLAPIENTRY eglUnlockSurfaceKHR (EGLDisplay dpy, EGLSurface surface);
|
||||
#endif
|
||||
#endif /* EGL_KHR_lock_surface */
|
||||
|
||||
#ifndef EGL_KHR_lock_surface2
|
||||
#define EGL_KHR_lock_surface2 1
|
||||
#define EGL_BITMAP_PIXEL_SIZE_KHR 0x3110
|
||||
#endif
|
||||
#define EGL_BITMAP_PIXEL_SIZE_KHR 0x3110
|
||||
#endif /* EGL_KHR_lock_surface2 */
|
||||
|
||||
#ifndef EGL_NV_coverage_sample
|
||||
#define EGL_NV_coverage_sample 1
|
||||
#define EGL_COVERAGE_BUFFERS_NV 0x30E0
|
||||
#define EGL_COVERAGE_SAMPLES_NV 0x30E1
|
||||
#endif
|
||||
|
||||
#ifndef EGL_NV_depth_nonlinear
|
||||
#define EGL_NV_depth_nonlinear 1
|
||||
#define EGL_DEPTH_ENCODING_NV 0x30E2
|
||||
#define EGL_DEPTH_ENCODING_NONE_NV 0
|
||||
#define EGL_DEPTH_ENCODING_NONLINEAR_NV 0x30E3
|
||||
#endif
|
||||
|
||||
#if KHRONOS_SUPPORT_INT64 /* EGLTimeNV requires 64-bit uint support */
|
||||
#ifndef EGL_NV_sync
|
||||
#define EGL_NV_sync 1
|
||||
#define EGL_SYNC_PRIOR_COMMANDS_COMPLETE_NV 0x30E6
|
||||
#define EGL_SYNC_STATUS_NV 0x30E7
|
||||
#define EGL_SIGNALED_NV 0x30E8
|
||||
#define EGL_UNSIGNALED_NV 0x30E9
|
||||
#define EGL_SYNC_FLUSH_COMMANDS_BIT_NV 0x0001
|
||||
#define EGL_FOREVER_NV 0xFFFFFFFFFFFFFFFFull
|
||||
#define EGL_ALREADY_SIGNALED_NV 0x30EA
|
||||
#define EGL_TIMEOUT_EXPIRED_NV 0x30EB
|
||||
#define EGL_CONDITION_SATISFIED_NV 0x30EC
|
||||
#define EGL_SYNC_TYPE_NV 0x30ED
|
||||
#define EGL_SYNC_CONDITION_NV 0x30EE
|
||||
#define EGL_SYNC_FENCE_NV 0x30EF
|
||||
#define EGL_NO_SYNC_NV ((EGLSyncNV)0)
|
||||
typedef void* EGLSyncNV;
|
||||
typedef khronos_utime_nanoseconds_t EGLTimeNV;
|
||||
#ifndef EGL_KHR_lock_surface3
|
||||
#define EGL_KHR_lock_surface3 1
|
||||
typedef EGLBoolean (EGLAPIENTRYP PFNEGLQUERYSURFACE64KHRPROC) (EGLDisplay dpy, EGLSurface surface, EGLint attribute, EGLAttribKHR *value);
|
||||
#ifdef EGL_EGLEXT_PROTOTYPES
|
||||
EGLSyncNV eglCreateFenceSyncNV (EGLDisplay dpy, EGLenum condition, const EGLint *attrib_list);
|
||||
EGLBoolean eglDestroySyncNV (EGLSyncNV sync);
|
||||
EGLBoolean eglFenceNV (EGLSyncNV sync);
|
||||
EGLint eglClientWaitSyncNV (EGLSyncNV sync, EGLint flags, EGLTimeNV timeout);
|
||||
EGLBoolean eglSignalSyncNV (EGLSyncNV sync, EGLenum mode);
|
||||
EGLBoolean eglGetSyncAttribNV (EGLSyncNV sync, EGLint attribute, EGLint *value);
|
||||
#endif /* EGL_EGLEXT_PROTOTYPES */
|
||||
typedef EGLSyncNV (EGLAPIENTRYP PFNEGLCREATEFENCESYNCNVPROC) (EGLDisplay dpy, EGLenum condition, const EGLint *attrib_list);
|
||||
typedef EGLBoolean (EGLAPIENTRYP PFNEGLDESTROYSYNCNVPROC) (EGLSyncNV sync);
|
||||
typedef EGLBoolean (EGLAPIENTRYP PFNEGLFENCENVPROC) (EGLSyncNV sync);
|
||||
typedef EGLint (EGLAPIENTRYP PFNEGLCLIENTWAITSYNCNVPROC) (EGLSyncNV sync, EGLint flags, EGLTimeNV timeout);
|
||||
typedef EGLBoolean (EGLAPIENTRYP PFNEGLSIGNALSYNCNVPROC) (EGLSyncNV sync, EGLenum mode);
|
||||
typedef EGLBoolean (EGLAPIENTRYP PFNEGLGETSYNCATTRIBNVPROC) (EGLSyncNV sync, EGLint attribute, EGLint *value);
|
||||
#endif
|
||||
EGLAPI EGLBoolean EGLAPIENTRY eglQuerySurface64KHR (EGLDisplay dpy, EGLSurface surface, EGLint attribute, EGLAttribKHR *value);
|
||||
#endif
|
||||
#endif /* EGL_KHR_lock_surface3 */
|
||||
|
||||
#if KHRONOS_SUPPORT_INT64 /* Dependent on EGL_KHR_reusable_sync which requires 64-bit uint support */
|
||||
#ifndef EGL_KHR_fence_sync
|
||||
#define EGL_KHR_fence_sync 1
|
||||
/* Reuses most tokens and entry points from EGL_KHR_reusable_sync */
|
||||
#define EGL_SYNC_PRIOR_COMMANDS_COMPLETE_KHR 0x30F0
|
||||
#define EGL_SYNC_CONDITION_KHR 0x30F8
|
||||
#define EGL_SYNC_FENCE_KHR 0x30F9
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef EGL_HI_clientpixmap
|
||||
#define EGL_HI_clientpixmap 1
|
||||
|
||||
/* Surface Attribute */
|
||||
#define EGL_CLIENT_PIXMAP_POINTER_HI 0x8F74
|
||||
/*
|
||||
* Structure representing a client pixmap
|
||||
* (pixmap's data is in client-space memory).
|
||||
*/
|
||||
struct EGLClientPixmapHI
|
||||
{
|
||||
void* pData;
|
||||
EGLint iWidth;
|
||||
EGLint iHeight;
|
||||
EGLint iStride;
|
||||
};
|
||||
|
||||
#ifndef EGL_KHR_reusable_sync
|
||||
#define EGL_KHR_reusable_sync 1
|
||||
typedef khronos_utime_nanoseconds_t EGLTimeKHR;
|
||||
#ifdef KHRONOS_SUPPORT_INT64
|
||||
#define EGL_SYNC_STATUS_KHR 0x30F1
|
||||
#define EGL_SIGNALED_KHR 0x30F2
|
||||
#define EGL_UNSIGNALED_KHR 0x30F3
|
||||
#define EGL_TIMEOUT_EXPIRED_KHR 0x30F5
|
||||
#define EGL_CONDITION_SATISFIED_KHR 0x30F6
|
||||
#define EGL_SYNC_TYPE_KHR 0x30F7
|
||||
#define EGL_SYNC_REUSABLE_KHR 0x30FA
|
||||
#define EGL_SYNC_FLUSH_COMMANDS_BIT_KHR 0x0001
|
||||
#define EGL_FOREVER_KHR 0xFFFFFFFFFFFFFFFFull
|
||||
#define EGL_NO_SYNC_KHR ((EGLSyncKHR)0)
|
||||
typedef EGLSyncKHR (EGLAPIENTRYP PFNEGLCREATESYNCKHRPROC) (EGLDisplay dpy, EGLenum type, const EGLint *attrib_list);
|
||||
typedef EGLBoolean (EGLAPIENTRYP PFNEGLDESTROYSYNCKHRPROC) (EGLDisplay dpy, EGLSyncKHR sync);
|
||||
typedef EGLint (EGLAPIENTRYP PFNEGLCLIENTWAITSYNCKHRPROC) (EGLDisplay dpy, EGLSyncKHR sync, EGLint flags, EGLTimeKHR timeout);
|
||||
typedef EGLBoolean (EGLAPIENTRYP PFNEGLSIGNALSYNCKHRPROC) (EGLDisplay dpy, EGLSyncKHR sync, EGLenum mode);
|
||||
typedef EGLBoolean (EGLAPIENTRYP PFNEGLGETSYNCATTRIBKHRPROC) (EGLDisplay dpy, EGLSyncKHR sync, EGLint attribute, EGLint *value);
|
||||
#ifdef EGL_EGLEXT_PROTOTYPES
|
||||
EGLAPI EGLSurface EGLAPIENTRY eglCreatePixmapSurfaceHI(EGLDisplay dpy, EGLConfig config, struct EGLClientPixmapHI* pixmap);
|
||||
#endif /* EGL_EGLEXT_PROTOTYPES */
|
||||
typedef EGLSurface (EGLAPIENTRYP PFNEGLCREATEPIXMAPSURFACEHIPROC) (EGLDisplay dpy, EGLConfig config, struct EGLClientPixmapHI* pixmap);
|
||||
#endif /* EGL_HI_clientpixmap */
|
||||
|
||||
#ifndef EGL_HI_colorformats
|
||||
#define EGL_HI_colorformats 1
|
||||
/* Config Attribute */
|
||||
#define EGL_COLOR_FORMAT_HI 0x8F70
|
||||
/* Color Formats */
|
||||
#define EGL_COLOR_RGB_HI 0x8F71
|
||||
#define EGL_COLOR_RGBA_HI 0x8F72
|
||||
#define EGL_COLOR_ARGB_HI 0x8F73
|
||||
#endif /* EGL_HI_colorformats */
|
||||
|
||||
#ifndef EGL_MESA_drm_image
|
||||
#define EGL_MESA_drm_image 1
|
||||
#define EGL_DRM_BUFFER_FORMAT_MESA 0x31D0 /* CreateDRMImageMESA attribute */
|
||||
#define EGL_DRM_BUFFER_USE_MESA 0x31D1 /* CreateDRMImageMESA attribute */
|
||||
#define EGL_DRM_BUFFER_FORMAT_ARGB32_MESA 0x31D2 /* EGL_IMAGE_FORMAT_MESA attribute value */
|
||||
#define EGL_DRM_BUFFER_MESA 0x31D3 /* eglCreateImageKHR target */
|
||||
#define EGL_DRM_BUFFER_STRIDE_MESA 0x31D4
|
||||
#define EGL_DRM_BUFFER_USE_SCANOUT_MESA 0x00000001 /* EGL_DRM_BUFFER_USE_MESA bits */
|
||||
#define EGL_DRM_BUFFER_USE_SHARE_MESA 0x00000002 /* EGL_DRM_BUFFER_USE_MESA bits */
|
||||
#ifdef EGL_EGLEXT_PROTOTYPES
|
||||
EGLAPI EGLImageKHR EGLAPIENTRY eglCreateDRMImageMESA (EGLDisplay dpy, const EGLint *attrib_list);
|
||||
EGLAPI EGLBoolean EGLAPIENTRY eglExportDRMImageMESA (EGLDisplay dpy, EGLImageKHR image, EGLint *name, EGLint *handle, EGLint *stride);
|
||||
#endif /* EGL_EGLEXT_PROTOTYPES */
|
||||
typedef EGLImageKHR (EGLAPIENTRYP PFNEGLCREATEDRMIMAGEMESAPROC) (EGLDisplay dpy, const EGLint *attrib_list);
|
||||
typedef EGLBoolean (EGLAPIENTRYP PFNEGLEXPORTDRMIMAGEMESAPROC) (EGLDisplay dpy, EGLImageKHR image, EGLint *name, EGLint *handle, EGLint *stride);
|
||||
EGLAPI EGLSyncKHR EGLAPIENTRY eglCreateSyncKHR (EGLDisplay dpy, EGLenum type, const EGLint *attrib_list);
|
||||
EGLAPI EGLBoolean EGLAPIENTRY eglDestroySyncKHR (EGLDisplay dpy, EGLSyncKHR sync);
|
||||
EGLAPI EGLint EGLAPIENTRY eglClientWaitSyncKHR (EGLDisplay dpy, EGLSyncKHR sync, EGLint flags, EGLTimeKHR timeout);
|
||||
EGLAPI EGLBoolean EGLAPIENTRY eglSignalSyncKHR (EGLDisplay dpy, EGLSyncKHR sync, EGLenum mode);
|
||||
EGLAPI EGLBoolean EGLAPIENTRY eglGetSyncAttribKHR (EGLDisplay dpy, EGLSyncKHR sync, EGLint attribute, EGLint *value);
|
||||
#endif
|
||||
#endif /* KHRONOS_SUPPORT_INT64 */
|
||||
#endif /* EGL_KHR_reusable_sync */
|
||||
|
||||
#ifndef EGL_NV_post_sub_buffer
|
||||
#define EGL_NV_post_sub_buffer 1
|
||||
#define EGL_POST_SUB_BUFFER_SUPPORTED_NV 0x30BE
|
||||
#ifndef EGL_KHR_stream
|
||||
#define EGL_KHR_stream 1
|
||||
typedef void *EGLStreamKHR;
|
||||
typedef khronos_uint64_t EGLuint64KHR;
|
||||
#ifdef KHRONOS_SUPPORT_INT64
|
||||
#define EGL_NO_STREAM_KHR ((EGLStreamKHR)0)
|
||||
#define EGL_CONSUMER_LATENCY_USEC_KHR 0x3210
|
||||
#define EGL_PRODUCER_FRAME_KHR 0x3212
|
||||
#define EGL_CONSUMER_FRAME_KHR 0x3213
|
||||
#define EGL_STREAM_STATE_KHR 0x3214
|
||||
#define EGL_STREAM_STATE_CREATED_KHR 0x3215
|
||||
#define EGL_STREAM_STATE_CONNECTING_KHR 0x3216
|
||||
#define EGL_STREAM_STATE_EMPTY_KHR 0x3217
|
||||
#define EGL_STREAM_STATE_NEW_FRAME_AVAILABLE_KHR 0x3218
|
||||
#define EGL_STREAM_STATE_OLD_FRAME_AVAILABLE_KHR 0x3219
|
||||
#define EGL_STREAM_STATE_DISCONNECTED_KHR 0x321A
|
||||
#define EGL_BAD_STREAM_KHR 0x321B
|
||||
#define EGL_BAD_STATE_KHR 0x321C
|
||||
typedef EGLStreamKHR (EGLAPIENTRYP PFNEGLCREATESTREAMKHRPROC) (EGLDisplay dpy, const EGLint *attrib_list);
|
||||
typedef EGLBoolean (EGLAPIENTRYP PFNEGLDESTROYSTREAMKHRPROC) (EGLDisplay dpy, EGLStreamKHR stream);
|
||||
typedef EGLBoolean (EGLAPIENTRYP PFNEGLSTREAMATTRIBKHRPROC) (EGLDisplay dpy, EGLStreamKHR stream, EGLenum attribute, EGLint value);
|
||||
typedef EGLBoolean (EGLAPIENTRYP PFNEGLQUERYSTREAMKHRPROC) (EGLDisplay dpy, EGLStreamKHR stream, EGLenum attribute, EGLint *value);
|
||||
typedef EGLBoolean (EGLAPIENTRYP PFNEGLQUERYSTREAMU64KHRPROC) (EGLDisplay dpy, EGLStreamKHR stream, EGLenum attribute, EGLuint64KHR *value);
|
||||
#ifdef EGL_EGLEXT_PROTOTYPES
|
||||
EGLAPI EGLBoolean EGLAPIENTRY eglPostSubBufferNV (EGLDisplay dpy, EGLSurface surface, EGLint x, EGLint y, EGLint width, EGLint height);
|
||||
#endif /* EGL_EGLEXT_PROTOTYPES */
|
||||
typedef EGLBoolean (EGLAPIENTRYP PFNEGLPOSTSUBBUFFERNVPROC) (EGLDisplay dpy, EGLSurface surface, EGLint x, EGLint y, EGLint width, EGLint height);
|
||||
EGLAPI EGLStreamKHR EGLAPIENTRY eglCreateStreamKHR (EGLDisplay dpy, const EGLint *attrib_list);
|
||||
EGLAPI EGLBoolean EGLAPIENTRY eglDestroyStreamKHR (EGLDisplay dpy, EGLStreamKHR stream);
|
||||
EGLAPI EGLBoolean EGLAPIENTRY eglStreamAttribKHR (EGLDisplay dpy, EGLStreamKHR stream, EGLenum attribute, EGLint value);
|
||||
EGLAPI EGLBoolean EGLAPIENTRY eglQueryStreamKHR (EGLDisplay dpy, EGLStreamKHR stream, EGLenum attribute, EGLint *value);
|
||||
EGLAPI EGLBoolean EGLAPIENTRY eglQueryStreamu64KHR (EGLDisplay dpy, EGLStreamKHR stream, EGLenum attribute, EGLuint64KHR *value);
|
||||
#endif
|
||||
#endif /* KHRONOS_SUPPORT_INT64 */
|
||||
#endif /* EGL_KHR_stream */
|
||||
|
||||
#ifndef EGL_KHR_stream_consumer_gltexture
|
||||
#define EGL_KHR_stream_consumer_gltexture 1
|
||||
#ifdef EGL_KHR_stream
|
||||
#define EGL_CONSUMER_ACQUIRE_TIMEOUT_USEC_KHR 0x321E
|
||||
typedef EGLBoolean (EGLAPIENTRYP PFNEGLSTREAMCONSUMERGLTEXTUREEXTERNALKHRPROC) (EGLDisplay dpy, EGLStreamKHR stream);
|
||||
typedef EGLBoolean (EGLAPIENTRYP PFNEGLSTREAMCONSUMERACQUIREKHRPROC) (EGLDisplay dpy, EGLStreamKHR stream);
|
||||
typedef EGLBoolean (EGLAPIENTRYP PFNEGLSTREAMCONSUMERRELEASEKHRPROC) (EGLDisplay dpy, EGLStreamKHR stream);
|
||||
#ifdef EGL_EGLEXT_PROTOTYPES
|
||||
EGLAPI EGLBoolean EGLAPIENTRY eglStreamConsumerGLTextureExternalKHR (EGLDisplay dpy, EGLStreamKHR stream);
|
||||
EGLAPI EGLBoolean EGLAPIENTRY eglStreamConsumerAcquireKHR (EGLDisplay dpy, EGLStreamKHR stream);
|
||||
EGLAPI EGLBoolean EGLAPIENTRY eglStreamConsumerReleaseKHR (EGLDisplay dpy, EGLStreamKHR stream);
|
||||
#endif
|
||||
#endif /* EGL_KHR_stream */
|
||||
#endif /* EGL_KHR_stream_consumer_gltexture */
|
||||
|
||||
#ifndef EGL_KHR_stream_cross_process_fd
|
||||
#define EGL_KHR_stream_cross_process_fd 1
|
||||
typedef int EGLNativeFileDescriptorKHR;
|
||||
#ifdef EGL_KHR_stream
|
||||
#define EGL_NO_FILE_DESCRIPTOR_KHR ((EGLNativeFileDescriptorKHR)(-1))
|
||||
typedef EGLNativeFileDescriptorKHR (EGLAPIENTRYP PFNEGLGETSTREAMFILEDESCRIPTORKHRPROC) (EGLDisplay dpy, EGLStreamKHR stream);
|
||||
typedef EGLStreamKHR (EGLAPIENTRYP PFNEGLCREATESTREAMFROMFILEDESCRIPTORKHRPROC) (EGLDisplay dpy, EGLNativeFileDescriptorKHR file_descriptor);
|
||||
#ifdef EGL_EGLEXT_PROTOTYPES
|
||||
EGLAPI EGLNativeFileDescriptorKHR EGLAPIENTRY eglGetStreamFileDescriptorKHR (EGLDisplay dpy, EGLStreamKHR stream);
|
||||
EGLAPI EGLStreamKHR EGLAPIENTRY eglCreateStreamFromFileDescriptorKHR (EGLDisplay dpy, EGLNativeFileDescriptorKHR file_descriptor);
|
||||
#endif
|
||||
#endif /* EGL_KHR_stream */
|
||||
#endif /* EGL_KHR_stream_cross_process_fd */
|
||||
|
||||
#ifndef EGL_KHR_stream_fifo
|
||||
#define EGL_KHR_stream_fifo 1
|
||||
#ifdef EGL_KHR_stream
|
||||
#define EGL_STREAM_FIFO_LENGTH_KHR 0x31FC
|
||||
#define EGL_STREAM_TIME_NOW_KHR 0x31FD
|
||||
#define EGL_STREAM_TIME_CONSUMER_KHR 0x31FE
|
||||
#define EGL_STREAM_TIME_PRODUCER_KHR 0x31FF
|
||||
typedef EGLBoolean (EGLAPIENTRYP PFNEGLQUERYSTREAMTIMEKHRPROC) (EGLDisplay dpy, EGLStreamKHR stream, EGLenum attribute, EGLTimeKHR *value);
|
||||
#ifdef EGL_EGLEXT_PROTOTYPES
|
||||
EGLAPI EGLBoolean EGLAPIENTRY eglQueryStreamTimeKHR (EGLDisplay dpy, EGLStreamKHR stream, EGLenum attribute, EGLTimeKHR *value);
|
||||
#endif
|
||||
#endif /* EGL_KHR_stream */
|
||||
#endif /* EGL_KHR_stream_fifo */
|
||||
|
||||
#ifndef EGL_KHR_stream_producer_aldatalocator
|
||||
#define EGL_KHR_stream_producer_aldatalocator 1
|
||||
#ifdef EGL_KHR_stream
|
||||
#endif /* EGL_KHR_stream */
|
||||
#endif /* EGL_KHR_stream_producer_aldatalocator */
|
||||
|
||||
#ifndef EGL_KHR_stream_producer_eglsurface
|
||||
#define EGL_KHR_stream_producer_eglsurface 1
|
||||
#ifdef EGL_KHR_stream
|
||||
#define EGL_STREAM_BIT_KHR 0x0800
|
||||
typedef EGLSurface (EGLAPIENTRYP PFNEGLCREATESTREAMPRODUCERSURFACEKHRPROC) (EGLDisplay dpy, EGLConfig config, EGLStreamKHR stream, const EGLint *attrib_list);
|
||||
#ifdef EGL_EGLEXT_PROTOTYPES
|
||||
EGLAPI EGLSurface EGLAPIENTRY eglCreateStreamProducerSurfaceKHR (EGLDisplay dpy, EGLConfig config, EGLStreamKHR stream, const EGLint *attrib_list);
|
||||
#endif
|
||||
#endif /* EGL_KHR_stream */
|
||||
#endif /* EGL_KHR_stream_producer_eglsurface */
|
||||
|
||||
#ifndef EGL_KHR_surfaceless_context
|
||||
#define EGL_KHR_surfaceless_context 1
|
||||
#endif /* EGL_KHR_surfaceless_context */
|
||||
|
||||
#ifndef EGL_KHR_vg_parent_image
|
||||
#define EGL_KHR_vg_parent_image 1
|
||||
#define EGL_VG_PARENT_IMAGE_KHR 0x30BA
|
||||
#endif /* EGL_KHR_vg_parent_image */
|
||||
|
||||
#ifndef EGL_KHR_wait_sync
|
||||
#define EGL_KHR_wait_sync 1
|
||||
typedef EGLint (EGLAPIENTRYP PFNEGLWAITSYNCKHRPROC) (EGLDisplay dpy, EGLSyncKHR sync, EGLint flags);
|
||||
#ifdef EGL_EGLEXT_PROTOTYPES
|
||||
EGLAPI EGLint EGLAPIENTRY eglWaitSyncKHR (EGLDisplay dpy, EGLSyncKHR sync, EGLint flags);
|
||||
#endif
|
||||
#endif /* EGL_KHR_wait_sync */
|
||||
|
||||
#ifndef EGL_ANDROID_blob_cache
|
||||
#define EGL_ANDROID_blob_cache 1
|
||||
typedef khronos_ssize_t EGLsizeiANDROID;
|
||||
typedef void (*EGLSetBlobFuncANDROID) (const void *key, EGLsizeiANDROID keySize, const void *value, EGLsizeiANDROID valueSize);
|
||||
typedef EGLsizeiANDROID (*EGLGetBlobFuncANDROID) (const void *key, EGLsizeiANDROID keySize, void *value, EGLsizeiANDROID valueSize);
|
||||
typedef void (EGLAPIENTRYP PFNEGLSETBLOBCACHEFUNCSANDROIDPROC) (EGLDisplay dpy, EGLSetBlobFuncANDROID set, EGLGetBlobFuncANDROID get);
|
||||
#ifdef EGL_EGLEXT_PROTOTYPES
|
||||
EGLAPI void EGLAPIENTRY eglSetBlobCacheFuncsANDROID (EGLDisplay dpy, EGLSetBlobFuncANDROID set, EGLGetBlobFuncANDROID get);
|
||||
#endif
|
||||
#endif /* EGL_ANDROID_blob_cache */
|
||||
|
||||
#ifndef EGL_ANDROID_framebuffer_target
|
||||
#define EGL_ANDROID_framebuffer_target 1
|
||||
#define EGL_FRAMEBUFFER_TARGET_ANDROID 0x3147
|
||||
#endif /* EGL_ANDROID_framebuffer_target */
|
||||
|
||||
#ifndef EGL_ANDROID_image_native_buffer
|
||||
#define EGL_ANDROID_image_native_buffer 1
|
||||
#define EGL_NATIVE_BUFFER_ANDROID 0x3140
|
||||
#endif /* EGL_ANDROID_image_native_buffer */
|
||||
|
||||
#ifndef EGL_ANDROID_native_fence_sync
|
||||
#define EGL_ANDROID_native_fence_sync 1
|
||||
#define EGL_SYNC_NATIVE_FENCE_ANDROID 0x3144
|
||||
#define EGL_SYNC_NATIVE_FENCE_FD_ANDROID 0x3145
|
||||
#define EGL_SYNC_NATIVE_FENCE_SIGNALED_ANDROID 0x3146
|
||||
#define EGL_NO_NATIVE_FENCE_FD_ANDROID -1
|
||||
typedef EGLint (EGLAPIENTRYP PFNEGLDUPNATIVEFENCEFDANDROIDPROC) (EGLDisplay dpy, EGLSyncKHR sync);
|
||||
#ifdef EGL_EGLEXT_PROTOTYPES
|
||||
EGLAPI EGLint EGLAPIENTRY eglDupNativeFenceFDANDROID (EGLDisplay dpy, EGLSyncKHR sync);
|
||||
#endif
|
||||
#endif /* EGL_ANDROID_native_fence_sync */
|
||||
|
||||
#ifndef EGL_ANDROID_recordable
|
||||
#define EGL_ANDROID_recordable 1
|
||||
#define EGL_RECORDABLE_ANDROID 0x3142
|
||||
#endif /* EGL_ANDROID_recordable */
|
||||
|
||||
#ifndef EGL_ANGLE_d3d_share_handle_client_buffer
|
||||
#define EGL_ANGLE_d3d_share_handle_client_buffer 1
|
||||
#define EGL_D3D_TEXTURE_2D_SHARE_HANDLE_ANGLE 0x3200
|
||||
#endif /* EGL_ANGLE_d3d_share_handle_client_buffer */
|
||||
|
||||
#ifndef EGL_ANGLE_query_surface_pointer
|
||||
#define EGL_ANGLE_query_surface_pointer 1
|
||||
typedef EGLBoolean (EGLAPIENTRYP PFNEGLQUERYSURFACEPOINTERANGLEPROC) (EGLDisplay dpy, EGLSurface surface, EGLint attribute, void **value);
|
||||
#ifdef EGL_EGLEXT_PROTOTYPES
|
||||
EGLAPI EGLBoolean eglQuerySurfacePointerANGLE(EGLDisplay dpy, EGLSurface surface, EGLint attribute, void **value);
|
||||
#endif
|
||||
typedef EGLBoolean (EGLAPIENTRYP PFNEGLQUERYSURFACEPOINTERANGLEPROC) (EGLDisplay dpy, EGLSurface surface, EGLint attribute, void **value);
|
||||
EGLAPI EGLBoolean EGLAPIENTRY eglQuerySurfacePointerANGLE (EGLDisplay dpy, EGLSurface surface, EGLint attribute, void **value);
|
||||
#endif
|
||||
#endif /* EGL_ANGLE_query_surface_pointer */
|
||||
|
||||
#ifndef EGL_ANGLE_surface_d3d_texture_2d_share_handle
|
||||
#define EGL_ANGLE_surface_d3d_texture_2d_share_handle 1
|
||||
#define EGL_D3D_TEXTURE_2D_SHARE_HANDLE_ANGLE 0x3200
|
||||
#endif /* EGL_ANGLE_surface_d3d_texture_2d_share_handle */
|
||||
|
||||
#ifndef EGL_ARM_pixmap_multisample_discard
|
||||
#define EGL_ARM_pixmap_multisample_discard 1
|
||||
#define EGL_DISCARD_SAMPLES_ARM 0x3286
|
||||
#endif /* EGL_ARM_pixmap_multisample_discard */
|
||||
|
||||
#ifndef EGL_EXT_buffer_age
|
||||
#define EGL_EXT_buffer_age 1
|
||||
#define EGL_BUFFER_AGE_EXT 0x313D
|
||||
#endif /* EGL_EXT_buffer_age */
|
||||
|
||||
#ifndef EGL_EXT_client_extensions
|
||||
#define EGL_EXT_client_extensions 1
|
||||
#endif /* EGL_EXT_client_extensions */
|
||||
|
||||
#ifndef EGL_EXT_create_context_robustness
|
||||
#define EGL_EXT_create_context_robustness 1
|
||||
#define EGL_CONTEXT_OPENGL_ROBUST_ACCESS_EXT 0x30BF
|
||||
#define EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_EXT 0x3138
|
||||
#define EGL_NO_RESET_NOTIFICATION_EXT 0x31BE
|
||||
#define EGL_LOSE_CONTEXT_ON_RESET_EXT 0x31BF
|
||||
#endif /* EGL_EXT_create_context_robustness */
|
||||
|
||||
#ifndef EGL_EXT_image_dma_buf_import
|
||||
#define EGL_EXT_image_dma_buf_import 1
|
||||
#define EGL_LINUX_DMA_BUF_EXT 0x3270
|
||||
#define EGL_LINUX_DRM_FOURCC_EXT 0x3271
|
||||
#define EGL_DMA_BUF_PLANE0_FD_EXT 0x3272
|
||||
#define EGL_DMA_BUF_PLANE0_OFFSET_EXT 0x3273
|
||||
#define EGL_DMA_BUF_PLANE0_PITCH_EXT 0x3274
|
||||
#define EGL_DMA_BUF_PLANE1_FD_EXT 0x3275
|
||||
#define EGL_DMA_BUF_PLANE1_OFFSET_EXT 0x3276
|
||||
#define EGL_DMA_BUF_PLANE1_PITCH_EXT 0x3277
|
||||
#define EGL_DMA_BUF_PLANE2_FD_EXT 0x3278
|
||||
#define EGL_DMA_BUF_PLANE2_OFFSET_EXT 0x3279
|
||||
#define EGL_DMA_BUF_PLANE2_PITCH_EXT 0x327A
|
||||
#define EGL_YUV_COLOR_SPACE_HINT_EXT 0x327B
|
||||
#define EGL_SAMPLE_RANGE_HINT_EXT 0x327C
|
||||
#define EGL_YUV_CHROMA_HORIZONTAL_SITING_HINT_EXT 0x327D
|
||||
#define EGL_YUV_CHROMA_VERTICAL_SITING_HINT_EXT 0x327E
|
||||
#define EGL_ITU_REC601_EXT 0x327F
|
||||
#define EGL_ITU_REC709_EXT 0x3280
|
||||
#define EGL_ITU_REC2020_EXT 0x3281
|
||||
#define EGL_YUV_FULL_RANGE_EXT 0x3282
|
||||
#define EGL_YUV_NARROW_RANGE_EXT 0x3283
|
||||
#define EGL_YUV_CHROMA_SITING_0_EXT 0x3284
|
||||
#define EGL_YUV_CHROMA_SITING_0_5_EXT 0x3285
|
||||
#endif /* EGL_EXT_image_dma_buf_import */
|
||||
|
||||
#ifndef EGL_EXT_multiview_window
|
||||
#define EGL_EXT_multiview_window 1
|
||||
#define EGL_MULTIVIEW_VIEW_COUNT_EXT 0x3134
|
||||
#endif /* EGL_EXT_multiview_window */
|
||||
|
||||
#ifndef EGL_EXT_platform_base
|
||||
#define EGL_EXT_platform_base 1
|
||||
typedef EGLDisplay (EGLAPIENTRYP PFNEGLGETPLATFORMDISPLAYEXTPROC) (EGLenum platform, void *native_display, const EGLint *attrib_list);
|
||||
typedef EGLSurface (EGLAPIENTRYP PFNEGLCREATEPLATFORMWINDOWSURFACEEXTPROC) (EGLDisplay dpy, EGLConfig config, void *native_window, const EGLint *attrib_list);
|
||||
typedef EGLSurface (EGLAPIENTRYP PFNEGLCREATEPLATFORMPIXMAPSURFACEEXTPROC) (EGLDisplay dpy, EGLConfig config, void *native_pixmap, const EGLint *attrib_list);
|
||||
#ifdef EGL_EGLEXT_PROTOTYPES
|
||||
EGLAPI EGLDisplay EGLAPIENTRY eglGetPlatformDisplayEXT (EGLenum platform, void *native_display, const EGLint *attrib_list);
|
||||
EGLAPI EGLSurface EGLAPIENTRY eglCreatePlatformWindowSurfaceEXT (EGLDisplay dpy, EGLConfig config, void *native_window, const EGLint *attrib_list);
|
||||
EGLAPI EGLSurface EGLAPIENTRY eglCreatePlatformPixmapSurfaceEXT (EGLDisplay dpy, EGLConfig config, void *native_pixmap, const EGLint *attrib_list);
|
||||
#endif
|
||||
#endif /* EGL_EXT_platform_base */
|
||||
|
||||
#ifndef EGL_EXT_platform_wayland
|
||||
#define EGL_EXT_platform_wayland 1
|
||||
#define EGL_PLATFORM_WAYLAND_EXT 0x31D8
|
||||
#endif /* EGL_EXT_platform_wayland */
|
||||
|
||||
#ifndef EGL_EXT_platform_x11
|
||||
#define EGL_EXT_platform_x11 1
|
||||
#define EGL_PLATFORM_X11_EXT 0x31D5
|
||||
#define EGL_PLATFORM_X11_SCREEN_EXT 0x31D6
|
||||
#endif /* EGL_EXT_platform_x11 */
|
||||
|
||||
#ifndef EGL_EXT_protected_surface
|
||||
#define EGL_EXT_protected_surface 1
|
||||
#define EGL_PROTECTED_CONTENT_EXT 0x32C0
|
||||
#endif /* EGL_EXT_protected_surface */
|
||||
|
||||
#ifndef EGL_EXT_swap_buffers_with_damage
|
||||
#define EGL_EXT_swap_buffers_with_damage 1
|
||||
typedef EGLBoolean (EGLAPIENTRYP PFNEGLSWAPBUFFERSWITHDAMAGEEXTPROC) (EGLDisplay dpy, EGLSurface surface, EGLint *rects, EGLint n_rects);
|
||||
#ifdef EGL_EGLEXT_PROTOTYPES
|
||||
EGLAPI EGLBoolean EGLAPIENTRY eglSwapBuffersWithDamageEXT (EGLDisplay dpy, EGLSurface surface, EGLint *rects, EGLint n_rects);
|
||||
#endif
|
||||
#endif /* EGL_EXT_swap_buffers_with_damage */
|
||||
|
||||
#ifndef EGL_HI_clientpixmap
|
||||
#define EGL_HI_clientpixmap 1
|
||||
struct EGLClientPixmapHI {
|
||||
void *pData;
|
||||
EGLint iWidth;
|
||||
EGLint iHeight;
|
||||
EGLint iStride;
|
||||
};
|
||||
#define EGL_CLIENT_PIXMAP_POINTER_HI 0x8F74
|
||||
typedef EGLSurface (EGLAPIENTRYP PFNEGLCREATEPIXMAPSURFACEHIPROC) (EGLDisplay dpy, EGLConfig config, struct EGLClientPixmapHI *pixmap);
|
||||
#ifdef EGL_EGLEXT_PROTOTYPES
|
||||
EGLAPI EGLSurface EGLAPIENTRY eglCreatePixmapSurfaceHI (EGLDisplay dpy, EGLConfig config, struct EGLClientPixmapHI *pixmap);
|
||||
#endif
|
||||
#endif /* EGL_HI_clientpixmap */
|
||||
|
||||
#ifndef EGL_HI_colorformats
|
||||
#define EGL_HI_colorformats 1
|
||||
#define EGL_COLOR_FORMAT_HI 0x8F70
|
||||
#define EGL_COLOR_RGB_HI 0x8F71
|
||||
#define EGL_COLOR_RGBA_HI 0x8F72
|
||||
#define EGL_COLOR_ARGB_HI 0x8F73
|
||||
#endif /* EGL_HI_colorformats */
|
||||
|
||||
#ifndef EGL_IMG_context_priority
|
||||
#define EGL_IMG_context_priority 1
|
||||
#define EGL_CONTEXT_PRIORITY_LEVEL_IMG 0x3100
|
||||
#define EGL_CONTEXT_PRIORITY_HIGH_IMG 0x3101
|
||||
#define EGL_CONTEXT_PRIORITY_MEDIUM_IMG 0x3102
|
||||
#define EGL_CONTEXT_PRIORITY_LOW_IMG 0x3103
|
||||
#endif /* EGL_IMG_context_priority */
|
||||
|
||||
#ifndef EGL_MESA_drm_image
|
||||
#define EGL_MESA_drm_image 1
|
||||
#define EGL_DRM_BUFFER_FORMAT_MESA 0x31D0
|
||||
#define EGL_DRM_BUFFER_USE_MESA 0x31D1
|
||||
#define EGL_DRM_BUFFER_FORMAT_ARGB32_MESA 0x31D2
|
||||
#define EGL_DRM_BUFFER_MESA 0x31D3
|
||||
#define EGL_DRM_BUFFER_STRIDE_MESA 0x31D4
|
||||
#define EGL_DRM_BUFFER_USE_SCANOUT_MESA 0x00000001
|
||||
#define EGL_DRM_BUFFER_USE_SHARE_MESA 0x00000002
|
||||
typedef EGLImageKHR (EGLAPIENTRYP PFNEGLCREATEDRMIMAGEMESAPROC) (EGLDisplay dpy, const EGLint *attrib_list);
|
||||
typedef EGLBoolean (EGLAPIENTRYP PFNEGLEXPORTDRMIMAGEMESAPROC) (EGLDisplay dpy, EGLImageKHR image, EGLint *name, EGLint *handle, EGLint *stride);
|
||||
#ifdef EGL_EGLEXT_PROTOTYPES
|
||||
EGLAPI EGLImageKHR EGLAPIENTRY eglCreateDRMImageMESA (EGLDisplay dpy, const EGLint *attrib_list);
|
||||
EGLAPI EGLBoolean EGLAPIENTRY eglExportDRMImageMESA (EGLDisplay dpy, EGLImageKHR image, EGLint *name, EGLint *handle, EGLint *stride);
|
||||
#endif
|
||||
#endif /* EGL_MESA_drm_image */
|
||||
|
||||
#ifndef EGL_MESA_platform_gbm
|
||||
#define EGL_MESA_platform_gbm 1
|
||||
#define EGL_PLATFORM_GBM_MESA 0x31D7
|
||||
#endif /* EGL_MESA_platform_gbm */
|
||||
|
||||
#ifndef EGL_NV_3dvision_surface
|
||||
#define EGL_NV_3dvision_surface 1
|
||||
#define EGL_AUTO_STEREO_NV 0x3136
|
||||
#endif /* EGL_NV_3dvision_surface */
|
||||
|
||||
#ifndef EGL_NV_coverage_sample
|
||||
#define EGL_NV_coverage_sample 1
|
||||
#define EGL_COVERAGE_BUFFERS_NV 0x30E0
|
||||
#define EGL_COVERAGE_SAMPLES_NV 0x30E1
|
||||
#endif /* EGL_NV_coverage_sample */
|
||||
|
||||
#ifndef EGL_NV_coverage_sample_resolve
|
||||
#define EGL_NV_coverage_sample_resolve 1
|
||||
#define EGL_COVERAGE_SAMPLE_RESOLVE_NV 0x3131
|
||||
#define EGL_COVERAGE_SAMPLE_RESOLVE_DEFAULT_NV 0x3132
|
||||
#define EGL_COVERAGE_SAMPLE_RESOLVE_NONE_NV 0x3133
|
||||
#endif
|
||||
#define EGL_COVERAGE_SAMPLE_RESOLVE_NV 0x3131
|
||||
#define EGL_COVERAGE_SAMPLE_RESOLVE_DEFAULT_NV 0x3132
|
||||
#define EGL_COVERAGE_SAMPLE_RESOLVE_NONE_NV 0x3133
|
||||
#endif /* EGL_NV_coverage_sample_resolve */
|
||||
|
||||
#if KHRONOS_SUPPORT_INT64 /* EGLTimeKHR requires 64-bit uint support */
|
||||
#ifndef EGL_NV_depth_nonlinear
|
||||
#define EGL_NV_depth_nonlinear 1
|
||||
#define EGL_DEPTH_ENCODING_NV 0x30E2
|
||||
#define EGL_DEPTH_ENCODING_NONE_NV 0
|
||||
#define EGL_DEPTH_ENCODING_NONLINEAR_NV 0x30E3
|
||||
#endif /* EGL_NV_depth_nonlinear */
|
||||
|
||||
#ifndef EGL_NV_native_query
|
||||
#define EGL_NV_native_query 1
|
||||
typedef EGLBoolean (EGLAPIENTRYP PFNEGLQUERYNATIVEDISPLAYNVPROC) (EGLDisplay dpy, EGLNativeDisplayType *display_id);
|
||||
typedef EGLBoolean (EGLAPIENTRYP PFNEGLQUERYNATIVEWINDOWNVPROC) (EGLDisplay dpy, EGLSurface surf, EGLNativeWindowType *window);
|
||||
typedef EGLBoolean (EGLAPIENTRYP PFNEGLQUERYNATIVEPIXMAPNVPROC) (EGLDisplay dpy, EGLSurface surf, EGLNativePixmapType *pixmap);
|
||||
#ifdef EGL_EGLEXT_PROTOTYPES
|
||||
EGLAPI EGLBoolean EGLAPIENTRY eglQueryNativeDisplayNV (EGLDisplay dpy, EGLNativeDisplayType *display_id);
|
||||
EGLAPI EGLBoolean EGLAPIENTRY eglQueryNativeWindowNV (EGLDisplay dpy, EGLSurface surf, EGLNativeWindowType *window);
|
||||
EGLAPI EGLBoolean EGLAPIENTRY eglQueryNativePixmapNV (EGLDisplay dpy, EGLSurface surf, EGLNativePixmapType *pixmap);
|
||||
#endif
|
||||
#endif /* EGL_NV_native_query */
|
||||
|
||||
#ifndef EGL_NV_post_convert_rounding
|
||||
#define EGL_NV_post_convert_rounding 1
|
||||
#endif /* EGL_NV_post_convert_rounding */
|
||||
|
||||
#ifndef EGL_NV_post_sub_buffer
|
||||
#define EGL_NV_post_sub_buffer 1
|
||||
#define EGL_POST_SUB_BUFFER_SUPPORTED_NV 0x30BE
|
||||
typedef EGLBoolean (EGLAPIENTRYP PFNEGLPOSTSUBBUFFERNVPROC) (EGLDisplay dpy, EGLSurface surface, EGLint x, EGLint y, EGLint width, EGLint height);
|
||||
#ifdef EGL_EGLEXT_PROTOTYPES
|
||||
EGLAPI EGLBoolean EGLAPIENTRY eglPostSubBufferNV (EGLDisplay dpy, EGLSurface surface, EGLint x, EGLint y, EGLint width, EGLint height);
|
||||
#endif
|
||||
#endif /* EGL_NV_post_sub_buffer */
|
||||
|
||||
#ifndef EGL_NV_stream_sync
|
||||
#define EGL_NV_stream_sync 1
|
||||
#define EGL_SYNC_NEW_FRAME_NV 0x321F
|
||||
typedef EGLSyncKHR (EGLAPIENTRYP PFNEGLCREATESTREAMSYNCNVPROC) (EGLDisplay dpy, EGLStreamKHR stream, EGLenum type, const EGLint *attrib_list);
|
||||
#ifdef EGL_EGLEXT_PROTOTYPES
|
||||
EGLAPI EGLSyncKHR EGLAPIENTRY eglCreateStreamSyncNV (EGLDisplay dpy, EGLStreamKHR stream, EGLenum type, const EGLint *attrib_list);
|
||||
#endif
|
||||
#endif /* EGL_NV_stream_sync */
|
||||
|
||||
#ifndef EGL_NV_sync
|
||||
#define EGL_NV_sync 1
|
||||
typedef void *EGLSyncNV;
|
||||
typedef khronos_utime_nanoseconds_t EGLTimeNV;
|
||||
#ifdef KHRONOS_SUPPORT_INT64
|
||||
#define EGL_SYNC_PRIOR_COMMANDS_COMPLETE_NV 0x30E6
|
||||
#define EGL_SYNC_STATUS_NV 0x30E7
|
||||
#define EGL_SIGNALED_NV 0x30E8
|
||||
#define EGL_UNSIGNALED_NV 0x30E9
|
||||
#define EGL_SYNC_FLUSH_COMMANDS_BIT_NV 0x0001
|
||||
#define EGL_FOREVER_NV 0xFFFFFFFFFFFFFFFFull
|
||||
#define EGL_ALREADY_SIGNALED_NV 0x30EA
|
||||
#define EGL_TIMEOUT_EXPIRED_NV 0x30EB
|
||||
#define EGL_CONDITION_SATISFIED_NV 0x30EC
|
||||
#define EGL_SYNC_TYPE_NV 0x30ED
|
||||
#define EGL_SYNC_CONDITION_NV 0x30EE
|
||||
#define EGL_SYNC_FENCE_NV 0x30EF
|
||||
#define EGL_NO_SYNC_NV ((EGLSyncNV)0)
|
||||
typedef EGLSyncNV (EGLAPIENTRYP PFNEGLCREATEFENCESYNCNVPROC) (EGLDisplay dpy, EGLenum condition, const EGLint *attrib_list);
|
||||
typedef EGLBoolean (EGLAPIENTRYP PFNEGLDESTROYSYNCNVPROC) (EGLSyncNV sync);
|
||||
typedef EGLBoolean (EGLAPIENTRYP PFNEGLFENCENVPROC) (EGLSyncNV sync);
|
||||
typedef EGLint (EGLAPIENTRYP PFNEGLCLIENTWAITSYNCNVPROC) (EGLSyncNV sync, EGLint flags, EGLTimeNV timeout);
|
||||
typedef EGLBoolean (EGLAPIENTRYP PFNEGLSIGNALSYNCNVPROC) (EGLSyncNV sync, EGLenum mode);
|
||||
typedef EGLBoolean (EGLAPIENTRYP PFNEGLGETSYNCATTRIBNVPROC) (EGLSyncNV sync, EGLint attribute, EGLint *value);
|
||||
#ifdef EGL_EGLEXT_PROTOTYPES
|
||||
EGLAPI EGLSyncNV EGLAPIENTRY eglCreateFenceSyncNV (EGLDisplay dpy, EGLenum condition, const EGLint *attrib_list);
|
||||
EGLAPI EGLBoolean EGLAPIENTRY eglDestroySyncNV (EGLSyncNV sync);
|
||||
EGLAPI EGLBoolean EGLAPIENTRY eglFenceNV (EGLSyncNV sync);
|
||||
EGLAPI EGLint EGLAPIENTRY eglClientWaitSyncNV (EGLSyncNV sync, EGLint flags, EGLTimeNV timeout);
|
||||
EGLAPI EGLBoolean EGLAPIENTRY eglSignalSyncNV (EGLSyncNV sync, EGLenum mode);
|
||||
EGLAPI EGLBoolean EGLAPIENTRY eglGetSyncAttribNV (EGLSyncNV sync, EGLint attribute, EGLint *value);
|
||||
#endif
|
||||
#endif /* KHRONOS_SUPPORT_INT64 */
|
||||
#endif /* EGL_NV_sync */
|
||||
|
||||
#ifndef EGL_NV_system_time
|
||||
#define EGL_NV_system_time 1
|
||||
|
||||
typedef khronos_utime_nanoseconds_t EGLuint64NV;
|
||||
|
||||
typedef khronos_utime_nanoseconds_t EGLuint64NV;
|
||||
#ifdef KHRONOS_SUPPORT_INT64
|
||||
typedef EGLuint64NV (EGLAPIENTRYP PFNEGLGETSYSTEMTIMEFREQUENCYNVPROC) (void);
|
||||
typedef EGLuint64NV (EGLAPIENTRYP PFNEGLGETSYSTEMTIMENVPROC) (void);
|
||||
#ifdef EGL_EGLEXT_PROTOTYPES
|
||||
EGLAPI EGLuint64NV EGLAPIENTRY eglGetSystemTimeFrequencyNV(void);
|
||||
EGLAPI EGLuint64NV EGLAPIENTRY eglGetSystemTimeNV(void);
|
||||
#endif /* EGL_EGLEXT_PROTOTYPES */
|
||||
typedef EGLuint64NV (EGLAPIENTRYP PFNEGLGETSYSTEMTIMEFREQUENCYNVPROC) (void);
|
||||
typedef EGLuint64NV (EGLAPIENTRYP PFNEGLGETSYSTEMTIMENVPROC) (void);
|
||||
EGLAPI EGLuint64NV EGLAPIENTRY eglGetSystemTimeFrequencyNV (void);
|
||||
EGLAPI EGLuint64NV EGLAPIENTRY eglGetSystemTimeNV (void);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#endif /* KHRONOS_SUPPORT_INT64 */
|
||||
#endif /* EGL_NV_system_time */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
#endif
|
||||
@@ -2,30 +2,30 @@
|
||||
#define __eglplatform_h_
|
||||
|
||||
/*
|
||||
** Copyright (c) 2007-2009 The Khronos Group Inc.
|
||||
**
|
||||
** Permission is hereby granted, free of charge, to any person obtaining a
|
||||
** copy of this software and/or associated documentation files (the
|
||||
** "Materials"), to deal in the Materials without restriction, including
|
||||
** without limitation the rights to use, copy, modify, merge, publish,
|
||||
** distribute, sublicense, and/or sell copies of the Materials, and to
|
||||
** permit persons to whom the Materials are 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 Materials.
|
||||
**
|
||||
** THE MATERIALS ARE 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
|
||||
** MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
|
||||
*/
|
||||
** Copyright (c) 2007-2013 The Khronos Group Inc.
|
||||
**
|
||||
** Permission is hereby granted, free of charge, to any person obtaining a
|
||||
** copy of this software and/or associated documentation files (the
|
||||
** "Materials"), to deal in the Materials without restriction, including
|
||||
** without limitation the rights to use, copy, modify, merge, publish,
|
||||
** distribute, sublicense, and/or sell copies of the Materials, and to
|
||||
** permit persons to whom the Materials are 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 Materials.
|
||||
**
|
||||
** THE MATERIALS ARE 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
|
||||
** MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
|
||||
*/
|
||||
|
||||
/* Platform-specific types and definitions for egl.h
|
||||
* $Revision: 12306 $ on $Date: 2010-08-25 09:51:28 -0700 (Wed, 25 Aug 2010) $
|
||||
* $Revision: 23432 $ on $Date: 2013-10-09 00:57:24 -0700 (Wed, 09 Oct 2013) $
|
||||
*
|
||||
* Adopters may modify khrplatform.h and this file to suit their platform.
|
||||
* You are encouraged to submit all modifications to the Khronos group so that
|
||||
@@ -83,6 +83,16 @@ typedef int EGLNativeDisplayType;
|
||||
typedef void *EGLNativeWindowType;
|
||||
typedef void *EGLNativePixmapType;
|
||||
|
||||
#elif defined(__ANDROID__) || defined(ANDROID)
|
||||
|
||||
#include <android/native_window.h>
|
||||
|
||||
struct egl_native_pixmap_t;
|
||||
|
||||
typedef struct ANativeWindow* EGLNativeWindowType;
|
||||
typedef struct egl_native_pixmap_t* EGLNativePixmapType;
|
||||
typedef void* EGLNativeDisplayType;
|
||||
|
||||
#elif defined(__unix__)
|
||||
|
||||
/* X11 (tentative) */
|
||||
@@ -112,4 +122,4 @@ typedef EGLNativeWindowType NativeWindowType;
|
||||
*/
|
||||
typedef khronos_int32_t EGLint;
|
||||
|
||||
#endif /* __eglplatform_h */
|
||||
#endif /* __eglplatform_h */
|
||||
File diff suppressed because it is too large.
Load diff
File diff suppressed because it is too large.
Load diff
File diff suppressed because it is too large.
Load diff
+244
-340
@@ -1,56 +1,83 @@
|
||||
#ifndef __gl2_h_
|
||||
#define __gl2_h_
|
||||
|
||||
/* $Revision: 10602 $ on $Date:: 2010-03-04 22:35:34 -0800 #$ */
|
||||
|
||||
#include <GLES2/gl2platform.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*
|
||||
* This document is licensed under the SGI Free Software B License Version
|
||||
* 2.0. For details, see http://oss.sgi.com/projects/FreeB/ .
|
||||
*/
|
||||
/*
|
||||
** Copyright (c) 2013 The Khronos Group Inc.
|
||||
**
|
||||
** Permission is hereby granted, free of charge, to any person obtaining a
|
||||
** copy of this software and/or associated documentation files (the
|
||||
** "Materials"), to deal in the Materials without restriction, including
|
||||
** without limitation the rights to use, copy, modify, merge, publish,
|
||||
** distribute, sublicense, and/or sell copies of the Materials, and to
|
||||
** permit persons to whom the Materials are 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 Materials.
|
||||
**
|
||||
** THE MATERIALS ARE 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
|
||||
** MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
|
||||
*/
|
||||
/*
|
||||
** This header is generated from the Khronos OpenGL / OpenGL ES XML
|
||||
** API Registry. The current version of the Registry, generator scripts
|
||||
** used to make the header, and the header can be found at
|
||||
** http://www.opengl.org/registry/
|
||||
**
|
||||
** Khronos $Revision: 24614 $ on $Date: 2013-12-30 04:44:46 -0800 (Mon, 30 Dec 2013) $
|
||||
*/
|
||||
|
||||
/*-------------------------------------------------------------------------
|
||||
* Data type definitions
|
||||
*-----------------------------------------------------------------------*/
|
||||
#include <GLES2/gl2platform.h>
|
||||
|
||||
typedef void GLvoid;
|
||||
typedef char GLchar;
|
||||
typedef unsigned int GLenum;
|
||||
typedef unsigned char GLboolean;
|
||||
typedef unsigned int GLbitfield;
|
||||
typedef khronos_int8_t GLbyte;
|
||||
typedef short GLshort;
|
||||
typedef int GLint;
|
||||
typedef int GLsizei;
|
||||
typedef khronos_uint8_t GLubyte;
|
||||
typedef unsigned short GLushort;
|
||||
typedef unsigned int GLuint;
|
||||
typedef khronos_float_t GLfloat;
|
||||
typedef khronos_float_t GLclampf;
|
||||
typedef khronos_int32_t GLfixed;
|
||||
/* Generated on date 20131230 */
|
||||
|
||||
/* GL types for handling large vertex buffer objects */
|
||||
typedef khronos_intptr_t GLintptr;
|
||||
typedef khronos_ssize_t GLsizeiptr;
|
||||
/* Generated C header for:
|
||||
* API: gles2
|
||||
* Profile: common
|
||||
* Versions considered: 2\.[0-9]
|
||||
* Versions emitted: .*
|
||||
* Default extensions included: None
|
||||
* Additional extensions included: _nomatch_^
|
||||
* Extensions removed: _nomatch_^
|
||||
*/
|
||||
|
||||
/* OpenGL ES core versions */
|
||||
#define GL_ES_VERSION_2_0 1
|
||||
|
||||
/* ClearBufferMask */
|
||||
#ifndef GL_ES_VERSION_2_0
|
||||
#define GL_ES_VERSION_2_0 1
|
||||
#include <KHR/khrplatform.h>
|
||||
typedef khronos_int8_t GLbyte;
|
||||
typedef khronos_float_t GLclampf;
|
||||
typedef khronos_int32_t GLfixed;
|
||||
typedef short GLshort;
|
||||
typedef unsigned short GLushort;
|
||||
typedef void GLvoid;
|
||||
typedef struct __GLsync *GLsync;
|
||||
typedef khronos_int64_t GLint64;
|
||||
typedef khronos_uint64_t GLuint64;
|
||||
typedef unsigned int GLenum;
|
||||
typedef unsigned int GLuint;
|
||||
typedef char GLchar;
|
||||
typedef khronos_float_t GLfloat;
|
||||
typedef khronos_ssize_t GLsizeiptr;
|
||||
typedef khronos_intptr_t GLintptr;
|
||||
typedef unsigned int GLbitfield;
|
||||
typedef int GLint;
|
||||
typedef unsigned char GLboolean;
|
||||
typedef int GLsizei;
|
||||
typedef khronos_uint8_t GLubyte;
|
||||
#define GL_DEPTH_BUFFER_BIT 0x00000100
|
||||
#define GL_STENCIL_BUFFER_BIT 0x00000400
|
||||
#define GL_COLOR_BUFFER_BIT 0x00004000
|
||||
|
||||
/* Boolean */
|
||||
#define GL_FALSE 0
|
||||
#define GL_TRUE 1
|
||||
|
||||
/* BeginMode */
|
||||
#define GL_POINTS 0x0000
|
||||
#define GL_LINES 0x0001
|
||||
#define GL_LINE_LOOP 0x0002
|
||||
@@ -58,18 +85,6 @@ typedef khronos_ssize_t GLsizeiptr;
|
||||
#define GL_TRIANGLES 0x0004
|
||||
#define GL_TRIANGLE_STRIP 0x0005
|
||||
#define GL_TRIANGLE_FAN 0x0006
|
||||
|
||||
/* AlphaFunction (not supported in ES20) */
|
||||
/* GL_NEVER */
|
||||
/* GL_LESS */
|
||||
/* GL_EQUAL */
|
||||
/* GL_LEQUAL */
|
||||
/* GL_GREATER */
|
||||
/* GL_NOTEQUAL */
|
||||
/* GL_GEQUAL */
|
||||
/* GL_ALWAYS */
|
||||
|
||||
/* BlendingFactorDest */
|
||||
#define GL_ZERO 0
|
||||
#define GL_ONE 1
|
||||
#define GL_SRC_COLOR 0x0300
|
||||
@@ -78,29 +93,15 @@ typedef khronos_ssize_t GLsizeiptr;
|
||||
#define GL_ONE_MINUS_SRC_ALPHA 0x0303
|
||||
#define GL_DST_ALPHA 0x0304
|
||||
#define GL_ONE_MINUS_DST_ALPHA 0x0305
|
||||
|
||||
/* BlendingFactorSrc */
|
||||
/* GL_ZERO */
|
||||
/* GL_ONE */
|
||||
#define GL_DST_COLOR 0x0306
|
||||
#define GL_ONE_MINUS_DST_COLOR 0x0307
|
||||
#define GL_SRC_ALPHA_SATURATE 0x0308
|
||||
/* GL_SRC_ALPHA */
|
||||
/* GL_ONE_MINUS_SRC_ALPHA */
|
||||
/* GL_DST_ALPHA */
|
||||
/* GL_ONE_MINUS_DST_ALPHA */
|
||||
|
||||
/* BlendEquationSeparate */
|
||||
#define GL_FUNC_ADD 0x8006
|
||||
#define GL_BLEND_EQUATION 0x8009
|
||||
#define GL_BLEND_EQUATION_RGB 0x8009 /* same as BLEND_EQUATION */
|
||||
#define GL_BLEND_EQUATION_RGB 0x8009
|
||||
#define GL_BLEND_EQUATION_ALPHA 0x883D
|
||||
|
||||
/* BlendSubtract */
|
||||
#define GL_FUNC_SUBTRACT 0x800A
|
||||
#define GL_FUNC_REVERSE_SUBTRACT 0x800B
|
||||
|
||||
/* Separate Blend Functions */
|
||||
#define GL_BLEND_DST_RGB 0x80C8
|
||||
#define GL_BLEND_SRC_RGB 0x80C9
|
||||
#define GL_BLEND_DST_ALPHA 0x80CA
|
||||
@@ -110,38 +111,19 @@ typedef khronos_ssize_t GLsizeiptr;
|
||||
#define GL_CONSTANT_ALPHA 0x8003
|
||||
#define GL_ONE_MINUS_CONSTANT_ALPHA 0x8004
|
||||
#define GL_BLEND_COLOR 0x8005
|
||||
|
||||
/* Buffer Objects */
|
||||
#define GL_ARRAY_BUFFER 0x8892
|
||||
#define GL_ELEMENT_ARRAY_BUFFER 0x8893
|
||||
#define GL_ARRAY_BUFFER_BINDING 0x8894
|
||||
#define GL_ELEMENT_ARRAY_BUFFER_BINDING 0x8895
|
||||
|
||||
#define GL_STREAM_DRAW 0x88E0
|
||||
#define GL_STATIC_DRAW 0x88E4
|
||||
#define GL_DYNAMIC_DRAW 0x88E8
|
||||
|
||||
#define GL_BUFFER_SIZE 0x8764
|
||||
#define GL_BUFFER_USAGE 0x8765
|
||||
|
||||
#define GL_CURRENT_VERTEX_ATTRIB 0x8626
|
||||
|
||||
/* CullFaceMode */
|
||||
#define GL_FRONT 0x0404
|
||||
#define GL_BACK 0x0405
|
||||
#define GL_FRONT_AND_BACK 0x0408
|
||||
|
||||
/* DepthFunction */
|
||||
/* GL_NEVER */
|
||||
/* GL_LESS */
|
||||
/* GL_EQUAL */
|
||||
/* GL_LEQUAL */
|
||||
/* GL_GREATER */
|
||||
/* GL_NOTEQUAL */
|
||||
/* GL_GEQUAL */
|
||||
/* GL_ALWAYS */
|
||||
|
||||
/* EnableCap */
|
||||
#define GL_TEXTURE_2D 0x0DE1
|
||||
#define GL_CULL_FACE 0x0B44
|
||||
#define GL_BLEND 0x0BE2
|
||||
@@ -152,19 +134,13 @@ typedef khronos_ssize_t GLsizeiptr;
|
||||
#define GL_POLYGON_OFFSET_FILL 0x8037
|
||||
#define GL_SAMPLE_ALPHA_TO_COVERAGE 0x809E
|
||||
#define GL_SAMPLE_COVERAGE 0x80A0
|
||||
|
||||
/* ErrorCode */
|
||||
#define GL_NO_ERROR 0
|
||||
#define GL_INVALID_ENUM 0x0500
|
||||
#define GL_INVALID_VALUE 0x0501
|
||||
#define GL_INVALID_OPERATION 0x0502
|
||||
#define GL_OUT_OF_MEMORY 0x0505
|
||||
|
||||
/* FrontFaceDirection */
|
||||
#define GL_CW 0x0900
|
||||
#define GL_CCW 0x0901
|
||||
|
||||
/* GetPName */
|
||||
#define GL_LINE_WIDTH 0x0B21
|
||||
#define GL_ALIASED_POINT_SIZE_RANGE 0x846D
|
||||
#define GL_ALIASED_LINE_WIDTH_RANGE 0x846E
|
||||
@@ -191,7 +167,6 @@ typedef khronos_ssize_t GLsizeiptr;
|
||||
#define GL_STENCIL_BACK_WRITEMASK 0x8CA5
|
||||
#define GL_VIEWPORT 0x0BA2
|
||||
#define GL_SCISSOR_BOX 0x0C10
|
||||
/* GL_SCISSOR_TEST */
|
||||
#define GL_COLOR_CLEAR_VALUE 0x0C22
|
||||
#define GL_COLOR_WRITEMASK 0x0C23
|
||||
#define GL_UNPACK_ALIGNMENT 0x0CF5
|
||||
@@ -206,32 +181,18 @@ typedef khronos_ssize_t GLsizeiptr;
|
||||
#define GL_DEPTH_BITS 0x0D56
|
||||
#define GL_STENCIL_BITS 0x0D57
|
||||
#define GL_POLYGON_OFFSET_UNITS 0x2A00
|
||||
/* GL_POLYGON_OFFSET_FILL */
|
||||
#define GL_POLYGON_OFFSET_FACTOR 0x8038
|
||||
#define GL_TEXTURE_BINDING_2D 0x8069
|
||||
#define GL_SAMPLE_BUFFERS 0x80A8
|
||||
#define GL_SAMPLES 0x80A9
|
||||
#define GL_SAMPLE_COVERAGE_VALUE 0x80AA
|
||||
#define GL_SAMPLE_COVERAGE_INVERT 0x80AB
|
||||
|
||||
/* GetTextureParameter */
|
||||
/* GL_TEXTURE_MAG_FILTER */
|
||||
/* GL_TEXTURE_MIN_FILTER */
|
||||
/* GL_TEXTURE_WRAP_S */
|
||||
/* GL_TEXTURE_WRAP_T */
|
||||
|
||||
#define GL_NUM_COMPRESSED_TEXTURE_FORMATS 0x86A2
|
||||
#define GL_COMPRESSED_TEXTURE_FORMATS 0x86A3
|
||||
|
||||
/* HintMode */
|
||||
#define GL_DONT_CARE 0x1100
|
||||
#define GL_FASTEST 0x1101
|
||||
#define GL_NICEST 0x1102
|
||||
|
||||
/* HintTarget */
|
||||
#define GL_GENERATE_MIPMAP_HINT 0x8192
|
||||
|
||||
/* DataType */
|
||||
#define GL_GENERATE_MIPMAP_HINT 0x8192
|
||||
#define GL_BYTE 0x1400
|
||||
#define GL_UNSIGNED_BYTE 0x1401
|
||||
#define GL_SHORT 0x1402
|
||||
@@ -240,44 +201,35 @@ typedef khronos_ssize_t GLsizeiptr;
|
||||
#define GL_UNSIGNED_INT 0x1405
|
||||
#define GL_FLOAT 0x1406
|
||||
#define GL_FIXED 0x140C
|
||||
|
||||
/* PixelFormat */
|
||||
#define GL_DEPTH_COMPONENT 0x1902
|
||||
#define GL_ALPHA 0x1906
|
||||
#define GL_RGB 0x1907
|
||||
#define GL_RGBA 0x1908
|
||||
#define GL_LUMINANCE 0x1909
|
||||
#define GL_LUMINANCE_ALPHA 0x190A
|
||||
|
||||
/* PixelType */
|
||||
/* GL_UNSIGNED_BYTE */
|
||||
#define GL_UNSIGNED_SHORT_4_4_4_4 0x8033
|
||||
#define GL_UNSIGNED_SHORT_5_5_5_1 0x8034
|
||||
#define GL_UNSIGNED_SHORT_5_6_5 0x8363
|
||||
|
||||
/* Shaders */
|
||||
#define GL_FRAGMENT_SHADER 0x8B30
|
||||
#define GL_VERTEX_SHADER 0x8B31
|
||||
#define GL_MAX_VERTEX_ATTRIBS 0x8869
|
||||
#define GL_MAX_VERTEX_UNIFORM_VECTORS 0x8DFB
|
||||
#define GL_MAX_VARYING_VECTORS 0x8DFC
|
||||
#define GL_FRAGMENT_SHADER 0x8B30
|
||||
#define GL_VERTEX_SHADER 0x8B31
|
||||
#define GL_MAX_VERTEX_ATTRIBS 0x8869
|
||||
#define GL_MAX_VERTEX_UNIFORM_VECTORS 0x8DFB
|
||||
#define GL_MAX_VARYING_VECTORS 0x8DFC
|
||||
#define GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS 0x8B4D
|
||||
#define GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS 0x8B4C
|
||||
#define GL_MAX_TEXTURE_IMAGE_UNITS 0x8872
|
||||
#define GL_MAX_FRAGMENT_UNIFORM_VECTORS 0x8DFD
|
||||
#define GL_SHADER_TYPE 0x8B4F
|
||||
#define GL_DELETE_STATUS 0x8B80
|
||||
#define GL_LINK_STATUS 0x8B82
|
||||
#define GL_VALIDATE_STATUS 0x8B83
|
||||
#define GL_ATTACHED_SHADERS 0x8B85
|
||||
#define GL_ACTIVE_UNIFORMS 0x8B86
|
||||
#define GL_ACTIVE_UNIFORM_MAX_LENGTH 0x8B87
|
||||
#define GL_ACTIVE_ATTRIBUTES 0x8B89
|
||||
#define GL_ACTIVE_ATTRIBUTE_MAX_LENGTH 0x8B8A
|
||||
#define GL_SHADING_LANGUAGE_VERSION 0x8B8C
|
||||
#define GL_CURRENT_PROGRAM 0x8B8D
|
||||
|
||||
/* StencilFunction */
|
||||
#define GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS 0x8B4C
|
||||
#define GL_MAX_TEXTURE_IMAGE_UNITS 0x8872
|
||||
#define GL_MAX_FRAGMENT_UNIFORM_VECTORS 0x8DFD
|
||||
#define GL_SHADER_TYPE 0x8B4F
|
||||
#define GL_DELETE_STATUS 0x8B80
|
||||
#define GL_LINK_STATUS 0x8B82
|
||||
#define GL_VALIDATE_STATUS 0x8B83
|
||||
#define GL_ATTACHED_SHADERS 0x8B85
|
||||
#define GL_ACTIVE_UNIFORMS 0x8B86
|
||||
#define GL_ACTIVE_UNIFORM_MAX_LENGTH 0x8B87
|
||||
#define GL_ACTIVE_ATTRIBUTES 0x8B89
|
||||
#define GL_ACTIVE_ATTRIBUTE_MAX_LENGTH 0x8B8A
|
||||
#define GL_SHADING_LANGUAGE_VERSION 0x8B8C
|
||||
#define GL_CURRENT_PROGRAM 0x8B8D
|
||||
#define GL_NEVER 0x0200
|
||||
#define GL_LESS 0x0201
|
||||
#define GL_EQUAL 0x0202
|
||||
@@ -286,9 +238,6 @@ typedef khronos_ssize_t GLsizeiptr;
|
||||
#define GL_NOTEQUAL 0x0205
|
||||
#define GL_GEQUAL 0x0206
|
||||
#define GL_ALWAYS 0x0207
|
||||
|
||||
/* StencilOp */
|
||||
/* GL_ZERO */
|
||||
#define GL_KEEP 0x1E00
|
||||
#define GL_REPLACE 0x1E01
|
||||
#define GL_INCR 0x1E02
|
||||
@@ -296,35 +245,21 @@ typedef khronos_ssize_t GLsizeiptr;
|
||||
#define GL_INVERT 0x150A
|
||||
#define GL_INCR_WRAP 0x8507
|
||||
#define GL_DECR_WRAP 0x8508
|
||||
|
||||
/* StringName */
|
||||
#define GL_VENDOR 0x1F00
|
||||
#define GL_RENDERER 0x1F01
|
||||
#define GL_VERSION 0x1F02
|
||||
#define GL_EXTENSIONS 0x1F03
|
||||
|
||||
/* TextureMagFilter */
|
||||
#define GL_NEAREST 0x2600
|
||||
#define GL_LINEAR 0x2601
|
||||
|
||||
/* TextureMinFilter */
|
||||
/* GL_NEAREST */
|
||||
/* GL_LINEAR */
|
||||
#define GL_NEAREST_MIPMAP_NEAREST 0x2700
|
||||
#define GL_LINEAR_MIPMAP_NEAREST 0x2701
|
||||
#define GL_NEAREST_MIPMAP_LINEAR 0x2702
|
||||
#define GL_LINEAR_MIPMAP_LINEAR 0x2703
|
||||
|
||||
/* TextureParameterName */
|
||||
#define GL_TEXTURE_MAG_FILTER 0x2800
|
||||
#define GL_TEXTURE_MIN_FILTER 0x2801
|
||||
#define GL_TEXTURE_WRAP_S 0x2802
|
||||
#define GL_TEXTURE_WRAP_T 0x2803
|
||||
|
||||
/* TextureTarget */
|
||||
/* GL_TEXTURE_2D */
|
||||
#define GL_TEXTURE 0x1702
|
||||
|
||||
#define GL_TEXTURE_CUBE_MAP 0x8513
|
||||
#define GL_TEXTURE_BINDING_CUBE_MAP 0x8514
|
||||
#define GL_TEXTURE_CUBE_MAP_POSITIVE_X 0x8515
|
||||
@@ -334,8 +269,6 @@ typedef khronos_ssize_t GLsizeiptr;
|
||||
#define GL_TEXTURE_CUBE_MAP_POSITIVE_Z 0x8519
|
||||
#define GL_TEXTURE_CUBE_MAP_NEGATIVE_Z 0x851A
|
||||
#define GL_MAX_CUBE_MAP_TEXTURE_SIZE 0x851C
|
||||
|
||||
/* TextureUnit */
|
||||
#define GL_TEXTURE0 0x84C0
|
||||
#define GL_TEXTURE1 0x84C1
|
||||
#define GL_TEXTURE2 0x84C2
|
||||
@@ -369,13 +302,9 @@ typedef khronos_ssize_t GLsizeiptr;
|
||||
#define GL_TEXTURE30 0x84DE
|
||||
#define GL_TEXTURE31 0x84DF
|
||||
#define GL_ACTIVE_TEXTURE 0x84E0
|
||||
|
||||
/* TextureWrapMode */
|
||||
#define GL_REPEAT 0x2901
|
||||
#define GL_CLAMP_TO_EDGE 0x812F
|
||||
#define GL_MIRRORED_REPEAT 0x8370
|
||||
|
||||
/* Uniform Types */
|
||||
#define GL_FLOAT_VEC2 0x8B50
|
||||
#define GL_FLOAT_VEC3 0x8B51
|
||||
#define GL_FLOAT_VEC4 0x8B52
|
||||
@@ -391,49 +320,34 @@ typedef khronos_ssize_t GLsizeiptr;
|
||||
#define GL_FLOAT_MAT4 0x8B5C
|
||||
#define GL_SAMPLER_2D 0x8B5E
|
||||
#define GL_SAMPLER_CUBE 0x8B60
|
||||
|
||||
/* Vertex Arrays */
|
||||
#define GL_VERTEX_ATTRIB_ARRAY_ENABLED 0x8622
|
||||
#define GL_VERTEX_ATTRIB_ARRAY_SIZE 0x8623
|
||||
#define GL_VERTEX_ATTRIB_ARRAY_STRIDE 0x8624
|
||||
#define GL_VERTEX_ATTRIB_ARRAY_TYPE 0x8625
|
||||
#define GL_VERTEX_ATTRIB_ARRAY_NORMALIZED 0x886A
|
||||
#define GL_VERTEX_ATTRIB_ARRAY_POINTER 0x8645
|
||||
#define GL_VERTEX_ATTRIB_ARRAY_ENABLED 0x8622
|
||||
#define GL_VERTEX_ATTRIB_ARRAY_SIZE 0x8623
|
||||
#define GL_VERTEX_ATTRIB_ARRAY_STRIDE 0x8624
|
||||
#define GL_VERTEX_ATTRIB_ARRAY_TYPE 0x8625
|
||||
#define GL_VERTEX_ATTRIB_ARRAY_NORMALIZED 0x886A
|
||||
#define GL_VERTEX_ATTRIB_ARRAY_POINTER 0x8645
|
||||
#define GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING 0x889F
|
||||
|
||||
/* Read Format */
|
||||
#define GL_IMPLEMENTATION_COLOR_READ_TYPE 0x8B9A
|
||||
#define GL_IMPLEMENTATION_COLOR_READ_TYPE 0x8B9A
|
||||
#define GL_IMPLEMENTATION_COLOR_READ_FORMAT 0x8B9B
|
||||
|
||||
/* Shader Source */
|
||||
#define GL_COMPILE_STATUS 0x8B81
|
||||
#define GL_INFO_LOG_LENGTH 0x8B84
|
||||
#define GL_SHADER_SOURCE_LENGTH 0x8B88
|
||||
#define GL_SHADER_COMPILER 0x8DFA
|
||||
|
||||
/* Shader Binary */
|
||||
#define GL_SHADER_BINARY_FORMATS 0x8DF8
|
||||
#define GL_NUM_SHADER_BINARY_FORMATS 0x8DF9
|
||||
|
||||
/* Shader Precision-Specified Types */
|
||||
#define GL_LOW_FLOAT 0x8DF0
|
||||
#define GL_MEDIUM_FLOAT 0x8DF1
|
||||
#define GL_HIGH_FLOAT 0x8DF2
|
||||
#define GL_LOW_INT 0x8DF3
|
||||
#define GL_MEDIUM_INT 0x8DF4
|
||||
#define GL_HIGH_INT 0x8DF5
|
||||
|
||||
/* Framebuffer Object. */
|
||||
#define GL_FRAMEBUFFER 0x8D40
|
||||
#define GL_RENDERBUFFER 0x8D41
|
||||
|
||||
#define GL_RGBA4 0x8056
|
||||
#define GL_RGB5_A1 0x8057
|
||||
#define GL_RGB565 0x8D62
|
||||
#define GL_DEPTH_COMPONENT16 0x81A5
|
||||
#define GL_STENCIL_INDEX 0x1901
|
||||
#define GL_STENCIL_INDEX8 0x8D48
|
||||
|
||||
#define GL_RENDERBUFFER_WIDTH 0x8D42
|
||||
#define GL_RENDERBUFFER_HEIGHT 0x8D43
|
||||
#define GL_RENDERBUFFER_INTERNAL_FORMAT 0x8D44
|
||||
@@ -443,179 +357,169 @@ typedef khronos_ssize_t GLsizeiptr;
|
||||
#define GL_RENDERBUFFER_ALPHA_SIZE 0x8D53
|
||||
#define GL_RENDERBUFFER_DEPTH_SIZE 0x8D54
|
||||
#define GL_RENDERBUFFER_STENCIL_SIZE 0x8D55
|
||||
|
||||
#define GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE 0x8CD0
|
||||
#define GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME 0x8CD1
|
||||
#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL 0x8CD2
|
||||
#define GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE 0x8CD0
|
||||
#define GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME 0x8CD1
|
||||
#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL 0x8CD2
|
||||
#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE 0x8CD3
|
||||
|
||||
#define GL_COLOR_ATTACHMENT0 0x8CE0
|
||||
#define GL_DEPTH_ATTACHMENT 0x8D00
|
||||
#define GL_STENCIL_ATTACHMENT 0x8D20
|
||||
|
||||
#define GL_NONE 0
|
||||
|
||||
#define GL_FRAMEBUFFER_COMPLETE 0x8CD5
|
||||
#define GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT 0x8CD6
|
||||
#define GL_FRAMEBUFFER_COMPLETE 0x8CD5
|
||||
#define GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT 0x8CD6
|
||||
#define GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT 0x8CD7
|
||||
#define GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS 0x8CD9
|
||||
#define GL_FRAMEBUFFER_UNSUPPORTED 0x8CDD
|
||||
|
||||
#define GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS 0x8CD9
|
||||
#define GL_FRAMEBUFFER_UNSUPPORTED 0x8CDD
|
||||
#define GL_FRAMEBUFFER_BINDING 0x8CA6
|
||||
#define GL_RENDERBUFFER_BINDING 0x8CA7
|
||||
#define GL_MAX_RENDERBUFFER_SIZE 0x84E8
|
||||
|
||||
#define GL_INVALID_FRAMEBUFFER_OPERATION 0x0506
|
||||
|
||||
/*-------------------------------------------------------------------------
|
||||
* GL core functions.
|
||||
*-----------------------------------------------------------------------*/
|
||||
|
||||
GL_APICALL void GL_APIENTRY glActiveTexture (GLenum texture);
|
||||
GL_APICALL void GL_APIENTRY glAttachShader (GLuint program, GLuint shader);
|
||||
GL_APICALL void GL_APIENTRY glBindAttribLocation (GLuint program, GLuint index, const GLchar* name);
|
||||
GL_APICALL void GL_APIENTRY glBindBuffer (GLenum target, GLuint buffer);
|
||||
GL_APICALL void GL_APIENTRY glBindFramebuffer (GLenum target, GLuint framebuffer);
|
||||
GL_APICALL void GL_APIENTRY glBindRenderbuffer (GLenum target, GLuint renderbuffer);
|
||||
GL_APICALL void GL_APIENTRY glBindTexture (GLenum target, GLuint texture);
|
||||
GL_APICALL void GL_APIENTRY glBlendColor (GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha);
|
||||
GL_APICALL void GL_APIENTRY glBlendEquation ( GLenum mode );
|
||||
GL_APICALL void GL_APIENTRY glBlendEquationSeparate (GLenum modeRGB, GLenum modeAlpha);
|
||||
GL_APICALL void GL_APIENTRY glBlendFunc (GLenum sfactor, GLenum dfactor);
|
||||
GL_APICALL void GL_APIENTRY glBlendFuncSeparate (GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, GLenum dstAlpha);
|
||||
GL_APICALL void GL_APIENTRY glBufferData (GLenum target, GLsizeiptr size, const GLvoid* data, GLenum usage);
|
||||
GL_APICALL void GL_APIENTRY glBufferSubData (GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid* data);
|
||||
GL_APICALL GLenum GL_APIENTRY glCheckFramebufferStatus (GLenum target);
|
||||
GL_APICALL void GL_APIENTRY glClear (GLbitfield mask);
|
||||
GL_APICALL void GL_APIENTRY glClearColor (GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha);
|
||||
GL_APICALL void GL_APIENTRY glClearDepthf (GLclampf depth);
|
||||
GL_APICALL void GL_APIENTRY glClearStencil (GLint s);
|
||||
GL_APICALL void GL_APIENTRY glColorMask (GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha);
|
||||
GL_APICALL void GL_APIENTRY glCompileShader (GLuint shader);
|
||||
GL_APICALL void GL_APIENTRY glCompressedTexImage2D (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const GLvoid* data);
|
||||
GL_APICALL void GL_APIENTRY glCompressedTexSubImage2D (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const GLvoid* data);
|
||||
GL_APICALL void GL_APIENTRY glCopyTexImage2D (GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border);
|
||||
GL_APICALL void GL_APIENTRY glCopyTexSubImage2D (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height);
|
||||
GL_APICALL GLuint GL_APIENTRY glCreateProgram (void);
|
||||
GL_APICALL GLuint GL_APIENTRY glCreateShader (GLenum type);
|
||||
GL_APICALL void GL_APIENTRY glCullFace (GLenum mode);
|
||||
GL_APICALL void GL_APIENTRY glDeleteBuffers (GLsizei n, const GLuint* buffers);
|
||||
GL_APICALL void GL_APIENTRY glDeleteFramebuffers (GLsizei n, const GLuint* framebuffers);
|
||||
GL_APICALL void GL_APIENTRY glDeleteProgram (GLuint program);
|
||||
GL_APICALL void GL_APIENTRY glDeleteRenderbuffers (GLsizei n, const GLuint* renderbuffers);
|
||||
GL_APICALL void GL_APIENTRY glDeleteShader (GLuint shader);
|
||||
GL_APICALL void GL_APIENTRY glDeleteTextures (GLsizei n, const GLuint* textures);
|
||||
GL_APICALL void GL_APIENTRY glDepthFunc (GLenum func);
|
||||
GL_APICALL void GL_APIENTRY glDepthMask (GLboolean flag);
|
||||
GL_APICALL void GL_APIENTRY glDepthRangef (GLclampf zNear, GLclampf zFar);
|
||||
GL_APICALL void GL_APIENTRY glDetachShader (GLuint program, GLuint shader);
|
||||
GL_APICALL void GL_APIENTRY glDisable (GLenum cap);
|
||||
GL_APICALL void GL_APIENTRY glDisableVertexAttribArray (GLuint index);
|
||||
GL_APICALL void GL_APIENTRY glDrawArrays (GLenum mode, GLint first, GLsizei count);
|
||||
GL_APICALL void GL_APIENTRY glDrawElements (GLenum mode, GLsizei count, GLenum type, const GLvoid* indices);
|
||||
GL_APICALL void GL_APIENTRY glEnable (GLenum cap);
|
||||
GL_APICALL void GL_APIENTRY glEnableVertexAttribArray (GLuint index);
|
||||
GL_APICALL void GL_APIENTRY glFinish (void);
|
||||
GL_APICALL void GL_APIENTRY glFlush (void);
|
||||
GL_APICALL void GL_APIENTRY glFramebufferRenderbuffer (GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer);
|
||||
GL_APICALL void GL_APIENTRY glFramebufferTexture2D (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level);
|
||||
GL_APICALL void GL_APIENTRY glFrontFace (GLenum mode);
|
||||
GL_APICALL void GL_APIENTRY glGenBuffers (GLsizei n, GLuint* buffers);
|
||||
GL_APICALL void GL_APIENTRY glGenerateMipmap (GLenum target);
|
||||
GL_APICALL void GL_APIENTRY glGenFramebuffers (GLsizei n, GLuint* framebuffers);
|
||||
GL_APICALL void GL_APIENTRY glGenRenderbuffers (GLsizei n, GLuint* renderbuffers);
|
||||
GL_APICALL void GL_APIENTRY glGenTextures (GLsizei n, GLuint* textures);
|
||||
GL_APICALL void GL_APIENTRY glGetActiveAttrib (GLuint program, GLuint index, GLsizei bufsize, GLsizei* length, GLint* size, GLenum* type, GLchar* name);
|
||||
GL_APICALL void GL_APIENTRY glGetActiveUniform (GLuint program, GLuint index, GLsizei bufsize, GLsizei* length, GLint* size, GLenum* type, GLchar* name);
|
||||
GL_APICALL void GL_APIENTRY glGetAttachedShaders (GLuint program, GLsizei maxcount, GLsizei* count, GLuint* shaders);
|
||||
GL_APICALL int GL_APIENTRY glGetAttribLocation (GLuint program, const GLchar* name);
|
||||
GL_APICALL void GL_APIENTRY glGetBooleanv (GLenum pname, GLboolean* params);
|
||||
GL_APICALL void GL_APIENTRY glGetBufferParameteriv (GLenum target, GLenum pname, GLint* params);
|
||||
GL_APICALL GLenum GL_APIENTRY glGetError (void);
|
||||
GL_APICALL void GL_APIENTRY glGetFloatv (GLenum pname, GLfloat* params);
|
||||
GL_APICALL void GL_APIENTRY glGetFramebufferAttachmentParameteriv (GLenum target, GLenum attachment, GLenum pname, GLint* params);
|
||||
GL_APICALL void GL_APIENTRY glGetIntegerv (GLenum pname, GLint* params);
|
||||
GL_APICALL void GL_APIENTRY glGetProgramiv (GLuint program, GLenum pname, GLint* params);
|
||||
GL_APICALL void GL_APIENTRY glGetProgramInfoLog (GLuint program, GLsizei bufsize, GLsizei* length, GLchar* infolog);
|
||||
GL_APICALL void GL_APIENTRY glGetRenderbufferParameteriv (GLenum target, GLenum pname, GLint* params);
|
||||
GL_APICALL void GL_APIENTRY glGetShaderiv (GLuint shader, GLenum pname, GLint* params);
|
||||
GL_APICALL void GL_APIENTRY glGetShaderInfoLog (GLuint shader, GLsizei bufsize, GLsizei* length, GLchar* infolog);
|
||||
GL_APICALL void GL_APIENTRY glGetShaderPrecisionFormat (GLenum shadertype, GLenum precisiontype, GLint* range, GLint* precision);
|
||||
GL_APICALL void GL_APIENTRY glGetShaderSource (GLuint shader, GLsizei bufsize, GLsizei* length, GLchar* source);
|
||||
GL_APICALL const GLubyte* GL_APIENTRY glGetString (GLenum name);
|
||||
GL_APICALL void GL_APIENTRY glGetTexParameterfv (GLenum target, GLenum pname, GLfloat* params);
|
||||
GL_APICALL void GL_APIENTRY glGetTexParameteriv (GLenum target, GLenum pname, GLint* params);
|
||||
GL_APICALL void GL_APIENTRY glGetUniformfv (GLuint program, GLint location, GLfloat* params);
|
||||
GL_APICALL void GL_APIENTRY glGetUniformiv (GLuint program, GLint location, GLint* params);
|
||||
GL_APICALL int GL_APIENTRY glGetUniformLocation (GLuint program, const GLchar* name);
|
||||
GL_APICALL void GL_APIENTRY glGetVertexAttribfv (GLuint index, GLenum pname, GLfloat* params);
|
||||
GL_APICALL void GL_APIENTRY glGetVertexAttribiv (GLuint index, GLenum pname, GLint* params);
|
||||
GL_APICALL void GL_APIENTRY glGetVertexAttribPointerv (GLuint index, GLenum pname, GLvoid** pointer);
|
||||
GL_APICALL void GL_APIENTRY glHint (GLenum target, GLenum mode);
|
||||
GL_APICALL GLboolean GL_APIENTRY glIsBuffer (GLuint buffer);
|
||||
GL_APICALL GLboolean GL_APIENTRY glIsEnabled (GLenum cap);
|
||||
GL_APICALL GLboolean GL_APIENTRY glIsFramebuffer (GLuint framebuffer);
|
||||
GL_APICALL GLboolean GL_APIENTRY glIsProgram (GLuint program);
|
||||
GL_APICALL GLboolean GL_APIENTRY glIsRenderbuffer (GLuint renderbuffer);
|
||||
GL_APICALL GLboolean GL_APIENTRY glIsShader (GLuint shader);
|
||||
GL_APICALL GLboolean GL_APIENTRY glIsTexture (GLuint texture);
|
||||
GL_APICALL void GL_APIENTRY glLineWidth (GLfloat width);
|
||||
GL_APICALL void GL_APIENTRY glLinkProgram (GLuint program);
|
||||
GL_APICALL void GL_APIENTRY glPixelStorei (GLenum pname, GLint param);
|
||||
GL_APICALL void GL_APIENTRY glPolygonOffset (GLfloat factor, GLfloat units);
|
||||
GL_APICALL void GL_APIENTRY glReadPixels (GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLvoid* pixels);
|
||||
GL_APICALL void GL_APIENTRY glReleaseShaderCompiler (void);
|
||||
GL_APICALL void GL_APIENTRY glRenderbufferStorage (GLenum target, GLenum internalformat, GLsizei width, GLsizei height);
|
||||
GL_APICALL void GL_APIENTRY glSampleCoverage (GLclampf value, GLboolean invert);
|
||||
GL_APICALL void GL_APIENTRY glScissor (GLint x, GLint y, GLsizei width, GLsizei height);
|
||||
GL_APICALL void GL_APIENTRY glShaderBinary (GLsizei n, const GLuint* shaders, GLenum binaryformat, const GLvoid* binary, GLsizei length);
|
||||
GL_APICALL void GL_APIENTRY glShaderSource (GLuint shader, GLsizei count, const GLchar** string, const GLint* length);
|
||||
GL_APICALL void GL_APIENTRY glStencilFunc (GLenum func, GLint ref, GLuint mask);
|
||||
GL_APICALL void GL_APIENTRY glStencilFuncSeparate (GLenum face, GLenum func, GLint ref, GLuint mask);
|
||||
GL_APICALL void GL_APIENTRY glStencilMask (GLuint mask);
|
||||
GL_APICALL void GL_APIENTRY glStencilMaskSeparate (GLenum face, GLuint mask);
|
||||
GL_APICALL void GL_APIENTRY glStencilOp (GLenum fail, GLenum zfail, GLenum zpass);
|
||||
GL_APICALL void GL_APIENTRY glStencilOpSeparate (GLenum face, GLenum fail, GLenum zfail, GLenum zpass);
|
||||
GL_APICALL void GL_APIENTRY glTexImage2D (GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const GLvoid* pixels);
|
||||
GL_APICALL void GL_APIENTRY glTexParameterf (GLenum target, GLenum pname, GLfloat param);
|
||||
GL_APICALL void GL_APIENTRY glTexParameterfv (GLenum target, GLenum pname, const GLfloat* params);
|
||||
GL_APICALL void GL_APIENTRY glTexParameteri (GLenum target, GLenum pname, GLint param);
|
||||
GL_APICALL void GL_APIENTRY glTexParameteriv (GLenum target, GLenum pname, const GLint* params);
|
||||
GL_APICALL void GL_APIENTRY glTexSubImage2D (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid* pixels);
|
||||
GL_APICALL void GL_APIENTRY glUniform1f (GLint location, GLfloat x);
|
||||
GL_APICALL void GL_APIENTRY glUniform1fv (GLint location, GLsizei count, const GLfloat* v);
|
||||
GL_APICALL void GL_APIENTRY glUniform1i (GLint location, GLint x);
|
||||
GL_APICALL void GL_APIENTRY glUniform1iv (GLint location, GLsizei count, const GLint* v);
|
||||
GL_APICALL void GL_APIENTRY glUniform2f (GLint location, GLfloat x, GLfloat y);
|
||||
GL_APICALL void GL_APIENTRY glUniform2fv (GLint location, GLsizei count, const GLfloat* v);
|
||||
GL_APICALL void GL_APIENTRY glUniform2i (GLint location, GLint x, GLint y);
|
||||
GL_APICALL void GL_APIENTRY glUniform2iv (GLint location, GLsizei count, const GLint* v);
|
||||
GL_APICALL void GL_APIENTRY glUniform3f (GLint location, GLfloat x, GLfloat y, GLfloat z);
|
||||
GL_APICALL void GL_APIENTRY glUniform3fv (GLint location, GLsizei count, const GLfloat* v);
|
||||
GL_APICALL void GL_APIENTRY glUniform3i (GLint location, GLint x, GLint y, GLint z);
|
||||
GL_APICALL void GL_APIENTRY glUniform3iv (GLint location, GLsizei count, const GLint* v);
|
||||
GL_APICALL void GL_APIENTRY glUniform4f (GLint location, GLfloat x, GLfloat y, GLfloat z, GLfloat w);
|
||||
GL_APICALL void GL_APIENTRY glUniform4fv (GLint location, GLsizei count, const GLfloat* v);
|
||||
GL_APICALL void GL_APIENTRY glUniform4i (GLint location, GLint x, GLint y, GLint z, GLint w);
|
||||
GL_APICALL void GL_APIENTRY glUniform4iv (GLint location, GLsizei count, const GLint* v);
|
||||
GL_APICALL void GL_APIENTRY glUniformMatrix2fv (GLint location, GLsizei count, GLboolean transpose, const GLfloat* value);
|
||||
GL_APICALL void GL_APIENTRY glUniformMatrix3fv (GLint location, GLsizei count, GLboolean transpose, const GLfloat* value);
|
||||
GL_APICALL void GL_APIENTRY glUniformMatrix4fv (GLint location, GLsizei count, GLboolean transpose, const GLfloat* value);
|
||||
GL_APICALL void GL_APIENTRY glUseProgram (GLuint program);
|
||||
GL_APICALL void GL_APIENTRY glValidateProgram (GLuint program);
|
||||
GL_APICALL void GL_APIENTRY glVertexAttrib1f (GLuint indx, GLfloat x);
|
||||
GL_APICALL void GL_APIENTRY glVertexAttrib1fv (GLuint indx, const GLfloat* values);
|
||||
GL_APICALL void GL_APIENTRY glVertexAttrib2f (GLuint indx, GLfloat x, GLfloat y);
|
||||
GL_APICALL void GL_APIENTRY glVertexAttrib2fv (GLuint indx, const GLfloat* values);
|
||||
GL_APICALL void GL_APIENTRY glVertexAttrib3f (GLuint indx, GLfloat x, GLfloat y, GLfloat z);
|
||||
GL_APICALL void GL_APIENTRY glVertexAttrib3fv (GLuint indx, const GLfloat* values);
|
||||
GL_APICALL void GL_APIENTRY glVertexAttrib4f (GLuint indx, GLfloat x, GLfloat y, GLfloat z, GLfloat w);
|
||||
GL_APICALL void GL_APIENTRY glVertexAttrib4fv (GLuint indx, const GLfloat* values);
|
||||
GL_APICALL void GL_APIENTRY glVertexAttribPointer (GLuint indx, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const GLvoid* ptr);
|
||||
GL_APICALL void GL_APIENTRY glViewport (GLint x, GLint y, GLsizei width, GLsizei height);
|
||||
|
||||
GL_APICALL void GL_APIENTRY glActiveTexture (GLenum texture);
|
||||
GL_APICALL void GL_APIENTRY glAttachShader (GLuint program, GLuint shader);
|
||||
GL_APICALL void GL_APIENTRY glBindAttribLocation (GLuint program, GLuint index, const GLchar *name);
|
||||
GL_APICALL void GL_APIENTRY glBindBuffer (GLenum target, GLuint buffer);
|
||||
GL_APICALL void GL_APIENTRY glBindFramebuffer (GLenum target, GLuint framebuffer);
|
||||
GL_APICALL void GL_APIENTRY glBindRenderbuffer (GLenum target, GLuint renderbuffer);
|
||||
GL_APICALL void GL_APIENTRY glBindTexture (GLenum target, GLuint texture);
|
||||
GL_APICALL void GL_APIENTRY glBlendColor (GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha);
|
||||
GL_APICALL void GL_APIENTRY glBlendEquation (GLenum mode);
|
||||
GL_APICALL void GL_APIENTRY glBlendEquationSeparate (GLenum modeRGB, GLenum modeAlpha);
|
||||
GL_APICALL void GL_APIENTRY glBlendFunc (GLenum sfactor, GLenum dfactor);
|
||||
GL_APICALL void GL_APIENTRY glBlendFuncSeparate (GLenum sfactorRGB, GLenum dfactorRGB, GLenum sfactorAlpha, GLenum dfactorAlpha);
|
||||
GL_APICALL void GL_APIENTRY glBufferData (GLenum target, GLsizeiptr size, const void *data, GLenum usage);
|
||||
GL_APICALL void GL_APIENTRY glBufferSubData (GLenum target, GLintptr offset, GLsizeiptr size, const void *data);
|
||||
GL_APICALL GLenum GL_APIENTRY glCheckFramebufferStatus (GLenum target);
|
||||
GL_APICALL void GL_APIENTRY glClear (GLbitfield mask);
|
||||
GL_APICALL void GL_APIENTRY glClearColor (GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha);
|
||||
GL_APICALL void GL_APIENTRY glClearDepthf (GLfloat d);
|
||||
GL_APICALL void GL_APIENTRY glClearStencil (GLint s);
|
||||
GL_APICALL void GL_APIENTRY glColorMask (GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha);
|
||||
GL_APICALL void GL_APIENTRY glCompileShader (GLuint shader);
|
||||
GL_APICALL void GL_APIENTRY glCompressedTexImage2D (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const void *data);
|
||||
GL_APICALL void GL_APIENTRY glCompressedTexSubImage2D (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void *data);
|
||||
GL_APICALL void GL_APIENTRY glCopyTexImage2D (GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border);
|
||||
GL_APICALL void GL_APIENTRY glCopyTexSubImage2D (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height);
|
||||
GL_APICALL GLuint GL_APIENTRY glCreateProgram (void);
|
||||
GL_APICALL GLuint GL_APIENTRY glCreateShader (GLenum type);
|
||||
GL_APICALL void GL_APIENTRY glCullFace (GLenum mode);
|
||||
GL_APICALL void GL_APIENTRY glDeleteBuffers (GLsizei n, const GLuint *buffers);
|
||||
GL_APICALL void GL_APIENTRY glDeleteFramebuffers (GLsizei n, const GLuint *framebuffers);
|
||||
GL_APICALL void GL_APIENTRY glDeleteProgram (GLuint program);
|
||||
GL_APICALL void GL_APIENTRY glDeleteRenderbuffers (GLsizei n, const GLuint *renderbuffers);
|
||||
GL_APICALL void GL_APIENTRY glDeleteShader (GLuint shader);
|
||||
GL_APICALL void GL_APIENTRY glDeleteTextures (GLsizei n, const GLuint *textures);
|
||||
GL_APICALL void GL_APIENTRY glDepthFunc (GLenum func);
|
||||
GL_APICALL void GL_APIENTRY glDepthMask (GLboolean flag);
|
||||
GL_APICALL void GL_APIENTRY glDepthRangef (GLfloat n, GLfloat f);
|
||||
GL_APICALL void GL_APIENTRY glDetachShader (GLuint program, GLuint shader);
|
||||
GL_APICALL void GL_APIENTRY glDisable (GLenum cap);
|
||||
GL_APICALL void GL_APIENTRY glDisableVertexAttribArray (GLuint index);
|
||||
GL_APICALL void GL_APIENTRY glDrawArrays (GLenum mode, GLint first, GLsizei count);
|
||||
GL_APICALL void GL_APIENTRY glDrawElements (GLenum mode, GLsizei count, GLenum type, const void *indices);
|
||||
GL_APICALL void GL_APIENTRY glEnable (GLenum cap);
|
||||
GL_APICALL void GL_APIENTRY glEnableVertexAttribArray (GLuint index);
|
||||
GL_APICALL void GL_APIENTRY glFinish (void);
|
||||
GL_APICALL void GL_APIENTRY glFlush (void);
|
||||
GL_APICALL void GL_APIENTRY glFramebufferRenderbuffer (GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer);
|
||||
GL_APICALL void GL_APIENTRY glFramebufferTexture2D (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level);
|
||||
GL_APICALL void GL_APIENTRY glFrontFace (GLenum mode);
|
||||
GL_APICALL void GL_APIENTRY glGenBuffers (GLsizei n, GLuint *buffers);
|
||||
GL_APICALL void GL_APIENTRY glGenerateMipmap (GLenum target);
|
||||
GL_APICALL void GL_APIENTRY glGenFramebuffers (GLsizei n, GLuint *framebuffers);
|
||||
GL_APICALL void GL_APIENTRY glGenRenderbuffers (GLsizei n, GLuint *renderbuffers);
|
||||
GL_APICALL void GL_APIENTRY glGenTextures (GLsizei n, GLuint *textures);
|
||||
GL_APICALL void GL_APIENTRY glGetActiveAttrib (GLuint program, GLuint index, GLsizei bufSize, GLsizei *length, GLint *size, GLenum *type, GLchar *name);
|
||||
GL_APICALL void GL_APIENTRY glGetActiveUniform (GLuint program, GLuint index, GLsizei bufSize, GLsizei *length, GLint *size, GLenum *type, GLchar *name);
|
||||
GL_APICALL void GL_APIENTRY glGetAttachedShaders (GLuint program, GLsizei maxCount, GLsizei *count, GLuint *shaders);
|
||||
GL_APICALL GLint GL_APIENTRY glGetAttribLocation (GLuint program, const GLchar *name);
|
||||
GL_APICALL void GL_APIENTRY glGetBooleanv (GLenum pname, GLboolean *data);
|
||||
GL_APICALL void GL_APIENTRY glGetBufferParameteriv (GLenum target, GLenum pname, GLint *params);
|
||||
GL_APICALL GLenum GL_APIENTRY glGetError (void);
|
||||
GL_APICALL void GL_APIENTRY glGetFloatv (GLenum pname, GLfloat *data);
|
||||
GL_APICALL void GL_APIENTRY glGetFramebufferAttachmentParameteriv (GLenum target, GLenum attachment, GLenum pname, GLint *params);
|
||||
GL_APICALL void GL_APIENTRY glGetIntegerv (GLenum pname, GLint *data);
|
||||
GL_APICALL void GL_APIENTRY glGetProgramiv (GLuint program, GLenum pname, GLint *params);
|
||||
GL_APICALL void GL_APIENTRY glGetProgramInfoLog (GLuint program, GLsizei bufSize, GLsizei *length, GLchar *infoLog);
|
||||
GL_APICALL void GL_APIENTRY glGetRenderbufferParameteriv (GLenum target, GLenum pname, GLint *params);
|
||||
GL_APICALL void GL_APIENTRY glGetShaderiv (GLuint shader, GLenum pname, GLint *params);
|
||||
GL_APICALL void GL_APIENTRY glGetShaderInfoLog (GLuint shader, GLsizei bufSize, GLsizei *length, GLchar *infoLog);
|
||||
GL_APICALL void GL_APIENTRY glGetShaderPrecisionFormat (GLenum shadertype, GLenum precisiontype, GLint *range, GLint *precision);
|
||||
GL_APICALL void GL_APIENTRY glGetShaderSource (GLuint shader, GLsizei bufSize, GLsizei *length, GLchar *source);
|
||||
GL_APICALL const GLubyte *GL_APIENTRY glGetString (GLenum name);
|
||||
GL_APICALL void GL_APIENTRY glGetTexParameterfv (GLenum target, GLenum pname, GLfloat *params);
|
||||
GL_APICALL void GL_APIENTRY glGetTexParameteriv (GLenum target, GLenum pname, GLint *params);
|
||||
GL_APICALL void GL_APIENTRY glGetUniformfv (GLuint program, GLint location, GLfloat *params);
|
||||
GL_APICALL void GL_APIENTRY glGetUniformiv (GLuint program, GLint location, GLint *params);
|
||||
GL_APICALL GLint GL_APIENTRY glGetUniformLocation (GLuint program, const GLchar *name);
|
||||
GL_APICALL void GL_APIENTRY glGetVertexAttribfv (GLuint index, GLenum pname, GLfloat *params);
|
||||
GL_APICALL void GL_APIENTRY glGetVertexAttribiv (GLuint index, GLenum pname, GLint *params);
|
||||
GL_APICALL void GL_APIENTRY glGetVertexAttribPointerv (GLuint index, GLenum pname, void **pointer);
|
||||
GL_APICALL void GL_APIENTRY glHint (GLenum target, GLenum mode);
|
||||
GL_APICALL GLboolean GL_APIENTRY glIsBuffer (GLuint buffer);
|
||||
GL_APICALL GLboolean GL_APIENTRY glIsEnabled (GLenum cap);
|
||||
GL_APICALL GLboolean GL_APIENTRY glIsFramebuffer (GLuint framebuffer);
|
||||
GL_APICALL GLboolean GL_APIENTRY glIsProgram (GLuint program);
|
||||
GL_APICALL GLboolean GL_APIENTRY glIsRenderbuffer (GLuint renderbuffer);
|
||||
GL_APICALL GLboolean GL_APIENTRY glIsShader (GLuint shader);
|
||||
GL_APICALL GLboolean GL_APIENTRY glIsTexture (GLuint texture);
|
||||
GL_APICALL void GL_APIENTRY glLineWidth (GLfloat width);
|
||||
GL_APICALL void GL_APIENTRY glLinkProgram (GLuint program);
|
||||
GL_APICALL void GL_APIENTRY glPixelStorei (GLenum pname, GLint param);
|
||||
GL_APICALL void GL_APIENTRY glPolygonOffset (GLfloat factor, GLfloat units);
|
||||
GL_APICALL void GL_APIENTRY glReadPixels (GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, void *pixels);
|
||||
GL_APICALL void GL_APIENTRY glReleaseShaderCompiler (void);
|
||||
GL_APICALL void GL_APIENTRY glRenderbufferStorage (GLenum target, GLenum internalformat, GLsizei width, GLsizei height);
|
||||
GL_APICALL void GL_APIENTRY glSampleCoverage (GLfloat value, GLboolean invert);
|
||||
GL_APICALL void GL_APIENTRY glScissor (GLint x, GLint y, GLsizei width, GLsizei height);
|
||||
GL_APICALL void GL_APIENTRY glShaderBinary (GLsizei count, const GLuint *shaders, GLenum binaryformat, const void *binary, GLsizei length);
|
||||
GL_APICALL void GL_APIENTRY glShaderSource (GLuint shader, GLsizei count, const GLchar *const*string, const GLint *length);
|
||||
GL_APICALL void GL_APIENTRY glStencilFunc (GLenum func, GLint ref, GLuint mask);
|
||||
GL_APICALL void GL_APIENTRY glStencilFuncSeparate (GLenum face, GLenum func, GLint ref, GLuint mask);
|
||||
GL_APICALL void GL_APIENTRY glStencilMask (GLuint mask);
|
||||
GL_APICALL void GL_APIENTRY glStencilMaskSeparate (GLenum face, GLuint mask);
|
||||
GL_APICALL void GL_APIENTRY glStencilOp (GLenum fail, GLenum zfail, GLenum zpass);
|
||||
GL_APICALL void GL_APIENTRY glStencilOpSeparate (GLenum face, GLenum sfail, GLenum dpfail, GLenum dppass);
|
||||
GL_APICALL void GL_APIENTRY glTexImage2D (GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const void *pixels);
|
||||
GL_APICALL void GL_APIENTRY glTexParameterf (GLenum target, GLenum pname, GLfloat param);
|
||||
GL_APICALL void GL_APIENTRY glTexParameterfv (GLenum target, GLenum pname, const GLfloat *params);
|
||||
GL_APICALL void GL_APIENTRY glTexParameteri (GLenum target, GLenum pname, GLint param);
|
||||
GL_APICALL void GL_APIENTRY glTexParameteriv (GLenum target, GLenum pname, const GLint *params);
|
||||
GL_APICALL void GL_APIENTRY glTexSubImage2D (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const void *pixels);
|
||||
GL_APICALL void GL_APIENTRY glUniform1f (GLint location, GLfloat v0);
|
||||
GL_APICALL void GL_APIENTRY glUniform1fv (GLint location, GLsizei count, const GLfloat *value);
|
||||
GL_APICALL void GL_APIENTRY glUniform1i (GLint location, GLint v0);
|
||||
GL_APICALL void GL_APIENTRY glUniform1iv (GLint location, GLsizei count, const GLint *value);
|
||||
GL_APICALL void GL_APIENTRY glUniform2f (GLint location, GLfloat v0, GLfloat v1);
|
||||
GL_APICALL void GL_APIENTRY glUniform2fv (GLint location, GLsizei count, const GLfloat *value);
|
||||
GL_APICALL void GL_APIENTRY glUniform2i (GLint location, GLint v0, GLint v1);
|
||||
GL_APICALL void GL_APIENTRY glUniform2iv (GLint location, GLsizei count, const GLint *value);
|
||||
GL_APICALL void GL_APIENTRY glUniform3f (GLint location, GLfloat v0, GLfloat v1, GLfloat v2);
|
||||
GL_APICALL void GL_APIENTRY glUniform3fv (GLint location, GLsizei count, const GLfloat *value);
|
||||
GL_APICALL void GL_APIENTRY glUniform3i (GLint location, GLint v0, GLint v1, GLint v2);
|
||||
GL_APICALL void GL_APIENTRY glUniform3iv (GLint location, GLsizei count, const GLint *value);
|
||||
GL_APICALL void GL_APIENTRY glUniform4f (GLint location, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3);
|
||||
GL_APICALL void GL_APIENTRY glUniform4fv (GLint location, GLsizei count, const GLfloat *value);
|
||||
GL_APICALL void GL_APIENTRY glUniform4i (GLint location, GLint v0, GLint v1, GLint v2, GLint v3);
|
||||
GL_APICALL void GL_APIENTRY glUniform4iv (GLint location, GLsizei count, const GLint *value);
|
||||
GL_APICALL void GL_APIENTRY glUniformMatrix2fv (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
|
||||
GL_APICALL void GL_APIENTRY glUniformMatrix3fv (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
|
||||
GL_APICALL void GL_APIENTRY glUniformMatrix4fv (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
|
||||
GL_APICALL void GL_APIENTRY glUseProgram (GLuint program);
|
||||
GL_APICALL void GL_APIENTRY glValidateProgram (GLuint program);
|
||||
GL_APICALL void GL_APIENTRY glVertexAttrib1f (GLuint index, GLfloat x);
|
||||
GL_APICALL void GL_APIENTRY glVertexAttrib1fv (GLuint index, const GLfloat *v);
|
||||
GL_APICALL void GL_APIENTRY glVertexAttrib2f (GLuint index, GLfloat x, GLfloat y);
|
||||
GL_APICALL void GL_APIENTRY glVertexAttrib2fv (GLuint index, const GLfloat *v);
|
||||
GL_APICALL void GL_APIENTRY glVertexAttrib3f (GLuint index, GLfloat x, GLfloat y, GLfloat z);
|
||||
GL_APICALL void GL_APIENTRY glVertexAttrib3fv (GLuint index, const GLfloat *v);
|
||||
GL_APICALL void GL_APIENTRY glVertexAttrib4f (GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w);
|
||||
GL_APICALL void GL_APIENTRY glVertexAttrib4fv (GLuint index, const GLfloat *v);
|
||||
GL_APICALL void GL_APIENTRY glVertexAttribPointer (GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const void *pointer);
|
||||
GL_APICALL void GL_APIENTRY glViewport (GLint x, GLint y, GLsizei width, GLsizei height);
|
||||
#endif /* GL_ES_VERSION_2_0 */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __gl2_h_ */
|
||||
#endif
|
||||
+1358
-1054
File diff suppressed because it is too large.
Load diff
@@ -1,7 +1,7 @@
|
||||
#ifndef __gl2platform_h_
|
||||
#define __gl2platform_h_
|
||||
|
||||
/* $Revision: 10602 $ on $Date:: 2010-03-04 22:35:34 -0800 #$ */
|
||||
/* $Revision: 23328 $ on $Date:: 2013-10-02 02:28:28 -0700 #$ */
|
||||
|
||||
/*
|
||||
* This document is licensed under the SGI Free Software B License Version
|
||||
@@ -27,4 +27,4 @@
|
||||
#define GL_APIENTRY KHRONOS_APIENTRY
|
||||
#endif
|
||||
|
||||
#endif /* __gl2platform_h_ */
|
||||
#endif /* __gl2platform_h_ */
|
||||
File diff suppressed because it is too large.
Load diff
@@ -0,0 +1,939 @@
|
||||
#ifndef __gl3_h_
|
||||
#define __gl3_h_
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*
|
||||
** Copyright (c) 2013 The Khronos Group Inc.
|
||||
**
|
||||
** Permission is hereby granted, free of charge, to any person obtaining a
|
||||
** copy of this software and/or associated documentation files (the
|
||||
** "Materials"), to deal in the Materials without restriction, including
|
||||
** without limitation the rights to use, copy, modify, merge, publish,
|
||||
** distribute, sublicense, and/or sell copies of the Materials, and to
|
||||
** permit persons to whom the Materials are 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 Materials.
|
||||
**
|
||||
** THE MATERIALS ARE 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
|
||||
** MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
|
||||
*/
|
||||
/*
|
||||
** This header is generated from the Khronos OpenGL / OpenGL ES XML
|
||||
** API Registry. The current version of the Registry, generator scripts
|
||||
** used to make the header, and the header can be found at
|
||||
** http://www.opengl.org/registry/
|
||||
**
|
||||
** Khronos $Revision: 24614 $ on $Date: 2013-12-30 04:44:46 -0800 (Mon, 30 Dec 2013) $
|
||||
*/
|
||||
|
||||
#include <GLES3/gl3platform.h>
|
||||
|
||||
/* Generated on date 20131230 */
|
||||
|
||||
/* Generated C header for:
|
||||
* API: gles2
|
||||
* Profile: common
|
||||
* Versions considered: [23]\.[0-9]
|
||||
* Versions emitted: .*
|
||||
* Default extensions included: None
|
||||
* Additional extensions included: _nomatch_^
|
||||
* Extensions removed: _nomatch_^
|
||||
*/
|
||||
|
||||
#ifndef GL_ES_VERSION_2_0
|
||||
#define GL_ES_VERSION_2_0 1
|
||||
#include <KHR/khrplatform.h>
|
||||
typedef khronos_int8_t GLbyte;
|
||||
typedef khronos_float_t GLclampf;
|
||||
typedef khronos_int32_t GLfixed;
|
||||
typedef short GLshort;
|
||||
typedef unsigned short GLushort;
|
||||
typedef void GLvoid;
|
||||
typedef struct __GLsync *GLsync;
|
||||
typedef khronos_int64_t GLint64;
|
||||
typedef khronos_uint64_t GLuint64;
|
||||
typedef unsigned int GLenum;
|
||||
typedef unsigned int GLuint;
|
||||
typedef char GLchar;
|
||||
typedef khronos_float_t GLfloat;
|
||||
typedef khronos_ssize_t GLsizeiptr;
|
||||
typedef khronos_intptr_t GLintptr;
|
||||
typedef unsigned int GLbitfield;
|
||||
typedef int GLint;
|
||||
typedef unsigned char GLboolean;
|
||||
typedef int GLsizei;
|
||||
typedef khronos_uint8_t GLubyte;
|
||||
#define GL_DEPTH_BUFFER_BIT 0x00000100
|
||||
#define GL_STENCIL_BUFFER_BIT 0x00000400
|
||||
#define GL_COLOR_BUFFER_BIT 0x00004000
|
||||
#define GL_FALSE 0
|
||||
#define GL_TRUE 1
|
||||
#define GL_POINTS 0x0000
|
||||
#define GL_LINES 0x0001
|
||||
#define GL_LINE_LOOP 0x0002
|
||||
#define GL_LINE_STRIP 0x0003
|
||||
#define GL_TRIANGLES 0x0004
|
||||
#define GL_TRIANGLE_STRIP 0x0005
|
||||
#define GL_TRIANGLE_FAN 0x0006
|
||||
#define GL_ZERO 0
|
||||
#define GL_ONE 1
|
||||
#define GL_SRC_COLOR 0x0300
|
||||
#define GL_ONE_MINUS_SRC_COLOR 0x0301
|
||||
#define GL_SRC_ALPHA 0x0302
|
||||
#define GL_ONE_MINUS_SRC_ALPHA 0x0303
|
||||
#define GL_DST_ALPHA 0x0304
|
||||
#define GL_ONE_MINUS_DST_ALPHA 0x0305
|
||||
#define GL_DST_COLOR 0x0306
|
||||
#define GL_ONE_MINUS_DST_COLOR 0x0307
|
||||
#define GL_SRC_ALPHA_SATURATE 0x0308
|
||||
#define GL_FUNC_ADD 0x8006
|
||||
#define GL_BLEND_EQUATION 0x8009
|
||||
#define GL_BLEND_EQUATION_RGB 0x8009
|
||||
#define GL_BLEND_EQUATION_ALPHA 0x883D
|
||||
#define GL_FUNC_SUBTRACT 0x800A
|
||||
#define GL_FUNC_REVERSE_SUBTRACT 0x800B
|
||||
#define GL_BLEND_DST_RGB 0x80C8
|
||||
#define GL_BLEND_SRC_RGB 0x80C9
|
||||
#define GL_BLEND_DST_ALPHA 0x80CA
|
||||
#define GL_BLEND_SRC_ALPHA 0x80CB
|
||||
#define GL_CONSTANT_COLOR 0x8001
|
||||
#define GL_ONE_MINUS_CONSTANT_COLOR 0x8002
|
||||
#define GL_CONSTANT_ALPHA 0x8003
|
||||
#define GL_ONE_MINUS_CONSTANT_ALPHA 0x8004
|
||||
#define GL_BLEND_COLOR 0x8005
|
||||
#define GL_ARRAY_BUFFER 0x8892
|
||||
#define GL_ELEMENT_ARRAY_BUFFER 0x8893
|
||||
#define GL_ARRAY_BUFFER_BINDING 0x8894
|
||||
#define GL_ELEMENT_ARRAY_BUFFER_BINDING 0x8895
|
||||
#define GL_STREAM_DRAW 0x88E0
|
||||
#define GL_STATIC_DRAW 0x88E4
|
||||
#define GL_DYNAMIC_DRAW 0x88E8
|
||||
#define GL_BUFFER_SIZE 0x8764
|
||||
#define GL_BUFFER_USAGE 0x8765
|
||||
#define GL_CURRENT_VERTEX_ATTRIB 0x8626
|
||||
#define GL_FRONT 0x0404
|
||||
#define GL_BACK 0x0405
|
||||
#define GL_FRONT_AND_BACK 0x0408
|
||||
#define GL_TEXTURE_2D 0x0DE1
|
||||
#define GL_CULL_FACE 0x0B44
|
||||
#define GL_BLEND 0x0BE2
|
||||
#define GL_DITHER 0x0BD0
|
||||
#define GL_STENCIL_TEST 0x0B90
|
||||
#define GL_DEPTH_TEST 0x0B71
|
||||
#define GL_SCISSOR_TEST 0x0C11
|
||||
#define GL_POLYGON_OFFSET_FILL 0x8037
|
||||
#define GL_SAMPLE_ALPHA_TO_COVERAGE 0x809E
|
||||
#define GL_SAMPLE_COVERAGE 0x80A0
|
||||
#define GL_NO_ERROR 0
|
||||
#define GL_INVALID_ENUM 0x0500
|
||||
#define GL_INVALID_VALUE 0x0501
|
||||
#define GL_INVALID_OPERATION 0x0502
|
||||
#define GL_OUT_OF_MEMORY 0x0505
|
||||
#define GL_CW 0x0900
|
||||
#define GL_CCW 0x0901
|
||||
#define GL_LINE_WIDTH 0x0B21
|
||||
#define GL_ALIASED_POINT_SIZE_RANGE 0x846D
|
||||
#define GL_ALIASED_LINE_WIDTH_RANGE 0x846E
|
||||
#define GL_CULL_FACE_MODE 0x0B45
|
||||
#define GL_FRONT_FACE 0x0B46
|
||||
#define GL_DEPTH_RANGE 0x0B70
|
||||
#define GL_DEPTH_WRITEMASK 0x0B72
|
||||
#define GL_DEPTH_CLEAR_VALUE 0x0B73
|
||||
#define GL_DEPTH_FUNC 0x0B74
|
||||
#define GL_STENCIL_CLEAR_VALUE 0x0B91
|
||||
#define GL_STENCIL_FUNC 0x0B92
|
||||
#define GL_STENCIL_FAIL 0x0B94
|
||||
#define GL_STENCIL_PASS_DEPTH_FAIL 0x0B95
|
||||
#define GL_STENCIL_PASS_DEPTH_PASS 0x0B96
|
||||
#define GL_STENCIL_REF 0x0B97
|
||||
#define GL_STENCIL_VALUE_MASK 0x0B93
|
||||
#define GL_STENCIL_WRITEMASK 0x0B98
|
||||
#define GL_STENCIL_BACK_FUNC 0x8800
|
||||
#define GL_STENCIL_BACK_FAIL 0x8801
|
||||
#define GL_STENCIL_BACK_PASS_DEPTH_FAIL 0x8802
|
||||
#define GL_STENCIL_BACK_PASS_DEPTH_PASS 0x8803
|
||||
#define GL_STENCIL_BACK_REF 0x8CA3
|
||||
#define GL_STENCIL_BACK_VALUE_MASK 0x8CA4
|
||||
#define GL_STENCIL_BACK_WRITEMASK 0x8CA5
|
||||
#define GL_VIEWPORT 0x0BA2
|
||||
#define GL_SCISSOR_BOX 0x0C10
|
||||
#define GL_COLOR_CLEAR_VALUE 0x0C22
|
||||
#define GL_COLOR_WRITEMASK 0x0C23
|
||||
#define GL_UNPACK_ALIGNMENT 0x0CF5
|
||||
#define GL_PACK_ALIGNMENT 0x0D05
|
||||
#define GL_MAX_TEXTURE_SIZE 0x0D33
|
||||
#define GL_MAX_VIEWPORT_DIMS 0x0D3A
|
||||
#define GL_SUBPIXEL_BITS 0x0D50
|
||||
#define GL_RED_BITS 0x0D52
|
||||
#define GL_GREEN_BITS 0x0D53
|
||||
#define GL_BLUE_BITS 0x0D54
|
||||
#define GL_ALPHA_BITS 0x0D55
|
||||
#define GL_DEPTH_BITS 0x0D56
|
||||
#define GL_STENCIL_BITS 0x0D57
|
||||
#define GL_POLYGON_OFFSET_UNITS 0x2A00
|
||||
#define GL_POLYGON_OFFSET_FACTOR 0x8038
|
||||
#define GL_TEXTURE_BINDING_2D 0x8069
|
||||
#define GL_SAMPLE_BUFFERS 0x80A8
|
||||
#define GL_SAMPLES 0x80A9
|
||||
#define GL_SAMPLE_COVERAGE_VALUE 0x80AA
|
||||
#define GL_SAMPLE_COVERAGE_INVERT 0x80AB
|
||||
#define GL_NUM_COMPRESSED_TEXTURE_FORMATS 0x86A2
|
||||
#define GL_COMPRESSED_TEXTURE_FORMATS 0x86A3
|
||||
#define GL_DONT_CARE 0x1100
|
||||
#define GL_FASTEST 0x1101
|
||||
#define GL_NICEST 0x1102
|
||||
#define GL_GENERATE_MIPMAP_HINT 0x8192
|
||||
#define GL_BYTE 0x1400
|
||||
#define GL_UNSIGNED_BYTE 0x1401
|
||||
#define GL_SHORT 0x1402
|
||||
#define GL_UNSIGNED_SHORT 0x1403
|
||||
#define GL_INT 0x1404
|
||||
#define GL_UNSIGNED_INT 0x1405
|
||||
#define GL_FLOAT 0x1406
|
||||
#define GL_FIXED 0x140C
|
||||
#define GL_DEPTH_COMPONENT 0x1902
|
||||
#define GL_ALPHA 0x1906
|
||||
#define GL_RGB 0x1907
|
||||
#define GL_RGBA 0x1908
|
||||
#define GL_LUMINANCE 0x1909
|
||||
#define GL_LUMINANCE_ALPHA 0x190A
|
||||
#define GL_UNSIGNED_SHORT_4_4_4_4 0x8033
|
||||
#define GL_UNSIGNED_SHORT_5_5_5_1 0x8034
|
||||
#define GL_UNSIGNED_SHORT_5_6_5 0x8363
|
||||
#define GL_FRAGMENT_SHADER 0x8B30
|
||||
#define GL_VERTEX_SHADER 0x8B31
|
||||
#define GL_MAX_VERTEX_ATTRIBS 0x8869
|
||||
#define GL_MAX_VERTEX_UNIFORM_VECTORS 0x8DFB
|
||||
#define GL_MAX_VARYING_VECTORS 0x8DFC
|
||||
#define GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS 0x8B4D
|
||||
#define GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS 0x8B4C
|
||||
#define GL_MAX_TEXTURE_IMAGE_UNITS 0x8872
|
||||
#define GL_MAX_FRAGMENT_UNIFORM_VECTORS 0x8DFD
|
||||
#define GL_SHADER_TYPE 0x8B4F
|
||||
#define GL_DELETE_STATUS 0x8B80
|
||||
#define GL_LINK_STATUS 0x8B82
|
||||
#define GL_VALIDATE_STATUS 0x8B83
|
||||
#define GL_ATTACHED_SHADERS 0x8B85
|
||||
#define GL_ACTIVE_UNIFORMS 0x8B86
|
||||
#define GL_ACTIVE_UNIFORM_MAX_LENGTH 0x8B87
|
||||
#define GL_ACTIVE_ATTRIBUTES 0x8B89
|
||||
#define GL_ACTIVE_ATTRIBUTE_MAX_LENGTH 0x8B8A
|
||||
#define GL_SHADING_LANGUAGE_VERSION 0x8B8C
|
||||
#define GL_CURRENT_PROGRAM 0x8B8D
|
||||
#define GL_NEVER 0x0200
|
||||
#define GL_LESS 0x0201
|
||||
#define GL_EQUAL 0x0202
|
||||
#define GL_LEQUAL 0x0203
|
||||
#define GL_GREATER 0x0204
|
||||
#define GL_NOTEQUAL 0x0205
|
||||
#define GL_GEQUAL 0x0206
|
||||
#define GL_ALWAYS 0x0207
|
||||
#define GL_KEEP 0x1E00
|
||||
#define GL_REPLACE 0x1E01
|
||||
#define GL_INCR 0x1E02
|
||||
#define GL_DECR 0x1E03
|
||||
#define GL_INVERT 0x150A
|
||||
#define GL_INCR_WRAP 0x8507
|
||||
#define GL_DECR_WRAP 0x8508
|
||||
#define GL_VENDOR 0x1F00
|
||||
#define GL_RENDERER 0x1F01
|
||||
#define GL_VERSION 0x1F02
|
||||
#define GL_EXTENSIONS 0x1F03
|
||||
#define GL_NEAREST 0x2600
|
||||
#define GL_LINEAR 0x2601
|
||||
#define GL_NEAREST_MIPMAP_NEAREST 0x2700
|
||||
#define GL_LINEAR_MIPMAP_NEAREST 0x2701
|
||||
#define GL_NEAREST_MIPMAP_LINEAR 0x2702
|
||||
#define GL_LINEAR_MIPMAP_LINEAR 0x2703
|
||||
#define GL_TEXTURE_MAG_FILTER 0x2800
|
||||
#define GL_TEXTURE_MIN_FILTER 0x2801
|
||||
#define GL_TEXTURE_WRAP_S 0x2802
|
||||
#define GL_TEXTURE_WRAP_T 0x2803
|
||||
#define GL_TEXTURE 0x1702
|
||||
#define GL_TEXTURE_CUBE_MAP 0x8513
|
||||
#define GL_TEXTURE_BINDING_CUBE_MAP 0x8514
|
||||
#define GL_TEXTURE_CUBE_MAP_POSITIVE_X 0x8515
|
||||
#define GL_TEXTURE_CUBE_MAP_NEGATIVE_X 0x8516
|
||||
#define GL_TEXTURE_CUBE_MAP_POSITIVE_Y 0x8517
|
||||
#define GL_TEXTURE_CUBE_MAP_NEGATIVE_Y 0x8518
|
||||
#define GL_TEXTURE_CUBE_MAP_POSITIVE_Z 0x8519
|
||||
#define GL_TEXTURE_CUBE_MAP_NEGATIVE_Z 0x851A
|
||||
#define GL_MAX_CUBE_MAP_TEXTURE_SIZE 0x851C
|
||||
#define GL_TEXTURE0 0x84C0
|
||||
#define GL_TEXTURE1 0x84C1
|
||||
#define GL_TEXTURE2 0x84C2
|
||||
#define GL_TEXTURE3 0x84C3
|
||||
#define GL_TEXTURE4 0x84C4
|
||||
#define GL_TEXTURE5 0x84C5
|
||||
#define GL_TEXTURE6 0x84C6
|
||||
#define GL_TEXTURE7 0x84C7
|
||||
#define GL_TEXTURE8 0x84C8
|
||||
#define GL_TEXTURE9 0x84C9
|
||||
#define GL_TEXTURE10 0x84CA
|
||||
#define GL_TEXTURE11 0x84CB
|
||||
#define GL_TEXTURE12 0x84CC
|
||||
#define GL_TEXTURE13 0x84CD
|
||||
#define GL_TEXTURE14 0x84CE
|
||||
#define GL_TEXTURE15 0x84CF
|
||||
#define GL_TEXTURE16 0x84D0
|
||||
#define GL_TEXTURE17 0x84D1
|
||||
#define GL_TEXTURE18 0x84D2
|
||||
#define GL_TEXTURE19 0x84D3
|
||||
#define GL_TEXTURE20 0x84D4
|
||||
#define GL_TEXTURE21 0x84D5
|
||||
#define GL_TEXTURE22 0x84D6
|
||||
#define GL_TEXTURE23 0x84D7
|
||||
#define GL_TEXTURE24 0x84D8
|
||||
#define GL_TEXTURE25 0x84D9
|
||||
#define GL_TEXTURE26 0x84DA
|
||||
#define GL_TEXTURE27 0x84DB
|
||||
#define GL_TEXTURE28 0x84DC
|
||||
#define GL_TEXTURE29 0x84DD
|
||||
#define GL_TEXTURE30 0x84DE
|
||||
#define GL_TEXTURE31 0x84DF
|
||||
#define GL_ACTIVE_TEXTURE 0x84E0
|
||||
#define GL_REPEAT 0x2901
|
||||
#define GL_CLAMP_TO_EDGE 0x812F
|
||||
#define GL_MIRRORED_REPEAT 0x8370
|
||||
#define GL_FLOAT_VEC2 0x8B50
|
||||
#define GL_FLOAT_VEC3 0x8B51
|
||||
#define GL_FLOAT_VEC4 0x8B52
|
||||
#define GL_INT_VEC2 0x8B53
|
||||
#define GL_INT_VEC3 0x8B54
|
||||
#define GL_INT_VEC4 0x8B55
|
||||
#define GL_BOOL 0x8B56
|
||||
#define GL_BOOL_VEC2 0x8B57
|
||||
#define GL_BOOL_VEC3 0x8B58
|
||||
#define GL_BOOL_VEC4 0x8B59
|
||||
#define GL_FLOAT_MAT2 0x8B5A
|
||||
#define GL_FLOAT_MAT3 0x8B5B
|
||||
#define GL_FLOAT_MAT4 0x8B5C
|
||||
#define GL_SAMPLER_2D 0x8B5E
|
||||
#define GL_SAMPLER_CUBE 0x8B60
|
||||
#define GL_VERTEX_ATTRIB_ARRAY_ENABLED 0x8622
|
||||
#define GL_VERTEX_ATTRIB_ARRAY_SIZE 0x8623
|
||||
#define GL_VERTEX_ATTRIB_ARRAY_STRIDE 0x8624
|
||||
#define GL_VERTEX_ATTRIB_ARRAY_TYPE 0x8625
|
||||
#define GL_VERTEX_ATTRIB_ARRAY_NORMALIZED 0x886A
|
||||
#define GL_VERTEX_ATTRIB_ARRAY_POINTER 0x8645
|
||||
#define GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING 0x889F
|
||||
#define GL_IMPLEMENTATION_COLOR_READ_TYPE 0x8B9A
|
||||
#define GL_IMPLEMENTATION_COLOR_READ_FORMAT 0x8B9B
|
||||
#define GL_COMPILE_STATUS 0x8B81
|
||||
#define GL_INFO_LOG_LENGTH 0x8B84
|
||||
#define GL_SHADER_SOURCE_LENGTH 0x8B88
|
||||
#define GL_SHADER_COMPILER 0x8DFA
|
||||
#define GL_SHADER_BINARY_FORMATS 0x8DF8
|
||||
#define GL_NUM_SHADER_BINARY_FORMATS 0x8DF9
|
||||
#define GL_LOW_FLOAT 0x8DF0
|
||||
#define GL_MEDIUM_FLOAT 0x8DF1
|
||||
#define GL_HIGH_FLOAT 0x8DF2
|
||||
#define GL_LOW_INT 0x8DF3
|
||||
#define GL_MEDIUM_INT 0x8DF4
|
||||
#define GL_HIGH_INT 0x8DF5
|
||||
#define GL_FRAMEBUFFER 0x8D40
|
||||
#define GL_RENDERBUFFER 0x8D41
|
||||
#define GL_RGBA4 0x8056
|
||||
#define GL_RGB5_A1 0x8057
|
||||
#define GL_RGB565 0x8D62
|
||||
#define GL_DEPTH_COMPONENT16 0x81A5
|
||||
#define GL_STENCIL_INDEX8 0x8D48
|
||||
#define GL_RENDERBUFFER_WIDTH 0x8D42
|
||||
#define GL_RENDERBUFFER_HEIGHT 0x8D43
|
||||
#define GL_RENDERBUFFER_INTERNAL_FORMAT 0x8D44
|
||||
#define GL_RENDERBUFFER_RED_SIZE 0x8D50
|
||||
#define GL_RENDERBUFFER_GREEN_SIZE 0x8D51
|
||||
#define GL_RENDERBUFFER_BLUE_SIZE 0x8D52
|
||||
#define GL_RENDERBUFFER_ALPHA_SIZE 0x8D53
|
||||
#define GL_RENDERBUFFER_DEPTH_SIZE 0x8D54
|
||||
#define GL_RENDERBUFFER_STENCIL_SIZE 0x8D55
|
||||
#define GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE 0x8CD0
|
||||
#define GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME 0x8CD1
|
||||
#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL 0x8CD2
|
||||
#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE 0x8CD3
|
||||
#define GL_COLOR_ATTACHMENT0 0x8CE0
|
||||
#define GL_DEPTH_ATTACHMENT 0x8D00
|
||||
#define GL_STENCIL_ATTACHMENT 0x8D20
|
||||
#define GL_NONE 0
|
||||
#define GL_FRAMEBUFFER_COMPLETE 0x8CD5
|
||||
#define GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT 0x8CD6
|
||||
#define GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT 0x8CD7
|
||||
#define GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS 0x8CD9
|
||||
#define GL_FRAMEBUFFER_UNSUPPORTED 0x8CDD
|
||||
#define GL_FRAMEBUFFER_BINDING 0x8CA6
|
||||
#define GL_RENDERBUFFER_BINDING 0x8CA7
|
||||
#define GL_MAX_RENDERBUFFER_SIZE 0x84E8
|
||||
#define GL_INVALID_FRAMEBUFFER_OPERATION 0x0506
|
||||
GL_APICALL void GL_APIENTRY glActiveTexture (GLenum texture);
|
||||
GL_APICALL void GL_APIENTRY glAttachShader (GLuint program, GLuint shader);
|
||||
GL_APICALL void GL_APIENTRY glBindAttribLocation (GLuint program, GLuint index, const GLchar *name);
|
||||
GL_APICALL void GL_APIENTRY glBindBuffer (GLenum target, GLuint buffer);
|
||||
GL_APICALL void GL_APIENTRY glBindFramebuffer (GLenum target, GLuint framebuffer);
|
||||
GL_APICALL void GL_APIENTRY glBindRenderbuffer (GLenum target, GLuint renderbuffer);
|
||||
GL_APICALL void GL_APIENTRY glBindTexture (GLenum target, GLuint texture);
|
||||
GL_APICALL void GL_APIENTRY glBlendColor (GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha);
|
||||
GL_APICALL void GL_APIENTRY glBlendEquation (GLenum mode);
|
||||
GL_APICALL void GL_APIENTRY glBlendEquationSeparate (GLenum modeRGB, GLenum modeAlpha);
|
||||
GL_APICALL void GL_APIENTRY glBlendFunc (GLenum sfactor, GLenum dfactor);
|
||||
GL_APICALL void GL_APIENTRY glBlendFuncSeparate (GLenum sfactorRGB, GLenum dfactorRGB, GLenum sfactorAlpha, GLenum dfactorAlpha);
|
||||
GL_APICALL void GL_APIENTRY glBufferData (GLenum target, GLsizeiptr size, const void *data, GLenum usage);
|
||||
GL_APICALL void GL_APIENTRY glBufferSubData (GLenum target, GLintptr offset, GLsizeiptr size, const void *data);
|
||||
GL_APICALL GLenum GL_APIENTRY glCheckFramebufferStatus (GLenum target);
|
||||
GL_APICALL void GL_APIENTRY glClear (GLbitfield mask);
|
||||
GL_APICALL void GL_APIENTRY glClearColor (GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha);
|
||||
GL_APICALL void GL_APIENTRY glClearDepthf (GLfloat d);
|
||||
GL_APICALL void GL_APIENTRY glClearStencil (GLint s);
|
||||
GL_APICALL void GL_APIENTRY glColorMask (GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha);
|
||||
GL_APICALL void GL_APIENTRY glCompileShader (GLuint shader);
|
||||
GL_APICALL void GL_APIENTRY glCompressedTexImage2D (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const void *data);
|
||||
GL_APICALL void GL_APIENTRY glCompressedTexSubImage2D (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void *data);
|
||||
GL_APICALL void GL_APIENTRY glCopyTexImage2D (GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border);
|
||||
GL_APICALL void GL_APIENTRY glCopyTexSubImage2D (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height);
|
||||
GL_APICALL GLuint GL_APIENTRY glCreateProgram (void);
|
||||
GL_APICALL GLuint GL_APIENTRY glCreateShader (GLenum type);
|
||||
GL_APICALL void GL_APIENTRY glCullFace (GLenum mode);
|
||||
GL_APICALL void GL_APIENTRY glDeleteBuffers (GLsizei n, const GLuint *buffers);
|
||||
GL_APICALL void GL_APIENTRY glDeleteFramebuffers (GLsizei n, const GLuint *framebuffers);
|
||||
GL_APICALL void GL_APIENTRY glDeleteProgram (GLuint program);
|
||||
GL_APICALL void GL_APIENTRY glDeleteRenderbuffers (GLsizei n, const GLuint *renderbuffers);
|
||||
GL_APICALL void GL_APIENTRY glDeleteShader (GLuint shader);
|
||||
GL_APICALL void GL_APIENTRY glDeleteTextures (GLsizei n, const GLuint *textures);
|
||||
GL_APICALL void GL_APIENTRY glDepthFunc (GLenum func);
|
||||
GL_APICALL void GL_APIENTRY glDepthMask (GLboolean flag);
|
||||
GL_APICALL void GL_APIENTRY glDepthRangef (GLfloat n, GLfloat f);
|
||||
GL_APICALL void GL_APIENTRY glDetachShader (GLuint program, GLuint shader);
|
||||
GL_APICALL void GL_APIENTRY glDisable (GLenum cap);
|
||||
GL_APICALL void GL_APIENTRY glDisableVertexAttribArray (GLuint index);
|
||||
GL_APICALL void GL_APIENTRY glDrawArrays (GLenum mode, GLint first, GLsizei count);
|
||||
GL_APICALL void GL_APIENTRY glDrawElements (GLenum mode, GLsizei count, GLenum type, const void *indices);
|
||||
GL_APICALL void GL_APIENTRY glEnable (GLenum cap);
|
||||
GL_APICALL void GL_APIENTRY glEnableVertexAttribArray (GLuint index);
|
||||
GL_APICALL void GL_APIENTRY glFinish (void);
|
||||
GL_APICALL void GL_APIENTRY glFlush (void);
|
||||
GL_APICALL void GL_APIENTRY glFramebufferRenderbuffer (GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer);
|
||||
GL_APICALL void GL_APIENTRY glFramebufferTexture2D (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level);
|
||||
GL_APICALL void GL_APIENTRY glFrontFace (GLenum mode);
|
||||
GL_APICALL void GL_APIENTRY glGenBuffers (GLsizei n, GLuint *buffers);
|
||||
GL_APICALL void GL_APIENTRY glGenerateMipmap (GLenum target);
|
||||
GL_APICALL void GL_APIENTRY glGenFramebuffers (GLsizei n, GLuint *framebuffers);
|
||||
GL_APICALL void GL_APIENTRY glGenRenderbuffers (GLsizei n, GLuint *renderbuffers);
|
||||
GL_APICALL void GL_APIENTRY glGenTextures (GLsizei n, GLuint *textures);
|
||||
GL_APICALL void GL_APIENTRY glGetActiveAttrib (GLuint program, GLuint index, GLsizei bufSize, GLsizei *length, GLint *size, GLenum *type, GLchar *name);
|
||||
GL_APICALL void GL_APIENTRY glGetActiveUniform (GLuint program, GLuint index, GLsizei bufSize, GLsizei *length, GLint *size, GLenum *type, GLchar *name);
|
||||
GL_APICALL void GL_APIENTRY glGetAttachedShaders (GLuint program, GLsizei maxCount, GLsizei *count, GLuint *shaders);
|
||||
GL_APICALL GLint GL_APIENTRY glGetAttribLocation (GLuint program, const GLchar *name);
|
||||
GL_APICALL void GL_APIENTRY glGetBooleanv (GLenum pname, GLboolean *data);
|
||||
GL_APICALL void GL_APIENTRY glGetBufferParameteriv (GLenum target, GLenum pname, GLint *params);
|
||||
GL_APICALL GLenum GL_APIENTRY glGetError (void);
|
||||
GL_APICALL void GL_APIENTRY glGetFloatv (GLenum pname, GLfloat *data);
|
||||
GL_APICALL void GL_APIENTRY glGetFramebufferAttachmentParameteriv (GLenum target, GLenum attachment, GLenum pname, GLint *params);
|
||||
GL_APICALL void GL_APIENTRY glGetIntegerv (GLenum pname, GLint *data);
|
||||
GL_APICALL void GL_APIENTRY glGetProgramiv (GLuint program, GLenum pname, GLint *params);
|
||||
GL_APICALL void GL_APIENTRY glGetProgramInfoLog (GLuint program, GLsizei bufSize, GLsizei *length, GLchar *infoLog);
|
||||
GL_APICALL void GL_APIENTRY glGetRenderbufferParameteriv (GLenum target, GLenum pname, GLint *params);
|
||||
GL_APICALL void GL_APIENTRY glGetShaderiv (GLuint shader, GLenum pname, GLint *params);
|
||||
GL_APICALL void GL_APIENTRY glGetShaderInfoLog (GLuint shader, GLsizei bufSize, GLsizei *length, GLchar *infoLog);
|
||||
GL_APICALL void GL_APIENTRY glGetShaderPrecisionFormat (GLenum shadertype, GLenum precisiontype, GLint *range, GLint *precision);
|
||||
GL_APICALL void GL_APIENTRY glGetShaderSource (GLuint shader, GLsizei bufSize, GLsizei *length, GLchar *source);
|
||||
GL_APICALL const GLubyte *GL_APIENTRY glGetString (GLenum name);
|
||||
GL_APICALL void GL_APIENTRY glGetTexParameterfv (GLenum target, GLenum pname, GLfloat *params);
|
||||
GL_APICALL void GL_APIENTRY glGetTexParameteriv (GLenum target, GLenum pname, GLint *params);
|
||||
GL_APICALL void GL_APIENTRY glGetUniformfv (GLuint program, GLint location, GLfloat *params);
|
||||
GL_APICALL void GL_APIENTRY glGetUniformiv (GLuint program, GLint location, GLint *params);
|
||||
GL_APICALL GLint GL_APIENTRY glGetUniformLocation (GLuint program, const GLchar *name);
|
||||
GL_APICALL void GL_APIENTRY glGetVertexAttribfv (GLuint index, GLenum pname, GLfloat *params);
|
||||
GL_APICALL void GL_APIENTRY glGetVertexAttribiv (GLuint index, GLenum pname, GLint *params);
|
||||
GL_APICALL void GL_APIENTRY glGetVertexAttribPointerv (GLuint index, GLenum pname, void **pointer);
|
||||
GL_APICALL void GL_APIENTRY glHint (GLenum target, GLenum mode);
|
||||
GL_APICALL GLboolean GL_APIENTRY glIsBuffer (GLuint buffer);
|
||||
GL_APICALL GLboolean GL_APIENTRY glIsEnabled (GLenum cap);
|
||||
GL_APICALL GLboolean GL_APIENTRY glIsFramebuffer (GLuint framebuffer);
|
||||
GL_APICALL GLboolean GL_APIENTRY glIsProgram (GLuint program);
|
||||
GL_APICALL GLboolean GL_APIENTRY glIsRenderbuffer (GLuint renderbuffer);
|
||||
GL_APICALL GLboolean GL_APIENTRY glIsShader (GLuint shader);
|
||||
GL_APICALL GLboolean GL_APIENTRY glIsTexture (GLuint texture);
|
||||
GL_APICALL void GL_APIENTRY glLineWidth (GLfloat width);
|
||||
GL_APICALL void GL_APIENTRY glLinkProgram (GLuint program);
|
||||
GL_APICALL void GL_APIENTRY glPixelStorei (GLenum pname, GLint param);
|
||||
GL_APICALL void GL_APIENTRY glPolygonOffset (GLfloat factor, GLfloat units);
|
||||
GL_APICALL void GL_APIENTRY glReadPixels (GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, void *pixels);
|
||||
GL_APICALL void GL_APIENTRY glReleaseShaderCompiler (void);
|
||||
GL_APICALL void GL_APIENTRY glRenderbufferStorage (GLenum target, GLenum internalformat, GLsizei width, GLsizei height);
|
||||
GL_APICALL void GL_APIENTRY glSampleCoverage (GLfloat value, GLboolean invert);
|
||||
GL_APICALL void GL_APIENTRY glScissor (GLint x, GLint y, GLsizei width, GLsizei height);
|
||||
GL_APICALL void GL_APIENTRY glShaderBinary (GLsizei count, const GLuint *shaders, GLenum binaryformat, const void *binary, GLsizei length);
|
||||
GL_APICALL void GL_APIENTRY glShaderSource (GLuint shader, GLsizei count, const GLchar *const*string, const GLint *length);
|
||||
GL_APICALL void GL_APIENTRY glStencilFunc (GLenum func, GLint ref, GLuint mask);
|
||||
GL_APICALL void GL_APIENTRY glStencilFuncSeparate (GLenum face, GLenum func, GLint ref, GLuint mask);
|
||||
GL_APICALL void GL_APIENTRY glStencilMask (GLuint mask);
|
||||
GL_APICALL void GL_APIENTRY glStencilMaskSeparate (GLenum face, GLuint mask);
|
||||
GL_APICALL void GL_APIENTRY glStencilOp (GLenum fail, GLenum zfail, GLenum zpass);
|
||||
GL_APICALL void GL_APIENTRY glStencilOpSeparate (GLenum face, GLenum sfail, GLenum dpfail, GLenum dppass);
|
||||
GL_APICALL void GL_APIENTRY glTexImage2D (GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const void *pixels);
|
||||
GL_APICALL void GL_APIENTRY glTexParameterf (GLenum target, GLenum pname, GLfloat param);
|
||||
GL_APICALL void GL_APIENTRY glTexParameterfv (GLenum target, GLenum pname, const GLfloat *params);
|
||||
GL_APICALL void GL_APIENTRY glTexParameteri (GLenum target, GLenum pname, GLint param);
|
||||
GL_APICALL void GL_APIENTRY glTexParameteriv (GLenum target, GLenum pname, const GLint *params);
|
||||
GL_APICALL void GL_APIENTRY glTexSubImage2D (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const void *pixels);
|
||||
GL_APICALL void GL_APIENTRY glUniform1f (GLint location, GLfloat v0);
|
||||
GL_APICALL void GL_APIENTRY glUniform1fv (GLint location, GLsizei count, const GLfloat *value);
|
||||
GL_APICALL void GL_APIENTRY glUniform1i (GLint location, GLint v0);
|
||||
GL_APICALL void GL_APIENTRY glUniform1iv (GLint location, GLsizei count, const GLint *value);
|
||||
GL_APICALL void GL_APIENTRY glUniform2f (GLint location, GLfloat v0, GLfloat v1);
|
||||
GL_APICALL void GL_APIENTRY glUniform2fv (GLint location, GLsizei count, const GLfloat *value);
|
||||
GL_APICALL void GL_APIENTRY glUniform2i (GLint location, GLint v0, GLint v1);
|
||||
GL_APICALL void GL_APIENTRY glUniform2iv (GLint location, GLsizei count, const GLint *value);
|
||||
GL_APICALL void GL_APIENTRY glUniform3f (GLint location, GLfloat v0, GLfloat v1, GLfloat v2);
|
||||
GL_APICALL void GL_APIENTRY glUniform3fv (GLint location, GLsizei count, const GLfloat *value);
|
||||
GL_APICALL void GL_APIENTRY glUniform3i (GLint location, GLint v0, GLint v1, GLint v2);
|
||||
GL_APICALL void GL_APIENTRY glUniform3iv (GLint location, GLsizei count, const GLint *value);
|
||||
GL_APICALL void GL_APIENTRY glUniform4f (GLint location, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3);
|
||||
GL_APICALL void GL_APIENTRY glUniform4fv (GLint location, GLsizei count, const GLfloat *value);
|
||||
GL_APICALL void GL_APIENTRY glUniform4i (GLint location, GLint v0, GLint v1, GLint v2, GLint v3);
|
||||
GL_APICALL void GL_APIENTRY glUniform4iv (GLint location, GLsizei count, const GLint *value);
|
||||
GL_APICALL void GL_APIENTRY glUniformMatrix2fv (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
|
||||
GL_APICALL void GL_APIENTRY glUniformMatrix3fv (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
|
||||
GL_APICALL void GL_APIENTRY glUniformMatrix4fv (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
|
||||
GL_APICALL void GL_APIENTRY glUseProgram (GLuint program);
|
||||
GL_APICALL void GL_APIENTRY glValidateProgram (GLuint program);
|
||||
GL_APICALL void GL_APIENTRY glVertexAttrib1f (GLuint index, GLfloat x);
|
||||
GL_APICALL void GL_APIENTRY glVertexAttrib1fv (GLuint index, const GLfloat *v);
|
||||
GL_APICALL void GL_APIENTRY glVertexAttrib2f (GLuint index, GLfloat x, GLfloat y);
|
||||
GL_APICALL void GL_APIENTRY glVertexAttrib2fv (GLuint index, const GLfloat *v);
|
||||
GL_APICALL void GL_APIENTRY glVertexAttrib3f (GLuint index, GLfloat x, GLfloat y, GLfloat z);
|
||||
GL_APICALL void GL_APIENTRY glVertexAttrib3fv (GLuint index, const GLfloat *v);
|
||||
GL_APICALL void GL_APIENTRY glVertexAttrib4f (GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w);
|
||||
GL_APICALL void GL_APIENTRY glVertexAttrib4fv (GLuint index, const GLfloat *v);
|
||||
GL_APICALL void GL_APIENTRY glVertexAttribPointer (GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const void *pointer);
|
||||
GL_APICALL void GL_APIENTRY glViewport (GLint x, GLint y, GLsizei width, GLsizei height);
|
||||
#endif /* GL_ES_VERSION_2_0 */
|
||||
|
||||
#ifndef GL_ES_VERSION_3_0
|
||||
#define GL_ES_VERSION_3_0 1
|
||||
typedef unsigned short GLhalf;
|
||||
#define GL_READ_BUFFER 0x0C02
|
||||
#define GL_UNPACK_ROW_LENGTH 0x0CF2
|
||||
#define GL_UNPACK_SKIP_ROWS 0x0CF3
|
||||
#define GL_UNPACK_SKIP_PIXELS 0x0CF4
|
||||
#define GL_PACK_ROW_LENGTH 0x0D02
|
||||
#define GL_PACK_SKIP_ROWS 0x0D03
|
||||
#define GL_PACK_SKIP_PIXELS 0x0D04
|
||||
#define GL_COLOR 0x1800
|
||||
#define GL_DEPTH 0x1801
|
||||
#define GL_STENCIL 0x1802
|
||||
#define GL_RED 0x1903
|
||||
#define GL_RGB8 0x8051
|
||||
#define GL_RGBA8 0x8058
|
||||
#define GL_RGB10_A2 0x8059
|
||||
#define GL_TEXTURE_BINDING_3D 0x806A
|
||||
#define GL_UNPACK_SKIP_IMAGES 0x806D
|
||||
#define GL_UNPACK_IMAGE_HEIGHT 0x806E
|
||||
#define GL_TEXTURE_3D 0x806F
|
||||
#define GL_TEXTURE_WRAP_R 0x8072
|
||||
#define GL_MAX_3D_TEXTURE_SIZE 0x8073
|
||||
#define GL_UNSIGNED_INT_2_10_10_10_REV 0x8368
|
||||
#define GL_MAX_ELEMENTS_VERTICES 0x80E8
|
||||
#define GL_MAX_ELEMENTS_INDICES 0x80E9
|
||||
#define GL_TEXTURE_MIN_LOD 0x813A
|
||||
#define GL_TEXTURE_MAX_LOD 0x813B
|
||||
#define GL_TEXTURE_BASE_LEVEL 0x813C
|
||||
#define GL_TEXTURE_MAX_LEVEL 0x813D
|
||||
#define GL_MIN 0x8007
|
||||
#define GL_MAX 0x8008
|
||||
#define GL_DEPTH_COMPONENT24 0x81A6
|
||||
#define GL_MAX_TEXTURE_LOD_BIAS 0x84FD
|
||||
#define GL_TEXTURE_COMPARE_MODE 0x884C
|
||||
#define GL_TEXTURE_COMPARE_FUNC 0x884D
|
||||
#define GL_CURRENT_QUERY 0x8865
|
||||
#define GL_QUERY_RESULT 0x8866
|
||||
#define GL_QUERY_RESULT_AVAILABLE 0x8867
|
||||
#define GL_BUFFER_MAPPED 0x88BC
|
||||
#define GL_BUFFER_MAP_POINTER 0x88BD
|
||||
#define GL_STREAM_READ 0x88E1
|
||||
#define GL_STREAM_COPY 0x88E2
|
||||
#define GL_STATIC_READ 0x88E5
|
||||
#define GL_STATIC_COPY 0x88E6
|
||||
#define GL_DYNAMIC_READ 0x88E9
|
||||
#define GL_DYNAMIC_COPY 0x88EA
|
||||
#define GL_MAX_DRAW_BUFFERS 0x8824
|
||||
#define GL_DRAW_BUFFER0 0x8825
|
||||
#define GL_DRAW_BUFFER1 0x8826
|
||||
#define GL_DRAW_BUFFER2 0x8827
|
||||
#define GL_DRAW_BUFFER3 0x8828
|
||||
#define GL_DRAW_BUFFER4 0x8829
|
||||
#define GL_DRAW_BUFFER5 0x882A
|
||||
#define GL_DRAW_BUFFER6 0x882B
|
||||
#define GL_DRAW_BUFFER7 0x882C
|
||||
#define GL_DRAW_BUFFER8 0x882D
|
||||
#define GL_DRAW_BUFFER9 0x882E
|
||||
#define GL_DRAW_BUFFER10 0x882F
|
||||
#define GL_DRAW_BUFFER11 0x8830
|
||||
#define GL_DRAW_BUFFER12 0x8831
|
||||
#define GL_DRAW_BUFFER13 0x8832
|
||||
#define GL_DRAW_BUFFER14 0x8833
|
||||
#define GL_DRAW_BUFFER15 0x8834
|
||||
#define GL_MAX_FRAGMENT_UNIFORM_COMPONENTS 0x8B49
|
||||
#define GL_MAX_VERTEX_UNIFORM_COMPONENTS 0x8B4A
|
||||
#define GL_SAMPLER_3D 0x8B5F
|
||||
#define GL_SAMPLER_2D_SHADOW 0x8B62
|
||||
#define GL_FRAGMENT_SHADER_DERIVATIVE_HINT 0x8B8B
|
||||
#define GL_PIXEL_PACK_BUFFER 0x88EB
|
||||
#define GL_PIXEL_UNPACK_BUFFER 0x88EC
|
||||
#define GL_PIXEL_PACK_BUFFER_BINDING 0x88ED
|
||||
#define GL_PIXEL_UNPACK_BUFFER_BINDING 0x88EF
|
||||
#define GL_FLOAT_MAT2x3 0x8B65
|
||||
#define GL_FLOAT_MAT2x4 0x8B66
|
||||
#define GL_FLOAT_MAT3x2 0x8B67
|
||||
#define GL_FLOAT_MAT3x4 0x8B68
|
||||
#define GL_FLOAT_MAT4x2 0x8B69
|
||||
#define GL_FLOAT_MAT4x3 0x8B6A
|
||||
#define GL_SRGB 0x8C40
|
||||
#define GL_SRGB8 0x8C41
|
||||
#define GL_SRGB8_ALPHA8 0x8C43
|
||||
#define GL_COMPARE_REF_TO_TEXTURE 0x884E
|
||||
#define GL_MAJOR_VERSION 0x821B
|
||||
#define GL_MINOR_VERSION 0x821C
|
||||
#define GL_NUM_EXTENSIONS 0x821D
|
||||
#define GL_RGBA32F 0x8814
|
||||
#define GL_RGB32F 0x8815
|
||||
#define GL_RGBA16F 0x881A
|
||||
#define GL_RGB16F 0x881B
|
||||
#define GL_VERTEX_ATTRIB_ARRAY_INTEGER 0x88FD
|
||||
#define GL_MAX_ARRAY_TEXTURE_LAYERS 0x88FF
|
||||
#define GL_MIN_PROGRAM_TEXEL_OFFSET 0x8904
|
||||
#define GL_MAX_PROGRAM_TEXEL_OFFSET 0x8905
|
||||
#define GL_MAX_VARYING_COMPONENTS 0x8B4B
|
||||
#define GL_TEXTURE_2D_ARRAY 0x8C1A
|
||||
#define GL_TEXTURE_BINDING_2D_ARRAY 0x8C1D
|
||||
#define GL_R11F_G11F_B10F 0x8C3A
|
||||
#define GL_UNSIGNED_INT_10F_11F_11F_REV 0x8C3B
|
||||
#define GL_RGB9_E5 0x8C3D
|
||||
#define GL_UNSIGNED_INT_5_9_9_9_REV 0x8C3E
|
||||
#define GL_TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH 0x8C76
|
||||
#define GL_TRANSFORM_FEEDBACK_BUFFER_MODE 0x8C7F
|
||||
#define GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_COMPONENTS 0x8C80
|
||||
#define GL_TRANSFORM_FEEDBACK_VARYINGS 0x8C83
|
||||
#define GL_TRANSFORM_FEEDBACK_BUFFER_START 0x8C84
|
||||
#define GL_TRANSFORM_FEEDBACK_BUFFER_SIZE 0x8C85
|
||||
#define GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN 0x8C88
|
||||
#define GL_RASTERIZER_DISCARD 0x8C89
|
||||
#define GL_MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS 0x8C8A
|
||||
#define GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS 0x8C8B
|
||||
#define GL_INTERLEAVED_ATTRIBS 0x8C8C
|
||||
#define GL_SEPARATE_ATTRIBS 0x8C8D
|
||||
#define GL_TRANSFORM_FEEDBACK_BUFFER 0x8C8E
|
||||
#define GL_TRANSFORM_FEEDBACK_BUFFER_BINDING 0x8C8F
|
||||
#define GL_RGBA32UI 0x8D70
|
||||
#define GL_RGB32UI 0x8D71
|
||||
#define GL_RGBA16UI 0x8D76
|
||||
#define GL_RGB16UI 0x8D77
|
||||
#define GL_RGBA8UI 0x8D7C
|
||||
#define GL_RGB8UI 0x8D7D
|
||||
#define GL_RGBA32I 0x8D82
|
||||
#define GL_RGB32I 0x8D83
|
||||
#define GL_RGBA16I 0x8D88
|
||||
#define GL_RGB16I 0x8D89
|
||||
#define GL_RGBA8I 0x8D8E
|
||||
#define GL_RGB8I 0x8D8F
|
||||
#define GL_RED_INTEGER 0x8D94
|
||||
#define GL_RGB_INTEGER 0x8D98
|
||||
#define GL_RGBA_INTEGER 0x8D99
|
||||
#define GL_SAMPLER_2D_ARRAY 0x8DC1
|
||||
#define GL_SAMPLER_2D_ARRAY_SHADOW 0x8DC4
|
||||
#define GL_SAMPLER_CUBE_SHADOW 0x8DC5
|
||||
#define GL_UNSIGNED_INT_VEC2 0x8DC6
|
||||
#define GL_UNSIGNED_INT_VEC3 0x8DC7
|
||||
#define GL_UNSIGNED_INT_VEC4 0x8DC8
|
||||
#define GL_INT_SAMPLER_2D 0x8DCA
|
||||
#define GL_INT_SAMPLER_3D 0x8DCB
|
||||
#define GL_INT_SAMPLER_CUBE 0x8DCC
|
||||
#define GL_INT_SAMPLER_2D_ARRAY 0x8DCF
|
||||
#define GL_UNSIGNED_INT_SAMPLER_2D 0x8DD2
|
||||
#define GL_UNSIGNED_INT_SAMPLER_3D 0x8DD3
|
||||
#define GL_UNSIGNED_INT_SAMPLER_CUBE 0x8DD4
|
||||
#define GL_UNSIGNED_INT_SAMPLER_2D_ARRAY 0x8DD7
|
||||
#define GL_BUFFER_ACCESS_FLAGS 0x911F
|
||||
#define GL_BUFFER_MAP_LENGTH 0x9120
|
||||
#define GL_BUFFER_MAP_OFFSET 0x9121
|
||||
#define GL_DEPTH_COMPONENT32F 0x8CAC
|
||||
#define GL_DEPTH32F_STENCIL8 0x8CAD
|
||||
#define GL_FLOAT_32_UNSIGNED_INT_24_8_REV 0x8DAD
|
||||
#define GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING 0x8210
|
||||
#define GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE 0x8211
|
||||
#define GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE 0x8212
|
||||
#define GL_FRAMEBUFFER_ATTACHMENT_GREEN_SIZE 0x8213
|
||||
#define GL_FRAMEBUFFER_ATTACHMENT_BLUE_SIZE 0x8214
|
||||
#define GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE 0x8215
|
||||
#define GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE 0x8216
|
||||
#define GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE 0x8217
|
||||
#define GL_FRAMEBUFFER_DEFAULT 0x8218
|
||||
#define GL_FRAMEBUFFER_UNDEFINED 0x8219
|
||||
#define GL_DEPTH_STENCIL_ATTACHMENT 0x821A
|
||||
#define GL_DEPTH_STENCIL 0x84F9
|
||||
#define GL_UNSIGNED_INT_24_8 0x84FA
|
||||
#define GL_DEPTH24_STENCIL8 0x88F0
|
||||
#define GL_UNSIGNED_NORMALIZED 0x8C17
|
||||
#define GL_DRAW_FRAMEBUFFER_BINDING 0x8CA6
|
||||
#define GL_READ_FRAMEBUFFER 0x8CA8
|
||||
#define GL_DRAW_FRAMEBUFFER 0x8CA9
|
||||
#define GL_READ_FRAMEBUFFER_BINDING 0x8CAA
|
||||
#define GL_RENDERBUFFER_SAMPLES 0x8CAB
|
||||
#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER 0x8CD4
|
||||
#define GL_MAX_COLOR_ATTACHMENTS 0x8CDF
|
||||
#define GL_COLOR_ATTACHMENT1 0x8CE1
|
||||
#define GL_COLOR_ATTACHMENT2 0x8CE2
|
||||
#define GL_COLOR_ATTACHMENT3 0x8CE3
|
||||
#define GL_COLOR_ATTACHMENT4 0x8CE4
|
||||
#define GL_COLOR_ATTACHMENT5 0x8CE5
|
||||
#define GL_COLOR_ATTACHMENT6 0x8CE6
|
||||
#define GL_COLOR_ATTACHMENT7 0x8CE7
|
||||
#define GL_COLOR_ATTACHMENT8 0x8CE8
|
||||
#define GL_COLOR_ATTACHMENT9 0x8CE9
|
||||
#define GL_COLOR_ATTACHMENT10 0x8CEA
|
||||
#define GL_COLOR_ATTACHMENT11 0x8CEB
|
||||
#define GL_COLOR_ATTACHMENT12 0x8CEC
|
||||
#define GL_COLOR_ATTACHMENT13 0x8CED
|
||||
#define GL_COLOR_ATTACHMENT14 0x8CEE
|
||||
#define GL_COLOR_ATTACHMENT15 0x8CEF
|
||||
#define GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE 0x8D56
|
||||
#define GL_MAX_SAMPLES 0x8D57
|
||||
#define GL_HALF_FLOAT 0x140B
|
||||
#define GL_MAP_READ_BIT 0x0001
|
||||
#define GL_MAP_WRITE_BIT 0x0002
|
||||
#define GL_MAP_INVALIDATE_RANGE_BIT 0x0004
|
||||
#define GL_MAP_INVALIDATE_BUFFER_BIT 0x0008
|
||||
#define GL_MAP_FLUSH_EXPLICIT_BIT 0x0010
|
||||
#define GL_MAP_UNSYNCHRONIZED_BIT 0x0020
|
||||
#define GL_RG 0x8227
|
||||
#define GL_RG_INTEGER 0x8228
|
||||
#define GL_R8 0x8229
|
||||
#define GL_RG8 0x822B
|
||||
#define GL_R16F 0x822D
|
||||
#define GL_R32F 0x822E
|
||||
#define GL_RG16F 0x822F
|
||||
#define GL_RG32F 0x8230
|
||||
#define GL_R8I 0x8231
|
||||
#define GL_R8UI 0x8232
|
||||
#define GL_R16I 0x8233
|
||||
#define GL_R16UI 0x8234
|
||||
#define GL_R32I 0x8235
|
||||
#define GL_R32UI 0x8236
|
||||
#define GL_RG8I 0x8237
|
||||
#define GL_RG8UI 0x8238
|
||||
#define GL_RG16I 0x8239
|
||||
#define GL_RG16UI 0x823A
|
||||
#define GL_RG32I 0x823B
|
||||
#define GL_RG32UI 0x823C
|
||||
#define GL_VERTEX_ARRAY_BINDING 0x85B5
|
||||
#define GL_R8_SNORM 0x8F94
|
||||
#define GL_RG8_SNORM 0x8F95
|
||||
#define GL_RGB8_SNORM 0x8F96
|
||||
#define GL_RGBA8_SNORM 0x8F97
|
||||
#define GL_SIGNED_NORMALIZED 0x8F9C
|
||||
#define GL_PRIMITIVE_RESTART_FIXED_INDEX 0x8D69
|
||||
#define GL_COPY_READ_BUFFER 0x8F36
|
||||
#define GL_COPY_WRITE_BUFFER 0x8F37
|
||||
#define GL_COPY_READ_BUFFER_BINDING 0x8F36
|
||||
#define GL_COPY_WRITE_BUFFER_BINDING 0x8F37
|
||||
#define GL_UNIFORM_BUFFER 0x8A11
|
||||
#define GL_UNIFORM_BUFFER_BINDING 0x8A28
|
||||
#define GL_UNIFORM_BUFFER_START 0x8A29
|
||||
#define GL_UNIFORM_BUFFER_SIZE 0x8A2A
|
||||
#define GL_MAX_VERTEX_UNIFORM_BLOCKS 0x8A2B
|
||||
#define GL_MAX_FRAGMENT_UNIFORM_BLOCKS 0x8A2D
|
||||
#define GL_MAX_COMBINED_UNIFORM_BLOCKS 0x8A2E
|
||||
#define GL_MAX_UNIFORM_BUFFER_BINDINGS 0x8A2F
|
||||
#define GL_MAX_UNIFORM_BLOCK_SIZE 0x8A30
|
||||
#define GL_MAX_COMBINED_VERTEX_UNIFORM_COMPONENTS 0x8A31
|
||||
#define GL_MAX_COMBINED_FRAGMENT_UNIFORM_COMPONENTS 0x8A33
|
||||
#define GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT 0x8A34
|
||||
#define GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH 0x8A35
|
||||
#define GL_ACTIVE_UNIFORM_BLOCKS 0x8A36
|
||||
#define GL_UNIFORM_TYPE 0x8A37
|
||||
#define GL_UNIFORM_SIZE 0x8A38
|
||||
#define GL_UNIFORM_NAME_LENGTH 0x8A39
|
||||
#define GL_UNIFORM_BLOCK_INDEX 0x8A3A
|
||||
#define GL_UNIFORM_OFFSET 0x8A3B
|
||||
#define GL_UNIFORM_ARRAY_STRIDE 0x8A3C
|
||||
#define GL_UNIFORM_MATRIX_STRIDE 0x8A3D
|
||||
#define GL_UNIFORM_IS_ROW_MAJOR 0x8A3E
|
||||
#define GL_UNIFORM_BLOCK_BINDING 0x8A3F
|
||||
#define GL_UNIFORM_BLOCK_DATA_SIZE 0x8A40
|
||||
#define GL_UNIFORM_BLOCK_NAME_LENGTH 0x8A41
|
||||
#define GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS 0x8A42
|
||||
#define GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES 0x8A43
|
||||
#define GL_UNIFORM_BLOCK_REFERENCED_BY_VERTEX_SHADER 0x8A44
|
||||
#define GL_UNIFORM_BLOCK_REFERENCED_BY_FRAGMENT_SHADER 0x8A46
|
||||
#define GL_INVALID_INDEX 0xFFFFFFFFu
|
||||
#define GL_MAX_VERTEX_OUTPUT_COMPONENTS 0x9122
|
||||
#define GL_MAX_FRAGMENT_INPUT_COMPONENTS 0x9125
|
||||
#define GL_MAX_SERVER_WAIT_TIMEOUT 0x9111
|
||||
#define GL_OBJECT_TYPE 0x9112
|
||||
#define GL_SYNC_CONDITION 0x9113
|
||||
#define GL_SYNC_STATUS 0x9114
|
||||
#define GL_SYNC_FLAGS 0x9115
|
||||
#define GL_SYNC_FENCE 0x9116
|
||||
#define GL_SYNC_GPU_COMMANDS_COMPLETE 0x9117
|
||||
#define GL_UNSIGNALED 0x9118
|
||||
#define GL_SIGNALED 0x9119
|
||||
#define GL_ALREADY_SIGNALED 0x911A
|
||||
#define GL_TIMEOUT_EXPIRED 0x911B
|
||||
#define GL_CONDITION_SATISFIED 0x911C
|
||||
#define GL_WAIT_FAILED 0x911D
|
||||
#define GL_SYNC_FLUSH_COMMANDS_BIT 0x00000001
|
||||
#define GL_TIMEOUT_IGNORED 0xFFFFFFFFFFFFFFFFull
|
||||
#define GL_VERTEX_ATTRIB_ARRAY_DIVISOR 0x88FE
|
||||
#define GL_ANY_SAMPLES_PASSED 0x8C2F
|
||||
#define GL_ANY_SAMPLES_PASSED_CONSERVATIVE 0x8D6A
|
||||
#define GL_SAMPLER_BINDING 0x8919
|
||||
#define GL_RGB10_A2UI 0x906F
|
||||
#define GL_TEXTURE_SWIZZLE_R 0x8E42
|
||||
#define GL_TEXTURE_SWIZZLE_G 0x8E43
|
||||
#define GL_TEXTURE_SWIZZLE_B 0x8E44
|
||||
#define GL_TEXTURE_SWIZZLE_A 0x8E45
|
||||
#define GL_GREEN 0x1904
|
||||
#define GL_BLUE 0x1905
|
||||
#define GL_INT_2_10_10_10_REV 0x8D9F
|
||||
#define GL_TRANSFORM_FEEDBACK 0x8E22
|
||||
#define GL_TRANSFORM_FEEDBACK_PAUSED 0x8E23
|
||||
#define GL_TRANSFORM_FEEDBACK_ACTIVE 0x8E24
|
||||
#define GL_TRANSFORM_FEEDBACK_BINDING 0x8E25
|
||||
#define GL_PROGRAM_BINARY_RETRIEVABLE_HINT 0x8257
|
||||
#define GL_PROGRAM_BINARY_LENGTH 0x8741
|
||||
#define GL_NUM_PROGRAM_BINARY_FORMATS 0x87FE
|
||||
#define GL_PROGRAM_BINARY_FORMATS 0x87FF
|
||||
#define GL_COMPRESSED_R11_EAC 0x9270
|
||||
#define GL_COMPRESSED_SIGNED_R11_EAC 0x9271
|
||||
#define GL_COMPRESSED_RG11_EAC 0x9272
|
||||
#define GL_COMPRESSED_SIGNED_RG11_EAC 0x9273
|
||||
#define GL_COMPRESSED_RGB8_ETC2 0x9274
|
||||
#define GL_COMPRESSED_SRGB8_ETC2 0x9275
|
||||
#define GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2 0x9276
|
||||
#define GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2 0x9277
|
||||
#define GL_COMPRESSED_RGBA8_ETC2_EAC 0x9278
|
||||
#define GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC 0x9279
|
||||
#define GL_TEXTURE_IMMUTABLE_FORMAT 0x912F
|
||||
#define GL_MAX_ELEMENT_INDEX 0x8D6B
|
||||
#define GL_NUM_SAMPLE_COUNTS 0x9380
|
||||
#define GL_TEXTURE_IMMUTABLE_LEVELS 0x82DF
|
||||
GL_APICALL void GL_APIENTRY glReadBuffer (GLenum mode);
|
||||
GL_APICALL void GL_APIENTRY glDrawRangeElements (GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const void *indices);
|
||||
GL_APICALL void GL_APIENTRY glTexImage3D (GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const void *pixels);
|
||||
GL_APICALL void GL_APIENTRY glTexSubImage3D (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const void *pixels);
|
||||
GL_APICALL void GL_APIENTRY glCopyTexSubImage3D (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height);
|
||||
GL_APICALL void GL_APIENTRY glCompressedTexImage3D (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const void *data);
|
||||
GL_APICALL void GL_APIENTRY glCompressedTexSubImage3D (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const void *data);
|
||||
GL_APICALL void GL_APIENTRY glGenQueries (GLsizei n, GLuint *ids);
|
||||
GL_APICALL void GL_APIENTRY glDeleteQueries (GLsizei n, const GLuint *ids);
|
||||
GL_APICALL GLboolean GL_APIENTRY glIsQuery (GLuint id);
|
||||
GL_APICALL void GL_APIENTRY glBeginQuery (GLenum target, GLuint id);
|
||||
GL_APICALL void GL_APIENTRY glEndQuery (GLenum target);
|
||||
GL_APICALL void GL_APIENTRY glGetQueryiv (GLenum target, GLenum pname, GLint *params);
|
||||
GL_APICALL void GL_APIENTRY glGetQueryObjectuiv (GLuint id, GLenum pname, GLuint *params);
|
||||
GL_APICALL GLboolean GL_APIENTRY glUnmapBuffer (GLenum target);
|
||||
GL_APICALL void GL_APIENTRY glGetBufferPointerv (GLenum target, GLenum pname, void **params);
|
||||
GL_APICALL void GL_APIENTRY glDrawBuffers (GLsizei n, const GLenum *bufs);
|
||||
GL_APICALL void GL_APIENTRY glUniformMatrix2x3fv (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
|
||||
GL_APICALL void GL_APIENTRY glUniformMatrix3x2fv (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
|
||||
GL_APICALL void GL_APIENTRY glUniformMatrix2x4fv (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
|
||||
GL_APICALL void GL_APIENTRY glUniformMatrix4x2fv (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
|
||||
GL_APICALL void GL_APIENTRY glUniformMatrix3x4fv (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
|
||||
GL_APICALL void GL_APIENTRY glUniformMatrix4x3fv (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
|
||||
GL_APICALL void GL_APIENTRY glBlitFramebuffer (GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter);
|
||||
GL_APICALL void GL_APIENTRY glRenderbufferStorageMultisample (GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height);
|
||||
GL_APICALL void GL_APIENTRY glFramebufferTextureLayer (GLenum target, GLenum attachment, GLuint texture, GLint level, GLint layer);
|
||||
GL_APICALL void *GL_APIENTRY glMapBufferRange (GLenum target, GLintptr offset, GLsizeiptr length, GLbitfield access);
|
||||
GL_APICALL void GL_APIENTRY glFlushMappedBufferRange (GLenum target, GLintptr offset, GLsizeiptr length);
|
||||
GL_APICALL void GL_APIENTRY glBindVertexArray (GLuint array);
|
||||
GL_APICALL void GL_APIENTRY glDeleteVertexArrays (GLsizei n, const GLuint *arrays);
|
||||
GL_APICALL void GL_APIENTRY glGenVertexArrays (GLsizei n, GLuint *arrays);
|
||||
GL_APICALL GLboolean GL_APIENTRY glIsVertexArray (GLuint array);
|
||||
GL_APICALL void GL_APIENTRY glGetIntegeri_v (GLenum target, GLuint index, GLint *data);
|
||||
GL_APICALL void GL_APIENTRY glBeginTransformFeedback (GLenum primitiveMode);
|
||||
GL_APICALL void GL_APIENTRY glEndTransformFeedback (void);
|
||||
GL_APICALL void GL_APIENTRY glBindBufferRange (GLenum target, GLuint index, GLuint buffer, GLintptr offset, GLsizeiptr size);
|
||||
GL_APICALL void GL_APIENTRY glBindBufferBase (GLenum target, GLuint index, GLuint buffer);
|
||||
GL_APICALL void GL_APIENTRY glTransformFeedbackVaryings (GLuint program, GLsizei count, const GLchar *const*varyings, GLenum bufferMode);
|
||||
GL_APICALL void GL_APIENTRY glGetTransformFeedbackVarying (GLuint program, GLuint index, GLsizei bufSize, GLsizei *length, GLsizei *size, GLenum *type, GLchar *name);
|
||||
GL_APICALL void GL_APIENTRY glVertexAttribIPointer (GLuint index, GLint size, GLenum type, GLsizei stride, const void *pointer);
|
||||
GL_APICALL void GL_APIENTRY glGetVertexAttribIiv (GLuint index, GLenum pname, GLint *params);
|
||||
GL_APICALL void GL_APIENTRY glGetVertexAttribIuiv (GLuint index, GLenum pname, GLuint *params);
|
||||
GL_APICALL void GL_APIENTRY glVertexAttribI4i (GLuint index, GLint x, GLint y, GLint z, GLint w);
|
||||
GL_APICALL void GL_APIENTRY glVertexAttribI4ui (GLuint index, GLuint x, GLuint y, GLuint z, GLuint w);
|
||||
GL_APICALL void GL_APIENTRY glVertexAttribI4iv (GLuint index, const GLint *v);
|
||||
GL_APICALL void GL_APIENTRY glVertexAttribI4uiv (GLuint index, const GLuint *v);
|
||||
GL_APICALL void GL_APIENTRY glGetUniformuiv (GLuint program, GLint location, GLuint *params);
|
||||
GL_APICALL GLint GL_APIENTRY glGetFragDataLocation (GLuint program, const GLchar *name);
|
||||
GL_APICALL void GL_APIENTRY glUniform1ui (GLint location, GLuint v0);
|
||||
GL_APICALL void GL_APIENTRY glUniform2ui (GLint location, GLuint v0, GLuint v1);
|
||||
GL_APICALL void GL_APIENTRY glUniform3ui (GLint location, GLuint v0, GLuint v1, GLuint v2);
|
||||
GL_APICALL void GL_APIENTRY glUniform4ui (GLint location, GLuint v0, GLuint v1, GLuint v2, GLuint v3);
|
||||
GL_APICALL void GL_APIENTRY glUniform1uiv (GLint location, GLsizei count, const GLuint *value);
|
||||
GL_APICALL void GL_APIENTRY glUniform2uiv (GLint location, GLsizei count, const GLuint *value);
|
||||
GL_APICALL void GL_APIENTRY glUniform3uiv (GLint location, GLsizei count, const GLuint *value);
|
||||
GL_APICALL void GL_APIENTRY glUniform4uiv (GLint location, GLsizei count, const GLuint *value);
|
||||
GL_APICALL void GL_APIENTRY glClearBufferiv (GLenum buffer, GLint drawbuffer, const GLint *value);
|
||||
GL_APICALL void GL_APIENTRY glClearBufferuiv (GLenum buffer, GLint drawbuffer, const GLuint *value);
|
||||
GL_APICALL void GL_APIENTRY glClearBufferfv (GLenum buffer, GLint drawbuffer, const GLfloat *value);
|
||||
GL_APICALL void GL_APIENTRY glClearBufferfi (GLenum buffer, GLint drawbuffer, GLfloat depth, GLint stencil);
|
||||
GL_APICALL const GLubyte *GL_APIENTRY glGetStringi (GLenum name, GLuint index);
|
||||
GL_APICALL void GL_APIENTRY glCopyBufferSubData (GLenum readTarget, GLenum writeTarget, GLintptr readOffset, GLintptr writeOffset, GLsizeiptr size);
|
||||
GL_APICALL void GL_APIENTRY glGetUniformIndices (GLuint program, GLsizei uniformCount, const GLchar *const*uniformNames, GLuint *uniformIndices);
|
||||
GL_APICALL void GL_APIENTRY glGetActiveUniformsiv (GLuint program, GLsizei uniformCount, const GLuint *uniformIndices, GLenum pname, GLint *params);
|
||||
GL_APICALL GLuint GL_APIENTRY glGetUniformBlockIndex (GLuint program, const GLchar *uniformBlockName);
|
||||
GL_APICALL void GL_APIENTRY glGetActiveUniformBlockiv (GLuint program, GLuint uniformBlockIndex, GLenum pname, GLint *params);
|
||||
GL_APICALL void GL_APIENTRY glGetActiveUniformBlockName (GLuint program, GLuint uniformBlockIndex, GLsizei bufSize, GLsizei *length, GLchar *uniformBlockName);
|
||||
GL_APICALL void GL_APIENTRY glUniformBlockBinding (GLuint program, GLuint uniformBlockIndex, GLuint uniformBlockBinding);
|
||||
GL_APICALL void GL_APIENTRY glDrawArraysInstanced (GLenum mode, GLint first, GLsizei count, GLsizei instancecount);
|
||||
GL_APICALL void GL_APIENTRY glDrawElementsInstanced (GLenum mode, GLsizei count, GLenum type, const void *indices, GLsizei instancecount);
|
||||
GL_APICALL GLsync GL_APIENTRY glFenceSync (GLenum condition, GLbitfield flags);
|
||||
GL_APICALL GLboolean GL_APIENTRY glIsSync (GLsync sync);
|
||||
GL_APICALL void GL_APIENTRY glDeleteSync (GLsync sync);
|
||||
GL_APICALL GLenum GL_APIENTRY glClientWaitSync (GLsync sync, GLbitfield flags, GLuint64 timeout);
|
||||
GL_APICALL void GL_APIENTRY glWaitSync (GLsync sync, GLbitfield flags, GLuint64 timeout);
|
||||
GL_APICALL void GL_APIENTRY glGetInteger64v (GLenum pname, GLint64 *data);
|
||||
GL_APICALL void GL_APIENTRY glGetSynciv (GLsync sync, GLenum pname, GLsizei bufSize, GLsizei *length, GLint *values);
|
||||
GL_APICALL void GL_APIENTRY glGetInteger64i_v (GLenum target, GLuint index, GLint64 *data);
|
||||
GL_APICALL void GL_APIENTRY glGetBufferParameteri64v (GLenum target, GLenum pname, GLint64 *params);
|
||||
GL_APICALL void GL_APIENTRY glGenSamplers (GLsizei count, GLuint *samplers);
|
||||
GL_APICALL void GL_APIENTRY glDeleteSamplers (GLsizei count, const GLuint *samplers);
|
||||
GL_APICALL GLboolean GL_APIENTRY glIsSampler (GLuint sampler);
|
||||
GL_APICALL void GL_APIENTRY glBindSampler (GLuint unit, GLuint sampler);
|
||||
GL_APICALL void GL_APIENTRY glSamplerParameteri (GLuint sampler, GLenum pname, GLint param);
|
||||
GL_APICALL void GL_APIENTRY glSamplerParameteriv (GLuint sampler, GLenum pname, const GLint *param);
|
||||
GL_APICALL void GL_APIENTRY glSamplerParameterf (GLuint sampler, GLenum pname, GLfloat param);
|
||||
GL_APICALL void GL_APIENTRY glSamplerParameterfv (GLuint sampler, GLenum pname, const GLfloat *param);
|
||||
GL_APICALL void GL_APIENTRY glGetSamplerParameteriv (GLuint sampler, GLenum pname, GLint *params);
|
||||
GL_APICALL void GL_APIENTRY glGetSamplerParameterfv (GLuint sampler, GLenum pname, GLfloat *params);
|
||||
GL_APICALL void GL_APIENTRY glVertexAttribDivisor (GLuint index, GLuint divisor);
|
||||
GL_APICALL void GL_APIENTRY glBindTransformFeedback (GLenum target, GLuint id);
|
||||
GL_APICALL void GL_APIENTRY glDeleteTransformFeedbacks (GLsizei n, const GLuint *ids);
|
||||
GL_APICALL void GL_APIENTRY glGenTransformFeedbacks (GLsizei n, GLuint *ids);
|
||||
GL_APICALL GLboolean GL_APIENTRY glIsTransformFeedback (GLuint id);
|
||||
GL_APICALL void GL_APIENTRY glPauseTransformFeedback (void);
|
||||
GL_APICALL void GL_APIENTRY glResumeTransformFeedback (void);
|
||||
GL_APICALL void GL_APIENTRY glGetProgramBinary (GLuint program, GLsizei bufSize, GLsizei *length, GLenum *binaryFormat, void *binary);
|
||||
GL_APICALL void GL_APIENTRY glProgramBinary (GLuint program, GLenum binaryFormat, const void *binary, GLsizei length);
|
||||
GL_APICALL void GL_APIENTRY glProgramParameteri (GLuint program, GLenum pname, GLint value);
|
||||
GL_APICALL void GL_APIENTRY glInvalidateFramebuffer (GLenum target, GLsizei numAttachments, const GLenum *attachments);
|
||||
GL_APICALL void GL_APIENTRY glInvalidateSubFramebuffer (GLenum target, GLsizei numAttachments, const GLenum *attachments, GLint x, GLint y, GLsizei width, GLsizei height);
|
||||
GL_APICALL void GL_APIENTRY glTexStorage2D (GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height);
|
||||
GL_APICALL void GL_APIENTRY glTexStorage3D (GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth);
|
||||
GL_APICALL void GL_APIENTRY glGetInternalformativ (GLenum target, GLenum internalformat, GLenum pname, GLsizei bufSize, GLint *params);
|
||||
#endif /* GL_ES_VERSION_3_0 */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,30 @@
|
||||
#ifndef __gl3platform_h_
|
||||
#define __gl3platform_h_
|
||||
|
||||
/* $Revision: 23328 $ on $Date:: 2013-10-02 02:28:28 -0700 #$ */
|
||||
|
||||
/*
|
||||
* This document is licensed under the SGI Free Software B License Version
|
||||
* 2.0. For details, see http://oss.sgi.com/projects/FreeB/ .
|
||||
*/
|
||||
|
||||
/* Platform-specific types and definitions for OpenGL ES 3.X gl3.h
|
||||
*
|
||||
* Adopters may modify khrplatform.h and this file to suit their platform.
|
||||
* You are encouraged to submit all modifications to the Khronos group so that
|
||||
* they can be included in future versions of this file. Please submit changes
|
||||
* by sending them to the public Khronos Bugzilla (http://khronos.org/bugzilla)
|
||||
* by filing a bug against product "OpenGL-ES" component "Registry".
|
||||
*/
|
||||
|
||||
#include <KHR/khrplatform.h>
|
||||
|
||||
#ifndef GL_APICALL
|
||||
#define GL_APICALL KHRONOS_APICALL
|
||||
#endif
|
||||
|
||||
#ifndef GL_APIENTRY
|
||||
#define GL_APIENTRY KHRONOS_APIENTRY
|
||||
#endif
|
||||
|
||||
#endif /* __gl3platform_h_ */
|
||||
@@ -2,31 +2,31 @@
|
||||
#define __khrplatform_h_
|
||||
|
||||
/*
|
||||
** Copyright (c) 2008-2009 The Khronos Group Inc.
|
||||
**
|
||||
** Permission is hereby granted, free of charge, to any person obtaining a
|
||||
** copy of this software and/or associated documentation files (the
|
||||
** "Materials"), to deal in the Materials without restriction, including
|
||||
** without limitation the rights to use, copy, modify, merge, publish,
|
||||
** distribute, sublicense, and/or sell copies of the Materials, and to
|
||||
** permit persons to whom the Materials are 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 Materials.
|
||||
**
|
||||
** THE MATERIALS ARE 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
|
||||
** MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
|
||||
*/
|
||||
** Copyright (c) 2008-2009 The Khronos Group Inc.
|
||||
**
|
||||
** Permission is hereby granted, free of charge, to any person obtaining a
|
||||
** copy of this software and/or associated documentation files (the
|
||||
** "Materials"), to deal in the Materials without restriction, including
|
||||
** without limitation the rights to use, copy, modify, merge, publish,
|
||||
** distribute, sublicense, and/or sell copies of the Materials, and to
|
||||
** permit persons to whom the Materials are 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 Materials.
|
||||
**
|
||||
** THE MATERIALS ARE 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
|
||||
** MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
|
||||
*/
|
||||
|
||||
/* Khronos platform-specific types and definitions.
|
||||
*
|
||||
* $Revision: 9356 $ on $Date: 2009-10-21 02:52:25 -0700 (Wed, 21 Oct 2009) $
|
||||
* $Revision: 23298 $ on $Date: 2013-09-30 17:07:13 -0700 (Mon, 30 Sep 2013) $
|
||||
*
|
||||
* Adopters may modify this file to suit their platform. Adopters are
|
||||
* encouraged to submit platform specific modifications to the Khronos
|
||||
@@ -112,7 +112,7 @@
|
||||
* name in the function prototype.
|
||||
*/
|
||||
#if defined(_WIN32) && !defined(_WIN32_WCE) && !defined(__SCITECH_SNAP__)
|
||||
/* Win32 but not WinCE */
|
||||
/* Win32 but not WinCE */
|
||||
# define KHRONOS_APIENTRY __stdcall
|
||||
#else
|
||||
# define KHRONOS_APIENTRY
|
||||
@@ -221,10 +221,23 @@ typedef signed char khronos_int8_t;
|
||||
typedef unsigned char khronos_uint8_t;
|
||||
typedef signed short int khronos_int16_t;
|
||||
typedef unsigned short int khronos_uint16_t;
|
||||
|
||||
/*
|
||||
* Types that differ between LLP64 and LP64 architectures - in LLP64,
|
||||
* pointers are 64 bits, but 'long' is still 32 bits. Win64 appears
|
||||
* to be the only LLP64 architecture in current use.
|
||||
*/
|
||||
#ifdef _WIN64
|
||||
typedef signed long long int khronos_intptr_t;
|
||||
typedef unsigned long long int khronos_uintptr_t;
|
||||
typedef signed long long int khronos_ssize_t;
|
||||
typedef unsigned long long int khronos_usize_t;
|
||||
#else
|
||||
typedef signed long int khronos_intptr_t;
|
||||
typedef unsigned long int khronos_uintptr_t;
|
||||
typedef signed long int khronos_ssize_t;
|
||||
typedef unsigned long int khronos_usize_t;
|
||||
#endif
|
||||
|
||||
#if KHRONOS_SUPPORT_FLOAT
|
||||
/*
|
||||
@@ -266,4 +279,4 @@ typedef enum {
|
||||
KHRONOS_BOOLEAN_ENUM_FORCE_SIZE = KHRONOS_MAX_ENUM
|
||||
} khronos_boolean_enum_t;
|
||||
|
||||
#endif /* __khrplatform_h_ */
|
||||
#endif /* __khrplatform_h_ */
|
||||
@@ -26,6 +26,8 @@
|
||||
|
||||
#if !defined(ANDROID)
|
||||
#include <linux/joystick.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/types.h>
|
||||
#endif
|
||||
|
||||
#ifdef TARGET_PANDORA
|
||||
@@ -717,3 +719,6 @@ u32 os_Push(void* frame, u32 samples, bool wait)
|
||||
return 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
int get_mic_data(u8* buffer) { return 0; }
|
||||
int push_vmu_screen(u8* buffer) { return 0; }
|
||||
@@ -34,9 +34,21 @@ struct sigcontext uc_mcontext;
|
||||
|
||||
#if HOST_CPU == CPU_ARM
|
||||
#define GET_PC_FROM_CONTEXT(c) (((ucontext_t *)(c))->uc_mcontext.arm_pc)
|
||||
#elif HOST_CPU == CPU_MIPS
|
||||
#ifdef _ANDROID
|
||||
#define GET_PC_FROM_CONTEXT(c) (((ucontext_t *)(c))->uc_mcontext.sc_pc)
|
||||
#else
|
||||
#define GET_PC_FROM_CONTEXT(c) (((ucontext_t *)(c))->uc_mcontext.pc)
|
||||
#endif
|
||||
#elif HOST_CPU == CPU_X86
|
||||
#ifdef _ANDROID
|
||||
#define GET_PC_FROM_CONTEXT(c) (((ucontext_t *)(c))->uc_mcontext.eip)
|
||||
#else
|
||||
#define GET_PC_FROM_CONTEXT(c) (((ucontext_t *)(c))->uc_mcontext.gregs[REG_EIP])
|
||||
#endif
|
||||
#else
|
||||
#error fix ->pc support
|
||||
#endif
|
||||
|
||||
#include "hw/sh4/dyna/ngen.h"
|
||||
|
||||
@@ -155,12 +167,43 @@ void VArray2::LockRegion(u32 offset,u32 size)
|
||||
}
|
||||
}
|
||||
|
||||
void print_mem_addr()
|
||||
{
|
||||
FILE *ifp, *ofp;
|
||||
char *mode = "r";
|
||||
char outputFilename[] = "/data/data/com.reicast.emulator/files/mem_alloc.txt";
|
||||
|
||||
ifp = fopen("/proc/self/maps", mode);
|
||||
|
||||
if (ifp == NULL) {
|
||||
fprintf(stderr, "Can't open input file /proc/self/maps!\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
ofp = fopen(outputFilename, "w");
|
||||
|
||||
if (ofp == NULL) {
|
||||
fprintf(stderr, "Can't open output file %s!\n",
|
||||
outputFilename);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
char line [ 512 ];
|
||||
while (fgets(line, sizeof line, ifp) != NULL) {
|
||||
fprintf(ofp, "%s", line);
|
||||
}
|
||||
|
||||
fclose(ifp);
|
||||
fclose(ofp);
|
||||
}
|
||||
|
||||
void VArray2::UnLockRegion(u32 offset,u32 size)
|
||||
{
|
||||
u32 inpage=offset & PAGE_MASK;
|
||||
u32 rv=mprotect (data+offset-inpage, size+inpage, PROT_READ | PROT_WRITE);
|
||||
if (rv!=0)
|
||||
{
|
||||
print_mem_addr();
|
||||
printf("mprotect(%08X,%08X,RW) failed: %d | %d\n",data+offset-inpage,size+inpage,rv,errno);
|
||||
die("mprotect failed ..\n");
|
||||
}
|
||||
|
||||
+15
-2
@@ -58,11 +58,21 @@ typedef struct ucontext_t
|
||||
|
||||
#if HOST_CPU == CPU_ARM
|
||||
#define GET_PC_FROM_CONTEXT(c) (((ucontext_t *)(c))->uc_mcontext.arm_pc)
|
||||
#elif HOST_CPU == CPU_MIPS
|
||||
#ifdef _ANDROID
|
||||
#define GET_PC_FROM_CONTEXT(c) (((ucontext_t *)(c))->uc_mcontext.sc_pc)
|
||||
#else
|
||||
#define GET_PC_FROM_CONTEXT(c) (((ucontext_t *)(c))->uc_mcontext.pc)
|
||||
#endif
|
||||
|
||||
|
||||
#elif HOST_CPU == CPU_X86
|
||||
#ifdef _ANDROID
|
||||
#define GET_PC_FROM_CONTEXT(c) (((ucontext_t *)(c))->uc_mcontext.eip)
|
||||
#else
|
||||
#define GET_PC_FROM_CONTEXT(c) (((ucontext_t *)(c))->uc_mcontext.gregs[REG_EIP])
|
||||
#endif
|
||||
#else
|
||||
#error fix ->pc support
|
||||
#endif
|
||||
|
||||
/**
|
||||
@file CallStack_Android.h
|
||||
@@ -275,7 +285,10 @@ void* prof(void *ptr)
|
||||
|
||||
//Write shrec syms file !
|
||||
prof_head(prof_out, "jitsym", "SH4");
|
||||
|
||||
#if !defined(HOST_NO_REC)
|
||||
sh4_jitsym(prof_out);
|
||||
#endif
|
||||
|
||||
//Write arm7rec syms file ! -> to do
|
||||
//prof_head(prof_out,"jitsym","ARM7");
|
||||
|
||||
+23
-5
@@ -12,6 +12,8 @@
|
||||
#include "hw/maple/maple_cfg.h"
|
||||
#include "hw/sh4/sh4_mem.h"
|
||||
|
||||
#include "webui/server.h"
|
||||
|
||||
settings_t settings;
|
||||
|
||||
/*
|
||||
@@ -41,7 +43,7 @@ int GetFile(char *szFileName, char *szParse=0,u32 flags=0)
|
||||
if (strcmp(szFileName,"null")==0)
|
||||
{
|
||||
#if defined(OMAP4)
|
||||
strcpy(szFileName,GetPath("gdimage/crazy_taxi.chd").c_str());
|
||||
strcpy(szFileName,GetPath("/gdimage/crazy_taxi.chd").c_str());
|
||||
#else
|
||||
#if HOST_OS==OS_WINDOWS
|
||||
OPENFILENAME ofn;
|
||||
@@ -64,7 +66,7 @@ int GetFile(char *szFileName, char *szParse=0,u32 flags=0)
|
||||
//strcpy(szFileName,ofn.lpstrFile);
|
||||
}
|
||||
#else
|
||||
strcpy(szFileName,GetPath("discs/game.gdi").c_str());
|
||||
strcpy(szFileName,GetPath("/discs/game.gdi").c_str());
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
@@ -127,6 +129,17 @@ void plugins_Reset(bool Manual)
|
||||
}
|
||||
|
||||
|
||||
void* webui_th(void* p)
|
||||
{
|
||||
#if (HOST_OS == OS_WINDOWS || HOST_OS == OS_LINUX) && !defined(TARGET_PANDORA)
|
||||
webui_start();
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
cThread webui_thd(&webui_th,0);
|
||||
|
||||
int dc_init(int argc,wchar* argv[])
|
||||
{
|
||||
setbuf(stdin,0);
|
||||
@@ -138,18 +151,18 @@ int dc_init(int argc,wchar* argv[])
|
||||
return -1;
|
||||
}
|
||||
|
||||
webui_thd.Start();
|
||||
|
||||
if(ParseCommandLine(argc,argv))
|
||||
{
|
||||
return 69;
|
||||
}
|
||||
|
||||
if(!cfgOpen())
|
||||
{
|
||||
msgboxf("Unable to open config file",MBX_ICONERROR);
|
||||
return -4;
|
||||
}
|
||||
LoadSettings();
|
||||
|
||||
#ifndef _ANDROID
|
||||
os_CreateWindow();
|
||||
#endif
|
||||
@@ -207,21 +220,25 @@ void dc_term()
|
||||
plugins_Term();
|
||||
_vmem_release();
|
||||
|
||||
#ifndef _ANDROID
|
||||
SaveSettings();
|
||||
#endif
|
||||
SaveRomFiles(GetPath("/data/"));
|
||||
}
|
||||
|
||||
void LoadSettings()
|
||||
{
|
||||
#ifndef _ANDROID
|
||||
settings.dynarec.Enable = cfgLoadInt("config","Dynarec.Enabled", 1)!=0;
|
||||
settings.dynarec.idleskip = cfgLoadInt("config","Dynarec.idleskip",1)!=0;
|
||||
settings.dynarec.unstable_opt = cfgLoadInt("config","Dynarec.unstable-opt",0);
|
||||
settings.dreamcast.cable = cfgLoadInt("config","Dreamcast.Cable", 3);
|
||||
settings.dreamcast.cable = cfgLoadInt("config","Dreamcast.Cable",3);
|
||||
settings.dreamcast.RTC = cfgLoadInt("config","Dreamcast.RTC",GetRTC_now());
|
||||
settings.dreamcast.region = cfgLoadInt("config","Dreamcast.Region",3);
|
||||
settings.dreamcast.broadcast = cfgLoadInt("config","Dreamcast.Broadcast",4);
|
||||
settings.aica.LimitFPS = cfgLoadInt("config","aica.LimitFPS",1);
|
||||
settings.aica.NoBatch = cfgLoadInt("config","aica.NoBatch",0);
|
||||
settings.aica.NoSound = cfgLoadInt("config","aica.NoSound",0);
|
||||
settings.rend.UseMipmaps = cfgLoadInt("config","rend.UseMipmaps",1);
|
||||
settings.rend.WideScreen = cfgLoadInt("config","rend.WideScreen",0);
|
||||
|
||||
@@ -229,6 +246,7 @@ void LoadSettings()
|
||||
|
||||
settings.pvr.ta_skip = cfgLoadInt("config","ta.skip",0);
|
||||
settings.pvr.rend = cfgLoadInt("config","pvr.rend",0);
|
||||
#endif
|
||||
|
||||
#if (HOST_OS != OS_LINUX || defined(_ANDROID) || defined(TARGET_PANDORA))
|
||||
settings.aica.BufferSize=2048;
|
||||
|
||||
+3
-1
@@ -28,4 +28,6 @@ u32 INLINE bitscanrev(u32 v)
|
||||
}
|
||||
|
||||
//FIX ME
|
||||
#define __assume(x)
|
||||
#define __assume(x)
|
||||
|
||||
void os_DebugBreak();
|
||||
@@ -41,7 +41,11 @@ MOV R1, #1
|
||||
B _Z8YUV_dataPjj
|
||||
|
||||
TAWriteSQ_vram: @vram write ..
|
||||
#ifdef TARGET_IPHONE
|
||||
bkpt #0
|
||||
#else
|
||||
bkpt
|
||||
#endif
|
||||
ubfx r0,r3,#5,#18 @ get vram offset
|
||||
add r3,r1,#0x04000000 @ get vram ptr from r1, part 1
|
||||
add r3,#512 @ get ram ptr from r1, part 2
|
||||
@@ -157,13 +161,23 @@ arm_compilecode:
|
||||
bl CompileCode
|
||||
b arm_dispatch
|
||||
|
||||
#ifdef TARGET_IPHONE
|
||||
Xarm_Reg: .word arm_Reg
|
||||
XEntryPoints: .word EntryPoints
|
||||
#endif
|
||||
|
||||
.global arm_mainloop
|
||||
arm_mainloop: @(cntx,lookup_base,cycles)
|
||||
|
||||
push {r4,r5,r8,r9,lr}
|
||||
|
||||
#ifdef TARGET_IPHONE
|
||||
ldr r8,Xarm_Reg @load cntx
|
||||
ldr r4,XEntryPoints @load lookup base
|
||||
#else
|
||||
ldr r8,=arm_Reg @load cntx
|
||||
ldr r4,=EntryPoints @load lookup base
|
||||
#endif
|
||||
|
||||
ldr r5,[r8,#192] @load cycle count
|
||||
add r5,r0 @add cycles for this timeslice
|
||||
@@ -172,7 +186,12 @@ push {r4,r5,r8,r9,lr}
|
||||
|
||||
.global arm_dispatch
|
||||
arm_dispatch:
|
||||
#ifdef TARGET_IPHONE
|
||||
ldrd r0,r1,[r8,#184] @load: Next PC, interrupt
|
||||
#else
|
||||
ldrd r0,[r8,#184] @load: Next PC, interrupt
|
||||
#endif
|
||||
|
||||
ubfx r2,r0,#2,#19
|
||||
cmp r1,#0
|
||||
bne arm_dofiq
|
||||
|
||||
@@ -76,6 +76,11 @@ struct d3d11 : Renderer
|
||||
void Resize(int w, int h) { }
|
||||
void Term() { }
|
||||
|
||||
bool Process(TA_context* ctx)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Render()
|
||||
{
|
||||
if (!pvrrc.isRTT)
|
||||
|
||||
+30
-28
@@ -81,11 +81,11 @@ u32 gcflip;
|
||||
static struct
|
||||
{
|
||||
TSP tsp;
|
||||
TCW tcw;
|
||||
//TCW tcw;
|
||||
PCW pcw;
|
||||
ISP_TSP isp;
|
||||
u32 clipmode;
|
||||
u32 texture_enabled;
|
||||
//u32 texture_enabled;
|
||||
u32 stencil_modvol_on;
|
||||
u32 program;
|
||||
GLuint texture;
|
||||
@@ -95,11 +95,11 @@ static struct
|
||||
program=~0;
|
||||
texture=~0;
|
||||
tsp.full = ~gp->tsp.full;
|
||||
tcw.full = ~gp->tcw.full;
|
||||
//tcw.full = ~gp->tcw.full;
|
||||
pcw.full = ~gp->pcw.full;
|
||||
isp.full = ~gp->isp.full;
|
||||
clipmode=0xFFFFFFFF;
|
||||
texture_enabled=~gp->pcw.Texture;
|
||||
// texture_enabled=~gp->pcw.Texture;
|
||||
stencil_modvol_on=false;
|
||||
}
|
||||
} cache;
|
||||
@@ -194,36 +194,29 @@ __forceinline
|
||||
glStencilFunc(GL_ALWAYS,stencil,stencil);
|
||||
}
|
||||
|
||||
if ((gp->tcw.full != cache.tcw.full) || (gp->tsp.full!=cache.tsp.full) || (cache.texture_enabled!= gp->pcw.Texture))
|
||||
if (gp->texid != cache.texture)
|
||||
{
|
||||
cache.tcw=gp->tcw;
|
||||
cache.texture_enabled = gp->pcw.Texture;
|
||||
|
||||
if (gp->pcw.Texture)
|
||||
{
|
||||
GLuint tex=GetTexture(gp->tsp,gp->tcw);
|
||||
if (tex!=cache.texture)
|
||||
{
|
||||
glBindTexture(GL_TEXTURE_2D,tex);
|
||||
cache.texture=tex;
|
||||
}
|
||||
cache.texture=gp->texid;
|
||||
if (gp->texid != -1) {
|
||||
//verify(glIsTexture(gp->texid));
|
||||
glBindTexture(GL_TEXTURE_2D, gp->texid);
|
||||
}
|
||||
}
|
||||
|
||||
if (gp->tsp.full!=cache.tsp.full)
|
||||
if (gp->tsp.full!=cache.tsp.full)
|
||||
{
|
||||
cache.tsp=gp->tsp;
|
||||
|
||||
if (Type==ListType_Translucent)
|
||||
{
|
||||
cache.tsp=gp->tsp;
|
||||
|
||||
if (Type==ListType_Translucent)
|
||||
{
|
||||
glBlendFunc(SrcBlendGL[gp->tsp.SrcInstr],DstBlendGL[gp->tsp.DstInstr]);
|
||||
glBlendFunc(SrcBlendGL[gp->tsp.SrcInstr],DstBlendGL[gp->tsp.DstInstr]);
|
||||
|
||||
#ifdef WEIRD_SLOWNESS
|
||||
//SGX seems to be super slow with discard enabled blended pixels
|
||||
//can't cache this -- due to opengl shader api
|
||||
bool clip_alpha_on_zero=gp->tsp.SrcInstr==4 && (gp->tsp.DstInstr==1 || gp->tsp.DstInstr==5);
|
||||
glUniform1f(CurrentShader->cp_AlphaTestValue,clip_alpha_on_zero?(1/255.f):(-2.f));
|
||||
//SGX seems to be super slow with discard enabled blended pixels
|
||||
//can't cache this -- due to opengl shader api
|
||||
bool clip_alpha_on_zero=gp->tsp.SrcInstr==4 && (gp->tsp.DstInstr==1 || gp->tsp.DstInstr==5);
|
||||
glUniform1f(CurrentShader->cp_AlphaTestValue,clip_alpha_on_zero?(1/255.f):(-2.f));
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -720,7 +713,7 @@ void GenSorted()
|
||||
|
||||
if (idx!=pid /* && !PP_EQ(&pp_base[pid],&pp_base[idx]) */ )
|
||||
{
|
||||
SortTrigDrawParam stdp={pp_base + pid, i*3, 0};
|
||||
SortTrigDrawParam stdp={pp_base + pid, (u16)(i*3), 0};
|
||||
|
||||
if (idx!=-1)
|
||||
{
|
||||
@@ -911,8 +904,13 @@ void SetMVS_Mode(u32 mv_mode,ISP_Modvol ispc)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void SetupMainVBO()
|
||||
{
|
||||
#ifndef GLES
|
||||
glBindVertexArray(gl.vbo.vao);
|
||||
#endif
|
||||
|
||||
glBindBuffer(GL_ARRAY_BUFFER, gl.vbo.geometry); glCheck();
|
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, gl.vbo.idxs); glCheck();
|
||||
|
||||
@@ -932,6 +930,10 @@ void SetupMainVBO()
|
||||
|
||||
void SetupModvolVBO()
|
||||
{
|
||||
#ifndef GLES
|
||||
glBindVertexArray(gl.vbo.vao);
|
||||
#endif
|
||||
|
||||
glBindBuffer(GL_ARRAY_BUFFER, gl.vbo.modvols); glCheck();
|
||||
|
||||
//setup vertex buffers attrib pointers
|
||||
|
||||
+417
-55
@@ -15,6 +15,11 @@
|
||||
int fbdev = -1;
|
||||
#endif
|
||||
|
||||
#ifndef GLES
|
||||
#include <GL3/gl3w.c>
|
||||
#pragma comment(lib,"Opengl32.lib")
|
||||
#endif
|
||||
|
||||
/*
|
||||
GL|ES 2
|
||||
Slower, smaller subset of gl2
|
||||
@@ -57,25 +62,36 @@ float fb_scale_x,fb_scale_y;
|
||||
|
||||
volatile bool render_restart = false;
|
||||
|
||||
#ifndef GLES
|
||||
#define attr "in"
|
||||
#define vary "out"
|
||||
#else
|
||||
#define attr "attribute"
|
||||
#define vary "varying"
|
||||
#endif
|
||||
#if 1
|
||||
|
||||
//Fragment and vertex shaders code
|
||||
//pretty much 1:1 copy of the d3d ones for now
|
||||
const char* VertexShaderSource = "\
|
||||
const char* VertexShaderSource =
|
||||
#ifndef GLES
|
||||
"#version 140 \n"
|
||||
#endif
|
||||
"\
|
||||
/* Vertex constants*/ \n\
|
||||
uniform highp vec4 scale; \n\
|
||||
uniform highp vec4 depth_scale; \n\
|
||||
uniform highp float sp_FOG_DENSITY; \n\
|
||||
/* Vertex output */ \n\
|
||||
attribute highp vec4 in_pos; \n\
|
||||
attribute lowp vec4 in_base; \n\
|
||||
attribute lowp vec4 in_offs; \n\
|
||||
attribute mediump vec2 in_uv; \n\
|
||||
/* Transformed input */ \n\
|
||||
varying lowp vec4 vtx_base; \n\
|
||||
varying lowp vec4 vtx_offs; \n\
|
||||
varying mediump vec2 vtx_uv; \n\
|
||||
varying highp vec3 vtx_xyz; \n\
|
||||
/* Vertex input */ \n\
|
||||
" attr " highp vec4 in_pos; \n\
|
||||
" attr " lowp vec4 in_base; \n\
|
||||
" attr " lowp vec4 in_offs; \n\
|
||||
" attr " mediump vec2 in_uv; \n\
|
||||
/* output */ \n\
|
||||
" vary " lowp vec4 vtx_base; \n\
|
||||
" vary " lowp vec4 vtx_offs; \n\
|
||||
" vary " mediump vec2 vtx_uv; \n\
|
||||
" vary " highp vec3 vtx_xyz; \n\
|
||||
void main() \n\
|
||||
{ \n\
|
||||
vtx_base=in_base; \n\
|
||||
@@ -199,7 +215,22 @@ lowp float fog_mode2(highp float invW) \n\
|
||||
} \n\
|
||||
*/
|
||||
|
||||
const char* PixelPipelineShader = "\
|
||||
#ifndef GLES
|
||||
#define FRAGCOL "FragColor"
|
||||
#define TEXLOOKUP "texture"
|
||||
#define vary "in"
|
||||
#else
|
||||
#define FRAGCOL "gl_FragColor"
|
||||
#define TEXLOOKUP "texture2D"
|
||||
#endif
|
||||
|
||||
|
||||
const char* PixelPipelineShader =
|
||||
#ifndef GLES
|
||||
"#version 140 \n"
|
||||
"out vec4 FragColor; \n"
|
||||
#endif
|
||||
"\
|
||||
\
|
||||
#define cp_AlphaTest %d \n\
|
||||
#define pp_ClipTestMode %d.0 \n\
|
||||
@@ -217,10 +248,10 @@ uniform lowp vec3 sp_FOG_COL_RAM,sp_FOG_COL_VERT; \n\
|
||||
uniform highp vec2 sp_LOG_FOG_COEFS; \n\
|
||||
uniform sampler2D tex,fog_table; \n\
|
||||
/* Vertex input*/ \n\
|
||||
varying lowp vec4 vtx_base; \n\
|
||||
varying lowp vec4 vtx_offs; \n\
|
||||
varying mediump vec2 vtx_uv; \n\
|
||||
varying highp vec3 vtx_xyz; \n\
|
||||
" vary " lowp vec4 vtx_base; \n\
|
||||
" vary " lowp vec4 vtx_offs; \n\
|
||||
" vary " mediump vec2 vtx_uv; \n\
|
||||
" vary " highp vec3 vtx_xyz; \n\
|
||||
lowp float fog_mode2(highp float val) \n\
|
||||
{ \n\
|
||||
highp float fog_idx=clamp(val,0.0,127.99); \n\
|
||||
@@ -237,7 +268,7 @@ void main() \n\
|
||||
#endif\n\
|
||||
#if pp_Texture==1 \n\
|
||||
{ \n\
|
||||
lowp vec4 texcol=texture2D(tex,vtx_uv); \n\
|
||||
lowp vec4 texcol=" TEXLOOKUP "(tex,vtx_uv); \n\
|
||||
\n\
|
||||
#if pp_IgnoreTexA==1 \n\
|
||||
texcol.a=1.0; \n\
|
||||
@@ -284,27 +315,37 @@ void main() \n\
|
||||
if (cp_AlphaTestValue>color.a) discard;\n\
|
||||
#endif \n\
|
||||
//color.rgb=vec3(vtx_xyz.z/255.0);\n\
|
||||
gl_FragColor=color; \n\
|
||||
" FRAGCOL "=color; \n\
|
||||
}";
|
||||
|
||||
const char* ModifierVolumeShader = " \
|
||||
const char* ModifierVolumeShader =
|
||||
#ifndef GLES
|
||||
"#version 140 \n"
|
||||
"out vec4 FragColor; \n"
|
||||
#endif
|
||||
" \
|
||||
uniform lowp float sp_ShaderColor; \n\
|
||||
/* Vertex input*/ \n\
|
||||
void main() \n\
|
||||
{ \n\
|
||||
gl_FragColor=vec4(0.0, 0.0, 0.0, sp_ShaderColor); \n\
|
||||
" FRAGCOL "=vec4(0.0, 0.0, 0.0, sp_ShaderColor); \n\
|
||||
}";
|
||||
|
||||
const char* OSD_Shader = " \
|
||||
varying lowp vec4 vtx_base; \n\
|
||||
varying mediump vec2 vtx_uv; \n\
|
||||
const char* OSD_Shader =
|
||||
#ifndef GLES
|
||||
"#version 140 \n"
|
||||
"out vec4 FragColor; \n"
|
||||
#endif
|
||||
" \
|
||||
" vary " lowp vec4 vtx_base; \n\
|
||||
" vary " mediump vec2 vtx_uv; \n\
|
||||
/* Vertex input*/ \n\
|
||||
uniform sampler2D tex; \n\
|
||||
void main() \n\
|
||||
{ \n\
|
||||
mediump vec2 uv=vtx_uv; \n\
|
||||
uv.y=1.0-uv.y; \n\
|
||||
gl_FragColor=vtx_base*texture2D(tex,uv); \n\n\
|
||||
" FRAGCOL "=vtx_base*" TEXLOOKUP "(tex,uv.st); \n\n\
|
||||
}";
|
||||
|
||||
|
||||
@@ -313,12 +354,13 @@ gl_ctx gl;
|
||||
int screen_width;
|
||||
int screen_height;
|
||||
|
||||
#ifdef GLES
|
||||
// Create a basic GLES context
|
||||
bool gl_init(EGLNativeWindowType wind, EGLNativeDisplayType disp)
|
||||
bool gl_init(void* wind, void* disp)
|
||||
{
|
||||
#if !defined(_ANDROID)
|
||||
gl.setup.native_wind=wind;
|
||||
gl.setup.native_disp=disp;
|
||||
gl.setup.native_wind=(EGLNativeWindowType)wind;
|
||||
gl.setup.native_disp=(EGLNativeDisplayType)disp;
|
||||
|
||||
//try to get a display
|
||||
gl.setup.display = eglGetDisplay(gl.setup.native_disp);
|
||||
@@ -427,6 +469,135 @@ void gl_term()
|
||||
gl.setup.display=0;
|
||||
#endif
|
||||
}
|
||||
#else
|
||||
|
||||
#define WGL_DRAW_TO_WINDOW_ARB 0x2001
|
||||
#define WGL_ACCELERATION_ARB 0x2003
|
||||
#define WGL_SWAP_METHOD_ARB 0x2007
|
||||
#define WGL_SUPPORT_OPENGL_ARB 0x2010
|
||||
#define WGL_DOUBLE_BUFFER_ARB 0x2011
|
||||
#define WGL_PIXEL_TYPE_ARB 0x2013
|
||||
#define WGL_COLOR_BITS_ARB 0x2014
|
||||
#define WGL_DEPTH_BITS_ARB 0x2022
|
||||
#define WGL_STENCIL_BITS_ARB 0x2023
|
||||
#define WGL_FULL_ACCELERATION_ARB 0x2027
|
||||
#define WGL_SWAP_EXCHANGE_ARB 0x2028
|
||||
#define WGL_TYPE_RGBA_ARB 0x202B
|
||||
#define WGL_CONTEXT_MAJOR_VERSION_ARB 0x2091
|
||||
#define WGL_CONTEXT_MINOR_VERSION_ARB 0x2092
|
||||
#define WGL_CONTEXT_FLAGS_ARB 0x2094
|
||||
|
||||
#define WGL_CONTEXT_PROFILE_MASK_ARB 0x9126
|
||||
#define WGL_CONTEXT_MAJOR_VERSION_ARB 0x2091
|
||||
#define WGL_CONTEXT_MINOR_VERSION_ARB 0x2092
|
||||
#define WGL_CONTEXT_LAYER_PLANE_ARB 0x2093
|
||||
#define WGL_CONTEXT_FLAGS_ARB 0x2094
|
||||
#define WGL_CONTEXT_DEBUG_BIT_ARB 0x0001
|
||||
#define WGL_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB 0x0002
|
||||
#define ERROR_INVALID_VERSION_ARB 0x2095
|
||||
#define WGL_CONTEXT_CORE_PROFILE_BIT_ARB 0x00000001
|
||||
|
||||
typedef BOOL (WINAPI * PFNWGLCHOOSEPIXELFORMATARBPROC) (HDC hdc, const int *piAttribIList, const FLOAT *pfAttribFList, UINT nMaxFormats,
|
||||
int *piFormats, UINT *nNumFormats);
|
||||
typedef HGLRC (WINAPI * PFNWGLCREATECONTEXTATTRIBSARBPROC) (HDC hDC, HGLRC hShareContext, const int *attribList);
|
||||
typedef BOOL (WINAPI * PFNWGLSWAPINTERVALEXTPROC) (int interval);
|
||||
|
||||
PFNWGLCHOOSEPIXELFORMATARBPROC wglChoosePixelFormatARB;
|
||||
PFNWGLCREATECONTEXTATTRIBSARBPROC wglCreateContextAttribsARB;
|
||||
PFNWGLSWAPINTERVALEXTPROC wglSwapIntervalEXT;
|
||||
|
||||
|
||||
HDC ourWindowHandleToDeviceContext;
|
||||
bool gl_init(void* hwnd, void* hdc)
|
||||
{
|
||||
PIXELFORMATDESCRIPTOR pfd =
|
||||
{
|
||||
sizeof(PIXELFORMATDESCRIPTOR),
|
||||
1,
|
||||
PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER, //Flags
|
||||
PFD_TYPE_RGBA, //The kind of framebuffer. RGBA or palette.
|
||||
32, //Colordepth of the framebuffer.
|
||||
0, 0, 0, 0, 0, 0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0, 0, 0, 0,
|
||||
24, //Number of bits for the depthbuffer
|
||||
8, //Number of bits for the stencilbuffer
|
||||
0, //Number of Aux buffers in the framebuffer.
|
||||
PFD_MAIN_PLANE,
|
||||
0,
|
||||
0, 0, 0
|
||||
};
|
||||
|
||||
/*HDC*/ ourWindowHandleToDeviceContext = (HDC)hdc;//GetDC((HWND)hwnd);
|
||||
|
||||
int letWindowsChooseThisPixelFormat;
|
||||
letWindowsChooseThisPixelFormat = ChoosePixelFormat(ourWindowHandleToDeviceContext, &pfd);
|
||||
SetPixelFormat(ourWindowHandleToDeviceContext,letWindowsChooseThisPixelFormat, &pfd);
|
||||
|
||||
HGLRC ourOpenGLRenderingContext = wglCreateContext(ourWindowHandleToDeviceContext);
|
||||
wglMakeCurrent (ourWindowHandleToDeviceContext, ourOpenGLRenderingContext);
|
||||
|
||||
bool rv = true;
|
||||
|
||||
if (rv) {
|
||||
|
||||
wglChoosePixelFormatARB = (PFNWGLCHOOSEPIXELFORMATARBPROC)wglGetProcAddress("wglChoosePixelFormatARB");
|
||||
if(!wglChoosePixelFormatARB)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
wglCreateContextAttribsARB = (PFNWGLCREATECONTEXTATTRIBSARBPROC)wglGetProcAddress("wglCreateContextAttribsARB");
|
||||
if(!wglCreateContextAttribsARB)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
wglSwapIntervalEXT = (PFNWGLSWAPINTERVALEXTPROC)wglGetProcAddress("wglSwapIntervalEXT");
|
||||
if(!wglSwapIntervalEXT)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
int attribs[] =
|
||||
{
|
||||
WGL_CONTEXT_MAJOR_VERSION_ARB, 3,
|
||||
WGL_CONTEXT_MINOR_VERSION_ARB, 1,
|
||||
WGL_CONTEXT_FLAGS_ARB, WGL_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB,
|
||||
WGL_CONTEXT_PROFILE_MASK_ARB, WGL_CONTEXT_CORE_PROFILE_BIT_ARB,
|
||||
0
|
||||
};
|
||||
|
||||
HGLRC m_hrc = wglCreateContextAttribsARB(ourWindowHandleToDeviceContext,0, attribs);
|
||||
|
||||
if (m_hrc)
|
||||
wglMakeCurrent(ourWindowHandleToDeviceContext,m_hrc);
|
||||
else
|
||||
rv = false;
|
||||
|
||||
wglDeleteContext(ourOpenGLRenderingContext);
|
||||
}
|
||||
|
||||
if (rv) {
|
||||
rv = gl3wInit() != -1 && gl3wIsSupported(3, 1);
|
||||
}
|
||||
|
||||
RECT r;
|
||||
GetClientRect((HWND)hwnd, &r);
|
||||
screen_width = r.right - r.left;
|
||||
screen_height = r.bottom - r.top;
|
||||
|
||||
return rv;
|
||||
}
|
||||
#include <Wingdi.h>
|
||||
void gl_swap()
|
||||
{
|
||||
wglSwapLayerBuffers(ourWindowHandleToDeviceContext,WGL_SWAP_MAIN_PLANE);
|
||||
//SwapBuffers(ourWindowHandleToDeviceContext);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
struct ShaderUniforms_t
|
||||
@@ -509,6 +680,10 @@ GLuint gl_CompileAndLink(const char* VertexShader, const char* FragmentShader)
|
||||
glBindAttribLocation(program, VERTEX_COL_OFFS_ARRAY, "in_offs");
|
||||
glBindAttribLocation(program, VERTEX_UV_ARRAY, "in_uv");
|
||||
|
||||
#ifndef GLES
|
||||
glBindFragDataLocation(program, 0, "FragColor");
|
||||
#endif
|
||||
|
||||
glLinkProgram(program);
|
||||
|
||||
GLint result;
|
||||
@@ -610,9 +785,20 @@ bool CompilePipelineShader( PipelineShader* s)
|
||||
}
|
||||
|
||||
GLuint osd_tex;
|
||||
#ifdef TARGET_PANDORA
|
||||
GLuint osd_font;
|
||||
#endif
|
||||
|
||||
bool gl_create_resources()
|
||||
{
|
||||
|
||||
#ifndef GLES
|
||||
//create vao
|
||||
//This is really not "proper", vaos are suposed to be defined once
|
||||
//i keep updating the same one to make the es2 code work in 3.1 context
|
||||
glGenVertexArrays(1, &gl.vbo.vao);
|
||||
#endif
|
||||
|
||||
//create vbos
|
||||
glGenBuffers(1, &gl.vbo.geometry);
|
||||
glGenBuffers(1, &gl.vbo.modvols);
|
||||
@@ -686,12 +872,14 @@ bool gl_create_resources()
|
||||
|
||||
int w, h;
|
||||
osd_tex=loadPNG(GetPath("/data/buttons.png"),w,h);
|
||||
#ifdef TARGET_PANDORA
|
||||
osd_font=loadPNG(GetPath("/font2.png"),w,h);
|
||||
#endif
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//create a basic gles context
|
||||
bool gl_init(EGLNativeWindowType wind, EGLNativeDisplayType disp);
|
||||
bool gl_init(void* wind, void* disp);
|
||||
|
||||
//swap buffers
|
||||
void gl_swap();
|
||||
@@ -707,19 +895,21 @@ bool gl_create_resources();
|
||||
|
||||
bool gles_init()
|
||||
{
|
||||
if (!gl_init((EGLNativeWindowType)libPvr_GetRenderTarget(),
|
||||
(EGLNativeDisplayType)libPvr_GetRenderSurface()))
|
||||
|
||||
if (!gl_init((void*)libPvr_GetRenderTarget(),
|
||||
(void*)libPvr_GetRenderSurface()))
|
||||
return false;
|
||||
|
||||
if (!gl_create_resources())
|
||||
return false;
|
||||
|
||||
|
||||
#ifdef GLES
|
||||
#ifdef TARGET_PANDORA
|
||||
fbdev=open("/dev/fb0", O_RDONLY);
|
||||
#else
|
||||
eglSwapInterval(gl.setup.display,1);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
//clean up all buffers ...
|
||||
for (int i=0;i<10;i++)
|
||||
@@ -897,12 +1087,120 @@ static void ClearBG()
|
||||
|
||||
|
||||
void DrawButton2(float* xy, bool state) { DrawButton(xy,state?0:255); }
|
||||
#ifdef TARGET_PANDORA
|
||||
static void DrawCenteredText(float yy, float scale, int transparency, const char* text)
|
||||
// Draw a centered text. Font is loaded from font2.png file. Each char is 16*16 size, so scale it down so it's not too big
|
||||
// Transparency 255=opaque, 0=not visible
|
||||
{
|
||||
Vertex vtx;
|
||||
|
||||
vtx.z=1;
|
||||
|
||||
float w=float(strlen(text)*14)*scale;
|
||||
|
||||
float x=320-w/2.0f;
|
||||
float y=yy;
|
||||
float h=16.0f*scale;
|
||||
w=14.0f*scale;
|
||||
float step=32.0f/512.0f;
|
||||
float step2=4.0f/512.0f;
|
||||
|
||||
if (transparency<0) transparency=0;
|
||||
if (transparency>255) transparency=255;
|
||||
|
||||
for (int i=0; i<strlen(text); i++) {
|
||||
int c=text[i];
|
||||
float u=float(c%16);
|
||||
float v=float(c/16);
|
||||
|
||||
vtx.col[0]=vtx.col[1]=vtx.col[2]=255;
|
||||
vtx.col[3]=transparency;
|
||||
|
||||
vtx.x=x; vtx.y=y;
|
||||
vtx.u=u*step+step2; vtx.v=v*step+step2;
|
||||
*pvrrc.verts.Append()=vtx;
|
||||
|
||||
vtx.x=x+w; vtx.y=y;
|
||||
vtx.u=u*step+step-step2; vtx.v=v*step+step2;
|
||||
*pvrrc.verts.Append()=vtx;
|
||||
|
||||
vtx.x=x; vtx.y=y+h;
|
||||
vtx.u=u*step+step2; vtx.v=v*step+step-step2;
|
||||
*pvrrc.verts.Append()=vtx;
|
||||
|
||||
vtx.x=x+w; vtx.y=y+h;
|
||||
vtx.u=u*step+step-step2; vtx.v=v*step+step-step2;
|
||||
*pvrrc.verts.Append()=vtx;
|
||||
|
||||
x+=w;
|
||||
|
||||
osd_count+=4;
|
||||
}
|
||||
}
|
||||
static void DrawRightedText(float yy, float scale, int transparency, const char* text)
|
||||
// Draw a text right justified. Font is loaded from font2.png file. Each char is 16*16 size, so scale it down so it's not too big
|
||||
// Transparency 255=opaque, 0=not visible
|
||||
{
|
||||
Vertex vtx;
|
||||
|
||||
vtx.z=1;
|
||||
|
||||
float w=float(strlen(text)*14)*scale;
|
||||
|
||||
float x=640-w;
|
||||
float y=yy;
|
||||
float h=16.0f*scale;
|
||||
w=14.0f*scale;
|
||||
float step=32.0f/512.0f;
|
||||
float step2=4.0f/512.0f;
|
||||
|
||||
if (transparency<0) transparency=0;
|
||||
if (transparency>255) transparency=255;
|
||||
|
||||
for (int i=0; i<strlen(text); i++) {
|
||||
int c=text[i];
|
||||
float u=float(c%16);
|
||||
float v=float(c/16);
|
||||
|
||||
vtx.col[0]=vtx.col[1]=vtx.col[2]=255;
|
||||
vtx.col[3]=transparency;
|
||||
|
||||
vtx.x=x; vtx.y=y;
|
||||
vtx.u=u*step+step2; vtx.v=v*step+step2;
|
||||
*pvrrc.verts.Append()=vtx;
|
||||
|
||||
vtx.x=x+w; vtx.y=y;
|
||||
vtx.u=u*step+step-step2; vtx.v=v*step+step2;
|
||||
*pvrrc.verts.Append()=vtx;
|
||||
|
||||
vtx.x=x; vtx.y=y+h;
|
||||
vtx.u=u*step+step2; vtx.v=v*step+step-step2;
|
||||
*pvrrc.verts.Append()=vtx;
|
||||
|
||||
vtx.x=x+w; vtx.y=y+h;
|
||||
vtx.u=u*step+step-step2; vtx.v=v*step+step-step2;
|
||||
*pvrrc.verts.Append()=vtx;
|
||||
|
||||
x+=w;
|
||||
|
||||
osd_count+=4;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef TARGET_PANDORA
|
||||
char OSD_Info[128];
|
||||
int OSD_Delay=0;
|
||||
char OSD_Counters[256];
|
||||
int OSD_Counter=0;
|
||||
#endif
|
||||
|
||||
static void OSD_HOOK()
|
||||
{
|
||||
osd_base=pvrrc.verts.used();
|
||||
osd_count=0;
|
||||
|
||||
#ifndef TARGET_PANDORA
|
||||
DrawButton2(vjoy_pos[0],kcode[0]&key_CONT_DPAD_LEFT);
|
||||
DrawButton2(vjoy_pos[1],kcode[0]&key_CONT_DPAD_UP);
|
||||
DrawButton2(vjoy_pos[2],kcode[0]&key_CONT_DPAD_RIGHT);
|
||||
@@ -921,15 +1219,29 @@ static void OSD_HOOK()
|
||||
|
||||
DrawButton2(vjoy_pos[11],1);
|
||||
DrawButton2(vjoy_pos[12],0);
|
||||
#endif
|
||||
#ifdef TARGET_PANDORA
|
||||
if (OSD_Delay) {
|
||||
DrawCenteredText(400, 1.0f, (OSD_Delay<255)?OSD_Delay:255, OSD_Info);
|
||||
OSD_Delay--; //*TODO* Delay should be in ms, not in ticks...
|
||||
}
|
||||
if (OSD_Counter) {
|
||||
DrawRightedText(20, 1.0f, 255, OSD_Counters);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
extern GLuint osd_tex;
|
||||
#ifdef TARGET_PANDORA
|
||||
extern GLuint osd_font;
|
||||
#endif
|
||||
|
||||
#define OSD_TEX_W 512
|
||||
#define OSD_TEX_H 256
|
||||
|
||||
void OSD_DRAW()
|
||||
{
|
||||
#ifndef TARGET_PANDORA
|
||||
if (osd_tex)
|
||||
{
|
||||
float u=0;
|
||||
@@ -959,7 +1271,7 @@ void OSD_DRAW()
|
||||
glUseProgram(gl.OSD_SHADER.program);
|
||||
|
||||
//reset rendering scale
|
||||
|
||||
/*
|
||||
float dc_width=640;
|
||||
float dc_height=480;
|
||||
|
||||
@@ -973,7 +1285,7 @@ void OSD_DRAW()
|
||||
ShaderUniforms.scale_coefs[3]=-1;
|
||||
|
||||
glUniform4fv( gl.OSD_SHADER.scale, 1, ShaderUniforms.scale_coefs);
|
||||
|
||||
*/
|
||||
|
||||
glEnable(GL_BLEND);
|
||||
glDisable(GL_DEPTH_TEST);
|
||||
@@ -990,21 +1302,78 @@ void OSD_DRAW()
|
||||
for (int i=0;i<dfa;i++)
|
||||
glDrawArrays(GL_TRIANGLE_STRIP,osd_base+i*4,4);
|
||||
}
|
||||
#endif
|
||||
#ifdef TARGET_PANDORA
|
||||
if (osd_font)
|
||||
{
|
||||
float u=0;
|
||||
float v=0;
|
||||
|
||||
verify(glIsProgram(gl.OSD_SHADER.program));
|
||||
|
||||
float dc_width=640;
|
||||
float dc_height=480;
|
||||
|
||||
float dc2s_scale_h=screen_height/480.0f;
|
||||
float ds2s_offs_x=(screen_width-dc2s_scale_h*640)/2;
|
||||
|
||||
|
||||
glBindTexture(GL_TEXTURE_2D,osd_font);
|
||||
glUseProgram(gl.OSD_SHADER.program);
|
||||
|
||||
/*
|
||||
//-1 -> too much to left
|
||||
ShaderUniforms.scale_coefs[0]=2.0f/(screen_width/dc2s_scale_h);
|
||||
ShaderUniforms.scale_coefs[1]=-2/dc_height;
|
||||
ShaderUniforms.scale_coefs[2]=1-2*ds2s_offs_x/(screen_width);
|
||||
ShaderUniforms.scale_coefs[3]=-1;
|
||||
|
||||
glUniform4fv( gl.OSD_SHADER.scale, 1, ShaderUniforms.scale_coefs);
|
||||
*/
|
||||
|
||||
glEnable(GL_BLEND);
|
||||
glDisable(GL_DEPTH_TEST);
|
||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||
|
||||
|
||||
glDepthMask(false);
|
||||
glDepthFunc(GL_ALWAYS);
|
||||
|
||||
|
||||
glDisable(GL_CULL_FACE);
|
||||
glDisable(GL_SCISSOR_TEST);
|
||||
|
||||
|
||||
int dfa=osd_count/4;
|
||||
|
||||
for (int i=0;i<dfa;i++)
|
||||
glDrawArrays(GL_TRIANGLE_STRIP,osd_base+i*4,4);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
bool ProcessFrame(TA_context* ctx)
|
||||
{
|
||||
//disable RTTs for now ..
|
||||
if (ctx->rend.isRTT)
|
||||
return false;
|
||||
|
||||
ctx->rend_inuse.Lock();
|
||||
ctx->MarkRend();
|
||||
|
||||
if (!ta_parse_vdrc(ctx))
|
||||
return false;
|
||||
|
||||
CollectCleanup();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool RenderFrame()
|
||||
{
|
||||
bool is_rtt=pvrrc.isRTT;//(FB_W_SOF1& 0x1000000)!=0;
|
||||
DoCleanup();
|
||||
|
||||
//disable RTTs for now ..
|
||||
if (is_rtt)
|
||||
return false;
|
||||
|
||||
_pvrrc->rend_inuse.Lock();
|
||||
_pvrrc->MarkRend();
|
||||
|
||||
if (!ta_parse_vdrc(_pvrrc))
|
||||
return false;
|
||||
bool is_rtt=pvrrc.isRTT;
|
||||
|
||||
OSD_HOOK();
|
||||
|
||||
@@ -1405,19 +1774,12 @@ struct glesrend : Renderer
|
||||
void Resize(int w, int h) { }
|
||||
void Term() { }
|
||||
|
||||
bool Render()
|
||||
{
|
||||
bool do_swp=RenderFrame();
|
||||
|
||||
if (do_swp)
|
||||
{
|
||||
OSD_DRAW();
|
||||
}
|
||||
|
||||
return do_swp;
|
||||
}
|
||||
bool Process(TA_context* ctx) { return ProcessFrame(ctx); }
|
||||
bool Render() { return RenderFrame(); }
|
||||
|
||||
void Present() { gl_swap(); }
|
||||
|
||||
void DrawOSD() { OSD_DRAW(); }
|
||||
};
|
||||
|
||||
|
||||
|
||||
Regular → Executable
+23
-6
@@ -1,9 +1,17 @@
|
||||
#pragma once
|
||||
#include "rend/rend.h"
|
||||
|
||||
|
||||
#ifdef GLES
|
||||
#ifdef TARGET_IPHONE //apple-specific ogles2 headers
|
||||
#include <APPLE/egl.h>
|
||||
#include <OpenGLES/ES2/gl.h>
|
||||
#include <OpenGLES/ES2/glext.h>
|
||||
#else
|
||||
#include <EGL/egl.h>
|
||||
#include <GLES2/gl2.h>
|
||||
#include <GLES2/gl2ext.h>
|
||||
#endif
|
||||
|
||||
#ifndef GL_NV_draw_path
|
||||
//IMGTEC GLES emulation
|
||||
@@ -11,9 +19,14 @@
|
||||
#pragma comment(lib,"libGLESv2.lib")
|
||||
#else /* NV gles emulation*/
|
||||
#pragma comment(lib,"libGLES20.lib")
|
||||
|
||||
#endif
|
||||
#define glCheck() false
|
||||
|
||||
#else
|
||||
#include <GL3/gl3w.h>
|
||||
#endif
|
||||
|
||||
|
||||
#define glCheck() verify(glGetError()==GL_NO_ERROR)
|
||||
#define eglCheck() false
|
||||
|
||||
#define VERTEX_POS_ARRAY 0
|
||||
@@ -21,10 +34,6 @@
|
||||
#define VERTEX_COL_OFFS_ARRAY 2
|
||||
#define VERTEX_UV_ARRAY 3
|
||||
|
||||
#ifdef TARGET_PANDORA
|
||||
#define WEIRD_SLOWNESS
|
||||
#endif
|
||||
|
||||
|
||||
//vertex types
|
||||
extern u32 gcflip;
|
||||
@@ -48,6 +57,7 @@ struct PipelineShader
|
||||
|
||||
struct gl_ctx
|
||||
{
|
||||
#ifdef GLES
|
||||
struct
|
||||
{
|
||||
EGLNativeWindowType native_wind;
|
||||
@@ -56,6 +66,7 @@ struct gl_ctx
|
||||
EGLSurface surface;
|
||||
EGLContext context;
|
||||
} setup;
|
||||
#endif
|
||||
|
||||
struct
|
||||
{
|
||||
@@ -75,6 +86,9 @@ struct gl_ctx
|
||||
struct
|
||||
{
|
||||
GLuint geometry,modvols,idxs,idxs2;
|
||||
#ifndef GLES
|
||||
GLuint vao;
|
||||
#endif
|
||||
} vbo;
|
||||
|
||||
|
||||
@@ -84,6 +98,9 @@ struct gl_ctx
|
||||
extern gl_ctx gl;
|
||||
|
||||
GLuint GetTexture(TSP tsp,TCW tcw);
|
||||
void CollectCleanup();
|
||||
void DoCleanup();
|
||||
|
||||
void BindRTT(u32 addy, u32 fbw, u32 fbh, u32 channels, u32 fmt);
|
||||
int GetProgramID(u32 cp_AlphaTest, u32 pp_ClipTestMode,
|
||||
u32 pp_Texture, u32 pp_UseAlpha, u32 pp_IgnoreTexA, u32 pp_ShadInstr, u32 pp_Offset,
|
||||
|
||||
@@ -78,7 +78,7 @@ struct TextureCacheData
|
||||
PvrTexInfo* tex;
|
||||
TexConvFP* texconv;
|
||||
|
||||
bool dirty;
|
||||
u32 dirty;
|
||||
vram_block* lock_block;
|
||||
|
||||
u32 Lookups;
|
||||
@@ -128,7 +128,7 @@ struct TextureCacheData
|
||||
//Reset state info ..
|
||||
Lookups=0;
|
||||
Updates=0;
|
||||
dirty=true;
|
||||
dirty=FrameCount;
|
||||
lock_block=0;
|
||||
|
||||
//decode info from tsp/tcw into the texture struct
|
||||
@@ -145,7 +145,9 @@ struct TextureCacheData
|
||||
SetRepeatMode(GL_TEXTURE_WRAP_S,tsp.ClampU,tsp.FlipU); // glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, (tsp.ClampU ? GL_CLAMP_TO_EDGE : (tsp.FlipU ? GL_MIRRORED_REPEAT : GL_REPEAT))) ;
|
||||
SetRepeatMode(GL_TEXTURE_WRAP_T,tsp.ClampV,tsp.FlipV); // glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, (tsp.ClampV ? GL_CLAMP_TO_EDGE : (tsp.FlipV ? GL_MIRRORED_REPEAT : GL_REPEAT))) ;
|
||||
|
||||
#ifdef GLES
|
||||
glHint(GL_GENERATE_MIPMAP_HINT, GL_NICEST);
|
||||
#endif
|
||||
|
||||
//set texture filter mode
|
||||
if ( tsp.FilterMode == 0 )
|
||||
@@ -242,7 +244,7 @@ struct TextureCacheData
|
||||
{
|
||||
//texture state tracking stuff
|
||||
Updates++;
|
||||
dirty=false;
|
||||
dirty=0;
|
||||
|
||||
GLuint textype=tex->type;
|
||||
|
||||
@@ -344,7 +346,11 @@ void BindRTT(u32 addy, u32 fbw, u32 fbh, u32 channels, u32 fmt)
|
||||
m_i32TexSize by m_i32TexSize.
|
||||
*/
|
||||
|
||||
#ifdef GLES
|
||||
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT24_OES, fbw, fbh);
|
||||
#else
|
||||
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT24, fbw, fbh);
|
||||
#endif
|
||||
|
||||
glGenRenderbuffers(1, &rv.stencilb);
|
||||
glBindRenderbuffer(GL_RENDERBUFFER, rv.stencilb);
|
||||
@@ -419,6 +425,32 @@ GLuint GetTexture(TSP tsp,TCW tcw)
|
||||
return tf->texID;
|
||||
}
|
||||
|
||||
void CollectCleanup() {
|
||||
vector<u64> list;
|
||||
|
||||
u32 TargetFrame = max((u32)120,FrameCount) - 120;
|
||||
|
||||
for (TexCacheIter i=TexCache.begin();i!=TexCache.end();i++)
|
||||
{
|
||||
if ( i->second.dirty && i->second.dirty < TargetFrame) {
|
||||
list.push_back(i->first);
|
||||
}
|
||||
|
||||
if (list.size() > 5)
|
||||
break;
|
||||
}
|
||||
|
||||
for (size_t i=0; i<list.size(); i++) {
|
||||
//printf("Deleting %d\n",TexCache[list[i]].texID);
|
||||
TexCache[list[i]].Delete();
|
||||
|
||||
TexCache.erase(list[i]);
|
||||
}
|
||||
}
|
||||
|
||||
void DoCleanup() {
|
||||
|
||||
}
|
||||
void killtex()
|
||||
{
|
||||
for (TexCacheIter i=TexCache.begin();i!=TexCache.end();i++)
|
||||
@@ -432,7 +464,7 @@ void killtex()
|
||||
void rend_text_invl(vram_block* bl)
|
||||
{
|
||||
TextureCacheData* tcd = (TextureCacheData*)bl->userdata;
|
||||
tcd->dirty=true;
|
||||
tcd->dirty=FrameCount;
|
||||
tcd->lock_block=0;
|
||||
|
||||
libCore_vramlock_Unlock_block_wb(bl);
|
||||
|
||||
Loaded 100 of 332 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user