mirror of
https://github.com/dragonpilot/dragonpilot.git
synced 2026-06-12 15:04:20 +08:00
Compare commits
18 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ae5cb7a0da | ||
|
|
e3ab9d6460 | ||
|
|
e425c1cf59 | ||
|
|
c210011c84 | ||
|
|
d5b884f824 | ||
|
|
2751d87d01 | ||
|
|
8849aa02a3 | ||
|
|
f49e9f4f09 | ||
|
|
f0a6db351e | ||
|
|
53b177b3c1 | ||
|
|
c6df34f55b | ||
|
|
28e3543ec4 | ||
|
|
ea6c19638c | ||
|
|
752df1681a | ||
|
|
7865525451 | ||
|
|
dcacbf606a | ||
|
|
4a5019d925 | ||
|
|
1b7b3b4e66 |
2
.gitignore
vendored
2
.gitignore
vendored
@@ -3,6 +3,7 @@
|
||||
.ipynb_checkpoints
|
||||
.idea
|
||||
model2.png
|
||||
a.out
|
||||
|
||||
*.DSYM
|
||||
*.d
|
||||
@@ -28,3 +29,4 @@ selfdrive/proclogd/proclogd
|
||||
selfdrive/ui/ui
|
||||
/src/
|
||||
|
||||
one
|
||||
|
||||
78
README.md
78
README.md
@@ -9,6 +9,15 @@ The openpilot codebase has been written to be concise and enable rapid prototypi
|
||||
|
||||
Here are [some](https://www.youtube.com/watch?v=9OwTJFuDI7g) [videos](https://www.youtube.com/watch?v=64Wvt5pYQmE) [of](https://www.youtube.com/watch?v=6IW7Nejsr3A) [it](https://www.youtube.com/watch?v=-VN1YcC83nA) [running](https://www.youtube.com/watch?v=EQJZvVeihZk). And a really cool [tutorial](https://www.youtube.com/watch?v=PwOnsT2UW5o).
|
||||
|
||||
Community
|
||||
------
|
||||
|
||||
openpilot is supported by [comma.ai](https://comma.ai/)
|
||||
|
||||
We have a [Twitter you should follow](https://twitter.com/comma_ai).
|
||||
|
||||
Also, we have a 3500+ person [community on slack](https://slack.comma.ai).
|
||||
|
||||
Hardware
|
||||
------
|
||||
|
||||
@@ -19,49 +28,75 @@ Install openpilot on a neo device by entering ``https://openpilot.comma.ai`` dur
|
||||
Supported Cars
|
||||
------
|
||||
|
||||
- Acura ILX 2016 with AcuraWatch Plus
|
||||
- Due to use of the cruise control for gas, it can only be enabled above 25 mph
|
||||
### Honda + Acura ###
|
||||
|
||||
- Honda Civic 2016-2018 with Honda Sensing
|
||||
- Honda Accord 2018 with Honda Sensing (alpha!)
|
||||
- Uses stock Honda Sensing for longitudinal control
|
||||
|
||||
- Honda Civic 2016+ with Honda Sensing
|
||||
- Due to limitations in steering firmware, steering is disabled below 12 mph
|
||||
- Note that the hatchback model is not supported
|
||||
|
||||
- Honda Civic Hatchback 2017+ with Honda Sensing (alpha!)
|
||||
- Due to limitations in steering firmware, steering is disabled below 12 mph
|
||||
- Uses stock Honda Sensing for longitudinal control
|
||||
|
||||
- Honda CR-V 2017-2018 with Honda Sensing (alpha!)
|
||||
- Due to limitations in steering firmware, steering is disabled below 12 mph
|
||||
- Uses stock Honda Sensing for longitudinal control
|
||||
|
||||
- Honda CR-V Touring 2015-2016
|
||||
- Can only be enabled above 25 mph
|
||||
|
||||
- Honda Odyssey 2018 with Honda Sensing (alpha!)
|
||||
- Can only be enabled above 25 mph
|
||||
|
||||
- Acura RDX 2018 with AcuraWatch Plus (alpha!)
|
||||
- Can only be enabled above 25 mph
|
||||
|
||||
- Honda Pilot 2017 with Honda Sensing (alpha!)
|
||||
- Can only be enabled above 27 mph
|
||||
|
||||
- Honda Ridgeline 2017 with Honda Sensing (alpha!)
|
||||
- Can only be enabled above 27 mph
|
||||
|
||||
- Acura ILX 2016 with AcuraWatch Plus
|
||||
- Due to use of the cruise control for gas, it can only be enabled above 25 mph
|
||||
|
||||
- Acura RDX 2018 with AcuraWatch Plus (alpha!)
|
||||
- Can only be enabled above 25 mph
|
||||
|
||||
### Toyota + Lexus ###
|
||||
|
||||
- Toyota RAV-4 2016+ non-hybrid with TSS-P
|
||||
- By default it uses stock Toyota ACC for longitudinal control
|
||||
- openpilot longitudinal control available after unplugging the [Driving Support ECU](https://community.comma.ai/wiki/index.php/Toyota#Rav4_.28for_openpilot.29) and can be enabled above 20 mph
|
||||
|
||||
- Toyota Prius 2017 (alpha!)
|
||||
- Toyota Prius 2017+
|
||||
- By default it uses stock Toyota ACC for longitudinal control
|
||||
- openpilot longitudinal control available after unplugging the [Driving Support ECU](https://community.comma.ai/wiki/index.php/Toyota#Prius_.28for_openpilot.29)
|
||||
- Lateral control needs improvements
|
||||
|
||||
- Toyota RAV-4 2017 hybrid (alpha!)
|
||||
- Toyota RAV-4 2017+ hybrid
|
||||
- By default it uses stock Toyota ACC for longitudinal control
|
||||
- openpilot longitudinal control available after unplugging the [Driving Support ECU](https://community.comma.ai/wiki/index.php/Toyota#Rav4_.28for_openpilot.29) and can do stop and go
|
||||
|
||||
- Toyota Corolla 2017 (alpha!)
|
||||
- Toyota Corolla 2017+
|
||||
- By default it uses stock Toyota ACC for longitudinal control
|
||||
- openpilot longitudinal control available after unplugging the [Driving Support ECU](https://community.comma.ai/wiki/index.php/Toyota#Corolla_.28for_openpilot.29) and can be enabled above 20 mph
|
||||
|
||||
- Lexus RX 2017 hybrid (alpha!)
|
||||
- Lexus RX 2017+ hybrid (alpha!)
|
||||
- By default it uses stock Lexus ACC for longitudinal control
|
||||
- openpilot longitudinal control available after unplugging the [Driving Support ECU](https://community.comma.ai/wiki/index.php/Toyota#Lexus_RX_hybrid)
|
||||
|
||||
### GM (Chevrolet + Cadillac) ###
|
||||
|
||||
- Chevrolet Volt Premier 2017+
|
||||
- Driver Confidence II package (adaptive cruise control) required
|
||||
- Can only be enabled above 18 mph
|
||||
- Read the [installation guide](https://www.zoneos.com/volt.htm)
|
||||
|
||||
- Cadillac CT6
|
||||
- Uses stock ACC for longitudinal control
|
||||
- Requires multiple panda for proxying the ASCMs
|
||||
|
||||
In Progress Cars
|
||||
------
|
||||
- All TSS-P Toyota with Steering Assist.
|
||||
@@ -71,12 +106,19 @@ In Progress Cars
|
||||
- 'All-Speed Range Dynamic Radar Cruise Control' is required to enable stop-and-go. Only the GS, GSH, GS, F, RX, RXH, LX, NX, NXH, LC, LCH, LS, LSH have this option.
|
||||
- Even though the LX have TSS-P, it does not have Steering Assist and is not supported.
|
||||
|
||||
Community WIP Cars
|
||||
Community Maintained Cars
|
||||
------
|
||||
|
||||
- [Chevy Volt 2016-2018 Premier with Driver Confidence II](https://github.com/commaai/openpilot/pull/104)
|
||||
- [Classic Tesla Model S (pre-AP)](https://github.com/commaai/openpilot/pull/246)
|
||||
|
||||
- [Classic Tesla Model S (pre-AP)](https://github.com/commaai/openpilot/pull/145)
|
||||
How can I add support for my car?
|
||||
------
|
||||
|
||||
If your car has adaptive cruise control and lane keep assist, you are in luck. Using a [panda](https://panda.comma.ai) and [cabana](https://community.comma.ai/cabana/), you can understand how to make your car drive by wire.
|
||||
|
||||
We've written a [porting guide](https://medium.com/@comma_ai/openpilot-port-guide-for-toyota-models-e5467f4b5fe6) for Toyota that might help you after you have the basics figured out.
|
||||
|
||||
Sadly, BMW, Audi, Volvo, and Mercedes all use [FlexRay](https://en.wikipedia.org/wiki/FlexRay) and are unlikely to be supported any time soon. We also put time into a Ford port, but the steering has a 10 second cutout limitation that makes it unusable.
|
||||
|
||||
Directory structure
|
||||
------
|
||||
@@ -95,6 +137,7 @@ Directory structure
|
||||
- debug -- Tools to help you debug and do car ports
|
||||
- logcatd -- Android logcat as a service
|
||||
- loggerd -- Logger and uploader of car data
|
||||
- orbd -- Service generating ORB features from road camera
|
||||
- proclogd -- Logs information from proc
|
||||
- sensord -- IMU / GPS interface code
|
||||
- test/plant -- Car simulator running code through virtual maneuvers
|
||||
@@ -117,13 +160,6 @@ The results are written to `selfdrive/test/plant/out/index.html`
|
||||
|
||||
More extensive testing infrastructure and simulation environments are coming soon.
|
||||
|
||||
Adding Car Support
|
||||
------
|
||||
|
||||
comma.ai offers [bounties](http://comma.ai/bounties.html) for adding additional car support.
|
||||
|
||||
CR-V Touring support came in through this program. Chevy Volt is close. Accord is close as well.
|
||||
|
||||
User Data / chffr Account / Crash Reporting
|
||||
------
|
||||
|
||||
@@ -148,7 +184,7 @@ Want to get paid to work on openpilot? [comma.ai is hiring](http://comma.ai/posi
|
||||
Licensing
|
||||
------
|
||||
|
||||
openpilot is released under the MIT license.
|
||||
openpilot is released under the MIT license. Some parts of the software are released under other licenses as specified.
|
||||
|
||||
Any user of this software shall indemnify and hold harmless Comma.ai, Inc. and its directors, officers, employees, agents, stockholders, affiliates, subcontractors and customers from and against all allegations, claims, actions, suits, demands, damages, liabilities, obligations, losses, settlements, judgments, costs and expenses (including without limitation attorneys’ fees and costs) which arise out of, relate to or result from any use of this software by user.
|
||||
|
||||
|
||||
17
RELEASES.md
17
RELEASES.md
@@ -1,3 +1,20 @@
|
||||
Version 0.4.7 (2018-06-15)
|
||||
==========================
|
||||
* New model!
|
||||
* GM Volt (and CT6 lateral) support!
|
||||
* Honda Bosch lateral support!
|
||||
* Improve actuator modeling to reduce lateral wobble
|
||||
* Minor refactor of car abstraction layer
|
||||
* Hack around orbd startup issue
|
||||
|
||||
Version 0.4.6 (2018-05-18)
|
||||
==========================
|
||||
* NEOSv6 required! Will autoupdate
|
||||
* Stability improvements
|
||||
* Fix all memory leaks
|
||||
* Update C++ compiler to clang6
|
||||
* Improve front camera exposure
|
||||
|
||||
Version 0.4.5 (2018-04-27)
|
||||
==========================
|
||||
* Release notes added to the update popup
|
||||
|
||||
Binary file not shown.
Binary file not shown.
@@ -57,6 +57,8 @@ struct CarEvent @0x9b1657f34caf3ad3 {
|
||||
plannerError @32;
|
||||
ipasOverride @33;
|
||||
debugAlert @34;
|
||||
steerTempUnavailableMute @35;
|
||||
resumeRequired @36;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -263,9 +265,9 @@ struct CarParams {
|
||||
radarNameDEPRECATED @1 :Text;
|
||||
carFingerprint @2 :Text;
|
||||
|
||||
enableSteer @3 :Bool;
|
||||
enableGas @4 :Bool;
|
||||
enableBrake @5 :Bool;
|
||||
enableSteerDEPRECATED @3 :Bool;
|
||||
enableGasInterceptor @4 :Bool;
|
||||
enableBrakeDEPRECATED @5 :Bool;
|
||||
enableCruise @6 :Bool;
|
||||
enableCamera @26 :Bool;
|
||||
enableDsu @27 :Bool; # driving support unit
|
||||
@@ -294,6 +296,7 @@ struct CarParams {
|
||||
gm @4;
|
||||
hondaBosch @5;
|
||||
ford @6;
|
||||
cadillac @7;
|
||||
}
|
||||
|
||||
# things about the car in the manual
|
||||
@@ -330,4 +333,13 @@ struct CarParams {
|
||||
stoppingControl @34 :Bool; # Does the car allows full control even at lows speeds when stopping
|
||||
startAccel @35 :Float32; # Required acceleraton to overcome creep braking
|
||||
steerRateCost @40 :Float32; # Lateral MPC cost on steering rate
|
||||
steerControlType @46 :SteerControlType;
|
||||
radarOffCan @47 :Bool; # True when radar objects aren't visible on CAN
|
||||
|
||||
steerActuatorDelay @48 :Float32; # Steering wheel actuator delay in seconds
|
||||
|
||||
enum SteerControlType {
|
||||
torque @0;
|
||||
angle @1;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,100 +1,37 @@
|
||||
class HONDA:
|
||||
CIVIC = "HONDA CIVIC 2016 TOURING"
|
||||
ACURA_ILX = "ACURA ILX 2016 ACURAWATCH PLUS"
|
||||
CRV = "HONDA CR-V 2016 TOURING"
|
||||
ODYSSEY = "HONDA ODYSSEY 2018 EX-L"
|
||||
ACURA_RDX = "ACURA RDX 2018 ACURAWATCH PLUS"
|
||||
PILOT = "HONDA PILOT 2017 TOURING"
|
||||
RIDGELINE = "HONDA RIDGELINE 2017 BLACK EDITION"
|
||||
import os
|
||||
from common.basedir import BASEDIR
|
||||
|
||||
def get_fingerprint_list():
|
||||
# read all the folders in selfdrive/car and return a dict where:
|
||||
# - keys are all the car models for which we have a fingerprint
|
||||
# - values are lists dicts of messages that constitute the unique
|
||||
# CAN fingerprint of each car model and all its variants
|
||||
fingerprints = {}
|
||||
for car_folder in [x[0] for x in os.walk(BASEDIR + '/selfdrive/car')]:
|
||||
try:
|
||||
car_name = car_folder.split('/')[-1]
|
||||
values = __import__('selfdrive.car.%s.values' % car_name, fromlist=['FINGERPRINTS'])
|
||||
if hasattr(values, 'FINGERPRINTS'):
|
||||
car_fingerprints = values.FINGERPRINTS
|
||||
else:
|
||||
continue
|
||||
for f, v in car_fingerprints.iteritems():
|
||||
fingerprints[f] = v
|
||||
except (ImportError, IOError):
|
||||
pass
|
||||
return fingerprints
|
||||
|
||||
|
||||
class TOYOTA:
|
||||
PRIUS = "TOYOTA PRIUS 2017"
|
||||
RAV4H = "TOYOTA RAV4 2017 HYBRID"
|
||||
RAV4 = "TOYOTA RAV4 2017"
|
||||
COROLLA = "TOYOTA COROLLA 2017"
|
||||
LEXUS_RXH = "LEXUS RX HYBRID 2017"
|
||||
|
||||
class GM:
|
||||
VOLT = "CHEVROLET VOLT PREMIER 2017"
|
||||
_FINGERPRINTS = get_fingerprint_list()
|
||||
|
||||
_DEBUG_ADDRESS = {1880: 8} # reserved for debug purposes
|
||||
|
||||
_FINGERPRINTS = {
|
||||
HONDA.ACURA_ILX: [{
|
||||
1024L: 5, 513L: 6, 1027L: 5, 1029L: 8, 929L: 4, 1057L: 5, 777L: 8, 1034L: 5, 1036L: 8, 398L: 3, 399L: 7, 145L: 8, 660L: 8, 985L: 3, 923L: 2, 542L: 7, 773L: 7, 800L: 8, 432L: 7, 419L: 8, 420L: 8, 1030L: 5, 422L: 8, 808L: 8, 428L: 8, 304L: 8, 819L: 7, 821L: 5, 57L: 3, 316L: 8, 545L: 4, 464L: 8, 1108L: 8, 597L: 8, 342L: 6, 983L: 8, 344L: 8, 804L: 8, 1039L: 8, 476L: 4, 892L: 8, 490L: 8, 1064L: 7, 882L: 2, 884L: 7, 887L: 8, 888L: 8, 380L: 8, 1365L: 5,
|
||||
# sent messages
|
||||
0xe4: 5, 0x1fa: 8, 0x200: 6, 0x30c: 8, 0x33d: 5,
|
||||
}],
|
||||
HONDA.ACURA_RDX: [{
|
||||
57L: 3, 145L: 8, 229L: 4, 308L: 5, 316L: 8, 342L: 6, 344L: 8, 380L: 8, 392L: 6, 398L: 3, 399L: 6, 404L: 4, 420L: 8, 422L: 8, 426L: 8, 432L: 7, 464L: 8, 474L: 5, 476L: 4, 487L: 4, 490L: 8, 506L: 8, 542L: 7, 545L: 4, 597L: 8, 660L: 8, 773L: 7, 777L: 8, 780L: 8, 800L: 8, 804L: 8, 808L: 8, 819L: 7, 821L: 5, 829L: 5, 882L: 2, 884L: 7, 887L: 8, 888L: 8, 892L: 8, 923L: 2, 929L: 4, 963L: 8, 965L: 8, 966L: 8, 967L: 8, 983L: 8, 985L: 3, 1024L: 5, 1027L: 5, 1029L: 8, 1033L: 5, 1034L: 5, 1036L: 8, 1039L: 8, 1057L: 5, 1064L: 7, 1108L: 8, 1365L: 5, 1424L: 5, 1729L: 1
|
||||
}],
|
||||
HONDA.CIVIC: [{
|
||||
1024L: 5, 513L: 6, 1027L: 5, 1029L: 8, 777L: 8, 1036L: 8, 1039L: 8, 1424L: 5, 401L: 8, 148L: 8, 662L: 4, 985L: 3, 795L: 8, 773L: 7, 800L: 8, 545L: 6, 420L: 8, 806L: 8, 808L: 8, 1322L: 5, 427L: 3, 428L: 8, 304L: 8, 432L: 7, 57L: 3, 450L: 8, 929L: 8, 330L: 8, 1302L: 8, 464L: 8, 1361L: 5, 1108L: 8, 597L: 8, 470L: 2, 344L: 8, 804L: 8, 399L: 7, 476L: 7, 1633L: 8, 487L: 4, 892L: 8, 490L: 8, 493L: 5, 884L: 8, 891L: 8, 380L: 8, 1365L: 5,
|
||||
# sent messages
|
||||
0xe4: 5, 0x1fa: 8, 0x200: 6, 0x30c: 8, 0x33d: 5, 0x35e: 8, 0x39f: 8,
|
||||
}],
|
||||
HONDA.CRV: [{
|
||||
57L: 3, 145L: 8, 316L: 8, 340L: 8, 342L: 6, 344L: 8, 380L: 8, 398L: 3, 399L: 6, 401L: 8, 420L: 8, 422L: 8, 426L: 8, 432L: 7, 464L: 8, 474L: 5, 476L: 4, 487L: 4, 490L: 8, 493L: 3, 507L: 1, 542L: 7, 545L: 4, 597L: 8, 660L: 8, 661L: 4, 773L: 7, 777L: 8, 800L: 8, 804L: 8, 808L: 8, 882L: 2, 884L: 7, 888L: 8, 891L: 8, 892L: 8, 923L: 2, 929L: 8, 983L: 8, 985L: 3, 1024L: 5, 1027L: 5, 1029L: 8, 1033L: 5, 1036L: 8, 1039L: 8, 1057L: 5, 1064L: 7, 1108L: 8, 1125L: 8, 1296L: 8, 1365L: 5, 1424L: 5, 1600L: 5, 1601L: 8,
|
||||
# sent messages
|
||||
0x194: 4, 0x1fa: 8, 0x30c: 8, 0x33d: 5,
|
||||
}],
|
||||
HONDA.ODYSSEY: [{
|
||||
57L: 3, 148L: 8, 228L: 5, 229L: 4, 316L: 8, 342L: 6, 344L: 8, 380L: 8, 399L: 7, 411L: 5, 419L: 8, 420L: 8, 427L: 3, 432L: 7, 450L: 8, 463L: 8, 464L: 8, 476L: 4, 490L: 8, 506L: 8, 542L: 7, 545L: 6, 597L: 8, 662L: 4, 773L: 7, 777L: 8, 780L: 8, 795L: 8, 800L: 8, 804L: 8, 806L: 8, 808L: 8, 817L: 4, 819L: 7, 821L: 5, 825L: 4, 829L: 5, 837L: 5, 856L: 7, 862L: 8, 871L: 8, 881L: 8, 882L: 4, 884L: 8, 891L: 8, 892L: 8, 905L: 8, 923L: 2, 927L: 8, 929L: 8, 963L: 8, 965L: 8, 966L: 8, 967L: 8, 983L: 8, 985L: 3, 1029L: 8, 1036L: 8, 1052L: 8, 1064L: 7, 1088L: 8, 1089L: 8, 1092L: 1, 1108L: 8, 1110L: 8, 1125L: 8, 1296L: 8, 1302L: 8, 1600L: 5, 1601L: 8, 1612L: 5, 1613L: 5, 1614L: 5, 1615L: 8, 1616L: 5, 1619L: 5, 1623L: 5, 1668L: 5
|
||||
},
|
||||
# Odyssey Elite
|
||||
{
|
||||
57L: 3, 148L: 8, 228L: 5, 229L: 4, 304L: 8, 342L: 6, 344L: 8, 380L: 8, 399L: 7, 411L: 5, 419L: 8, 420L: 8, 427L: 3, 432L: 7, 440L: 8, 450L: 8, 463L: 8, 464L: 8, 476L: 4, 490L: 8, 506L: 8, 507L: 1, 542L: 7, 545L: 6, 597L: 8, 662L: 4, 773L: 7, 777L: 8, 780L: 8, 795L: 8, 800L: 8, 804L: 8, 806L: 8, 808L: 8, 817L: 4, 819L: 7, 821L: 5, 825L: 4, 829L: 5, 837L: 5, 856L: 7, 862L: 8, 871L: 8, 881L: 8, 882L: 4, 884L: 8, 891L: 8, 892L: 8, 905L: 8, 923L: 2, 927L: 8, 929L: 8, 963L: 8, 965L: 8, 966L: 8, 967L: 8, 983L: 8, 985L: 3, 1029L: 8, 1036L: 8, 1052L: 8, 1064L: 7, 1088L: 8, 1089L: 8, 1092L: 1, 1108L: 8, 1110L: 8, 1125L: 8, 1296L: 8, 1302L: 8, 1600L: 5, 1601L: 8, 1612L: 5, 1613L: 5, 1614L: 5, 1616L: 5, 1619L: 5, 1623L: 5, 1668L: 5
|
||||
}],
|
||||
HONDA.PILOT: [{
|
||||
1600L: 5, 1027L: 5, 1668L: 5, 1029L: 8, 1601L: 8, 777L: 8, 891L: 8, 1036L: 8, 399L: 7, 1424L: 5, 145L: 8, 660L: 8, 985L: 3, 1616L: 5, 538L: 3, 795L: 8, 542L: 7, 773L: 7, 800L: 8, 545L: 5, 546L: 3, 419L: 8, 420L: 8, 422L: 8, 1064L: 7, 425L: 8, 426L: 8, 427L: 3, 432L: 7, 819L: 7, 308L: 5, 821L: 5, 57L: 3, 965L: 8, 316L: 8, 829L: 5, 1088L: 8, 1089L: 8, 963L: 8, 837L: 5, 966L: 8, 929L: 8, 780L: 8, 923L: 2, 1613L: 5, 334L: 8, 463L: 8, 464L: 8, 1618L: 5, 1108L: 8, 597L: 8, 342L: 6, 983L: 8, 856L: 7, 804L: 8, 1612L: 5, 476L: 4, 1125L: 8, 344L: 8, 1296L: 8, 379L: 8, 228L: 5, 229L: 4, 871L: 8, 892L: 8, 490L: 8, 808L: 8, 882L: 2, 884L: 7, 967L: 8, 506L: 8, 507L: 1, 380L: 8,
|
||||
}],
|
||||
HONDA.RIDGELINE: [{
|
||||
57L: 3, 145L: 8, 228L: 5, 229L: 4, 308L: 5, 316L: 8, 339L: 7, 342L: 6, 344L: 8, 380L: 8, 392L: 6, 399L: 7, 419L: 8, 420L: 8, 422L: 8, 425L: 8, 426L: 8, 427L: 3, 432L: 7, 464L: 8, 471L: 3, 476L: 4, 490L: 8, 506L: 8, 545L: 5, 546L: 3, 597L: 8, 660L: 8, 773L: 7, 777L: 8, 780L: 8, 795L: 8, 800L: 8, 804L: 8, 808L: 8, 819L: 7, 821L: 5, 829L: 5, 871L: 8, 882L: 2, 884L: 7, 892L: 8, 923L: 2, 927L: 8, 929L: 8, 963L: 8, 965L: 8, 966L: 8, 967L: 8, 983L: 8, 985L: 3, 1027L: 5, 1029L: 8, 1036L: 8, 1039L: 8, 1064L: 7, 1088L: 8, 1089L: 8, 1108L: 8, 1125L: 8, 1296L: 8, 1365L: 5, 1424L: 5, 1600L: 5, 1601L: 8, 1613L: 5, 1616L: 5, 1618L: 5, 1668L: 5, 2015L: 3
|
||||
}],
|
||||
TOYOTA.RAV4: [{
|
||||
36L: 8, 37L: 8, 170L: 8, 180L: 8, 186L: 4, 426L: 6, 452L: 8, 464L: 8, 466L: 8, 467L: 8, 547L: 8, 548L: 8, 552L: 4, 562L: 4, 608L: 8, 610L: 5, 643L: 7, 705L: 8, 725L: 2, 740L: 5, 800L: 8, 835L: 8, 836L: 8, 849L: 4, 869L: 7, 870L: 7, 871L: 2, 896L: 8, 897L: 8, 900L: 6, 902L: 6, 905L: 8, 911L: 8, 916L: 3, 918L: 7, 921L: 8, 933L: 8, 944L: 8, 945L: 8, 951L: 8, 955L: 4, 956L: 8, 979L: 2, 998L: 5, 999L: 7, 1000L: 8, 1001L: 8, 1005L: 2, 1008L: 2, 1014L: 8, 1017L: 8, 1041L: 8, 1042L: 8, 1043L: 8, 1044L: 8, 1056L: 8, 1059L: 1, 1114L: 8, 1161L: 8, 1162L: 8, 1163L: 8, 1176L: 8, 1177L: 8, 1178L: 8, 1179L: 8, 1180L: 8, 1181L: 8, 1190L: 8, 1191L: 8, 1192L: 8, 1196L: 8, 1227L: 8, 1228L: 8, 1235L: 8, 1237L: 8, 1263L: 8, 1264L: 8, 1279L: 8, 1408L: 8, 1409L: 8, 1410L: 8, 1552L: 8, 1553L: 8, 1554L: 8, 1555L: 8, 1556L: 8, 1557L: 8, 1561L: 8, 1562L: 8, 1568L: 8, 1569L: 8, 1570L: 8, 1571L: 8, 1572L: 8, 1584L: 8, 1589L: 8, 1592L: 8, 1593L: 8, 1595L: 8, 1596L: 8, 1597L: 8, 1600L: 8, 1656L: 8, 1664L: 8, 1728L: 8, 1745L: 8, 1779L: 8, 1904L: 8, 1912L: 8, 1990L: 8, 1998L: 8
|
||||
}],
|
||||
TOYOTA.RAV4H: [{
|
||||
36L: 8, 37L: 8, 170L: 8, 180L: 8, 186L: 4, 296L: 8, 426L: 6, 452L: 8, 464L: 8, 466L: 8, 467L: 8, 547L: 8, 548L: 8, 550L: 8, 552L: 4, 560L: 7, 562L: 4, 581L: 5, 608L: 8, 610L: 5, 643L: 7, 705L: 8, 713L: 8, 725L: 2, 740L: 5, 800L: 8, 835L: 8, 836L: 8, 849L: 4, 869L: 7, 870L: 7, 871L: 2, 896L: 8, 897L: 8, 900L: 6, 902L: 6, 905L: 8, 911L: 8, 916L: 3, 918L: 7, 921L: 8, 933L: 8, 944L: 8, 945L: 8, 950L: 8, 951L: 8, 953L: 3, 955L: 8, 956L: 8, 979L: 2, 998L: 5, 999L: 7, 1000L: 8, 1001L: 8, 1005L: 2, 1008L: 2, 1014L: 8, 1017L: 8, 1041L: 8, 1042L: 8, 1043L: 8, 1044L: 8, 1056L: 8, 1059L: 1, 1114L: 8, 1161L: 8, 1162L: 8, 1163L: 8, 1176L: 8, 1177L: 8, 1178L: 8, 1179L: 8, 1180L: 8, 1181L: 8, 1184L: 8, 1185L: 8, 1186L: 8, 1190L: 8, 1191L: 8, 1192L: 8, 1196L: 8, 1197L: 8, 1198L: 8, 1199L: 8, 1212L: 8, 1227L: 8, 1228L: 8, 1232L: 8, 1235L: 8, 1237L: 8, 1263L: 8, 1264L: 8, 1279L: 8, 1408L: 8, 1409L: 8, 1410L: 8, 1552L: 8, 1553L: 8, 1554L: 8, 1555L: 8, 1556L: 8, 1557L: 8, 1561L: 8, 1562L: 8, 1568L: 8, 1569L: 8, 1570L: 8, 1571L: 8, 1572L: 8, 1584L: 8, 1589L: 8, 1592L: 8, 1593L: 8, 1595L: 8, 1596L: 8, 1597L: 8, 1600L: 8, 1656L: 8, 1664L: 8, 1728L: 8, 1745L: 8, 1779L: 8, 1904L: 8, 1912L: 8, 1990L: 8, 1998L: 8
|
||||
}],
|
||||
TOYOTA.PRIUS: [{
|
||||
36L: 8, 37L: 8, 166L: 8, 170L: 8, 180L: 8, 295L: 8, 296L: 8, 426L: 6, 452L: 8, 466L: 8, 467L: 8, 550L: 8, 552L: 4, 560L: 7, 562L: 6, 581L: 5, 608L: 8, 610L: 8, 614L: 8, 643L: 7, 658L: 8, 713L: 8, 740L: 5, 742L: 8, 743L: 8, 800L: 8, 810L: 2, 814L: 8, 829L: 2, 830L: 7, 835L: 8, 836L: 8, 863L: 8, 869L: 7, 870L: 7, 871L: 2, 898L: 8, 900L: 6, 902L: 6, 905L: 8, 918L: 8, 921L: 8, 933L: 8, 944L: 8, 945L: 8, 950L: 8, 951L: 8, 953L: 8, 955L: 8, 956L: 8, 971L: 7, 975L: 5, 993L: 8, 998L: 5, 999L: 7, 1000L: 8, 1001L: 8, 1014L: 8, 1017L: 8, 1020L: 8, 1041L: 8, 1042L: 8, 1044L: 8, 1056L: 8, 1057L: 8, 1059L: 1, 1071L: 8, 1077L: 8, 1082L: 8, 1083L: 8, 1084L: 8, 1085L: 8, 1086L: 8, 1114L: 8, 1132L: 8, 1161L: 8, 1162L: 8, 1163L: 8, 1175L: 8, 1227L: 8, 1228L: 8, 1235L: 8, 1237L: 8, 1279L: 8, 1552L: 8, 1553L: 8, 1556L: 8, 1557L: 8, 1568L: 8, 1570L: 8, 1571L: 8, 1572L: 8, 1595L: 8, 1777L: 8, 1779L: 8, 1904L: 8, 1912L: 8, 1990L: 8, 1998L: 8
|
||||
},
|
||||
# Prius Prime
|
||||
{
|
||||
36L: 8, 37L: 8, 166L: 8, 170L: 8, 180L: 8, 295L: 8, 296L: 8, 426L: 6, 452L: 8, 466L: 8, 467L: 8, 550L: 8, 552L: 4, 560L: 7, 562L: 6, 581L: 5, 608L: 8, 610L: 8, 614L: 8, 643L: 7, 658L: 8, 713L: 8, 740L: 5, 742L: 8, 743L: 8, 800L: 8, 810L: 2, 814L: 8, 824L: 2, 829L: 2, 830L: 7, 835L: 8, 836L: 8, 863L: 8, 869L: 7, 870L: 7, 871L: 2,898L: 8, 900L: 6, 902L: 6, 905L: 8, 913L: 8, 918L: 8, 921L: 8, 933L: 8, 944L: 8, 945L: 8, 950L: 8, 951L: 8, 953L: 8, 955L: 8, 956L: 8, 971L: 7, 974L: 8, 975L: 5, 993L: 8, 998L: 5, 999L: 7, 1000L: 8, 1001L: 8, 1014L: 8, 1017L: 8, 1020L: 8, 1041L: 8, 1042L: 8, 1044L: 8, 1056L: 8, 1057L: 8, 1059L: 1, 1071L: 8, 1076L: 8, 1077L: 8, 1082L: 8, 1083L: 8, 1084L: 8, 1085L: 8, 1086L: 8, 1114L: 8, 1132L: 8, 1161L: 8, 1162L: 8, 1163L: 8, 1164L: 8, 1165L: 8, 1166L: 8, 1167L: 8, 1175L: 8, 1227L: 8, 1228L: 8, 1235L: 8, 1237L: 8, 1279L: 8, 1552L: 8, 1553L: 8, 1556L: 8, 1557L: 8, 1568L: 8, 1570L: 8, 1571L: 8, 1572L: 8, 1595L: 8, 1777L: 8, 1779L: 8, 1904L: 8, 1912L: 8, 1990L: 8, 1998L: 8
|
||||
},
|
||||
# Taiwanese Prius Prime
|
||||
{
|
||||
36L: 8, 37L: 8, 166L: 8, 170L: 8, 180L: 8, 295L: 8, 296L: 8, 426L: 6, 452L: 8, 466L: 8, 467L: 8, 550L: 8, 552L: 4, 560L: 7, 562L: 6, 581L: 5, 608L: 8, 610L: 8, 614L: 8, 643L: 7, 658L: 8, 713L: 8, 740L: 5, 742L: 8, 743L: 8, 800L: 8, 810L: 2, 814L: 8, 824L: 2, 829L: 2, 830L: 7, 835L: 8, 836L: 8, 845L: 5, 863L: 8, 869L: 7, 870L: 7, 871L: 2,898L: 8, 900L: 6, 902L: 6, 905L: 8, 913L: 8, 918L: 8, 921L: 8, 933L: 8, 944L: 8, 945L: 8, 950L: 8, 951L: 8, 953L: 8, 955L: 8, 956L: 8, 971L: 7, 974L: 8, 975L: 5, 993L: 8, 998L: 5, 999L: 7, 1000L: 8, 1001L: 8, 1005L: 2, 1014L: 8, 1017L: 8, 1020L: 8, 1041L: 8, 1042L: 8, 1044L: 8, 1056L: 8, 1057L: 8, 1059L: 1, 1071L: 8, 1076L: 8, 1077L: 8, 1082L: 8, 1083L: 8, 1084L: 8, 1085L: 8, 1086L: 8, 1114L: 8, 1132L: 8, 1161L: 8, 1162L: 8, 1163L: 8, 1164L: 8, 1165L: 8, 1166L: 8, 1167L: 8, 1175L: 8, 1227L: 8, 1228L: 8, 1235L: 8, 1237L: 8, 1264L: 8, 1279L: 8, 1552L: 8, 1553L: 8, 1556L: 8, 1557L: 8, 1568L: 8, 1570L: 8, 1571L: 8, 1572L: 8, 1595L: 8, 1777L: 8, 1779L: 8, 1904L: 8, 1912L: 8, 1990L: 8, 1998L: 8
|
||||
}],
|
||||
TOYOTA.COROLLA: [{
|
||||
36: 8, 37: 8, 170: 8, 180: 8, 186: 4, 426: 6, 452: 8, 464: 8, 466: 8, 467: 8, 547: 8, 548: 8, 552: 4, 608: 8, 610: 5, 643: 7, 705: 8, 740: 5, 800: 8, 835: 8, 836: 8, 849: 4, 869: 7, 870: 7, 871: 2, 896: 8, 897: 8, 900: 6, 902: 6, 905: 8, 911: 8, 916: 2, 921: 8, 933: 8, 944: 8, 945: 8, 951: 8, 955: 4, 956: 8, 979: 2, 992: 8, 998: 5, 999: 7, 1000: 8, 1001: 8, 1017: 8, 1041: 8, 1042: 8, 1043: 8, 1044: 8, 1056: 8, 1059: 1, 1114: 8, 1161: 8, 1162: 8, 1163: 8, 1196: 8, 1227: 8, 1235: 8, 1279: 8, 1552: 8, 1553: 8, 1556: 8, 1557: 8, 1561: 8, 1562: 8, 1568: 8, 1569: 8, 1570: 8, 1571: 8, 1572: 8, 1584: 8, 1589: 8, 1592: 8, 1596: 8, 1597: 8, 1600: 8, 1664: 8, 1728: 8, 1779: 8, 1904: 8, 1912: 8, 1990: 8, 1998: 8
|
||||
},
|
||||
# Corolla LE 2017
|
||||
{
|
||||
36: 8, 37: 8, 170: 8, 180: 8, 186: 4, 426: 6, 452: 8, 464: 8, 466: 8, 467: 8, 547: 8, 548: 8, 552: 4, 608: 8, 610: 5, 643: 7, 705: 8, 740: 5, 800: 8, 835: 8, 836: 8, 849: 4, 869: 7, 870: 7, 871: 2, 896: 8, 897: 8, 900: 6, 902: 6, 905: 8, 911: 8, 916: 2, 921: 8, 933: 8, 944: 8, 945: 8, 951: 8, 955: 4, 956: 8, 979: 2, 998: 5, 999: 7, 1000: 8, 1001: 8, 1017: 8, 1041: 8, 1042: 8, 1043: 8, 1044: 8, 1056: 8, 1059: 1, 1114: 8, 1161: 8, 1162: 8, 1163: 8, 1196: 8, 1227: 8, 1235: 8, 1279: 8, 1552: 8, 1553: 8, 1556: 8, 1557: 8, 1561: 8, 1562: 8, 1568: 8, 1569: 8, 1570: 8, 1571: 8, 1572: 8, 1592: 8, 1596: 8, 1597: 8, 1600: 8, 1664: 8, 1779: 8, 1904: 8, 1912: 8, 1990: 8, 1998: 8, 2016: 8, 2017: 8, 2018: 8, 2019: 8, 2020: 8, 2021: 8, 2022: 8, 2023: 8, 2024: 8
|
||||
}],
|
||||
TOYOTA.LEXUS_RXH: [{
|
||||
36: 8, 37: 8, 166: 8, 170: 8, 180: 8, 295: 8, 296: 8, 426: 6, 452: 8, 466: 8, 467: 8, 550: 8, 552: 4, 560: 7, 562: 6, 581: 5, 608: 8, 610: 5, 643: 7, 658: 8, 713: 8, 740: 5, 742: 8, 743: 8, 800: 8, 810: 2, 812: 3, 814: 8, 830: 7, 835: 8, 836: 8, 845: 5, 863: 8, 869: 7, 870: 7, 871: 2, 898: 8, 900: 6, 902: 6, 905: 8, 913: 8, 918: 8, 921: 8, 933: 8, 944: 8, 945: 8, 950: 8, 951: 8, 953: 8, 955: 8, 956: 8, 971: 7, 975: 6, 993: 8, 998: 5, 999: 7, 1000: 8, 1001: 8, 1005: 2, 1014: 8, 1017: 8, 1020: 8, 1041: 8, 1042: 8, 1044: 8, 1056: 8, 1059: 1, 1063: 8, 1071: 8, 1077: 8, 1082: 8, 1114: 8, 1161: 8, 1162: 8, 1163: 8, 1164: 8, 1165: 8, 1166: 8, 1167: 8, 1227: 8, 1228: 8, 1235: 8, 1237: 8, 1264: 8, 1279: 8, 1552: 8, 1553: 8, 1556: 8, 1557: 8, 1568: 8, 1570: 8, 1571: 8, 1572: 8, 1575: 8, 1595: 8, 1777: 8, 1779: 8, 1808: 8, 1810: 8, 1816: 8, 1818: 8, 1840: 8, 1848: 8, 1904: 8, 1912: 8, 1940: 8, 1941: 8, 1948: 8, 1949: 8, 1952: 8, 1956: 8, 1960: 8, 1964: 8, 1986: 8, 1990: 8, 1994: 8, 1998: 8, 2004: 8, 2012: 8
|
||||
}],
|
||||
GM.VOLT: [{
|
||||
170: 8, 171: 8, 189: 7, 190: 6, 193: 8, 197: 8, 199: 4, 201: 8, 209: 7, 211: 2, 241: 6, 288: 5, 289: 8, 298: 8, 304: 1, 308: 4, 309: 8, 311: 8, 313: 8, 320: 3, 328: 1, 352: 5, 381: 6, 386: 8, 388: 8, 389: 2, 390: 7, 417: 7, 419: 1, 426: 7, 451: 8, 452: 8, 453: 6, 454: 8, 456: 8, 479: 3, 481: 7, 485: 8, 489: 8, 493: 8, 495: 4, 497: 8, 499: 3, 500: 6, 501: 8, 508: 8, 528: 4, 532: 6, 546: 7, 550: 8, 554: 3, 558: 8, 560: 8, 562: 8, 563: 5, 564: 5, 565: 5, 566: 5, 567: 3, 568: 1, 573: 1, 577: 8, 647: 3, 707: 8, 711: 6, 761: 7, 810: 8, 840: 5, 842: 5, 844: 8, 866: 4, 961: 8, 969: 8, 977: 8, 979: 7, 988: 6, 989: 8, 995: 7, 1001: 8, 1005: 6, 1009: 8, 1017: 8, 1019: 2, 1020: 8, 1105: 6, 1187: 4, 1217: 8, 1221: 5, 1223: 3, 1225: 7, 1227: 4, 1233: 8, 1249: 8, 1257: 6, 1265: 8, 1267: 1, 1273: 3, 1275: 3, 1280: 4, 1300: 8, 1322: 6, 1323: 4, 1328: 4, 1417: 8, 1601: 8, 1905: 7, 1906: 7, 1907: 7, 1910: 7, 1912: 7, 1922: 7, 1927: 7, 1928: 7, 2016: 8, 2020: 8, 2024: 8, 2028: 8
|
||||
}],
|
||||
}
|
||||
|
||||
# support additional internal only fingerprints
|
||||
try:
|
||||
from common.fingerprints_internal import add_additional_fingerprints
|
||||
add_additional_fingerprints(_FINGERPRINTS)
|
||||
except ImportError:
|
||||
pass
|
||||
|
||||
|
||||
def is_valid_for_fingerprint(msg, car_fingerprint):
|
||||
adr = msg.address
|
||||
return msg.src != 0 or (adr in car_fingerprint and car_fingerprint[adr] == len(msg.dat))
|
||||
bus = msg.src
|
||||
# ignore addresses that are more than 11 bits
|
||||
return (adr in car_fingerprint and car_fingerprint[adr] == len(msg.dat)) or \
|
||||
bus != 0 or adr >= 0x800
|
||||
|
||||
|
||||
def eliminate_incompatible_cars(msg, candidate_cars):
|
||||
@@ -108,6 +45,7 @@ def eliminate_incompatible_cars(msg, candidate_cars):
|
||||
A list containing the subset of candidate_cars that could have sent msg.
|
||||
"""
|
||||
compatible_cars = []
|
||||
|
||||
for car_name in candidate_cars:
|
||||
car_fingerprints = _FINGERPRINTS[car_name]
|
||||
|
||||
|
||||
@@ -18,7 +18,7 @@ def json_robust_dumps(obj):
|
||||
|
||||
class NiceOrderedDict(OrderedDict):
|
||||
def __str__(self):
|
||||
return '{'+', '.join("%r: %r" % p for p in self.iteritems())+'}'
|
||||
return json_robust_dumps(self)
|
||||
|
||||
class SwagFormatter(logging.Formatter):
|
||||
def __init__(self, swaglogger):
|
||||
@@ -62,6 +62,10 @@ class SwagFormatter(logging.Formatter):
|
||||
def format(self, record):
|
||||
return json_robust_dumps(self.format_dict(record))
|
||||
|
||||
class SwagErrorFilter(logging.Filter):
|
||||
def filter(self, record):
|
||||
return record.levelno < logging.ERROR
|
||||
|
||||
_tmpfunc = lambda: 0
|
||||
_srcfile = os.path.normcase(_tmpfunc.__code__.co_filename)
|
||||
|
||||
@@ -128,15 +132,40 @@ class SwagLogger(logging.Logger):
|
||||
if args:
|
||||
evt['args'] = args
|
||||
evt.update(kwargs)
|
||||
self.info(evt)
|
||||
if 'error' in kwargs:
|
||||
self.error(evt)
|
||||
else:
|
||||
self.info(evt)
|
||||
|
||||
if __name__ == "__main__":
|
||||
log = SwagLogger()
|
||||
|
||||
stdout_handler = logging.StreamHandler(sys.stdout)
|
||||
stdout_handler.setLevel(logging.INFO)
|
||||
stdout_handler.addFilter(SwagErrorFilter())
|
||||
log.addHandler(stdout_handler)
|
||||
|
||||
stderr_handler = logging.StreamHandler(sys.stderr)
|
||||
stderr_handler.setLevel(logging.ERROR)
|
||||
log.addHandler(stderr_handler)
|
||||
|
||||
log.info("asdasd %s", "a")
|
||||
log.info({'wut': 1})
|
||||
log.warning("warning")
|
||||
log.error("error")
|
||||
log.critical("critical")
|
||||
log.event("test", x="y")
|
||||
|
||||
with log.ctx():
|
||||
stdout_handler.setFormatter(SwagFormatter(log))
|
||||
stderr_handler.setFormatter(SwagFormatter(log))
|
||||
log.bind(user="some user")
|
||||
log.info("in req")
|
||||
log.event("do_req")
|
||||
print("")
|
||||
log.warning("warning")
|
||||
print("")
|
||||
log.error("error")
|
||||
print("")
|
||||
log.critical("critical")
|
||||
print("")
|
||||
log.event("do_req", a=1, b="c")
|
||||
|
||||
@@ -1,29 +1,18 @@
|
||||
def int_rnd(x):
|
||||
return int(round(x))
|
||||
|
||||
|
||||
def clip(x, lo, hi):
|
||||
return max(lo, min(hi, x))
|
||||
|
||||
|
||||
def interp(x, xp, fp):
|
||||
N = len(xp)
|
||||
if not hasattr(x, '__iter__'):
|
||||
def get_interp(xv):
|
||||
hi = 0
|
||||
while hi < N and x > xp[hi]:
|
||||
while hi < N and xv > xp[hi]:
|
||||
hi += 1
|
||||
low = hi - 1
|
||||
return fp[-1] if hi == N and x > xp[low] else (
|
||||
fp[0] if hi == 0 else
|
||||
(x - xp[low]) * (fp[hi] - fp[low]) / (xp[hi] - xp[low]) + fp[low])
|
||||
|
||||
result = []
|
||||
for v in x:
|
||||
hi = 0
|
||||
while hi < N and v > xp[hi]:
|
||||
hi += 1
|
||||
low = hi - 1
|
||||
result.append(fp[-1] if hi == N and v > xp[low] else (fp[
|
||||
0] if hi == 0 else (v - xp[low]) * (fp[hi] - fp[low]) / (xp[hi] - xp[low]
|
||||
) + fp[low]))
|
||||
return result
|
||||
return fp[-1] if hi == N and xv > xp[low] else (
|
||||
fp[0] if hi == 0 else
|
||||
(xv - xp[low]) * (fp[hi] - fp[low]) / (xp[hi] - xp[low]) + fp[low])
|
||||
return [get_interp(v) for v in x] if hasattr(
|
||||
x, '__iter__') else get_interp(x)
|
||||
|
||||
@@ -37,7 +37,7 @@ def mkdirs_exists_ok(path):
|
||||
raise
|
||||
|
||||
class TxType(Enum):
|
||||
PERSISTANT = 1
|
||||
PERSISTENT = 1
|
||||
CLEAR_ON_MANAGER_START = 2
|
||||
CLEAR_ON_CAR_START = 3
|
||||
|
||||
@@ -47,37 +47,37 @@ class UnknownKeyName(Exception):
|
||||
keys = {
|
||||
# written: manager
|
||||
# read: loggerd, uploaderd, offroad
|
||||
"DongleId": TxType.PERSISTANT,
|
||||
"AccessToken": TxType.PERSISTANT,
|
||||
"Version": TxType.PERSISTANT,
|
||||
"TrainingVersion": TxType.PERSISTANT,
|
||||
"GitCommit": TxType.PERSISTANT,
|
||||
"GitBranch": TxType.PERSISTANT,
|
||||
"GitRemote": TxType.PERSISTANT,
|
||||
"DongleId": TxType.PERSISTENT,
|
||||
"AccessToken": TxType.PERSISTENT,
|
||||
"Version": TxType.PERSISTENT,
|
||||
"TrainingVersion": TxType.PERSISTENT,
|
||||
"GitCommit": TxType.PERSISTENT,
|
||||
"GitBranch": TxType.PERSISTENT,
|
||||
"GitRemote": TxType.PERSISTENT,
|
||||
# written: baseui
|
||||
# read: ui, controls
|
||||
"IsMetric": TxType.PERSISTANT,
|
||||
"IsRearViewMirror": TxType.PERSISTANT,
|
||||
"IsFcwEnabled": TxType.PERSISTANT,
|
||||
"HasAcceptedTerms": TxType.PERSISTANT,
|
||||
"CompletedTrainingVersion": TxType.PERSISTANT,
|
||||
"IsUploadVideoOverCellularEnabled": TxType.PERSISTANT,
|
||||
"IsMetric": TxType.PERSISTENT,
|
||||
"IsRearViewMirror": TxType.PERSISTENT,
|
||||
"IsFcwEnabled": TxType.PERSISTENT,
|
||||
"HasAcceptedTerms": TxType.PERSISTENT,
|
||||
"CompletedTrainingVersion": TxType.PERSISTENT,
|
||||
"IsUploadVideoOverCellularEnabled": TxType.PERSISTENT,
|
||||
# written: visiond
|
||||
# read: visiond, controlsd
|
||||
"CalibrationParams": TxType.PERSISTANT,
|
||||
"CalibrationParams": TxType.PERSISTENT,
|
||||
# written: visiond
|
||||
# read: visiond, ui
|
||||
"CloudCalibration": TxType.PERSISTANT,
|
||||
"CloudCalibration": TxType.PERSISTENT,
|
||||
# written: controlsd
|
||||
# read: radard
|
||||
"CarParams": TxType.CLEAR_ON_CAR_START,
|
||||
|
||||
"Passive": TxType.PERSISTANT,
|
||||
"Passive": TxType.PERSISTENT,
|
||||
"DoUninstall": TxType.CLEAR_ON_MANAGER_START,
|
||||
"ShouldDoUpdate": TxType.CLEAR_ON_MANAGER_START,
|
||||
"IsUpdateAvailable": TxType.PERSISTANT,
|
||||
"IsUpdateAvailable": TxType.PERSISTENT,
|
||||
|
||||
"RecordFront": TxType.PERSISTANT,
|
||||
"RecordFront": TxType.PERSISTENT,
|
||||
}
|
||||
|
||||
def fsync_dir(path):
|
||||
|
||||
BIN
installer/updater/updater
Executable file
BIN
installer/updater/updater
Executable file
Binary file not shown.
@@ -22,18 +22,6 @@ function launch {
|
||||
echo 0-3 > /dev/cpuset/foreground/cpus
|
||||
echo 0-3 > /dev/cpuset/android/cpus
|
||||
|
||||
# check if NEOS update is required
|
||||
while [ "$(cat /VERSION)" -lt 4 ] && [ ! -e /data/media/0/noupdate ]; do
|
||||
# wait for network
|
||||
(cd selfdrive/ui/spinner && exec ./spinner 'waiting for network...') & spin_pid=$!
|
||||
until ping -W 1 -c 1 8.8.8.8; do sleep 1; done
|
||||
kill $spin_pid
|
||||
|
||||
# update NEOS
|
||||
curl -o /tmp/updater https://neos.comma.ai/updater && chmod +x /tmp/updater && /tmp/updater
|
||||
sleep 10
|
||||
done
|
||||
|
||||
export PYTHONPATH="$PWD"
|
||||
|
||||
# start manager
|
||||
|
||||
@@ -8,7 +8,7 @@ The project to democratize access to the decoder ring of your car.
|
||||
### DBC file basics
|
||||
|
||||
A DBC file encodes, in a humanly readable way, the information needed to understand a vehicle's CAN bus traffic. A vehicle might have multiple CAN buses and every CAN bus is represented by its own dbc file.
|
||||
Wondering what's the DBC file format? [Here](http://www.socialledge.com/sjsu/index.php?title=DBC_Format) a good overview.
|
||||
Wondering what's the DBC file format? [Here](http://www.socialledge.com/sjsu/index.php?title=DBC_Format) and [Here](https://github.com/stefanhoelzl/CANpy/blob/master/docs/DBC_Specification.md) a couple of good overviews.
|
||||
|
||||
### How to start reverse engineering cars
|
||||
|
||||
|
||||
@@ -1,6 +1,24 @@
|
||||
CM_ "AUTOGENERATED FILE, DO NOT EDIT"
|
||||
|
||||
|
||||
CM_ "Imported file _comma.dbc starts here"
|
||||
BO_ 512 GAS_COMMAND: 6 EON
|
||||
SG_ GAS_COMMAND : 7|16@0+ (0.253984064,-83.3) [0|1] "" INTERCEPTOR
|
||||
SG_ GAS_COMMAND2 : 23|16@0+ (0.126992032,-83.3) [0|1] "" INTERCEPTOR
|
||||
SG_ ENABLE : 39|1@0+ (1,0) [0|1] "" INTERCEPTOR
|
||||
SG_ COUNTER : 45|2@0+ (1,0) [0|3] "" INTERCEPTOR
|
||||
SG_ CHECKSUM : 43|4@0+ (1,0) [0|3] "" INTERCEPTOR
|
||||
|
||||
BO_ 513 GAS_SENSOR: 6 INTERCEPTOR
|
||||
SG_ INTERCEPTOR_GAS : 7|16@0+ (0.253984064,-83.3) [0|1] "" EON
|
||||
SG_ INTERCEPTOR_GAS2 : 23|16@0+ (0.126992032,-83.3) [0|1] "" EON
|
||||
SG_ STATE : 39|8@0+ (1,0) [0|255] "" EON
|
||||
SG_ COUNTER : 45|2@0+ (1,0) [0|3] "" EON
|
||||
SG_ CHECKSUM : 43|4@0+ (1,0) [0|3] "" EON
|
||||
|
||||
VAL_ 513 STATE 5 "FAULT_TIMEOUT" 4 "FAULT_STARTUP" 3 "FAULT_SCE" 2 "FAULT_SEND" 1 "FAULT_BAD_CHECKSUM" 0 "NO_FAULT" ;
|
||||
|
||||
|
||||
CM_ "Imported file _honda_2017.dbc starts here"
|
||||
VERSION ""
|
||||
|
||||
@@ -211,6 +229,7 @@ VAL_ 829 BEEP 3 "single_beep" 2 "triple_beep" 1 "repeated_beep" 0 "no_beep" ;
|
||||
CM_ "acura_rdx_2018_can.dbc starts here"
|
||||
|
||||
|
||||
|
||||
BO_ 342 STEERING_SENSORS: 6 EPS
|
||||
SG_ STEER_ANGLE : 7|16@0- (-0.1,0) [-500|500] "deg" EON
|
||||
SG_ STEER_ANGLE_RATE : 23|16@0- (1,0) [-3000|3000] "deg/s" EON
|
||||
|
||||
95
opendbc/cadillac_ct6_chassis.dbc
Normal file
95
opendbc/cadillac_ct6_chassis.dbc
Normal file
@@ -0,0 +1,95 @@
|
||||
VERSION ""
|
||||
|
||||
|
||||
NS_ :
|
||||
NS_DESC_
|
||||
CM_
|
||||
BA_DEF_
|
||||
BA_
|
||||
VAL_
|
||||
CAT_DEF_
|
||||
CAT_
|
||||
FILTER
|
||||
BA_DEF_DEF_
|
||||
EV_DATA_
|
||||
ENVVAR_DATA_
|
||||
SGTYPE_
|
||||
SGTYPE_VAL_
|
||||
BA_DEF_SGTYPE_
|
||||
BA_SGTYPE_
|
||||
SIG_TYPE_REF_
|
||||
VAL_TABLE_
|
||||
SIG_GROUP_
|
||||
SIG_VALTYPE_
|
||||
SIGTYPE_VALTYPE_
|
||||
BO_TX_BU_
|
||||
BA_DEF_REL_
|
||||
BA_REL_
|
||||
BA_DEF_DEF_REL_
|
||||
BU_SG_REL_
|
||||
BU_EV_REL_
|
||||
BU_BO_REL_
|
||||
SG_MUL_VAL_
|
||||
|
||||
BS_:
|
||||
|
||||
BU_: K182_PACM K43_PSCM K17_EBCM NEO K124_ASCM
|
||||
|
||||
|
||||
|
||||
BO_ 823 PACMParkAssitCmd: 7 NEO
|
||||
SG_ RollingCounter : 35|2@0+ (1,0) [0|0] "" NEO
|
||||
SG_ SteeringWheelChecksum : 47|16@0+ (1,0) [0|0] "" NEO
|
||||
SG_ SteeringWheelCmd : 23|16@0+ (1,0) [0|0] "" NEO
|
||||
|
||||
BO_ 560 EBCMRegen: 6 K17_EBCM
|
||||
SG_ Regen : 1|10@0+ (1,0) [0|0] "" NEO
|
||||
|
||||
BO_ 338 ASCMLKASteeringCmd: 6 NEO
|
||||
SG_ LKASteeringCmdActive : 7|1@0+ (1,0) [0|0] "" NEO
|
||||
SG_ LKASteeringCmd : 5|14@0- (1,0) [0|0] "" NEO
|
||||
SG_ RollingCounter : 23|2@0+ (1,0) [0|0] "" NEO
|
||||
SG_ SetMe1 : 21|1@0+ (1,0) [0|0] "" NEO
|
||||
SG_ LKASVehicleSpeed : 20|13@0+ (0.22,0) [0|0] "kph" NEO
|
||||
SG_ LKASMode : 36|2@0+ (1,0) [0|0] "" NEO
|
||||
SG_ LKASteeringCmdChecksum : 33|10@0+ (1,0) [0|0] "" NEO
|
||||
|
||||
BO_ 340 ASCMBLKASteeringCmd: 6 NEO
|
||||
SG_ LKASteeringCmdActive : 7|1@0+ (1,0) [0|0] "" NEO
|
||||
SG_ LKASteeringCmd : 5|14@0- (1,0) [0|0] "" NEO
|
||||
SG_ RollingCounter : 23|2@0+ (1,0) [0|0] "" NEO
|
||||
SG_ SetMe1 : 21|1@0+ (1,0) [0|0] "" NEO
|
||||
SG_ LKASVehicleSpeed : 20|13@0+ (0.22,0) [0|0] "kph" NEO
|
||||
SG_ LKASteeringCmdActive2 : 35|1@0+ (1,0) [0|0] "" NEO
|
||||
SG_ LKASteeringCmdChecksum : 33|10@0+ (1,0) [0|0] "" NEO
|
||||
|
||||
BO_ 368 EBCMFrictionBrakeStatus: 8 K17_EBCM
|
||||
SG_ FrictionBrakePressure : 23|16@0+ (1,0) [0|0] "" NEO
|
||||
|
||||
BO_ 789 EBCMFrictionBrakeCmd: 5 K17_EBCM
|
||||
SG_ RollingCounter : 37|6@0+ (1,0) [0|0] "" NEO
|
||||
SG_ FrictionBrakeMode : 7|4@0+ (1,0) [0|0] "" NEO
|
||||
SG_ FrictionBrakeChecksum : 23|16@0+ (1,0) [0|0] "" NEO
|
||||
SG_ FrictionBrakeCmd : 3|12@0- (1,0) [0|0] "" NEO
|
||||
|
||||
BO_TX_BU_ 823 : K43_PSCM,NEO;
|
||||
BO_TX_BU_ 789 : NEO,K17_EBCM;
|
||||
|
||||
|
||||
CM_ BU_ K182_PACM "Parking Assist Control Module";
|
||||
CM_ BU_ K43_PSCM "Power Steering Control Module";
|
||||
CM_ BU_ K17_EBCM "Electronic Brake Control Module";
|
||||
CM_ BU_ NEO "Comma NEO";
|
||||
CM_ BU_ K124_ASCM "Active Safety Control Module";
|
||||
BA_DEF_ "UseGMParameterIDs" INT 0 0;
|
||||
BA_DEF_ "ProtocolType" STRING ;
|
||||
BA_DEF_ "BusType" STRING ;
|
||||
BA_DEF_DEF_ "UseGMParameterIDs" 1;
|
||||
BA_DEF_DEF_ "ProtocolType" "GMLAN";
|
||||
BA_DEF_DEF_ "BusType" "";
|
||||
BA_ "UseGMParameterIDs" 0;
|
||||
BA_ "BusType" "CAN";
|
||||
BA_ "ProtocolType" "GMLAN";
|
||||
|
||||
VAL_ 338 LKASteeringCmdActive 1 "Active" 0 "Inactive" ;
|
||||
VAL_ 338 LKASMode 2 "supercruise" 1 "lkas" 0 "Inactive" ;
|
||||
3470
opendbc/cadillac_ct6_object.dbc
Normal file
3470
opendbc/cadillac_ct6_object.dbc
Normal file
File diff suppressed because it is too large
Load Diff
244
opendbc/cadillac_ct6_powertrain.dbc
Normal file
244
opendbc/cadillac_ct6_powertrain.dbc
Normal file
@@ -0,0 +1,244 @@
|
||||
VERSION ""
|
||||
|
||||
|
||||
NS_ :
|
||||
NS_DESC_
|
||||
CM_
|
||||
BA_DEF_
|
||||
BA_
|
||||
VAL_
|
||||
CAT_DEF_
|
||||
CAT_
|
||||
FILTER
|
||||
BA_DEF_DEF_
|
||||
EV_DATA_
|
||||
ENVVAR_DATA_
|
||||
SGTYPE_
|
||||
SGTYPE_VAL_
|
||||
BA_DEF_SGTYPE_
|
||||
BA_SGTYPE_
|
||||
SIG_TYPE_REF_
|
||||
VAL_TABLE_
|
||||
SIG_GROUP_
|
||||
SIG_VALTYPE_
|
||||
SIGTYPE_VALTYPE_
|
||||
BO_TX_BU_
|
||||
BA_DEF_REL_
|
||||
BA_REL_
|
||||
BA_DEF_DEF_REL_
|
||||
BU_SG_REL_
|
||||
BU_EV_REL_
|
||||
BU_BO_REL_
|
||||
SG_MUL_VAL_
|
||||
|
||||
BS_:
|
||||
|
||||
BU_: K16_BECM K73_TCIC K9_BCM K43_PSCM K17_EBCM K20_ECM K114B_HPCM NEO K124_ASCM
|
||||
VAL_TABLE_ TurnSignals 2 "Right Turn" 1 "Left Turn" 0 "None" ;
|
||||
VAL_TABLE_ ACCLeadCar 1 "Present" 0 "Not Present" ;
|
||||
VAL_TABLE_ ACCCmdActive 1 "Active" 0 "Inactive" ;
|
||||
VAL_TABLE_ BrakePedalPressed 1 "Pressed" 0 "Depressed" ;
|
||||
VAL_TABLE_ DistanceButton 1 "Active" 0 "Inactive" ;
|
||||
VAL_TABLE_ LKAButton 1 "Active" 0 "Inactive" ;
|
||||
VAL_TABLE_ ACCButtons 6 "Cancel" 5 "Main" 3 "Set" 2 "Resume" 1 "None" ;
|
||||
VAL_TABLE_ PRNDL 3 "Reverse" 2 "Drive" 1 "Neutral" 0 "Park" ;
|
||||
VAL_TABLE_ DoorStatus 1 "Opened" 0 "Closed" ;
|
||||
VAL_TABLE_ SeatBeltStatus 1 "Latched" 0 "Unlatched" ;
|
||||
VAL_TABLE_ LKASteeringCmdActive 1 "Active" 0 "Inactive" ;
|
||||
VAL_TABLE_ ACCGapLevel 3 "Far" 2 "Med" 1 "Near" 0 "Inactive" ;
|
||||
VAL_TABLE_ GasRegenCmdActiveInv 1 "Inactive" 0 "Active" ;
|
||||
VAL_TABLE_ GasRegenCmdActive 1 "Active" 0 "Inactive" ;
|
||||
VAL_TABLE_ LKATorqueDeliveredStatus 3 "Failed" 2 "Temp. Limited" 1 "Active" 0 "Inactive" ;
|
||||
VAL_TABLE_ HandsOffSWDetectionStatus 1 "Hands On" 0 "Hands Off" ;
|
||||
VAL_TABLE_ HandsOffSWDetectionMode 2 "Failed" 1 "Enabled" 0 "Disabled" ;
|
||||
|
||||
|
||||
BO_ 717 ASCM_2CD: 5 K124_ASCM
|
||||
|
||||
BO_ 869 ASCM_365: 4 K124_ASCM
|
||||
|
||||
BO_ 1034 ASCM_40A: 7 K124_ASCM
|
||||
|
||||
BO_ 1296 ASCM_510: 4 K124_ASCM
|
||||
|
||||
BO_ 1930 ASCM_78A: 7 K124_ASCM
|
||||
|
||||
BO_ 190 ECMAcceleratorPos: 6 K20_ECM
|
||||
SG_ BrakePedalPos : 15|8@0+ (1,0) [0|0] "sticky" NEO
|
||||
SG_ GasPedalAndAcc : 23|8@0+ (1,0) [0|0] "" NEO
|
||||
|
||||
BO_ 201 ECMEngineStatus: 8 K20_ECM
|
||||
SG_ EngineTPS : 39|8@0+ (0.392156863,0) [0|100.000000065] "%" NEO
|
||||
SG_ EngineRPM : 15|16@0+ (0.25,0) [0|0] "RPM" NEO
|
||||
|
||||
BO_ 209 EBCMBrakePedalTorque: 7 K17_EBCM
|
||||
SG_ BrakePedalTorque : 3|12@0+ (1,0) [0|0] "" NEO
|
||||
|
||||
BO_ 241 EBCMBrakePedalPosition: 6 K17_EBCM
|
||||
SG_ BrakePedalPosition : 15|8@0+ (1,0) [0|255] "" NEO
|
||||
|
||||
BO_ 298 BCMDoorBeltStatus: 8 K9_BCM
|
||||
SG_ RearLeftDoor : 8|1@0+ (1,0) [0|0] "" NEO
|
||||
SG_ FrontLeftDoor : 9|1@0+ (1,0) [0|0] "" NEO
|
||||
SG_ FrontRightDoor : 10|1@0+ (1,0) [0|0] "" NEO
|
||||
SG_ RearRightDoor : 23|1@0+ (1,0) [0|0] "" NEO
|
||||
SG_ LeftSeatBelt : 12|1@0+ (1,0) [0|0] "" NEO
|
||||
SG_ RightSeatBelt : 53|1@0+ (1,0) [0|0] "" NEO
|
||||
|
||||
BO_ 309 ECMPRDNL: 8 K20_ECM
|
||||
SG_ PRNDL : 2|3@0+ (1,0) [0|0] "" NEO
|
||||
|
||||
BO_ 320 BCMTurnSignals: 3 K9_BCM
|
||||
SG_ TurnSignals : 19|2@0+ (1,0) [0|0] "" NEO
|
||||
|
||||
BO_ 336 ASCMLKASStatus: 1 NEO
|
||||
SG_ Available : 7|1@0+ (1,0) [0|0] "" NEO
|
||||
|
||||
BO_ 338 ASCMLKASteeringCmd: 6 NEO
|
||||
SG_ LKASteeringCmdActive : 7|1@0+ (1,0) [0|0] "" NEO
|
||||
SG_ LKASteeringCmd : 5|14@0- (1,0) [0|0] "" NEO
|
||||
SG_ RollingCounter : 23|2@0+ (1,0) [0|0] "" NEO
|
||||
SG_ SetMe1 : 21|1@0+ (1,0) [0|0] "" NEO
|
||||
SG_ LKASVehicleSpeed : 20|13@0+ (0.22,0) [0|0] "kph" NEO
|
||||
SG_ LKASMode : 36|2@0+ (1,0) [0|0] "" NEO
|
||||
SG_ LKASteeringCmdChecksum : 33|10@0+ (1,0) [0|0] "" NEO
|
||||
|
||||
BO_ 340 ASCMBLKASteeringCmd: 6 NEO
|
||||
SG_ LKASteeringCmdActive : 7|1@0+ (1,0) [0|0] "" NEO
|
||||
SG_ LKASteeringCmd : 5|14@0- (1,0) [0|0] "" NEO
|
||||
SG_ RollingCounter : 23|2@0+ (1,0) [0|0] "" NEO
|
||||
SG_ SetMe1 : 21|1@0+ (1,0) [0|0] "" NEO
|
||||
SG_ LKASVehicleSpeed : 20|13@0+ (0.22,0) [0|0] "kph" NEO
|
||||
SG_ LKASMode : 36|2@0+ (1,0) [0|0] "" NEO
|
||||
SG_ LKASteeringCmdChecksum : 33|10@0+ (1,0) [0|0] "" NEO
|
||||
|
||||
BO_ 381 MSG_17D: 8 K20_ECM
|
||||
SG_ MSG17D_AccPower : 35|12@0- (1,0) [0|0] "" NEO
|
||||
|
||||
BO_ 356 PSCMStatus: 8 K43_PSCM
|
||||
SG_ LKATorqueDeliveredStatus : 7|3@0+ (1,0) [0|7] "" NEO
|
||||
SG_ LKADriverAppldTrq : 2|11@0- (0.01,0) [-10.24|10.23] "Nm" NEO
|
||||
SG_ LKATBDTorque : 21|14@0- (-0.005,0) [-10.24|10.23] "Nm" NEO
|
||||
SG_ RollingCounter : 39|2@0+ (1,0) [0|0] "" NEO
|
||||
SG_ LKATotalTorqueDelivered : 37|14@0- (0.01,0) [-10.24|10.23] "Nm" NEO
|
||||
|
||||
BO_ 417 AcceleratorPedal: 7 XXX
|
||||
SG_ AcceleratorPedal : 55|8@0+ (1,0) [0|0] "" NEO
|
||||
|
||||
BO_ 451 GasAndAcc: 8 XXX
|
||||
SG_ GasPedalAndAcc2 : 55|8@0+ (1,0) [0|0] "" NEO
|
||||
|
||||
BO_ 452 AcceleratorPedal2: 8 XXX
|
||||
SG_ AcceleratorPedal2 : 47|8@0+ (1,0) [0|0] "" NEO
|
||||
|
||||
BO_ 481 ASCMSteeringButton: 7 K124_ASCM
|
||||
SG_ DistanceButton : 22|1@0+ (1,0) [0|0] "" NEO
|
||||
SG_ LKAButton : 23|1@0+ (1,0) [0|0] "" NEO
|
||||
SG_ ACCButtons : 46|3@0+ (1,0) [0|0] "" NEO
|
||||
|
||||
BO_ 485 PSCMSteeringAngle: 8 K43_PSCM
|
||||
SG_ SteeringWheelAngle : 15|16@0- (0.0625,0) [-540|540] "deg" NEO
|
||||
SG_ SteeringWheelRate : 27|12@0- (0.5,0) [-100|100] "deg/s" NEO
|
||||
|
||||
BO_ 489 EBCMVehicleDynamic: 8 K17_EBCM
|
||||
SG_ YawRate : 51|12@0- (0.0625,0) [-2047|2047] "grad/s" NEO
|
||||
SG_ LateralAcceleration : 3|12@0- (0.0161,0) [-2047|2047] "m/s2" NEO
|
||||
SG_ BrakePedalPressed : 6|1@0+ (1,0) [0|0] "" NEO
|
||||
|
||||
BO_ 711 BECMBatteryVoltageCurrent: 6 K17_EBCM
|
||||
SG_ HVBatteryVoltage : 31|12@0+ (0.125,0) [0|511.875] "V" NEO
|
||||
SG_ HVBatteryCurrent : 12|13@0- (0.15,0) [-614.4|614.25] "A" NEO
|
||||
|
||||
BO_ 715 ASCMGasRegenCmd: 8 K124_ASCM
|
||||
SG_ GasRegenAlwaysOne : 9|1@0+ (1,1) [1|1] "" NEO
|
||||
SG_ GasRegenAlwaysThree : 15|2@0+ (1,1) [1|1] "" NEO
|
||||
SG_ GasRegenChecksum : 47|24@0+ (1,0) [0|0] "" NEO
|
||||
SG_ GasRegenCmdActiveInv : 32|1@0+ (1,0) [0|0] "" NEO
|
||||
SG_ GasRegenFullStopActive : 13|1@0+ (1,0) [0|0] "" NEO
|
||||
SG_ GasRegenCmdActive : 0|1@0+ (1,0) [0|0] "" NEO
|
||||
SG_ RollingCounter : 7|2@0+ (1,0) [0|0] "" NEO
|
||||
SG_ RollingCounter2 : 36|4@0+ (1,0) [0|0] "" NEO
|
||||
SG_ GasRegenAlwaysOne2 : 23|1@0+ (1,0) [0|1] "" NEO
|
||||
SG_ GasRegenCmd : 22|15@0+ (1,0) [0|0] "" NEO
|
||||
|
||||
BO_ 810 TCICOnStarGPSPosition: 8 K73_TCIC
|
||||
SG_ GPSLongitude : 39|32@0+ (1,0) [0|0] "milliarcsecond" NEO
|
||||
SG_ GPSLatitude : 7|32@0+ (1,0) [0|0] "milliarcsecond" NEO
|
||||
|
||||
BO_ 840 EBCMWheelSpdFront: 4 K17_EBCM
|
||||
SG_ FLWheelSpd : 7|16@0+ (0.0311,0) [0|255] "km/h" NEO
|
||||
SG_ FRWheelSpd : 23|16@0+ (0.0311,0) [0|255] "km/h" NEO
|
||||
|
||||
BO_ 842 EBCMWheelSpdRear: 4 K17_EBCM
|
||||
SG_ RLWheelSpd : 7|16@0+ (0.0311,0) [0|255] "km/h" NEO
|
||||
SG_ RRWheelSpd : 23|16@0+ (0.0311,0) [0|255] "km/h" NEO
|
||||
|
||||
BO_ 880 ASCMActiveCruiseControlStatus: 6 K124_ASCM
|
||||
SG_ ACCLeadCar : 44|1@0+ (1,0) [0|0] "" Vector__XXX
|
||||
SG_ ACCAlwaysOne2 : 32|1@0+ (1,0) [0|0] "" Vector__XXX
|
||||
SG_ ACCAlwaysOne : 0|1@0+ (1,0) [0|0] "" Vector__XXX
|
||||
SG_ ACCSpeedSetpoint : 19|12@0+ (1,0) [0|0] "km/h" NEO
|
||||
SG_ ACCGapLevel : 21|2@0+ (1,0) [0|0] "" NEO
|
||||
SG_ ACCResumeButton : 1|1@0+ (1,0) [0|0] "" NEO
|
||||
SG_ ACCCmdActive : 23|1@0+ (1,0) [0|0] "" NEO
|
||||
|
||||
BO_ 1001 ECMVehicleSpeed: 8 K20_ECM
|
||||
SG_ VehicleSpeed : 7|16@0+ (0.01,0) [0|0] "mph" NEO
|
||||
|
||||
BO_ 1033 ASCMKeepAlive: 7 NEO
|
||||
SG_ ASCMKeepAliveAllZero : 7|56@0+ (1,0) [0|0] "" NEO
|
||||
|
||||
BO_ 1217 ECMEngineCoolantTemp: 8 K20_ECM
|
||||
SG_ EngineCoolantTemp : 23|8@0+ (1,-40) [0|0] "°C" NEO
|
||||
|
||||
BO_ 1249 VIN_Part2: 8 K20_ECM
|
||||
SG_ VINPart2 : 7|64@0+ (1,0) [0|0] "" NEO
|
||||
|
||||
BO_ 1300 VIN_Part1: 8 K20_ECM
|
||||
SG_ VINPart1 : 7|64@0+ (1,0) [0|0] "" NEO
|
||||
|
||||
BO_ 1912 PSCM_778: 8 K43_PSCM
|
||||
|
||||
BO_TX_BU_ 338 : K124_ASCM,NEO;
|
||||
BO_TX_BU_ 880 : NEO,K124_ASCM;
|
||||
BO_TX_BU_ 1033 : K124_ASCM,NEO;
|
||||
BO_TX_BU_ 715 : NEO,K124_ASCM;
|
||||
|
||||
|
||||
CM_ BU_ K16_BECM "Battery Energy Control Module";
|
||||
CM_ BU_ K73_TCIC "Telematics Communication Control Module";
|
||||
CM_ BU_ K9_BCM "Body Control Module";
|
||||
CM_ BU_ K43_PSCM "Power Steering Control Module";
|
||||
CM_ BU_ K17_EBCM "Electronic Brake Control Module";
|
||||
CM_ BU_ K20_ECM "Engine Control Module";
|
||||
CM_ BU_ K114B_HPCM "Hybrid Powertrain Control Module";
|
||||
CM_ BU_ NEO "Comma NEO";
|
||||
CM_ BU_ K124_ASCM "Active Safety Control Module";
|
||||
CM_ SG_ 381 MSG17D_AccPower "Need to investigate";
|
||||
CM_ SG_ 190 GasPedalAndAcc "ACC baseline is 62";
|
||||
CM_ SG_ 451 GasPedalAndAcc2 "ACC baseline is 62";
|
||||
CM_ SG_ 715 RollingCounter2 "Values cycle between 0, 7, 10, 13";
|
||||
BA_DEF_ "UseGMParameterIDs" INT 0 0;
|
||||
BA_DEF_ "ProtocolType" STRING ;
|
||||
BA_DEF_ "BusType" STRING ;
|
||||
BA_DEF_DEF_ "UseGMParameterIDs" 1;
|
||||
BA_DEF_DEF_ "ProtocolType" "GMLAN";
|
||||
BA_DEF_DEF_ "BusType" "";
|
||||
BA_ "BusType" "CAN";
|
||||
BA_ "ProtocolType" "GMLAN";
|
||||
BA_ "UseGMParameterIDs" 0;
|
||||
VAL_ 481 DistanceButton 1 "Active" 0 "Inactive" ;
|
||||
VAL_ 481 LKAButton 1 "Active" 0 "Inactive" ;
|
||||
VAL_ 481 ACCButtons 6 "Cancel" 5 "Main" 3 "Set" 2 "Resume" 1 "None" ;
|
||||
VAL_ 309 PRNDL 3 "Reverse" 2 "Drive" 1 "Neutral" 0 "Park" ;
|
||||
VAL_ 338 LKASteeringCmdActive 1 "Active" 0 "Inactive" ;
|
||||
VAL_ 338 LKASMode 2 "supercruise" 1 "lkas" 0 "Inactive" ;
|
||||
VAL_ 880 ACCLeadCar 1 "Present" 0 "Not Present" ;
|
||||
VAL_ 880 ACCGapLevel 3 "Far" 2 "Med" 1 "Near" 0 "Inactive" ;
|
||||
VAL_ 880 ACCResumeButton 1 "Pressed" 0 "Depressed" ;
|
||||
VAL_ 880 ACCCmdActive 1 "Active" 0 "Inactive" ;
|
||||
VAL_ 356 LKATorqueDeliveredStatus 7 "Override Fault" 6 "LKAS Fault but Responsive" 5 "TBD but Responsive" 4 "TBD but Responsive" 3 "Fault" 1 "Active" 0 "Inactive" ;
|
||||
VAL_ 489 BrakePedalPressed 1 "Pressed" 0 "Depressed" ;
|
||||
VAL_ 715 GasRegenCmdActiveInv 1 "Inactive" 0 "Active" ;
|
||||
VAL_ 715 GasRegenCmdActive 1 "Active" 0 "Inactive" ;
|
||||
|
||||
@@ -76,6 +76,7 @@ BO_ 146 Accel_Data: 8 XXX
|
||||
SG_ VehLat_A_Actl : 4|13@0+ (0.01,-40.0) [0|0] "m/s^2" XXX
|
||||
|
||||
BO_ 357 Cruise_Status: 8 XXX
|
||||
SG_ Brake_Drv_Appl : 5|1@0+ (1,0) [0|0] "" XXX
|
||||
SG_ Cruise_State : 11|4@0+ (1,0) [0|0] "" XXX
|
||||
SG_ Set_Speed : 23|8@0+ (1,0) [0|0] "" XXX
|
||||
|
||||
@@ -99,6 +100,15 @@ BO_ 534 WheelData: 8 XXX
|
||||
SG_ WhlRotatFl_No_Cnt : 15|8@0+ (1,0) [0|0] "" XXX
|
||||
SG_ WHEEL_ROLLING_TIMESTAMP : 47|8@0+ (1,0) [0|0] "" XXX
|
||||
|
||||
BO_ 947 Doors: 8 XXX
|
||||
SG_ Door_FL_Open : 61|1@0+ (1,0) [0|0] "" XXX
|
||||
SG_ Door_FR_Open : 60|1@0+ (1,0) [0|0] "" XXX
|
||||
SG_ Door_RL_Open : 48|1@0+ (1,0) [0|0] "" XXX
|
||||
SG_ Door_RR_Open : 49|1@0+ (1,0) [0|0] "" XXX
|
||||
|
||||
BO_ 963 BCM_to_HS_Body: 8 XXX
|
||||
SG_ Brake_Lights : 8|1@0+ (1,0) [0|0] "" XXX
|
||||
|
||||
BO_ 970 Lane_Keep_Assist_Control: 8 XXX
|
||||
SG_ Lkas_Action : 7|4@0+ (1,0) [0|15] "" XXX
|
||||
SG_ Lkas_Alert : 3|4@0+ (1,0) [0|15] "" XXX
|
||||
@@ -119,7 +129,8 @@ BO_ 984 Lane_Keep_Assist_Ui: 8 XXX
|
||||
SG_ Set_Me_X30 : 63|8@0+ (1,0) [0|255] "" XXX
|
||||
|
||||
VAL_ 357 Cruise_State 4 "active" 3 "standby" 0 "off" ;
|
||||
VAL_ 970 Lkas_Action 15 "off" 9 "active" ;
|
||||
VAL_ 970 Lkas_Action 15 "off" 9 "abrupt" 8 "abrupt2" 5 "smooth" 4 "smooth2" ;
|
||||
VAL_ 970 Lkas_Alert 15 "no_alert" 3 "high_intensity" 2 "mid_intensity" 1 "low_intensity" ;
|
||||
VAL_ 972 LaActAvail_D_Actl 3 "available" 2 "tbd" 1 "not_available" 0 "fault" ;
|
||||
VAL_ 984 Lines_Hud 15 "none" 11 "grey_yellow" 8 "green_red" 7 "yellow_grey" 6 "grey_grey" 4 "red_green" 3 "green_green" ;
|
||||
CM_ SG_ 970 Lkas_Action "only vals 4, 5, 8, 9 seem to work. 4 and 5 are a bit smoother" ;
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
CM_ "IMPORT _honda_2017.dbc"
|
||||
CM_ "IMPORT _comma.dbc"
|
||||
|
||||
BO_ 342 STEERING_SENSORS: 6 EPS
|
||||
SG_ STEER_ANGLE : 7|16@0- (-0.1,0) [-500|500] "deg" EON
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
CM_ "IMPORT _honda_2017.dbc"
|
||||
CM_ "IMPORT _comma.dbc"
|
||||
|
||||
BO_ 342 STEERING_SENSORS: 6 EPS
|
||||
SG_ STEER_ANGLE : 7|16@0- (-0.1,0) [-500|500] "deg" EON
|
||||
@@ -71,4 +72,4 @@ VAL_ 422 LIGHTS_SETTING 3 "high_beam" 2 "low_beam" 1 "position" 0 "no_lights" ;
|
||||
VAL_ 422 CRUISE_SETTING 3 "distance_adj" 2 "tbd" 1 "lkas_button" 0 "none" ;
|
||||
VAL_ 891 WIPERS 4 "High" 2 "Low" 0 "Off" ;
|
||||
|
||||
CM_ "CHFFR_METRIC 342 STEER_ANGLE STEER_ANGLE 0.36 180; CHFFR_METRIC 380 ENGINE_RPM ENGINE_RPM 1 0; CHFFR_METRIC 804 ENGINE_TEMPERATURE ENGINE_TEMPERATURE 1 0";
|
||||
CM_ "CHFFR_METRIC 342 STEER_ANGLE STEER_ANGLE 0.36 180; CHFFR_METRIC 380 ENGINE_RPM ENGINE_RPM 1 0; CHFFR_METRIC 804 ENGINE_TEMPERATURE ENGINE_TEMPERATURE 1 0";
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
CM_ "IMPORT _honda_2017.dbc"
|
||||
CM_ "IMPORT _comma.dbc"
|
||||
|
||||
BO_ 228 STEERING_CONTROL: 5 ADAS
|
||||
SG_ STEER_TORQUE : 7|16@0- (1,0) [-3840|3840] "" EPS
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
CM_ "IMPORT _honda_2017.dbc"
|
||||
CM_ "IMPORT _comma.dbc"
|
||||
|
||||
BO_ 145 KINEMATICS: 8 XXX
|
||||
SG_ LAT_ACCEL : 7|10@0+ (0.02,-512) [-20|20] "m/s2" EON
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
CM_ "IMPORT _honda_2017.dbc"
|
||||
CM_ "IMPORT _comma.dbc"
|
||||
|
||||
BO_ 145 KINEMATICS: 8 XXX
|
||||
SG_ LAT_ACCEL : 7|10@0+ (0.02,-512) [-20|20] "m/s2" EON
|
||||
|
||||
11
opendbc/generator/toyota/_comma.dbc
Normal file
11
opendbc/generator/toyota/_comma.dbc
Normal file
@@ -0,0 +1,11 @@
|
||||
BO_ 359 STEERING_IPAS_COMMA: 8 IPAS
|
||||
SG_ STATE : 7|4@0+ (1,0) [0|15] "" XXX
|
||||
SG_ ANGLE : 3|12@0- (1.5,0) [-510|510] "deg" XXX
|
||||
SG_ SET_ME_X10 : 23|8@0+ (1,0) [0|255] "" XXX
|
||||
SG_ SET_ME_X00 : 31|8@0+ (1,0) [0|255] "" XXX
|
||||
SG_ DIRECTION_CMD : 38|2@0+ (1,0) [0|3] "" XXX
|
||||
SG_ SET_ME_X40 : 47|8@0+ (1,0) [0|255] "" XXX
|
||||
SG_ SET_ME_X00 : 55|8@0+ (1,0) [0|255] "" XXX
|
||||
SG_ CHECKSUM : 63|8@0+ (1,0) [0|255] "" XXX
|
||||
|
||||
CM BO_ STEERING_IPAS_COMMA "Copy of msg 614 so we can do angle control while the Park Assist ECU is connected (Panda spoofs 614 with 359 on connector J70). Note that addresses 0x266 and 0x167 are checksum-invariant";
|
||||
33
opendbc/generator/toyota/toyota_avalon_2017_pt.dbc
Normal file
33
opendbc/generator/toyota/toyota_avalon_2017_pt.dbc
Normal file
@@ -0,0 +1,33 @@
|
||||
CM_ "IMPORT _toyota_2017.dbc"
|
||||
CM_ "IMPORT _comma.dbc"
|
||||
|
||||
BO_ 550 BRAKE_MODULE: 8 XXX
|
||||
SG_ BRAKE_PRESSURE : 0|9@0+ (1,0) [0|255] "" XXX
|
||||
SG_ BRAKE_POSITION : 16|9@0+ (1,0) [0|65535] "" XXX
|
||||
SG_ BRAKE_PRESSED : 37|1@0+ (1,0) [0|3] "" XXX
|
||||
|
||||
BO_ 705 GAS_PEDAL: 8 XXX
|
||||
SG_ GAS_RELEASED : 3|1@0+ (1,0) [0|1] "" XXX
|
||||
SG_ GAS_PEDAL : 55|8@0+ (0.005,0) [0|1] "" XXX
|
||||
|
||||
BO_ 608 STEER_TORQUE_SENSOR: 8 XXX
|
||||
SG_ STEER_TORQUE_EPS : 47|16@0- (0.73,0) [-20000|20000] "" XXX
|
||||
SG_ STEER_TORQUE_DRIVER : 15|16@0- (1,0) [-32768|32767] "" XXX
|
||||
SG_ STEER_OVERRIDE : 0|1@0+ (1,0) [0|1] "" XXX
|
||||
SG_ CHECKSUM : 63|8@0+ (1,0) [0|255] "" XXX
|
||||
|
||||
BO_ 610 EPS_STATUS: 5 EPS
|
||||
SG_ IPAS_STATE : 3|4@0+ (1,0) [0|15] "" XXX
|
||||
SG_ LKA_STATE : 31|7@0+ (1,0) [0|127] "" XXX
|
||||
SG_ TYPE : 24|1@0+ (1,0) [0|1] "" XXX
|
||||
SG_ CHECKSUM : 39|8@0+ (1,0) [0|255] "" XXX
|
||||
|
||||
BO_ 956 GEAR_PACKET: 8 XXX
|
||||
SG_ GEAR : 13|6@0+ (1,0) [0|63] "" XXX
|
||||
|
||||
CM_ SG_ 548 BRAKE_PRESSURE "seems prop to pedal force";
|
||||
CM_ SG_ 548 BRAKE_POSITION "seems proportional to pedal displacement, unclear the max value of 0x1c8";
|
||||
CM_ SG_ 610 TYPE "seems 1 on Corolla, 0 on all others";
|
||||
VAL_ 956 GEAR 0 "D" 1 "S" 8 "N" 16 "R" 32 "P";
|
||||
VAL_ 610 IPAS_STATE 5 "override" 3 "enabled" 1 "disabled";
|
||||
VAL_ 610 LKA_STATE 25 "temporary_fault" 9 "temporary_fault2" 5 "active" 1 "standby";
|
||||
33
opendbc/generator/toyota/toyota_highlander_2017_pt.dbc
Normal file
33
opendbc/generator/toyota/toyota_highlander_2017_pt.dbc
Normal file
@@ -0,0 +1,33 @@
|
||||
CM_ "IMPORT _toyota_2017.dbc"
|
||||
CM_ "IMPORT _comma.dbc"
|
||||
|
||||
BO_ 550 BRAKE_MODULE: 8 XXX
|
||||
SG_ BRAKE_PRESSURE : 0|9@0+ (1,0) [0|255] "" XXX
|
||||
SG_ BRAKE_POSITION : 16|9@0+ (1,0) [0|65535] "" XXX
|
||||
SG_ BRAKE_PRESSED : 37|1@0+ (1,0) [0|3] "" XXX
|
||||
|
||||
BO_ 705 GAS_PEDAL: 8 XXX
|
||||
SG_ GAS_RELEASED : 3|1@0+ (1,0) [0|1] "" XXX
|
||||
SG_ GAS_PEDAL : 55|8@0+ (0.005,0) [0|1] "" XXX
|
||||
|
||||
BO_ 608 STEER_TORQUE_SENSOR: 8 XXX
|
||||
SG_ STEER_TORQUE_EPS : 47|16@0- (0.73,0) [-20000|20000] "" XXX
|
||||
SG_ STEER_TORQUE_DRIVER : 15|16@0- (1,0) [-32768|32767] "" XXX
|
||||
SG_ STEER_OVERRIDE : 0|1@0+ (1,0) [0|1] "" XXX
|
||||
SG_ CHECKSUM : 63|8@0+ (1,0) [0|255] "" XXX
|
||||
|
||||
BO_ 610 EPS_STATUS: 5 EPS
|
||||
SG_ IPAS_STATE : 3|4@0+ (1,0) [0|15] "" XXX
|
||||
SG_ LKA_STATE : 31|7@0+ (1,0) [0|127] "" XXX
|
||||
SG_ TYPE : 24|1@0+ (1,0) [0|1] "" XXX
|
||||
SG_ CHECKSUM : 39|8@0+ (1,0) [0|255] "" XXX
|
||||
|
||||
BO_ 956 GEAR_PACKET: 8 XXX
|
||||
SG_ GEAR : 13|6@0+ (1,0) [0|63] "" XXX
|
||||
|
||||
CM_ SG_ 548 BRAKE_PRESSURE "seems prop to pedal force";
|
||||
CM_ SG_ 548 BRAKE_POSITION "seems proportional to pedal displacement, unclear the max value of 0x1c8";
|
||||
CM_ SG_ 610 TYPE "seems 1 on Corolla, 0 on all others";
|
||||
VAL_ 956 GEAR 0 "D" 1 "S" 8 "N" 16 "R" 32 "P";
|
||||
VAL_ 610 IPAS_STATE 5 "override" 3 "enabled" 1 "disabled";
|
||||
VAL_ 610 LKA_STATE 25 "temporary_fault" 9 "temporary_fault2" 5 "active" 1 "standby";
|
||||
@@ -52,7 +52,7 @@ BO_ 789 EBCMFrictionBrakeCmd: 5 K17_EBCM
|
||||
SG_ RollingCounter : 33|2@0+ (1,0) [0|0] "" NEO
|
||||
SG_ FrictionBrakeMode : 7|4@0+ (1,0) [0|0] "" NEO
|
||||
SG_ FrictionBrakeChecksum : 23|16@0+ (1,0) [0|0] "" NEO
|
||||
SG_ FirctionBrakeCmd : 3|12@0- (1,0) [0|0] "" NEO
|
||||
SG_ FrictionBrakeCmd : 3|12@0- (1,0) [0|0] "" NEO
|
||||
|
||||
BO_TX_BU_ 823 : K43_PSCM,NEO;
|
||||
BO_TX_BU_ 789 : NEO,K17_EBCM;
|
||||
|
||||
@@ -33,7 +33,7 @@ NS_ :
|
||||
|
||||
BS_:
|
||||
|
||||
BU_: K16_BECM K73_TCIC K9_BCM K43_PSCM K17_EBCM K20_ECM K114B_HPCM NEO K124_ASCM
|
||||
BU_: K16_BECM K73_TCIC K9_BCM K43_PSCM K17_EBCM K20_ECM K114B_HPCM NEO K124_ASCM EPB
|
||||
VAL_TABLE_ TurnSignals 2 "Right Turn" 1 "Left Turn" 0 "None" ;
|
||||
VAL_TABLE_ ACCLeadCar 1 "Present" 0 "Not Present" ;
|
||||
VAL_TABLE_ ACCCmdActive 1 "Active" 0 "Inactive" ;
|
||||
@@ -53,36 +53,23 @@ VAL_TABLE_ HandsOffSWDetectionStatus 1 "Hands On" 0 "Hands Off" ;
|
||||
VAL_TABLE_ HandsOffSWDetectionMode 2 "Failed" 1 "Enabled" 0 "Disabled" ;
|
||||
|
||||
|
||||
BO_ 320 BCMTurnSignals: 3 K9_BCM
|
||||
SG_ TurnSignals : 19|2@0+ (1,0) [0|0] "" NEO
|
||||
BO_ 189 EBCMRegenPaddle: 7 K17_EBCM
|
||||
SG_ RegenPaddle : 7|4@0+ (1,0) [0|0] "" NEO
|
||||
|
||||
BO_ 1217 ECMEngineCoolantTemp: 8 K20_ECM
|
||||
SG_ EngineCoolantTemp : 23|8@0+ (1,-40) [0|0] "°C" NEO
|
||||
BO_ 190 ECMAcceleratorPos: 6 K20_ECM
|
||||
SG_ BrakePedalPos : 15|8@0+ (1,0) [0|0] "sticky" NEO
|
||||
SG_ GasPedalAndAcc : 23|8@0+ (1,0) [0|0] "" NEO
|
||||
|
||||
BO_ 1249 VIN_Part2: 8 K20_ECM
|
||||
SG_ VINPart2 : 7|64@0+ (1,0) [0|0] "" NEO
|
||||
BO_ 201 ECMEngineStatus: 8 K20_ECM
|
||||
SG_ EngineTPS : 39|8@0+ (0.392156863,0) [0|100.000000065] "%" NEO
|
||||
SG_ EngineRPM : 15|16@0+ (0.25,0) [0|0] "RPM" NEO
|
||||
SG_ CruiseMainOn : 29|1@0+ (1,0) [0|1] "" NEO
|
||||
|
||||
BO_ 1300 VIN_Part1: 8 K20_ECM
|
||||
SG_ VINPart1 : 7|64@0+ (1,0) [0|0] "" NEO
|
||||
BO_ 209 EBCMBrakePedalTorque: 7 K17_EBCM
|
||||
SG_ BrakePedalTorque : 3|12@0+ (1,0) [0|0] "" NEO
|
||||
|
||||
BO_ 481 ASCMSteeringButton: 7 K124_ASCM
|
||||
SG_ DistanceButton : 22|1@0+ (1,0) [0|0] "" NEO
|
||||
SG_ LKAButton : 23|1@0+ (1,0) [0|0] "" NEO
|
||||
SG_ ACCButtons : 46|3@0+ (1,0) [0|0] "" NEO
|
||||
|
||||
BO_ 1912 PSCM_778: 8 K43_PSCM
|
||||
|
||||
BO_ 328 PSCM_148: 1 K43_PSCM
|
||||
|
||||
BO_ 309 ECMPRDNL: 8 K20_ECM
|
||||
SG_ PRNDL : 2|3@0+ (1,0) [0|0] "" NEO
|
||||
|
||||
BO_ 810 TCICOnStarGPSPosition: 8 K73_TCIC
|
||||
SG_ GPSLongitude : 39|32@0+ (1,0) [0|0] "milliarcsecond" NEO
|
||||
SG_ GPSLatitude : 7|32@0+ (1,0) [0|0] "milliarcsecond" NEO
|
||||
|
||||
BO_ 1001 ECMVehicleSpeed: 8 K20_ECM
|
||||
SG_ VehicleSpeed : 7|16@0+ (0.01,0) [0|0] "mph" NEO
|
||||
BO_ 241 EBCMBrakePedalPosition: 6 K17_EBCM
|
||||
SG_ BrakePedalPosition : 15|8@0+ (1,0) [0|255] "" NEO
|
||||
|
||||
BO_ 298 BCMDoorBeltStatus: 8 K9_BCM
|
||||
SG_ RearLeftDoor : 8|1@0+ (1,0) [0|0] "" NEO
|
||||
@@ -92,22 +79,89 @@ BO_ 298 BCMDoorBeltStatus: 8 K9_BCM
|
||||
SG_ LeftSeatBelt : 12|1@0+ (1,0) [0|0] "" NEO
|
||||
SG_ RightSeatBelt : 53|1@0+ (1,0) [0|0] "" NEO
|
||||
|
||||
BO_ 381 MSG_17D: 6 K20_ECM
|
||||
BO_ 309 ECMPRDNL: 8 K20_ECM
|
||||
SG_ PRNDL : 2|3@0+ (1,0) [0|0] "" NEO
|
||||
|
||||
BO_ 320 BCMTurnSignals: 3 K9_BCM
|
||||
SG_ TurnSignals : 19|2@0+ (1,0) [0|0] "" NEO
|
||||
|
||||
BO_ 328 PSCM_148: 1 K43_PSCM
|
||||
|
||||
BO_ 381 ESPStatus: 6 K20_ECM
|
||||
SG_ TractionControlOn : 5|1@0+ (1,0) [0|0] "" NEO
|
||||
SG_ MSG17D_AccPower : 35|12@0- (1,0) [0|0] "" NEO
|
||||
|
||||
BO_ 201 ECMEngineStatus: 8 K20_ECM
|
||||
SG_ EngineTPS : 39|8@0+ (0.392156863,0) [0|100.000000065] "%" NEO
|
||||
SG_ EngineRPM : 15|16@0+ (0.25,0) [0|0] "RPM" NEO
|
||||
|
||||
BO_ 209 EBCMBrakePedalTorque: 7 K17_EBCM
|
||||
SG_ BrakePedalTorque : 3|12@0+ (1,0) [0|0] "" NEO
|
||||
|
||||
BO_ 384 ASCMLKASteeringCmd: 4 NEO
|
||||
SG_ RollingCounter : 5|2@0+ (1,0) [0|0] "" NEO
|
||||
SG_ LKASteeringCmdChecksum : 19|12@0+ (1,0) [0|0] "" NEO
|
||||
SG_ LKASteeringCmdActive : 3|1@0+ (1,0) [0|0] "" NEO
|
||||
SG_ LKASteeringCmd : 2|11@0- (1,0) [0|0] "" NEO
|
||||
|
||||
BO_ 388 PSCMStatus: 8 K43_PSCM
|
||||
SG_ HandsOffSWDetectionMode : 20|2@0+ (1,0) [0|3] "" NEO
|
||||
SG_ HandsOffSWlDetectionStatus : 21|1@0+ (1,0) [0|1] "" NEO
|
||||
SG_ LKATorqueDeliveredStatus : 5|3@0+ (1,0) [0|7] "" NEO
|
||||
SG_ LKADriverAppldTrq : 50|11@0- (0.01,0) [-10.24|10.23] "Nm" NEO
|
||||
SG_ LKATotalTorqueDelivered : 2|11@0- (0.01,0) [-10.24|10.23] "Nm" NEO
|
||||
|
||||
BO_ 417 AcceleratorPedal: 8 XXX
|
||||
SG_ AcceleratorPedal : 55|8@0+ (1,0) [0|0] "" NEO
|
||||
|
||||
BO_ 451 GasAndAcc: 8 XXX
|
||||
SG_ GasPedalAndAcc2 : 55|8@0+ (1,0) [0|0] "" NEO
|
||||
|
||||
BO_ 452 AcceleratorPedal2: 8 XXX
|
||||
SG_ CruiseState : 15|3@0+ (1,0) [0|7] "" NEO
|
||||
SG_ AcceleratorPedal2 : 47|8@0+ (1,0) [0|0] "" NEO
|
||||
|
||||
BO_ 481 ASCMSteeringButton: 7 K124_ASCM
|
||||
SG_ DistanceButton : 22|1@0+ (1,0) [0|0] "" NEO
|
||||
SG_ LKAButton : 23|1@0+ (1,0) [0|0] "" NEO
|
||||
SG_ ACCButtons : 46|3@0+ (1,0) [0|0] "" NEO
|
||||
|
||||
BO_ 485 PSCMSteeringAngle: 8 K43_PSCM
|
||||
SG_ SteeringWheelAngle : 15|16@0- (0.0625,0) [-540|540] "deg" NEO
|
||||
SG_ SteeringWheelRate : 27|12@0- (0.5,0) [-100|100] "deg/s" NEO
|
||||
|
||||
BO_ 489 EBCMVehicleDynamic: 8 K17_EBCM
|
||||
SG_ YawRate : 51|12@0- (0.0625,0) [-2047|2047] "grad/s" NEO
|
||||
SG_ LateralAcceleration : 3|12@0- (0.0161,0) [-2047|2047] "m/s2" NEO
|
||||
SG_ BrakePedalPressed : 6|1@0+ (1,0) [0|0] "" NEO
|
||||
|
||||
BO_ 560 EPBStatus: 8 EPB
|
||||
SG_ EPBClosed : 12|1@0+ (1,0) [0|1] "" NEO
|
||||
|
||||
BO_ 711 BECMBatteryVoltageCurrent: 6 K17_EBCM
|
||||
SG_ HVBatteryVoltage : 31|12@0+ (0.125,0) [0|511.875] "V" NEO
|
||||
SG_ HVBatteryCurrent : 12|13@0- (0.15,0) [-614.4|614.25] "A" NEO
|
||||
|
||||
BO_ 715 ASCMGasRegenCmd: 8 K124_ASCM
|
||||
SG_ GasRegenAlwaysOne2 : 9|1@0+ (1,0) [0|1] "" NEO
|
||||
SG_ GasRegenAlwaysOne : 14|1@0+ (1,0) [0|1] "" NEO
|
||||
SG_ GasRegenChecksum : 47|24@0+ (1,0) [0|0] "" NEO
|
||||
SG_ GasRegenCmdActiveInv : 32|1@0+ (1,0) [0|0] "" NEO
|
||||
SG_ GasRegenFullStopActive : 13|1@0+ (1,0) [0|0] "" NEO
|
||||
SG_ GasRegenCmdActive : 0|1@0+ (1,0) [0|0] "" NEO
|
||||
SG_ RollingCounter : 7|2@0+ (1,0) [0|0] "" NEO
|
||||
SG_ GasRegenAlwaysOne3 : 23|1@0+ (1,0) [0|1] "" NEO
|
||||
SG_ GasRegenCmd : 22|12@0+ (1,0) [0|0] "" NEO
|
||||
|
||||
BO_ 717 ASCM_2CD: 5 K124_ASCM
|
||||
|
||||
BO_ 810 TCICOnStarGPSPosition: 8 K73_TCIC
|
||||
SG_ GPSLongitude : 39|32@0+ (1,0) [0|0] "milliarcsecond" NEO
|
||||
SG_ GPSLatitude : 7|32@0+ (1,0) [0|0] "milliarcsecond" NEO
|
||||
|
||||
BO_ 840 EBCMWheelSpdFront: 4 K17_EBCM
|
||||
SG_ FLWheelSpd : 7|16@0+ (0.0311,0) [0|255] "km/h" NEO
|
||||
SG_ FRWheelSpd : 23|16@0+ (0.0311,0) [0|255] "km/h" NEO
|
||||
|
||||
BO_ 842 EBCMWheelSpdRear: 4 K17_EBCM
|
||||
SG_ RLWheelSpd : 7|16@0+ (0.0311,0) [0|255] "km/h" NEO
|
||||
SG_ RRWheelSpd : 23|16@0+ (0.0311,0) [0|255] "km/h" NEO
|
||||
|
||||
BO_ 869 ASCM_365: 4 K124_ASCM
|
||||
|
||||
BO_ 880 ASCMActiveCruiseControlStatus: 6 K124_ASCM
|
||||
SG_ ACCLeadCar : 44|1@0+ (1,0) [0|0] "" Vector__XXX
|
||||
SG_ ACCAlwaysOne2 : 32|1@0+ (1,0) [0|0] "" Vector__XXX
|
||||
@@ -117,76 +171,28 @@ BO_ 880 ASCMActiveCruiseControlStatus: 6 K124_ASCM
|
||||
SG_ ACCResumeButton : 1|1@0+ (1,0) [0|0] "" NEO
|
||||
SG_ ACCCmdActive : 23|1@0+ (1,0) [0|0] "" NEO
|
||||
|
||||
BO_ 1930 ASCM_78A: 7 K124_ASCM
|
||||
|
||||
BO_ 1296 ASCM_510: 4 K124_ASCM
|
||||
|
||||
BO_ 1034 ASCM_40A: 7 K124_ASCM
|
||||
|
||||
BO_ 869 ASCM_365: 4 K124_ASCM
|
||||
|
||||
BO_ 717 ASCM_2CD: 5 K124_ASCM
|
||||
BO_ 1001 ECMVehicleSpeed: 8 K20_ECM
|
||||
SG_ VehicleSpeed : 7|16@0+ (0.01,0) [0|0] "mph" NEO
|
||||
|
||||
BO_ 1033 ASCMKeepAlive: 7 NEO
|
||||
SG_ ASCMKeepAliveAllZero : 7|56@0+ (1,0) [0|0] "" NEO
|
||||
|
||||
BO_ 485 PSCMSteeringAngle: 8 K43_PSCM
|
||||
SG_ SteeringWheelAngle : 15|16@0- (0.0625,0) [-540|540] "deg" NEO
|
||||
SG_ SteeringWheelRate : 27|12@0- (0.5,0) [-100|100] "deg/s" NEO
|
||||
BO_ 1034 ASCM_40A: 7 K124_ASCM
|
||||
|
||||
BO_ 388 PSCMStatus: 8 K43_PSCM
|
||||
SG_ HandsOffSWDetectionMode : 20|2@0+ (1,0) [0|3] "" NEO
|
||||
SG_ HandsOffSWlDetectionStatus : 21|1@0+ (1,0) [0|1] "" NEO
|
||||
SG_ LKATorqueDeliveredStatus : 5|3@0+ (1,0) [0|7] "" NEO
|
||||
SG_ LKADriverAppldTrq : 50|11@0- (0.01,0) [-10.24|10.23] "Nm" NEO
|
||||
SG_ LKATotalTorqueDelivered : 2|11@0- (0.01,0) [-10.24|10.23] "Nm" NEO
|
||||
BO_ 1217 ECMEngineCoolantTemp: 8 K20_ECM
|
||||
SG_ EngineCoolantTemp : 23|8@0+ (1,-40) [0|0] "°C" NEO
|
||||
|
||||
BO_ 489 EBCMVehicleDynamic: 8 K17_EBCM
|
||||
SG_ YawRate : 51|12@0- (0.0625,0) [-2047|2047] "grad/s" NEO
|
||||
SG_ LateralAcceleration : 3|12@0- (0.0161,0) [-2047|2047] "m/s2" NEO
|
||||
SG_ BrakePedalPressed : 6|1@0+ (1,0) [0|0] "" NEO
|
||||
BO_ 1249 VIN_Part2: 8 K20_ECM
|
||||
SG_ VINPart2 : 7|64@0+ (1,0) [0|0] "" NEO
|
||||
|
||||
BO_ 189 EBCMRegenPaddle: 7 K17_EBCM
|
||||
SG_ RegenPaddle : 7|4@0+ (1,0) [0|0] "" NEO
|
||||
BO_ 1296 ASCM_510: 4 K124_ASCM
|
||||
|
||||
BO_ 190 ECMAcceleratorPos: 6 K20_ECM
|
||||
SG_ BrakePedalPos : 15|8@0+ (1,0) [0|0] "sticky" NEO
|
||||
SG_ GasPedalAndAcc : 23|8@0+ (1,0) [0|0] "" NEO
|
||||
BO_ 1300 VIN_Part1: 8 K20_ECM
|
||||
SG_ VINPart1 : 7|64@0+ (1,0) [0|0] "" NEO
|
||||
|
||||
BO_ 715 ASCMGasRegenCmd: 8 K124_ASCM
|
||||
SG_ GasRegenAlwaysOne2 : 9|1@0+ (1,1) [1|1] "" NEO
|
||||
SG_ GasRegenAlwaysOne : 14|1@0+ (1,1) [1|1] "" NEO
|
||||
SG_ GasRegenChecksum : 47|24@0+ (1,0) [0|0] "" NEO
|
||||
SG_ GasRegenCmdActiveInv : 32|1@0+ (1,0) [0|0] "" NEO
|
||||
SG_ GasRegenFullStopActive : 13|1@0+ (1,0) [0|0] "" NEO
|
||||
SG_ GasRegenCmdActive : 0|1@0+ (1,0) [0|0] "" NEO
|
||||
SG_ RollingCounter : 7|2@0+ (1,0) [0|0] "" NEO
|
||||
SG_ GasRegenAlwaysOne3 : 23|1@0+ (1,0) [0|1] "" NEO
|
||||
SG_ GasRegenCmd : 22|12@0+ (1,0) [0|0] "" NEO
|
||||
BO_ 1912 PSCM_778: 8 K43_PSCM
|
||||
|
||||
BO_ 840 EBCMWheelSpdFront: 4 K17_EBCM
|
||||
SG_ FLWheelSpd : 7|16@0+ (0.0311,0) [0|255] "km/h" NEO
|
||||
SG_ FRWheelSpd : 23|16@0+ (0.0311,0) [0|255] "km/h" NEO
|
||||
|
||||
BO_ 842 EBCMWheelSpdRear: 4 K17_EBCM
|
||||
SG_ RLWheelSpd : 7|16@0+ (0.0311,0) [0|255] "km/h" NEO
|
||||
SG_ RRWheelSpd : 23|16@0+ (0.0311,0) [0|255] "km/h" NEO
|
||||
|
||||
BO_ 241 EBCMBrakePedalPosition: 6 K17_EBCM
|
||||
SG_ BrakePedalPosition : 15|8@0+ (1,0) [0|255] "" NEO
|
||||
|
||||
BO_ 711 BECMBatteryVoltageCurrent: 6 K17_EBCM
|
||||
SG_ HVBatteryVoltage : 31|12@0+ (0.125,0) [0|511.875] "V" NEO
|
||||
SG_ HVBatteryCurrent : 12|13@0- (0.15,0) [-614.4|614.25] "A" NEO
|
||||
|
||||
BO_ 417 AcceleratorPedal: 8 XXX
|
||||
SG_ AcceleratorPedal : 55|8@0+ (1,0) [0|0] "" NEO
|
||||
|
||||
BO_ 451 GasAndAcc: 8 XXX
|
||||
SG_ GasPedalAndAcc2 : 55|8@0+ (1,0) [0|0] "" NEO
|
||||
|
||||
BO_ 452 AcceleratorPedal2: 8 XXX
|
||||
SG_ AcceleratorPedal2 : 47|8@0+ (1,0) [0|0] "" NEO
|
||||
BO_ 1930 ASCM_78A: 7 K124_ASCM
|
||||
|
||||
BO_TX_BU_ 384 : K124_ASCM,NEO;
|
||||
BO_TX_BU_ 880 : NEO,K124_ASCM;
|
||||
@@ -218,6 +224,7 @@ BA_ "UseGMParameterIDs" 0;
|
||||
VAL_ 481 DistanceButton 1 "Active" 0 "Inactive" ;
|
||||
VAL_ 481 LKAButton 1 "Active" 0 "Inactive" ;
|
||||
VAL_ 481 ACCButtons 6 "Cancel" 5 "Main" 3 "Set" 2 "Resume" 1 "None" ;
|
||||
VAL_ 452 CruiseState 4 "Standstill" 3 "Faulted" 1 "Active" 0 "Off" ;
|
||||
VAL_ 309 PRNDL 3 "Reverse" 2 "Drive" 1 "Neutral" 0 "Park" ;
|
||||
VAL_ 384 LKASteeringCmdActive 1 "Active" 0 "Inactive" ;
|
||||
VAL_ 880 ACCLeadCar 1 "Present" 0 "Not Present" ;
|
||||
|
||||
@@ -1,6 +1,24 @@
|
||||
CM_ "AUTOGENERATED FILE, DO NOT EDIT"
|
||||
|
||||
|
||||
CM_ "Imported file _comma.dbc starts here"
|
||||
BO_ 512 GAS_COMMAND: 6 EON
|
||||
SG_ GAS_COMMAND : 7|16@0+ (0.253984064,-83.3) [0|1] "" INTERCEPTOR
|
||||
SG_ GAS_COMMAND2 : 23|16@0+ (0.126992032,-83.3) [0|1] "" INTERCEPTOR
|
||||
SG_ ENABLE : 39|1@0+ (1,0) [0|1] "" INTERCEPTOR
|
||||
SG_ COUNTER : 45|2@0+ (1,0) [0|3] "" INTERCEPTOR
|
||||
SG_ CHECKSUM : 43|4@0+ (1,0) [0|3] "" INTERCEPTOR
|
||||
|
||||
BO_ 513 GAS_SENSOR: 6 INTERCEPTOR
|
||||
SG_ INTERCEPTOR_GAS : 7|16@0+ (0.253984064,-83.3) [0|1] "" EON
|
||||
SG_ INTERCEPTOR_GAS2 : 23|16@0+ (0.126992032,-83.3) [0|1] "" EON
|
||||
SG_ STATE : 39|8@0+ (1,0) [0|255] "" EON
|
||||
SG_ COUNTER : 45|2@0+ (1,0) [0|3] "" EON
|
||||
SG_ CHECKSUM : 43|4@0+ (1,0) [0|3] "" EON
|
||||
|
||||
VAL_ 513 STATE 5 "FAULT_TIMEOUT" 4 "FAULT_STARTUP" 3 "FAULT_SCE" 2 "FAULT_SEND" 1 "FAULT_BAD_CHECKSUM" 0 "NO_FAULT" ;
|
||||
|
||||
|
||||
CM_ "Imported file _honda_2017.dbc starts here"
|
||||
VERSION ""
|
||||
|
||||
@@ -211,6 +229,7 @@ VAL_ 829 BEEP 3 "single_beep" 2 "triple_beep" 1 "repeated_beep" 0 "no_beep" ;
|
||||
CM_ "honda_crv_touring_2016_can.dbc starts here"
|
||||
|
||||
|
||||
|
||||
BO_ 342 STEERING_SENSORS: 6 EPS
|
||||
SG_ STEER_ANGLE : 7|16@0- (-0.1,0) [-500|500] "deg" EON
|
||||
SG_ STEER_ANGLE_RATE : 23|16@0- (1,0) [-3000|3000] "deg/s" EON
|
||||
@@ -282,4 +301,4 @@ VAL_ 422 LIGHTS_SETTING 3 "high_beam" 2 "low_beam" 1 "position" 0 "no_lights" ;
|
||||
VAL_ 422 CRUISE_SETTING 3 "distance_adj" 2 "tbd" 1 "lkas_button" 0 "none" ;
|
||||
VAL_ 891 WIPERS 4 "High" 2 "Low" 0 "Off" ;
|
||||
|
||||
CM_ "CHFFR_METRIC 342 STEER_ANGLE STEER_ANGLE 0.36 180; CHFFR_METRIC 380 ENGINE_RPM ENGINE_RPM 1 0; CHFFR_METRIC 804 ENGINE_TEMPERATURE ENGINE_TEMPERATURE 1 0";
|
||||
CM_ "CHFFR_METRIC 342 STEER_ANGLE STEER_ANGLE 0.36 180; CHFFR_METRIC 380 ENGINE_RPM ENGINE_RPM 1 0; CHFFR_METRIC 804 ENGINE_TEMPERATURE ENGINE_TEMPERATURE 1 0";
|
||||
|
||||
@@ -1,6 +1,24 @@
|
||||
CM_ "AUTOGENERATED FILE, DO NOT EDIT"
|
||||
|
||||
|
||||
CM_ "Imported file _comma.dbc starts here"
|
||||
BO_ 512 GAS_COMMAND: 6 EON
|
||||
SG_ GAS_COMMAND : 7|16@0+ (0.253984064,-83.3) [0|1] "" INTERCEPTOR
|
||||
SG_ GAS_COMMAND2 : 23|16@0+ (0.126992032,-83.3) [0|1] "" INTERCEPTOR
|
||||
SG_ ENABLE : 39|1@0+ (1,0) [0|1] "" INTERCEPTOR
|
||||
SG_ COUNTER : 45|2@0+ (1,0) [0|3] "" INTERCEPTOR
|
||||
SG_ CHECKSUM : 43|4@0+ (1,0) [0|3] "" INTERCEPTOR
|
||||
|
||||
BO_ 513 GAS_SENSOR: 6 INTERCEPTOR
|
||||
SG_ INTERCEPTOR_GAS : 7|16@0+ (0.253984064,-83.3) [0|1] "" EON
|
||||
SG_ INTERCEPTOR_GAS2 : 23|16@0+ (0.126992032,-83.3) [0|1] "" EON
|
||||
SG_ STATE : 39|8@0+ (1,0) [0|255] "" EON
|
||||
SG_ COUNTER : 45|2@0+ (1,0) [0|3] "" EON
|
||||
SG_ CHECKSUM : 43|4@0+ (1,0) [0|3] "" EON
|
||||
|
||||
VAL_ 513 STATE 5 "FAULT_TIMEOUT" 4 "FAULT_STARTUP" 3 "FAULT_SCE" 2 "FAULT_SEND" 1 "FAULT_BAD_CHECKSUM" 0 "NO_FAULT" ;
|
||||
|
||||
|
||||
CM_ "Imported file _honda_2017.dbc starts here"
|
||||
VERSION ""
|
||||
|
||||
@@ -211,6 +229,7 @@ VAL_ 829 BEEP 3 "single_beep" 2 "triple_beep" 1 "repeated_beep" 0 "no_beep" ;
|
||||
CM_ "honda_odyssey_exl_2018.dbc starts here"
|
||||
|
||||
|
||||
|
||||
BO_ 228 STEERING_CONTROL: 5 ADAS
|
||||
SG_ STEER_TORQUE : 7|16@0- (1,0) [-3840|3840] "" EPS
|
||||
SG_ STEER_TORQUE_REQUEST : 23|1@0+ (1,0) [0|1] "" EPS
|
||||
|
||||
@@ -1,6 +1,24 @@
|
||||
CM_ "AUTOGENERATED FILE, DO NOT EDIT"
|
||||
|
||||
|
||||
CM_ "Imported file _comma.dbc starts here"
|
||||
BO_ 512 GAS_COMMAND: 6 EON
|
||||
SG_ GAS_COMMAND : 7|16@0+ (0.253984064,-83.3) [0|1] "" INTERCEPTOR
|
||||
SG_ GAS_COMMAND2 : 23|16@0+ (0.126992032,-83.3) [0|1] "" INTERCEPTOR
|
||||
SG_ ENABLE : 39|1@0+ (1,0) [0|1] "" INTERCEPTOR
|
||||
SG_ COUNTER : 45|2@0+ (1,0) [0|3] "" INTERCEPTOR
|
||||
SG_ CHECKSUM : 43|4@0+ (1,0) [0|3] "" INTERCEPTOR
|
||||
|
||||
BO_ 513 GAS_SENSOR: 6 INTERCEPTOR
|
||||
SG_ INTERCEPTOR_GAS : 7|16@0+ (0.253984064,-83.3) [0|1] "" EON
|
||||
SG_ INTERCEPTOR_GAS2 : 23|16@0+ (0.126992032,-83.3) [0|1] "" EON
|
||||
SG_ STATE : 39|8@0+ (1,0) [0|255] "" EON
|
||||
SG_ COUNTER : 45|2@0+ (1,0) [0|3] "" EON
|
||||
SG_ CHECKSUM : 43|4@0+ (1,0) [0|3] "" EON
|
||||
|
||||
VAL_ 513 STATE 5 "FAULT_TIMEOUT" 4 "FAULT_STARTUP" 3 "FAULT_SCE" 2 "FAULT_SEND" 1 "FAULT_BAD_CHECKSUM" 0 "NO_FAULT" ;
|
||||
|
||||
|
||||
CM_ "Imported file _honda_2017.dbc starts here"
|
||||
VERSION ""
|
||||
|
||||
@@ -211,6 +229,7 @@ VAL_ 829 BEEP 3 "single_beep" 2 "triple_beep" 1 "repeated_beep" 0 "no_beep" ;
|
||||
CM_ "honda_pilot_touring_2017_can.dbc starts here"
|
||||
|
||||
|
||||
|
||||
BO_ 145 KINEMATICS: 8 XXX
|
||||
SG_ LAT_ACCEL : 7|10@0+ (0.02,-512) [-20|20] "m/s2" EON
|
||||
|
||||
|
||||
@@ -1,6 +1,24 @@
|
||||
CM_ "AUTOGENERATED FILE, DO NOT EDIT"
|
||||
|
||||
|
||||
CM_ "Imported file _comma.dbc starts here"
|
||||
BO_ 512 GAS_COMMAND: 6 EON
|
||||
SG_ GAS_COMMAND : 7|16@0+ (0.253984064,-83.3) [0|1] "" INTERCEPTOR
|
||||
SG_ GAS_COMMAND2 : 23|16@0+ (0.126992032,-83.3) [0|1] "" INTERCEPTOR
|
||||
SG_ ENABLE : 39|1@0+ (1,0) [0|1] "" INTERCEPTOR
|
||||
SG_ COUNTER : 45|2@0+ (1,0) [0|3] "" INTERCEPTOR
|
||||
SG_ CHECKSUM : 43|4@0+ (1,0) [0|3] "" INTERCEPTOR
|
||||
|
||||
BO_ 513 GAS_SENSOR: 6 INTERCEPTOR
|
||||
SG_ INTERCEPTOR_GAS : 7|16@0+ (0.253984064,-83.3) [0|1] "" EON
|
||||
SG_ INTERCEPTOR_GAS2 : 23|16@0+ (0.126992032,-83.3) [0|1] "" EON
|
||||
SG_ STATE : 39|8@0+ (1,0) [0|255] "" EON
|
||||
SG_ COUNTER : 45|2@0+ (1,0) [0|3] "" EON
|
||||
SG_ CHECKSUM : 43|4@0+ (1,0) [0|3] "" EON
|
||||
|
||||
VAL_ 513 STATE 5 "FAULT_TIMEOUT" 4 "FAULT_STARTUP" 3 "FAULT_SCE" 2 "FAULT_SEND" 1 "FAULT_BAD_CHECKSUM" 0 "NO_FAULT" ;
|
||||
|
||||
|
||||
CM_ "Imported file _honda_2017.dbc starts here"
|
||||
VERSION ""
|
||||
|
||||
@@ -211,6 +229,7 @@ VAL_ 829 BEEP 3 "single_beep" 2 "triple_beep" 1 "repeated_beep" 0 "no_beep" ;
|
||||
CM_ "honda_ridgeline_black_edition_2017_can.dbc starts here"
|
||||
|
||||
|
||||
|
||||
BO_ 145 KINEMATICS: 8 XXX
|
||||
SG_ LAT_ACCEL : 7|10@0+ (0.02,-512) [-20|20] "m/s2" EON
|
||||
|
||||
|
||||
244
opendbc/toyota_avalon_2017_pt_generated.dbc
Normal file
244
opendbc/toyota_avalon_2017_pt_generated.dbc
Normal file
@@ -0,0 +1,244 @@
|
||||
CM_ "AUTOGENERATED FILE, DO NOT EDIT"
|
||||
|
||||
|
||||
CM_ "Imported file _comma.dbc starts here"
|
||||
BO_ 359 STEERING_IPAS_COMMA: 8 IPAS
|
||||
SG_ STATE : 7|4@0+ (1,0) [0|15] "" XXX
|
||||
SG_ ANGLE : 3|12@0- (1.5,0) [-510|510] "deg" XXX
|
||||
SG_ SET_ME_X10 : 23|8@0+ (1,0) [0|255] "" XXX
|
||||
SG_ SET_ME_X00 : 31|8@0+ (1,0) [0|255] "" XXX
|
||||
SG_ DIRECTION_CMD : 38|2@0+ (1,0) [0|3] "" XXX
|
||||
SG_ SET_ME_X40 : 47|8@0+ (1,0) [0|255] "" XXX
|
||||
SG_ SET_ME_X00 : 55|8@0+ (1,0) [0|255] "" XXX
|
||||
SG_ CHECKSUM : 63|8@0+ (1,0) [0|255] "" XXX
|
||||
|
||||
CM BO_ STEERING_IPAS_COMMA "Copy of msg 614 so we can do angle control while the Park Assist ECU is connected (Panda spoofs 614 with 359 on connector J70). Note that addresses 0x266 and 0x167 are checksum-invariant";
|
||||
|
||||
|
||||
CM_ "Imported file _toyota_2017.dbc starts here"
|
||||
VERSION ""
|
||||
|
||||
|
||||
NS_ :
|
||||
NS_DESC_
|
||||
CM_
|
||||
BA_DEF_
|
||||
BA_
|
||||
VAL_
|
||||
CAT_DEF_
|
||||
CAT_
|
||||
FILTER
|
||||
BA_DEF_DEF_
|
||||
EV_DATA_
|
||||
ENVVAR_DATA_
|
||||
SGTYPE_
|
||||
SGTYPE_VAL_
|
||||
BA_DEF_SGTYPE_
|
||||
BA_SGTYPE_
|
||||
SIG_TYPE_REF_
|
||||
VAL_TABLE_
|
||||
SIG_GROUP_
|
||||
SIG_VALTYPE_
|
||||
SIGTYPE_VALTYPE_
|
||||
BO_TX_BU_
|
||||
BA_DEF_REL_
|
||||
BA_REL_
|
||||
BA_DEF_DEF_REL_
|
||||
BU_SG_REL_
|
||||
BU_EV_REL_
|
||||
BU_BO_REL_
|
||||
SG_MUL_VAL_
|
||||
|
||||
BS_:
|
||||
|
||||
BU_: XXX DSU HCU EPS IPAS
|
||||
|
||||
BO_ 36 KINEMATICS: 8 XXX
|
||||
SG_ ACCEL_Y : 33|10@0+ (1,-512) [0|65535] "" XXX
|
||||
SG_ YAW_RATE : 1|10@0+ (1,-512) [0|65535] "" XXX
|
||||
SG_ STEERING_TORQUE : 17|10@0+ (1,-512) [0|65535] "" XXX
|
||||
|
||||
BO_ 166 BRAKE: 8 XXX
|
||||
SG_ BRAKE_AMOUNT : 7|8@0+ (1,0) [0|255] "" XXX
|
||||
SG_ BRAKE_PEDAL : 23|8@0+ (1,0) [0|255] "" XXX
|
||||
|
||||
BO_ 170 WHEEL_SPEEDS: 8 XXX
|
||||
SG_ WHEEL_SPEED_FR : 7|16@0+ (0.01,-67.67) [0|250] "kph" XXX
|
||||
SG_ WHEEL_SPEED_FL : 23|16@0+ (0.01,-67.67) [0|250] "kph" XXX
|
||||
SG_ WHEEL_SPEED_RR : 39|16@0+ (0.01,-67.67) [0|250] "kph" XXX
|
||||
SG_ WHEEL_SPEED_RL : 55|16@0+ (0.01,-67.67) [0|250] "kph" XXX
|
||||
|
||||
BO_ 180 SPEED: 8 XXX
|
||||
SG_ ENCODER : 39|8@0+ (1,0) [0|255] "" XXX
|
||||
SG_ CHECKSUM : 63|8@0+ (1,0) [0|255] "" XXX
|
||||
SG_ SPEED : 47|16@0+ (0.01,0) [0|250] "kph" XXX
|
||||
|
||||
BO_ 466 PCM_CRUISE: 8 XXX
|
||||
SG_ GAS_RELEASED : 4|1@0+ (1,0) [0|1] "" XXX
|
||||
SG_ STANDSTILL_ON : 12|1@0+ (1,0) [0|1] "" XXX
|
||||
SG_ ACCEL_NET : 23|16@0- (0.001,0) [-20|20] "m/s2" XXX
|
||||
SG_ CRUISE_STATE : 55|4@0+ (1,0) [0|15] "" XXX
|
||||
SG_ CHECKSUM : 63|8@0+ (1,0) [0|255] "" XXX
|
||||
|
||||
BO_ 552 ACCELEROMETER: 8 XXX
|
||||
SG_ ACCEL_Z : 22|15@0- (1,0) [0|32767] "" XXX
|
||||
SG_ ACCEL_X : 6|15@0- (0.001,0) [-20|20] "m/s2" XXX
|
||||
|
||||
BO_ 560 BRAKE_MODULE2: 7 XXX
|
||||
SG_ BRAKE_PRESSED : 26|1@0+ (1,0) [0|1] "" XXX
|
||||
|
||||
BO_ 614 STEERING_IPAS: 8 IPAS
|
||||
SG_ STATE : 7|4@0+ (1,0) [0|15] "" XXX
|
||||
SG_ ANGLE : 3|12@0- (1.5,0) [-510|510] "deg" XXX
|
||||
SG_ SET_ME_X10 : 23|8@0+ (1,0) [0|255] "" XXX
|
||||
SG_ SET_ME_X00 : 31|8@0+ (1,0) [0|255] "" XXX
|
||||
SG_ DIRECTION_CMD : 38|2@0+ (1,0) [0|3] "" XXX
|
||||
SG_ SET_ME_X40 : 47|8@0+ (1,0) [0|255] "" XXX
|
||||
SG_ SET_ME_X00 : 55|8@0+ (1,0) [0|255] "" XXX
|
||||
SG_ CHECKSUM : 63|8@0+ (1,0) [0|255] "" XXX
|
||||
|
||||
BO_ 643 PRE_COLLISION: 8 XXX
|
||||
|
||||
BO_ 740 STEERING_LKA: 5 XXX
|
||||
SG_ LKA_STATE : 31|8@0+ (1,0) [0|255] "" XXX
|
||||
SG_ STEER_REQUEST : 0|1@0+ (1,0) [0|1] "" XXX
|
||||
SG_ COUNTER : 6|6@0+ (1,0) [0|63] "" XXX
|
||||
SG_ SET_ME_1 : 7|1@0+ (1,0) [0|1] "" XXX
|
||||
SG_ STEER_TORQUE_CMD : 15|16@0- (1,0) [0|65535] "" XXX
|
||||
SG_ CHECKSUM : 39|8@0+ (1,0) [0|255] "" XXX
|
||||
|
||||
BO_ 742 LEAD_INFO: 8 DSU
|
||||
SG_ CHECKSUM : 63|8@0+ (1,0) [0|255] "" HCU
|
||||
SG_ LEAD_REL_SPEED : 23|12@0- (0.025,0) [-100|100] "m/s" HCU
|
||||
SG_ LEAD_LONG_DIST : 7|13@0+ (0.05,0) [0|300] "m" HCU
|
||||
|
||||
BO_ 835 ACC_CONTROL: 8 DSU
|
||||
SG_ ACCEL_CMD : 7|16@0- (0.001,0) [-20|20] "m/s2" HCU
|
||||
SG_ SET_ME_X63 : 23|8@0+ (1,0) [0|255] "" HCU
|
||||
SG_ SET_ME_1 : 30|1@0+ (1,0) [0|1] "" HCU
|
||||
SG_ RELEASE_STANDSTILL : 31|1@0+ (1,0) [0|1] "" HCU
|
||||
SG_ CANCEL_REQ : 24|1@0+ (1,0) [0|1] "" HCU
|
||||
SG_ CHECKSUM : 63|8@0+ (1,0) [0|255] "" XXX
|
||||
|
||||
BO_ 1556 STEERING_LEVERS: 8 XXX
|
||||
SG_ TURN_SIGNALS : 29|2@0+ (1,0) [0|3] "" XXX
|
||||
|
||||
BO_ 37 STEER_ANGLE_SENSOR: 8 XXX
|
||||
SG_ STEER_ANGLE : 3|12@0- (1.5,0) [-500|500] "deg" XXX
|
||||
SG_ STEER_FRACTION : 39|4@0- (0.1,0) [-0.7|0.7] "deg" XXX
|
||||
SG_ STEER_RATE : 35|12@0- (1,0) [-2000|2000] "deg/s" XXX
|
||||
|
||||
BO_ 467 PCM_CRUISE_2: 8 XXX
|
||||
SG_ MAIN_ON : 15|1@0+ (1,0) [0|1] "" XXX
|
||||
SG_ LOW_SPEED_LOCKOUT : 14|2@0+ (1,0) [0|3] "kph" XXX
|
||||
SG_ SET_SPEED : 23|8@0+ (1,0) [0|255] "kph" XXX
|
||||
SG_ CHECKSUM : 63|8@0+ (1,0) [0|255] "" XXX
|
||||
|
||||
BO_ 921 PCM_CRUISE_SM: 8 XXX
|
||||
SG_ MAIN_ON : 4|1@0+ (1,0) [0|1] "" XXX
|
||||
SG_ CRUISE_CONTROL_STATE : 11|4@0+ (1,0) [0|15] "" XXX
|
||||
SG_ UI_SET_SPEED : 31|8@0+ (1,0) [0|255] "" XXX
|
||||
|
||||
BO_ 951 ESP_CONTROL: 8 ESP
|
||||
SG_ TC_DISABLED : 13|1@0+ (1,0) [0|1] "" XXX
|
||||
SG_ BRAKE_LIGHTS_ACC : 18|1@0+ (1,0) [0|1] "" XXX
|
||||
|
||||
BO_ 1041 ACC_HUD: 8 DSU
|
||||
SG_ FCW : 4|1@0+ (1,0) [0|1] "" XXX
|
||||
SG_ SET_ME_X20 : 15|8@0+ (1,0) [0|1] "" XXX
|
||||
SG_ SET_ME_X10 : 39|8@0+ (1,0) [0|1] "" XXX
|
||||
SG_ SET_ME_X80 : 55|8@0+ (1,0) [0|1] "" XXX
|
||||
|
||||
BO_ 1042 LKAS_HUD: 8 XXX
|
||||
SG_ BARRIERS : 1|2@0+ (1,0) [0|3] "" XXX
|
||||
SG_ RIGHT_LINE : 3|2@0+ (1,0) [0|3] "" XXX
|
||||
SG_ LEFT_LINE : 5|2@0+ (1,0) [0|3] "" XXX
|
||||
SG_ SET_ME_X01 : 7|2@0+ (1,0) [0|3] "" XXX
|
||||
SG_ SET_ME_X01_2 : 11|2@0+ (1,0) [0|3] "" XXX
|
||||
SG_ LDA_ALERT : 9|2@0+ (1,0) [0|3] "" XXX
|
||||
SG_ TWO_BEEPS : 12|1@0+ (1,0) [0|1] "" XXX
|
||||
SG_ ADJUSTING_CAMERA : 13|1@0+ (1,0) [0|1] "" XXX
|
||||
SG_ LDA_MALFUNCTION : 15|1@0+ (1,0) [0|1] "" XXX
|
||||
SG_ REPEATED_BEEPS : 32|1@0+ (1,0) [0|1] "" XXX
|
||||
SG_ SET_ME_X0C : 23|8@0+ (1,0) [0|1] "" XXX
|
||||
SG_ SET_ME_X2C : 47|8@0+ (1,0) [0|1] "" XXX
|
||||
SG_ SET_ME_X38 : 55|8@0+ (1,0) [0|1] "" XXX
|
||||
SG_ SET_ME_X02 : 63|8@0+ (1,0) [0|1] "" XXX
|
||||
|
||||
BO_ 1553 UI_SEETING: 8 XXX
|
||||
SG_ UNITS : 26|2@0+ (1,0) [0|3] "" XXX
|
||||
|
||||
BO_ 1568 SEATS_DOORS: 8 XXX
|
||||
SG_ SEATBELT_DRIVER_UNLATCHED : 62|1@0+ (1,0) [0|1] "" XXX
|
||||
SG_ DOOR_OPEN_FL : 45|1@0+ (1,0) [0|1] "" XXX
|
||||
SG_ DOOR_OPEN_RL : 42|1@0+ (1,0) [0|1] "" XXX
|
||||
SG_ DOOR_OPEN_RR : 43|1@0+ (1,0) [0|1] "" XXX
|
||||
SG_ DOOR_OPEN_FR : 44|1@0+ (1,0) [0|1] "" XXX
|
||||
|
||||
BO_ 1570 LIGHT_STALK: 8 SCM
|
||||
SG_ AUTO_HIGH_BEAM : 37|1@0+ (1,0) [0|1] "" XXX
|
||||
|
||||
CM_ SG_ 36 ACCEL_Y "unit is tbd";
|
||||
CM_ SG_ 36 YAW_RATE "verify";
|
||||
CM_ SG_ 36 STEERING_TORQUE "does not seem the steer torque, tbd";
|
||||
CM_ SG_ 466 ACCEL_NET "net acceleration produced by the system, given ACCEL_CMD, road grade and other factors";
|
||||
CM_ SG_ 560 BRAKE_PRESSED "another brake pressed?";
|
||||
CM_ SG_ 951 BRAKE_LIGHTS_ACC "brake lights when ACC commands decel";
|
||||
CM_ SG_ 608 STEER_TORQUE_DRIVER "driver torque";
|
||||
CM_ SG_ 608 STEER_OVERRIDE "set when driver torque exceeds a certain value";
|
||||
CM_ SG_ 614 ANGLE "set to measured angle when ipas control isn't active";
|
||||
CM_ SG_ 37 STEER_FRACTION "1/15th of the signal STEER_ANGLE, which is 1.5 deg; note that 0x8 is never set";
|
||||
CM_ SG_ 37 STEER_RATE "factor is tbd";
|
||||
CM_ SG_ 467 SET_SPEED "43 kph are shown as 28mph, so conversion isnt perfect";
|
||||
CM_ SG_ 467 LOW_SPEED_LOCKOUT "in low speed lockout, system would always disengage below 28mph";
|
||||
CM_ SG_ 921 UI_SET_SPEED "set speed shown in UI with user set unit";
|
||||
CM_ SG_ 1042 SET_ME_1 "unclear what this is, but it's always 1 in drive traces";
|
||||
CM_ SG_ 1042 REPEATED_BEEPS "recommended for fcw and other important alerts";
|
||||
VAL_ 466 CRUISE_STATE 8 "active" 7 "standstill" 1 "off" ;
|
||||
VAL_ 467 LOW_SPEED_LOCKOUT 2 "low speed locked" 1 "ok" ;
|
||||
VAL_ 614 STATE 3 "enabled" 1 "disabled";
|
||||
VAL_ 614 DIRECTION_CMD 3 "right" 2 "center" 1 "left";
|
||||
VAL_ 1553 UNITS 1 "km" 2 "miles";
|
||||
VAL_ 1556 TURN_SIGNALS 3 "none" 2 "right" 1 "left" ;
|
||||
VAL_ 1042 LDA_ALERT 3 "hold with continuous beep" 2 "LDA unavailable" 1 "hold" 0 "none";
|
||||
VAL_ 1042 BARRIERS 3 "both" 2 "right" 1 "left" 0 "none";
|
||||
VAL_ 1042 RIGHT_LINE 3 "orange" 2 "double" 1 "solid" 0 "none";
|
||||
VAL_ 1042 LEFT_LINE 3 "orange" 2 "double" 1 "solid" 0 "none";
|
||||
VAL_ 921 CRUISE_CONTROL_STATE 2 "disabled" 11 "hold" 10 "hold_waiting_user_cmd" 6 "enabled" 5 "faulted";
|
||||
|
||||
CM_ "CHFFR_METRIC 37 STEER_ANGLE STEER_ANGLE 0.36 180";
|
||||
|
||||
CM_ "toyota_avalon_2017_pt.dbc starts here"
|
||||
|
||||
|
||||
|
||||
BO_ 550 BRAKE_MODULE: 8 XXX
|
||||
SG_ BRAKE_PRESSURE : 0|9@0+ (1,0) [0|255] "" XXX
|
||||
SG_ BRAKE_POSITION : 16|9@0+ (1,0) [0|65535] "" XXX
|
||||
SG_ BRAKE_PRESSED : 37|1@0+ (1,0) [0|3] "" XXX
|
||||
|
||||
BO_ 705 GAS_PEDAL: 8 XXX
|
||||
SG_ GAS_RELEASED : 3|1@0+ (1,0) [0|1] "" XXX
|
||||
SG_ GAS_PEDAL : 55|8@0+ (0.005,0) [0|1] "" XXX
|
||||
|
||||
BO_ 608 STEER_TORQUE_SENSOR: 8 XXX
|
||||
SG_ STEER_TORQUE_EPS : 47|16@0- (0.73,0) [-20000|20000] "" XXX
|
||||
SG_ STEER_TORQUE_DRIVER : 15|16@0- (1,0) [-32768|32767] "" XXX
|
||||
SG_ STEER_OVERRIDE : 0|1@0+ (1,0) [0|1] "" XXX
|
||||
SG_ CHECKSUM : 63|8@0+ (1,0) [0|255] "" XXX
|
||||
|
||||
BO_ 610 EPS_STATUS: 5 EPS
|
||||
SG_ IPAS_STATE : 3|4@0+ (1,0) [0|15] "" XXX
|
||||
SG_ LKA_STATE : 31|7@0+ (1,0) [0|127] "" XXX
|
||||
SG_ TYPE : 24|1@0+ (1,0) [0|1] "" XXX
|
||||
SG_ CHECKSUM : 39|8@0+ (1,0) [0|255] "" XXX
|
||||
|
||||
BO_ 956 GEAR_PACKET: 8 XXX
|
||||
SG_ GEAR : 13|6@0+ (1,0) [0|63] "" XXX
|
||||
|
||||
CM_ SG_ 548 BRAKE_PRESSURE "seems prop to pedal force";
|
||||
CM_ SG_ 548 BRAKE_POSITION "seems proportional to pedal displacement, unclear the max value of 0x1c8";
|
||||
CM_ SG_ 610 TYPE "seems 1 on Corolla, 0 on all others";
|
||||
VAL_ 956 GEAR 0 "D" 1 "S" 8 "N" 16 "R" 32 "P";
|
||||
VAL_ 610 IPAS_STATE 5 "override" 3 "enabled" 1 "disabled";
|
||||
VAL_ 610 LKA_STATE 25 "temporary_fault" 9 "temporary_fault2" 5 "active" 1 "standby";
|
||||
244
opendbc/toyota_highlander_2017_pt_generated.dbc
Normal file
244
opendbc/toyota_highlander_2017_pt_generated.dbc
Normal file
@@ -0,0 +1,244 @@
|
||||
CM_ "AUTOGENERATED FILE, DO NOT EDIT"
|
||||
|
||||
|
||||
CM_ "Imported file _comma.dbc starts here"
|
||||
BO_ 359 STEERING_IPAS_COMMA: 8 IPAS
|
||||
SG_ STATE : 7|4@0+ (1,0) [0|15] "" XXX
|
||||
SG_ ANGLE : 3|12@0- (1.5,0) [-510|510] "deg" XXX
|
||||
SG_ SET_ME_X10 : 23|8@0+ (1,0) [0|255] "" XXX
|
||||
SG_ SET_ME_X00 : 31|8@0+ (1,0) [0|255] "" XXX
|
||||
SG_ DIRECTION_CMD : 38|2@0+ (1,0) [0|3] "" XXX
|
||||
SG_ SET_ME_X40 : 47|8@0+ (1,0) [0|255] "" XXX
|
||||
SG_ SET_ME_X00 : 55|8@0+ (1,0) [0|255] "" XXX
|
||||
SG_ CHECKSUM : 63|8@0+ (1,0) [0|255] "" XXX
|
||||
|
||||
CM BO_ STEERING_IPAS_COMMA "Copy of msg 614 so we can do angle control while the Park Assist ECU is connected (Panda spoofs 614 with 359 on connector J70). Note that addresses 0x266 and 0x167 are checksum-invariant";
|
||||
|
||||
|
||||
CM_ "Imported file _toyota_2017.dbc starts here"
|
||||
VERSION ""
|
||||
|
||||
|
||||
NS_ :
|
||||
NS_DESC_
|
||||
CM_
|
||||
BA_DEF_
|
||||
BA_
|
||||
VAL_
|
||||
CAT_DEF_
|
||||
CAT_
|
||||
FILTER
|
||||
BA_DEF_DEF_
|
||||
EV_DATA_
|
||||
ENVVAR_DATA_
|
||||
SGTYPE_
|
||||
SGTYPE_VAL_
|
||||
BA_DEF_SGTYPE_
|
||||
BA_SGTYPE_
|
||||
SIG_TYPE_REF_
|
||||
VAL_TABLE_
|
||||
SIG_GROUP_
|
||||
SIG_VALTYPE_
|
||||
SIGTYPE_VALTYPE_
|
||||
BO_TX_BU_
|
||||
BA_DEF_REL_
|
||||
BA_REL_
|
||||
BA_DEF_DEF_REL_
|
||||
BU_SG_REL_
|
||||
BU_EV_REL_
|
||||
BU_BO_REL_
|
||||
SG_MUL_VAL_
|
||||
|
||||
BS_:
|
||||
|
||||
BU_: XXX DSU HCU EPS IPAS
|
||||
|
||||
BO_ 36 KINEMATICS: 8 XXX
|
||||
SG_ ACCEL_Y : 33|10@0+ (1,-512) [0|65535] "" XXX
|
||||
SG_ YAW_RATE : 1|10@0+ (1,-512) [0|65535] "" XXX
|
||||
SG_ STEERING_TORQUE : 17|10@0+ (1,-512) [0|65535] "" XXX
|
||||
|
||||
BO_ 166 BRAKE: 8 XXX
|
||||
SG_ BRAKE_AMOUNT : 7|8@0+ (1,0) [0|255] "" XXX
|
||||
SG_ BRAKE_PEDAL : 23|8@0+ (1,0) [0|255] "" XXX
|
||||
|
||||
BO_ 170 WHEEL_SPEEDS: 8 XXX
|
||||
SG_ WHEEL_SPEED_FR : 7|16@0+ (0.01,-67.67) [0|250] "kph" XXX
|
||||
SG_ WHEEL_SPEED_FL : 23|16@0+ (0.01,-67.67) [0|250] "kph" XXX
|
||||
SG_ WHEEL_SPEED_RR : 39|16@0+ (0.01,-67.67) [0|250] "kph" XXX
|
||||
SG_ WHEEL_SPEED_RL : 55|16@0+ (0.01,-67.67) [0|250] "kph" XXX
|
||||
|
||||
BO_ 180 SPEED: 8 XXX
|
||||
SG_ ENCODER : 39|8@0+ (1,0) [0|255] "" XXX
|
||||
SG_ CHECKSUM : 63|8@0+ (1,0) [0|255] "" XXX
|
||||
SG_ SPEED : 47|16@0+ (0.01,0) [0|250] "kph" XXX
|
||||
|
||||
BO_ 466 PCM_CRUISE: 8 XXX
|
||||
SG_ GAS_RELEASED : 4|1@0+ (1,0) [0|1] "" XXX
|
||||
SG_ STANDSTILL_ON : 12|1@0+ (1,0) [0|1] "" XXX
|
||||
SG_ ACCEL_NET : 23|16@0- (0.001,0) [-20|20] "m/s2" XXX
|
||||
SG_ CRUISE_STATE : 55|4@0+ (1,0) [0|15] "" XXX
|
||||
SG_ CHECKSUM : 63|8@0+ (1,0) [0|255] "" XXX
|
||||
|
||||
BO_ 552 ACCELEROMETER: 8 XXX
|
||||
SG_ ACCEL_Z : 22|15@0- (1,0) [0|32767] "" XXX
|
||||
SG_ ACCEL_X : 6|15@0- (0.001,0) [-20|20] "m/s2" XXX
|
||||
|
||||
BO_ 560 BRAKE_MODULE2: 7 XXX
|
||||
SG_ BRAKE_PRESSED : 26|1@0+ (1,0) [0|1] "" XXX
|
||||
|
||||
BO_ 614 STEERING_IPAS: 8 IPAS
|
||||
SG_ STATE : 7|4@0+ (1,0) [0|15] "" XXX
|
||||
SG_ ANGLE : 3|12@0- (1.5,0) [-510|510] "deg" XXX
|
||||
SG_ SET_ME_X10 : 23|8@0+ (1,0) [0|255] "" XXX
|
||||
SG_ SET_ME_X00 : 31|8@0+ (1,0) [0|255] "" XXX
|
||||
SG_ DIRECTION_CMD : 38|2@0+ (1,0) [0|3] "" XXX
|
||||
SG_ SET_ME_X40 : 47|8@0+ (1,0) [0|255] "" XXX
|
||||
SG_ SET_ME_X00 : 55|8@0+ (1,0) [0|255] "" XXX
|
||||
SG_ CHECKSUM : 63|8@0+ (1,0) [0|255] "" XXX
|
||||
|
||||
BO_ 643 PRE_COLLISION: 8 XXX
|
||||
|
||||
BO_ 740 STEERING_LKA: 5 XXX
|
||||
SG_ LKA_STATE : 31|8@0+ (1,0) [0|255] "" XXX
|
||||
SG_ STEER_REQUEST : 0|1@0+ (1,0) [0|1] "" XXX
|
||||
SG_ COUNTER : 6|6@0+ (1,0) [0|63] "" XXX
|
||||
SG_ SET_ME_1 : 7|1@0+ (1,0) [0|1] "" XXX
|
||||
SG_ STEER_TORQUE_CMD : 15|16@0- (1,0) [0|65535] "" XXX
|
||||
SG_ CHECKSUM : 39|8@0+ (1,0) [0|255] "" XXX
|
||||
|
||||
BO_ 742 LEAD_INFO: 8 DSU
|
||||
SG_ CHECKSUM : 63|8@0+ (1,0) [0|255] "" HCU
|
||||
SG_ LEAD_REL_SPEED : 23|12@0- (0.025,0) [-100|100] "m/s" HCU
|
||||
SG_ LEAD_LONG_DIST : 7|13@0+ (0.05,0) [0|300] "m" HCU
|
||||
|
||||
BO_ 835 ACC_CONTROL: 8 DSU
|
||||
SG_ ACCEL_CMD : 7|16@0- (0.001,0) [-20|20] "m/s2" HCU
|
||||
SG_ SET_ME_X63 : 23|8@0+ (1,0) [0|255] "" HCU
|
||||
SG_ SET_ME_1 : 30|1@0+ (1,0) [0|1] "" HCU
|
||||
SG_ RELEASE_STANDSTILL : 31|1@0+ (1,0) [0|1] "" HCU
|
||||
SG_ CANCEL_REQ : 24|1@0+ (1,0) [0|1] "" HCU
|
||||
SG_ CHECKSUM : 63|8@0+ (1,0) [0|255] "" XXX
|
||||
|
||||
BO_ 1556 STEERING_LEVERS: 8 XXX
|
||||
SG_ TURN_SIGNALS : 29|2@0+ (1,0) [0|3] "" XXX
|
||||
|
||||
BO_ 37 STEER_ANGLE_SENSOR: 8 XXX
|
||||
SG_ STEER_ANGLE : 3|12@0- (1.5,0) [-500|500] "deg" XXX
|
||||
SG_ STEER_FRACTION : 39|4@0- (0.1,0) [-0.7|0.7] "deg" XXX
|
||||
SG_ STEER_RATE : 35|12@0- (1,0) [-2000|2000] "deg/s" XXX
|
||||
|
||||
BO_ 467 PCM_CRUISE_2: 8 XXX
|
||||
SG_ MAIN_ON : 15|1@0+ (1,0) [0|1] "" XXX
|
||||
SG_ LOW_SPEED_LOCKOUT : 14|2@0+ (1,0) [0|3] "kph" XXX
|
||||
SG_ SET_SPEED : 23|8@0+ (1,0) [0|255] "kph" XXX
|
||||
SG_ CHECKSUM : 63|8@0+ (1,0) [0|255] "" XXX
|
||||
|
||||
BO_ 921 PCM_CRUISE_SM: 8 XXX
|
||||
SG_ MAIN_ON : 4|1@0+ (1,0) [0|1] "" XXX
|
||||
SG_ CRUISE_CONTROL_STATE : 11|4@0+ (1,0) [0|15] "" XXX
|
||||
SG_ UI_SET_SPEED : 31|8@0+ (1,0) [0|255] "" XXX
|
||||
|
||||
BO_ 951 ESP_CONTROL: 8 ESP
|
||||
SG_ TC_DISABLED : 13|1@0+ (1,0) [0|1] "" XXX
|
||||
SG_ BRAKE_LIGHTS_ACC : 18|1@0+ (1,0) [0|1] "" XXX
|
||||
|
||||
BO_ 1041 ACC_HUD: 8 DSU
|
||||
SG_ FCW : 4|1@0+ (1,0) [0|1] "" XXX
|
||||
SG_ SET_ME_X20 : 15|8@0+ (1,0) [0|1] "" XXX
|
||||
SG_ SET_ME_X10 : 39|8@0+ (1,0) [0|1] "" XXX
|
||||
SG_ SET_ME_X80 : 55|8@0+ (1,0) [0|1] "" XXX
|
||||
|
||||
BO_ 1042 LKAS_HUD: 8 XXX
|
||||
SG_ BARRIERS : 1|2@0+ (1,0) [0|3] "" XXX
|
||||
SG_ RIGHT_LINE : 3|2@0+ (1,0) [0|3] "" XXX
|
||||
SG_ LEFT_LINE : 5|2@0+ (1,0) [0|3] "" XXX
|
||||
SG_ SET_ME_X01 : 7|2@0+ (1,0) [0|3] "" XXX
|
||||
SG_ SET_ME_X01_2 : 11|2@0+ (1,0) [0|3] "" XXX
|
||||
SG_ LDA_ALERT : 9|2@0+ (1,0) [0|3] "" XXX
|
||||
SG_ TWO_BEEPS : 12|1@0+ (1,0) [0|1] "" XXX
|
||||
SG_ ADJUSTING_CAMERA : 13|1@0+ (1,0) [0|1] "" XXX
|
||||
SG_ LDA_MALFUNCTION : 15|1@0+ (1,0) [0|1] "" XXX
|
||||
SG_ REPEATED_BEEPS : 32|1@0+ (1,0) [0|1] "" XXX
|
||||
SG_ SET_ME_X0C : 23|8@0+ (1,0) [0|1] "" XXX
|
||||
SG_ SET_ME_X2C : 47|8@0+ (1,0) [0|1] "" XXX
|
||||
SG_ SET_ME_X38 : 55|8@0+ (1,0) [0|1] "" XXX
|
||||
SG_ SET_ME_X02 : 63|8@0+ (1,0) [0|1] "" XXX
|
||||
|
||||
BO_ 1553 UI_SEETING: 8 XXX
|
||||
SG_ UNITS : 26|2@0+ (1,0) [0|3] "" XXX
|
||||
|
||||
BO_ 1568 SEATS_DOORS: 8 XXX
|
||||
SG_ SEATBELT_DRIVER_UNLATCHED : 62|1@0+ (1,0) [0|1] "" XXX
|
||||
SG_ DOOR_OPEN_FL : 45|1@0+ (1,0) [0|1] "" XXX
|
||||
SG_ DOOR_OPEN_RL : 42|1@0+ (1,0) [0|1] "" XXX
|
||||
SG_ DOOR_OPEN_RR : 43|1@0+ (1,0) [0|1] "" XXX
|
||||
SG_ DOOR_OPEN_FR : 44|1@0+ (1,0) [0|1] "" XXX
|
||||
|
||||
BO_ 1570 LIGHT_STALK: 8 SCM
|
||||
SG_ AUTO_HIGH_BEAM : 37|1@0+ (1,0) [0|1] "" XXX
|
||||
|
||||
CM_ SG_ 36 ACCEL_Y "unit is tbd";
|
||||
CM_ SG_ 36 YAW_RATE "verify";
|
||||
CM_ SG_ 36 STEERING_TORQUE "does not seem the steer torque, tbd";
|
||||
CM_ SG_ 466 ACCEL_NET "net acceleration produced by the system, given ACCEL_CMD, road grade and other factors";
|
||||
CM_ SG_ 560 BRAKE_PRESSED "another brake pressed?";
|
||||
CM_ SG_ 951 BRAKE_LIGHTS_ACC "brake lights when ACC commands decel";
|
||||
CM_ SG_ 608 STEER_TORQUE_DRIVER "driver torque";
|
||||
CM_ SG_ 608 STEER_OVERRIDE "set when driver torque exceeds a certain value";
|
||||
CM_ SG_ 614 ANGLE "set to measured angle when ipas control isn't active";
|
||||
CM_ SG_ 37 STEER_FRACTION "1/15th of the signal STEER_ANGLE, which is 1.5 deg; note that 0x8 is never set";
|
||||
CM_ SG_ 37 STEER_RATE "factor is tbd";
|
||||
CM_ SG_ 467 SET_SPEED "43 kph are shown as 28mph, so conversion isnt perfect";
|
||||
CM_ SG_ 467 LOW_SPEED_LOCKOUT "in low speed lockout, system would always disengage below 28mph";
|
||||
CM_ SG_ 921 UI_SET_SPEED "set speed shown in UI with user set unit";
|
||||
CM_ SG_ 1042 SET_ME_1 "unclear what this is, but it's always 1 in drive traces";
|
||||
CM_ SG_ 1042 REPEATED_BEEPS "recommended for fcw and other important alerts";
|
||||
VAL_ 466 CRUISE_STATE 8 "active" 7 "standstill" 1 "off" ;
|
||||
VAL_ 467 LOW_SPEED_LOCKOUT 2 "low speed locked" 1 "ok" ;
|
||||
VAL_ 614 STATE 3 "enabled" 1 "disabled";
|
||||
VAL_ 614 DIRECTION_CMD 3 "right" 2 "center" 1 "left";
|
||||
VAL_ 1553 UNITS 1 "km" 2 "miles";
|
||||
VAL_ 1556 TURN_SIGNALS 3 "none" 2 "right" 1 "left" ;
|
||||
VAL_ 1042 LDA_ALERT 3 "hold with continuous beep" 2 "LDA unavailable" 1 "hold" 0 "none";
|
||||
VAL_ 1042 BARRIERS 3 "both" 2 "right" 1 "left" 0 "none";
|
||||
VAL_ 1042 RIGHT_LINE 3 "orange" 2 "double" 1 "solid" 0 "none";
|
||||
VAL_ 1042 LEFT_LINE 3 "orange" 2 "double" 1 "solid" 0 "none";
|
||||
VAL_ 921 CRUISE_CONTROL_STATE 2 "disabled" 11 "hold" 10 "hold_waiting_user_cmd" 6 "enabled" 5 "faulted";
|
||||
|
||||
CM_ "CHFFR_METRIC 37 STEER_ANGLE STEER_ANGLE 0.36 180";
|
||||
|
||||
CM_ "toyota_highlander_2017_pt.dbc starts here"
|
||||
|
||||
|
||||
|
||||
BO_ 550 BRAKE_MODULE: 8 XXX
|
||||
SG_ BRAKE_PRESSURE : 0|9@0+ (1,0) [0|255] "" XXX
|
||||
SG_ BRAKE_POSITION : 16|9@0+ (1,0) [0|65535] "" XXX
|
||||
SG_ BRAKE_PRESSED : 37|1@0+ (1,0) [0|3] "" XXX
|
||||
|
||||
BO_ 705 GAS_PEDAL: 8 XXX
|
||||
SG_ GAS_RELEASED : 3|1@0+ (1,0) [0|1] "" XXX
|
||||
SG_ GAS_PEDAL : 55|8@0+ (0.005,0) [0|1] "" XXX
|
||||
|
||||
BO_ 608 STEER_TORQUE_SENSOR: 8 XXX
|
||||
SG_ STEER_TORQUE_EPS : 47|16@0- (0.73,0) [-20000|20000] "" XXX
|
||||
SG_ STEER_TORQUE_DRIVER : 15|16@0- (1,0) [-32768|32767] "" XXX
|
||||
SG_ STEER_OVERRIDE : 0|1@0+ (1,0) [0|1] "" XXX
|
||||
SG_ CHECKSUM : 63|8@0+ (1,0) [0|255] "" XXX
|
||||
|
||||
BO_ 610 EPS_STATUS: 5 EPS
|
||||
SG_ IPAS_STATE : 3|4@0+ (1,0) [0|15] "" XXX
|
||||
SG_ LKA_STATE : 31|7@0+ (1,0) [0|127] "" XXX
|
||||
SG_ TYPE : 24|1@0+ (1,0) [0|1] "" XXX
|
||||
SG_ CHECKSUM : 39|8@0+ (1,0) [0|255] "" XXX
|
||||
|
||||
BO_ 956 GEAR_PACKET: 8 XXX
|
||||
SG_ GEAR : 13|6@0+ (1,0) [0|63] "" XXX
|
||||
|
||||
CM_ SG_ 548 BRAKE_PRESSURE "seems prop to pedal force";
|
||||
CM_ SG_ 548 BRAKE_POSITION "seems proportional to pedal displacement, unclear the max value of 0x1c8";
|
||||
CM_ SG_ 610 TYPE "seems 1 on Corolla, 0 on all others";
|
||||
VAL_ 956 GEAR 0 "D" 1 "S" 8 "N" 16 "R" 32 "P";
|
||||
VAL_ 610 IPAS_STATE 5 "override" 3 "enabled" 1 "disabled";
|
||||
VAL_ 610 LKA_STATE 25 "temporary_fault" 9 "temporary_fault2" 5 "active" 1 "standby";
|
||||
@@ -15,7 +15,7 @@ It is 2nd gen hardware, reusing code and parts from the [NEO](https://github.com
|
||||
|
||||
[](https://circleci.com/gh/commaai/panda)
|
||||
|
||||
Usage
|
||||
Usage (Python)
|
||||
------
|
||||
|
||||
To install the library:
|
||||
@@ -37,6 +37,12 @@ And to send one on bus 0:
|
||||
```
|
||||
Find user made scripts on the [wiki](https://community.comma.ai/wiki/index.php/Panda_scripts)
|
||||
|
||||
Usage (JavaScript)
|
||||
-------
|
||||
|
||||
See [PandaJS](https://github.com/commaai/pandajs)
|
||||
|
||||
|
||||
Software interface support
|
||||
------
|
||||
|
||||
|
||||
@@ -1 +1 @@
|
||||
v1.1.1
|
||||
v1.1.2
|
||||
@@ -415,6 +415,9 @@ void can_rx(uint8_t can_number) {
|
||||
to_push.RDLR = CAN->sFIFOMailBox[0].RDLR;
|
||||
to_push.RDHR = CAN->sFIFOMailBox[0].RDHR;
|
||||
|
||||
// modify RDTR for our API
|
||||
to_push.RDTR = (to_push.RDTR & 0xFFFF000F) | (bus_number << 4);
|
||||
|
||||
// forwarding (panda only)
|
||||
#ifdef PANDA
|
||||
int bus_fwd_num = can_forwarding[bus_number] != -1 ? can_forwarding[bus_number] : safety_fwd_hook(bus_number, &to_push);
|
||||
@@ -428,8 +431,6 @@ void can_rx(uint8_t can_number) {
|
||||
}
|
||||
#endif
|
||||
|
||||
// modify RDTR for our API
|
||||
to_push.RDTR = (to_push.RDTR & 0xFFFF000F) | (bus_number << 4);
|
||||
safety_rx_hook(&to_push);
|
||||
|
||||
#ifdef PANDA
|
||||
@@ -460,14 +461,21 @@ void CAN3_SCE_IRQHandler() { can_sce(CAN3); }
|
||||
|
||||
#endif
|
||||
|
||||
#include "canbitbang.h"
|
||||
|
||||
void can_send(CAN_FIFOMailBox_TypeDef *to_push, uint8_t bus_number) {
|
||||
if (safety_tx_hook(to_push) && !can_autobaud_enabled[bus_number]) {
|
||||
if (bus_number < BUS_MAX) {
|
||||
// add CAN packet to send queue
|
||||
// bus number isn't passed through
|
||||
to_push->RDTR &= 0xF;
|
||||
can_push(can_queues[bus_number], to_push);
|
||||
process_can(CAN_NUM_FROM_BUS_NUM(bus_number));
|
||||
if (bus_number == 3 && can_num_lookup[3] == 0xFF) {
|
||||
// TODO: why uint8 bro? only int8?
|
||||
bitbang_gmlan(to_push);
|
||||
} else {
|
||||
can_push(can_queues[bus_number], to_push);
|
||||
process_can(CAN_NUM_FROM_BUS_NUM(bus_number));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
203
panda/board/drivers/canbitbang.h
Normal file
203
panda/board/drivers/canbitbang.h
Normal file
@@ -0,0 +1,203 @@
|
||||
#define MAX_BITS_CAN_PACKET (200)
|
||||
|
||||
// returns out_len
|
||||
int do_bitstuff(char *out, char *in, int in_len) {
|
||||
int last_bit = -1;
|
||||
int bit_cnt = 0;
|
||||
int j = 0;
|
||||
for (int i = 0; i < in_len; i++) {
|
||||
char bit = in[i];
|
||||
out[j++] = bit;
|
||||
|
||||
// do the stuffing
|
||||
if (bit == last_bit) {
|
||||
bit_cnt++;
|
||||
if (bit_cnt == 5) {
|
||||
// 5 in a row the same, do stuff
|
||||
last_bit = !bit;
|
||||
out[j++] = last_bit;
|
||||
bit_cnt = 1;
|
||||
}
|
||||
} else {
|
||||
// this is a new bit
|
||||
last_bit = bit;
|
||||
bit_cnt = 1;
|
||||
}
|
||||
}
|
||||
return j;
|
||||
}
|
||||
|
||||
int append_crc(char *in, int in_len) {
|
||||
int crc = 0;
|
||||
for (int i = 0; i < in_len; i++) {
|
||||
crc <<= 1;
|
||||
if (in[i] ^ ((crc>>15)&1)) {
|
||||
crc = crc ^ 0x4599;
|
||||
}
|
||||
crc &= 0x7fff;
|
||||
}
|
||||
for (int i = 14; i >= 0; i--) {
|
||||
in[in_len++] = (crc>>i)&1;
|
||||
}
|
||||
return in_len;
|
||||
}
|
||||
|
||||
int append_bits(char *in, int in_len, char *app, int app_len) {
|
||||
for (int i = 0; i < app_len; i++) {
|
||||
in[in_len++] = app[i];
|
||||
}
|
||||
return in_len;
|
||||
}
|
||||
|
||||
int append_int(char *in, int in_len, int val, int val_len) {
|
||||
for (int i = val_len-1; i >= 0; i--) {
|
||||
in[in_len++] = (val&(1<<i)) != 0;
|
||||
}
|
||||
return in_len;
|
||||
}
|
||||
|
||||
int get_bit_message(char *out, CAN_FIFOMailBox_TypeDef *to_bang) {
|
||||
char pkt[MAX_BITS_CAN_PACKET];
|
||||
char footer[] = {
|
||||
1, // CRC delimiter
|
||||
1, // ACK
|
||||
1, // ACK delimiter
|
||||
1,1,1,1,1,1,1, // EOF
|
||||
1,1,1, // IFS
|
||||
};
|
||||
|
||||
int len = 0;
|
||||
|
||||
// test packet
|
||||
int dlc_len = to_bang->RDTR & 0xF;
|
||||
len = append_int(pkt, len, 0, 1); // Start-of-frame
|
||||
|
||||
if (to_bang->RIR & 4) {
|
||||
// extended identifier
|
||||
len = append_int(pkt, len, to_bang->RIR >> 21, 11); // Identifier
|
||||
len = append_int(pkt, len, 3, 2); // SRR+IDE
|
||||
len = append_int(pkt, len, (to_bang->RIR >> 3) & ((1<<18)-1), 18); // Identifier
|
||||
len = append_int(pkt, len, 0, 3); // RTR+r1+r0
|
||||
} else {
|
||||
// standard identifier
|
||||
len = append_int(pkt, len, to_bang->RIR >> 21, 11); // Identifier
|
||||
len = append_int(pkt, len, 0, 3); // RTR+IDE+reserved
|
||||
}
|
||||
|
||||
len = append_int(pkt, len, dlc_len, 4); // Data length code
|
||||
|
||||
// append data
|
||||
for (int i = 0; i < dlc_len; i++) {
|
||||
unsigned char dat = ((unsigned char *)(&(to_bang->RDLR)))[i];
|
||||
len = append_int(pkt, len, dat, 8);
|
||||
}
|
||||
|
||||
// append crc
|
||||
len = append_crc(pkt, len);
|
||||
|
||||
// do bitstuffing
|
||||
len = do_bitstuff(out, pkt, len);
|
||||
|
||||
// append footer
|
||||
len = append_bits(out, len, footer, sizeof(footer));
|
||||
return len;
|
||||
}
|
||||
|
||||
// hardware stuff below this line
|
||||
|
||||
#ifdef PANDA
|
||||
|
||||
void set_bitbanged_gmlan(int val) {
|
||||
if (val) {
|
||||
GPIOB->ODR |= (1 << 13);
|
||||
} else {
|
||||
GPIOB->ODR &= ~(1 << 13);
|
||||
}
|
||||
}
|
||||
|
||||
char pkt_stuffed[MAX_BITS_CAN_PACKET];
|
||||
int gmlan_sending = -1;
|
||||
int gmlan_sendmax = -1;
|
||||
|
||||
int gmlan_silent_count = 0;
|
||||
int gmlan_fail_count = 0;
|
||||
#define REQUIRED_SILENT_TIME 10
|
||||
#define MAX_FAIL_COUNT 10
|
||||
|
||||
void TIM4_IRQHandler(void) {
|
||||
if (TIM4->SR & TIM_SR_UIF && gmlan_sendmax != -1) {
|
||||
int read = get_gpio_input(GPIOB, 12);
|
||||
if (gmlan_silent_count < REQUIRED_SILENT_TIME) {
|
||||
if (read == 0) {
|
||||
gmlan_silent_count = 0;
|
||||
} else {
|
||||
gmlan_silent_count++;
|
||||
}
|
||||
} else if (gmlan_silent_count == REQUIRED_SILENT_TIME) {
|
||||
int retry = 0;
|
||||
// in send loop
|
||||
if (gmlan_sending > 0 && // not first bit
|
||||
(read == 0 && pkt_stuffed[gmlan_sending-1] == 1) && // bus wrongly dominant
|
||||
gmlan_sending != (gmlan_sendmax-11)) { //not ack bit
|
||||
puts("GMLAN ERR: bus driven at ");
|
||||
puth(gmlan_sending);
|
||||
puts("\n");
|
||||
retry = 1;
|
||||
} else if (read == 1 && gmlan_sending == (gmlan_sendmax-11)) { // recessive during ACK
|
||||
puts("GMLAN ERR: didn't recv ACK\n");
|
||||
retry = 1;
|
||||
}
|
||||
if (retry) {
|
||||
// reset sender (retry after 7 silent)
|
||||
set_bitbanged_gmlan(1); // recessive
|
||||
gmlan_silent_count = 0;
|
||||
gmlan_sending = 0;
|
||||
gmlan_fail_count++;
|
||||
if (gmlan_fail_count == MAX_FAIL_COUNT) {
|
||||
puts("GMLAN ERR: giving up send\n");
|
||||
}
|
||||
} else {
|
||||
set_bitbanged_gmlan(pkt_stuffed[gmlan_sending]);
|
||||
gmlan_sending++;
|
||||
}
|
||||
}
|
||||
if (gmlan_sending == gmlan_sendmax || gmlan_fail_count == MAX_FAIL_COUNT) {
|
||||
set_bitbanged_gmlan(1); // recessive
|
||||
set_gpio_mode(GPIOB, 13, MODE_INPUT);
|
||||
TIM4->DIER = 0; // no update interrupt
|
||||
TIM4->CR1 = 0; // disable timer
|
||||
gmlan_sendmax = -1; // exit
|
||||
}
|
||||
}
|
||||
TIM4->SR = 0;
|
||||
}
|
||||
|
||||
void bitbang_gmlan(CAN_FIFOMailBox_TypeDef *to_bang) {
|
||||
// TODO: make failure less silent
|
||||
if (gmlan_sendmax != -1) return;
|
||||
|
||||
int len = get_bit_message(pkt_stuffed, to_bang);
|
||||
gmlan_fail_count = 0;
|
||||
gmlan_silent_count = 0;
|
||||
gmlan_sending = 0;
|
||||
gmlan_sendmax = len;
|
||||
|
||||
// setup for bitbang loop
|
||||
set_bitbanged_gmlan(1); // recessive
|
||||
set_gpio_mode(GPIOB, 13, MODE_OUTPUT);
|
||||
|
||||
// setup
|
||||
TIM4->PSC = 48-1; // tick on 1 us
|
||||
TIM4->CR1 = TIM_CR1_CEN; // enable
|
||||
TIM4->ARR = 30-1; // 33.3 kbps
|
||||
|
||||
// in case it's disabled
|
||||
NVIC_EnableIRQ(TIM4_IRQn);
|
||||
|
||||
// run the interrupt
|
||||
TIM4->DIER = TIM_DIER_UIE; // update interrupt
|
||||
TIM4->SR = 0;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -119,7 +119,7 @@ void periph_init() {
|
||||
RCC->APB1ENR |= RCC_APB1ENR_DACEN;
|
||||
RCC->APB1ENR |= RCC_APB1ENR_TIM2EN;
|
||||
RCC->APB1ENR |= RCC_APB1ENR_TIM3EN;
|
||||
//RCC->APB1ENR |= RCC_APB1ENR_TIM4EN;
|
||||
RCC->APB1ENR |= RCC_APB1ENR_TIM4EN;
|
||||
RCC->APB2ENR |= RCC_APB2ENR_USART1EN;
|
||||
RCC->AHB2ENR |= RCC_AHB2ENR_OTGFSEN;
|
||||
RCC->APB2ENR |= RCC_APB2ENR_TIM1EN;
|
||||
|
||||
@@ -1,7 +1,24 @@
|
||||
// sample struct that keeps 3 samples in memory
|
||||
struct sample_t {
|
||||
int values[6];
|
||||
int min;
|
||||
int max;
|
||||
} sample_t_default = {{0}, 0, 0};
|
||||
|
||||
void safety_rx_hook(CAN_FIFOMailBox_TypeDef *to_push);
|
||||
int safety_tx_hook(CAN_FIFOMailBox_TypeDef *to_send);
|
||||
int safety_tx_lin_hook(int lin_num, uint8_t *data, int len);
|
||||
int safety_ignition_hook();
|
||||
uint32_t get_ts_elapsed(uint32_t ts, uint32_t ts_last);
|
||||
int to_signed(int d, int bits);
|
||||
void update_sample(struct sample_t *sample, int sample_new);
|
||||
int max_limit_check(int val, const int MAX);
|
||||
int dist_to_meas_check(int val, int val_last, struct sample_t *val_meas,
|
||||
const int MAX_RATE_UP, const int MAX_RATE_DOWN, const int MAX_ERROR);
|
||||
int driver_limit_check(int val, int val_last, struct sample_t *val_driver,
|
||||
const int MAX, const int MAX_RATE_UP, const int MAX_RATE_DOWN,
|
||||
const int MAX_ALLOWANCE, const int DRIVER_FACTOR);
|
||||
int rt_rate_limit_check(int val, int val_last, const int MAX_RT_DELTA);
|
||||
|
||||
typedef void (*safety_hook_init)(int16_t param);
|
||||
typedef void (*rx_hook)(CAN_FIFOMailBox_TypeDef *to_push);
|
||||
@@ -30,6 +47,8 @@ int controls_allowed = 0;
|
||||
#include "safety/safety_toyota_ipas.h"
|
||||
#endif
|
||||
#include "safety/safety_gm.h"
|
||||
#include "safety/safety_ford.h"
|
||||
#include "safety/safety_cadillac.h"
|
||||
#include "safety/safety_elm327.h"
|
||||
|
||||
const safety_hooks *current_hooks = &nooutput_hooks;
|
||||
@@ -64,10 +83,12 @@ typedef struct {
|
||||
#define SAFETY_NOOUTPUT 0
|
||||
#define SAFETY_HONDA 1
|
||||
#define SAFETY_TOYOTA 2
|
||||
#define SAFETY_TOYOTA_IPAS 0x1335
|
||||
#define SAFETY_TOYOTA_NOLIMITS 0x1336
|
||||
#define SAFETY_GM 3
|
||||
#define SAFETY_HONDA_BOSCH 4
|
||||
#define SAFETY_FORD 5
|
||||
#define SAFETY_CADILLAC 6
|
||||
#define SAFETY_TOYOTA_IPAS 0x1335
|
||||
#define SAFETY_TOYOTA_NOLIMITS 0x1336
|
||||
#define SAFETY_ALLOUTPUT 0x1337
|
||||
#define SAFETY_ELM327 0xE327
|
||||
|
||||
@@ -76,11 +97,13 @@ const safety_hook_config safety_hook_registry[] = {
|
||||
{SAFETY_HONDA, &honda_hooks},
|
||||
{SAFETY_HONDA_BOSCH, &honda_bosch_hooks},
|
||||
{SAFETY_TOYOTA, &toyota_hooks},
|
||||
{SAFETY_GM, &gm_hooks},
|
||||
{SAFETY_FORD, &ford_hooks},
|
||||
{SAFETY_CADILLAC, &cadillac_hooks},
|
||||
{SAFETY_TOYOTA_NOLIMITS, &toyota_nolimits_hooks},
|
||||
#ifdef PANDA
|
||||
{SAFETY_TOYOTA_IPAS, &toyota_ipas_hooks},
|
||||
#endif
|
||||
{SAFETY_GM, &gm_hooks},
|
||||
{SAFETY_ALLOUTPUT, &alloutput_hooks},
|
||||
{SAFETY_ELM327, &elm327_hooks},
|
||||
};
|
||||
@@ -98,3 +121,83 @@ int safety_set_mode(uint16_t mode, int16_t param) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
// compute the time elapsed (in microseconds) from 2 counter samples
|
||||
uint32_t get_ts_elapsed(uint32_t ts, uint32_t ts_last) {
|
||||
return ts > ts_last ? ts - ts_last : (0xFFFFFFFF - ts_last) + 1 + ts;
|
||||
}
|
||||
|
||||
// convert a trimmed integer to signed 32 bit int
|
||||
int to_signed(int d, int bits) {
|
||||
if (d >= (1 << (bits - 1))) {
|
||||
d -= (1 << bits);
|
||||
}
|
||||
return d;
|
||||
}
|
||||
|
||||
// given a new sample, update the smaple_t struct
|
||||
void update_sample(struct sample_t *sample, int sample_new) {
|
||||
for (int i = sizeof(sample->values)/sizeof(sample->values[0]) - 1; i > 0; i--) {
|
||||
sample->values[i] = sample->values[i-1];
|
||||
}
|
||||
sample->values[0] = sample_new;
|
||||
|
||||
// get the minimum and maximum measured samples
|
||||
sample->min = sample->max = sample->values[0];
|
||||
for (int i = 1; i < sizeof(sample->values)/sizeof(sample->values[0]); i++) {
|
||||
if (sample->values[i] < sample->min) sample->min = sample->values[i];
|
||||
if (sample->values[i] > sample->max) sample->max = sample->values[i];
|
||||
}
|
||||
}
|
||||
|
||||
int max_limit_check(int val, const int MAX) {
|
||||
return (val > MAX) | (val < -MAX);
|
||||
}
|
||||
|
||||
// check that commanded value isn't too far from measured
|
||||
int dist_to_meas_check(int val, int val_last, struct sample_t *val_meas,
|
||||
const int MAX_RATE_UP, const int MAX_RATE_DOWN, const int MAX_ERROR) {
|
||||
|
||||
// *** val rate limit check ***
|
||||
int16_t highest_allowed_val = max(val_last, 0) + MAX_RATE_UP;
|
||||
int16_t lowest_allowed_val = min(val_last, 0) - MAX_RATE_UP;
|
||||
|
||||
// if we've exceeded the meas val, we must start moving toward 0
|
||||
highest_allowed_val = min(highest_allowed_val, max(val_last - MAX_RATE_DOWN, max(val_meas->max, 0) + MAX_ERROR));
|
||||
lowest_allowed_val = max(lowest_allowed_val, min(val_last + MAX_RATE_DOWN, min(val_meas->min, 0) - MAX_ERROR));
|
||||
|
||||
// check for violation
|
||||
return (val < lowest_allowed_val) || (val > highest_allowed_val);
|
||||
}
|
||||
|
||||
// check that commanded value isn't fighting against driver
|
||||
int driver_limit_check(int val, int val_last, struct sample_t *val_driver,
|
||||
const int MAX, const int MAX_RATE_UP, const int MAX_RATE_DOWN,
|
||||
const int MAX_ALLOWANCE, const int DRIVER_FACTOR) {
|
||||
|
||||
int highest_allowed = max(val_last, 0) + MAX_RATE_UP;
|
||||
int lowest_allowed = min(val_last, 0) - MAX_RATE_UP;
|
||||
|
||||
int driver_max_limit = MAX + (MAX_ALLOWANCE + val_driver->max) * DRIVER_FACTOR;
|
||||
int driver_min_limit = -MAX + (-MAX_ALLOWANCE + val_driver->min) * DRIVER_FACTOR;
|
||||
|
||||
// if we've exceeded the applied torque, we must start moving toward 0
|
||||
highest_allowed = min(highest_allowed, max(val_last - MAX_RATE_DOWN,
|
||||
max(driver_max_limit, 0)));
|
||||
lowest_allowed = max(lowest_allowed, min(val_last + MAX_RATE_DOWN,
|
||||
min(driver_min_limit, 0)));
|
||||
|
||||
// check for violation
|
||||
return (val < lowest_allowed) || (val > highest_allowed);
|
||||
}
|
||||
|
||||
|
||||
// real time check, mainly used for steer torque rate limiter
|
||||
int rt_rate_limit_check(int val, int val_last, const int MAX_RT_DELTA) {
|
||||
|
||||
// *** torque real time rate limit check ***
|
||||
int16_t highest_val = max(val_last, 0) + MAX_RT_DELTA;
|
||||
int16_t lowest_val = min(val_last, 0) - MAX_RT_DELTA;
|
||||
|
||||
// check for violation
|
||||
return (val < lowest_val) || (val > highest_val);
|
||||
}
|
||||
|
||||
131
panda/board/safety/safety_cadillac.h
Normal file
131
panda/board/safety/safety_cadillac.h
Normal file
@@ -0,0 +1,131 @@
|
||||
const int CADILLAC_MAX_STEER = 150; // 1s
|
||||
// real time torque limit to prevent controls spamming
|
||||
// the real time limit is 1500/sec
|
||||
const int CADILLAC_MAX_RT_DELTA = 75; // max delta torque allowed for real time checks
|
||||
const int32_t CADILLAC_RT_INTERVAL = 250000; // 250ms between real time checks
|
||||
const int CADILLAC_MAX_RATE_UP = 2;
|
||||
const int CADILLAC_MAX_RATE_DOWN = 5;
|
||||
const int CADILLAC_DRIVER_TORQUE_ALLOWANCE = 50;
|
||||
const int CADILLAC_DRIVER_TORQUE_FACTOR = 4;
|
||||
|
||||
int cadillac_ign = 0;
|
||||
int cadillac_cruise_engaged_last = 0;
|
||||
int cadillac_rt_torque_last = 0;
|
||||
int cadillac_desired_torque_last[4] = {0}; // 4 torque messages
|
||||
uint32_t cadillac_ts_last = 0;
|
||||
int cadillac_supercruise_on = 0;
|
||||
struct sample_t cadillac_torque_driver; // last few driver torques measured
|
||||
|
||||
int cadillac_get_torque_idx(uint32_t addr) {
|
||||
if (addr==0x151) return 0;
|
||||
else if (addr==0x152) return 1;
|
||||
else if (addr==0x153) return 2;
|
||||
else return 3;
|
||||
}
|
||||
|
||||
static void cadillac_rx_hook(CAN_FIFOMailBox_TypeDef *to_push) {
|
||||
int bus_number = (to_push->RDTR >> 4) & 0xFF;
|
||||
uint32_t addr = to_push->RIR >> 21;
|
||||
|
||||
if (addr == 356) {
|
||||
int torque_driver_new = ((to_push->RDLR & 0x7) << 8) | ((to_push->RDLR >> 8) & 0xFF);
|
||||
torque_driver_new = to_signed(torque_driver_new, 11);
|
||||
// update array of samples
|
||||
update_sample(&cadillac_torque_driver, torque_driver_new);
|
||||
}
|
||||
|
||||
// this message isn't all zeros when ignition is on
|
||||
if (addr == 0x160 && bus_number == 0) {
|
||||
cadillac_ign = to_push->RDLR > 0;
|
||||
}
|
||||
|
||||
// enter controls on rising edge of ACC, exit controls on ACC off
|
||||
if ((addr == 0x370) && (bus_number == 0)) {
|
||||
int cruise_engaged = to_push->RDLR & 0x800000; // bit 23
|
||||
if (cruise_engaged && !cadillac_cruise_engaged_last) {
|
||||
controls_allowed = 1;
|
||||
} else if (!cruise_engaged) {
|
||||
controls_allowed = 0;
|
||||
}
|
||||
cadillac_cruise_engaged_last = cruise_engaged;
|
||||
}
|
||||
|
||||
// know supercruise mode and block openpilot msgs if on
|
||||
if ((addr == 0x152) || (addr == 0x154)) {
|
||||
cadillac_supercruise_on = (to_push->RDHR>>4) & 0x1;
|
||||
}
|
||||
}
|
||||
|
||||
static int cadillac_tx_hook(CAN_FIFOMailBox_TypeDef *to_send) {
|
||||
uint32_t addr = to_send->RIR >> 21;
|
||||
|
||||
// steer cmd checks
|
||||
if (addr == 0x151 || addr == 0x152 || addr == 0x153 || addr == 0x154) {
|
||||
int desired_torque = ((to_send->RDLR & 0x3f) << 8) + ((to_send->RDLR & 0xff00) >> 8);
|
||||
int violation = 0;
|
||||
uint32_t ts = TIM2->CNT;
|
||||
int idx = cadillac_get_torque_idx(addr);
|
||||
desired_torque = to_signed(desired_torque, 14);
|
||||
|
||||
if (controls_allowed) {
|
||||
|
||||
// *** global torque limit check ***
|
||||
violation |= max_limit_check(desired_torque, CADILLAC_MAX_STEER);
|
||||
|
||||
// *** torque rate limit check ***
|
||||
int desired_torque_last = cadillac_desired_torque_last[idx];
|
||||
violation |= driver_limit_check(desired_torque, desired_torque_last, &cadillac_torque_driver,
|
||||
CADILLAC_MAX_STEER, CADILLAC_MAX_RATE_UP, CADILLAC_MAX_RATE_DOWN,
|
||||
CADILLAC_DRIVER_TORQUE_ALLOWANCE, CADILLAC_DRIVER_TORQUE_FACTOR);
|
||||
|
||||
// used next time
|
||||
cadillac_desired_torque_last[idx] = desired_torque;
|
||||
|
||||
// *** torque real time rate limit check ***
|
||||
violation |= rt_rate_limit_check(desired_torque, cadillac_rt_torque_last, CADILLAC_MAX_RT_DELTA);
|
||||
|
||||
// every RT_INTERVAL set the new limits
|
||||
uint32_t ts_elapsed = get_ts_elapsed(ts, cadillac_ts_last);
|
||||
if (ts_elapsed > CADILLAC_RT_INTERVAL) {
|
||||
cadillac_rt_torque_last = desired_torque;
|
||||
cadillac_ts_last = ts;
|
||||
}
|
||||
}
|
||||
|
||||
// no torque if controls is not allowed
|
||||
if (!controls_allowed && (desired_torque != 0)) {
|
||||
violation = 1;
|
||||
}
|
||||
|
||||
// reset to 0 if either controls is not allowed or there's a violation
|
||||
if (violation || !controls_allowed) {
|
||||
cadillac_desired_torque_last[idx] = 0;
|
||||
cadillac_rt_torque_last = 0;
|
||||
cadillac_ts_last = ts;
|
||||
}
|
||||
|
||||
if (violation || cadillac_supercruise_on) {
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static void cadillac_init(int16_t param) {
|
||||
controls_allowed = 0;
|
||||
cadillac_ign = 0;
|
||||
}
|
||||
|
||||
static int cadillac_ign_hook() {
|
||||
return cadillac_ign;
|
||||
}
|
||||
|
||||
const safety_hooks cadillac_hooks = {
|
||||
.init = cadillac_init,
|
||||
.rx = cadillac_rx_hook,
|
||||
.tx = cadillac_tx_hook,
|
||||
.tx_lin = alloutput_tx_lin_hook,
|
||||
.ignition = cadillac_ign_hook,
|
||||
.fwd = alloutput_fwd_hook,
|
||||
};
|
||||
@@ -1,5 +1,9 @@
|
||||
void default_rx_hook(CAN_FIFOMailBox_TypeDef *to_push) {}
|
||||
|
||||
int default_ign_hook() {
|
||||
return -1; // use GPIO to determine ignition
|
||||
}
|
||||
|
||||
// *** no output safety mode ***
|
||||
|
||||
static void nooutput_init(int16_t param) {
|
||||
@@ -14,9 +18,6 @@ static int nooutput_tx_lin_hook(int lin_num, uint8_t *data, int len) {
|
||||
return false;
|
||||
}
|
||||
|
||||
static int nooutput_ign_hook() {
|
||||
return -1;
|
||||
}
|
||||
static int nooutput_fwd_hook(int bus_num, CAN_FIFOMailBox_TypeDef *to_fwd) {
|
||||
return -1;
|
||||
}
|
||||
@@ -26,7 +27,7 @@ const safety_hooks nooutput_hooks = {
|
||||
.rx = default_rx_hook,
|
||||
.tx = nooutput_tx_hook,
|
||||
.tx_lin = nooutput_tx_lin_hook,
|
||||
.ignition = nooutput_ign_hook,
|
||||
.ignition = default_ign_hook,
|
||||
.fwd = nooutput_fwd_hook,
|
||||
};
|
||||
|
||||
@@ -44,10 +45,6 @@ static int alloutput_tx_lin_hook(int lin_num, uint8_t *data, int len) {
|
||||
return true;
|
||||
}
|
||||
|
||||
static int alloutput_ign_hook() {
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int alloutput_fwd_hook(int bus_num, CAN_FIFOMailBox_TypeDef *to_fwd) {
|
||||
return -1;
|
||||
}
|
||||
@@ -57,7 +54,7 @@ const safety_hooks alloutput_hooks = {
|
||||
.rx = default_rx_hook,
|
||||
.tx = alloutput_tx_hook,
|
||||
.tx_lin = alloutput_tx_lin_hook,
|
||||
.ignition = alloutput_ign_hook,
|
||||
.ignition = default_ign_hook,
|
||||
.fwd = alloutput_fwd_hook,
|
||||
};
|
||||
|
||||
|
||||
@@ -31,10 +31,6 @@ static void elm327_init(int16_t param) {
|
||||
controls_allowed = 1;
|
||||
}
|
||||
|
||||
static int elm327_ign_hook() {
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int elm327_fwd_hook(int bus_num, CAN_FIFOMailBox_TypeDef *to_fwd) {
|
||||
return -1;
|
||||
}
|
||||
@@ -44,6 +40,6 @@ const safety_hooks elm327_hooks = {
|
||||
.rx = elm327_rx_hook,
|
||||
.tx = elm327_tx_hook,
|
||||
.tx_lin = elm327_tx_lin_hook,
|
||||
.ignition = elm327_ign_hook,
|
||||
.ignition = default_ign_hook,
|
||||
.fwd = elm327_fwd_hook,
|
||||
};
|
||||
|
||||
106
panda/board/safety/safety_ford.h
Normal file
106
panda/board/safety/safety_ford.h
Normal file
@@ -0,0 +1,106 @@
|
||||
// board enforces
|
||||
// in-state
|
||||
// accel set/resume
|
||||
// out-state
|
||||
// cancel button
|
||||
// accel rising edge
|
||||
// brake rising edge
|
||||
// brake > 0mph
|
||||
|
||||
int ford_brake_prev = 0;
|
||||
int ford_gas_prev = 0;
|
||||
int ford_is_moving = 0;
|
||||
|
||||
static void ford_rx_hook(CAN_FIFOMailBox_TypeDef *to_push) {
|
||||
|
||||
if ((to_push->RIR>>21) == 0x217) {
|
||||
// wheel speeds are 14 bits every 16
|
||||
ford_is_moving = 0xFCFF & (to_push->RDLR | (to_push->RDLR >> 16) |
|
||||
to_push->RDHR | (to_push->RDHR >> 16));
|
||||
}
|
||||
|
||||
// state machine to enter and exit controls
|
||||
if ((to_push->RIR>>21) == 0x83) {
|
||||
int cancel = ((to_push->RDLR >> 8) & 0x1);
|
||||
int set_or_resume = (to_push->RDLR >> 28) & 0x3;
|
||||
if (cancel) {
|
||||
controls_allowed = 0;
|
||||
} else if (set_or_resume) {
|
||||
controls_allowed = 1;
|
||||
}
|
||||
}
|
||||
|
||||
// exit controls on rising edge of brake press or on brake press when
|
||||
// speed > 0
|
||||
if ((to_push->RIR>>21) == 0x165) {
|
||||
int brake = to_push->RDLR & 0x20;
|
||||
if (brake && (!(ford_brake_prev) || ford_is_moving)) {
|
||||
controls_allowed = 0;
|
||||
}
|
||||
ford_brake_prev = brake;
|
||||
}
|
||||
|
||||
// exit controls on rising edge of gas press
|
||||
if ((to_push->RIR>>21) == 0x204) {
|
||||
int gas = to_push->RDLR & 0xFF03;
|
||||
if (gas && !(ford_gas_prev)) {
|
||||
controls_allowed = 0;
|
||||
}
|
||||
ford_gas_prev = gas;
|
||||
}
|
||||
}
|
||||
|
||||
// all commands: just steering
|
||||
// if controls_allowed and no pedals pressed
|
||||
// allow all commands up to limit
|
||||
// else
|
||||
// block all commands that produce actuation
|
||||
|
||||
static int ford_tx_hook(CAN_FIFOMailBox_TypeDef *to_send) {
|
||||
|
||||
// disallow actuator commands if gas or brake (with vehicle moving) are pressed
|
||||
// and the the latching controls_allowed flag is True
|
||||
int pedal_pressed = ford_gas_prev || (ford_brake_prev && ford_is_moving);
|
||||
int current_controls_allowed = controls_allowed && !(pedal_pressed);
|
||||
|
||||
// STEER: safety check
|
||||
if ((to_send->RIR>>21) == 0x3CA) {
|
||||
if (current_controls_allowed) {
|
||||
// all messages are fine here
|
||||
} else {
|
||||
// bits 7-4 need to be 0xF to disallow lkas commands
|
||||
if (((to_send->RDLR >> 4) & 0xF) != 0xF) return 0;
|
||||
}
|
||||
}
|
||||
|
||||
// FORCE CANCEL: safety check only relevant when spamming the cancel button
|
||||
// ensuring that set and resume aren't sent
|
||||
if ((to_send->RIR>>21) == 0x83) {
|
||||
if ((to_send->RDLR >> 28) & 0x3) return 0;
|
||||
}
|
||||
|
||||
// 1 allows the message through
|
||||
return true;
|
||||
}
|
||||
|
||||
static int ford_tx_lin_hook(int lin_num, uint8_t *data, int len) {
|
||||
// TODO: add safety if using LIN
|
||||
return true;
|
||||
}
|
||||
|
||||
static void ford_init(int16_t param) {
|
||||
controls_allowed = 0;
|
||||
}
|
||||
|
||||
static int ford_fwd_hook(int bus_num, CAN_FIFOMailBox_TypeDef *to_fwd) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
const safety_hooks ford_hooks = {
|
||||
.init = ford_init,
|
||||
.rx = ford_rx_hook,
|
||||
.tx = ford_tx_hook,
|
||||
.tx_lin = ford_tx_lin_hook,
|
||||
.ignition = default_ign_hook,
|
||||
.fwd = ford_fwd_hook,
|
||||
};
|
||||
@@ -8,15 +8,27 @@
|
||||
// brake rising edge
|
||||
// brake > 0mph
|
||||
|
||||
// gm_: poor man's namespacing
|
||||
const int GM_MAX_STEER = 255;
|
||||
const int GM_MAX_RT_DELTA = 128; // max delta torque allowed for real time checks
|
||||
const int32_t GM_RT_INTERVAL = 250000; // 250ms between real time checks
|
||||
const int GM_MAX_RATE_UP = 7;
|
||||
const int GM_MAX_RATE_DOWN = 17;
|
||||
const int GM_DRIVER_TORQUE_ALLOWANCE = 50;
|
||||
const int GM_DRIVER_TORQUE_FACTOR = 4;
|
||||
const int GM_MAX_GAS = 3072;
|
||||
const int GM_MAX_REGEN = 1404;
|
||||
const int GM_MAX_BRAKE = 350;
|
||||
|
||||
int gm_brake_prev = 0;
|
||||
int gm_gas_prev = 0;
|
||||
int gm_speed = 0;
|
||||
|
||||
// silence everything if stock ECUs are still online
|
||||
int gm_ascm_detected = 0;
|
||||
|
||||
int gm_ignition_started = 0;
|
||||
int gm_rt_torque_last = 0;
|
||||
int gm_desired_torque_last = 0;
|
||||
uint32_t gm_ts_last = 0;
|
||||
struct sample_t gm_torque_driver; // last few driver torques measured
|
||||
|
||||
static void gm_rx_hook(CAN_FIFOMailBox_TypeDef *to_push) {
|
||||
int bus_number = (to_push->RDTR >> 4) & 0xFF;
|
||||
@@ -31,10 +43,18 @@ static void gm_rx_hook(CAN_FIFOMailBox_TypeDef *to_push) {
|
||||
addr = to_push->RIR >> 21;
|
||||
}
|
||||
|
||||
if (addr == 0x135 && bus_number == 0) {
|
||||
//Gear selector (used for determining ignition)
|
||||
int gear = to_push->RDLR & 0x7;
|
||||
gm_ignition_started = gear > 0; //Park = 0. If out of park, we're "on."
|
||||
if (addr == 388) {
|
||||
int torque_driver_new = (((to_push->RDHR >> 16) & 0x7) << 8) | ((to_push->RDHR >> 24) & 0xFF);
|
||||
torque_driver_new = to_signed(torque_driver_new, 11);
|
||||
// update array of samples
|
||||
update_sample(&gm_torque_driver, torque_driver_new);
|
||||
}
|
||||
|
||||
if (addr == 0x1f1 && bus_number == 0) {
|
||||
//Bit 5 should be ignition "on"
|
||||
//Backup plan is Bit 2 (accessory power)
|
||||
uint32_t ign = (to_push->RDLR) & 0x20;
|
||||
gm_ignition_started = ign > 0;
|
||||
}
|
||||
|
||||
// sample speed, really only care if car is moving or not
|
||||
@@ -126,7 +146,7 @@ static int gm_tx_hook(CAN_FIFOMailBox_TypeDef *to_send) {
|
||||
int brake = ((rdlr & 0xF) << 8) + ((rdlr & 0xFF00) >> 8);
|
||||
brake = (0x1000 - brake) & 0xFFF;
|
||||
if (current_controls_allowed) {
|
||||
if (brake > 255) return 0;
|
||||
if (brake > GM_MAX_BRAKE) return 0;
|
||||
} else {
|
||||
if (brake != 0) return 0;
|
||||
}
|
||||
@@ -135,17 +155,49 @@ static int gm_tx_hook(CAN_FIFOMailBox_TypeDef *to_send) {
|
||||
// LKA STEER: safety check
|
||||
if (addr == 384) {
|
||||
int rdlr = to_send->RDLR;
|
||||
int steer = ((rdlr & 0x7) << 8) + ((rdlr & 0xFF00) >> 8);
|
||||
int max_steer = 255;
|
||||
int desired_torque = ((rdlr & 0x7) << 8) + ((rdlr & 0xFF00) >> 8);
|
||||
uint32_t ts = TIM2->CNT;
|
||||
int violation = 0;
|
||||
desired_torque = to_signed(desired_torque, 11);
|
||||
|
||||
if (current_controls_allowed) {
|
||||
// Signed arithmetic
|
||||
if (steer & 0x400) {
|
||||
if (steer < (0x800 - max_steer)) return 0;
|
||||
} else {
|
||||
if (steer > max_steer) return 0;
|
||||
|
||||
// *** global torque limit check ***
|
||||
violation |= max_limit_check(desired_torque, GM_MAX_STEER);
|
||||
|
||||
// *** torque rate limit check ***
|
||||
violation |= driver_limit_check(desired_torque, gm_desired_torque_last, &gm_torque_driver,
|
||||
GM_MAX_STEER, GM_MAX_RATE_UP, GM_MAX_RATE_DOWN,
|
||||
GM_DRIVER_TORQUE_ALLOWANCE, GM_DRIVER_TORQUE_FACTOR);
|
||||
|
||||
// used next time
|
||||
gm_desired_torque_last = desired_torque;
|
||||
|
||||
// *** torque real time rate limit check ***
|
||||
violation |= rt_rate_limit_check(desired_torque, gm_rt_torque_last, GM_MAX_RT_DELTA);
|
||||
|
||||
// every RT_INTERVAL set the new limits
|
||||
uint32_t ts_elapsed = get_ts_elapsed(ts, gm_ts_last);
|
||||
if (ts_elapsed > GM_RT_INTERVAL) {
|
||||
gm_rt_torque_last = desired_torque;
|
||||
gm_ts_last = ts;
|
||||
}
|
||||
} else {
|
||||
if (steer != 0) return 0;
|
||||
}
|
||||
|
||||
// no torque if controls is not allowed
|
||||
if (!current_controls_allowed && (desired_torque != 0)) {
|
||||
violation = 1;
|
||||
}
|
||||
|
||||
// reset to 0 if either controls is not allowed or there's a violation
|
||||
if (violation || !current_controls_allowed) {
|
||||
gm_desired_torque_last = 0;
|
||||
gm_rt_torque_last = 0;
|
||||
gm_ts_last = ts;
|
||||
}
|
||||
|
||||
if (violation) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -158,11 +210,11 @@ static int gm_tx_hook(CAN_FIFOMailBox_TypeDef *to_send) {
|
||||
int gas_regen = ((rdlr & 0x7F0000) >> 11) + ((rdlr & 0xF8000000) >> 27);
|
||||
int apply = rdlr & 1;
|
||||
if (current_controls_allowed) {
|
||||
if (gas_regen > 3072) return 0;
|
||||
if (gas_regen > GM_MAX_GAS) return 0;
|
||||
} else {
|
||||
// Disabled message is !engaed with gas
|
||||
// value that corresponds to max regen.
|
||||
if (apply || gas_regen != 1404) return 0;
|
||||
if (apply || gas_regen != GM_MAX_REGEN) return 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -16,6 +16,7 @@ int gas_interceptor_prev = 0;
|
||||
int ego_speed = 0;
|
||||
// TODO: auto-detect bosch hardware based on CAN messages?
|
||||
bool bosch_hardware = false;
|
||||
bool honda_alt_brake_msg = false;
|
||||
|
||||
static void honda_rx_hook(CAN_FIFOMailBox_TypeDef *to_push) {
|
||||
|
||||
@@ -36,11 +37,14 @@ static void honda_rx_hook(CAN_FIFOMailBox_TypeDef *to_push) {
|
||||
}
|
||||
}
|
||||
|
||||
// user brake signal is different for nidec vs bosch hardware
|
||||
// nidec hardware: 0x17C bit 53
|
||||
// bosch hardware: 0x1BE bit 4
|
||||
#define IS_USER_BRAKE_MSG(to_push) (!bosch_hardware ? to_push->RIR>>21 == 0x17C : to_push->RIR>>21 == 0x1BE)
|
||||
#define USER_BRAKE_VALUE(to_push) (!bosch_hardware ? to_push->RDHR & 0x200000 : to_push->RDLR & 0x10)
|
||||
// user brake signal on 0x17C reports applied brake from computer brake on accord
|
||||
// and crv, which prevents the usual brake safety from working correctly. these
|
||||
// cars have a signal on 0x1BE which only detects user's brake being applied so
|
||||
// in these cases, this is used instead.
|
||||
// most hondas: 0x17C bit 53
|
||||
// accord, crv: 0x1BE bit 4
|
||||
#define IS_USER_BRAKE_MSG(to_push) (!honda_alt_brake_msg ? to_push->RIR>>21 == 0x17C : to_push->RIR>>21 == 0x1BE)
|
||||
#define USER_BRAKE_VALUE(to_push) (!honda_alt_brake_msg ? to_push->RDHR & 0x200000 : to_push->RDLR & 0x10)
|
||||
// exit controls on rising edge of brake press or on brake press when
|
||||
// speed > 0
|
||||
if (IS_USER_BRAKE_MSG(to_push)) {
|
||||
@@ -115,6 +119,14 @@ static int honda_tx_hook(CAN_FIFOMailBox_TypeDef *to_send) {
|
||||
if ((to_send->RDLR & 0xFFFF0000) != to_send->RDLR) return 0;
|
||||
}
|
||||
}
|
||||
|
||||
// FORCE CANCEL: safety check only relevant when spamming the cancel button in Bosch HW
|
||||
// ensuring that only the cancel button press is sent (VAL 2) when controls are off.
|
||||
// This avoids unintended engagements while still allowing resume spam
|
||||
if (((to_send->RIR>>21) == 0x296) && bosch_hardware &&
|
||||
!current_controls_allowed && ((to_send->RDTR >> 4) & 0xFF) == 0) {
|
||||
if (((to_send->RDLR >> 5) & 0x7) != 2) return 0;
|
||||
}
|
||||
|
||||
// 1 allows the message through
|
||||
return true;
|
||||
@@ -128,28 +140,27 @@ static int honda_tx_lin_hook(int lin_num, uint8_t *data, int len) {
|
||||
static void honda_init(int16_t param) {
|
||||
controls_allowed = 0;
|
||||
bosch_hardware = false;
|
||||
honda_alt_brake_msg = false;
|
||||
}
|
||||
|
||||
static int honda_fwd_hook(int bus_num, CAN_FIFOMailBox_TypeDef *to_fwd) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int honda_ign_hook() {
|
||||
return -1;
|
||||
}
|
||||
|
||||
const safety_hooks honda_hooks = {
|
||||
.init = honda_init,
|
||||
.rx = honda_rx_hook,
|
||||
.tx = honda_tx_hook,
|
||||
.tx_lin = honda_tx_lin_hook,
|
||||
.ignition = honda_ign_hook,
|
||||
.ignition = default_ign_hook,
|
||||
.fwd = honda_fwd_hook,
|
||||
};
|
||||
|
||||
static void honda_bosch_init(int16_t param) {
|
||||
controls_allowed = 0;
|
||||
bosch_hardware = true;
|
||||
// Checking for alternate brake override from safety parameter
|
||||
honda_alt_brake_msg = param == 1 ? true : false;
|
||||
}
|
||||
|
||||
static int honda_bosch_fwd_hook(int bus_num, CAN_FIFOMailBox_TypeDef *to_fwd) {
|
||||
@@ -165,6 +176,6 @@ const safety_hooks honda_bosch_hooks = {
|
||||
.rx = honda_rx_hook,
|
||||
.tx = honda_tx_hook,
|
||||
.tx_lin = honda_tx_lin_hook,
|
||||
.ignition = honda_ign_hook,
|
||||
.ignition = default_ign_hook,
|
||||
.fwd = honda_bosch_fwd_hook,
|
||||
};
|
||||
|
||||
@@ -1,64 +1,45 @@
|
||||
// track the torque measured for limiting
|
||||
struct sample_t {
|
||||
int values[3];
|
||||
int min;
|
||||
int max;
|
||||
} sample_t_default = {{0, 0, 0}, 0, 0};
|
||||
struct sample_t torque_meas; // last 3 motor torques produced by the eps
|
||||
|
||||
// global torque limit
|
||||
const int32_t MAX_TORQUE = 1500; // max torque cmd allowed ever
|
||||
const int MAX_TORQUE = 1500; // max torque cmd allowed ever
|
||||
|
||||
// rate based torque limit + stay within actually applied
|
||||
// packet is sent at 100hz, so this limit is 1000/sec
|
||||
const int32_t MAX_RATE_UP = 10; // ramp up slow
|
||||
const int32_t MAX_RATE_DOWN = 25; // ramp down fast
|
||||
const int32_t MAX_TORQUE_ERROR = 350; // max torque cmd in excess of torque motor
|
||||
const int MAX_RATE_UP = 10; // ramp up slow
|
||||
const int MAX_RATE_DOWN = 25; // ramp down fast
|
||||
const int MAX_TORQUE_ERROR = 350; // max torque cmd in excess of torque motor
|
||||
|
||||
// real time torque limit to prevent controls spamming
|
||||
// the real time limit is 1500/sec
|
||||
const int32_t MAX_RT_DELTA = 375; // max delta torque allowed for real time checks
|
||||
const int32_t RT_INTERVAL = 250000; // 250ms between real time checks
|
||||
const int MAX_RT_DELTA = 375; // max delta torque allowed for real time checks
|
||||
const int RT_INTERVAL = 250000; // 250ms between real time checks
|
||||
|
||||
// longitudinal limits
|
||||
const int16_t MAX_ACCEL = 1500; // 1.5 m/s2
|
||||
const int16_t MIN_ACCEL = -3000; // 3.0 m/s2
|
||||
const int MAX_ACCEL = 1500; // 1.5 m/s2
|
||||
const int MIN_ACCEL = -3000; // 3.0 m/s2
|
||||
|
||||
// global actuation limit state
|
||||
int actuation_limits = 1; // by default steer limits are imposed
|
||||
int16_t dbc_eps_torque_factor = 100; // conversion factor for STEER_TORQUE_EPS in %: see dbc file
|
||||
int dbc_eps_torque_factor = 100; // conversion factor for STEER_TORQUE_EPS in %: see dbc file
|
||||
|
||||
// state of torque limits
|
||||
int16_t desired_torque_last = 0; // last desired steer torque
|
||||
int16_t rt_torque_last = 0; // last desired torque for real time check
|
||||
int desired_torque_last = 0; // last desired steer torque
|
||||
int rt_torque_last = 0; // last desired torque for real time check
|
||||
uint32_t ts_last = 0;
|
||||
int cruise_engaged_last = 0; // cruise state
|
||||
|
||||
uint32_t get_ts_elapsed(uint32_t ts, uint32_t ts_last) {
|
||||
return ts > ts_last ? ts - ts_last : (0xFFFFFFFF - ts_last) + 1 + ts;
|
||||
}
|
||||
|
||||
void update_sample(struct sample_t *sample, int sample_new) {
|
||||
for (int i = sizeof(sample->values)/sizeof(sample->values[0]) - 1; i > 0; i--) {
|
||||
sample->values[i] = sample->values[i-1];
|
||||
}
|
||||
sample->values[0] = sample_new;
|
||||
|
||||
// get the minimum and maximum measured torque over the last 3 frames
|
||||
sample->min = sample->max = sample->values[0];
|
||||
for (int i = 1; i < sizeof(sample->values)/sizeof(sample->values[0]); i++) {
|
||||
if (sample->values[i] < sample->min) sample->min = sample->values[i];
|
||||
if (sample->values[i] > sample->max) sample->max = sample->values[i];
|
||||
}
|
||||
}
|
||||
|
||||
static void toyota_rx_hook(CAN_FIFOMailBox_TypeDef *to_push) {
|
||||
// get eps motor torque (0.66 factor in dbc)
|
||||
if ((to_push->RIR>>21) == 0x260) {
|
||||
int16_t torque_meas_new_16 = (((to_push->RDHR) & 0xFF00) | ((to_push->RDHR >> 16) & 0xFF));
|
||||
int torque_meas_new = (((to_push->RDHR) & 0xFF00) | ((to_push->RDHR >> 16) & 0xFF));
|
||||
torque_meas_new = to_signed(torque_meas_new, 16);
|
||||
|
||||
// scale by dbc_factor
|
||||
torque_meas_new = (torque_meas_new * dbc_eps_torque_factor) / 100;
|
||||
|
||||
// increase torque_meas by 1 to be conservative on rounding
|
||||
int torque_meas_new = ((int)(torque_meas_new_16) * dbc_eps_torque_factor / 100) + (torque_meas_new_16 > 0 ? 1 : -1);
|
||||
torque_meas_new += (torque_meas_new > 0 ? 1 : -1);
|
||||
|
||||
// update array of sample
|
||||
update_sample(&torque_meas, torque_meas_new);
|
||||
@@ -87,7 +68,8 @@ static int toyota_tx_hook(CAN_FIFOMailBox_TypeDef *to_send) {
|
||||
|
||||
// ACCEL: safety check on byte 1-2
|
||||
if ((to_send->RIR>>21) == 0x343) {
|
||||
int16_t desired_accel = ((to_send->RDLR & 0xFF) << 8) | ((to_send->RDLR >> 8) & 0xFF);
|
||||
int desired_accel = ((to_send->RDLR & 0xFF) << 8) | ((to_send->RDLR >> 8) & 0xFF);
|
||||
desired_accel = to_signed(desired_accel, 16);
|
||||
if (controls_allowed && actuation_limits) {
|
||||
if ((desired_accel > MAX_ACCEL) || (desired_accel < MIN_ACCEL)) {
|
||||
return 0;
|
||||
@@ -99,8 +81,9 @@ static int toyota_tx_hook(CAN_FIFOMailBox_TypeDef *to_send) {
|
||||
|
||||
// STEER: safety check on bytes 2-3
|
||||
if ((to_send->RIR>>21) == 0x2E4) {
|
||||
int16_t desired_torque = (to_send->RDLR & 0xFF00) | ((to_send->RDLR >> 16) & 0xFF);
|
||||
int16_t violation = 0;
|
||||
int desired_torque = (to_send->RDLR & 0xFF00) | ((to_send->RDLR >> 16) & 0xFF);
|
||||
desired_torque = to_signed(desired_torque, 16);
|
||||
int violation = 0;
|
||||
|
||||
uint32_t ts = TIM2->CNT;
|
||||
|
||||
@@ -108,35 +91,16 @@ static int toyota_tx_hook(CAN_FIFOMailBox_TypeDef *to_send) {
|
||||
if (controls_allowed && actuation_limits) {
|
||||
|
||||
// *** global torque limit check ***
|
||||
if (desired_torque < -MAX_TORQUE) violation = 1;
|
||||
if (desired_torque > MAX_TORQUE) violation = 1;
|
||||
|
||||
violation |= max_limit_check(desired_torque, MAX_TORQUE);
|
||||
|
||||
// *** torque rate limit check ***
|
||||
int16_t highest_allowed_torque = max(desired_torque_last, 0) + MAX_RATE_UP;
|
||||
int16_t lowest_allowed_torque = min(desired_torque_last, 0) - MAX_RATE_UP;
|
||||
|
||||
// if we've exceeded the applied torque, we must start moving toward 0
|
||||
highest_allowed_torque = min(highest_allowed_torque, max(desired_torque_last - MAX_RATE_DOWN, max(torque_meas.max, 0) + MAX_TORQUE_ERROR));
|
||||
lowest_allowed_torque = max(lowest_allowed_torque, min(desired_torque_last + MAX_RATE_DOWN, min(torque_meas.min, 0) - MAX_TORQUE_ERROR));
|
||||
|
||||
// check for violation
|
||||
if ((desired_torque < lowest_allowed_torque) || (desired_torque > highest_allowed_torque)) {
|
||||
violation = 1;
|
||||
}
|
||||
violation |= dist_to_meas_check(desired_torque, desired_torque_last, &torque_meas, MAX_RATE_UP, MAX_RATE_DOWN, MAX_TORQUE_ERROR);
|
||||
|
||||
// used next time
|
||||
desired_torque_last = desired_torque;
|
||||
|
||||
|
||||
// *** torque real time rate limit check ***
|
||||
int16_t highest_rt_torque = max(rt_torque_last, 0) + MAX_RT_DELTA;
|
||||
int16_t lowest_rt_torque = min(rt_torque_last, 0) - MAX_RT_DELTA;
|
||||
|
||||
// check for violation
|
||||
if ((desired_torque < lowest_rt_torque) || (desired_torque > highest_rt_torque)) {
|
||||
violation = 1;
|
||||
}
|
||||
violation |= rt_rate_limit_check(desired_torque, rt_torque_last, MAX_RT_DELTA);
|
||||
|
||||
// every RT_INTERVAL set the new limits
|
||||
uint32_t ts_elapsed = get_ts_elapsed(ts, ts_last);
|
||||
@@ -179,10 +143,6 @@ static void toyota_init(int16_t param) {
|
||||
dbc_eps_torque_factor = param;
|
||||
}
|
||||
|
||||
static int toyota_ign_hook() {
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int toyota_fwd_hook(int bus_num, CAN_FIFOMailBox_TypeDef *to_fwd) {
|
||||
return -1;
|
||||
}
|
||||
@@ -192,7 +152,7 @@ const safety_hooks toyota_hooks = {
|
||||
.rx = toyota_rx_hook,
|
||||
.tx = toyota_tx_hook,
|
||||
.tx_lin = toyota_tx_lin_hook,
|
||||
.ignition = toyota_ign_hook,
|
||||
.ignition = default_ign_hook,
|
||||
.fwd = toyota_fwd_hook,
|
||||
};
|
||||
|
||||
@@ -207,6 +167,6 @@ const safety_hooks toyota_nolimits_hooks = {
|
||||
.rx = toyota_rx_hook,
|
||||
.tx = toyota_tx_hook,
|
||||
.tx_lin = toyota_tx_lin_hook,
|
||||
.ignition = toyota_ign_hook,
|
||||
.ignition = default_ign_hook,
|
||||
.fwd = toyota_fwd_hook,
|
||||
};
|
||||
|
||||
@@ -35,13 +35,6 @@ uint32_t ts_angle_last = 0;
|
||||
|
||||
int controls_allowed_last = 0;
|
||||
|
||||
int to_signed(int d, int bits) {
|
||||
if (d >= (1 << (bits - 1))) {
|
||||
d -= (1 << bits);
|
||||
}
|
||||
return d;
|
||||
}
|
||||
|
||||
// interp function that holds extreme values
|
||||
float interpolate(struct lookup_t xy, float x) {
|
||||
int size = sizeof(xy.x) / sizeof(xy.x[0]);
|
||||
@@ -187,7 +180,7 @@ const safety_hooks toyota_ipas_hooks = {
|
||||
.rx = toyota_ipas_rx_hook,
|
||||
.tx = toyota_ipas_tx_hook,
|
||||
.tx_lin = toyota_tx_lin_hook,
|
||||
.ignition = toyota_ign_hook,
|
||||
.ignition = default_ign_hook,
|
||||
.fwd = toyota_fwd_hook,
|
||||
};
|
||||
|
||||
|
||||
BIN
panda/buy.png
BIN
panda/buy.png
Binary file not shown.
|
Before Width: | Height: | Size: 4.0 KiB After Width: | Height: | Size: 12 KiB |
BIN
panda/panda.png
BIN
panda/panda.png
Binary file not shown.
|
Before Width: | Height: | Size: 71 KiB After Width: | Height: | Size: 71 KiB |
@@ -15,7 +15,7 @@ from update import ensure_st_up_to_date
|
||||
from serial import PandaSerial
|
||||
from isotp import isotp_send, isotp_recv
|
||||
|
||||
__version__ = '0.0.7'
|
||||
__version__ = '0.0.8'
|
||||
|
||||
BASEDIR = os.path.join(os.path.dirname(os.path.realpath(__file__)), "../")
|
||||
|
||||
|
||||
17
panda/tests/gmbitbang/recv.py
Executable file
17
panda/tests/gmbitbang/recv.py
Executable file
@@ -0,0 +1,17 @@
|
||||
#!/usr/bin/env python
|
||||
import time
|
||||
from panda import Panda
|
||||
|
||||
p = Panda()
|
||||
p.set_safety_mode(Panda.SAFETY_ALLOUTPUT)
|
||||
p.set_gmlan(bus=2)
|
||||
#p.can_send(0xaaa, "\x00\x00", bus=3)
|
||||
last_add = None
|
||||
while 1:
|
||||
ret = p.can_recv()
|
||||
if len(ret) > 0:
|
||||
add = ret[0][0]
|
||||
if last_add is not None and add != last_add+1:
|
||||
print "MISS %d %d" % (last_add, add)
|
||||
last_add = add
|
||||
print ret
|
||||
35
panda/tests/gmbitbang/rigol.py
Executable file
35
panda/tests/gmbitbang/rigol.py
Executable file
@@ -0,0 +1,35 @@
|
||||
#!/usr/bin/env python
|
||||
import numpy as np
|
||||
import visa
|
||||
import matplotlib.pyplot as plt
|
||||
|
||||
resources = visa.ResourceManager()
|
||||
print resources.list_resources()
|
||||
|
||||
scope = resources.open_resource('USB0::0x1AB1::0x04CE::DS1ZA184652242::INSTR', timeout=2000, chunk_size=1024000)
|
||||
print(scope.query('*IDN?').strip())
|
||||
|
||||
#voltscale = scope.ask_for_values(':CHAN1:SCAL?')[0]
|
||||
#voltoffset = scope.ask_for_values(":CHAN1:OFFS?")[0]
|
||||
|
||||
#scope.write(":STOP")
|
||||
scope.write(":WAV:POIN:MODE RAW")
|
||||
scope.write(":WAV:DATA? CHAN1")[10:]
|
||||
rawdata = scope.read_raw()
|
||||
data = np.frombuffer(rawdata, 'B')
|
||||
print data.shape
|
||||
|
||||
s1 = data[0:650]
|
||||
s2 = data[650:]
|
||||
s1i = np.argmax(s1 > 100)
|
||||
s2i = np.argmax(s2 > 100)
|
||||
s1 = s1[s1i:]
|
||||
s2 = s2[s2i:]
|
||||
|
||||
plt.plot(s1)
|
||||
plt.plot(s2)
|
||||
plt.show()
|
||||
#data = (data - 130.0 - voltoffset/voltscale*25) / 25 * voltscale
|
||||
|
||||
print data
|
||||
|
||||
33
panda/tests/gmbitbang/test.py
Executable file
33
panda/tests/gmbitbang/test.py
Executable file
@@ -0,0 +1,33 @@
|
||||
#!/usr/bin/env python
|
||||
import time
|
||||
from panda import Panda
|
||||
|
||||
p1 = Panda('380016000551363338383037')
|
||||
p2 = Panda('430026000951363338383037')
|
||||
|
||||
# this is a test, no safety
|
||||
p1.set_safety_mode(Panda.SAFETY_ALLOUTPUT)
|
||||
p2.set_safety_mode(Panda.SAFETY_ALLOUTPUT)
|
||||
|
||||
# get versions
|
||||
print(p1.get_version())
|
||||
print(p2.get_version())
|
||||
|
||||
# this sets bus 2 to actually be GMLAN
|
||||
p2.set_gmlan(bus=2)
|
||||
|
||||
# send w bitbang then without
|
||||
#iden = 123
|
||||
iden = 18000
|
||||
#dat = "\x01\x02"
|
||||
dat = "\x01\x02\x03\x04\x05\x06\x07\x08"
|
||||
while 1:
|
||||
iden += 1
|
||||
p1.set_gmlan(bus=None)
|
||||
p1.can_send(iden, dat, bus=3)
|
||||
#p1.set_gmlan(bus=2)
|
||||
#p1.can_send(iden, dat, bus=3)
|
||||
time.sleep(0.01)
|
||||
print p2.can_recv()
|
||||
#exit(0)
|
||||
|
||||
23
panda/tests/gmbitbang/test_one.py
Executable file
23
panda/tests/gmbitbang/test_one.py
Executable file
@@ -0,0 +1,23 @@
|
||||
#!/usr/bin/env python
|
||||
import time
|
||||
from panda import Panda
|
||||
|
||||
p = Panda()
|
||||
p.set_safety_mode(Panda.SAFETY_ALLOUTPUT)
|
||||
|
||||
# ack any crap on bus
|
||||
p.set_gmlan(bus=2)
|
||||
time.sleep(0.1)
|
||||
while len(p.can_recv()) > 0:
|
||||
print "clearing"
|
||||
time.sleep(0.1)
|
||||
print "cleared"
|
||||
p.set_gmlan(bus=None)
|
||||
|
||||
iden = 18000
|
||||
dat = "\x01\x02\x03\x04\x05\x06\x07\x08"
|
||||
while 1:
|
||||
iden += 1
|
||||
p.can_send(iden, dat, bus=3)
|
||||
time.sleep(0.01)
|
||||
|
||||
32
panda/tests/gmbitbang/test_packer.c
Normal file
32
panda/tests/gmbitbang/test_packer.c
Normal file
@@ -0,0 +1,32 @@
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
|
||||
typedef struct {
|
||||
uint32_t RIR; /*!< CAN receive FIFO mailbox identifier register */
|
||||
uint32_t RDTR; /*!< CAN receive FIFO mailbox data length control and time stamp register */
|
||||
uint32_t RDLR; /*!< CAN receive FIFO mailbox data low register */
|
||||
uint32_t RDHR; /*!< CAN receive FIFO mailbox data high register */
|
||||
} CAN_FIFOMailBox_TypeDef;
|
||||
|
||||
#include "../../board/drivers/canbitbang.h"
|
||||
|
||||
int main() {
|
||||
char out[300];
|
||||
CAN_FIFOMailBox_TypeDef to_bang = {0};
|
||||
to_bang.RIR = 20 << 21;
|
||||
to_bang.RDTR = 1;
|
||||
to_bang.RDLR = 1;
|
||||
|
||||
int len = get_bit_message(out, &to_bang);
|
||||
printf("T:");
|
||||
for (int i = 0; i < len; i++) {
|
||||
printf("%d", out[i]);
|
||||
}
|
||||
printf("\n");
|
||||
printf("R:0000010010100000100010000010011110111010100111111111111111");
|
||||
printf("\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -39,6 +39,8 @@ int get_controls_allowed(void);
|
||||
void init_tests_toyota(void);
|
||||
void set_timer(int t);
|
||||
void set_torque_meas(int min, int max);
|
||||
void set_cadillac_torque_driver(int min, int max);
|
||||
void set_gm_torque_driver(int min, int max);
|
||||
void set_rt_torque_last(int t);
|
||||
void set_desired_torque_last(int t);
|
||||
int get_torque_meas_min(void);
|
||||
@@ -51,6 +53,22 @@ void honda_rx_hook(CAN_FIFOMailBox_TypeDef *to_push);
|
||||
int honda_tx_hook(CAN_FIFOMailBox_TypeDef *to_send);
|
||||
int get_brake_prev(void);
|
||||
int get_gas_prev(void);
|
||||
void set_honda_alt_brake_msg(bool);
|
||||
void set_bosch_hardware(bool);
|
||||
|
||||
void init_tests_cadillac(void);
|
||||
void cadillac_init(int16_t param);
|
||||
void cadillac_rx_hook(CAN_FIFOMailBox_TypeDef *to_push);
|
||||
int cadillac_tx_hook(CAN_FIFOMailBox_TypeDef *to_send);
|
||||
void set_cadillac_desired_torque_last(int t);
|
||||
void set_cadillac_rt_torque_last(int t);
|
||||
|
||||
void init_tests_gm(void);
|
||||
void gm_init(int16_t param);
|
||||
void gm_rx_hook(CAN_FIFOMailBox_TypeDef *to_push);
|
||||
int gm_tx_hook(CAN_FIFOMailBox_TypeDef *to_send);
|
||||
void set_gm_desired_torque_last(int t);
|
||||
void set_gm_rt_torque_last(int t);
|
||||
|
||||
void toyota_ipas_rx_hook(CAN_FIFOMailBox_TypeDef *to_push);
|
||||
int toyota_ipas_tx_hook(CAN_FIFOMailBox_TypeDef *to_send);
|
||||
|
||||
@@ -23,6 +23,8 @@ typedef struct
|
||||
} TIM_TypeDef;
|
||||
|
||||
struct sample_t torque_meas;
|
||||
struct sample_t cadillac_torque_driver;
|
||||
struct sample_t gm_torque_driver;
|
||||
|
||||
TIM_TypeDef timer;
|
||||
TIM_TypeDef *TIM2 = &timer;
|
||||
@@ -63,6 +65,16 @@ void set_torque_meas(int min, int max){
|
||||
torque_meas.max = max;
|
||||
}
|
||||
|
||||
void set_cadillac_torque_driver(int min, int max){
|
||||
cadillac_torque_driver.min = min;
|
||||
cadillac_torque_driver.max = max;
|
||||
}
|
||||
|
||||
void set_gm_torque_driver(int min, int max){
|
||||
gm_torque_driver.min = min;
|
||||
gm_torque_driver.max = max;
|
||||
}
|
||||
|
||||
int get_torque_meas_min(void){
|
||||
return torque_meas.min;
|
||||
}
|
||||
@@ -75,10 +87,27 @@ void set_rt_torque_last(int t){
|
||||
rt_torque_last = t;
|
||||
}
|
||||
|
||||
void set_cadillac_rt_torque_last(int t){
|
||||
cadillac_rt_torque_last = t;
|
||||
}
|
||||
|
||||
void set_gm_rt_torque_last(int t){
|
||||
gm_rt_torque_last = t;
|
||||
}
|
||||
|
||||
void set_desired_torque_last(int t){
|
||||
desired_torque_last = t;
|
||||
}
|
||||
|
||||
void set_cadillac_desired_torque_last(int t){
|
||||
for (int i = 0; i < 4; i++) cadillac_desired_torque_last[i] = t;
|
||||
}
|
||||
|
||||
void set_gm_desired_torque_last(int t){
|
||||
gm_desired_torque_last = t;
|
||||
}
|
||||
|
||||
|
||||
int get_ego_speed(void){
|
||||
return ego_speed;
|
||||
}
|
||||
@@ -91,6 +120,14 @@ int get_gas_prev(void){
|
||||
return gas_prev;
|
||||
}
|
||||
|
||||
void set_honda_alt_brake_msg(bool c){
|
||||
honda_alt_brake_msg = c;
|
||||
}
|
||||
|
||||
void set_bosch_hardware(bool c){
|
||||
bosch_hardware = c;
|
||||
}
|
||||
|
||||
void init_tests_toyota(void){
|
||||
torque_meas.min = 0;
|
||||
torque_meas.max = 0;
|
||||
@@ -100,6 +137,24 @@ void init_tests_toyota(void){
|
||||
set_timer(0);
|
||||
}
|
||||
|
||||
void init_tests_cadillac(void){
|
||||
cadillac_torque_driver.min = 0;
|
||||
cadillac_torque_driver.max = 0;
|
||||
for (int i = 0; i < 4; i++) cadillac_desired_torque_last[i] = 0;
|
||||
cadillac_rt_torque_last = 0;
|
||||
cadillac_ts_last = 0;
|
||||
set_timer(0);
|
||||
}
|
||||
|
||||
void init_tests_gm(void){
|
||||
gm_torque_driver.min = 0;
|
||||
gm_torque_driver.max = 0;
|
||||
gm_desired_torque_last = 0;
|
||||
gm_rt_torque_last = 0;
|
||||
gm_ts_last = 0;
|
||||
set_timer(0);
|
||||
}
|
||||
|
||||
void init_tests_honda(void){
|
||||
ego_speed = 0;
|
||||
gas_interceptor_detected = 0;
|
||||
|
||||
182
panda/tests/safety/test_cadillac.py
Normal file
182
panda/tests/safety/test_cadillac.py
Normal file
@@ -0,0 +1,182 @@
|
||||
#!/usr/bin/env python2
|
||||
import unittest
|
||||
import numpy as np
|
||||
import libpandasafety_py
|
||||
|
||||
MAX_RATE_UP = 2
|
||||
MAX_RATE_DOWN = 5
|
||||
MAX_TORQUE = 150
|
||||
|
||||
MAX_RT_DELTA = 75
|
||||
RT_INTERVAL = 250000
|
||||
|
||||
DRIVER_TORQUE_ALLOWANCE = 50;
|
||||
DRIVER_TORQUE_FACTOR = 4;
|
||||
|
||||
IPAS_OVERRIDE_THRESHOLD = 200
|
||||
|
||||
def twos_comp(val, bits):
|
||||
if val >= 0:
|
||||
return val
|
||||
else:
|
||||
return (2**bits) + val
|
||||
|
||||
def sign(a):
|
||||
if a > 0:
|
||||
return 1
|
||||
else:
|
||||
return -1
|
||||
|
||||
class TestCadillacSafety(unittest.TestCase):
|
||||
@classmethod
|
||||
def setUp(cls):
|
||||
cls.safety = libpandasafety_py.libpandasafety
|
||||
cls.safety.cadillac_init(0)
|
||||
cls.safety.init_tests_cadillac()
|
||||
|
||||
def _set_prev_torque(self, t):
|
||||
self.safety.set_cadillac_desired_torque_last(t)
|
||||
self.safety.set_cadillac_rt_torque_last(t)
|
||||
|
||||
def _torque_driver_msg(self, torque):
|
||||
to_send = libpandasafety_py.ffi.new('CAN_FIFOMailBox_TypeDef *')
|
||||
to_send[0].RIR = 0x164 << 21
|
||||
|
||||
t = twos_comp(torque, 11)
|
||||
to_send[0].RDLR = ((t >> 8) & 0x7) | ((t & 0xFF) << 8)
|
||||
return to_send
|
||||
|
||||
def _torque_driver_msg_array(self, torque):
|
||||
for i in range(3):
|
||||
self.safety.cadillac_ipas_rx_hook(self._torque_driver_msg(torque))
|
||||
|
||||
def _torque_msg(self, torque):
|
||||
to_send = libpandasafety_py.ffi.new('CAN_FIFOMailBox_TypeDef *')
|
||||
to_send[0].RIR = 0x151 << 21
|
||||
|
||||
t = twos_comp(torque, 14)
|
||||
to_send[0].RDLR = ((t >> 8) & 0x3F) | ((t & 0xFF) << 8)
|
||||
return to_send
|
||||
|
||||
def test_default_controls_not_allowed(self):
|
||||
self.assertFalse(self.safety.get_controls_allowed())
|
||||
|
||||
def test_manually_enable_controls_allowed(self):
|
||||
self.safety.set_controls_allowed(1)
|
||||
self.assertTrue(self.safety.get_controls_allowed())
|
||||
self.safety.set_controls_allowed(0)
|
||||
|
||||
def test_enable_control_allowed_from_cruise(self):
|
||||
to_push = libpandasafety_py.ffi.new('CAN_FIFOMailBox_TypeDef *')
|
||||
to_push[0].RIR = 0x370 << 21
|
||||
to_push[0].RDLR = 0x800000
|
||||
to_push[0].RDTR = 0
|
||||
|
||||
self.safety.cadillac_rx_hook(to_push)
|
||||
self.assertTrue(self.safety.get_controls_allowed())
|
||||
|
||||
def test_disable_control_allowed_from_cruise(self):
|
||||
to_push = libpandasafety_py.ffi.new('CAN_FIFOMailBox_TypeDef *')
|
||||
to_push[0].RIR = 0x370 << 21
|
||||
to_push[0].RDLR = 0
|
||||
to_push[0].RDTR = 0
|
||||
|
||||
self.safety.set_controls_allowed(1)
|
||||
self.safety.cadillac_rx_hook(to_push)
|
||||
self.assertFalse(self.safety.get_controls_allowed())
|
||||
|
||||
def test_torque_absolute_limits(self):
|
||||
for controls_allowed in [True, False]:
|
||||
for torque in np.arange(-MAX_TORQUE - 1000, MAX_TORQUE + 1000, MAX_RATE_UP):
|
||||
self.safety.set_controls_allowed(controls_allowed)
|
||||
self.safety.set_cadillac_rt_torque_last(torque)
|
||||
self.safety.set_cadillac_torque_driver(0, 0)
|
||||
self.safety.set_cadillac_desired_torque_last(torque - MAX_RATE_UP)
|
||||
|
||||
if controls_allowed:
|
||||
send = (-MAX_TORQUE <= torque <= MAX_TORQUE)
|
||||
else:
|
||||
send = torque == 0
|
||||
|
||||
self.assertEqual(send, self.safety.cadillac_tx_hook(self._torque_msg(torque)))
|
||||
|
||||
def test_non_realtime_limit_up(self):
|
||||
self.safety.set_cadillac_torque_driver(0, 0)
|
||||
self.safety.set_controls_allowed(True)
|
||||
|
||||
self._set_prev_torque(0)
|
||||
self.assertTrue(self.safety.cadillac_tx_hook(self._torque_msg(MAX_RATE_UP)))
|
||||
self._set_prev_torque(0)
|
||||
self.assertTrue(self.safety.cadillac_tx_hook(self._torque_msg(-MAX_RATE_UP)))
|
||||
|
||||
self._set_prev_torque(0)
|
||||
self.assertFalse(self.safety.cadillac_tx_hook(self._torque_msg(MAX_RATE_UP + 1)))
|
||||
self.safety.set_controls_allowed(True)
|
||||
self._set_prev_torque(0)
|
||||
self.assertFalse(self.safety.cadillac_tx_hook(self._torque_msg(-MAX_RATE_UP - 1)))
|
||||
|
||||
def test_non_realtime_limit_down(self):
|
||||
self.safety.set_cadillac_torque_driver(0, 0)
|
||||
self.safety.set_controls_allowed(True)
|
||||
|
||||
def test_exceed_torque_sensor(self):
|
||||
self.safety.set_controls_allowed(True)
|
||||
|
||||
for sign in [-1, 1]:
|
||||
for t in np.arange(0, DRIVER_TORQUE_ALLOWANCE + 1, 1):
|
||||
t *= -sign
|
||||
self.safety.set_cadillac_torque_driver(t, t)
|
||||
self._set_prev_torque(MAX_TORQUE * sign)
|
||||
self.assertTrue(self.safety.cadillac_tx_hook(self._torque_msg(MAX_TORQUE * sign)))
|
||||
|
||||
self.safety.set_cadillac_torque_driver(DRIVER_TORQUE_ALLOWANCE + 1, DRIVER_TORQUE_ALLOWANCE + 1)
|
||||
self.assertFalse(self.safety.cadillac_tx_hook(self._torque_msg(-MAX_TORQUE)))
|
||||
|
||||
# spot check some individual cases
|
||||
for sign in [-1, 1]:
|
||||
driver_torque = (DRIVER_TORQUE_ALLOWANCE + 10) * sign
|
||||
torque_desired = (MAX_TORQUE - 10 * DRIVER_TORQUE_FACTOR) * sign
|
||||
delta = 1 * sign
|
||||
self._set_prev_torque(torque_desired)
|
||||
self.safety.set_cadillac_torque_driver(-driver_torque, -driver_torque)
|
||||
self.assertTrue(self.safety.cadillac_tx_hook(self._torque_msg(torque_desired)))
|
||||
self._set_prev_torque(torque_desired + delta)
|
||||
self.safety.set_cadillac_torque_driver(-driver_torque, -driver_torque)
|
||||
self.assertFalse(self.safety.cadillac_tx_hook(self._torque_msg(torque_desired + delta)))
|
||||
|
||||
self._set_prev_torque(MAX_TORQUE * sign)
|
||||
self.safety.set_cadillac_torque_driver(-MAX_TORQUE * sign, -MAX_TORQUE * sign)
|
||||
self.assertTrue(self.safety.cadillac_tx_hook(self._torque_msg((MAX_TORQUE - MAX_RATE_DOWN) * sign)))
|
||||
self._set_prev_torque(MAX_TORQUE * sign)
|
||||
self.safety.set_cadillac_torque_driver(-MAX_TORQUE * sign, -MAX_TORQUE * sign)
|
||||
self.assertTrue(self.safety.cadillac_tx_hook(self._torque_msg(0)))
|
||||
self._set_prev_torque(MAX_TORQUE * sign)
|
||||
self.safety.set_cadillac_torque_driver(-MAX_TORQUE * sign, -MAX_TORQUE * sign)
|
||||
self.assertFalse(self.safety.cadillac_tx_hook(self._torque_msg((MAX_TORQUE - MAX_RATE_DOWN + 1) * sign)))
|
||||
|
||||
|
||||
def test_realtime_limits(self):
|
||||
self.safety.set_controls_allowed(True)
|
||||
|
||||
for sign in [-1, 1]:
|
||||
self.safety.init_tests_cadillac()
|
||||
self._set_prev_torque(0)
|
||||
self.safety.set_cadillac_torque_driver(0, 0)
|
||||
for t in np.arange(0, MAX_RT_DELTA, 1):
|
||||
t *= sign
|
||||
self.assertTrue(self.safety.cadillac_tx_hook(self._torque_msg(t)))
|
||||
self.assertFalse(self.safety.cadillac_tx_hook(self._torque_msg(sign * (MAX_RT_DELTA + 1))))
|
||||
|
||||
self._set_prev_torque(0)
|
||||
for t in np.arange(0, MAX_RT_DELTA, 1):
|
||||
t *= sign
|
||||
self.assertTrue(self.safety.cadillac_tx_hook(self._torque_msg(t)))
|
||||
|
||||
# Increase timer to update rt_torque_last
|
||||
self.safety.set_timer(RT_INTERVAL + 1)
|
||||
self.assertTrue(self.safety.cadillac_tx_hook(self._torque_msg(sign * (MAX_RT_DELTA - 1))))
|
||||
self.assertTrue(self.safety.cadillac_tx_hook(self._torque_msg(sign * (MAX_RT_DELTA + 1))))
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
270
panda/tests/safety/test_gm.py
Normal file
270
panda/tests/safety/test_gm.py
Normal file
@@ -0,0 +1,270 @@
|
||||
#!/usr/bin/env python2
|
||||
import unittest
|
||||
import numpy as np
|
||||
import libpandasafety_py
|
||||
|
||||
MAX_RATE_UP = 7
|
||||
MAX_RATE_DOWN = 17
|
||||
MAX_STEER = 255
|
||||
MAX_BRAKE = 350
|
||||
MAX_GAS = 3072
|
||||
MAX_REGEN = 1404
|
||||
|
||||
MAX_RT_DELTA = 128
|
||||
RT_INTERVAL = 250000
|
||||
|
||||
DRIVER_TORQUE_ALLOWANCE = 50;
|
||||
DRIVER_TORQUE_FACTOR = 4;
|
||||
|
||||
def twos_comp(val, bits):
|
||||
if val >= 0:
|
||||
return val
|
||||
else:
|
||||
return (2**bits) + val
|
||||
|
||||
def sign(a):
|
||||
if a > 0:
|
||||
return 1
|
||||
else:
|
||||
return -1
|
||||
|
||||
class TestGmSafety(unittest.TestCase):
|
||||
@classmethod
|
||||
def setUp(cls):
|
||||
cls.safety = libpandasafety_py.libpandasafety
|
||||
cls.safety.gm_init(0)
|
||||
cls.safety.init_tests_gm()
|
||||
|
||||
def _speed_msg(self, speed):
|
||||
to_send = libpandasafety_py.ffi.new('CAN_FIFOMailBox_TypeDef *')
|
||||
to_send[0].RIR = 842 << 21
|
||||
to_send[0].RDLR = speed
|
||||
return to_send
|
||||
|
||||
def _button_msg(self, buttons):
|
||||
to_send = libpandasafety_py.ffi.new('CAN_FIFOMailBox_TypeDef *')
|
||||
to_send[0].RIR = 481 << 21
|
||||
to_send[0].RDHR = buttons << 12
|
||||
return to_send
|
||||
|
||||
def _brake_msg(self, brake):
|
||||
to_send = libpandasafety_py.ffi.new('CAN_FIFOMailBox_TypeDef *')
|
||||
to_send[0].RIR = 241 << 21
|
||||
to_send[0].RDLR = 0xa00 if brake else 0x900
|
||||
return to_send
|
||||
|
||||
def _gas_msg(self, gas):
|
||||
to_send = libpandasafety_py.ffi.new('CAN_FIFOMailBox_TypeDef *')
|
||||
to_send[0].RIR = 417 << 21
|
||||
to_send[0].RDHR = (1 << 16) if gas else 0
|
||||
return to_send
|
||||
|
||||
def _send_brake_msg(self, brake):
|
||||
to_send = libpandasafety_py.ffi.new('CAN_FIFOMailBox_TypeDef *')
|
||||
to_send[0].RIR = 789 << 21
|
||||
brake = (-brake) & 0xfff
|
||||
to_send[0].RDLR = (brake >> 8) | ((brake &0xff) << 8)
|
||||
return to_send
|
||||
|
||||
def _send_gas_msg(self, gas):
|
||||
to_send = libpandasafety_py.ffi.new('CAN_FIFOMailBox_TypeDef *')
|
||||
to_send[0].RIR = 715 << 21
|
||||
to_send[0].RDLR = ((gas & 0x1f) << 27) | ((gas & 0xfe0) << 11)
|
||||
return to_send
|
||||
|
||||
def _set_prev_torque(self, t):
|
||||
self.safety.set_gm_desired_torque_last(t)
|
||||
self.safety.set_gm_rt_torque_last(t)
|
||||
|
||||
def _torque_driver_msg(self, torque):
|
||||
to_send = libpandasafety_py.ffi.new('CAN_FIFOMailBox_TypeDef *')
|
||||
to_send[0].RIR = 388 << 21
|
||||
|
||||
t = twos_comp(torque, 11)
|
||||
to_send[0].RDHR = (((t >> 8) & 0x7) << 16) | ((t & 0xFF) << 24)
|
||||
return to_send
|
||||
|
||||
def _torque_driver_msg_array(self, torque):
|
||||
for i in range(3):
|
||||
self.safety.gm_ipas_rx_hook(self._torque_driver_msg(torque))
|
||||
|
||||
def _torque_msg(self, torque):
|
||||
to_send = libpandasafety_py.ffi.new('CAN_FIFOMailBox_TypeDef *')
|
||||
to_send[0].RIR = 384 << 21
|
||||
|
||||
t = twos_comp(torque, 11)
|
||||
to_send[0].RDLR = ((t >> 8) & 0x7) | ((t & 0xFF) << 8)
|
||||
return to_send
|
||||
|
||||
def test_default_controls_not_allowed(self):
|
||||
self.assertFalse(self.safety.get_controls_allowed())
|
||||
|
||||
def test_resume_button(self):
|
||||
RESUME_BTN = 2
|
||||
self.safety.set_controls_allowed(0)
|
||||
self.safety.gm_rx_hook(self._button_msg(RESUME_BTN))
|
||||
self.assertTrue(self.safety.get_controls_allowed())
|
||||
|
||||
def test_set_button(self):
|
||||
SET_BTN = 3
|
||||
self.safety.set_controls_allowed(0)
|
||||
self.safety.gm_rx_hook(self._button_msg(SET_BTN))
|
||||
self.assertTrue(self.safety.get_controls_allowed())
|
||||
|
||||
def test_cancel_button(self):
|
||||
CANCEL_BTN = 6
|
||||
self.safety.set_controls_allowed(1)
|
||||
self.safety.gm_rx_hook(self._button_msg(CANCEL_BTN))
|
||||
self.assertFalse(self.safety.get_controls_allowed())
|
||||
|
||||
def test_disengage_on_brake(self):
|
||||
self.safety.set_controls_allowed(1)
|
||||
self.safety.gm_rx_hook(self._brake_msg(True))
|
||||
self.assertFalse(self.safety.get_controls_allowed())
|
||||
|
||||
def test_allow_brake_at_zero_speed(self):
|
||||
# Brake was already pressed
|
||||
self.safety.gm_rx_hook(self._brake_msg(True))
|
||||
self.safety.set_controls_allowed(1)
|
||||
|
||||
self.safety.gm_rx_hook(self._brake_msg(True))
|
||||
self.assertTrue(self.safety.get_controls_allowed())
|
||||
self.safety.gm_rx_hook(self._brake_msg(False))
|
||||
|
||||
def test_not_allow_brake_when_moving(self):
|
||||
# Brake was already pressed
|
||||
self.safety.gm_rx_hook(self._brake_msg(True))
|
||||
self.safety.gm_rx_hook(self._speed_msg(100))
|
||||
self.safety.set_controls_allowed(1)
|
||||
|
||||
self.safety.gm_rx_hook(self._brake_msg(True))
|
||||
self.assertFalse(self.safety.get_controls_allowed())
|
||||
self.safety.gm_rx_hook(self._brake_msg(False))
|
||||
|
||||
def test_disengage_on_gas(self):
|
||||
self.safety.set_controls_allowed(1)
|
||||
self.safety.gm_rx_hook(self._gas_msg(True))
|
||||
self.assertFalse(self.safety.get_controls_allowed())
|
||||
self.safety.gm_rx_hook(self._gas_msg(False))
|
||||
|
||||
def test_allow_engage_with_gas_pressed(self):
|
||||
self.safety.gm_rx_hook(self._gas_msg(True))
|
||||
self.safety.set_controls_allowed(1)
|
||||
self.safety.gm_rx_hook(self._gas_msg(True))
|
||||
self.assertTrue(self.safety.get_controls_allowed())
|
||||
self.safety.gm_rx_hook(self._gas_msg(False))
|
||||
|
||||
def test_brake_safety_check(self):
|
||||
for enabled in [0, 1]:
|
||||
for b in range(0, 500):
|
||||
self.safety.set_controls_allowed(enabled)
|
||||
if abs(b) > MAX_BRAKE or (not enabled and b != 0):
|
||||
self.assertFalse(self.safety.gm_tx_hook(self._send_brake_msg(b)))
|
||||
else:
|
||||
self.assertTrue(self.safety.gm_tx_hook(self._send_brake_msg(b)))
|
||||
|
||||
def test_gas_safety_check(self):
|
||||
for enabled in [0, 1]:
|
||||
for g in range(0, 2**12-1):
|
||||
self.safety.set_controls_allowed(enabled)
|
||||
if abs(g) > MAX_GAS or (not enabled and g != MAX_REGEN):
|
||||
self.assertFalse(self.safety.gm_tx_hook(self._send_gas_msg(g)))
|
||||
else:
|
||||
self.assertTrue(self.safety.gm_tx_hook(self._send_gas_msg(g)))
|
||||
|
||||
def test_steer_safety_check(self):
|
||||
for enabled in [0, 1]:
|
||||
for t in range(-0x200, 0x200):
|
||||
self.safety.set_controls_allowed(enabled)
|
||||
self._set_prev_torque(t)
|
||||
if abs(t) > MAX_STEER or (not enabled and abs(t) > 0):
|
||||
self.assertFalse(self.safety.gm_tx_hook(self._torque_msg(t)))
|
||||
else:
|
||||
self.assertTrue(self.safety.gm_tx_hook(self._torque_msg(t)))
|
||||
|
||||
def test_manually_enable_controls_allowed(self):
|
||||
self.safety.set_controls_allowed(1)
|
||||
self.assertTrue(self.safety.get_controls_allowed())
|
||||
self.safety.set_controls_allowed(0)
|
||||
self.assertFalse(self.safety.get_controls_allowed())
|
||||
|
||||
def test_non_realtime_limit_up(self):
|
||||
self.safety.set_gm_torque_driver(0, 0)
|
||||
self.safety.set_controls_allowed(True)
|
||||
|
||||
self._set_prev_torque(0)
|
||||
self.assertTrue(self.safety.gm_tx_hook(self._torque_msg(MAX_RATE_UP)))
|
||||
self._set_prev_torque(0)
|
||||
self.assertTrue(self.safety.gm_tx_hook(self._torque_msg(-MAX_RATE_UP)))
|
||||
|
||||
self._set_prev_torque(0)
|
||||
self.assertFalse(self.safety.gm_tx_hook(self._torque_msg(MAX_RATE_UP + 1)))
|
||||
self.safety.set_controls_allowed(True)
|
||||
self._set_prev_torque(0)
|
||||
self.assertFalse(self.safety.gm_tx_hook(self._torque_msg(-MAX_RATE_UP - 1)))
|
||||
|
||||
def test_non_realtime_limit_down(self):
|
||||
self.safety.set_gm_torque_driver(0, 0)
|
||||
self.safety.set_controls_allowed(True)
|
||||
|
||||
def test_against_torque_driver(self):
|
||||
self.safety.set_controls_allowed(True)
|
||||
|
||||
for sign in [-1, 1]:
|
||||
for t in np.arange(0, DRIVER_TORQUE_ALLOWANCE + 1, 1):
|
||||
t *= -sign
|
||||
self.safety.set_gm_torque_driver(t, t)
|
||||
self._set_prev_torque(MAX_STEER * sign)
|
||||
self.assertTrue(self.safety.gm_tx_hook(self._torque_msg(MAX_STEER * sign)))
|
||||
|
||||
self.safety.set_gm_torque_driver(DRIVER_TORQUE_ALLOWANCE + 1, DRIVER_TORQUE_ALLOWANCE + 1)
|
||||
self.assertFalse(self.safety.gm_tx_hook(self._torque_msg(-MAX_STEER)))
|
||||
|
||||
# spot check some individual cases
|
||||
for sign in [-1, 1]:
|
||||
driver_torque = (DRIVER_TORQUE_ALLOWANCE + 10) * sign
|
||||
torque_desired = (MAX_STEER - 10 * DRIVER_TORQUE_FACTOR) * sign
|
||||
delta = 1 * sign
|
||||
self._set_prev_torque(torque_desired)
|
||||
self.safety.set_gm_torque_driver(-driver_torque, -driver_torque)
|
||||
self.assertTrue(self.safety.gm_tx_hook(self._torque_msg(torque_desired)))
|
||||
self._set_prev_torque(torque_desired + delta)
|
||||
self.safety.set_gm_torque_driver(-driver_torque, -driver_torque)
|
||||
self.assertFalse(self.safety.gm_tx_hook(self._torque_msg(torque_desired + delta)))
|
||||
|
||||
self._set_prev_torque(MAX_STEER * sign)
|
||||
self.safety.set_gm_torque_driver(-MAX_STEER * sign, -MAX_STEER * sign)
|
||||
self.assertTrue(self.safety.gm_tx_hook(self._torque_msg((MAX_STEER - MAX_RATE_DOWN) * sign)))
|
||||
self._set_prev_torque(MAX_STEER * sign)
|
||||
self.safety.set_gm_torque_driver(-MAX_STEER * sign, -MAX_STEER * sign)
|
||||
self.assertTrue(self.safety.gm_tx_hook(self._torque_msg(0)))
|
||||
self._set_prev_torque(MAX_STEER * sign)
|
||||
self.safety.set_gm_torque_driver(-MAX_STEER * sign, -MAX_STEER * sign)
|
||||
self.assertFalse(self.safety.gm_tx_hook(self._torque_msg((MAX_STEER - MAX_RATE_DOWN + 1) * sign)))
|
||||
|
||||
|
||||
def test_realtime_limits(self):
|
||||
self.safety.set_controls_allowed(True)
|
||||
|
||||
for sign in [-1, 1]:
|
||||
self.safety.init_tests_gm()
|
||||
self._set_prev_torque(0)
|
||||
self.safety.set_gm_torque_driver(0, 0)
|
||||
for t in np.arange(0, MAX_RT_DELTA, 1):
|
||||
t *= sign
|
||||
self.assertTrue(self.safety.gm_tx_hook(self._torque_msg(t)))
|
||||
self.assertFalse(self.safety.gm_tx_hook(self._torque_msg(sign * (MAX_RT_DELTA + 1))))
|
||||
|
||||
self._set_prev_torque(0)
|
||||
for t in np.arange(0, MAX_RT_DELTA, 1):
|
||||
t *= sign
|
||||
self.assertTrue(self.safety.gm_tx_hook(self._torque_msg(t)))
|
||||
|
||||
# Increase timer to update rt_torque_last
|
||||
self.safety.set_timer(RT_INTERVAL + 1)
|
||||
self.assertTrue(self.safety.gm_tx_hook(self._torque_msg(sign * (MAX_RT_DELTA - 1))))
|
||||
self.assertTrue(self.safety.gm_tx_hook(self._torque_msg(sign * (MAX_RT_DELTA + 1))))
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
@@ -18,9 +18,9 @@ class TestHondaSafety(unittest.TestCase):
|
||||
|
||||
return to_send
|
||||
|
||||
def _button_msg(self, buttons):
|
||||
def _button_msg(self, buttons, msg):
|
||||
to_send = libpandasafety_py.ffi.new('CAN_FIFOMailBox_TypeDef *')
|
||||
to_send[0].RIR = 0x1A6 << 21
|
||||
to_send[0].RIR = msg << 21
|
||||
to_send[0].RDLR = buttons << 5
|
||||
|
||||
return to_send
|
||||
@@ -32,6 +32,13 @@ class TestHondaSafety(unittest.TestCase):
|
||||
|
||||
return to_send
|
||||
|
||||
def _alt_brake_msg(self, brake):
|
||||
to_send = libpandasafety_py.ffi.new('CAN_FIFOMailBox_TypeDef *')
|
||||
to_send[0].RIR = 0x1BE << 21
|
||||
to_send[0].RDLR = 0x10 if brake else 0
|
||||
|
||||
return to_send
|
||||
|
||||
def _gas_msg(self, gas):
|
||||
to_send = libpandasafety_py.ffi.new('CAN_FIFOMailBox_TypeDef *')
|
||||
to_send[0].RIR = 0x17C << 21
|
||||
@@ -65,18 +72,20 @@ class TestHondaSafety(unittest.TestCase):
|
||||
|
||||
def test_resume_button(self):
|
||||
RESUME_BTN = 4
|
||||
self.safety.honda_rx_hook(self._button_msg(RESUME_BTN))
|
||||
self.safety.set_controls_allowed(0)
|
||||
self.safety.honda_rx_hook(self._button_msg(RESUME_BTN, 0x1A6))
|
||||
self.assertTrue(self.safety.get_controls_allowed())
|
||||
|
||||
def test_set_button(self):
|
||||
SET_BTN = 3
|
||||
self.safety.honda_rx_hook(self._button_msg(SET_BTN))
|
||||
self.safety.set_controls_allowed(0)
|
||||
self.safety.honda_rx_hook(self._button_msg(SET_BTN, 0x1A6))
|
||||
self.assertTrue(self.safety.get_controls_allowed())
|
||||
|
||||
def test_cancel_button(self):
|
||||
CANCEL_BTN = 2
|
||||
self.safety.set_controls_allowed(1)
|
||||
self.safety.honda_rx_hook(self._button_msg(CANCEL_BTN))
|
||||
self.safety.honda_rx_hook(self._button_msg(CANCEL_BTN, 0x1A6))
|
||||
self.assertFalse(self.safety.get_controls_allowed())
|
||||
|
||||
def test_sample_speed(self):
|
||||
@@ -94,6 +103,17 @@ class TestHondaSafety(unittest.TestCase):
|
||||
self.safety.honda_rx_hook(self._brake_msg(1))
|
||||
self.assertFalse(self.safety.get_controls_allowed())
|
||||
|
||||
def test_alt_disengage_on_brake(self):
|
||||
self.safety.set_honda_alt_brake_msg(1)
|
||||
self.safety.set_controls_allowed(1)
|
||||
self.safety.honda_rx_hook(self._alt_brake_msg(1))
|
||||
self.assertFalse(self.safety.get_controls_allowed())
|
||||
|
||||
self.safety.set_honda_alt_brake_msg(0)
|
||||
self.safety.set_controls_allowed(1)
|
||||
self.safety.honda_rx_hook(self._alt_brake_msg(1))
|
||||
self.assertTrue(self.safety.get_controls_allowed())
|
||||
|
||||
def test_allow_brake_at_zero_speed(self):
|
||||
# Brake was already pressed
|
||||
self.safety.honda_rx_hook(self._brake_msg(True))
|
||||
@@ -101,6 +121,7 @@ class TestHondaSafety(unittest.TestCase):
|
||||
|
||||
self.safety.honda_rx_hook(self._brake_msg(True))
|
||||
self.assertTrue(self.safety.get_controls_allowed())
|
||||
self.safety.honda_rx_hook(self._brake_msg(False)) # reset no brakes
|
||||
|
||||
def test_not_allow_brake_when_moving(self):
|
||||
# Brake was already pressed
|
||||
@@ -136,13 +157,29 @@ class TestHondaSafety(unittest.TestCase):
|
||||
self.assertFalse(self.safety.honda_tx_hook(self._send_brake_msg(0x00F0)))
|
||||
|
||||
def test_gas_safety_check(self):
|
||||
self.assertTrue(self.safety.honda_tx_hook(self._send_brake_msg(0x0000)))
|
||||
self.assertFalse(self.safety.honda_tx_hook(self._send_brake_msg(0x1000)))
|
||||
self.safety.set_controls_allowed(0)
|
||||
self.assertTrue(self.safety.honda_tx_hook(self._send_gas_msg(0x0000)))
|
||||
self.assertFalse(self.safety.honda_tx_hook(self._send_gas_msg(0x1000)))
|
||||
|
||||
def test_steer_safety_check(self):
|
||||
self.safety.set_controls_allowed(0)
|
||||
self.assertTrue(self.safety.honda_tx_hook(self._send_steer_msg(0x0000)))
|
||||
self.assertFalse(self.safety.honda_tx_hook(self._send_steer_msg(0x1000)))
|
||||
|
||||
def test_spam_cancel_safety_check(self):
|
||||
RESUME_BTN = 4
|
||||
SET_BTN = 3
|
||||
CANCEL_BTN = 2
|
||||
BUTTON_MSG = 0x296
|
||||
self.safety.set_bosch_hardware(1)
|
||||
self.safety.set_controls_allowed(0)
|
||||
self.assertTrue(self.safety.honda_tx_hook(self._button_msg(CANCEL_BTN, BUTTON_MSG)))
|
||||
self.assertFalse(self.safety.honda_tx_hook(self._button_msg(RESUME_BTN, BUTTON_MSG)))
|
||||
self.assertFalse(self.safety.honda_tx_hook(self._button_msg(SET_BTN, BUTTON_MSG)))
|
||||
# do not block resume if we are engaged already
|
||||
self.safety.set_controls_allowed(1)
|
||||
self.assertTrue(self.safety.honda_tx_hook(self._button_msg(RESUME_BTN, BUTTON_MSG)))
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
|
||||
@@ -62,7 +62,7 @@ class TestToyotaSafety(unittest.TestCase):
|
||||
return to_send
|
||||
|
||||
def _torque_driver_msg_array(self, torque):
|
||||
for i in range(3):
|
||||
for i in range(6):
|
||||
self.safety.toyota_ipas_rx_hook(self._torque_driver_msg(torque))
|
||||
|
||||
def _angle_meas_msg(self, angle):
|
||||
@@ -74,7 +74,7 @@ class TestToyotaSafety(unittest.TestCase):
|
||||
return to_send
|
||||
|
||||
def _angle_meas_msg_array(self, angle):
|
||||
for i in range(3):
|
||||
for i in range(6):
|
||||
self.safety.toyota_ipas_rx_hook(self._angle_meas_msg(angle))
|
||||
|
||||
def _torque_msg(self, torque):
|
||||
@@ -229,6 +229,9 @@ class TestToyotaSafety(unittest.TestCase):
|
||||
self.safety.toyota_rx_hook(self._torque_meas_msg(50))
|
||||
self.safety.toyota_rx_hook(self._torque_meas_msg(-50))
|
||||
self.safety.toyota_rx_hook(self._torque_meas_msg(0))
|
||||
self.safety.toyota_rx_hook(self._torque_meas_msg(0))
|
||||
self.safety.toyota_rx_hook(self._torque_meas_msg(0))
|
||||
self.safety.toyota_rx_hook(self._torque_meas_msg(0))
|
||||
|
||||
self.assertEqual(-51, self.safety.get_torque_meas_min())
|
||||
self.assertEqual(51, self.safety.get_torque_meas_max())
|
||||
|
||||
BIN
phonelibs/capnp-cpp/aarch64/bin/capnp
Executable file
BIN
phonelibs/capnp-cpp/aarch64/bin/capnp
Executable file
Binary file not shown.
1
phonelibs/capnp-cpp/aarch64/bin/capnpc
Symbolic link
1
phonelibs/capnp-cpp/aarch64/bin/capnpc
Symbolic link
@@ -0,0 +1 @@
|
||||
capnp
|
||||
BIN
phonelibs/capnp-cpp/aarch64/bin/capnpc-c++
Executable file
BIN
phonelibs/capnp-cpp/aarch64/bin/capnpc-c++
Executable file
Binary file not shown.
BIN
phonelibs/capnp-cpp/aarch64/bin/capnpc-capnp
Executable file
BIN
phonelibs/capnp-cpp/aarch64/bin/capnpc-capnp
Executable file
Binary file not shown.
BIN
phonelibs/capnp-cpp/aarch64/lib/libcapnp.a
Normal file
BIN
phonelibs/capnp-cpp/aarch64/lib/libcapnp.a
Normal file
Binary file not shown.
BIN
phonelibs/capnp-cpp/aarch64/lib/libcapnpc.a
Normal file
BIN
phonelibs/capnp-cpp/aarch64/lib/libcapnpc.a
Normal file
Binary file not shown.
BIN
phonelibs/capnp-cpp/aarch64/lib/libkj.a
Normal file
BIN
phonelibs/capnp-cpp/aarch64/lib/libkj.a
Normal file
Binary file not shown.
1073
phonelibs/capnp-cpp/include/capnp/any.h
Normal file
1073
phonelibs/capnp-cpp/include/capnp/any.h
Normal file
File diff suppressed because it is too large
Load Diff
220
phonelibs/capnp-cpp/include/capnp/blob.h
Normal file
220
phonelibs/capnp-cpp/include/capnp/blob.h
Normal file
@@ -0,0 +1,220 @@
|
||||
// Copyright (c) 2013-2014 Sandstorm Development Group, Inc. and contributors
|
||||
// Licensed under the MIT License:
|
||||
//
|
||||
// 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.
|
||||
|
||||
#ifndef CAPNP_BLOB_H_
|
||||
#define CAPNP_BLOB_H_
|
||||
|
||||
#if defined(__GNUC__) && !defined(CAPNP_HEADER_WARNINGS)
|
||||
#pragma GCC system_header
|
||||
#endif
|
||||
|
||||
#include <kj/common.h>
|
||||
#include <kj/string.h>
|
||||
#include "common.h"
|
||||
#include <string.h>
|
||||
|
||||
namespace capnp {
|
||||
|
||||
struct Data {
|
||||
Data() = delete;
|
||||
class Reader;
|
||||
class Builder;
|
||||
class Pipeline {};
|
||||
};
|
||||
|
||||
struct Text {
|
||||
Text() = delete;
|
||||
class Reader;
|
||||
class Builder;
|
||||
class Pipeline {};
|
||||
};
|
||||
|
||||
class Data::Reader: public kj::ArrayPtr<const byte> {
|
||||
// Points to a blob of bytes. The usual Reader rules apply -- Data::Reader behaves like a simple
|
||||
// pointer which does not own its target, can be passed by value, etc.
|
||||
|
||||
public:
|
||||
typedef Data Reads;
|
||||
|
||||
Reader() = default;
|
||||
inline Reader(decltype(nullptr)): ArrayPtr<const byte>(nullptr) {}
|
||||
inline Reader(const byte* value, size_t size): ArrayPtr<const byte>(value, size) {}
|
||||
inline Reader(const kj::Array<const byte>& value): ArrayPtr<const byte>(value) {}
|
||||
inline Reader(const ArrayPtr<const byte>& value): ArrayPtr<const byte>(value) {}
|
||||
inline Reader(const kj::Array<byte>& value): ArrayPtr<const byte>(value) {}
|
||||
inline Reader(const ArrayPtr<byte>& value): ArrayPtr<const byte>(value) {}
|
||||
};
|
||||
|
||||
class Text::Reader: public kj::StringPtr {
|
||||
// Like Data::Reader, but points at NUL-terminated UTF-8 text. The NUL terminator is not counted
|
||||
// in the size but must be present immediately after the last byte.
|
||||
//
|
||||
// Text::Reader's interface contract is that its data MUST be NUL-terminated. The producer of
|
||||
// the Text::Reader must guarantee this, so that the consumer need not check. The data SHOULD
|
||||
// also be valid UTF-8, but this is NOT guaranteed -- the consumer must verify if it cares.
|
||||
|
||||
public:
|
||||
typedef Text Reads;
|
||||
|
||||
Reader() = default;
|
||||
inline Reader(decltype(nullptr)): StringPtr(nullptr) {}
|
||||
inline Reader(const char* value): StringPtr(value) {}
|
||||
inline Reader(const char* value, size_t size): StringPtr(value, size) {}
|
||||
inline Reader(const kj::String& value): StringPtr(value) {}
|
||||
inline Reader(const StringPtr& value): StringPtr(value) {}
|
||||
|
||||
#if KJ_COMPILER_SUPPORTS_STL_STRING_INTEROP
|
||||
template <typename T, typename = decltype(kj::instance<T>().c_str())>
|
||||
inline Reader(const T& t): StringPtr(t) {}
|
||||
// Allow implicit conversion from any class that has a c_str() method (namely, std::string).
|
||||
// We use a template trick to detect std::string in order to avoid including the header for
|
||||
// those who don't want it.
|
||||
#endif
|
||||
};
|
||||
|
||||
class Data::Builder: public kj::ArrayPtr<byte> {
|
||||
// Like Data::Reader except the pointers aren't const.
|
||||
|
||||
public:
|
||||
typedef Data Builds;
|
||||
|
||||
Builder() = default;
|
||||
inline Builder(decltype(nullptr)): ArrayPtr<byte>(nullptr) {}
|
||||
inline Builder(byte* value, size_t size): ArrayPtr<byte>(value, size) {}
|
||||
inline Builder(kj::Array<byte>& value): ArrayPtr<byte>(value) {}
|
||||
inline Builder(ArrayPtr<byte> value): ArrayPtr<byte>(value) {}
|
||||
|
||||
inline Data::Reader asReader() const { return Data::Reader(*this); }
|
||||
inline operator Reader() const { return asReader(); }
|
||||
};
|
||||
|
||||
class Text::Builder: public kj::DisallowConstCopy {
|
||||
// Basically identical to kj::StringPtr, except that the contents are non-const.
|
||||
|
||||
public:
|
||||
inline Builder(): content(nulstr, 1) {}
|
||||
inline Builder(decltype(nullptr)): content(nulstr, 1) {}
|
||||
inline Builder(char* value): content(value, strlen(value) + 1) {}
|
||||
inline Builder(char* value, size_t size): content(value, size + 1) {
|
||||
KJ_IREQUIRE(value[size] == '\0', "StringPtr must be NUL-terminated.");
|
||||
}
|
||||
|
||||
inline Reader asReader() const { return Reader(content.begin(), content.size() - 1); }
|
||||
inline operator Reader() const { return asReader(); }
|
||||
|
||||
inline operator kj::ArrayPtr<char>();
|
||||
inline kj::ArrayPtr<char> asArray();
|
||||
inline operator kj::ArrayPtr<const char>() const;
|
||||
inline kj::ArrayPtr<const char> asArray() const;
|
||||
inline kj::ArrayPtr<byte> asBytes() { return asArray().asBytes(); }
|
||||
inline kj::ArrayPtr<const byte> asBytes() const { return asArray().asBytes(); }
|
||||
// Result does not include NUL terminator.
|
||||
|
||||
inline operator kj::StringPtr() const;
|
||||
inline kj::StringPtr asString() const;
|
||||
|
||||
inline const char* cStr() const { return content.begin(); }
|
||||
// Returns NUL-terminated string.
|
||||
|
||||
inline size_t size() const { return content.size() - 1; }
|
||||
// Result does not include NUL terminator.
|
||||
|
||||
inline char operator[](size_t index) const { return content[index]; }
|
||||
inline char& operator[](size_t index) { return content[index]; }
|
||||
|
||||
inline char* begin() { return content.begin(); }
|
||||
inline char* end() { return content.end() - 1; }
|
||||
inline const char* begin() const { return content.begin(); }
|
||||
inline const char* end() const { return content.end() - 1; }
|
||||
|
||||
inline bool operator==(decltype(nullptr)) const { return content.size() <= 1; }
|
||||
inline bool operator!=(decltype(nullptr)) const { return content.size() > 1; }
|
||||
|
||||
inline bool operator==(Builder other) const { return asString() == other.asString(); }
|
||||
inline bool operator!=(Builder other) const { return asString() != other.asString(); }
|
||||
inline bool operator< (Builder other) const { return asString() < other.asString(); }
|
||||
inline bool operator> (Builder other) const { return asString() > other.asString(); }
|
||||
inline bool operator<=(Builder other) const { return asString() <= other.asString(); }
|
||||
inline bool operator>=(Builder other) const { return asString() >= other.asString(); }
|
||||
|
||||
inline kj::StringPtr slice(size_t start) const;
|
||||
inline kj::ArrayPtr<const char> slice(size_t start, size_t end) const;
|
||||
inline Builder slice(size_t start);
|
||||
inline kj::ArrayPtr<char> slice(size_t start, size_t end);
|
||||
// A string slice is only NUL-terminated if it is a suffix, so slice() has a one-parameter
|
||||
// version that assumes end = size().
|
||||
|
||||
private:
|
||||
inline explicit Builder(kj::ArrayPtr<char> content): content(content) {}
|
||||
|
||||
kj::ArrayPtr<char> content;
|
||||
|
||||
static char nulstr[1];
|
||||
};
|
||||
|
||||
inline kj::StringPtr KJ_STRINGIFY(Text::Builder builder) {
|
||||
return builder.asString();
|
||||
}
|
||||
|
||||
inline bool operator==(const char* a, const Text::Builder& b) { return a == b.asString(); }
|
||||
inline bool operator!=(const char* a, const Text::Builder& b) { return a != b.asString(); }
|
||||
|
||||
inline Text::Builder::operator kj::StringPtr() const {
|
||||
return kj::StringPtr(content.begin(), content.size() - 1);
|
||||
}
|
||||
|
||||
inline kj::StringPtr Text::Builder::asString() const {
|
||||
return kj::StringPtr(content.begin(), content.size() - 1);
|
||||
}
|
||||
|
||||
inline Text::Builder::operator kj::ArrayPtr<char>() {
|
||||
return content.slice(0, content.size() - 1);
|
||||
}
|
||||
|
||||
inline kj::ArrayPtr<char> Text::Builder::asArray() {
|
||||
return content.slice(0, content.size() - 1);
|
||||
}
|
||||
|
||||
inline Text::Builder::operator kj::ArrayPtr<const char>() const {
|
||||
return content.slice(0, content.size() - 1);
|
||||
}
|
||||
|
||||
inline kj::ArrayPtr<const char> Text::Builder::asArray() const {
|
||||
return content.slice(0, content.size() - 1);
|
||||
}
|
||||
|
||||
inline kj::StringPtr Text::Builder::slice(size_t start) const {
|
||||
return asReader().slice(start);
|
||||
}
|
||||
inline kj::ArrayPtr<const char> Text::Builder::slice(size_t start, size_t end) const {
|
||||
return content.slice(start, end);
|
||||
}
|
||||
|
||||
inline Text::Builder Text::Builder::slice(size_t start) {
|
||||
return Text::Builder(content.slice(start, content.size()));
|
||||
}
|
||||
inline kj::ArrayPtr<char> Text::Builder::slice(size_t start, size_t end) {
|
||||
return content.slice(start, end);
|
||||
}
|
||||
|
||||
} // namespace capnp
|
||||
|
||||
#endif // CAPNP_BLOB_H_
|
||||
26
phonelibs/capnp-cpp/include/capnp/c++.capnp
Normal file
26
phonelibs/capnp-cpp/include/capnp/c++.capnp
Normal file
@@ -0,0 +1,26 @@
|
||||
# Copyright (c) 2013-2014 Sandstorm Development Group, Inc. and contributors
|
||||
# Licensed under the MIT License:
|
||||
#
|
||||
# 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.
|
||||
|
||||
@0xbdf87d7bb8304e81;
|
||||
$namespace("capnp::annotations");
|
||||
|
||||
annotation namespace(file): Text;
|
||||
annotation name(field, enumerant, struct, enum, interface, method, param, group, union): Text;
|
||||
33
phonelibs/capnp-cpp/include/capnp/c++.capnp.h
Normal file
33
phonelibs/capnp-cpp/include/capnp/c++.capnp.h
Normal file
@@ -0,0 +1,33 @@
|
||||
// Generated by Cap'n Proto compiler, DO NOT EDIT
|
||||
// source: c++.capnp
|
||||
|
||||
#ifndef CAPNP_INCLUDED_bdf87d7bb8304e81_
|
||||
#define CAPNP_INCLUDED_bdf87d7bb8304e81_
|
||||
|
||||
#include <capnp/generated-header-support.h>
|
||||
|
||||
#if CAPNP_VERSION != 6001
|
||||
#error "Version mismatch between generated code and library headers. You must use the same version of the Cap'n Proto compiler and library."
|
||||
#endif
|
||||
|
||||
|
||||
namespace capnp {
|
||||
namespace schemas {
|
||||
|
||||
CAPNP_DECLARE_SCHEMA(b9c6f99ebf805f2c);
|
||||
CAPNP_DECLARE_SCHEMA(f264a779fef191ce);
|
||||
|
||||
} // namespace schemas
|
||||
} // namespace capnp
|
||||
|
||||
namespace capnp {
|
||||
namespace annotations {
|
||||
|
||||
// =======================================================================================
|
||||
|
||||
// =======================================================================================
|
||||
|
||||
} // namespace
|
||||
} // namespace
|
||||
|
||||
#endif // CAPNP_INCLUDED_bdf87d7bb8304e81_
|
||||
37
phonelibs/capnp-cpp/include/capnp/c.capnp
Normal file
37
phonelibs/capnp-cpp/include/capnp/c.capnp
Normal file
@@ -0,0 +1,37 @@
|
||||
# Copyright (c) 2016 NetDEF, Inc. and contributors
|
||||
# Licensed under the MIT License:
|
||||
#
|
||||
# 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.
|
||||
|
||||
@0xc0183dd65ffef0f3;
|
||||
|
||||
annotation nameinfix @0x85a8d86d736ba637 (file): Text;
|
||||
# add an infix (middle insert) for output file names
|
||||
#
|
||||
# "make" generally has implicit rules for compiling "foo.c" => "foo". This
|
||||
# is very annoying with capnp since the rule will be "foo" => "foo.c", leading
|
||||
# to a loop. $nameinfix (recommended parameter: "-gen") inserts its parameter
|
||||
# before the ".c", so the filename becomes "foo-gen.c"
|
||||
#
|
||||
# ("foo" is really "foo.capnp", so it's foo.capnp-gen.c)
|
||||
|
||||
annotation fieldgetset @0xf72bc690355d66de (file): Void;
|
||||
# generate getter & setter functions for accessing fields
|
||||
#
|
||||
# allows grabbing/putting values without de-/encoding the entire struct.
|
||||
884
phonelibs/capnp-cpp/include/capnp/capability.h
Normal file
884
phonelibs/capnp-cpp/include/capnp/capability.h
Normal file
@@ -0,0 +1,884 @@
|
||||
// Copyright (c) 2013-2014 Sandstorm Development Group, Inc. and contributors
|
||||
// Licensed under the MIT License:
|
||||
//
|
||||
// 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.
|
||||
|
||||
#ifndef CAPNP_CAPABILITY_H_
|
||||
#define CAPNP_CAPABILITY_H_
|
||||
|
||||
#if defined(__GNUC__) && !defined(CAPNP_HEADER_WARNINGS)
|
||||
#pragma GCC system_header
|
||||
#endif
|
||||
|
||||
#if CAPNP_LITE
|
||||
#error "RPC APIs, including this header, are not available in lite mode."
|
||||
#endif
|
||||
|
||||
#include <kj/async.h>
|
||||
#include <kj/vector.h>
|
||||
#include "raw-schema.h"
|
||||
#include "any.h"
|
||||
#include "pointer-helpers.h"
|
||||
|
||||
namespace capnp {
|
||||
|
||||
template <typename Results>
|
||||
class Response;
|
||||
|
||||
template <typename T>
|
||||
class RemotePromise: public kj::Promise<Response<T>>, public T::Pipeline {
|
||||
// A Promise which supports pipelined calls. T is typically a struct type. T must declare
|
||||
// an inner "mix-in" type "Pipeline" which implements pipelining; RemotePromise simply
|
||||
// multiply-inherits that type along with Promise<Response<T>>. T::Pipeline must be movable,
|
||||
// but does not need to be copyable (i.e. just like Promise<T>).
|
||||
//
|
||||
// The promise is for an owned pointer so that the RPC system can allocate the MessageReader
|
||||
// itself.
|
||||
|
||||
public:
|
||||
inline RemotePromise(kj::Promise<Response<T>>&& promise, typename T::Pipeline&& pipeline)
|
||||
: kj::Promise<Response<T>>(kj::mv(promise)),
|
||||
T::Pipeline(kj::mv(pipeline)) {}
|
||||
inline RemotePromise(decltype(nullptr))
|
||||
: kj::Promise<Response<T>>(nullptr),
|
||||
T::Pipeline(nullptr) {}
|
||||
KJ_DISALLOW_COPY(RemotePromise);
|
||||
RemotePromise(RemotePromise&& other) = default;
|
||||
RemotePromise& operator=(RemotePromise&& other) = default;
|
||||
};
|
||||
|
||||
class LocalClient;
|
||||
namespace _ { // private
|
||||
extern const RawSchema NULL_INTERFACE_SCHEMA; // defined in schema.c++
|
||||
class CapabilityServerSetBase;
|
||||
} // namespace _ (private)
|
||||
|
||||
struct Capability {
|
||||
// A capability without type-safe methods. Typed capability clients wrap `Client` and typed
|
||||
// capability servers subclass `Server` to dispatch to the regular, typed methods.
|
||||
|
||||
class Client;
|
||||
class Server;
|
||||
|
||||
struct _capnpPrivate {
|
||||
struct IsInterface;
|
||||
static constexpr uint64_t typeId = 0x3;
|
||||
static constexpr Kind kind = Kind::INTERFACE;
|
||||
static constexpr _::RawSchema const* schema = &_::NULL_INTERFACE_SCHEMA;
|
||||
|
||||
static const _::RawBrandedSchema* brand() {
|
||||
return &_::NULL_INTERFACE_SCHEMA.defaultBrand;
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
// =======================================================================================
|
||||
// Capability clients
|
||||
|
||||
class RequestHook;
|
||||
class ResponseHook;
|
||||
class PipelineHook;
|
||||
class ClientHook;
|
||||
|
||||
template <typename Params, typename Results>
|
||||
class Request: public Params::Builder {
|
||||
// A call that hasn't been sent yet. This class extends a Builder for the call's "Params"
|
||||
// structure with a method send() that actually sends it.
|
||||
//
|
||||
// Given a Cap'n Proto method `foo(a :A, b :B): C`, the generated client interface will have
|
||||
// a method `Request<FooParams, C> fooRequest()` (as well as a convenience method
|
||||
// `RemotePromise<C> foo(A::Reader a, B::Reader b)`).
|
||||
|
||||
public:
|
||||
inline Request(typename Params::Builder builder, kj::Own<RequestHook>&& hook)
|
||||
: Params::Builder(builder), hook(kj::mv(hook)) {}
|
||||
inline Request(decltype(nullptr)): Params::Builder(nullptr) {}
|
||||
|
||||
RemotePromise<Results> send() KJ_WARN_UNUSED_RESULT;
|
||||
// Send the call and return a promise for the results.
|
||||
|
||||
private:
|
||||
kj::Own<RequestHook> hook;
|
||||
|
||||
friend class Capability::Client;
|
||||
friend struct DynamicCapability;
|
||||
template <typename, typename>
|
||||
friend class CallContext;
|
||||
friend class RequestHook;
|
||||
};
|
||||
|
||||
template <typename Results>
|
||||
class Response: public Results::Reader {
|
||||
// A completed call. This class extends a Reader for the call's answer structure. The Response
|
||||
// is move-only -- once it goes out-of-scope, the underlying message will be freed.
|
||||
|
||||
public:
|
||||
inline Response(typename Results::Reader reader, kj::Own<ResponseHook>&& hook)
|
||||
: Results::Reader(reader), hook(kj::mv(hook)) {}
|
||||
|
||||
private:
|
||||
kj::Own<ResponseHook> hook;
|
||||
|
||||
template <typename, typename>
|
||||
friend class Request;
|
||||
friend class ResponseHook;
|
||||
};
|
||||
|
||||
class Capability::Client {
|
||||
// Base type for capability clients.
|
||||
|
||||
public:
|
||||
typedef Capability Reads;
|
||||
typedef Capability Calls;
|
||||
|
||||
Client(decltype(nullptr));
|
||||
// If you need to declare a Client before you have anything to assign to it (perhaps because
|
||||
// the assignment is going to occur in an if/else scope), you can start by initializing it to
|
||||
// `nullptr`. The resulting client is not meant to be called and throws exceptions from all
|
||||
// methods.
|
||||
|
||||
template <typename T, typename = kj::EnableIf<kj::canConvert<T*, Capability::Server*>()>>
|
||||
Client(kj::Own<T>&& server);
|
||||
// Make a client capability that wraps the given server capability. The server's methods will
|
||||
// only be executed in the given EventLoop, regardless of what thread calls the client's methods.
|
||||
|
||||
template <typename T, typename = kj::EnableIf<kj::canConvert<T*, Client*>()>>
|
||||
Client(kj::Promise<T>&& promise);
|
||||
// Make a client from a promise for a future client. The resulting client queues calls until the
|
||||
// promise resolves.
|
||||
|
||||
Client(kj::Exception&& exception);
|
||||
// Make a broken client that throws the given exception from all calls.
|
||||
|
||||
Client(Client& other);
|
||||
Client& operator=(Client& other);
|
||||
// Copies by reference counting. Warning: This refcounting is not thread-safe. All copies of
|
||||
// the client must remain in one thread.
|
||||
|
||||
Client(Client&&) = default;
|
||||
Client& operator=(Client&&) = default;
|
||||
// Move constructor avoids reference counting.
|
||||
|
||||
explicit Client(kj::Own<ClientHook>&& hook);
|
||||
// For use by the RPC implementation: Wrap a ClientHook.
|
||||
|
||||
template <typename T>
|
||||
typename T::Client castAs();
|
||||
// Reinterpret the capability as implementing the given interface. Note that no error will occur
|
||||
// here if the capability does not actually implement this interface, but later method calls will
|
||||
// fail. It's up to the application to decide how indicate that additional interfaces are
|
||||
// supported.
|
||||
//
|
||||
// TODO(perf): GCC 4.8 / Clang 3.3: rvalue-qualified version for better performance.
|
||||
|
||||
template <typename T>
|
||||
typename T::Client castAs(InterfaceSchema schema);
|
||||
// Dynamic version. `T` must be `DynamicCapability`, and you must `#include <capnp/dynamic.h>`.
|
||||
|
||||
kj::Promise<void> whenResolved();
|
||||
// If the capability is actually only a promise, the returned promise resolves once the
|
||||
// capability itself has resolved to its final destination (or propagates the exception if
|
||||
// the capability promise is rejected). This is mainly useful for error-checking in the case
|
||||
// where no calls are being made. There is no reason to wait for this before making calls; if
|
||||
// the capability does not resolve, the call results will propagate the error.
|
||||
|
||||
Request<AnyPointer, AnyPointer> typelessRequest(
|
||||
uint64_t interfaceId, uint16_t methodId,
|
||||
kj::Maybe<MessageSize> sizeHint);
|
||||
// Make a request without knowing the types of the params or results. You specify the type ID
|
||||
// and method number manually.
|
||||
|
||||
// TODO(someday): method(s) for Join
|
||||
|
||||
protected:
|
||||
Client() = default;
|
||||
|
||||
template <typename Params, typename Results>
|
||||
Request<Params, Results> newCall(uint64_t interfaceId, uint16_t methodId,
|
||||
kj::Maybe<MessageSize> sizeHint);
|
||||
|
||||
private:
|
||||
kj::Own<ClientHook> hook;
|
||||
|
||||
static kj::Own<ClientHook> makeLocalClient(kj::Own<Capability::Server>&& server);
|
||||
|
||||
template <typename, Kind>
|
||||
friend struct _::PointerHelpers;
|
||||
friend struct DynamicCapability;
|
||||
friend class Orphanage;
|
||||
friend struct DynamicStruct;
|
||||
friend struct DynamicList;
|
||||
template <typename, Kind>
|
||||
friend struct List;
|
||||
friend class _::CapabilityServerSetBase;
|
||||
friend class ClientHook;
|
||||
};
|
||||
|
||||
// =======================================================================================
|
||||
// Capability servers
|
||||
|
||||
class CallContextHook;
|
||||
|
||||
template <typename Params, typename Results>
|
||||
class CallContext: public kj::DisallowConstCopy {
|
||||
// Wrapper around CallContextHook with a specific return type.
|
||||
//
|
||||
// Methods of this class may only be called from within the server's event loop, not from other
|
||||
// threads.
|
||||
//
|
||||
// The CallContext becomes invalid as soon as the call reports completion.
|
||||
|
||||
public:
|
||||
explicit CallContext(CallContextHook& hook);
|
||||
|
||||
typename Params::Reader getParams();
|
||||
// Get the params payload.
|
||||
|
||||
void releaseParams();
|
||||
// Release the params payload. getParams() will throw an exception after this is called.
|
||||
// Releasing the params may allow the RPC system to free up buffer space to handle other
|
||||
// requests. Long-running asynchronous methods should try to call this as early as is
|
||||
// convenient.
|
||||
|
||||
typename Results::Builder getResults(kj::Maybe<MessageSize> sizeHint = nullptr);
|
||||
typename Results::Builder initResults(kj::Maybe<MessageSize> sizeHint = nullptr);
|
||||
void setResults(typename Results::Reader value);
|
||||
void adoptResults(Orphan<Results>&& value);
|
||||
Orphanage getResultsOrphanage(kj::Maybe<MessageSize> sizeHint = nullptr);
|
||||
// Manipulate the results payload. The "Return" message (part of the RPC protocol) will
|
||||
// typically be allocated the first time one of these is called. Some RPC systems may
|
||||
// allocate these messages in a limited space (such as a shared memory segment), therefore the
|
||||
// application should delay calling these as long as is convenient to do so (but don't delay
|
||||
// if doing so would require extra copies later).
|
||||
//
|
||||
// `sizeHint` indicates a guess at the message size. This will usually be used to decide how
|
||||
// much space to allocate for the first message segment (don't worry: only space that is actually
|
||||
// used will be sent on the wire). If omitted, the system decides. The message root pointer
|
||||
// should not be included in the size. So, if you are simply going to copy some existing message
|
||||
// directly into the results, just call `.totalSize()` and pass that in.
|
||||
|
||||
template <typename SubParams>
|
||||
kj::Promise<void> tailCall(Request<SubParams, Results>&& tailRequest);
|
||||
// Resolve the call by making a tail call. `tailRequest` is a request that has been filled in
|
||||
// but not yet sent. The context will send the call, then fill in the results with the result
|
||||
// of the call. If tailCall() is used, {get,init,set,adopt}Results (above) *must not* be called.
|
||||
//
|
||||
// The RPC implementation may be able to optimize a tail call to another machine such that the
|
||||
// results never actually pass through this machine. Even if no such optimization is possible,
|
||||
// `tailCall()` may allow pipelined calls to be forwarded optimistically to the new call site.
|
||||
//
|
||||
// In general, this should be the last thing a method implementation calls, and the promise
|
||||
// returned from `tailCall()` should then be returned by the method implementation.
|
||||
|
||||
void allowCancellation();
|
||||
// Indicate that it is OK for the RPC system to discard its Promise for this call's result if
|
||||
// the caller cancels the call, thereby transitively canceling any asynchronous operations the
|
||||
// call implementation was performing. This is not done by default because it could represent a
|
||||
// security risk: applications must be carefully written to ensure that they do not end up in
|
||||
// a bad state if an operation is canceled at an arbitrary point. However, for long-running
|
||||
// method calls that hold significant resources, prompt cancellation is often useful.
|
||||
//
|
||||
// Keep in mind that asynchronous cancellation cannot occur while the method is synchronously
|
||||
// executing on a local thread. The method must perform an asynchronous operation or call
|
||||
// `EventLoop::current().evalLater()` to yield control.
|
||||
//
|
||||
// Note: You might think that we should offer `onCancel()` and/or `isCanceled()` methods that
|
||||
// provide notification when the caller cancels the request without forcefully killing off the
|
||||
// promise chain. Unfortunately, this composes poorly with promise forking: the canceled
|
||||
// path may be just one branch of a fork of the result promise. The other branches still want
|
||||
// the call to continue. Promise forking is used within the Cap'n Proto implementation -- in
|
||||
// particular each pipelined call forks the result promise. So, if a caller made a pipelined
|
||||
// call and then dropped the original object, the call should not be canceled, but it would be
|
||||
// excessively complicated for the framework to avoid notififying of cancellation as long as
|
||||
// pipelined calls still exist.
|
||||
|
||||
private:
|
||||
CallContextHook* hook;
|
||||
|
||||
friend class Capability::Server;
|
||||
friend struct DynamicCapability;
|
||||
};
|
||||
|
||||
class Capability::Server {
|
||||
// Objects implementing a Cap'n Proto interface must subclass this. Typically, such objects
|
||||
// will instead subclass a typed Server interface which will take care of implementing
|
||||
// dispatchCall().
|
||||
|
||||
public:
|
||||
typedef Capability Serves;
|
||||
|
||||
virtual kj::Promise<void> dispatchCall(uint64_t interfaceId, uint16_t methodId,
|
||||
CallContext<AnyPointer, AnyPointer> context) = 0;
|
||||
// Call the given method. `params` is the input struct, and should be released as soon as it
|
||||
// is no longer needed. `context` may be used to allocate the output struct and deal with
|
||||
// cancellation.
|
||||
|
||||
// TODO(someday): Method which can optionally be overridden to implement Join when the object is
|
||||
// a proxy.
|
||||
|
||||
protected:
|
||||
inline Capability::Client thisCap();
|
||||
// Get a capability pointing to this object, much like the `this` keyword.
|
||||
//
|
||||
// The effect of this method is undefined if:
|
||||
// - No capability client has been created pointing to this object. (This is always the case in
|
||||
// the server's constructor.)
|
||||
// - The capability client pointing at this object has been destroyed. (This is always the case
|
||||
// in the server's destructor.)
|
||||
// - Multiple capability clients have been created around the same server (possible if the server
|
||||
// is refcounted, which is not recommended since the client itself provides refcounting).
|
||||
|
||||
template <typename Params, typename Results>
|
||||
CallContext<Params, Results> internalGetTypedContext(
|
||||
CallContext<AnyPointer, AnyPointer> typeless);
|
||||
kj::Promise<void> internalUnimplemented(const char* actualInterfaceName,
|
||||
uint64_t requestedTypeId);
|
||||
kj::Promise<void> internalUnimplemented(const char* interfaceName,
|
||||
uint64_t typeId, uint16_t methodId);
|
||||
kj::Promise<void> internalUnimplemented(const char* interfaceName, const char* methodName,
|
||||
uint64_t typeId, uint16_t methodId);
|
||||
|
||||
private:
|
||||
ClientHook* thisHook = nullptr;
|
||||
friend class LocalClient;
|
||||
};
|
||||
|
||||
// =======================================================================================
|
||||
|
||||
class ReaderCapabilityTable: private _::CapTableReader {
|
||||
// Class which imbues Readers with the ability to read capabilities.
|
||||
//
|
||||
// In Cap'n Proto format, the encoding of a capability pointer is simply an integer index into
|
||||
// an external table. Since these pointers fundamentally point outside the message, a
|
||||
// MessageReader by default has no idea what they point at, and therefore reading capabilities
|
||||
// from such a reader will throw exceptions.
|
||||
//
|
||||
// In order to be able to read capabilities, you must first attach a capability table, using
|
||||
// this class. By "imbuing" a Reader, you get a new Reader which will interpret capability
|
||||
// pointers by treating them as indexes into the ReaderCapabilityTable.
|
||||
//
|
||||
// Note that when using Cap'n Proto's RPC system, this is handled automatically.
|
||||
|
||||
public:
|
||||
explicit ReaderCapabilityTable(kj::Array<kj::Maybe<kj::Own<ClientHook>>> table);
|
||||
KJ_DISALLOW_COPY(ReaderCapabilityTable);
|
||||
|
||||
template <typename T>
|
||||
T imbue(T reader);
|
||||
// Return a reader equivalent to `reader` except that when reading capability-valued fields,
|
||||
// the capabilities are looked up in this table.
|
||||
|
||||
private:
|
||||
kj::Array<kj::Maybe<kj::Own<ClientHook>>> table;
|
||||
|
||||
kj::Maybe<kj::Own<ClientHook>> extractCap(uint index) override;
|
||||
};
|
||||
|
||||
class BuilderCapabilityTable: private _::CapTableBuilder {
|
||||
// Class which imbues Builders with the ability to read and write capabilities.
|
||||
//
|
||||
// This is much like ReaderCapabilityTable, except for builders. The table starts out empty,
|
||||
// but capabilities can be added to it over time.
|
||||
|
||||
public:
|
||||
BuilderCapabilityTable();
|
||||
KJ_DISALLOW_COPY(BuilderCapabilityTable);
|
||||
|
||||
inline kj::ArrayPtr<kj::Maybe<kj::Own<ClientHook>>> getTable() { return table; }
|
||||
|
||||
template <typename T>
|
||||
T imbue(T builder);
|
||||
// Return a builder equivalent to `builder` except that when reading capability-valued fields,
|
||||
// the capabilities are looked up in this table.
|
||||
|
||||
private:
|
||||
kj::Vector<kj::Maybe<kj::Own<ClientHook>>> table;
|
||||
|
||||
kj::Maybe<kj::Own<ClientHook>> extractCap(uint index) override;
|
||||
uint injectCap(kj::Own<ClientHook>&& cap) override;
|
||||
void dropCap(uint index) override;
|
||||
};
|
||||
|
||||
// =======================================================================================
|
||||
|
||||
namespace _ { // private
|
||||
|
||||
class CapabilityServerSetBase {
|
||||
public:
|
||||
Capability::Client addInternal(kj::Own<Capability::Server>&& server, void* ptr);
|
||||
kj::Promise<void*> getLocalServerInternal(Capability::Client& client);
|
||||
};
|
||||
|
||||
} // namespace _ (private)
|
||||
|
||||
template <typename T>
|
||||
class CapabilityServerSet: private _::CapabilityServerSetBase {
|
||||
// Allows a server to recognize its own capabilities when passed back to it, and obtain the
|
||||
// underlying Server objects associated with them.
|
||||
//
|
||||
// All objects in the set must have the same interface type T. The objects may implement various
|
||||
// interfaces derived from T (and in fact T can be `capnp::Capability` to accept all objects),
|
||||
// but note that if you compile with RTTI disabled then you will not be able to down-cast through
|
||||
// virtual inheritance, and all inheritance between server interfaces is virtual. So, with RTTI
|
||||
// disabled, you will likely need to set T to be the most-derived Cap'n Proto interface type,
|
||||
// and you server class will need to be directly derived from that, so that you can use
|
||||
// static_cast (or kj::downcast) to cast to it after calling getLocalServer(). (If you compile
|
||||
// with RTTI, then you can freely dynamic_cast and ignore this issue!)
|
||||
|
||||
public:
|
||||
CapabilityServerSet() = default;
|
||||
KJ_DISALLOW_COPY(CapabilityServerSet);
|
||||
|
||||
typename T::Client add(kj::Own<typename T::Server>&& server);
|
||||
// Create a new capability Client for the given Server and also add this server to the set.
|
||||
|
||||
kj::Promise<kj::Maybe<typename T::Server&>> getLocalServer(typename T::Client& client);
|
||||
// Given a Client pointing to a server previously passed to add(), return the corresponding
|
||||
// Server. This returns a promise because if the input client is itself a promise, this must
|
||||
// wait for it to resolve. Keep in mind that the server will be deleted when all clients are
|
||||
// gone, so the caller should make sure to keep the client alive (hence why this method only
|
||||
// accepts an lvalue input).
|
||||
};
|
||||
|
||||
// =======================================================================================
|
||||
// Hook interfaces which must be implemented by the RPC system. Applications never call these
|
||||
// directly; the RPC system implements them and the types defined earlier in this file wrap them.
|
||||
|
||||
class RequestHook {
|
||||
// Hook interface implemented by RPC system representing a request being built.
|
||||
|
||||
public:
|
||||
virtual RemotePromise<AnyPointer> send() = 0;
|
||||
// Send the call and return a promise for the result.
|
||||
|
||||
virtual const void* getBrand() = 0;
|
||||
// Returns a void* that identifies who made this request. This can be used by an RPC adapter to
|
||||
// discover when tail call is going to be sent over its own connection and therefore can be
|
||||
// optimized into a remote tail call.
|
||||
|
||||
template <typename T, typename U>
|
||||
inline static kj::Own<RequestHook> from(Request<T, U>&& request) {
|
||||
return kj::mv(request.hook);
|
||||
}
|
||||
};
|
||||
|
||||
class ResponseHook {
|
||||
// Hook interface implemented by RPC system representing a response.
|
||||
//
|
||||
// At present this class has no methods. It exists only for garbage collection -- when the
|
||||
// ResponseHook is destroyed, the results can be freed.
|
||||
|
||||
public:
|
||||
virtual ~ResponseHook() noexcept(false);
|
||||
// Just here to make sure the type is dynamic.
|
||||
|
||||
template <typename T>
|
||||
inline static kj::Own<ResponseHook> from(Response<T>&& response) {
|
||||
return kj::mv(response.hook);
|
||||
}
|
||||
};
|
||||
|
||||
// class PipelineHook is declared in any.h because it is needed there.
|
||||
|
||||
class ClientHook {
|
||||
public:
|
||||
ClientHook();
|
||||
|
||||
virtual Request<AnyPointer, AnyPointer> newCall(
|
||||
uint64_t interfaceId, uint16_t methodId, kj::Maybe<MessageSize> sizeHint) = 0;
|
||||
// Start a new call, allowing the client to allocate request/response objects as it sees fit.
|
||||
// This version is used when calls are made from application code in the local process.
|
||||
|
||||
struct VoidPromiseAndPipeline {
|
||||
kj::Promise<void> promise;
|
||||
kj::Own<PipelineHook> pipeline;
|
||||
};
|
||||
|
||||
virtual VoidPromiseAndPipeline call(uint64_t interfaceId, uint16_t methodId,
|
||||
kj::Own<CallContextHook>&& context) = 0;
|
||||
// Call the object, but the caller controls allocation of the request/response objects. If the
|
||||
// callee insists on allocating these objects itself, it must make a copy. This version is used
|
||||
// when calls come in over the network via an RPC system. Note that even if the returned
|
||||
// `Promise<void>` is discarded, the call may continue executing if any pipelined calls are
|
||||
// waiting for it.
|
||||
//
|
||||
// Since the caller of this method chooses the CallContext implementation, it is the caller's
|
||||
// responsibility to ensure that the returned promise is not canceled unless allowed via
|
||||
// the context's `allowCancellation()`.
|
||||
//
|
||||
// The call must not begin synchronously; the callee must arrange for the call to begin in a
|
||||
// later turn of the event loop. Otherwise, application code may call back and affect the
|
||||
// callee's state in an unexpected way.
|
||||
|
||||
virtual kj::Maybe<ClientHook&> getResolved() = 0;
|
||||
// If this ClientHook is a promise that has already resolved, returns the inner, resolved version
|
||||
// of the capability. The caller may permanently replace this client with the resolved one if
|
||||
// desired. Returns null if the client isn't a promise or hasn't resolved yet -- use
|
||||
// `whenMoreResolved()` to distinguish between them.
|
||||
|
||||
virtual kj::Maybe<kj::Promise<kj::Own<ClientHook>>> whenMoreResolved() = 0;
|
||||
// If this client is a settled reference (not a promise), return nullptr. Otherwise, return a
|
||||
// promise that eventually resolves to a new client that is closer to being the final, settled
|
||||
// client (i.e. the value eventually returned by `getResolved()`). Calling this repeatedly
|
||||
// should eventually produce a settled client.
|
||||
|
||||
kj::Promise<void> whenResolved();
|
||||
// Repeatedly calls whenMoreResolved() until it returns nullptr.
|
||||
|
||||
virtual kj::Own<ClientHook> addRef() = 0;
|
||||
// Return a new reference to the same capability.
|
||||
|
||||
virtual const void* getBrand() = 0;
|
||||
// Returns a void* that identifies who made this client. This can be used by an RPC adapter to
|
||||
// discover when a capability it needs to marshal is one that it created in the first place, and
|
||||
// therefore it can transfer the capability without proxying.
|
||||
|
||||
static const uint NULL_CAPABILITY_BRAND;
|
||||
// Value is irrelevant; used for pointer.
|
||||
|
||||
inline bool isNull() { return getBrand() == &NULL_CAPABILITY_BRAND; }
|
||||
// Returns true if the capability was created as a result of assigning a Client to null or by
|
||||
// reading a null pointer out of a Cap'n Proto message.
|
||||
|
||||
virtual void* getLocalServer(_::CapabilityServerSetBase& capServerSet);
|
||||
// If this is a local capability created through `capServerSet`, return the underlying Server.
|
||||
// Otherwise, return nullptr. Default implementation (which everyone except LocalClient should
|
||||
// use) always returns nullptr.
|
||||
|
||||
static kj::Own<ClientHook> from(Capability::Client client) { return kj::mv(client.hook); }
|
||||
};
|
||||
|
||||
class CallContextHook {
|
||||
// Hook interface implemented by RPC system to manage a call on the server side. See
|
||||
// CallContext<T>.
|
||||
|
||||
public:
|
||||
virtual AnyPointer::Reader getParams() = 0;
|
||||
virtual void releaseParams() = 0;
|
||||
virtual AnyPointer::Builder getResults(kj::Maybe<MessageSize> sizeHint) = 0;
|
||||
virtual kj::Promise<void> tailCall(kj::Own<RequestHook>&& request) = 0;
|
||||
virtual void allowCancellation() = 0;
|
||||
|
||||
virtual kj::Promise<AnyPointer::Pipeline> onTailCall() = 0;
|
||||
// If `tailCall()` is called, resolves to the PipelineHook from the tail call. An
|
||||
// implementation of `ClientHook::call()` is allowed to call this at most once.
|
||||
|
||||
virtual ClientHook::VoidPromiseAndPipeline directTailCall(kj::Own<RequestHook>&& request) = 0;
|
||||
// Call this when you would otherwise call onTailCall() immediately followed by tailCall().
|
||||
// Implementations of tailCall() should typically call directTailCall() and then fulfill the
|
||||
// promise fulfiller for onTailCall() with the returned pipeline.
|
||||
|
||||
virtual kj::Own<CallContextHook> addRef() = 0;
|
||||
};
|
||||
|
||||
kj::Own<ClientHook> newLocalPromiseClient(kj::Promise<kj::Own<ClientHook>>&& promise);
|
||||
// Returns a ClientHook that queues up calls until `promise` resolves, then forwards them to
|
||||
// the new client. This hook's `getResolved()` and `whenMoreResolved()` methods will reflect the
|
||||
// redirection to the eventual replacement client.
|
||||
|
||||
kj::Own<PipelineHook> newLocalPromisePipeline(kj::Promise<kj::Own<PipelineHook>>&& promise);
|
||||
// Returns a PipelineHook that queues up calls until `promise` resolves, then forwards them to
|
||||
// the new pipeline.
|
||||
|
||||
kj::Own<ClientHook> newBrokenCap(kj::StringPtr reason);
|
||||
kj::Own<ClientHook> newBrokenCap(kj::Exception&& reason);
|
||||
// Helper function that creates a capability which simply throws exceptions when called.
|
||||
|
||||
kj::Own<PipelineHook> newBrokenPipeline(kj::Exception&& reason);
|
||||
// Helper function that creates a pipeline which simply throws exceptions when called.
|
||||
|
||||
Request<AnyPointer, AnyPointer> newBrokenRequest(
|
||||
kj::Exception&& reason, kj::Maybe<MessageSize> sizeHint);
|
||||
// Helper function that creates a Request object that simply throws exceptions when sent.
|
||||
|
||||
// =======================================================================================
|
||||
// Extend PointerHelpers for interfaces
|
||||
|
||||
namespace _ { // private
|
||||
|
||||
template <typename T>
|
||||
struct PointerHelpers<T, Kind::INTERFACE> {
|
||||
static inline typename T::Client get(PointerReader reader) {
|
||||
return typename T::Client(reader.getCapability());
|
||||
}
|
||||
static inline typename T::Client get(PointerBuilder builder) {
|
||||
return typename T::Client(builder.getCapability());
|
||||
}
|
||||
static inline void set(PointerBuilder builder, typename T::Client&& value) {
|
||||
builder.setCapability(kj::mv(value.Capability::Client::hook));
|
||||
}
|
||||
static inline void set(PointerBuilder builder, typename T::Client& value) {
|
||||
builder.setCapability(value.Capability::Client::hook->addRef());
|
||||
}
|
||||
static inline void adopt(PointerBuilder builder, Orphan<T>&& value) {
|
||||
builder.adopt(kj::mv(value.builder));
|
||||
}
|
||||
static inline Orphan<T> disown(PointerBuilder builder) {
|
||||
return Orphan<T>(builder.disown());
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace _ (private)
|
||||
|
||||
// =======================================================================================
|
||||
// Extend List for interfaces
|
||||
|
||||
template <typename T>
|
||||
struct List<T, Kind::INTERFACE> {
|
||||
List() = delete;
|
||||
|
||||
class Reader {
|
||||
public:
|
||||
typedef List<T> Reads;
|
||||
|
||||
Reader() = default;
|
||||
inline explicit Reader(_::ListReader reader): reader(reader) {}
|
||||
|
||||
inline uint size() const { return unbound(reader.size() / ELEMENTS); }
|
||||
inline typename T::Client operator[](uint index) const {
|
||||
KJ_IREQUIRE(index < size());
|
||||
return typename T::Client(reader.getPointerElement(
|
||||
bounded(index) * ELEMENTS).getCapability());
|
||||
}
|
||||
|
||||
typedef _::IndexingIterator<const Reader, typename T::Client> Iterator;
|
||||
inline Iterator begin() const { return Iterator(this, 0); }
|
||||
inline Iterator end() const { return Iterator(this, size()); }
|
||||
|
||||
private:
|
||||
_::ListReader reader;
|
||||
template <typename U, Kind K>
|
||||
friend struct _::PointerHelpers;
|
||||
template <typename U, Kind K>
|
||||
friend struct List;
|
||||
friend class Orphanage;
|
||||
template <typename U, Kind K>
|
||||
friend struct ToDynamic_;
|
||||
};
|
||||
|
||||
class Builder {
|
||||
public:
|
||||
typedef List<T> Builds;
|
||||
|
||||
Builder() = delete;
|
||||
inline Builder(decltype(nullptr)) {}
|
||||
inline explicit Builder(_::ListBuilder builder): builder(builder) {}
|
||||
|
||||
inline operator Reader() const { return Reader(builder.asReader()); }
|
||||
inline Reader asReader() const { return Reader(builder.asReader()); }
|
||||
|
||||
inline uint size() const { return unbound(builder.size() / ELEMENTS); }
|
||||
inline typename T::Client operator[](uint index) {
|
||||
KJ_IREQUIRE(index < size());
|
||||
return typename T::Client(builder.getPointerElement(
|
||||
bounded(index) * ELEMENTS).getCapability());
|
||||
}
|
||||
inline void set(uint index, typename T::Client value) {
|
||||
KJ_IREQUIRE(index < size());
|
||||
builder.getPointerElement(bounded(index) * ELEMENTS).setCapability(kj::mv(value.hook));
|
||||
}
|
||||
inline void adopt(uint index, Orphan<T>&& value) {
|
||||
KJ_IREQUIRE(index < size());
|
||||
builder.getPointerElement(bounded(index) * ELEMENTS).adopt(kj::mv(value));
|
||||
}
|
||||
inline Orphan<T> disown(uint index) {
|
||||
KJ_IREQUIRE(index < size());
|
||||
return Orphan<T>(builder.getPointerElement(bounded(index) * ELEMENTS).disown());
|
||||
}
|
||||
|
||||
typedef _::IndexingIterator<Builder, typename T::Client> Iterator;
|
||||
inline Iterator begin() { return Iterator(this, 0); }
|
||||
inline Iterator end() { return Iterator(this, size()); }
|
||||
|
||||
private:
|
||||
_::ListBuilder builder;
|
||||
friend class Orphanage;
|
||||
template <typename U, Kind K>
|
||||
friend struct ToDynamic_;
|
||||
};
|
||||
|
||||
private:
|
||||
inline static _::ListBuilder initPointer(_::PointerBuilder builder, uint size) {
|
||||
return builder.initList(ElementSize::POINTER, bounded(size) * ELEMENTS);
|
||||
}
|
||||
inline static _::ListBuilder getFromPointer(_::PointerBuilder builder, const word* defaultValue) {
|
||||
return builder.getList(ElementSize::POINTER, defaultValue);
|
||||
}
|
||||
inline static _::ListReader getFromPointer(
|
||||
const _::PointerReader& reader, const word* defaultValue) {
|
||||
return reader.getList(ElementSize::POINTER, defaultValue);
|
||||
}
|
||||
|
||||
template <typename U, Kind k>
|
||||
friend struct List;
|
||||
template <typename U, Kind K>
|
||||
friend struct _::PointerHelpers;
|
||||
};
|
||||
|
||||
// =======================================================================================
|
||||
// Inline implementation details
|
||||
|
||||
template <typename Params, typename Results>
|
||||
RemotePromise<Results> Request<Params, Results>::send() {
|
||||
auto typelessPromise = hook->send();
|
||||
hook = nullptr; // prevent reuse
|
||||
|
||||
// Convert the Promise to return the correct response type.
|
||||
// Explicitly upcast to kj::Promise to make clear that calling .then() doesn't invalidate the
|
||||
// Pipeline part of the RemotePromise.
|
||||
auto typedPromise = kj::implicitCast<kj::Promise<Response<AnyPointer>>&>(typelessPromise)
|
||||
.then([](Response<AnyPointer>&& response) -> Response<Results> {
|
||||
return Response<Results>(response.getAs<Results>(), kj::mv(response.hook));
|
||||
});
|
||||
|
||||
// Wrap the typeless pipeline in a typed wrapper.
|
||||
typename Results::Pipeline typedPipeline(
|
||||
kj::mv(kj::implicitCast<AnyPointer::Pipeline&>(typelessPromise)));
|
||||
|
||||
return RemotePromise<Results>(kj::mv(typedPromise), kj::mv(typedPipeline));
|
||||
}
|
||||
|
||||
inline Capability::Client::Client(kj::Own<ClientHook>&& hook): hook(kj::mv(hook)) {}
|
||||
template <typename T, typename>
|
||||
inline Capability::Client::Client(kj::Own<T>&& server)
|
||||
: hook(makeLocalClient(kj::mv(server))) {}
|
||||
template <typename T, typename>
|
||||
inline Capability::Client::Client(kj::Promise<T>&& promise)
|
||||
: hook(newLocalPromiseClient(promise.then([](T&& t) { return kj::mv(t.hook); }))) {}
|
||||
inline Capability::Client::Client(Client& other): hook(other.hook->addRef()) {}
|
||||
inline Capability::Client& Capability::Client::operator=(Client& other) {
|
||||
hook = other.hook->addRef();
|
||||
return *this;
|
||||
}
|
||||
template <typename T>
|
||||
inline typename T::Client Capability::Client::castAs() {
|
||||
return typename T::Client(hook->addRef());
|
||||
}
|
||||
inline kj::Promise<void> Capability::Client::whenResolved() {
|
||||
return hook->whenResolved();
|
||||
}
|
||||
inline Request<AnyPointer, AnyPointer> Capability::Client::typelessRequest(
|
||||
uint64_t interfaceId, uint16_t methodId,
|
||||
kj::Maybe<MessageSize> sizeHint) {
|
||||
return newCall<AnyPointer, AnyPointer>(interfaceId, methodId, sizeHint);
|
||||
}
|
||||
template <typename Params, typename Results>
|
||||
inline Request<Params, Results> Capability::Client::newCall(
|
||||
uint64_t interfaceId, uint16_t methodId, kj::Maybe<MessageSize> sizeHint) {
|
||||
auto typeless = hook->newCall(interfaceId, methodId, sizeHint);
|
||||
return Request<Params, Results>(typeless.template getAs<Params>(), kj::mv(typeless.hook));
|
||||
}
|
||||
|
||||
template <typename Params, typename Results>
|
||||
inline CallContext<Params, Results>::CallContext(CallContextHook& hook): hook(&hook) {}
|
||||
template <typename Params, typename Results>
|
||||
inline typename Params::Reader CallContext<Params, Results>::getParams() {
|
||||
return hook->getParams().template getAs<Params>();
|
||||
}
|
||||
template <typename Params, typename Results>
|
||||
inline void CallContext<Params, Results>::releaseParams() {
|
||||
hook->releaseParams();
|
||||
}
|
||||
template <typename Params, typename Results>
|
||||
inline typename Results::Builder CallContext<Params, Results>::getResults(
|
||||
kj::Maybe<MessageSize> sizeHint) {
|
||||
// `template` keyword needed due to: http://llvm.org/bugs/show_bug.cgi?id=17401
|
||||
return hook->getResults(sizeHint).template getAs<Results>();
|
||||
}
|
||||
template <typename Params, typename Results>
|
||||
inline typename Results::Builder CallContext<Params, Results>::initResults(
|
||||
kj::Maybe<MessageSize> sizeHint) {
|
||||
// `template` keyword needed due to: http://llvm.org/bugs/show_bug.cgi?id=17401
|
||||
return hook->getResults(sizeHint).template initAs<Results>();
|
||||
}
|
||||
template <typename Params, typename Results>
|
||||
inline void CallContext<Params, Results>::setResults(typename Results::Reader value) {
|
||||
hook->getResults(value.totalSize()).template setAs<Results>(value);
|
||||
}
|
||||
template <typename Params, typename Results>
|
||||
inline void CallContext<Params, Results>::adoptResults(Orphan<Results>&& value) {
|
||||
hook->getResults(nullptr).adopt(kj::mv(value));
|
||||
}
|
||||
template <typename Params, typename Results>
|
||||
inline Orphanage CallContext<Params, Results>::getResultsOrphanage(
|
||||
kj::Maybe<MessageSize> sizeHint) {
|
||||
return Orphanage::getForMessageContaining(hook->getResults(sizeHint));
|
||||
}
|
||||
template <typename Params, typename Results>
|
||||
template <typename SubParams>
|
||||
inline kj::Promise<void> CallContext<Params, Results>::tailCall(
|
||||
Request<SubParams, Results>&& tailRequest) {
|
||||
return hook->tailCall(kj::mv(tailRequest.hook));
|
||||
}
|
||||
template <typename Params, typename Results>
|
||||
inline void CallContext<Params, Results>::allowCancellation() {
|
||||
hook->allowCancellation();
|
||||
}
|
||||
|
||||
template <typename Params, typename Results>
|
||||
CallContext<Params, Results> Capability::Server::internalGetTypedContext(
|
||||
CallContext<AnyPointer, AnyPointer> typeless) {
|
||||
return CallContext<Params, Results>(*typeless.hook);
|
||||
}
|
||||
|
||||
Capability::Client Capability::Server::thisCap() {
|
||||
return Client(thisHook->addRef());
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
T ReaderCapabilityTable::imbue(T reader) {
|
||||
return T(_::PointerHelpers<FromReader<T>>::getInternalReader(reader).imbue(this));
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
T BuilderCapabilityTable::imbue(T builder) {
|
||||
return T(_::PointerHelpers<FromBuilder<T>>::getInternalBuilder(kj::mv(builder)).imbue(this));
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
typename T::Client CapabilityServerSet<T>::add(kj::Own<typename T::Server>&& server) {
|
||||
void* ptr = reinterpret_cast<void*>(server.get());
|
||||
// Clang insists that `castAs` is a template-dependent member and therefore we need the
|
||||
// `template` keyword here, but AFAICT this is wrong: addImpl() is not a template.
|
||||
return addInternal(kj::mv(server), ptr).template castAs<T>();
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
kj::Promise<kj::Maybe<typename T::Server&>> CapabilityServerSet<T>::getLocalServer(
|
||||
typename T::Client& client) {
|
||||
return getLocalServerInternal(client)
|
||||
.then([](void* server) -> kj::Maybe<typename T::Server&> {
|
||||
if (server == nullptr) {
|
||||
return nullptr;
|
||||
} else {
|
||||
return *reinterpret_cast<typename T::Server*>(server);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
struct Orphanage::GetInnerReader<T, Kind::INTERFACE> {
|
||||
static inline kj::Own<ClientHook> apply(typename T::Client t) {
|
||||
return ClientHook::from(kj::mv(t));
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace capnp
|
||||
|
||||
#endif // CAPNP_CAPABILITY_H_
|
||||
723
phonelibs/capnp-cpp/include/capnp/common.h
Normal file
723
phonelibs/capnp-cpp/include/capnp/common.h
Normal file
@@ -0,0 +1,723 @@
|
||||
// Copyright (c) 2013-2014 Sandstorm Development Group, Inc. and contributors
|
||||
// Licensed under the MIT License:
|
||||
//
|
||||
// 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.
|
||||
|
||||
// This file contains types which are intended to help detect incorrect usage at compile
|
||||
// time, but should then be optimized down to basic primitives (usually, integers) by the
|
||||
// compiler.
|
||||
|
||||
#ifndef CAPNP_COMMON_H_
|
||||
#define CAPNP_COMMON_H_
|
||||
|
||||
#if defined(__GNUC__) && !defined(CAPNP_HEADER_WARNINGS)
|
||||
#pragma GCC system_header
|
||||
#endif
|
||||
|
||||
#include <inttypes.h>
|
||||
#include <kj/string.h>
|
||||
#include <kj/memory.h>
|
||||
|
||||
#if CAPNP_DEBUG_TYPES
|
||||
#include <kj/units.h>
|
||||
#endif
|
||||
|
||||
namespace capnp {
|
||||
|
||||
#define CAPNP_VERSION_MAJOR 0
|
||||
#define CAPNP_VERSION_MINOR 6
|
||||
#define CAPNP_VERSION_MICRO 1
|
||||
|
||||
#define CAPNP_VERSION \
|
||||
(CAPNP_VERSION_MAJOR * 1000000 + CAPNP_VERSION_MINOR * 1000 + CAPNP_VERSION_MICRO)
|
||||
|
||||
#ifndef CAPNP_LITE
|
||||
#define CAPNP_LITE 0
|
||||
#endif
|
||||
|
||||
typedef unsigned int uint;
|
||||
|
||||
struct Void {
|
||||
// Type used for Void fields. Using C++'s "void" type creates a bunch of issues since it behaves
|
||||
// differently from other types.
|
||||
|
||||
inline constexpr bool operator==(Void other) const { return true; }
|
||||
inline constexpr bool operator!=(Void other) const { return false; }
|
||||
};
|
||||
|
||||
static constexpr Void VOID = Void();
|
||||
// Constant value for `Void`, which is an empty struct.
|
||||
|
||||
inline kj::StringPtr KJ_STRINGIFY(Void) { return "void"; }
|
||||
|
||||
struct Text;
|
||||
struct Data;
|
||||
|
||||
enum class Kind: uint8_t {
|
||||
PRIMITIVE,
|
||||
BLOB,
|
||||
ENUM,
|
||||
STRUCT,
|
||||
UNION,
|
||||
INTERFACE,
|
||||
LIST,
|
||||
|
||||
OTHER
|
||||
// Some other type which is often a type parameter to Cap'n Proto templates, but which needs
|
||||
// special handling. This includes types like AnyPointer, Dynamic*, etc.
|
||||
};
|
||||
|
||||
enum class Style: uint8_t {
|
||||
PRIMITIVE,
|
||||
POINTER, // other than struct
|
||||
STRUCT,
|
||||
CAPABILITY
|
||||
};
|
||||
|
||||
enum class ElementSize: uint8_t {
|
||||
// Size of a list element.
|
||||
|
||||
VOID = 0,
|
||||
BIT = 1,
|
||||
BYTE = 2,
|
||||
TWO_BYTES = 3,
|
||||
FOUR_BYTES = 4,
|
||||
EIGHT_BYTES = 5,
|
||||
|
||||
POINTER = 6,
|
||||
|
||||
INLINE_COMPOSITE = 7
|
||||
};
|
||||
|
||||
enum class PointerType {
|
||||
// Various wire types a pointer field can take
|
||||
|
||||
NULL_,
|
||||
// Should be NULL, but that's #defined in stddef.h
|
||||
|
||||
STRUCT,
|
||||
LIST,
|
||||
CAPABILITY
|
||||
};
|
||||
|
||||
namespace schemas {
|
||||
|
||||
template <typename T>
|
||||
struct EnumInfo;
|
||||
|
||||
} // namespace schemas
|
||||
|
||||
namespace _ { // private
|
||||
|
||||
template <typename T, typename = void> struct Kind_;
|
||||
|
||||
template <> struct Kind_<Void> { static constexpr Kind kind = Kind::PRIMITIVE; };
|
||||
template <> struct Kind_<bool> { static constexpr Kind kind = Kind::PRIMITIVE; };
|
||||
template <> struct Kind_<int8_t> { static constexpr Kind kind = Kind::PRIMITIVE; };
|
||||
template <> struct Kind_<int16_t> { static constexpr Kind kind = Kind::PRIMITIVE; };
|
||||
template <> struct Kind_<int32_t> { static constexpr Kind kind = Kind::PRIMITIVE; };
|
||||
template <> struct Kind_<int64_t> { static constexpr Kind kind = Kind::PRIMITIVE; };
|
||||
template <> struct Kind_<uint8_t> { static constexpr Kind kind = Kind::PRIMITIVE; };
|
||||
template <> struct Kind_<uint16_t> { static constexpr Kind kind = Kind::PRIMITIVE; };
|
||||
template <> struct Kind_<uint32_t> { static constexpr Kind kind = Kind::PRIMITIVE; };
|
||||
template <> struct Kind_<uint64_t> { static constexpr Kind kind = Kind::PRIMITIVE; };
|
||||
template <> struct Kind_<float> { static constexpr Kind kind = Kind::PRIMITIVE; };
|
||||
template <> struct Kind_<double> { static constexpr Kind kind = Kind::PRIMITIVE; };
|
||||
template <> struct Kind_<Text> { static constexpr Kind kind = Kind::BLOB; };
|
||||
template <> struct Kind_<Data> { static constexpr Kind kind = Kind::BLOB; };
|
||||
|
||||
template <typename T> struct Kind_<T, kj::VoidSfinae<typename T::_capnpPrivate::IsStruct>> {
|
||||
static constexpr Kind kind = Kind::STRUCT;
|
||||
};
|
||||
template <typename T> struct Kind_<T, kj::VoidSfinae<typename T::_capnpPrivate::IsInterface>> {
|
||||
static constexpr Kind kind = Kind::INTERFACE;
|
||||
};
|
||||
template <typename T> struct Kind_<T, kj::VoidSfinae<typename schemas::EnumInfo<T>::IsEnum>> {
|
||||
static constexpr Kind kind = Kind::ENUM;
|
||||
};
|
||||
|
||||
} // namespace _ (private)
|
||||
|
||||
template <typename T, Kind k = _::Kind_<T>::kind>
|
||||
inline constexpr Kind kind() {
|
||||
// This overload of kind() matches types which have a Kind_ specialization.
|
||||
|
||||
return k;
|
||||
}
|
||||
|
||||
#if _MSC_VER
|
||||
|
||||
#define CAPNP_KIND(T) ::capnp::_::Kind_<T>::kind
|
||||
// Avoid constexpr methods in MSVC (it remains buggy in many situations).
|
||||
|
||||
#else // _MSC_VER
|
||||
|
||||
#define CAPNP_KIND(T) ::capnp::kind<T>()
|
||||
// Use this macro rather than kind<T>() in any code which must work in MSVC.
|
||||
|
||||
#endif // _MSC_VER, else
|
||||
|
||||
#if !CAPNP_LITE
|
||||
|
||||
template <typename T, Kind k = kind<T>()>
|
||||
inline constexpr Style style() {
|
||||
return k == Kind::PRIMITIVE || k == Kind::ENUM ? Style::PRIMITIVE
|
||||
: k == Kind::STRUCT ? Style::STRUCT
|
||||
: k == Kind::INTERFACE ? Style::CAPABILITY : Style::POINTER;
|
||||
}
|
||||
|
||||
#endif // !CAPNP_LITE
|
||||
|
||||
template <typename T, Kind k = CAPNP_KIND(T)>
|
||||
struct List;
|
||||
|
||||
#if _MSC_VER
|
||||
|
||||
template <typename T, Kind k>
|
||||
struct List {};
|
||||
// For some reason, without this declaration, MSVC will error out on some uses of List
|
||||
// claiming that "T" -- as used in the default initializer for the second template param, "k" --
|
||||
// is not defined. I do not understand this error, but adding this empty default declaration fixes
|
||||
// it.
|
||||
|
||||
#endif
|
||||
|
||||
template <typename T> struct ListElementType_;
|
||||
template <typename T> struct ListElementType_<List<T>> { typedef T Type; };
|
||||
template <typename T> using ListElementType = typename ListElementType_<T>::Type;
|
||||
|
||||
namespace _ { // private
|
||||
template <typename T, Kind k> struct Kind_<List<T, k>> {
|
||||
static constexpr Kind kind = Kind::LIST;
|
||||
};
|
||||
} // namespace _ (private)
|
||||
|
||||
template <typename T, Kind k = CAPNP_KIND(T)> struct ReaderFor_ { typedef typename T::Reader Type; };
|
||||
template <typename T> struct ReaderFor_<T, Kind::PRIMITIVE> { typedef T Type; };
|
||||
template <typename T> struct ReaderFor_<T, Kind::ENUM> { typedef T Type; };
|
||||
template <typename T> struct ReaderFor_<T, Kind::INTERFACE> { typedef typename T::Client Type; };
|
||||
template <typename T> using ReaderFor = typename ReaderFor_<T>::Type;
|
||||
// The type returned by List<T>::Reader::operator[].
|
||||
|
||||
template <typename T, Kind k = CAPNP_KIND(T)> struct BuilderFor_ { typedef typename T::Builder Type; };
|
||||
template <typename T> struct BuilderFor_<T, Kind::PRIMITIVE> { typedef T Type; };
|
||||
template <typename T> struct BuilderFor_<T, Kind::ENUM> { typedef T Type; };
|
||||
template <typename T> struct BuilderFor_<T, Kind::INTERFACE> { typedef typename T::Client Type; };
|
||||
template <typename T> using BuilderFor = typename BuilderFor_<T>::Type;
|
||||
// The type returned by List<T>::Builder::operator[].
|
||||
|
||||
template <typename T, Kind k = CAPNP_KIND(T)> struct PipelineFor_ { typedef typename T::Pipeline Type;};
|
||||
template <typename T> struct PipelineFor_<T, Kind::INTERFACE> { typedef typename T::Client Type; };
|
||||
template <typename T> using PipelineFor = typename PipelineFor_<T>::Type;
|
||||
|
||||
template <typename T, Kind k = CAPNP_KIND(T)> struct TypeIfEnum_;
|
||||
template <typename T> struct TypeIfEnum_<T, Kind::ENUM> { typedef T Type; };
|
||||
|
||||
template <typename T>
|
||||
using TypeIfEnum = typename TypeIfEnum_<kj::Decay<T>>::Type;
|
||||
|
||||
template <typename T>
|
||||
using FromReader = typename kj::Decay<T>::Reads;
|
||||
// FromReader<MyType::Reader> = MyType (for any Cap'n Proto type).
|
||||
|
||||
template <typename T>
|
||||
using FromBuilder = typename kj::Decay<T>::Builds;
|
||||
// FromBuilder<MyType::Builder> = MyType (for any Cap'n Proto type).
|
||||
|
||||
template <typename T>
|
||||
using FromPipeline = typename kj::Decay<T>::Pipelines;
|
||||
// FromBuilder<MyType::Pipeline> = MyType (for any Cap'n Proto type).
|
||||
|
||||
template <typename T>
|
||||
using FromClient = typename kj::Decay<T>::Calls;
|
||||
// FromReader<MyType::Client> = MyType (for any Cap'n Proto interface type).
|
||||
|
||||
template <typename T>
|
||||
using FromServer = typename kj::Decay<T>::Serves;
|
||||
// FromBuilder<MyType::Server> = MyType (for any Cap'n Proto interface type).
|
||||
|
||||
template <typename T, typename = void>
|
||||
struct FromAny_;
|
||||
|
||||
template <typename T>
|
||||
struct FromAny_<T, kj::VoidSfinae<FromReader<T>>> {
|
||||
using Type = FromReader<T>;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct FromAny_<T, kj::VoidSfinae<FromBuilder<T>>> {
|
||||
using Type = FromBuilder<T>;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct FromAny_<T, kj::VoidSfinae<FromPipeline<T>>> {
|
||||
using Type = FromPipeline<T>;
|
||||
};
|
||||
|
||||
// Note that T::Client is covered by FromReader
|
||||
|
||||
template <typename T>
|
||||
struct FromAny_<kj::Own<T>, kj::VoidSfinae<FromServer<T>>> {
|
||||
using Type = FromServer<T>;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct FromAny_<T,
|
||||
kj::EnableIf<_::Kind_<T>::kind == Kind::PRIMITIVE || _::Kind_<T>::kind == Kind::ENUM>> {
|
||||
// TODO(msvc): Ideally the EnableIf condition would be `style<T>() == Style::PRIMITIVE`, but MSVC
|
||||
// cannot yet use style<T>() in this constexpr context.
|
||||
|
||||
using Type = kj::Decay<T>;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
using FromAny = typename FromAny_<T>::Type;
|
||||
// Given any Cap'n Proto value type as an input, return the Cap'n Proto base type. That is:
|
||||
//
|
||||
// Foo::Reader -> Foo
|
||||
// Foo::Builder -> Foo
|
||||
// Foo::Pipeline -> Foo
|
||||
// Foo::Client -> Foo
|
||||
// Own<Foo::Server> -> Foo
|
||||
// uint32_t -> uint32_t
|
||||
|
||||
namespace _ { // private
|
||||
|
||||
template <typename T, Kind k = CAPNP_KIND(T)>
|
||||
struct PointerHelpers;
|
||||
|
||||
#if _MSC_VER
|
||||
|
||||
template <typename T, Kind k>
|
||||
struct PointerHelpers {};
|
||||
// For some reason, without this declaration, MSVC will error out on some uses of PointerHelpers
|
||||
// claiming that "T" -- as used in the default initializer for the second template param, "k" --
|
||||
// is not defined. I do not understand this error, but adding this empty default declaration fixes
|
||||
// it.
|
||||
|
||||
#endif
|
||||
|
||||
} // namespace _ (private)
|
||||
|
||||
struct MessageSize {
|
||||
// Size of a message. Every struct type has a method `.totalSize()` that returns this.
|
||||
uint64_t wordCount;
|
||||
uint capCount;
|
||||
};
|
||||
|
||||
// =======================================================================================
|
||||
// Raw memory types and measures
|
||||
|
||||
using kj::byte;
|
||||
|
||||
class word { uint64_t content KJ_UNUSED_MEMBER; KJ_DISALLOW_COPY(word); public: word() = default; };
|
||||
// word is an opaque type with size of 64 bits. This type is useful only to make pointer
|
||||
// arithmetic clearer. Since the contents are private, the only way to access them is to first
|
||||
// reinterpret_cast to some other pointer type.
|
||||
//
|
||||
// Copying is disallowed because you should always use memcpy(). Otherwise, you may run afoul of
|
||||
// aliasing rules.
|
||||
//
|
||||
// A pointer of type word* should always be word-aligned even if won't actually be dereferenced as
|
||||
// that type.
|
||||
|
||||
static_assert(sizeof(byte) == 1, "uint8_t is not one byte?");
|
||||
static_assert(sizeof(word) == 8, "uint64_t is not 8 bytes?");
|
||||
|
||||
#if CAPNP_DEBUG_TYPES
|
||||
// Set CAPNP_DEBUG_TYPES to 1 to use kj::Quantity for "count" types. Otherwise, plain integers are
|
||||
// used. All the code should still operate exactly the same, we just lose compile-time checking.
|
||||
// Note that this will also change symbol names, so it's important that the library and any clients
|
||||
// be compiled with the same setting here.
|
||||
//
|
||||
// We disable this by default to reduce symbol name size and avoid any possibility of the compiler
|
||||
// failing to fully-optimize the types, but anyone modifying Cap'n Proto itself should enable this
|
||||
// during development and testing.
|
||||
|
||||
namespace _ { class BitLabel; class ElementLabel; struct WirePointer; }
|
||||
|
||||
template <uint width, typename T = uint>
|
||||
using BitCountN = kj::Quantity<kj::Bounded<kj::maxValueForBits<width>(), T>, _::BitLabel>;
|
||||
template <uint width, typename T = uint>
|
||||
using ByteCountN = kj::Quantity<kj::Bounded<kj::maxValueForBits<width>(), T>, byte>;
|
||||
template <uint width, typename T = uint>
|
||||
using WordCountN = kj::Quantity<kj::Bounded<kj::maxValueForBits<width>(), T>, word>;
|
||||
template <uint width, typename T = uint>
|
||||
using ElementCountN = kj::Quantity<kj::Bounded<kj::maxValueForBits<width>(), T>, _::ElementLabel>;
|
||||
template <uint width, typename T = uint>
|
||||
using WirePointerCountN = kj::Quantity<kj::Bounded<kj::maxValueForBits<width>(), T>, _::WirePointer>;
|
||||
|
||||
typedef BitCountN<8, uint8_t> BitCount8;
|
||||
typedef BitCountN<16, uint16_t> BitCount16;
|
||||
typedef BitCountN<32, uint32_t> BitCount32;
|
||||
typedef BitCountN<64, uint64_t> BitCount64;
|
||||
typedef BitCountN<sizeof(uint) * 8, uint> BitCount;
|
||||
|
||||
typedef ByteCountN<8, uint8_t> ByteCount8;
|
||||
typedef ByteCountN<16, uint16_t> ByteCount16;
|
||||
typedef ByteCountN<32, uint32_t> ByteCount32;
|
||||
typedef ByteCountN<64, uint64_t> ByteCount64;
|
||||
typedef ByteCountN<sizeof(uint) * 8, uint> ByteCount;
|
||||
|
||||
typedef WordCountN<8, uint8_t> WordCount8;
|
||||
typedef WordCountN<16, uint16_t> WordCount16;
|
||||
typedef WordCountN<32, uint32_t> WordCount32;
|
||||
typedef WordCountN<64, uint64_t> WordCount64;
|
||||
typedef WordCountN<sizeof(uint) * 8, uint> WordCount;
|
||||
|
||||
typedef ElementCountN<8, uint8_t> ElementCount8;
|
||||
typedef ElementCountN<16, uint16_t> ElementCount16;
|
||||
typedef ElementCountN<32, uint32_t> ElementCount32;
|
||||
typedef ElementCountN<64, uint64_t> ElementCount64;
|
||||
typedef ElementCountN<sizeof(uint) * 8, uint> ElementCount;
|
||||
|
||||
typedef WirePointerCountN<8, uint8_t> WirePointerCount8;
|
||||
typedef WirePointerCountN<16, uint16_t> WirePointerCount16;
|
||||
typedef WirePointerCountN<32, uint32_t> WirePointerCount32;
|
||||
typedef WirePointerCountN<64, uint64_t> WirePointerCount64;
|
||||
typedef WirePointerCountN<sizeof(uint) * 8, uint> WirePointerCount;
|
||||
|
||||
template <uint width>
|
||||
using BitsPerElementN = decltype(BitCountN<width>() / ElementCountN<width>());
|
||||
template <uint width>
|
||||
using BytesPerElementN = decltype(ByteCountN<width>() / ElementCountN<width>());
|
||||
template <uint width>
|
||||
using WordsPerElementN = decltype(WordCountN<width>() / ElementCountN<width>());
|
||||
template <uint width>
|
||||
using PointersPerElementN = decltype(WirePointerCountN<width>() / ElementCountN<width>());
|
||||
|
||||
using kj::bounded;
|
||||
using kj::unbound;
|
||||
using kj::unboundAs;
|
||||
using kj::unboundMax;
|
||||
using kj::unboundMaxBits;
|
||||
using kj::assertMax;
|
||||
using kj::assertMaxBits;
|
||||
using kj::upgradeBound;
|
||||
using kj::ThrowOverflow;
|
||||
using kj::assumeBits;
|
||||
using kj::assumeMax;
|
||||
using kj::subtractChecked;
|
||||
using kj::trySubtract;
|
||||
|
||||
template <typename T, typename U>
|
||||
inline constexpr U* operator+(U* ptr, kj::Quantity<T, U> offset) {
|
||||
return ptr + unbound(offset / kj::unit<kj::Quantity<T, U>>());
|
||||
}
|
||||
template <typename T, typename U>
|
||||
inline constexpr const U* operator+(const U* ptr, kj::Quantity<T, U> offset) {
|
||||
return ptr + unbound(offset / kj::unit<kj::Quantity<T, U>>());
|
||||
}
|
||||
template <typename T, typename U>
|
||||
inline constexpr U* operator+=(U*& ptr, kj::Quantity<T, U> offset) {
|
||||
return ptr = ptr + unbound(offset / kj::unit<kj::Quantity<T, U>>());
|
||||
}
|
||||
template <typename T, typename U>
|
||||
inline constexpr const U* operator+=(const U*& ptr, kj::Quantity<T, U> offset) {
|
||||
return ptr = ptr + unbound(offset / kj::unit<kj::Quantity<T, U>>());
|
||||
}
|
||||
|
||||
template <typename T, typename U>
|
||||
inline constexpr U* operator-(U* ptr, kj::Quantity<T, U> offset) {
|
||||
return ptr - unbound(offset / kj::unit<kj::Quantity<T, U>>());
|
||||
}
|
||||
template <typename T, typename U>
|
||||
inline constexpr const U* operator-(const U* ptr, kj::Quantity<T, U> offset) {
|
||||
return ptr - unbound(offset / kj::unit<kj::Quantity<T, U>>());
|
||||
}
|
||||
template <typename T, typename U>
|
||||
inline constexpr U* operator-=(U*& ptr, kj::Quantity<T, U> offset) {
|
||||
return ptr = ptr - unbound(offset / kj::unit<kj::Quantity<T, U>>());
|
||||
}
|
||||
template <typename T, typename U>
|
||||
inline constexpr const U* operator-=(const U*& ptr, kj::Quantity<T, U> offset) {
|
||||
return ptr = ptr - unbound(offset / kj::unit<kj::Quantity<T, U>>());
|
||||
}
|
||||
|
||||
constexpr auto BITS = kj::unit<BitCountN<1>>();
|
||||
constexpr auto BYTES = kj::unit<ByteCountN<1>>();
|
||||
constexpr auto WORDS = kj::unit<WordCountN<1>>();
|
||||
constexpr auto ELEMENTS = kj::unit<ElementCountN<1>>();
|
||||
constexpr auto POINTERS = kj::unit<WirePointerCountN<1>>();
|
||||
|
||||
constexpr auto ZERO = kj::bounded<0>();
|
||||
constexpr auto ONE = kj::bounded<1>();
|
||||
|
||||
// GCC 4.7 actually gives unused warnings on these constants in opt mode...
|
||||
constexpr auto BITS_PER_BYTE KJ_UNUSED = bounded<8>() * BITS / BYTES;
|
||||
constexpr auto BITS_PER_WORD KJ_UNUSED = bounded<64>() * BITS / WORDS;
|
||||
constexpr auto BYTES_PER_WORD KJ_UNUSED = bounded<8>() * BYTES / WORDS;
|
||||
|
||||
constexpr auto BITS_PER_POINTER KJ_UNUSED = bounded<64>() * BITS / POINTERS;
|
||||
constexpr auto BYTES_PER_POINTER KJ_UNUSED = bounded<8>() * BYTES / POINTERS;
|
||||
constexpr auto WORDS_PER_POINTER KJ_UNUSED = ONE * WORDS / POINTERS;
|
||||
|
||||
constexpr auto POINTER_SIZE_IN_WORDS = ONE * POINTERS * WORDS_PER_POINTER;
|
||||
|
||||
constexpr uint SEGMENT_WORD_COUNT_BITS = 29; // Number of words in a segment.
|
||||
constexpr uint LIST_ELEMENT_COUNT_BITS = 29; // Number of elements in a list.
|
||||
constexpr uint STRUCT_DATA_WORD_COUNT_BITS = 16; // Number of words in a Struct data section.
|
||||
constexpr uint STRUCT_POINTER_COUNT_BITS = 16; // Number of pointers in a Struct pointer section.
|
||||
constexpr uint BLOB_SIZE_BITS = 29; // Number of bytes in a blob.
|
||||
|
||||
typedef WordCountN<SEGMENT_WORD_COUNT_BITS> SegmentWordCount;
|
||||
typedef ElementCountN<LIST_ELEMENT_COUNT_BITS> ListElementCount;
|
||||
typedef WordCountN<STRUCT_DATA_WORD_COUNT_BITS, uint16_t> StructDataWordCount;
|
||||
typedef WirePointerCountN<STRUCT_POINTER_COUNT_BITS, uint16_t> StructPointerCount;
|
||||
typedef ByteCountN<BLOB_SIZE_BITS> BlobSize;
|
||||
|
||||
constexpr auto MAX_SEGMENT_WORDS =
|
||||
bounded<kj::maxValueForBits<SEGMENT_WORD_COUNT_BITS>()>() * WORDS;
|
||||
constexpr auto MAX_LIST_ELEMENTS =
|
||||
bounded<kj::maxValueForBits<LIST_ELEMENT_COUNT_BITS>()>() * ELEMENTS;
|
||||
constexpr auto MAX_STUCT_DATA_WORDS =
|
||||
bounded<kj::maxValueForBits<STRUCT_DATA_WORD_COUNT_BITS>()>() * WORDS;
|
||||
constexpr auto MAX_STRUCT_POINTER_COUNT =
|
||||
bounded<kj::maxValueForBits<STRUCT_POINTER_COUNT_BITS>()>() * POINTERS;
|
||||
|
||||
using StructDataBitCount = decltype(WordCountN<STRUCT_POINTER_COUNT_BITS>() * BITS_PER_WORD);
|
||||
// Number of bits in a Struct data segment (should come out to BitCountN<22>).
|
||||
|
||||
using StructDataOffset = decltype(StructDataBitCount() * (ONE * ELEMENTS / BITS));
|
||||
using StructPointerOffset = StructPointerCount;
|
||||
// Type of a field offset.
|
||||
|
||||
inline StructDataOffset assumeDataOffset(uint32_t offset) {
|
||||
return assumeMax(MAX_STUCT_DATA_WORDS * BITS_PER_WORD * (ONE * ELEMENTS / BITS),
|
||||
bounded(offset) * ELEMENTS);
|
||||
}
|
||||
|
||||
inline StructPointerOffset assumePointerOffset(uint32_t offset) {
|
||||
return assumeMax(MAX_STRUCT_POINTER_COUNT, bounded(offset) * POINTERS);
|
||||
}
|
||||
|
||||
constexpr uint MAX_TEXT_SIZE = kj::maxValueForBits<BLOB_SIZE_BITS>() - 1;
|
||||
typedef kj::Quantity<kj::Bounded<MAX_TEXT_SIZE, uint>, byte> TextSize;
|
||||
// Not including NUL terminator.
|
||||
|
||||
template <typename T>
|
||||
inline KJ_CONSTEXPR() decltype(bounded<sizeof(T)>() * BYTES / ELEMENTS) bytesPerElement() {
|
||||
return bounded<sizeof(T)>() * BYTES / ELEMENTS;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline KJ_CONSTEXPR() decltype(bounded<sizeof(T) * 8>() * BITS / ELEMENTS) bitsPerElement() {
|
||||
return bounded<sizeof(T) * 8>() * BITS / ELEMENTS;
|
||||
}
|
||||
|
||||
template <typename T, uint maxN>
|
||||
inline constexpr kj::Quantity<kj::Bounded<maxN, size_t>, T>
|
||||
intervalLength(const T* a, const T* b, kj::Quantity<kj::BoundedConst<maxN>, T>) {
|
||||
return kj::assumeMax<maxN>(b - a) * kj::unit<kj::Quantity<kj::BoundedConst<1u>, T>>();
|
||||
}
|
||||
|
||||
template <typename T, typename U>
|
||||
inline constexpr kj::ArrayPtr<const U> arrayPtr(const U* ptr, kj::Quantity<T, U> size) {
|
||||
return kj::ArrayPtr<const U>(ptr, unbound(size / kj::unit<kj::Quantity<T, U>>()));
|
||||
}
|
||||
template <typename T, typename U>
|
||||
inline constexpr kj::ArrayPtr<U> arrayPtr(U* ptr, kj::Quantity<T, U> size) {
|
||||
return kj::ArrayPtr<U>(ptr, unbound(size / kj::unit<kj::Quantity<T, U>>()));
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
template <uint width, typename T = uint>
|
||||
using BitCountN = T;
|
||||
template <uint width, typename T = uint>
|
||||
using ByteCountN = T;
|
||||
template <uint width, typename T = uint>
|
||||
using WordCountN = T;
|
||||
template <uint width, typename T = uint>
|
||||
using ElementCountN = T;
|
||||
template <uint width, typename T = uint>
|
||||
using WirePointerCountN = T;
|
||||
|
||||
|
||||
// XXX
|
||||
typedef BitCountN<8, uint8_t> BitCount8;
|
||||
typedef BitCountN<16, uint16_t> BitCount16;
|
||||
typedef BitCountN<32, uint32_t> BitCount32;
|
||||
typedef BitCountN<64, uint64_t> BitCount64;
|
||||
typedef BitCountN<sizeof(uint) * 8, uint> BitCount;
|
||||
|
||||
typedef ByteCountN<8, uint8_t> ByteCount8;
|
||||
typedef ByteCountN<16, uint16_t> ByteCount16;
|
||||
typedef ByteCountN<32, uint32_t> ByteCount32;
|
||||
typedef ByteCountN<64, uint64_t> ByteCount64;
|
||||
typedef ByteCountN<sizeof(uint) * 8, uint> ByteCount;
|
||||
|
||||
typedef WordCountN<8, uint8_t> WordCount8;
|
||||
typedef WordCountN<16, uint16_t> WordCount16;
|
||||
typedef WordCountN<32, uint32_t> WordCount32;
|
||||
typedef WordCountN<64, uint64_t> WordCount64;
|
||||
typedef WordCountN<sizeof(uint) * 8, uint> WordCount;
|
||||
|
||||
typedef ElementCountN<8, uint8_t> ElementCount8;
|
||||
typedef ElementCountN<16, uint16_t> ElementCount16;
|
||||
typedef ElementCountN<32, uint32_t> ElementCount32;
|
||||
typedef ElementCountN<64, uint64_t> ElementCount64;
|
||||
typedef ElementCountN<sizeof(uint) * 8, uint> ElementCount;
|
||||
|
||||
typedef WirePointerCountN<8, uint8_t> WirePointerCount8;
|
||||
typedef WirePointerCountN<16, uint16_t> WirePointerCount16;
|
||||
typedef WirePointerCountN<32, uint32_t> WirePointerCount32;
|
||||
typedef WirePointerCountN<64, uint64_t> WirePointerCount64;
|
||||
typedef WirePointerCountN<sizeof(uint) * 8, uint> WirePointerCount;
|
||||
|
||||
template <uint width>
|
||||
using BitsPerElementN = decltype(BitCountN<width>() / ElementCountN<width>());
|
||||
template <uint width>
|
||||
using BytesPerElementN = decltype(ByteCountN<width>() / ElementCountN<width>());
|
||||
template <uint width>
|
||||
using WordsPerElementN = decltype(WordCountN<width>() / ElementCountN<width>());
|
||||
template <uint width>
|
||||
using PointersPerElementN = decltype(WirePointerCountN<width>() / ElementCountN<width>());
|
||||
|
||||
using kj::ThrowOverflow;
|
||||
// YYY
|
||||
|
||||
template <uint i> inline constexpr uint bounded() { return i; }
|
||||
template <typename T> inline constexpr T bounded(T i) { return i; }
|
||||
template <typename T> inline constexpr T unbound(T i) { return i; }
|
||||
|
||||
template <typename T, typename U> inline constexpr T unboundAs(U i) { return i; }
|
||||
|
||||
template <uint64_t requestedMax, typename T> inline constexpr uint unboundMax(T i) { return i; }
|
||||
template <uint bits, typename T> inline constexpr uint unboundMaxBits(T i) { return i; }
|
||||
|
||||
template <uint newMax, typename T, typename ErrorFunc>
|
||||
inline T assertMax(T value, ErrorFunc&& func) {
|
||||
if (KJ_UNLIKELY(value > newMax)) func();
|
||||
return value;
|
||||
}
|
||||
|
||||
template <typename T, typename ErrorFunc>
|
||||
inline T assertMax(uint newMax, T value, ErrorFunc&& func) {
|
||||
if (KJ_UNLIKELY(value > newMax)) func();
|
||||
return value;
|
||||
}
|
||||
|
||||
template <uint bits, typename T, typename ErrorFunc = ThrowOverflow>
|
||||
inline T assertMaxBits(T value, ErrorFunc&& func = ErrorFunc()) {
|
||||
if (KJ_UNLIKELY(value > kj::maxValueForBits<bits>())) func();
|
||||
return value;
|
||||
}
|
||||
|
||||
template <typename T, typename ErrorFunc = ThrowOverflow>
|
||||
inline T assertMaxBits(uint bits, T value, ErrorFunc&& func = ErrorFunc()) {
|
||||
if (KJ_UNLIKELY(value > (1ull << bits) - 1)) func();
|
||||
return value;
|
||||
}
|
||||
|
||||
template <typename T, typename U> inline constexpr T upgradeBound(U i) { return i; }
|
||||
|
||||
template <uint bits, typename T> inline constexpr T assumeBits(T i) { return i; }
|
||||
template <uint64_t max, typename T> inline constexpr T assumeMax(T i) { return i; }
|
||||
|
||||
template <typename T, typename U, typename ErrorFunc = ThrowOverflow>
|
||||
inline auto subtractChecked(T a, U b, ErrorFunc&& errorFunc = ErrorFunc())
|
||||
-> decltype(a - b) {
|
||||
if (b > a) errorFunc();
|
||||
return a - b;
|
||||
}
|
||||
|
||||
template <typename T, typename U>
|
||||
inline auto trySubtract(T a, U b) -> kj::Maybe<decltype(a - b)> {
|
||||
if (b > a) {
|
||||
return nullptr;
|
||||
} else {
|
||||
return a - b;
|
||||
}
|
||||
}
|
||||
|
||||
constexpr uint BITS = 1;
|
||||
constexpr uint BYTES = 1;
|
||||
constexpr uint WORDS = 1;
|
||||
constexpr uint ELEMENTS = 1;
|
||||
constexpr uint POINTERS = 1;
|
||||
|
||||
constexpr uint ZERO = 0;
|
||||
constexpr uint ONE = 1;
|
||||
|
||||
// GCC 4.7 actually gives unused warnings on these constants in opt mode...
|
||||
constexpr uint BITS_PER_BYTE KJ_UNUSED = 8;
|
||||
constexpr uint BITS_PER_WORD KJ_UNUSED = 64;
|
||||
constexpr uint BYTES_PER_WORD KJ_UNUSED = 8;
|
||||
|
||||
constexpr uint BITS_PER_POINTER KJ_UNUSED = 64;
|
||||
constexpr uint BYTES_PER_POINTER KJ_UNUSED = 8;
|
||||
constexpr uint WORDS_PER_POINTER KJ_UNUSED = 1;
|
||||
|
||||
// XXX
|
||||
constexpr uint POINTER_SIZE_IN_WORDS = ONE * POINTERS * WORDS_PER_POINTER;
|
||||
|
||||
constexpr uint SEGMENT_WORD_COUNT_BITS = 29; // Number of words in a segment.
|
||||
constexpr uint LIST_ELEMENT_COUNT_BITS = 29; // Number of elements in a list.
|
||||
constexpr uint STRUCT_DATA_WORD_COUNT_BITS = 16; // Number of words in a Struct data section.
|
||||
constexpr uint STRUCT_POINTER_COUNT_BITS = 16; // Number of pointers in a Struct pointer section.
|
||||
constexpr uint BLOB_SIZE_BITS = 29; // Number of bytes in a blob.
|
||||
|
||||
typedef WordCountN<SEGMENT_WORD_COUNT_BITS> SegmentWordCount;
|
||||
typedef ElementCountN<LIST_ELEMENT_COUNT_BITS> ListElementCount;
|
||||
typedef WordCountN<STRUCT_DATA_WORD_COUNT_BITS, uint16_t> StructDataWordCount;
|
||||
typedef WirePointerCountN<STRUCT_POINTER_COUNT_BITS, uint16_t> StructPointerCount;
|
||||
typedef ByteCountN<BLOB_SIZE_BITS> BlobSize;
|
||||
// YYY
|
||||
|
||||
constexpr auto MAX_SEGMENT_WORDS = kj::maxValueForBits<SEGMENT_WORD_COUNT_BITS>();
|
||||
constexpr auto MAX_LIST_ELEMENTS = kj::maxValueForBits<LIST_ELEMENT_COUNT_BITS>();
|
||||
constexpr auto MAX_STUCT_DATA_WORDS = kj::maxValueForBits<STRUCT_DATA_WORD_COUNT_BITS>();
|
||||
constexpr auto MAX_STRUCT_POINTER_COUNT = kj::maxValueForBits<STRUCT_POINTER_COUNT_BITS>();
|
||||
|
||||
typedef uint StructDataBitCount;
|
||||
typedef uint StructDataOffset;
|
||||
typedef uint StructPointerOffset;
|
||||
|
||||
inline StructDataOffset assumeDataOffset(uint32_t offset) { return offset; }
|
||||
inline StructPointerOffset assumePointerOffset(uint32_t offset) { return offset; }
|
||||
|
||||
constexpr uint MAX_TEXT_SIZE = kj::maxValueForBits<BLOB_SIZE_BITS>() - 1;
|
||||
typedef uint TextSize;
|
||||
|
||||
template <typename T>
|
||||
inline KJ_CONSTEXPR() size_t bytesPerElement() { return sizeof(T); }
|
||||
|
||||
template <typename T>
|
||||
inline KJ_CONSTEXPR() size_t bitsPerElement() { return sizeof(T) * 8; }
|
||||
|
||||
template <typename T>
|
||||
inline constexpr ptrdiff_t intervalLength(const T* a, const T* b, uint) {
|
||||
return b - a;
|
||||
}
|
||||
|
||||
template <typename T, typename U>
|
||||
inline constexpr kj::ArrayPtr<const U> arrayPtr(const U* ptr, T size) {
|
||||
return kj::arrayPtr(ptr, size);
|
||||
}
|
||||
template <typename T, typename U>
|
||||
inline constexpr kj::ArrayPtr<U> arrayPtr(U* ptr, T size) {
|
||||
return kj::arrayPtr(ptr, size);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
} // namespace capnp
|
||||
|
||||
#endif // CAPNP_COMMON_H_
|
||||
860
phonelibs/capnp-cpp/include/capnp/compat/json.capnp.h
Normal file
860
phonelibs/capnp-cpp/include/capnp/compat/json.capnp.h
Normal file
@@ -0,0 +1,860 @@
|
||||
// Generated by Cap'n Proto compiler, DO NOT EDIT
|
||||
// source: json.capnp
|
||||
|
||||
#ifndef CAPNP_INCLUDED_8ef99297a43a5e34_
|
||||
#define CAPNP_INCLUDED_8ef99297a43a5e34_
|
||||
|
||||
#include <capnp/generated-header-support.h>
|
||||
#if !CAPNP_LITE
|
||||
#include <capnp/capability.h>
|
||||
#endif // !CAPNP_LITE
|
||||
|
||||
#if CAPNP_VERSION != 6001
|
||||
#error "Version mismatch between generated code and library headers. You must use the same version of the Cap'n Proto compiler and library."
|
||||
#endif
|
||||
|
||||
|
||||
namespace capnp {
|
||||
namespace schemas {
|
||||
|
||||
CAPNP_DECLARE_SCHEMA(8825ffaa852cda72);
|
||||
CAPNP_DECLARE_SCHEMA(c27855d853a937cc);
|
||||
CAPNP_DECLARE_SCHEMA(9bbf84153dd4bb60);
|
||||
|
||||
} // namespace schemas
|
||||
} // namespace capnp
|
||||
|
||||
namespace capnp {
|
||||
|
||||
struct JsonValue {
|
||||
JsonValue() = delete;
|
||||
|
||||
class Reader;
|
||||
class Builder;
|
||||
class Pipeline;
|
||||
enum Which: uint16_t {
|
||||
NULL_,
|
||||
BOOLEAN,
|
||||
NUMBER,
|
||||
STRING,
|
||||
ARRAY,
|
||||
OBJECT,
|
||||
CALL,
|
||||
};
|
||||
struct Field;
|
||||
struct Call;
|
||||
|
||||
struct _capnpPrivate {
|
||||
CAPNP_DECLARE_STRUCT_HEADER(8825ffaa852cda72, 2, 1)
|
||||
#if !CAPNP_LITE
|
||||
static constexpr ::capnp::_::RawBrandedSchema const* brand() { return &schema->defaultBrand; }
|
||||
#endif // !CAPNP_LITE
|
||||
};
|
||||
};
|
||||
|
||||
struct JsonValue::Field {
|
||||
Field() = delete;
|
||||
|
||||
class Reader;
|
||||
class Builder;
|
||||
class Pipeline;
|
||||
|
||||
struct _capnpPrivate {
|
||||
CAPNP_DECLARE_STRUCT_HEADER(c27855d853a937cc, 0, 2)
|
||||
#if !CAPNP_LITE
|
||||
static constexpr ::capnp::_::RawBrandedSchema const* brand() { return &schema->defaultBrand; }
|
||||
#endif // !CAPNP_LITE
|
||||
};
|
||||
};
|
||||
|
||||
struct JsonValue::Call {
|
||||
Call() = delete;
|
||||
|
||||
class Reader;
|
||||
class Builder;
|
||||
class Pipeline;
|
||||
|
||||
struct _capnpPrivate {
|
||||
CAPNP_DECLARE_STRUCT_HEADER(9bbf84153dd4bb60, 0, 2)
|
||||
#if !CAPNP_LITE
|
||||
static constexpr ::capnp::_::RawBrandedSchema const* brand() { return &schema->defaultBrand; }
|
||||
#endif // !CAPNP_LITE
|
||||
};
|
||||
};
|
||||
|
||||
// =======================================================================================
|
||||
|
||||
class JsonValue::Reader {
|
||||
public:
|
||||
typedef JsonValue Reads;
|
||||
|
||||
Reader() = default;
|
||||
inline explicit Reader(::capnp::_::StructReader base): _reader(base) {}
|
||||
|
||||
inline ::capnp::MessageSize totalSize() const {
|
||||
return _reader.totalSize().asPublic();
|
||||
}
|
||||
|
||||
#if !CAPNP_LITE
|
||||
inline ::kj::StringTree toString() const {
|
||||
return ::capnp::_::structString(_reader, *_capnpPrivate::brand());
|
||||
}
|
||||
#endif // !CAPNP_LITE
|
||||
|
||||
inline Which which() const;
|
||||
inline bool isNull() const;
|
||||
inline ::capnp::Void getNull() const;
|
||||
|
||||
inline bool isBoolean() const;
|
||||
inline bool getBoolean() const;
|
||||
|
||||
inline bool isNumber() const;
|
||||
inline double getNumber() const;
|
||||
|
||||
inline bool isString() const;
|
||||
inline bool hasString() const;
|
||||
inline ::capnp::Text::Reader getString() const;
|
||||
|
||||
inline bool isArray() const;
|
||||
inline bool hasArray() const;
|
||||
inline ::capnp::List< ::capnp::JsonValue>::Reader getArray() const;
|
||||
|
||||
inline bool isObject() const;
|
||||
inline bool hasObject() const;
|
||||
inline ::capnp::List< ::capnp::JsonValue::Field>::Reader getObject() const;
|
||||
|
||||
inline bool isCall() const;
|
||||
inline bool hasCall() const;
|
||||
inline ::capnp::JsonValue::Call::Reader getCall() const;
|
||||
|
||||
private:
|
||||
::capnp::_::StructReader _reader;
|
||||
template <typename, ::capnp::Kind>
|
||||
friend struct ::capnp::ToDynamic_;
|
||||
template <typename, ::capnp::Kind>
|
||||
friend struct ::capnp::_::PointerHelpers;
|
||||
template <typename, ::capnp::Kind>
|
||||
friend struct ::capnp::List;
|
||||
friend class ::capnp::MessageBuilder;
|
||||
friend class ::capnp::Orphanage;
|
||||
};
|
||||
|
||||
class JsonValue::Builder {
|
||||
public:
|
||||
typedef JsonValue Builds;
|
||||
|
||||
Builder() = delete; // Deleted to discourage incorrect usage.
|
||||
// You can explicitly initialize to nullptr instead.
|
||||
inline Builder(decltype(nullptr)) {}
|
||||
inline explicit Builder(::capnp::_::StructBuilder base): _builder(base) {}
|
||||
inline operator Reader() const { return Reader(_builder.asReader()); }
|
||||
inline Reader asReader() const { return *this; }
|
||||
|
||||
inline ::capnp::MessageSize totalSize() const { return asReader().totalSize(); }
|
||||
#if !CAPNP_LITE
|
||||
inline ::kj::StringTree toString() const { return asReader().toString(); }
|
||||
#endif // !CAPNP_LITE
|
||||
|
||||
inline Which which();
|
||||
inline bool isNull();
|
||||
inline ::capnp::Void getNull();
|
||||
inline void setNull( ::capnp::Void value = ::capnp::VOID);
|
||||
|
||||
inline bool isBoolean();
|
||||
inline bool getBoolean();
|
||||
inline void setBoolean(bool value);
|
||||
|
||||
inline bool isNumber();
|
||||
inline double getNumber();
|
||||
inline void setNumber(double value);
|
||||
|
||||
inline bool isString();
|
||||
inline bool hasString();
|
||||
inline ::capnp::Text::Builder getString();
|
||||
inline void setString( ::capnp::Text::Reader value);
|
||||
inline ::capnp::Text::Builder initString(unsigned int size);
|
||||
inline void adoptString(::capnp::Orphan< ::capnp::Text>&& value);
|
||||
inline ::capnp::Orphan< ::capnp::Text> disownString();
|
||||
|
||||
inline bool isArray();
|
||||
inline bool hasArray();
|
||||
inline ::capnp::List< ::capnp::JsonValue>::Builder getArray();
|
||||
inline void setArray( ::capnp::List< ::capnp::JsonValue>::Reader value);
|
||||
inline ::capnp::List< ::capnp::JsonValue>::Builder initArray(unsigned int size);
|
||||
inline void adoptArray(::capnp::Orphan< ::capnp::List< ::capnp::JsonValue>>&& value);
|
||||
inline ::capnp::Orphan< ::capnp::List< ::capnp::JsonValue>> disownArray();
|
||||
|
||||
inline bool isObject();
|
||||
inline bool hasObject();
|
||||
inline ::capnp::List< ::capnp::JsonValue::Field>::Builder getObject();
|
||||
inline void setObject( ::capnp::List< ::capnp::JsonValue::Field>::Reader value);
|
||||
inline ::capnp::List< ::capnp::JsonValue::Field>::Builder initObject(unsigned int size);
|
||||
inline void adoptObject(::capnp::Orphan< ::capnp::List< ::capnp::JsonValue::Field>>&& value);
|
||||
inline ::capnp::Orphan< ::capnp::List< ::capnp::JsonValue::Field>> disownObject();
|
||||
|
||||
inline bool isCall();
|
||||
inline bool hasCall();
|
||||
inline ::capnp::JsonValue::Call::Builder getCall();
|
||||
inline void setCall( ::capnp::JsonValue::Call::Reader value);
|
||||
inline ::capnp::JsonValue::Call::Builder initCall();
|
||||
inline void adoptCall(::capnp::Orphan< ::capnp::JsonValue::Call>&& value);
|
||||
inline ::capnp::Orphan< ::capnp::JsonValue::Call> disownCall();
|
||||
|
||||
private:
|
||||
::capnp::_::StructBuilder _builder;
|
||||
template <typename, ::capnp::Kind>
|
||||
friend struct ::capnp::ToDynamic_;
|
||||
friend class ::capnp::Orphanage;
|
||||
template <typename, ::capnp::Kind>
|
||||
friend struct ::capnp::_::PointerHelpers;
|
||||
};
|
||||
|
||||
#if !CAPNP_LITE
|
||||
class JsonValue::Pipeline {
|
||||
public:
|
||||
typedef JsonValue Pipelines;
|
||||
|
||||
inline Pipeline(decltype(nullptr)): _typeless(nullptr) {}
|
||||
inline explicit Pipeline(::capnp::AnyPointer::Pipeline&& typeless)
|
||||
: _typeless(kj::mv(typeless)) {}
|
||||
|
||||
private:
|
||||
::capnp::AnyPointer::Pipeline _typeless;
|
||||
friend class ::capnp::PipelineHook;
|
||||
template <typename, ::capnp::Kind>
|
||||
friend struct ::capnp::ToDynamic_;
|
||||
};
|
||||
#endif // !CAPNP_LITE
|
||||
|
||||
class JsonValue::Field::Reader {
|
||||
public:
|
||||
typedef Field Reads;
|
||||
|
||||
Reader() = default;
|
||||
inline explicit Reader(::capnp::_::StructReader base): _reader(base) {}
|
||||
|
||||
inline ::capnp::MessageSize totalSize() const {
|
||||
return _reader.totalSize().asPublic();
|
||||
}
|
||||
|
||||
#if !CAPNP_LITE
|
||||
inline ::kj::StringTree toString() const {
|
||||
return ::capnp::_::structString(_reader, *_capnpPrivate::brand());
|
||||
}
|
||||
#endif // !CAPNP_LITE
|
||||
|
||||
inline bool hasName() const;
|
||||
inline ::capnp::Text::Reader getName() const;
|
||||
|
||||
inline bool hasValue() const;
|
||||
inline ::capnp::JsonValue::Reader getValue() const;
|
||||
|
||||
private:
|
||||
::capnp::_::StructReader _reader;
|
||||
template <typename, ::capnp::Kind>
|
||||
friend struct ::capnp::ToDynamic_;
|
||||
template <typename, ::capnp::Kind>
|
||||
friend struct ::capnp::_::PointerHelpers;
|
||||
template <typename, ::capnp::Kind>
|
||||
friend struct ::capnp::List;
|
||||
friend class ::capnp::MessageBuilder;
|
||||
friend class ::capnp::Orphanage;
|
||||
};
|
||||
|
||||
class JsonValue::Field::Builder {
|
||||
public:
|
||||
typedef Field Builds;
|
||||
|
||||
Builder() = delete; // Deleted to discourage incorrect usage.
|
||||
// You can explicitly initialize to nullptr instead.
|
||||
inline Builder(decltype(nullptr)) {}
|
||||
inline explicit Builder(::capnp::_::StructBuilder base): _builder(base) {}
|
||||
inline operator Reader() const { return Reader(_builder.asReader()); }
|
||||
inline Reader asReader() const { return *this; }
|
||||
|
||||
inline ::capnp::MessageSize totalSize() const { return asReader().totalSize(); }
|
||||
#if !CAPNP_LITE
|
||||
inline ::kj::StringTree toString() const { return asReader().toString(); }
|
||||
#endif // !CAPNP_LITE
|
||||
|
||||
inline bool hasName();
|
||||
inline ::capnp::Text::Builder getName();
|
||||
inline void setName( ::capnp::Text::Reader value);
|
||||
inline ::capnp::Text::Builder initName(unsigned int size);
|
||||
inline void adoptName(::capnp::Orphan< ::capnp::Text>&& value);
|
||||
inline ::capnp::Orphan< ::capnp::Text> disownName();
|
||||
|
||||
inline bool hasValue();
|
||||
inline ::capnp::JsonValue::Builder getValue();
|
||||
inline void setValue( ::capnp::JsonValue::Reader value);
|
||||
inline ::capnp::JsonValue::Builder initValue();
|
||||
inline void adoptValue(::capnp::Orphan< ::capnp::JsonValue>&& value);
|
||||
inline ::capnp::Orphan< ::capnp::JsonValue> disownValue();
|
||||
|
||||
private:
|
||||
::capnp::_::StructBuilder _builder;
|
||||
template <typename, ::capnp::Kind>
|
||||
friend struct ::capnp::ToDynamic_;
|
||||
friend class ::capnp::Orphanage;
|
||||
template <typename, ::capnp::Kind>
|
||||
friend struct ::capnp::_::PointerHelpers;
|
||||
};
|
||||
|
||||
#if !CAPNP_LITE
|
||||
class JsonValue::Field::Pipeline {
|
||||
public:
|
||||
typedef Field Pipelines;
|
||||
|
||||
inline Pipeline(decltype(nullptr)): _typeless(nullptr) {}
|
||||
inline explicit Pipeline(::capnp::AnyPointer::Pipeline&& typeless)
|
||||
: _typeless(kj::mv(typeless)) {}
|
||||
|
||||
inline ::capnp::JsonValue::Pipeline getValue();
|
||||
private:
|
||||
::capnp::AnyPointer::Pipeline _typeless;
|
||||
friend class ::capnp::PipelineHook;
|
||||
template <typename, ::capnp::Kind>
|
||||
friend struct ::capnp::ToDynamic_;
|
||||
};
|
||||
#endif // !CAPNP_LITE
|
||||
|
||||
class JsonValue::Call::Reader {
|
||||
public:
|
||||
typedef Call Reads;
|
||||
|
||||
Reader() = default;
|
||||
inline explicit Reader(::capnp::_::StructReader base): _reader(base) {}
|
||||
|
||||
inline ::capnp::MessageSize totalSize() const {
|
||||
return _reader.totalSize().asPublic();
|
||||
}
|
||||
|
||||
#if !CAPNP_LITE
|
||||
inline ::kj::StringTree toString() const {
|
||||
return ::capnp::_::structString(_reader, *_capnpPrivate::brand());
|
||||
}
|
||||
#endif // !CAPNP_LITE
|
||||
|
||||
inline bool hasFunction() const;
|
||||
inline ::capnp::Text::Reader getFunction() const;
|
||||
|
||||
inline bool hasParams() const;
|
||||
inline ::capnp::List< ::capnp::JsonValue>::Reader getParams() const;
|
||||
|
||||
private:
|
||||
::capnp::_::StructReader _reader;
|
||||
template <typename, ::capnp::Kind>
|
||||
friend struct ::capnp::ToDynamic_;
|
||||
template <typename, ::capnp::Kind>
|
||||
friend struct ::capnp::_::PointerHelpers;
|
||||
template <typename, ::capnp::Kind>
|
||||
friend struct ::capnp::List;
|
||||
friend class ::capnp::MessageBuilder;
|
||||
friend class ::capnp::Orphanage;
|
||||
};
|
||||
|
||||
class JsonValue::Call::Builder {
|
||||
public:
|
||||
typedef Call Builds;
|
||||
|
||||
Builder() = delete; // Deleted to discourage incorrect usage.
|
||||
// You can explicitly initialize to nullptr instead.
|
||||
inline Builder(decltype(nullptr)) {}
|
||||
inline explicit Builder(::capnp::_::StructBuilder base): _builder(base) {}
|
||||
inline operator Reader() const { return Reader(_builder.asReader()); }
|
||||
inline Reader asReader() const { return *this; }
|
||||
|
||||
inline ::capnp::MessageSize totalSize() const { return asReader().totalSize(); }
|
||||
#if !CAPNP_LITE
|
||||
inline ::kj::StringTree toString() const { return asReader().toString(); }
|
||||
#endif // !CAPNP_LITE
|
||||
|
||||
inline bool hasFunction();
|
||||
inline ::capnp::Text::Builder getFunction();
|
||||
inline void setFunction( ::capnp::Text::Reader value);
|
||||
inline ::capnp::Text::Builder initFunction(unsigned int size);
|
||||
inline void adoptFunction(::capnp::Orphan< ::capnp::Text>&& value);
|
||||
inline ::capnp::Orphan< ::capnp::Text> disownFunction();
|
||||
|
||||
inline bool hasParams();
|
||||
inline ::capnp::List< ::capnp::JsonValue>::Builder getParams();
|
||||
inline void setParams( ::capnp::List< ::capnp::JsonValue>::Reader value);
|
||||
inline ::capnp::List< ::capnp::JsonValue>::Builder initParams(unsigned int size);
|
||||
inline void adoptParams(::capnp::Orphan< ::capnp::List< ::capnp::JsonValue>>&& value);
|
||||
inline ::capnp::Orphan< ::capnp::List< ::capnp::JsonValue>> disownParams();
|
||||
|
||||
private:
|
||||
::capnp::_::StructBuilder _builder;
|
||||
template <typename, ::capnp::Kind>
|
||||
friend struct ::capnp::ToDynamic_;
|
||||
friend class ::capnp::Orphanage;
|
||||
template <typename, ::capnp::Kind>
|
||||
friend struct ::capnp::_::PointerHelpers;
|
||||
};
|
||||
|
||||
#if !CAPNP_LITE
|
||||
class JsonValue::Call::Pipeline {
|
||||
public:
|
||||
typedef Call Pipelines;
|
||||
|
||||
inline Pipeline(decltype(nullptr)): _typeless(nullptr) {}
|
||||
inline explicit Pipeline(::capnp::AnyPointer::Pipeline&& typeless)
|
||||
: _typeless(kj::mv(typeless)) {}
|
||||
|
||||
private:
|
||||
::capnp::AnyPointer::Pipeline _typeless;
|
||||
friend class ::capnp::PipelineHook;
|
||||
template <typename, ::capnp::Kind>
|
||||
friend struct ::capnp::ToDynamic_;
|
||||
};
|
||||
#endif // !CAPNP_LITE
|
||||
|
||||
// =======================================================================================
|
||||
|
||||
inline ::capnp::JsonValue::Which JsonValue::Reader::which() const {
|
||||
return _reader.getDataField<Which>(
|
||||
::capnp::bounded<0>() * ::capnp::ELEMENTS);
|
||||
}
|
||||
inline ::capnp::JsonValue::Which JsonValue::Builder::which() {
|
||||
return _builder.getDataField<Which>(
|
||||
::capnp::bounded<0>() * ::capnp::ELEMENTS);
|
||||
}
|
||||
|
||||
inline bool JsonValue::Reader::isNull() const {
|
||||
return which() == JsonValue::NULL_;
|
||||
}
|
||||
inline bool JsonValue::Builder::isNull() {
|
||||
return which() == JsonValue::NULL_;
|
||||
}
|
||||
inline ::capnp::Void JsonValue::Reader::getNull() const {
|
||||
KJ_IREQUIRE((which() == JsonValue::NULL_),
|
||||
"Must check which() before get()ing a union member.");
|
||||
return _reader.getDataField< ::capnp::Void>(
|
||||
::capnp::bounded<0>() * ::capnp::ELEMENTS);
|
||||
}
|
||||
|
||||
inline ::capnp::Void JsonValue::Builder::getNull() {
|
||||
KJ_IREQUIRE((which() == JsonValue::NULL_),
|
||||
"Must check which() before get()ing a union member.");
|
||||
return _builder.getDataField< ::capnp::Void>(
|
||||
::capnp::bounded<0>() * ::capnp::ELEMENTS);
|
||||
}
|
||||
inline void JsonValue::Builder::setNull( ::capnp::Void value) {
|
||||
_builder.setDataField<JsonValue::Which>(
|
||||
::capnp::bounded<0>() * ::capnp::ELEMENTS, JsonValue::NULL_);
|
||||
_builder.setDataField< ::capnp::Void>(
|
||||
::capnp::bounded<0>() * ::capnp::ELEMENTS, value);
|
||||
}
|
||||
|
||||
inline bool JsonValue::Reader::isBoolean() const {
|
||||
return which() == JsonValue::BOOLEAN;
|
||||
}
|
||||
inline bool JsonValue::Builder::isBoolean() {
|
||||
return which() == JsonValue::BOOLEAN;
|
||||
}
|
||||
inline bool JsonValue::Reader::getBoolean() const {
|
||||
KJ_IREQUIRE((which() == JsonValue::BOOLEAN),
|
||||
"Must check which() before get()ing a union member.");
|
||||
return _reader.getDataField<bool>(
|
||||
::capnp::bounded<16>() * ::capnp::ELEMENTS);
|
||||
}
|
||||
|
||||
inline bool JsonValue::Builder::getBoolean() {
|
||||
KJ_IREQUIRE((which() == JsonValue::BOOLEAN),
|
||||
"Must check which() before get()ing a union member.");
|
||||
return _builder.getDataField<bool>(
|
||||
::capnp::bounded<16>() * ::capnp::ELEMENTS);
|
||||
}
|
||||
inline void JsonValue::Builder::setBoolean(bool value) {
|
||||
_builder.setDataField<JsonValue::Which>(
|
||||
::capnp::bounded<0>() * ::capnp::ELEMENTS, JsonValue::BOOLEAN);
|
||||
_builder.setDataField<bool>(
|
||||
::capnp::bounded<16>() * ::capnp::ELEMENTS, value);
|
||||
}
|
||||
|
||||
inline bool JsonValue::Reader::isNumber() const {
|
||||
return which() == JsonValue::NUMBER;
|
||||
}
|
||||
inline bool JsonValue::Builder::isNumber() {
|
||||
return which() == JsonValue::NUMBER;
|
||||
}
|
||||
inline double JsonValue::Reader::getNumber() const {
|
||||
KJ_IREQUIRE((which() == JsonValue::NUMBER),
|
||||
"Must check which() before get()ing a union member.");
|
||||
return _reader.getDataField<double>(
|
||||
::capnp::bounded<1>() * ::capnp::ELEMENTS);
|
||||
}
|
||||
|
||||
inline double JsonValue::Builder::getNumber() {
|
||||
KJ_IREQUIRE((which() == JsonValue::NUMBER),
|
||||
"Must check which() before get()ing a union member.");
|
||||
return _builder.getDataField<double>(
|
||||
::capnp::bounded<1>() * ::capnp::ELEMENTS);
|
||||
}
|
||||
inline void JsonValue::Builder::setNumber(double value) {
|
||||
_builder.setDataField<JsonValue::Which>(
|
||||
::capnp::bounded<0>() * ::capnp::ELEMENTS, JsonValue::NUMBER);
|
||||
_builder.setDataField<double>(
|
||||
::capnp::bounded<1>() * ::capnp::ELEMENTS, value);
|
||||
}
|
||||
|
||||
inline bool JsonValue::Reader::isString() const {
|
||||
return which() == JsonValue::STRING;
|
||||
}
|
||||
inline bool JsonValue::Builder::isString() {
|
||||
return which() == JsonValue::STRING;
|
||||
}
|
||||
inline bool JsonValue::Reader::hasString() const {
|
||||
if (which() != JsonValue::STRING) return false;
|
||||
return !_reader.getPointerField(
|
||||
::capnp::bounded<0>() * ::capnp::POINTERS).isNull();
|
||||
}
|
||||
inline bool JsonValue::Builder::hasString() {
|
||||
if (which() != JsonValue::STRING) return false;
|
||||
return !_builder.getPointerField(
|
||||
::capnp::bounded<0>() * ::capnp::POINTERS).isNull();
|
||||
}
|
||||
inline ::capnp::Text::Reader JsonValue::Reader::getString() const {
|
||||
KJ_IREQUIRE((which() == JsonValue::STRING),
|
||||
"Must check which() before get()ing a union member.");
|
||||
return ::capnp::_::PointerHelpers< ::capnp::Text>::get(_reader.getPointerField(
|
||||
::capnp::bounded<0>() * ::capnp::POINTERS));
|
||||
}
|
||||
inline ::capnp::Text::Builder JsonValue::Builder::getString() {
|
||||
KJ_IREQUIRE((which() == JsonValue::STRING),
|
||||
"Must check which() before get()ing a union member.");
|
||||
return ::capnp::_::PointerHelpers< ::capnp::Text>::get(_builder.getPointerField(
|
||||
::capnp::bounded<0>() * ::capnp::POINTERS));
|
||||
}
|
||||
inline void JsonValue::Builder::setString( ::capnp::Text::Reader value) {
|
||||
_builder.setDataField<JsonValue::Which>(
|
||||
::capnp::bounded<0>() * ::capnp::ELEMENTS, JsonValue::STRING);
|
||||
::capnp::_::PointerHelpers< ::capnp::Text>::set(_builder.getPointerField(
|
||||
::capnp::bounded<0>() * ::capnp::POINTERS), value);
|
||||
}
|
||||
inline ::capnp::Text::Builder JsonValue::Builder::initString(unsigned int size) {
|
||||
_builder.setDataField<JsonValue::Which>(
|
||||
::capnp::bounded<0>() * ::capnp::ELEMENTS, JsonValue::STRING);
|
||||
return ::capnp::_::PointerHelpers< ::capnp::Text>::init(_builder.getPointerField(
|
||||
::capnp::bounded<0>() * ::capnp::POINTERS), size);
|
||||
}
|
||||
inline void JsonValue::Builder::adoptString(
|
||||
::capnp::Orphan< ::capnp::Text>&& value) {
|
||||
_builder.setDataField<JsonValue::Which>(
|
||||
::capnp::bounded<0>() * ::capnp::ELEMENTS, JsonValue::STRING);
|
||||
::capnp::_::PointerHelpers< ::capnp::Text>::adopt(_builder.getPointerField(
|
||||
::capnp::bounded<0>() * ::capnp::POINTERS), kj::mv(value));
|
||||
}
|
||||
inline ::capnp::Orphan< ::capnp::Text> JsonValue::Builder::disownString() {
|
||||
KJ_IREQUIRE((which() == JsonValue::STRING),
|
||||
"Must check which() before get()ing a union member.");
|
||||
return ::capnp::_::PointerHelpers< ::capnp::Text>::disown(_builder.getPointerField(
|
||||
::capnp::bounded<0>() * ::capnp::POINTERS));
|
||||
}
|
||||
|
||||
inline bool JsonValue::Reader::isArray() const {
|
||||
return which() == JsonValue::ARRAY;
|
||||
}
|
||||
inline bool JsonValue::Builder::isArray() {
|
||||
return which() == JsonValue::ARRAY;
|
||||
}
|
||||
inline bool JsonValue::Reader::hasArray() const {
|
||||
if (which() != JsonValue::ARRAY) return false;
|
||||
return !_reader.getPointerField(
|
||||
::capnp::bounded<0>() * ::capnp::POINTERS).isNull();
|
||||
}
|
||||
inline bool JsonValue::Builder::hasArray() {
|
||||
if (which() != JsonValue::ARRAY) return false;
|
||||
return !_builder.getPointerField(
|
||||
::capnp::bounded<0>() * ::capnp::POINTERS).isNull();
|
||||
}
|
||||
inline ::capnp::List< ::capnp::JsonValue>::Reader JsonValue::Reader::getArray() const {
|
||||
KJ_IREQUIRE((which() == JsonValue::ARRAY),
|
||||
"Must check which() before get()ing a union member.");
|
||||
return ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::JsonValue>>::get(_reader.getPointerField(
|
||||
::capnp::bounded<0>() * ::capnp::POINTERS));
|
||||
}
|
||||
inline ::capnp::List< ::capnp::JsonValue>::Builder JsonValue::Builder::getArray() {
|
||||
KJ_IREQUIRE((which() == JsonValue::ARRAY),
|
||||
"Must check which() before get()ing a union member.");
|
||||
return ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::JsonValue>>::get(_builder.getPointerField(
|
||||
::capnp::bounded<0>() * ::capnp::POINTERS));
|
||||
}
|
||||
inline void JsonValue::Builder::setArray( ::capnp::List< ::capnp::JsonValue>::Reader value) {
|
||||
_builder.setDataField<JsonValue::Which>(
|
||||
::capnp::bounded<0>() * ::capnp::ELEMENTS, JsonValue::ARRAY);
|
||||
::capnp::_::PointerHelpers< ::capnp::List< ::capnp::JsonValue>>::set(_builder.getPointerField(
|
||||
::capnp::bounded<0>() * ::capnp::POINTERS), value);
|
||||
}
|
||||
inline ::capnp::List< ::capnp::JsonValue>::Builder JsonValue::Builder::initArray(unsigned int size) {
|
||||
_builder.setDataField<JsonValue::Which>(
|
||||
::capnp::bounded<0>() * ::capnp::ELEMENTS, JsonValue::ARRAY);
|
||||
return ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::JsonValue>>::init(_builder.getPointerField(
|
||||
::capnp::bounded<0>() * ::capnp::POINTERS), size);
|
||||
}
|
||||
inline void JsonValue::Builder::adoptArray(
|
||||
::capnp::Orphan< ::capnp::List< ::capnp::JsonValue>>&& value) {
|
||||
_builder.setDataField<JsonValue::Which>(
|
||||
::capnp::bounded<0>() * ::capnp::ELEMENTS, JsonValue::ARRAY);
|
||||
::capnp::_::PointerHelpers< ::capnp::List< ::capnp::JsonValue>>::adopt(_builder.getPointerField(
|
||||
::capnp::bounded<0>() * ::capnp::POINTERS), kj::mv(value));
|
||||
}
|
||||
inline ::capnp::Orphan< ::capnp::List< ::capnp::JsonValue>> JsonValue::Builder::disownArray() {
|
||||
KJ_IREQUIRE((which() == JsonValue::ARRAY),
|
||||
"Must check which() before get()ing a union member.");
|
||||
return ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::JsonValue>>::disown(_builder.getPointerField(
|
||||
::capnp::bounded<0>() * ::capnp::POINTERS));
|
||||
}
|
||||
|
||||
inline bool JsonValue::Reader::isObject() const {
|
||||
return which() == JsonValue::OBJECT;
|
||||
}
|
||||
inline bool JsonValue::Builder::isObject() {
|
||||
return which() == JsonValue::OBJECT;
|
||||
}
|
||||
inline bool JsonValue::Reader::hasObject() const {
|
||||
if (which() != JsonValue::OBJECT) return false;
|
||||
return !_reader.getPointerField(
|
||||
::capnp::bounded<0>() * ::capnp::POINTERS).isNull();
|
||||
}
|
||||
inline bool JsonValue::Builder::hasObject() {
|
||||
if (which() != JsonValue::OBJECT) return false;
|
||||
return !_builder.getPointerField(
|
||||
::capnp::bounded<0>() * ::capnp::POINTERS).isNull();
|
||||
}
|
||||
inline ::capnp::List< ::capnp::JsonValue::Field>::Reader JsonValue::Reader::getObject() const {
|
||||
KJ_IREQUIRE((which() == JsonValue::OBJECT),
|
||||
"Must check which() before get()ing a union member.");
|
||||
return ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::JsonValue::Field>>::get(_reader.getPointerField(
|
||||
::capnp::bounded<0>() * ::capnp::POINTERS));
|
||||
}
|
||||
inline ::capnp::List< ::capnp::JsonValue::Field>::Builder JsonValue::Builder::getObject() {
|
||||
KJ_IREQUIRE((which() == JsonValue::OBJECT),
|
||||
"Must check which() before get()ing a union member.");
|
||||
return ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::JsonValue::Field>>::get(_builder.getPointerField(
|
||||
::capnp::bounded<0>() * ::capnp::POINTERS));
|
||||
}
|
||||
inline void JsonValue::Builder::setObject( ::capnp::List< ::capnp::JsonValue::Field>::Reader value) {
|
||||
_builder.setDataField<JsonValue::Which>(
|
||||
::capnp::bounded<0>() * ::capnp::ELEMENTS, JsonValue::OBJECT);
|
||||
::capnp::_::PointerHelpers< ::capnp::List< ::capnp::JsonValue::Field>>::set(_builder.getPointerField(
|
||||
::capnp::bounded<0>() * ::capnp::POINTERS), value);
|
||||
}
|
||||
inline ::capnp::List< ::capnp::JsonValue::Field>::Builder JsonValue::Builder::initObject(unsigned int size) {
|
||||
_builder.setDataField<JsonValue::Which>(
|
||||
::capnp::bounded<0>() * ::capnp::ELEMENTS, JsonValue::OBJECT);
|
||||
return ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::JsonValue::Field>>::init(_builder.getPointerField(
|
||||
::capnp::bounded<0>() * ::capnp::POINTERS), size);
|
||||
}
|
||||
inline void JsonValue::Builder::adoptObject(
|
||||
::capnp::Orphan< ::capnp::List< ::capnp::JsonValue::Field>>&& value) {
|
||||
_builder.setDataField<JsonValue::Which>(
|
||||
::capnp::bounded<0>() * ::capnp::ELEMENTS, JsonValue::OBJECT);
|
||||
::capnp::_::PointerHelpers< ::capnp::List< ::capnp::JsonValue::Field>>::adopt(_builder.getPointerField(
|
||||
::capnp::bounded<0>() * ::capnp::POINTERS), kj::mv(value));
|
||||
}
|
||||
inline ::capnp::Orphan< ::capnp::List< ::capnp::JsonValue::Field>> JsonValue::Builder::disownObject() {
|
||||
KJ_IREQUIRE((which() == JsonValue::OBJECT),
|
||||
"Must check which() before get()ing a union member.");
|
||||
return ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::JsonValue::Field>>::disown(_builder.getPointerField(
|
||||
::capnp::bounded<0>() * ::capnp::POINTERS));
|
||||
}
|
||||
|
||||
inline bool JsonValue::Reader::isCall() const {
|
||||
return which() == JsonValue::CALL;
|
||||
}
|
||||
inline bool JsonValue::Builder::isCall() {
|
||||
return which() == JsonValue::CALL;
|
||||
}
|
||||
inline bool JsonValue::Reader::hasCall() const {
|
||||
if (which() != JsonValue::CALL) return false;
|
||||
return !_reader.getPointerField(
|
||||
::capnp::bounded<0>() * ::capnp::POINTERS).isNull();
|
||||
}
|
||||
inline bool JsonValue::Builder::hasCall() {
|
||||
if (which() != JsonValue::CALL) return false;
|
||||
return !_builder.getPointerField(
|
||||
::capnp::bounded<0>() * ::capnp::POINTERS).isNull();
|
||||
}
|
||||
inline ::capnp::JsonValue::Call::Reader JsonValue::Reader::getCall() const {
|
||||
KJ_IREQUIRE((which() == JsonValue::CALL),
|
||||
"Must check which() before get()ing a union member.");
|
||||
return ::capnp::_::PointerHelpers< ::capnp::JsonValue::Call>::get(_reader.getPointerField(
|
||||
::capnp::bounded<0>() * ::capnp::POINTERS));
|
||||
}
|
||||
inline ::capnp::JsonValue::Call::Builder JsonValue::Builder::getCall() {
|
||||
KJ_IREQUIRE((which() == JsonValue::CALL),
|
||||
"Must check which() before get()ing a union member.");
|
||||
return ::capnp::_::PointerHelpers< ::capnp::JsonValue::Call>::get(_builder.getPointerField(
|
||||
::capnp::bounded<0>() * ::capnp::POINTERS));
|
||||
}
|
||||
inline void JsonValue::Builder::setCall( ::capnp::JsonValue::Call::Reader value) {
|
||||
_builder.setDataField<JsonValue::Which>(
|
||||
::capnp::bounded<0>() * ::capnp::ELEMENTS, JsonValue::CALL);
|
||||
::capnp::_::PointerHelpers< ::capnp::JsonValue::Call>::set(_builder.getPointerField(
|
||||
::capnp::bounded<0>() * ::capnp::POINTERS), value);
|
||||
}
|
||||
inline ::capnp::JsonValue::Call::Builder JsonValue::Builder::initCall() {
|
||||
_builder.setDataField<JsonValue::Which>(
|
||||
::capnp::bounded<0>() * ::capnp::ELEMENTS, JsonValue::CALL);
|
||||
return ::capnp::_::PointerHelpers< ::capnp::JsonValue::Call>::init(_builder.getPointerField(
|
||||
::capnp::bounded<0>() * ::capnp::POINTERS));
|
||||
}
|
||||
inline void JsonValue::Builder::adoptCall(
|
||||
::capnp::Orphan< ::capnp::JsonValue::Call>&& value) {
|
||||
_builder.setDataField<JsonValue::Which>(
|
||||
::capnp::bounded<0>() * ::capnp::ELEMENTS, JsonValue::CALL);
|
||||
::capnp::_::PointerHelpers< ::capnp::JsonValue::Call>::adopt(_builder.getPointerField(
|
||||
::capnp::bounded<0>() * ::capnp::POINTERS), kj::mv(value));
|
||||
}
|
||||
inline ::capnp::Orphan< ::capnp::JsonValue::Call> JsonValue::Builder::disownCall() {
|
||||
KJ_IREQUIRE((which() == JsonValue::CALL),
|
||||
"Must check which() before get()ing a union member.");
|
||||
return ::capnp::_::PointerHelpers< ::capnp::JsonValue::Call>::disown(_builder.getPointerField(
|
||||
::capnp::bounded<0>() * ::capnp::POINTERS));
|
||||
}
|
||||
|
||||
inline bool JsonValue::Field::Reader::hasName() const {
|
||||
return !_reader.getPointerField(
|
||||
::capnp::bounded<0>() * ::capnp::POINTERS).isNull();
|
||||
}
|
||||
inline bool JsonValue::Field::Builder::hasName() {
|
||||
return !_builder.getPointerField(
|
||||
::capnp::bounded<0>() * ::capnp::POINTERS).isNull();
|
||||
}
|
||||
inline ::capnp::Text::Reader JsonValue::Field::Reader::getName() const {
|
||||
return ::capnp::_::PointerHelpers< ::capnp::Text>::get(_reader.getPointerField(
|
||||
::capnp::bounded<0>() * ::capnp::POINTERS));
|
||||
}
|
||||
inline ::capnp::Text::Builder JsonValue::Field::Builder::getName() {
|
||||
return ::capnp::_::PointerHelpers< ::capnp::Text>::get(_builder.getPointerField(
|
||||
::capnp::bounded<0>() * ::capnp::POINTERS));
|
||||
}
|
||||
inline void JsonValue::Field::Builder::setName( ::capnp::Text::Reader value) {
|
||||
::capnp::_::PointerHelpers< ::capnp::Text>::set(_builder.getPointerField(
|
||||
::capnp::bounded<0>() * ::capnp::POINTERS), value);
|
||||
}
|
||||
inline ::capnp::Text::Builder JsonValue::Field::Builder::initName(unsigned int size) {
|
||||
return ::capnp::_::PointerHelpers< ::capnp::Text>::init(_builder.getPointerField(
|
||||
::capnp::bounded<0>() * ::capnp::POINTERS), size);
|
||||
}
|
||||
inline void JsonValue::Field::Builder::adoptName(
|
||||
::capnp::Orphan< ::capnp::Text>&& value) {
|
||||
::capnp::_::PointerHelpers< ::capnp::Text>::adopt(_builder.getPointerField(
|
||||
::capnp::bounded<0>() * ::capnp::POINTERS), kj::mv(value));
|
||||
}
|
||||
inline ::capnp::Orphan< ::capnp::Text> JsonValue::Field::Builder::disownName() {
|
||||
return ::capnp::_::PointerHelpers< ::capnp::Text>::disown(_builder.getPointerField(
|
||||
::capnp::bounded<0>() * ::capnp::POINTERS));
|
||||
}
|
||||
|
||||
inline bool JsonValue::Field::Reader::hasValue() const {
|
||||
return !_reader.getPointerField(
|
||||
::capnp::bounded<1>() * ::capnp::POINTERS).isNull();
|
||||
}
|
||||
inline bool JsonValue::Field::Builder::hasValue() {
|
||||
return !_builder.getPointerField(
|
||||
::capnp::bounded<1>() * ::capnp::POINTERS).isNull();
|
||||
}
|
||||
inline ::capnp::JsonValue::Reader JsonValue::Field::Reader::getValue() const {
|
||||
return ::capnp::_::PointerHelpers< ::capnp::JsonValue>::get(_reader.getPointerField(
|
||||
::capnp::bounded<1>() * ::capnp::POINTERS));
|
||||
}
|
||||
inline ::capnp::JsonValue::Builder JsonValue::Field::Builder::getValue() {
|
||||
return ::capnp::_::PointerHelpers< ::capnp::JsonValue>::get(_builder.getPointerField(
|
||||
::capnp::bounded<1>() * ::capnp::POINTERS));
|
||||
}
|
||||
#if !CAPNP_LITE
|
||||
inline ::capnp::JsonValue::Pipeline JsonValue::Field::Pipeline::getValue() {
|
||||
return ::capnp::JsonValue::Pipeline(_typeless.getPointerField(1));
|
||||
}
|
||||
#endif // !CAPNP_LITE
|
||||
inline void JsonValue::Field::Builder::setValue( ::capnp::JsonValue::Reader value) {
|
||||
::capnp::_::PointerHelpers< ::capnp::JsonValue>::set(_builder.getPointerField(
|
||||
::capnp::bounded<1>() * ::capnp::POINTERS), value);
|
||||
}
|
||||
inline ::capnp::JsonValue::Builder JsonValue::Field::Builder::initValue() {
|
||||
return ::capnp::_::PointerHelpers< ::capnp::JsonValue>::init(_builder.getPointerField(
|
||||
::capnp::bounded<1>() * ::capnp::POINTERS));
|
||||
}
|
||||
inline void JsonValue::Field::Builder::adoptValue(
|
||||
::capnp::Orphan< ::capnp::JsonValue>&& value) {
|
||||
::capnp::_::PointerHelpers< ::capnp::JsonValue>::adopt(_builder.getPointerField(
|
||||
::capnp::bounded<1>() * ::capnp::POINTERS), kj::mv(value));
|
||||
}
|
||||
inline ::capnp::Orphan< ::capnp::JsonValue> JsonValue::Field::Builder::disownValue() {
|
||||
return ::capnp::_::PointerHelpers< ::capnp::JsonValue>::disown(_builder.getPointerField(
|
||||
::capnp::bounded<1>() * ::capnp::POINTERS));
|
||||
}
|
||||
|
||||
inline bool JsonValue::Call::Reader::hasFunction() const {
|
||||
return !_reader.getPointerField(
|
||||
::capnp::bounded<0>() * ::capnp::POINTERS).isNull();
|
||||
}
|
||||
inline bool JsonValue::Call::Builder::hasFunction() {
|
||||
return !_builder.getPointerField(
|
||||
::capnp::bounded<0>() * ::capnp::POINTERS).isNull();
|
||||
}
|
||||
inline ::capnp::Text::Reader JsonValue::Call::Reader::getFunction() const {
|
||||
return ::capnp::_::PointerHelpers< ::capnp::Text>::get(_reader.getPointerField(
|
||||
::capnp::bounded<0>() * ::capnp::POINTERS));
|
||||
}
|
||||
inline ::capnp::Text::Builder JsonValue::Call::Builder::getFunction() {
|
||||
return ::capnp::_::PointerHelpers< ::capnp::Text>::get(_builder.getPointerField(
|
||||
::capnp::bounded<0>() * ::capnp::POINTERS));
|
||||
}
|
||||
inline void JsonValue::Call::Builder::setFunction( ::capnp::Text::Reader value) {
|
||||
::capnp::_::PointerHelpers< ::capnp::Text>::set(_builder.getPointerField(
|
||||
::capnp::bounded<0>() * ::capnp::POINTERS), value);
|
||||
}
|
||||
inline ::capnp::Text::Builder JsonValue::Call::Builder::initFunction(unsigned int size) {
|
||||
return ::capnp::_::PointerHelpers< ::capnp::Text>::init(_builder.getPointerField(
|
||||
::capnp::bounded<0>() * ::capnp::POINTERS), size);
|
||||
}
|
||||
inline void JsonValue::Call::Builder::adoptFunction(
|
||||
::capnp::Orphan< ::capnp::Text>&& value) {
|
||||
::capnp::_::PointerHelpers< ::capnp::Text>::adopt(_builder.getPointerField(
|
||||
::capnp::bounded<0>() * ::capnp::POINTERS), kj::mv(value));
|
||||
}
|
||||
inline ::capnp::Orphan< ::capnp::Text> JsonValue::Call::Builder::disownFunction() {
|
||||
return ::capnp::_::PointerHelpers< ::capnp::Text>::disown(_builder.getPointerField(
|
||||
::capnp::bounded<0>() * ::capnp::POINTERS));
|
||||
}
|
||||
|
||||
inline bool JsonValue::Call::Reader::hasParams() const {
|
||||
return !_reader.getPointerField(
|
||||
::capnp::bounded<1>() * ::capnp::POINTERS).isNull();
|
||||
}
|
||||
inline bool JsonValue::Call::Builder::hasParams() {
|
||||
return !_builder.getPointerField(
|
||||
::capnp::bounded<1>() * ::capnp::POINTERS).isNull();
|
||||
}
|
||||
inline ::capnp::List< ::capnp::JsonValue>::Reader JsonValue::Call::Reader::getParams() const {
|
||||
return ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::JsonValue>>::get(_reader.getPointerField(
|
||||
::capnp::bounded<1>() * ::capnp::POINTERS));
|
||||
}
|
||||
inline ::capnp::List< ::capnp::JsonValue>::Builder JsonValue::Call::Builder::getParams() {
|
||||
return ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::JsonValue>>::get(_builder.getPointerField(
|
||||
::capnp::bounded<1>() * ::capnp::POINTERS));
|
||||
}
|
||||
inline void JsonValue::Call::Builder::setParams( ::capnp::List< ::capnp::JsonValue>::Reader value) {
|
||||
::capnp::_::PointerHelpers< ::capnp::List< ::capnp::JsonValue>>::set(_builder.getPointerField(
|
||||
::capnp::bounded<1>() * ::capnp::POINTERS), value);
|
||||
}
|
||||
inline ::capnp::List< ::capnp::JsonValue>::Builder JsonValue::Call::Builder::initParams(unsigned int size) {
|
||||
return ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::JsonValue>>::init(_builder.getPointerField(
|
||||
::capnp::bounded<1>() * ::capnp::POINTERS), size);
|
||||
}
|
||||
inline void JsonValue::Call::Builder::adoptParams(
|
||||
::capnp::Orphan< ::capnp::List< ::capnp::JsonValue>>&& value) {
|
||||
::capnp::_::PointerHelpers< ::capnp::List< ::capnp::JsonValue>>::adopt(_builder.getPointerField(
|
||||
::capnp::bounded<1>() * ::capnp::POINTERS), kj::mv(value));
|
||||
}
|
||||
inline ::capnp::Orphan< ::capnp::List< ::capnp::JsonValue>> JsonValue::Call::Builder::disownParams() {
|
||||
return ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::JsonValue>>::disown(_builder.getPointerField(
|
||||
::capnp::bounded<1>() * ::capnp::POINTERS));
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
#endif // CAPNP_INCLUDED_8ef99297a43a5e34_
|
||||
462
phonelibs/capnp-cpp/include/capnp/compat/json.h
Normal file
462
phonelibs/capnp-cpp/include/capnp/compat/json.h
Normal file
@@ -0,0 +1,462 @@
|
||||
// Copyright (c) 2015 Sandstorm Development Group, Inc. and contributors
|
||||
// Licensed under the MIT License:
|
||||
//
|
||||
// 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.
|
||||
|
||||
#ifndef CAPNP_COMPAT_JSON_H_
|
||||
#define CAPNP_COMPAT_JSON_H_
|
||||
|
||||
#include <capnp/schema.h>
|
||||
#include <capnp/dynamic.h>
|
||||
#include <capnp/compat/json.capnp.h>
|
||||
|
||||
namespace capnp {
|
||||
|
||||
class JsonCodec {
|
||||
// Flexible class for encoding Cap'n Proto types as JSON, and decoding JSON back to Cap'n Proto.
|
||||
//
|
||||
// Typical usage:
|
||||
//
|
||||
// JsonCodec json;
|
||||
//
|
||||
// // encode
|
||||
// kj::String encoded = json.encode(someStructReader);
|
||||
//
|
||||
// // decode
|
||||
// json.decode(encoded, someStructBuilder);
|
||||
//
|
||||
// Advanced users can do fancy things like override the way certain types or fields are
|
||||
// represented in JSON by registering handlers. See the unit test for an example.
|
||||
//
|
||||
// Notes:
|
||||
// - When encoding, all primitive fields are always encoded, even if default-valued. Pointer
|
||||
// fields are only encoded if they are non-null.
|
||||
// - 64-bit integers are encoded as strings, since JSON "numbers" are double-precision floating
|
||||
// points which cannot store a 64-bit integer without losing data.
|
||||
// - NaNs and infinite floating point numbers are not allowed by the JSON spec, and so are encoded
|
||||
// as null. This matches the behavior of `JSON.stringify` in at least Firefox and Chrome.
|
||||
// - Data is encoded as an array of numbers in the range [0,255]. You probably want to register
|
||||
// a handler that does something better, like maybe base64 encoding, but there are a zillion
|
||||
// different ways people do this.
|
||||
// - Encoding/decoding capabilities and AnyPointers requires registering a Handler, since there's
|
||||
// no obvious default behavior.
|
||||
// - When decoding, unrecognized field names are ignored. Note: This means that JSON is NOT a
|
||||
// good format for receiving input from a human. Consider `capnp eval` or the SchemaParser
|
||||
// library for human input.
|
||||
|
||||
public:
|
||||
JsonCodec();
|
||||
~JsonCodec() noexcept(false);
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// standard API
|
||||
|
||||
void setPrettyPrint(bool enabled);
|
||||
// Enable to insert newlines, indentation, and other extra spacing into the output. The default
|
||||
// is to use minimal whitespace.
|
||||
|
||||
void setMaxNestingDepth(size_t maxNestingDepth);
|
||||
// Set maximum nesting depth when decoding JSON to prevent highly nested input from overflowing
|
||||
// the call stack. The default is 64.
|
||||
|
||||
template <typename T>
|
||||
kj::String encode(T&& value);
|
||||
// Encode any Cap'n Proto value to JSON, including primitives and
|
||||
// Dynamic{Enum,Struct,List,Capability}, but not DynamicValue (see below).
|
||||
|
||||
kj::String encode(DynamicValue::Reader value, Type type) const;
|
||||
// Encode a DynamicValue to JSON. `type` is needed because `DynamicValue` itself does
|
||||
// not distinguish between e.g. int32 and int64, which in JSON are handled differently. Most
|
||||
// of the time, though, you can use the single-argument templated version of `encode()` instead.
|
||||
|
||||
void decode(kj::ArrayPtr<const char> input, DynamicStruct::Builder output) const;
|
||||
// Decode JSON text directly into a struct builder. This only works for structs since lists
|
||||
// need to be allocated with the correct size in advance.
|
||||
//
|
||||
// (Remember that any Cap'n Proto struct reader type can be implicitly cast to
|
||||
// DynamicStruct::Reader.)
|
||||
|
||||
template <typename T>
|
||||
Orphan<T> decode(kj::ArrayPtr<const char> input, Orphanage orphanage) const;
|
||||
// Decode JSON text to any Cap'n Proto object (pointer value), allocated using the given
|
||||
// orphanage. T must be specified explicitly and cannot be dynamic, e.g.:
|
||||
//
|
||||
// Orphan<MyType> orphan = json.decode<MyType>(text, orphanage);
|
||||
|
||||
template <typename T>
|
||||
ReaderFor<T> decode(kj::ArrayPtr<const char> input) const;
|
||||
// Decode JSON text into a primitive or capability value. T must be specified explicitly and
|
||||
// cannot be dynamic, e.g.:
|
||||
//
|
||||
// uint32_t n = json.decode<uint32_t>(text);
|
||||
|
||||
Orphan<DynamicValue> decode(kj::ArrayPtr<const char> input, Type type, Orphanage orphanage) const;
|
||||
Orphan<DynamicList> decode(
|
||||
kj::ArrayPtr<const char> input, ListSchema type, Orphanage orphanage) const;
|
||||
Orphan<DynamicStruct> decode(
|
||||
kj::ArrayPtr<const char> input, StructSchema type, Orphanage orphanage) const;
|
||||
DynamicCapability::Client decode(kj::ArrayPtr<const char> input, InterfaceSchema type) const;
|
||||
DynamicEnum decode(kj::ArrayPtr<const char> input, EnumSchema type) const;
|
||||
// Decode to a dynamic value, specifying the type schema.
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// layered API
|
||||
//
|
||||
// You can separate text <-> JsonValue from JsonValue <-> T. These are particularly useful
|
||||
// for calling from Handler implementations.
|
||||
|
||||
kj::String encodeRaw(JsonValue::Reader value) const;
|
||||
void decodeRaw(kj::ArrayPtr<const char> input, JsonValue::Builder output) const;
|
||||
// Translate JsonValue <-> text.
|
||||
|
||||
template <typename T>
|
||||
void encode(T&& value, JsonValue::Builder output);
|
||||
void encode(DynamicValue::Reader input, Type type, JsonValue::Builder output) const;
|
||||
void decode(JsonValue::Reader input, DynamicStruct::Builder output) const;
|
||||
template <typename T>
|
||||
Orphan<T> decode(JsonValue::Reader input, Orphanage orphanage) const;
|
||||
template <typename T>
|
||||
ReaderFor<T> decode(JsonValue::Reader input) const;
|
||||
|
||||
Orphan<DynamicValue> decode(JsonValue::Reader input, Type type, Orphanage orphanage) const;
|
||||
Orphan<DynamicList> decode(JsonValue::Reader input, ListSchema type, Orphanage orphanage) const;
|
||||
Orphan<DynamicStruct> decode(
|
||||
JsonValue::Reader input, StructSchema type, Orphanage orphanage) const;
|
||||
DynamicCapability::Client decode(JsonValue::Reader input, InterfaceSchema type) const;
|
||||
DynamicEnum decode(JsonValue::Reader input, EnumSchema type) const;
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// specializing particular types
|
||||
|
||||
template <typename T, Style s = style<T>()>
|
||||
class Handler;
|
||||
// Implement this interface to specify a special encoding for a particular type or field.
|
||||
//
|
||||
// The templates are a bit ugly, but subclasses of this type essentially implement two methods,
|
||||
// one to encode values of this type and one to decode values of this type. `encode()` is simple:
|
||||
//
|
||||
// void encode(const JsonCodec& codec, ReaderFor<T> input, JsonValue::Builder output) const;
|
||||
//
|
||||
// `decode()` is a bit trickier. When T is a struct (including DynamicStruct), it is:
|
||||
//
|
||||
// void decode(const JsonCodec& codec, JsonValue::Reader input, BuilderFor<T> output) const;
|
||||
//
|
||||
// However, when T is a primitive, decode() is:
|
||||
//
|
||||
// T decode(const JsonCodec& codec, JsonValue::Reader input) const;
|
||||
//
|
||||
// Or when T is any non-struct object (list, blob), decode() is:
|
||||
//
|
||||
// Orphan<T> decode(const JsonCodec& codec, JsonValue::Reader input, Orphanage orphanage) const;
|
||||
//
|
||||
// Or when T is an interface:
|
||||
//
|
||||
// T::Client decode(const JsonCodec& codec, JsonValue::Reader input) const;
|
||||
//
|
||||
// Additionally, when T is a struct you can *optionally* also implement the orphan-returning form
|
||||
// of decode(), but it will only be called when the struct would be allocated as an individual
|
||||
// object, not as part of a list. This allows you to return "nullptr" in these cases to say that
|
||||
// the pointer value should be null. This does not apply to list elements because struct list
|
||||
// elements cannot ever be null (since Cap'n Proto encodes struct lists as a flat list rather
|
||||
// than list-of-pointers).
|
||||
|
||||
template <typename T>
|
||||
void addTypeHandler(Handler<T>& handler);
|
||||
void addTypeHandler(Type type, Handler<DynamicValue>& handler);
|
||||
void addTypeHandler(EnumSchema type, Handler<DynamicEnum>& handler);
|
||||
void addTypeHandler(StructSchema type, Handler<DynamicStruct>& handler);
|
||||
void addTypeHandler(ListSchema type, Handler<DynamicList>& handler);
|
||||
void addTypeHandler(InterfaceSchema type, Handler<DynamicCapability>& handler);
|
||||
// Arrange that whenever the type T appears in the message, your handler will be used to
|
||||
// encode/decode it.
|
||||
//
|
||||
// Note that if you register a handler for a capability type, it will also apply to subtypes.
|
||||
// Thus Handler<Capability> handles all capabilities.
|
||||
|
||||
template <typename T>
|
||||
void addFieldHandler(StructSchema::Field field, Handler<T>& handler);
|
||||
// Matches only the specific field. T can be a dynamic type. T must match the field's type.
|
||||
|
||||
private:
|
||||
class HandlerBase;
|
||||
struct Impl;
|
||||
|
||||
kj::Own<Impl> impl;
|
||||
|
||||
void encodeField(StructSchema::Field field, DynamicValue::Reader input,
|
||||
JsonValue::Builder output) const;
|
||||
void decodeArray(List<JsonValue>::Reader input, DynamicList::Builder output) const;
|
||||
void decodeObject(List<JsonValue::Field>::Reader input, DynamicStruct::Builder output) const;
|
||||
void addTypeHandlerImpl(Type type, HandlerBase& handler);
|
||||
void addFieldHandlerImpl(StructSchema::Field field, Type type, HandlerBase& handler);
|
||||
};
|
||||
|
||||
// =======================================================================================
|
||||
// inline implementation details
|
||||
|
||||
template <typename T>
|
||||
kj::String JsonCodec::encode(T&& value) {
|
||||
typedef FromAny<kj::Decay<T>> Base;
|
||||
return encode(DynamicValue::Reader(ReaderFor<Base>(kj::fwd<T>(value))), Type::from<Base>());
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline Orphan<T> JsonCodec::decode(kj::ArrayPtr<const char> input, Orphanage orphanage) const {
|
||||
return decode(input, Type::from<T>(), orphanage).template releaseAs<T>();
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline ReaderFor<T> JsonCodec::decode(kj::ArrayPtr<const char> input) const {
|
||||
static_assert(style<T>() == Style::PRIMITIVE || style<T>() == Style::CAPABILITY,
|
||||
"must specify an orphanage to decode an object type");
|
||||
return decode(input, Type::from<T>(), Orphanage()).getReader().template as<T>();
|
||||
}
|
||||
|
||||
inline Orphan<DynamicList> JsonCodec::decode(
|
||||
kj::ArrayPtr<const char> input, ListSchema type, Orphanage orphanage) const {
|
||||
return decode(input, Type(type), orphanage).releaseAs<DynamicList>();
|
||||
}
|
||||
inline Orphan<DynamicStruct> JsonCodec::decode(
|
||||
kj::ArrayPtr<const char> input, StructSchema type, Orphanage orphanage) const {
|
||||
return decode(input, Type(type), orphanage).releaseAs<DynamicStruct>();
|
||||
}
|
||||
inline DynamicCapability::Client JsonCodec::decode(
|
||||
kj::ArrayPtr<const char> input, InterfaceSchema type) const {
|
||||
return decode(input, Type(type), Orphanage()).getReader().as<DynamicCapability>();
|
||||
}
|
||||
inline DynamicEnum JsonCodec::decode(kj::ArrayPtr<const char> input, EnumSchema type) const {
|
||||
return decode(input, Type(type), Orphanage()).getReader().as<DynamicEnum>();
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
template <typename T>
|
||||
void JsonCodec::encode(T&& value, JsonValue::Builder output) {
|
||||
typedef FromAny<kj::Decay<T>> Base;
|
||||
encode(DynamicValue::Reader(ReaderFor<Base>(kj::fwd<T>(value))), Type::from<Base>(), output);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline Orphan<T> JsonCodec::decode(JsonValue::Reader input, Orphanage orphanage) const {
|
||||
return decode(input, Type::from<T>(), orphanage).template releaseAs<T>();
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline ReaderFor<T> JsonCodec::decode(JsonValue::Reader input) const {
|
||||
static_assert(style<T>() == Style::PRIMITIVE || style<T>() == Style::CAPABILITY,
|
||||
"must specify an orphanage to decode an object type");
|
||||
return decode(input, Type::from<T>(), Orphanage()).getReader().template as<T>();
|
||||
}
|
||||
|
||||
inline Orphan<DynamicList> JsonCodec::decode(
|
||||
JsonValue::Reader input, ListSchema type, Orphanage orphanage) const {
|
||||
return decode(input, Type(type), orphanage).releaseAs<DynamicList>();
|
||||
}
|
||||
inline Orphan<DynamicStruct> JsonCodec::decode(
|
||||
JsonValue::Reader input, StructSchema type, Orphanage orphanage) const {
|
||||
return decode(input, Type(type), orphanage).releaseAs<DynamicStruct>();
|
||||
}
|
||||
inline DynamicCapability::Client JsonCodec::decode(
|
||||
JsonValue::Reader input, InterfaceSchema type) const {
|
||||
return decode(input, Type(type), Orphanage()).getReader().as<DynamicCapability>();
|
||||
}
|
||||
inline DynamicEnum JsonCodec::decode(JsonValue::Reader input, EnumSchema type) const {
|
||||
return decode(input, Type(type), Orphanage()).getReader().as<DynamicEnum>();
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
class JsonCodec::HandlerBase {
|
||||
// Internal helper; ignore.
|
||||
public:
|
||||
virtual void encodeBase(const JsonCodec& codec, DynamicValue::Reader input,
|
||||
JsonValue::Builder output) const = 0;
|
||||
virtual Orphan<DynamicValue> decodeBase(const JsonCodec& codec, JsonValue::Reader input,
|
||||
Type type, Orphanage orphanage) const;
|
||||
virtual void decodeStructBase(const JsonCodec& codec, JsonValue::Reader input,
|
||||
DynamicStruct::Builder output) const;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
class JsonCodec::Handler<T, Style::POINTER>: private JsonCodec::HandlerBase {
|
||||
public:
|
||||
virtual void encode(const JsonCodec& codec, ReaderFor<T> input,
|
||||
JsonValue::Builder output) const = 0;
|
||||
virtual Orphan<T> decode(const JsonCodec& codec, JsonValue::Reader input,
|
||||
Orphanage orphanage) const = 0;
|
||||
|
||||
private:
|
||||
void encodeBase(const JsonCodec& codec, DynamicValue::Reader input,
|
||||
JsonValue::Builder output) const override final {
|
||||
encode(codec, input.as<T>(), output);
|
||||
}
|
||||
Orphan<DynamicValue> decodeBase(const JsonCodec& codec, JsonValue::Reader input,
|
||||
Type type, Orphanage orphanage) const override final {
|
||||
return decode(codec, input, orphanage);
|
||||
}
|
||||
friend class JsonCodec;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
class JsonCodec::Handler<T, Style::STRUCT>: private JsonCodec::HandlerBase {
|
||||
public:
|
||||
virtual void encode(const JsonCodec& codec, ReaderFor<T> input,
|
||||
JsonValue::Builder output) const = 0;
|
||||
virtual void decode(const JsonCodec& codec, JsonValue::Reader input,
|
||||
BuilderFor<T> output) const = 0;
|
||||
virtual Orphan<T> decode(const JsonCodec& codec, JsonValue::Reader input,
|
||||
Orphanage orphanage) const {
|
||||
// If subclass does not override, fall back to regular version.
|
||||
auto result = orphanage.newOrphan<T>();
|
||||
decode(codec, input, result.get());
|
||||
return result;
|
||||
}
|
||||
|
||||
private:
|
||||
void encodeBase(const JsonCodec& codec, DynamicValue::Reader input,
|
||||
JsonValue::Builder output) const override final {
|
||||
encode(codec, input.as<T>(), output);
|
||||
}
|
||||
Orphan<DynamicValue> decodeBase(const JsonCodec& codec, JsonValue::Reader input,
|
||||
Type type, Orphanage orphanage) const override final {
|
||||
return decode(codec, input, orphanage);
|
||||
}
|
||||
void decodeStructBase(const JsonCodec& codec, JsonValue::Reader input,
|
||||
DynamicStruct::Builder output) const override final {
|
||||
decode(codec, input, output.as<T>());
|
||||
}
|
||||
friend class JsonCodec;
|
||||
};
|
||||
|
||||
template <>
|
||||
class JsonCodec::Handler<DynamicStruct>: private JsonCodec::HandlerBase {
|
||||
// Almost identical to Style::STRUCT except that we pass the struct type to decode().
|
||||
|
||||
public:
|
||||
virtual void encode(const JsonCodec& codec, DynamicStruct::Reader input,
|
||||
JsonValue::Builder output) const = 0;
|
||||
virtual void decode(const JsonCodec& codec, JsonValue::Reader input,
|
||||
DynamicStruct::Builder output) const = 0;
|
||||
virtual Orphan<DynamicStruct> decode(const JsonCodec& codec, JsonValue::Reader input,
|
||||
StructSchema type, Orphanage orphanage) const {
|
||||
// If subclass does not override, fall back to regular version.
|
||||
auto result = orphanage.newOrphan(type);
|
||||
decode(codec, input, result.get());
|
||||
return result;
|
||||
}
|
||||
|
||||
private:
|
||||
void encodeBase(const JsonCodec& codec, DynamicValue::Reader input,
|
||||
JsonValue::Builder output) const override final {
|
||||
encode(codec, input.as<DynamicStruct>(), output);
|
||||
}
|
||||
Orphan<DynamicValue> decodeBase(const JsonCodec& codec, JsonValue::Reader input,
|
||||
Type type, Orphanage orphanage) const override final {
|
||||
return decode(codec, input, type.asStruct(), orphanage);
|
||||
}
|
||||
void decodeStructBase(const JsonCodec& codec, JsonValue::Reader input,
|
||||
DynamicStruct::Builder output) const override final {
|
||||
decode(codec, input, output.as<DynamicStruct>());
|
||||
}
|
||||
friend class JsonCodec;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
class JsonCodec::Handler<T, Style::PRIMITIVE>: private JsonCodec::HandlerBase {
|
||||
public:
|
||||
virtual void encode(const JsonCodec& codec, T input, JsonValue::Builder output) const = 0;
|
||||
virtual T decode(const JsonCodec& codec, JsonValue::Reader input) const = 0;
|
||||
|
||||
private:
|
||||
void encodeBase(const JsonCodec& codec, DynamicValue::Reader input,
|
||||
JsonValue::Builder output) const override final {
|
||||
encode(codec, input.as<T>(), output);
|
||||
}
|
||||
Orphan<DynamicValue> decodeBase(const JsonCodec& codec, JsonValue::Reader input,
|
||||
Type type, Orphanage orphanage) const override final {
|
||||
return decode(codec, input);
|
||||
}
|
||||
friend class JsonCodec;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
class JsonCodec::Handler<T, Style::CAPABILITY>: private JsonCodec::HandlerBase {
|
||||
public:
|
||||
virtual void encode(const JsonCodec& codec, typename T::Client input,
|
||||
JsonValue::Builder output) const = 0;
|
||||
virtual typename T::Client decode(const JsonCodec& codec, JsonValue::Reader input) const = 0;
|
||||
|
||||
private:
|
||||
void encodeBase(const JsonCodec& codec, DynamicValue::Reader input,
|
||||
JsonValue::Builder output) const override final {
|
||||
encode(codec, input.as<T>(), output);
|
||||
}
|
||||
Orphan<DynamicValue> decodeBase(const JsonCodec& codec, JsonValue::Reader input,
|
||||
Type type, Orphanage orphanage) const override final {
|
||||
return orphanage.newOrphanCopy(decode(codec, input));
|
||||
}
|
||||
friend class JsonCodec;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
inline void JsonCodec::addTypeHandler(Handler<T>& handler) {
|
||||
addTypeHandlerImpl(Type::from<T>(), handler);
|
||||
}
|
||||
inline void JsonCodec::addTypeHandler(Type type, Handler<DynamicValue>& handler) {
|
||||
addTypeHandlerImpl(type, handler);
|
||||
}
|
||||
inline void JsonCodec::addTypeHandler(EnumSchema type, Handler<DynamicEnum>& handler) {
|
||||
addTypeHandlerImpl(type, handler);
|
||||
}
|
||||
inline void JsonCodec::addTypeHandler(StructSchema type, Handler<DynamicStruct>& handler) {
|
||||
addTypeHandlerImpl(type, handler);
|
||||
}
|
||||
inline void JsonCodec::addTypeHandler(ListSchema type, Handler<DynamicList>& handler) {
|
||||
addTypeHandlerImpl(type, handler);
|
||||
}
|
||||
inline void JsonCodec::addTypeHandler(InterfaceSchema type, Handler<DynamicCapability>& handler) {
|
||||
addTypeHandlerImpl(type, handler);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline void JsonCodec::addFieldHandler(StructSchema::Field field, Handler<T>& handler) {
|
||||
addFieldHandlerImpl(field, Type::from<T>(), handler);
|
||||
}
|
||||
|
||||
template <> void JsonCodec::addTypeHandler(Handler<DynamicValue>& handler)
|
||||
KJ_UNAVAILABLE("JSON handlers for type sets (e.g. all structs, all lists) not implemented; "
|
||||
"try specifying a specific type schema as the first parameter");
|
||||
template <> void JsonCodec::addTypeHandler(Handler<DynamicEnum>& handler)
|
||||
KJ_UNAVAILABLE("JSON handlers for type sets (e.g. all structs, all lists) not implemented; "
|
||||
"try specifying a specific type schema as the first parameter");
|
||||
template <> void JsonCodec::addTypeHandler(Handler<DynamicStruct>& handler)
|
||||
KJ_UNAVAILABLE("JSON handlers for type sets (e.g. all structs, all lists) not implemented; "
|
||||
"try specifying a specific type schema as the first parameter");
|
||||
template <> void JsonCodec::addTypeHandler(Handler<DynamicList>& handler)
|
||||
KJ_UNAVAILABLE("JSON handlers for type sets (e.g. all structs, all lists) not implemented; "
|
||||
"try specifying a specific type schema as the first parameter");
|
||||
template <> void JsonCodec::addTypeHandler(Handler<DynamicCapability>& handler)
|
||||
KJ_UNAVAILABLE("JSON handlers for type sets (e.g. all structs, all lists) not implemented; "
|
||||
"try specifying a specific type schema as the first parameter");
|
||||
// TODO(someday): Implement support for registering handlers that cover thinsg like "all structs"
|
||||
// or "all lists". Currently you can only target a specific struct or list type.
|
||||
|
||||
} // namespace capnp
|
||||
|
||||
#endif // CAPNP_COMPAT_JSON_H_
|
||||
1643
phonelibs/capnp-cpp/include/capnp/dynamic.h
Normal file
1643
phonelibs/capnp-cpp/include/capnp/dynamic.h
Normal file
File diff suppressed because it is too large
Load Diff
309
phonelibs/capnp-cpp/include/capnp/endian.h
Normal file
309
phonelibs/capnp-cpp/include/capnp/endian.h
Normal file
@@ -0,0 +1,309 @@
|
||||
// Copyright (c) 2013-2014 Sandstorm Development Group, Inc. and contributors
|
||||
// Licensed under the MIT License:
|
||||
//
|
||||
// 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.
|
||||
|
||||
#ifndef CAPNP_ENDIAN_H_
|
||||
#define CAPNP_ENDIAN_H_
|
||||
|
||||
#if defined(__GNUC__) && !defined(CAPNP_HEADER_WARNINGS)
|
||||
#pragma GCC system_header
|
||||
#endif
|
||||
|
||||
#include "common.h"
|
||||
#include <inttypes.h>
|
||||
#include <string.h> // memcpy
|
||||
|
||||
namespace capnp {
|
||||
namespace _ { // private
|
||||
|
||||
// WireValue
|
||||
//
|
||||
// Wraps a primitive value as it appears on the wire. Namely, values are little-endian on the
|
||||
// wire, because little-endian is the most common endianness in modern CPUs.
|
||||
//
|
||||
// Note: In general, code that depends cares about byte ordering is bad. See:
|
||||
// http://commandcenter.blogspot.com/2012/04/byte-order-fallacy.html
|
||||
// Cap'n Proto is special because it is essentially doing compiler-like things, fussing over
|
||||
// allocation and layout of memory, in order to squeeze out every last drop of performance.
|
||||
|
||||
#if _MSC_VER
|
||||
// Assume Windows is little-endian.
|
||||
//
|
||||
// TODO(msvc): This is ugly. Maybe refactor later checks to be based on CAPNP_BYTE_ORDER or
|
||||
// CAPNP_SWAP_BYTES or something, and define that in turn based on _MSC_VER or the GCC
|
||||
// intrinsics.
|
||||
|
||||
#ifndef __ORDER_BIG_ENDIAN__
|
||||
#define __ORDER_BIG_ENDIAN__ 4321
|
||||
#endif
|
||||
#ifndef __ORDER_LITTLE_ENDIAN__
|
||||
#define __ORDER_LITTLE_ENDIAN__ 1234
|
||||
#endif
|
||||
#ifndef __BYTE_ORDER__
|
||||
#define __BYTE_ORDER__ __ORDER_LITTLE_ENDIAN__
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if CAPNP_REVERSE_ENDIAN
|
||||
#define CAPNP_WIRE_BYTE_ORDER __ORDER_BIG_ENDIAN__
|
||||
#define CAPNP_OPPOSITE_OF_WIRE_BYTE_ORDER __ORDER_LITTLE_ENDIAN__
|
||||
#else
|
||||
#define CAPNP_WIRE_BYTE_ORDER __ORDER_LITTLE_ENDIAN__
|
||||
#define CAPNP_OPPOSITE_OF_WIRE_BYTE_ORDER __ORDER_BIG_ENDIAN__
|
||||
#endif
|
||||
|
||||
#if defined(__BYTE_ORDER__) && \
|
||||
__BYTE_ORDER__ == CAPNP_WIRE_BYTE_ORDER && \
|
||||
!CAPNP_DISABLE_ENDIAN_DETECTION
|
||||
// CPU is little-endian. We can just read/write the memory directly.
|
||||
|
||||
template <typename T>
|
||||
class DirectWireValue {
|
||||
public:
|
||||
KJ_ALWAYS_INLINE(T get() const) { return value; }
|
||||
KJ_ALWAYS_INLINE(void set(T newValue)) { value = newValue; }
|
||||
|
||||
private:
|
||||
T value;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
using WireValue = DirectWireValue<T>;
|
||||
// To prevent ODR problems when endian-test, endian-reverse-test, and endian-fallback-test are
|
||||
// linked together, we define each implementation with a different name and define an alias to the
|
||||
// one we want to use.
|
||||
|
||||
#elif defined(__BYTE_ORDER__) && \
|
||||
__BYTE_ORDER__ == CAPNP_OPPOSITE_OF_WIRE_BYTE_ORDER && \
|
||||
defined(__GNUC__) && !CAPNP_DISABLE_ENDIAN_DETECTION
|
||||
// Big-endian, but GCC's __builtin_bswap() is available.
|
||||
|
||||
// TODO(perf): Use dedicated instructions to read little-endian data on big-endian CPUs that have
|
||||
// them.
|
||||
|
||||
// TODO(perf): Verify that this code optimizes reasonably. In particular, ensure that the
|
||||
// compiler optimizes away the memcpy()s and keeps everything in registers.
|
||||
|
||||
template <typename T, size_t size = sizeof(T)>
|
||||
class SwappingWireValue;
|
||||
|
||||
template <typename T>
|
||||
class SwappingWireValue<T, 1> {
|
||||
public:
|
||||
KJ_ALWAYS_INLINE(T get() const) { return value; }
|
||||
KJ_ALWAYS_INLINE(void set(T newValue)) { value = newValue; }
|
||||
|
||||
private:
|
||||
T value;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
class SwappingWireValue<T, 2> {
|
||||
public:
|
||||
KJ_ALWAYS_INLINE(T get() const) {
|
||||
// Not all platforms have __builtin_bswap16() for some reason. In particular, it is missing
|
||||
// on gcc-4.7.3-cygwin32 (but present on gcc-4.8.1-cygwin64).
|
||||
uint16_t swapped = (value << 8) | (value >> 8);
|
||||
T result;
|
||||
memcpy(&result, &swapped, sizeof(T));
|
||||
return result;
|
||||
}
|
||||
KJ_ALWAYS_INLINE(void set(T newValue)) {
|
||||
uint16_t raw;
|
||||
memcpy(&raw, &newValue, sizeof(T));
|
||||
// Not all platforms have __builtin_bswap16() for some reason. In particular, it is missing
|
||||
// on gcc-4.7.3-cygwin32 (but present on gcc-4.8.1-cygwin64).
|
||||
value = (raw << 8) | (raw >> 8);
|
||||
}
|
||||
|
||||
private:
|
||||
uint16_t value;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
class SwappingWireValue<T, 4> {
|
||||
public:
|
||||
KJ_ALWAYS_INLINE(T get() const) {
|
||||
uint32_t swapped = __builtin_bswap32(value);
|
||||
T result;
|
||||
memcpy(&result, &swapped, sizeof(T));
|
||||
return result;
|
||||
}
|
||||
KJ_ALWAYS_INLINE(void set(T newValue)) {
|
||||
uint32_t raw;
|
||||
memcpy(&raw, &newValue, sizeof(T));
|
||||
value = __builtin_bswap32(raw);
|
||||
}
|
||||
|
||||
private:
|
||||
uint32_t value;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
class SwappingWireValue<T, 8> {
|
||||
public:
|
||||
KJ_ALWAYS_INLINE(T get() const) {
|
||||
uint64_t swapped = __builtin_bswap64(value);
|
||||
T result;
|
||||
memcpy(&result, &swapped, sizeof(T));
|
||||
return result;
|
||||
}
|
||||
KJ_ALWAYS_INLINE(void set(T newValue)) {
|
||||
uint64_t raw;
|
||||
memcpy(&raw, &newValue, sizeof(T));
|
||||
value = __builtin_bswap64(raw);
|
||||
}
|
||||
|
||||
private:
|
||||
uint64_t value;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
using WireValue = SwappingWireValue<T>;
|
||||
// To prevent ODR problems when endian-test, endian-reverse-test, and endian-fallback-test are
|
||||
// linked together, we define each implementation with a different name and define an alias to the
|
||||
// one we want to use.
|
||||
|
||||
#else
|
||||
// Unknown endianness. Fall back to bit shifts.
|
||||
|
||||
#if !CAPNP_DISABLE_ENDIAN_DETECTION
|
||||
#if _MSC_VER
|
||||
#pragma message("Couldn't detect endianness of your platform. Using unoptimized fallback implementation.")
|
||||
#pragma message("Consider changing this code to detect your platform and send us a patch!")
|
||||
#else
|
||||
#warning "Couldn't detect endianness of your platform. Using unoptimized fallback implementation."
|
||||
#warning "Consider changing this code to detect your platform and send us a patch!"
|
||||
#endif
|
||||
#endif // !CAPNP_DISABLE_ENDIAN_DETECTION
|
||||
|
||||
template <typename T, size_t size = sizeof(T)>
|
||||
class ShiftingWireValue;
|
||||
|
||||
template <typename T>
|
||||
class ShiftingWireValue<T, 1> {
|
||||
public:
|
||||
KJ_ALWAYS_INLINE(T get() const) { return value; }
|
||||
KJ_ALWAYS_INLINE(void set(T newValue)) { value = newValue; }
|
||||
|
||||
private:
|
||||
T value;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
class ShiftingWireValue<T, 2> {
|
||||
public:
|
||||
KJ_ALWAYS_INLINE(T get() const) {
|
||||
uint16_t raw = (static_cast<uint16_t>(bytes[0]) ) |
|
||||
(static_cast<uint16_t>(bytes[1]) << 8);
|
||||
T result;
|
||||
memcpy(&result, &raw, sizeof(T));
|
||||
return result;
|
||||
}
|
||||
KJ_ALWAYS_INLINE(void set(T newValue)) {
|
||||
uint16_t raw;
|
||||
memcpy(&raw, &newValue, sizeof(T));
|
||||
bytes[0] = raw;
|
||||
bytes[1] = raw >> 8;
|
||||
}
|
||||
|
||||
private:
|
||||
union {
|
||||
byte bytes[2];
|
||||
uint16_t align;
|
||||
};
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
class ShiftingWireValue<T, 4> {
|
||||
public:
|
||||
KJ_ALWAYS_INLINE(T get() const) {
|
||||
uint32_t raw = (static_cast<uint32_t>(bytes[0]) ) |
|
||||
(static_cast<uint32_t>(bytes[1]) << 8) |
|
||||
(static_cast<uint32_t>(bytes[2]) << 16) |
|
||||
(static_cast<uint32_t>(bytes[3]) << 24);
|
||||
T result;
|
||||
memcpy(&result, &raw, sizeof(T));
|
||||
return result;
|
||||
}
|
||||
KJ_ALWAYS_INLINE(void set(T newValue)) {
|
||||
uint32_t raw;
|
||||
memcpy(&raw, &newValue, sizeof(T));
|
||||
bytes[0] = raw;
|
||||
bytes[1] = raw >> 8;
|
||||
bytes[2] = raw >> 16;
|
||||
bytes[3] = raw >> 24;
|
||||
}
|
||||
|
||||
private:
|
||||
union {
|
||||
byte bytes[4];
|
||||
uint32_t align;
|
||||
};
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
class ShiftingWireValue<T, 8> {
|
||||
public:
|
||||
KJ_ALWAYS_INLINE(T get() const) {
|
||||
uint64_t raw = (static_cast<uint64_t>(bytes[0]) ) |
|
||||
(static_cast<uint64_t>(bytes[1]) << 8) |
|
||||
(static_cast<uint64_t>(bytes[2]) << 16) |
|
||||
(static_cast<uint64_t>(bytes[3]) << 24) |
|
||||
(static_cast<uint64_t>(bytes[4]) << 32) |
|
||||
(static_cast<uint64_t>(bytes[5]) << 40) |
|
||||
(static_cast<uint64_t>(bytes[6]) << 48) |
|
||||
(static_cast<uint64_t>(bytes[7]) << 56);
|
||||
T result;
|
||||
memcpy(&result, &raw, sizeof(T));
|
||||
return result;
|
||||
}
|
||||
KJ_ALWAYS_INLINE(void set(T newValue)) {
|
||||
uint64_t raw;
|
||||
memcpy(&raw, &newValue, sizeof(T));
|
||||
bytes[0] = raw;
|
||||
bytes[1] = raw >> 8;
|
||||
bytes[2] = raw >> 16;
|
||||
bytes[3] = raw >> 24;
|
||||
bytes[4] = raw >> 32;
|
||||
bytes[5] = raw >> 40;
|
||||
bytes[6] = raw >> 48;
|
||||
bytes[7] = raw >> 56;
|
||||
}
|
||||
|
||||
private:
|
||||
union {
|
||||
byte bytes[8];
|
||||
uint64_t align;
|
||||
};
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
using WireValue = ShiftingWireValue<T>;
|
||||
// To prevent ODR problems when endian-test, endian-reverse-test, and endian-fallback-test are
|
||||
// linked together, we define each implementation with a different name and define an alias to the
|
||||
// one we want to use.
|
||||
|
||||
#endif
|
||||
|
||||
} // namespace _ (private)
|
||||
} // namespace capnp
|
||||
|
||||
#endif // CAPNP_ENDIAN_H_
|
||||
254
phonelibs/capnp-cpp/include/capnp/ez-rpc.h
Normal file
254
phonelibs/capnp-cpp/include/capnp/ez-rpc.h
Normal file
@@ -0,0 +1,254 @@
|
||||
// Copyright (c) 2013-2014 Sandstorm Development Group, Inc. and contributors
|
||||
// Licensed under the MIT License:
|
||||
//
|
||||
// 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.
|
||||
|
||||
#ifndef CAPNP_EZ_RPC_H_
|
||||
#define CAPNP_EZ_RPC_H_
|
||||
|
||||
#if defined(__GNUC__) && !defined(CAPNP_HEADER_WARNINGS)
|
||||
#pragma GCC system_header
|
||||
#endif
|
||||
|
||||
#include "rpc.h"
|
||||
#include "message.h"
|
||||
|
||||
struct sockaddr;
|
||||
|
||||
namespace kj { class AsyncIoProvider; class LowLevelAsyncIoProvider; }
|
||||
|
||||
namespace capnp {
|
||||
|
||||
class EzRpcContext;
|
||||
|
||||
class EzRpcClient {
|
||||
// Super-simple interface for setting up a Cap'n Proto RPC client. Example:
|
||||
//
|
||||
// # Cap'n Proto schema
|
||||
// interface Adder {
|
||||
// add @0 (left :Int32, right :Int32) -> (value :Int32);
|
||||
// }
|
||||
//
|
||||
// // C++ client
|
||||
// int main() {
|
||||
// capnp::EzRpcClient client("localhost:3456");
|
||||
// Adder::Client adder = client.getMain<Adder>();
|
||||
// auto request = adder.addRequest();
|
||||
// request.setLeft(12);
|
||||
// request.setRight(34);
|
||||
// auto response = request.send().wait(client.getWaitScope());
|
||||
// assert(response.getValue() == 46);
|
||||
// return 0;
|
||||
// }
|
||||
//
|
||||
// // C++ server
|
||||
// class AdderImpl final: public Adder::Server {
|
||||
// public:
|
||||
// kj::Promise<void> add(AddContext context) override {
|
||||
// auto params = context.getParams();
|
||||
// context.getResults().setValue(params.getLeft() + params.getRight());
|
||||
// return kj::READY_NOW;
|
||||
// }
|
||||
// };
|
||||
//
|
||||
// int main() {
|
||||
// capnp::EzRpcServer server(kj::heap<AdderImpl>(), "*:3456");
|
||||
// kj::NEVER_DONE.wait(server.getWaitScope());
|
||||
// }
|
||||
//
|
||||
// This interface is easy, but it hides a lot of useful features available from the lower-level
|
||||
// classes:
|
||||
// - The server can only export a small set of public, singleton capabilities under well-known
|
||||
// string names. This is fine for transient services where no state needs to be kept between
|
||||
// connections, but hides the power of Cap'n Proto when it comes to long-lived resources.
|
||||
// - EzRpcClient/EzRpcServer automatically set up a `kj::EventLoop` and make it current for the
|
||||
// thread. Only one `kj::EventLoop` can exist per thread, so you cannot use these interfaces
|
||||
// if you wish to set up your own event loop. (However, you can safely create multiple
|
||||
// EzRpcClient / EzRpcServer objects in a single thread; they will make sure to make no more
|
||||
// than one EventLoop.)
|
||||
// - These classes only support simple two-party connections, not multilateral VatNetworks.
|
||||
// - These classes only support communication over a raw, unencrypted socket. If you want to
|
||||
// build on an abstract stream (perhaps one which supports encryption), you must use the
|
||||
// lower-level interfaces.
|
||||
//
|
||||
// Some of these restrictions will probably be lifted in future versions, but some things will
|
||||
// always require using the low-level interfaces directly. If you are interested in working
|
||||
// at a lower level, start by looking at these interfaces:
|
||||
// - `kj::setupAsyncIo()` in `kj/async-io.h`.
|
||||
// - `RpcSystem` in `capnp/rpc.h`.
|
||||
// - `TwoPartyVatNetwork` in `capnp/rpc-twoparty.h`.
|
||||
|
||||
public:
|
||||
explicit EzRpcClient(kj::StringPtr serverAddress, uint defaultPort = 0,
|
||||
ReaderOptions readerOpts = ReaderOptions());
|
||||
// Construct a new EzRpcClient and connect to the given address. The connection is formed in
|
||||
// the background -- if it fails, calls to capabilities returned by importCap() will fail with an
|
||||
// appropriate exception.
|
||||
//
|
||||
// `defaultPort` is the IP port number to use if `serverAddress` does not include it explicitly.
|
||||
// If unspecified, the port is required in `serverAddress`.
|
||||
//
|
||||
// The address is parsed by `kj::Network` in `kj/async-io.h`. See that interface for more info
|
||||
// on the address format, but basically it's what you'd expect.
|
||||
//
|
||||
// `readerOpts` is the ReaderOptions structure used to read each incoming message on the
|
||||
// connection. Setting this may be necessary if you need to receive very large individual
|
||||
// messages or messages. However, it is recommended that you instead think about how to change
|
||||
// your protocol to send large data blobs in multiple small chunks -- this is much better for
|
||||
// both security and performance. See `ReaderOptions` in `message.h` for more details.
|
||||
|
||||
EzRpcClient(const struct sockaddr* serverAddress, uint addrSize,
|
||||
ReaderOptions readerOpts = ReaderOptions());
|
||||
// Like the above constructor, but connects to an already-resolved socket address. Any address
|
||||
// format supported by `kj::Network` in `kj/async-io.h` is accepted.
|
||||
|
||||
explicit EzRpcClient(int socketFd, ReaderOptions readerOpts = ReaderOptions());
|
||||
// Create a client on top of an already-connected socket.
|
||||
// `readerOpts` acts as in the first constructor.
|
||||
|
||||
~EzRpcClient() noexcept(false);
|
||||
|
||||
template <typename Type>
|
||||
typename Type::Client getMain();
|
||||
Capability::Client getMain();
|
||||
// Get the server's main (aka "bootstrap") interface.
|
||||
|
||||
template <typename Type>
|
||||
typename Type::Client importCap(kj::StringPtr name)
|
||||
KJ_DEPRECATED("Change your server to export a main interface, then use getMain() instead.");
|
||||
Capability::Client importCap(kj::StringPtr name)
|
||||
KJ_DEPRECATED("Change your server to export a main interface, then use getMain() instead.");
|
||||
// ** DEPRECATED **
|
||||
//
|
||||
// Ask the sever for the capability with the given name. You may specify a type to automatically
|
||||
// down-cast to that type. It is up to you to specify the correct expected type.
|
||||
//
|
||||
// Named interfaces are deprecated. The new preferred usage pattern is for the server to export
|
||||
// a "main" interface which itself has methods for getting any other interfaces.
|
||||
|
||||
kj::WaitScope& getWaitScope();
|
||||
// Get the `WaitScope` for the client's `EventLoop`, which allows you to synchronously wait on
|
||||
// promises.
|
||||
|
||||
kj::AsyncIoProvider& getIoProvider();
|
||||
// Get the underlying AsyncIoProvider set up by the RPC system. This is useful if you want
|
||||
// to do some non-RPC I/O in asynchronous fashion.
|
||||
|
||||
kj::LowLevelAsyncIoProvider& getLowLevelIoProvider();
|
||||
// Get the underlying LowLevelAsyncIoProvider set up by the RPC system. This is useful if you
|
||||
// want to do some non-RPC I/O in asynchronous fashion.
|
||||
|
||||
private:
|
||||
struct Impl;
|
||||
kj::Own<Impl> impl;
|
||||
};
|
||||
|
||||
class EzRpcServer {
|
||||
// The server counterpart to `EzRpcClient`. See `EzRpcClient` for an example.
|
||||
|
||||
public:
|
||||
explicit EzRpcServer(Capability::Client mainInterface, kj::StringPtr bindAddress,
|
||||
uint defaultPort = 0, ReaderOptions readerOpts = ReaderOptions());
|
||||
// Construct a new `EzRpcServer` that binds to the given address. An address of "*" means to
|
||||
// bind to all local addresses.
|
||||
//
|
||||
// `defaultPort` is the IP port number to use if `serverAddress` does not include it explicitly.
|
||||
// If unspecified, a port is chosen automatically, and you must call getPort() to find out what
|
||||
// it is.
|
||||
//
|
||||
// The address is parsed by `kj::Network` in `kj/async-io.h`. See that interface for more info
|
||||
// on the address format, but basically it's what you'd expect.
|
||||
//
|
||||
// The server might not begin listening immediately, especially if `bindAddress` needs to be
|
||||
// resolved. If you need to wait until the server is definitely up, wait on the promise returned
|
||||
// by `getPort()`.
|
||||
//
|
||||
// `readerOpts` is the ReaderOptions structure used to read each incoming message on the
|
||||
// connection. Setting this may be necessary if you need to receive very large individual
|
||||
// messages or messages. However, it is recommended that you instead think about how to change
|
||||
// your protocol to send large data blobs in multiple small chunks -- this is much better for
|
||||
// both security and performance. See `ReaderOptions` in `message.h` for more details.
|
||||
|
||||
EzRpcServer(Capability::Client mainInterface, struct sockaddr* bindAddress, uint addrSize,
|
||||
ReaderOptions readerOpts = ReaderOptions());
|
||||
// Like the above constructor, but binds to an already-resolved socket address. Any address
|
||||
// format supported by `kj::Network` in `kj/async-io.h` is accepted.
|
||||
|
||||
EzRpcServer(Capability::Client mainInterface, int socketFd, uint port,
|
||||
ReaderOptions readerOpts = ReaderOptions());
|
||||
// Create a server on top of an already-listening socket (i.e. one on which accept() may be
|
||||
// called). `port` is returned by `getPort()` -- it serves no other purpose.
|
||||
// `readerOpts` acts as in the other two above constructors.
|
||||
|
||||
explicit EzRpcServer(kj::StringPtr bindAddress, uint defaultPort = 0,
|
||||
ReaderOptions readerOpts = ReaderOptions())
|
||||
KJ_DEPRECATED("Please specify a main interface for your server.");
|
||||
EzRpcServer(struct sockaddr* bindAddress, uint addrSize,
|
||||
ReaderOptions readerOpts = ReaderOptions())
|
||||
KJ_DEPRECATED("Please specify a main interface for your server.");
|
||||
EzRpcServer(int socketFd, uint port, ReaderOptions readerOpts = ReaderOptions())
|
||||
KJ_DEPRECATED("Please specify a main interface for your server.");
|
||||
|
||||
~EzRpcServer() noexcept(false);
|
||||
|
||||
void exportCap(kj::StringPtr name, Capability::Client cap);
|
||||
// Export a capability publicly under the given name, so that clients can import it.
|
||||
//
|
||||
// Keep in mind that you can implicitly convert `kj::Own<MyType::Server>&&` to
|
||||
// `Capability::Client`, so it's typical to pass something like
|
||||
// `kj::heap<MyImplementation>(<constructor params>)` as the second parameter.
|
||||
|
||||
kj::Promise<uint> getPort();
|
||||
// Get the IP port number on which this server is listening. This promise won't resolve until
|
||||
// the server is actually listening. If the address was not an IP address (e.g. it was a Unix
|
||||
// domain socket) then getPort() resolves to zero.
|
||||
|
||||
kj::WaitScope& getWaitScope();
|
||||
// Get the `WaitScope` for the client's `EventLoop`, which allows you to synchronously wait on
|
||||
// promises.
|
||||
|
||||
kj::AsyncIoProvider& getIoProvider();
|
||||
// Get the underlying AsyncIoProvider set up by the RPC system. This is useful if you want
|
||||
// to do some non-RPC I/O in asynchronous fashion.
|
||||
|
||||
kj::LowLevelAsyncIoProvider& getLowLevelIoProvider();
|
||||
// Get the underlying LowLevelAsyncIoProvider set up by the RPC system. This is useful if you
|
||||
// want to do some non-RPC I/O in asynchronous fashion.
|
||||
|
||||
private:
|
||||
struct Impl;
|
||||
kj::Own<Impl> impl;
|
||||
};
|
||||
|
||||
// =======================================================================================
|
||||
// inline implementation details
|
||||
|
||||
template <typename Type>
|
||||
inline typename Type::Client EzRpcClient::getMain() {
|
||||
return getMain().castAs<Type>();
|
||||
}
|
||||
|
||||
template <typename Type>
|
||||
inline typename Type::Client EzRpcClient::importCap(kj::StringPtr name) {
|
||||
return importCap(name).castAs<Type>();
|
||||
}
|
||||
|
||||
} // namespace capnp
|
||||
|
||||
#endif // CAPNP_EZ_RPC_H_
|
||||
407
phonelibs/capnp-cpp/include/capnp/generated-header-support.h
Normal file
407
phonelibs/capnp-cpp/include/capnp/generated-header-support.h
Normal file
@@ -0,0 +1,407 @@
|
||||
// Copyright (c) 2013-2014 Sandstorm Development Group, Inc. and contributors
|
||||
// Licensed under the MIT License:
|
||||
//
|
||||
// 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.
|
||||
|
||||
// This file is included from all generated headers.
|
||||
|
||||
#ifndef CAPNP_GENERATED_HEADER_SUPPORT_H_
|
||||
#define CAPNP_GENERATED_HEADER_SUPPORT_H_
|
||||
|
||||
#if defined(__GNUC__) && !defined(CAPNP_HEADER_WARNINGS)
|
||||
#pragma GCC system_header
|
||||
#endif
|
||||
|
||||
#include "raw-schema.h"
|
||||
#include "layout.h"
|
||||
#include "list.h"
|
||||
#include "orphan.h"
|
||||
#include "pointer-helpers.h"
|
||||
#include "any.h"
|
||||
#include <kj/string.h>
|
||||
#include <kj/string-tree.h>
|
||||
|
||||
namespace capnp {
|
||||
|
||||
class MessageBuilder; // So that it can be declared a friend.
|
||||
|
||||
template <typename T, Kind k = CAPNP_KIND(T)>
|
||||
struct ToDynamic_; // Defined in dynamic.h, needs to be declared as everyone's friend.
|
||||
|
||||
struct DynamicStruct; // So that it can be declared a friend.
|
||||
|
||||
struct Capability; // To declare brandBindingFor<Capability>()
|
||||
|
||||
namespace _ { // private
|
||||
|
||||
#if !CAPNP_LITE
|
||||
|
||||
template <typename T, typename CapnpPrivate = typename T::_capnpPrivate, bool = false>
|
||||
inline const RawSchema& rawSchema() {
|
||||
return *CapnpPrivate::schema;
|
||||
}
|
||||
template <typename T, uint64_t id = schemas::EnumInfo<T>::typeId>
|
||||
inline const RawSchema& rawSchema() {
|
||||
return *schemas::EnumInfo<T>::schema;
|
||||
}
|
||||
|
||||
template <typename T, typename CapnpPrivate = typename T::_capnpPrivate>
|
||||
inline const RawBrandedSchema& rawBrandedSchema() {
|
||||
return *CapnpPrivate::brand();
|
||||
}
|
||||
template <typename T, uint64_t id = schemas::EnumInfo<T>::typeId>
|
||||
inline const RawBrandedSchema& rawBrandedSchema() {
|
||||
return schemas::EnumInfo<T>::schema->defaultBrand;
|
||||
}
|
||||
|
||||
template <typename TypeTag, typename... Params>
|
||||
struct ChooseBrand;
|
||||
// If all of `Params` are `AnyPointer`, return the type's default brand. Otherwise, return a
|
||||
// specific brand instance. TypeTag is the _capnpPrivate struct for the type in question.
|
||||
|
||||
template <typename TypeTag>
|
||||
struct ChooseBrand<TypeTag> {
|
||||
// All params were AnyPointer. No specific brand needed.
|
||||
static constexpr _::RawBrandedSchema const* brand() { return &TypeTag::schema->defaultBrand; }
|
||||
};
|
||||
|
||||
template <typename TypeTag, typename... Rest>
|
||||
struct ChooseBrand<TypeTag, AnyPointer, Rest...>: public ChooseBrand<TypeTag, Rest...> {};
|
||||
// The first parameter is AnyPointer, so recurse to check the rest.
|
||||
|
||||
template <typename TypeTag, typename First, typename... Rest>
|
||||
struct ChooseBrand<TypeTag, First, Rest...> {
|
||||
// At least one parameter is not AnyPointer, so use the specificBrand constant.
|
||||
static constexpr _::RawBrandedSchema const* brand() { return &TypeTag::specificBrand; }
|
||||
};
|
||||
|
||||
template <typename T, Kind k = kind<T>()>
|
||||
struct BrandBindingFor_;
|
||||
|
||||
#define HANDLE_TYPE(Type, which) \
|
||||
template <> \
|
||||
struct BrandBindingFor_<Type, Kind::PRIMITIVE> { \
|
||||
static constexpr RawBrandedSchema::Binding get(uint16_t listDepth) { \
|
||||
return { which, listDepth, nullptr }; \
|
||||
} \
|
||||
}
|
||||
HANDLE_TYPE(Void, 0);
|
||||
HANDLE_TYPE(bool, 1);
|
||||
HANDLE_TYPE(int8_t, 2);
|
||||
HANDLE_TYPE(int16_t, 3);
|
||||
HANDLE_TYPE(int32_t, 4);
|
||||
HANDLE_TYPE(int64_t, 5);
|
||||
HANDLE_TYPE(uint8_t, 6);
|
||||
HANDLE_TYPE(uint16_t, 7);
|
||||
HANDLE_TYPE(uint32_t, 8);
|
||||
HANDLE_TYPE(uint64_t, 9);
|
||||
HANDLE_TYPE(float, 10);
|
||||
HANDLE_TYPE(double, 11);
|
||||
#undef HANDLE_TYPE
|
||||
|
||||
template <>
|
||||
struct BrandBindingFor_<Text, Kind::BLOB> {
|
||||
static constexpr RawBrandedSchema::Binding get(uint16_t listDepth) {
|
||||
return { 12, listDepth, nullptr };
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct BrandBindingFor_<Data, Kind::BLOB> {
|
||||
static constexpr RawBrandedSchema::Binding get(uint16_t listDepth) {
|
||||
return { 13, listDepth, nullptr };
|
||||
}
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct BrandBindingFor_<List<T>, Kind::LIST> {
|
||||
static constexpr RawBrandedSchema::Binding get(uint16_t listDepth) {
|
||||
return BrandBindingFor_<T>::get(listDepth + 1);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct BrandBindingFor_<T, Kind::ENUM> {
|
||||
static constexpr RawBrandedSchema::Binding get(uint16_t listDepth) {
|
||||
return { 15, listDepth, nullptr };
|
||||
}
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct BrandBindingFor_<T, Kind::STRUCT> {
|
||||
static constexpr RawBrandedSchema::Binding get(uint16_t listDepth) {
|
||||
return { 16, listDepth, T::_capnpPrivate::brand() };
|
||||
}
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct BrandBindingFor_<T, Kind::INTERFACE> {
|
||||
static constexpr RawBrandedSchema::Binding get(uint16_t listDepth) {
|
||||
return { 17, listDepth, T::_capnpPrivate::brand() };
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct BrandBindingFor_<AnyPointer, Kind::OTHER> {
|
||||
static constexpr RawBrandedSchema::Binding get(uint16_t listDepth) {
|
||||
return { 18, listDepth, 0, 0 };
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct BrandBindingFor_<AnyStruct, Kind::OTHER> {
|
||||
static constexpr RawBrandedSchema::Binding get(uint16_t listDepth) {
|
||||
return { 18, listDepth, 0, 1 };
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct BrandBindingFor_<AnyList, Kind::OTHER> {
|
||||
static constexpr RawBrandedSchema::Binding get(uint16_t listDepth) {
|
||||
return { 18, listDepth, 0, 2 };
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct BrandBindingFor_<Capability, Kind::OTHER> {
|
||||
static constexpr RawBrandedSchema::Binding get(uint16_t listDepth) {
|
||||
return { 18, listDepth, 0, 3 };
|
||||
}
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
constexpr RawBrandedSchema::Binding brandBindingFor() {
|
||||
return BrandBindingFor_<T>::get(0);
|
||||
}
|
||||
|
||||
kj::StringTree structString(StructReader reader, const RawBrandedSchema& schema);
|
||||
kj::String enumString(uint16_t value, const RawBrandedSchema& schema);
|
||||
// Declared here so that we can declare inline stringify methods on generated types.
|
||||
// Defined in stringify.c++, which depends on dynamic.c++, which is allowed not to be linked in.
|
||||
|
||||
template <typename T>
|
||||
inline kj::StringTree structString(StructReader reader) {
|
||||
return structString(reader, rawBrandedSchema<T>());
|
||||
}
|
||||
template <typename T>
|
||||
inline kj::String enumString(T value) {
|
||||
return enumString(static_cast<uint16_t>(value), rawBrandedSchema<T>());
|
||||
}
|
||||
|
||||
#endif // !CAPNP_LITE
|
||||
|
||||
// TODO(cleanup): Unify ConstStruct and ConstList.
|
||||
template <typename T>
|
||||
class ConstStruct {
|
||||
public:
|
||||
ConstStruct() = delete;
|
||||
KJ_DISALLOW_COPY(ConstStruct);
|
||||
inline explicit constexpr ConstStruct(const word* ptr): ptr(ptr) {}
|
||||
|
||||
inline typename T::Reader get() const {
|
||||
return AnyPointer::Reader(PointerReader::getRootUnchecked(ptr)).getAs<T>();
|
||||
}
|
||||
|
||||
inline operator typename T::Reader() const { return get(); }
|
||||
inline typename T::Reader operator*() const { return get(); }
|
||||
inline TemporaryPointer<typename T::Reader> operator->() const { return get(); }
|
||||
|
||||
private:
|
||||
const word* ptr;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
class ConstList {
|
||||
public:
|
||||
ConstList() = delete;
|
||||
KJ_DISALLOW_COPY(ConstList);
|
||||
inline explicit constexpr ConstList(const word* ptr): ptr(ptr) {}
|
||||
|
||||
inline typename List<T>::Reader get() const {
|
||||
return AnyPointer::Reader(PointerReader::getRootUnchecked(ptr)).getAs<List<T>>();
|
||||
}
|
||||
|
||||
inline operator typename List<T>::Reader() const { return get(); }
|
||||
inline typename List<T>::Reader operator*() const { return get(); }
|
||||
inline TemporaryPointer<typename List<T>::Reader> operator->() const { return get(); }
|
||||
|
||||
private:
|
||||
const word* ptr;
|
||||
};
|
||||
|
||||
template <size_t size>
|
||||
class ConstText {
|
||||
public:
|
||||
ConstText() = delete;
|
||||
KJ_DISALLOW_COPY(ConstText);
|
||||
inline explicit constexpr ConstText(const word* ptr): ptr(ptr) {}
|
||||
|
||||
inline Text::Reader get() const {
|
||||
return Text::Reader(reinterpret_cast<const char*>(ptr), size);
|
||||
}
|
||||
|
||||
inline operator Text::Reader() const { return get(); }
|
||||
inline Text::Reader operator*() const { return get(); }
|
||||
inline TemporaryPointer<Text::Reader> operator->() const { return get(); }
|
||||
|
||||
inline kj::StringPtr toString() const {
|
||||
return get();
|
||||
}
|
||||
|
||||
private:
|
||||
const word* ptr;
|
||||
};
|
||||
|
||||
template <size_t size>
|
||||
inline kj::StringPtr KJ_STRINGIFY(const ConstText<size>& s) {
|
||||
return s.get();
|
||||
}
|
||||
|
||||
template <size_t size>
|
||||
class ConstData {
|
||||
public:
|
||||
ConstData() = delete;
|
||||
KJ_DISALLOW_COPY(ConstData);
|
||||
inline explicit constexpr ConstData(const word* ptr): ptr(ptr) {}
|
||||
|
||||
inline Data::Reader get() const {
|
||||
return Data::Reader(reinterpret_cast<const byte*>(ptr), size);
|
||||
}
|
||||
|
||||
inline operator Data::Reader() const { return get(); }
|
||||
inline Data::Reader operator*() const { return get(); }
|
||||
inline TemporaryPointer<Data::Reader> operator->() const { return get(); }
|
||||
|
||||
private:
|
||||
const word* ptr;
|
||||
};
|
||||
|
||||
template <size_t size>
|
||||
inline auto KJ_STRINGIFY(const ConstData<size>& s) -> decltype(kj::toCharSequence(s.get())) {
|
||||
return kj::toCharSequence(s.get());
|
||||
}
|
||||
|
||||
} // namespace _ (private)
|
||||
|
||||
template <typename T, typename CapnpPrivate = typename T::_capnpPrivate>
|
||||
inline constexpr uint64_t typeId() { return CapnpPrivate::typeId; }
|
||||
template <typename T, uint64_t id = schemas::EnumInfo<T>::typeId>
|
||||
inline constexpr uint64_t typeId() { return id; }
|
||||
// typeId<MyType>() returns the type ID as defined in the schema. Works with structs, enums, and
|
||||
// interfaces.
|
||||
|
||||
template <typename T>
|
||||
inline constexpr uint sizeInWords() {
|
||||
// Return the size, in words, of a Struct type, if allocated free-standing (not in a list).
|
||||
// May be useful for pre-computing space needed in order to precisely allocate messages.
|
||||
|
||||
return unbound((upgradeBound<uint>(_::structSize<T>().data) +
|
||||
_::structSize<T>().pointers * WORDS_PER_POINTER) / WORDS);
|
||||
}
|
||||
|
||||
} // namespace capnp
|
||||
|
||||
#if _MSC_VER
|
||||
// MSVC doesn't understand floating-point constexpr yet.
|
||||
//
|
||||
// TODO(msvc): Remove this hack when MSVC is fixed.
|
||||
#define CAPNP_NON_INT_CONSTEXPR_DECL_INIT(value)
|
||||
#define CAPNP_NON_INT_CONSTEXPR_DEF_INIT(value) = value
|
||||
#else
|
||||
#define CAPNP_NON_INT_CONSTEXPR_DECL_INIT(value) = value
|
||||
#define CAPNP_NON_INT_CONSTEXPR_DEF_INIT(value)
|
||||
#endif
|
||||
|
||||
#if _MSC_VER
|
||||
// TODO(msvc): A little hack to allow MSVC to use C++14 return type deduction in cases where the
|
||||
// explicit type exposes bugs in the compiler.
|
||||
#define CAPNP_AUTO_IF_MSVC(...) auto
|
||||
#else
|
||||
#define CAPNP_AUTO_IF_MSVC(...) __VA_ARGS__
|
||||
#endif
|
||||
|
||||
#if CAPNP_LITE
|
||||
|
||||
#define CAPNP_DECLARE_SCHEMA(id) \
|
||||
extern ::capnp::word const* const bp_##id
|
||||
|
||||
#define CAPNP_DECLARE_ENUM(type, id) \
|
||||
inline ::kj::String KJ_STRINGIFY(type##_##id value) { \
|
||||
return ::kj::str(static_cast<uint16_t>(value)); \
|
||||
} \
|
||||
template <> struct EnumInfo<type##_##id> { \
|
||||
struct IsEnum; \
|
||||
static constexpr uint64_t typeId = 0x##id; \
|
||||
static inline ::capnp::word const* encodedSchema() { return bp_##id; } \
|
||||
}
|
||||
|
||||
#if _MSC_VER
|
||||
// TODO(msvc): MSVC dosen't expect constexprs to have definitions.
|
||||
#define CAPNP_DEFINE_ENUM(type, id)
|
||||
#else
|
||||
#define CAPNP_DEFINE_ENUM(type, id) \
|
||||
constexpr uint64_t EnumInfo<type>::typeId
|
||||
#endif
|
||||
|
||||
#define CAPNP_DECLARE_STRUCT_HEADER(id, dataWordSize_, pointerCount_) \
|
||||
struct IsStruct; \
|
||||
static constexpr uint64_t typeId = 0x##id; \
|
||||
static constexpr uint16_t dataWordSize = dataWordSize_; \
|
||||
static constexpr uint16_t pointerCount = pointerCount_; \
|
||||
static inline ::capnp::word const* encodedSchema() { return ::capnp::schemas::bp_##id; }
|
||||
|
||||
#else // CAPNP_LITE
|
||||
|
||||
#define CAPNP_DECLARE_SCHEMA(id) \
|
||||
extern ::capnp::word const* const bp_##id; \
|
||||
extern const ::capnp::_::RawSchema s_##id
|
||||
|
||||
#define CAPNP_DECLARE_ENUM(type, id) \
|
||||
inline ::kj::String KJ_STRINGIFY(type##_##id value) { \
|
||||
return ::capnp::_::enumString(value); \
|
||||
} \
|
||||
template <> struct EnumInfo<type##_##id> { \
|
||||
struct IsEnum; \
|
||||
static constexpr uint64_t typeId = 0x##id; \
|
||||
static inline ::capnp::word const* encodedSchema() { return bp_##id; } \
|
||||
static constexpr ::capnp::_::RawSchema const* schema = &s_##id; \
|
||||
}
|
||||
#define CAPNP_DEFINE_ENUM(type, id) \
|
||||
constexpr uint64_t EnumInfo<type>::typeId; \
|
||||
constexpr ::capnp::_::RawSchema const* EnumInfo<type>::schema
|
||||
|
||||
#define CAPNP_DECLARE_STRUCT_HEADER(id, dataWordSize_, pointerCount_) \
|
||||
struct IsStruct; \
|
||||
static constexpr uint64_t typeId = 0x##id; \
|
||||
static constexpr ::capnp::Kind kind = ::capnp::Kind::STRUCT; \
|
||||
static constexpr uint16_t dataWordSize = dataWordSize_; \
|
||||
static constexpr uint16_t pointerCount = pointerCount_; \
|
||||
static inline ::capnp::word const* encodedSchema() { return ::capnp::schemas::bp_##id; } \
|
||||
static constexpr ::capnp::_::RawSchema const* schema = &::capnp::schemas::s_##id;
|
||||
|
||||
#define CAPNP_DECLARE_INTERFACE_HEADER(id) \
|
||||
struct IsInterface; \
|
||||
static constexpr uint64_t typeId = 0x##id; \
|
||||
static constexpr ::capnp::Kind kind = ::capnp::Kind::INTERFACE; \
|
||||
static inline ::capnp::word const* encodedSchema() { return ::capnp::schemas::bp_##id; } \
|
||||
static constexpr ::capnp::_::RawSchema const* schema = &::capnp::schemas::s_##id;
|
||||
|
||||
#endif // CAPNP_LITE, else
|
||||
|
||||
#endif // CAPNP_GENERATED_HEADER_SUPPORT_H_
|
||||
58
phonelibs/capnp-cpp/include/capnp/json.capnp
Normal file
58
phonelibs/capnp-cpp/include/capnp/json.capnp
Normal file
@@ -0,0 +1,58 @@
|
||||
# Copyright (c) 2015 Sandstorm Development Group, Inc. and contributors
|
||||
# Licensed under the MIT License:
|
||||
#
|
||||
# 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.
|
||||
|
||||
@0x8ef99297a43a5e34;
|
||||
|
||||
$import "/capnp/c++.capnp".namespace("capnp");
|
||||
|
||||
struct JsonValue {
|
||||
union {
|
||||
null @0 :Void;
|
||||
boolean @1 :Bool;
|
||||
number @2 :Float64;
|
||||
string @3 :Text;
|
||||
array @4 :List(JsonValue);
|
||||
object @5 :List(Field);
|
||||
# Standard JSON values.
|
||||
|
||||
call @6 :Call;
|
||||
# Non-standard: A "function call", applying a named function (named by a single identifier)
|
||||
# to a parameter list. Examples:
|
||||
#
|
||||
# BinData(0, "Zm9vCg==")
|
||||
# ISODate("2015-04-15T08:44:50.218Z")
|
||||
#
|
||||
# Mongo DB users will recognize the above as exactly the syntax Mongo uses to represent BSON
|
||||
# "binary" and "date" types in text, since JSON has no analog of these. This is basically the
|
||||
# reason this extension exists. We do NOT recommend using `call` unless you specifically need
|
||||
# to be compatible with some silly format that uses this syntax.
|
||||
}
|
||||
|
||||
struct Field {
|
||||
name @0 :Text;
|
||||
value @1 :JsonValue;
|
||||
}
|
||||
|
||||
struct Call {
|
||||
function @0 :Text;
|
||||
params @1 :List(JsonValue);
|
||||
}
|
||||
}
|
||||
1274
phonelibs/capnp-cpp/include/capnp/layout.h
Normal file
1274
phonelibs/capnp-cpp/include/capnp/layout.h
Normal file
File diff suppressed because it is too large
Load Diff
546
phonelibs/capnp-cpp/include/capnp/list.h
Normal file
546
phonelibs/capnp-cpp/include/capnp/list.h
Normal file
@@ -0,0 +1,546 @@
|
||||
// Copyright (c) 2013-2014 Sandstorm Development Group, Inc. and contributors
|
||||
// Licensed under the MIT License:
|
||||
//
|
||||
// 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.
|
||||
|
||||
#ifndef CAPNP_LIST_H_
|
||||
#define CAPNP_LIST_H_
|
||||
|
||||
#if defined(__GNUC__) && !defined(CAPNP_HEADER_WARNINGS)
|
||||
#pragma GCC system_header
|
||||
#endif
|
||||
|
||||
#include "layout.h"
|
||||
#include "orphan.h"
|
||||
#include <initializer_list>
|
||||
#ifdef KJ_STD_COMPAT
|
||||
#include <iterator>
|
||||
#endif // KJ_STD_COMPAT
|
||||
|
||||
namespace capnp {
|
||||
namespace _ { // private
|
||||
|
||||
template <typename T>
|
||||
class TemporaryPointer {
|
||||
// This class is a little hack which lets us define operator->() in cases where it needs to
|
||||
// return a pointer to a temporary value. We instead construct a TemporaryPointer and return that
|
||||
// (by value). The compiler then invokes operator->() on the TemporaryPointer, which itself is
|
||||
// able to return a real pointer to its member.
|
||||
|
||||
public:
|
||||
TemporaryPointer(T&& value): value(kj::mv(value)) {}
|
||||
TemporaryPointer(const T& value): value(value) {}
|
||||
|
||||
inline T* operator->() { return &value; }
|
||||
private:
|
||||
T value;
|
||||
};
|
||||
|
||||
template <typename Container, typename Element>
|
||||
class IndexingIterator {
|
||||
public:
|
||||
IndexingIterator() = default;
|
||||
|
||||
inline Element operator*() const { return (*container)[index]; }
|
||||
inline TemporaryPointer<Element> operator->() const {
|
||||
return TemporaryPointer<Element>((*container)[index]);
|
||||
}
|
||||
inline Element operator[]( int off) const { return (*container)[index]; }
|
||||
inline Element operator[](uint off) const { return (*container)[index]; }
|
||||
|
||||
inline IndexingIterator& operator++() { ++index; return *this; }
|
||||
inline IndexingIterator operator++(int) { IndexingIterator other = *this; ++index; return other; }
|
||||
inline IndexingIterator& operator--() { --index; return *this; }
|
||||
inline IndexingIterator operator--(int) { IndexingIterator other = *this; --index; return other; }
|
||||
|
||||
inline IndexingIterator operator+(uint amount) const { return IndexingIterator(container, index + amount); }
|
||||
inline IndexingIterator operator-(uint amount) const { return IndexingIterator(container, index - amount); }
|
||||
inline IndexingIterator operator+( int amount) const { return IndexingIterator(container, index + amount); }
|
||||
inline IndexingIterator operator-( int amount) const { return IndexingIterator(container, index - amount); }
|
||||
|
||||
inline int operator-(const IndexingIterator& other) const { return index - other.index; }
|
||||
|
||||
inline IndexingIterator& operator+=(uint amount) { index += amount; return *this; }
|
||||
inline IndexingIterator& operator-=(uint amount) { index -= amount; return *this; }
|
||||
inline IndexingIterator& operator+=( int amount) { index += amount; return *this; }
|
||||
inline IndexingIterator& operator-=( int amount) { index -= amount; return *this; }
|
||||
|
||||
// STL says comparing iterators of different containers is not allowed, so we only compare
|
||||
// indices here.
|
||||
inline bool operator==(const IndexingIterator& other) const { return index == other.index; }
|
||||
inline bool operator!=(const IndexingIterator& other) const { return index != other.index; }
|
||||
inline bool operator<=(const IndexingIterator& other) const { return index <= other.index; }
|
||||
inline bool operator>=(const IndexingIterator& other) const { return index >= other.index; }
|
||||
inline bool operator< (const IndexingIterator& other) const { return index < other.index; }
|
||||
inline bool operator> (const IndexingIterator& other) const { return index > other.index; }
|
||||
|
||||
private:
|
||||
Container* container;
|
||||
uint index;
|
||||
|
||||
friend Container;
|
||||
inline IndexingIterator(Container* container, uint index)
|
||||
: container(container), index(index) {}
|
||||
};
|
||||
|
||||
} // namespace _ (private)
|
||||
|
||||
template <typename T>
|
||||
struct List<T, Kind::PRIMITIVE> {
|
||||
// List of primitives.
|
||||
|
||||
List() = delete;
|
||||
|
||||
class Reader {
|
||||
public:
|
||||
typedef List<T> Reads;
|
||||
|
||||
inline Reader(): reader(_::elementSizeForType<T>()) {}
|
||||
inline explicit Reader(_::ListReader reader): reader(reader) {}
|
||||
|
||||
inline uint size() const { return unbound(reader.size() / ELEMENTS); }
|
||||
inline T operator[](uint index) const {
|
||||
KJ_IREQUIRE(index < size());
|
||||
return reader.template getDataElement<T>(bounded(index) * ELEMENTS);
|
||||
}
|
||||
|
||||
typedef _::IndexingIterator<const Reader, T> Iterator;
|
||||
inline Iterator begin() const { return Iterator(this, 0); }
|
||||
inline Iterator end() const { return Iterator(this, size()); }
|
||||
|
||||
private:
|
||||
_::ListReader reader;
|
||||
template <typename U, Kind K>
|
||||
friend struct _::PointerHelpers;
|
||||
template <typename U, Kind K>
|
||||
friend struct List;
|
||||
friend class Orphanage;
|
||||
template <typename U, Kind K>
|
||||
friend struct ToDynamic_;
|
||||
};
|
||||
|
||||
class Builder {
|
||||
public:
|
||||
typedef List<T> Builds;
|
||||
|
||||
inline Builder(): builder(_::elementSizeForType<T>()) {}
|
||||
inline Builder(decltype(nullptr)): Builder() {}
|
||||
inline explicit Builder(_::ListBuilder builder): builder(builder) {}
|
||||
|
||||
inline operator Reader() const { return Reader(builder.asReader()); }
|
||||
inline Reader asReader() const { return Reader(builder.asReader()); }
|
||||
|
||||
inline uint size() const { return unbound(builder.size() / ELEMENTS); }
|
||||
inline T operator[](uint index) {
|
||||
KJ_IREQUIRE(index < size());
|
||||
return builder.template getDataElement<T>(bounded(index) * ELEMENTS);
|
||||
}
|
||||
inline void set(uint index, T value) {
|
||||
// Alas, it is not possible to make operator[] return a reference to which you can assign,
|
||||
// since the encoded representation does not necessarily match the compiler's representation
|
||||
// of the type. We can't even return a clever class that implements operator T() and
|
||||
// operator=() because it will lead to surprising behavior when using type inference (e.g.
|
||||
// calling a template function with inferred argument types, or using "auto" or "decltype").
|
||||
|
||||
builder.template setDataElement<T>(bounded(index) * ELEMENTS, value);
|
||||
}
|
||||
|
||||
typedef _::IndexingIterator<Builder, T> Iterator;
|
||||
inline Iterator begin() { return Iterator(this, 0); }
|
||||
inline Iterator end() { return Iterator(this, size()); }
|
||||
|
||||
private:
|
||||
_::ListBuilder builder;
|
||||
template <typename U, Kind K>
|
||||
friend struct _::PointerHelpers;
|
||||
friend class Orphanage;
|
||||
template <typename U, Kind K>
|
||||
friend struct ToDynamic_;
|
||||
};
|
||||
|
||||
class Pipeline {};
|
||||
|
||||
private:
|
||||
inline static _::ListBuilder initPointer(_::PointerBuilder builder, uint size) {
|
||||
return builder.initList(_::elementSizeForType<T>(), bounded(size) * ELEMENTS);
|
||||
}
|
||||
inline static _::ListBuilder getFromPointer(_::PointerBuilder builder, const word* defaultValue) {
|
||||
return builder.getList(_::elementSizeForType<T>(), defaultValue);
|
||||
}
|
||||
inline static _::ListReader getFromPointer(
|
||||
const _::PointerReader& reader, const word* defaultValue) {
|
||||
return reader.getList(_::elementSizeForType<T>(), defaultValue);
|
||||
}
|
||||
|
||||
template <typename U, Kind k>
|
||||
friend struct List;
|
||||
template <typename U, Kind K>
|
||||
friend struct _::PointerHelpers;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct List<T, Kind::ENUM>: public List<T, Kind::PRIMITIVE> {};
|
||||
|
||||
template <typename T>
|
||||
struct List<T, Kind::STRUCT> {
|
||||
// List of structs.
|
||||
|
||||
List() = delete;
|
||||
|
||||
class Reader {
|
||||
public:
|
||||
typedef List<T> Reads;
|
||||
|
||||
inline Reader(): reader(ElementSize::INLINE_COMPOSITE) {}
|
||||
inline explicit Reader(_::ListReader reader): reader(reader) {}
|
||||
|
||||
inline uint size() const { return unbound(reader.size() / ELEMENTS); }
|
||||
inline typename T::Reader operator[](uint index) const {
|
||||
KJ_IREQUIRE(index < size());
|
||||
return typename T::Reader(reader.getStructElement(bounded(index) * ELEMENTS));
|
||||
}
|
||||
|
||||
typedef _::IndexingIterator<const Reader, typename T::Reader> Iterator;
|
||||
inline Iterator begin() const { return Iterator(this, 0); }
|
||||
inline Iterator end() const { return Iterator(this, size()); }
|
||||
|
||||
private:
|
||||
_::ListReader reader;
|
||||
template <typename U, Kind K>
|
||||
friend struct _::PointerHelpers;
|
||||
template <typename U, Kind K>
|
||||
friend struct List;
|
||||
friend class Orphanage;
|
||||
template <typename U, Kind K>
|
||||
friend struct ToDynamic_;
|
||||
};
|
||||
|
||||
class Builder {
|
||||
public:
|
||||
typedef List<T> Builds;
|
||||
|
||||
inline Builder(): builder(ElementSize::INLINE_COMPOSITE) {}
|
||||
inline Builder(decltype(nullptr)): Builder() {}
|
||||
inline explicit Builder(_::ListBuilder builder): builder(builder) {}
|
||||
|
||||
inline operator Reader() const { return Reader(builder.asReader()); }
|
||||
inline Reader asReader() const { return Reader(builder.asReader()); }
|
||||
|
||||
inline uint size() const { return unbound(builder.size() / ELEMENTS); }
|
||||
inline typename T::Builder operator[](uint index) {
|
||||
KJ_IREQUIRE(index < size());
|
||||
return typename T::Builder(builder.getStructElement(bounded(index) * ELEMENTS));
|
||||
}
|
||||
|
||||
inline void adoptWithCaveats(uint index, Orphan<T>&& orphan) {
|
||||
// Mostly behaves like you'd expect `adopt` to behave, but with two caveats originating from
|
||||
// the fact that structs in a struct list are allocated inline rather than by pointer:
|
||||
// * This actually performs a shallow copy, effectively adopting each of the orphan's
|
||||
// children rather than adopting the orphan itself. The orphan ends up being discarded,
|
||||
// possibly wasting space in the message object.
|
||||
// * If the orphan is larger than the target struct -- say, because the orphan was built
|
||||
// using a newer version of the schema that has additional fields -- it will be truncated,
|
||||
// losing data.
|
||||
|
||||
KJ_IREQUIRE(index < size());
|
||||
|
||||
// We pass a zero-valued StructSize to asStruct() because we do not want the struct to be
|
||||
// expanded under any circumstances. We're just going to throw it away anyway, and
|
||||
// transferContentFrom() already carefully compares the struct sizes before transferring.
|
||||
builder.getStructElement(bounded(index) * ELEMENTS).transferContentFrom(
|
||||
orphan.builder.asStruct(_::StructSize(ZERO * WORDS, ZERO * POINTERS)));
|
||||
}
|
||||
inline void setWithCaveats(uint index, const typename T::Reader& reader) {
|
||||
// Mostly behaves like you'd expect `set` to behave, but with a caveat originating from
|
||||
// the fact that structs in a struct list are allocated inline rather than by pointer:
|
||||
// If the source struct is larger than the target struct -- say, because the source was built
|
||||
// using a newer version of the schema that has additional fields -- it will be truncated,
|
||||
// losing data.
|
||||
//
|
||||
// Note: If you are trying to concatenate some lists, use Orphanage::newOrphanConcat() to
|
||||
// do it without losing any data in case the source lists come from a newer version of the
|
||||
// protocol. (Plus, it's easier to use anyhow.)
|
||||
|
||||
KJ_IREQUIRE(index < size());
|
||||
builder.getStructElement(bounded(index) * ELEMENTS).copyContentFrom(reader._reader);
|
||||
}
|
||||
|
||||
// There are no init(), set(), adopt(), or disown() methods for lists of structs because the
|
||||
// elements of the list are inlined and are initialized when the list is initialized. This
|
||||
// means that init() would be redundant, and set() would risk data loss if the input struct
|
||||
// were from a newer version of the protocol.
|
||||
|
||||
typedef _::IndexingIterator<Builder, typename T::Builder> Iterator;
|
||||
inline Iterator begin() { return Iterator(this, 0); }
|
||||
inline Iterator end() { return Iterator(this, size()); }
|
||||
|
||||
private:
|
||||
_::ListBuilder builder;
|
||||
template <typename U, Kind K>
|
||||
friend struct _::PointerHelpers;
|
||||
friend class Orphanage;
|
||||
template <typename U, Kind K>
|
||||
friend struct ToDynamic_;
|
||||
};
|
||||
|
||||
class Pipeline {};
|
||||
|
||||
private:
|
||||
inline static _::ListBuilder initPointer(_::PointerBuilder builder, uint size) {
|
||||
return builder.initStructList(bounded(size) * ELEMENTS, _::structSize<T>());
|
||||
}
|
||||
inline static _::ListBuilder getFromPointer(_::PointerBuilder builder, const word* defaultValue) {
|
||||
return builder.getStructList(_::structSize<T>(), defaultValue);
|
||||
}
|
||||
inline static _::ListReader getFromPointer(
|
||||
const _::PointerReader& reader, const word* defaultValue) {
|
||||
return reader.getList(ElementSize::INLINE_COMPOSITE, defaultValue);
|
||||
}
|
||||
|
||||
template <typename U, Kind k>
|
||||
friend struct List;
|
||||
template <typename U, Kind K>
|
||||
friend struct _::PointerHelpers;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct List<List<T>, Kind::LIST> {
|
||||
// List of lists.
|
||||
|
||||
List() = delete;
|
||||
|
||||
class Reader {
|
||||
public:
|
||||
typedef List<List<T>> Reads;
|
||||
|
||||
inline Reader(): reader(ElementSize::POINTER) {}
|
||||
inline explicit Reader(_::ListReader reader): reader(reader) {}
|
||||
|
||||
inline uint size() const { return unbound(reader.size() / ELEMENTS); }
|
||||
inline typename List<T>::Reader operator[](uint index) const {
|
||||
KJ_IREQUIRE(index < size());
|
||||
return typename List<T>::Reader(_::PointerHelpers<List<T>>::get(
|
||||
reader.getPointerElement(bounded(index) * ELEMENTS)));
|
||||
}
|
||||
|
||||
typedef _::IndexingIterator<const Reader, typename List<T>::Reader> Iterator;
|
||||
inline Iterator begin() const { return Iterator(this, 0); }
|
||||
inline Iterator end() const { return Iterator(this, size()); }
|
||||
|
||||
private:
|
||||
_::ListReader reader;
|
||||
template <typename U, Kind K>
|
||||
friend struct _::PointerHelpers;
|
||||
template <typename U, Kind K>
|
||||
friend struct List;
|
||||
friend class Orphanage;
|
||||
template <typename U, Kind K>
|
||||
friend struct ToDynamic_;
|
||||
};
|
||||
|
||||
class Builder {
|
||||
public:
|
||||
typedef List<List<T>> Builds;
|
||||
|
||||
inline Builder(): builder(ElementSize::POINTER) {}
|
||||
inline Builder(decltype(nullptr)): Builder() {}
|
||||
inline explicit Builder(_::ListBuilder builder): builder(builder) {}
|
||||
|
||||
inline operator Reader() const { return Reader(builder.asReader()); }
|
||||
inline Reader asReader() const { return Reader(builder.asReader()); }
|
||||
|
||||
inline uint size() const { return unbound(builder.size() / ELEMENTS); }
|
||||
inline typename List<T>::Builder operator[](uint index) {
|
||||
KJ_IREQUIRE(index < size());
|
||||
return typename List<T>::Builder(_::PointerHelpers<List<T>>::get(
|
||||
builder.getPointerElement(bounded(index) * ELEMENTS)));
|
||||
}
|
||||
inline typename List<T>::Builder init(uint index, uint size) {
|
||||
KJ_IREQUIRE(index < this->size());
|
||||
return typename List<T>::Builder(_::PointerHelpers<List<T>>::init(
|
||||
builder.getPointerElement(bounded(index) * ELEMENTS), size));
|
||||
}
|
||||
inline void set(uint index, typename List<T>::Reader value) {
|
||||
KJ_IREQUIRE(index < size());
|
||||
builder.getPointerElement(bounded(index) * ELEMENTS).setList(value.reader);
|
||||
}
|
||||
void set(uint index, std::initializer_list<ReaderFor<T>> value) {
|
||||
KJ_IREQUIRE(index < size());
|
||||
auto l = init(index, value.size());
|
||||
uint i = 0;
|
||||
for (auto& element: value) {
|
||||
l.set(i++, element);
|
||||
}
|
||||
}
|
||||
inline void adopt(uint index, Orphan<T>&& value) {
|
||||
KJ_IREQUIRE(index < size());
|
||||
builder.getPointerElement(bounded(index) * ELEMENTS).adopt(kj::mv(value.builder));
|
||||
}
|
||||
inline Orphan<T> disown(uint index) {
|
||||
KJ_IREQUIRE(index < size());
|
||||
return Orphan<T>(builder.getPointerElement(bounded(index) * ELEMENTS).disown());
|
||||
}
|
||||
|
||||
typedef _::IndexingIterator<Builder, typename List<T>::Builder> Iterator;
|
||||
inline Iterator begin() { return Iterator(this, 0); }
|
||||
inline Iterator end() { return Iterator(this, size()); }
|
||||
|
||||
private:
|
||||
_::ListBuilder builder;
|
||||
template <typename U, Kind K>
|
||||
friend struct _::PointerHelpers;
|
||||
friend class Orphanage;
|
||||
template <typename U, Kind K>
|
||||
friend struct ToDynamic_;
|
||||
};
|
||||
|
||||
class Pipeline {};
|
||||
|
||||
private:
|
||||
inline static _::ListBuilder initPointer(_::PointerBuilder builder, uint size) {
|
||||
return builder.initList(ElementSize::POINTER, bounded(size) * ELEMENTS);
|
||||
}
|
||||
inline static _::ListBuilder getFromPointer(_::PointerBuilder builder, const word* defaultValue) {
|
||||
return builder.getList(ElementSize::POINTER, defaultValue);
|
||||
}
|
||||
inline static _::ListReader getFromPointer(
|
||||
const _::PointerReader& reader, const word* defaultValue) {
|
||||
return reader.getList(ElementSize::POINTER, defaultValue);
|
||||
}
|
||||
|
||||
template <typename U, Kind k>
|
||||
friend struct List;
|
||||
template <typename U, Kind K>
|
||||
friend struct _::PointerHelpers;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct List<T, Kind::BLOB> {
|
||||
List() = delete;
|
||||
|
||||
class Reader {
|
||||
public:
|
||||
typedef List<T> Reads;
|
||||
|
||||
inline Reader(): reader(ElementSize::POINTER) {}
|
||||
inline explicit Reader(_::ListReader reader): reader(reader) {}
|
||||
|
||||
inline uint size() const { return unbound(reader.size() / ELEMENTS); }
|
||||
inline typename T::Reader operator[](uint index) const {
|
||||
KJ_IREQUIRE(index < size());
|
||||
return reader.getPointerElement(bounded(index) * ELEMENTS)
|
||||
.template getBlob<T>(nullptr, ZERO * BYTES);
|
||||
}
|
||||
|
||||
typedef _::IndexingIterator<const Reader, typename T::Reader> Iterator;
|
||||
inline Iterator begin() const { return Iterator(this, 0); }
|
||||
inline Iterator end() const { return Iterator(this, size()); }
|
||||
|
||||
private:
|
||||
_::ListReader reader;
|
||||
template <typename U, Kind K>
|
||||
friend struct _::PointerHelpers;
|
||||
template <typename U, Kind K>
|
||||
friend struct List;
|
||||
friend class Orphanage;
|
||||
template <typename U, Kind K>
|
||||
friend struct ToDynamic_;
|
||||
};
|
||||
|
||||
class Builder {
|
||||
public:
|
||||
typedef List<T> Builds;
|
||||
|
||||
inline Builder(): builder(ElementSize::POINTER) {}
|
||||
inline Builder(decltype(nullptr)): Builder() {}
|
||||
inline explicit Builder(_::ListBuilder builder): builder(builder) {}
|
||||
|
||||
inline operator Reader() const { return Reader(builder.asReader()); }
|
||||
inline Reader asReader() const { return Reader(builder.asReader()); }
|
||||
|
||||
inline uint size() const { return unbound(builder.size() / ELEMENTS); }
|
||||
inline typename T::Builder operator[](uint index) {
|
||||
KJ_IREQUIRE(index < size());
|
||||
return builder.getPointerElement(bounded(index) * ELEMENTS)
|
||||
.template getBlob<T>(nullptr, ZERO * BYTES);
|
||||
}
|
||||
inline void set(uint index, typename T::Reader value) {
|
||||
KJ_IREQUIRE(index < size());
|
||||
builder.getPointerElement(bounded(index) * ELEMENTS).template setBlob<T>(value);
|
||||
}
|
||||
inline typename T::Builder init(uint index, uint size) {
|
||||
KJ_IREQUIRE(index < this->size());
|
||||
return builder.getPointerElement(bounded(index) * ELEMENTS)
|
||||
.template initBlob<T>(bounded(size) * BYTES);
|
||||
}
|
||||
inline void adopt(uint index, Orphan<T>&& value) {
|
||||
KJ_IREQUIRE(index < size());
|
||||
builder.getPointerElement(bounded(index) * ELEMENTS).adopt(kj::mv(value.builder));
|
||||
}
|
||||
inline Orphan<T> disown(uint index) {
|
||||
KJ_IREQUIRE(index < size());
|
||||
return Orphan<T>(builder.getPointerElement(bounded(index) * ELEMENTS).disown());
|
||||
}
|
||||
|
||||
typedef _::IndexingIterator<Builder, typename T::Builder> Iterator;
|
||||
inline Iterator begin() { return Iterator(this, 0); }
|
||||
inline Iterator end() { return Iterator(this, size()); }
|
||||
|
||||
private:
|
||||
_::ListBuilder builder;
|
||||
template <typename U, Kind K>
|
||||
friend struct _::PointerHelpers;
|
||||
friend class Orphanage;
|
||||
template <typename U, Kind K>
|
||||
friend struct ToDynamic_;
|
||||
};
|
||||
|
||||
class Pipeline {};
|
||||
|
||||
private:
|
||||
inline static _::ListBuilder initPointer(_::PointerBuilder builder, uint size) {
|
||||
return builder.initList(ElementSize::POINTER, bounded(size) * ELEMENTS);
|
||||
}
|
||||
inline static _::ListBuilder getFromPointer(_::PointerBuilder builder, const word* defaultValue) {
|
||||
return builder.getList(ElementSize::POINTER, defaultValue);
|
||||
}
|
||||
inline static _::ListReader getFromPointer(
|
||||
const _::PointerReader& reader, const word* defaultValue) {
|
||||
return reader.getList(ElementSize::POINTER, defaultValue);
|
||||
}
|
||||
|
||||
template <typename U, Kind k>
|
||||
friend struct List;
|
||||
template <typename U, Kind K>
|
||||
friend struct _::PointerHelpers;
|
||||
};
|
||||
|
||||
} // namespace capnp
|
||||
|
||||
#ifdef KJ_STD_COMPAT
|
||||
namespace std {
|
||||
|
||||
template <typename Container, typename Element>
|
||||
struct iterator_traits<capnp::_::IndexingIterator<Container, Element>>
|
||||
: public std::iterator<std::random_access_iterator_tag, Element, int> {};
|
||||
|
||||
} // namespace std
|
||||
#endif // KJ_STD_COMPAT
|
||||
|
||||
#endif // CAPNP_LIST_H_
|
||||
202
phonelibs/capnp-cpp/include/capnp/membrane.h
Normal file
202
phonelibs/capnp-cpp/include/capnp/membrane.h
Normal file
@@ -0,0 +1,202 @@
|
||||
// Copyright (c) 2015 Sandstorm Development Group, Inc. and contributors
|
||||
// Licensed under the MIT License:
|
||||
//
|
||||
// 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.
|
||||
|
||||
#ifndef CAPNP_MEMBRANE_H_
|
||||
#define CAPNP_MEMBRANE_H_
|
||||
// In capability theory, a "membrane" is a wrapper around a capability which (usually) forwards
|
||||
// calls but recursively wraps capabilities in those calls in the same membrane. The purpose of a
|
||||
// membrane is to enforce a barrier between two capabilities that cannot be bypassed by merely
|
||||
// introducing new objects.
|
||||
//
|
||||
// The most common use case for a membrane is revocation: Say Alice wants to give Bob a capability
|
||||
// to access Carol, but wants to be able to revoke this capability later. Alice can accomplish this
|
||||
// by wrapping Carol in a revokable wrapper which passes through calls until such a time as Alice
|
||||
// indicates it should be revoked, after which all calls through the wrapper will throw exceptions.
|
||||
// However, a naive wrapper approach has a problem: if Bob makes a call to Carol and sends a new
|
||||
// capability in that call, or if Carol returns a capability to Bob in the response to a call, then
|
||||
// the two are now able to communicate using this new capability, which Alice cannot revoke. In
|
||||
// order to avoid this problem, Alice must use not just a wrapper but a "membrane", which
|
||||
// recursively wraps all objects that pass through it in either direction. Thus, all connections
|
||||
// formed between Bob and Carol (originating from Alice's original introduction) can be revoked
|
||||
// together by revoking the membrane.
|
||||
//
|
||||
// Note that when a capability is passed into a membrane and then passed back out, the result is
|
||||
// the original capability, not a double-membraned capability. This means that in our revocation
|
||||
// example, if Bob uses his capability to Carol to obtain another capability from her, then send
|
||||
// it back to her, the capability Carol receives back will NOT be revoked when Bob's access to
|
||||
// Carol is revoked. Thus Bob can create long-term irrevocable connections. In most practical use
|
||||
// cases, this is what you want. APIs commonly rely on the fact that a capability obtained and then
|
||||
// passed back can be recognized as the original capability.
|
||||
//
|
||||
// Mark Miller on membranes: http://www.eros-os.org/pipermail/e-lang/2003-January/008434.html
|
||||
|
||||
#include "capability.h"
|
||||
|
||||
namespace capnp {
|
||||
|
||||
class MembranePolicy {
|
||||
// Applications may implement this interface to define a membrane policy, which allows some
|
||||
// calls crossing the membrane to be blocked or redirected.
|
||||
|
||||
public:
|
||||
virtual kj::Maybe<Capability::Client> inboundCall(
|
||||
uint64_t interfaceId, uint16_t methodId, Capability::Client target) = 0;
|
||||
// Given an inbound call (a call originating "outside" the membrane destined for an object
|
||||
// "inside" the membrane), decides what to do with it. The policy may:
|
||||
//
|
||||
// - Return null to indicate that the call should proceed to the destination. All capabilities
|
||||
// in the parameters or result will be properly wrapped in the same membrane.
|
||||
// - Return a capability to have the call redirected to that capability. Note that the redirect
|
||||
// capability will be treated as outside the membrane, so the params and results will not be
|
||||
// auto-wrapped; however, the callee can easily wrap the returned capability in the membrane
|
||||
// itself before returning to achieve this effect.
|
||||
// - Throw an exception to cause the call to fail with that exception.
|
||||
//
|
||||
// `target` is the underlying capability (*inside* the membrane) for which the call is destined.
|
||||
// Generally, the only way you should use `target` is to wrap it in some capability which you
|
||||
// return as a redirect. The redirect capability may modify the call in some way and send it to
|
||||
// `target`. Be careful to use `copyIntoMembrane()` and `copyOutOfMembrane()` as appropriate when
|
||||
// copying parameters or results across the membrane.
|
||||
//
|
||||
// Note that since `target` is inside the capability, if you were to directly return it (rather
|
||||
// than return null), the effect would be that the membrane would be broken: the call would
|
||||
// proceed directly and any new capabilities introduced through it would not be membraned. You
|
||||
// generally should not do that.
|
||||
|
||||
virtual kj::Maybe<Capability::Client> outboundCall(
|
||||
uint64_t interfaceId, uint16_t methodId, Capability::Client target) = 0;
|
||||
// Like `inboundCall()`, but applies to calls originating *inside* the membrane and terminating
|
||||
// outside.
|
||||
//
|
||||
// Note: It is strongly recommended that `outboundCall()` returns null in exactly the same cases
|
||||
// that `inboundCall()` return null. Conversely, for any case where `inboundCall()` would
|
||||
// redirect or throw, `outboundCall()` should also redirect or throw. Otherwise, you can run
|
||||
// into inconsistent behavion when a promise is returned across a membrane, and that promise
|
||||
// later resolves to a capability on the other side of the membrane: calls on the promise
|
||||
// will enter and then exit the membrane, but calls on the eventual resolution will not cross
|
||||
// the membrane at all, so it is important that these two cases behave the same.
|
||||
|
||||
virtual kj::Own<MembranePolicy> addRef() = 0;
|
||||
// Return a new owned pointer to the same policy.
|
||||
//
|
||||
// Typically an implementation of MembranePolicy should also inherit kj::Refcounted and implement
|
||||
// `addRef()` as `return kj::addRef(*this);`.
|
||||
//
|
||||
// Note that the membraning system considers two membranes created with the same MembranePolicy
|
||||
// object actually to be the *same* membrane. This is relevant when an object passes into the
|
||||
// membrane and then back out (or out and then back in): instead of double-wrapping the object,
|
||||
// the wrapping will be removed.
|
||||
};
|
||||
|
||||
Capability::Client membrane(Capability::Client inner, kj::Own<MembranePolicy> policy);
|
||||
// Wrap `inner` in a membrane specified by `policy`. `inner` is considered "inside" the membrane,
|
||||
// while the returned capability should only be called from outside the membrane.
|
||||
|
||||
Capability::Client reverseMembrane(Capability::Client outer, kj::Own<MembranePolicy> policy);
|
||||
// Like `membrane` but treat the input capability as "outside" the membrane, and return a
|
||||
// capability appropriate for use inside.
|
||||
//
|
||||
// Applications typically won't use this directly; the membraning code automatically sets up
|
||||
// reverse membranes where needed.
|
||||
|
||||
template <typename ClientType>
|
||||
ClientType membrane(ClientType inner, kj::Own<MembranePolicy> policy);
|
||||
template <typename ClientType>
|
||||
ClientType reverseMembrane(ClientType inner, kj::Own<MembranePolicy> policy);
|
||||
// Convenience templates which return the same interface type as the input.
|
||||
|
||||
template <typename ServerType>
|
||||
typename ServerType::Serves::Client membrane(
|
||||
kj::Own<ServerType> inner, kj::Own<MembranePolicy> policy);
|
||||
template <typename ServerType>
|
||||
typename ServerType::Serves::Client reverseMembrane(
|
||||
kj::Own<ServerType> inner, kj::Own<MembranePolicy> policy);
|
||||
// Convenience templates which input a capability server type and return the appropriate client
|
||||
// type.
|
||||
|
||||
template <typename Reader>
|
||||
Orphan<typename kj::Decay<Reader>::Reads> copyIntoMembrane(
|
||||
Reader&& from, Orphanage to, kj::Own<MembranePolicy> policy);
|
||||
// Copy a Cap'n Proto object (e.g. struct or list), adding the given membrane to any capabilities
|
||||
// found within it. `from` is interpreted as "outside" the membrane while `to` is "inside".
|
||||
|
||||
template <typename Reader>
|
||||
Orphan<typename kj::Decay<Reader>::Reads> copyOutOfMembrane(
|
||||
Reader&& from, Orphanage to, kj::Own<MembranePolicy> policy);
|
||||
// Like copyIntoMembrane() except that `from` is "inside" the membrane and `to` is "outside".
|
||||
|
||||
// =======================================================================================
|
||||
// inline implementation details
|
||||
|
||||
template <typename ClientType>
|
||||
ClientType membrane(ClientType inner, kj::Own<MembranePolicy> policy) {
|
||||
return membrane(Capability::Client(kj::mv(inner)), kj::mv(policy))
|
||||
.castAs<typename ClientType::Calls>();
|
||||
}
|
||||
template <typename ClientType>
|
||||
ClientType reverseMembrane(ClientType inner, kj::Own<MembranePolicy> policy) {
|
||||
return reverseMembrane(Capability::Client(kj::mv(inner)), kj::mv(policy))
|
||||
.castAs<typename ClientType::Calls>();
|
||||
}
|
||||
|
||||
template <typename ServerType>
|
||||
typename ServerType::Serves::Client membrane(
|
||||
kj::Own<ServerType> inner, kj::Own<MembranePolicy> policy) {
|
||||
return membrane(Capability::Client(kj::mv(inner)), kj::mv(policy))
|
||||
.castAs<typename ServerType::Serves>();
|
||||
}
|
||||
template <typename ServerType>
|
||||
typename ServerType::Serves::Client reverseMembrane(
|
||||
kj::Own<ServerType> inner, kj::Own<MembranePolicy> policy) {
|
||||
return reverseMembrane(Capability::Client(kj::mv(inner)), kj::mv(policy))
|
||||
.castAs<typename ServerType::Serves>();
|
||||
}
|
||||
|
||||
namespace _ { // private
|
||||
|
||||
OrphanBuilder copyOutOfMembrane(PointerReader from, Orphanage to,
|
||||
kj::Own<MembranePolicy> policy, bool reverse);
|
||||
OrphanBuilder copyOutOfMembrane(StructReader from, Orphanage to,
|
||||
kj::Own<MembranePolicy> policy, bool reverse);
|
||||
OrphanBuilder copyOutOfMembrane(ListReader from, Orphanage to,
|
||||
kj::Own<MembranePolicy> policy, bool reverse);
|
||||
|
||||
} // namespace _ (private)
|
||||
|
||||
template <typename Reader>
|
||||
Orphan<typename kj::Decay<Reader>::Reads> copyIntoMembrane(
|
||||
Reader&& from, Orphanage to, kj::Own<MembranePolicy> policy) {
|
||||
return _::copyOutOfMembrane(
|
||||
_::PointerHelpers<typename kj::Decay<Reader>::Reads>::getInternalReader(from),
|
||||
to, kj::mv(policy), true);
|
||||
}
|
||||
|
||||
template <typename Reader>
|
||||
Orphan<typename kj::Decay<Reader>::Reads> copyOutOfMembrane(
|
||||
Reader&& from, Orphanage to, kj::Own<MembranePolicy> policy) {
|
||||
return _::copyOutOfMembrane(
|
||||
_::PointerHelpers<typename kj::Decay<Reader>::Reads>::getInternalReader(from),
|
||||
to, kj::mv(policy), false);
|
||||
}
|
||||
|
||||
} // namespace capnp
|
||||
|
||||
#endif // CAPNP_MEMBRANE_H_
|
||||
508
phonelibs/capnp-cpp/include/capnp/message.h
Normal file
508
phonelibs/capnp-cpp/include/capnp/message.h
Normal file
@@ -0,0 +1,508 @@
|
||||
// Copyright (c) 2013-2016 Sandstorm Development Group, Inc. and contributors
|
||||
// Licensed under the MIT License:
|
||||
//
|
||||
// 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.
|
||||
|
||||
#include <kj/common.h>
|
||||
#include <kj/memory.h>
|
||||
#include <kj/mutex.h>
|
||||
#include <kj/debug.h>
|
||||
#include "common.h"
|
||||
#include "layout.h"
|
||||
#include "any.h"
|
||||
|
||||
#ifndef CAPNP_MESSAGE_H_
|
||||
#define CAPNP_MESSAGE_H_
|
||||
|
||||
#if defined(__GNUC__) && !defined(CAPNP_HEADER_WARNINGS)
|
||||
#pragma GCC system_header
|
||||
#endif
|
||||
|
||||
namespace capnp {
|
||||
|
||||
namespace _ { // private
|
||||
class ReaderArena;
|
||||
class BuilderArena;
|
||||
}
|
||||
|
||||
class StructSchema;
|
||||
class Orphanage;
|
||||
template <typename T>
|
||||
class Orphan;
|
||||
|
||||
// =======================================================================================
|
||||
|
||||
struct ReaderOptions {
|
||||
// Options controlling how data is read.
|
||||
|
||||
uint64_t traversalLimitInWords = 8 * 1024 * 1024;
|
||||
// Limits how many total words of data are allowed to be traversed. Traversal is counted when
|
||||
// a new struct or list builder is obtained, e.g. from a get() accessor. This means that calling
|
||||
// the getter for the same sub-struct multiple times will cause it to be double-counted. Once
|
||||
// the traversal limit is reached, an error will be reported.
|
||||
//
|
||||
// This limit exists for security reasons. It is possible for an attacker to construct a message
|
||||
// in which multiple pointers point at the same location. This is technically invalid, but hard
|
||||
// to detect. Using such a message, an attacker could cause a message which is small on the wire
|
||||
// to appear much larger when actually traversed, possibly exhausting server resources leading to
|
||||
// denial-of-service.
|
||||
//
|
||||
// It makes sense to set a traversal limit that is much larger than the underlying message.
|
||||
// Together with sensible coding practices (e.g. trying to avoid calling sub-object getters
|
||||
// multiple times, which is expensive anyway), this should provide adequate protection without
|
||||
// inconvenience.
|
||||
//
|
||||
// The default limit is 64 MiB. This may or may not be a sensible number for any given use case,
|
||||
// but probably at least prevents easy exploitation while also avoiding causing problems in most
|
||||
// typical cases.
|
||||
|
||||
int nestingLimit = 64;
|
||||
// Limits how deeply-nested a message structure can be, e.g. structs containing other structs or
|
||||
// lists of structs.
|
||||
//
|
||||
// Like the traversal limit, this limit exists for security reasons. Since it is common to use
|
||||
// recursive code to traverse recursive data structures, an attacker could easily cause a stack
|
||||
// overflow by sending a very-deeply-nested (or even cyclic) message, without the message even
|
||||
// being very large. The default limit of 64 is probably low enough to prevent any chance of
|
||||
// stack overflow, yet high enough that it is never a problem in practice.
|
||||
};
|
||||
|
||||
class MessageReader {
|
||||
// Abstract interface for an object used to read a Cap'n Proto message. Subclasses of
|
||||
// MessageReader are responsible for reading the raw, flat message content. Callers should
|
||||
// usually call `messageReader.getRoot<MyStructType>()` to get a `MyStructType::Reader`
|
||||
// representing the root of the message, then use that to traverse the message content.
|
||||
//
|
||||
// Some common subclasses of `MessageReader` include `SegmentArrayMessageReader`, whose
|
||||
// constructor accepts pointers to the raw data, and `StreamFdMessageReader` (from
|
||||
// `serialize.h`), which reads the message from a file descriptor. One might implement other
|
||||
// subclasses to handle things like reading from shared memory segments, mmap()ed files, etc.
|
||||
|
||||
public:
|
||||
MessageReader(ReaderOptions options);
|
||||
// It is suggested that subclasses take ReaderOptions as a constructor parameter, but give it a
|
||||
// default value of "ReaderOptions()". The base class constructor doesn't have a default value
|
||||
// in order to remind subclasses that they really need to give the user a way to provide this.
|
||||
|
||||
virtual ~MessageReader() noexcept(false);
|
||||
|
||||
virtual kj::ArrayPtr<const word> getSegment(uint id) = 0;
|
||||
// Gets the segment with the given ID, or returns null if no such segment exists. This method
|
||||
// will be called at most once for each segment ID.
|
||||
|
||||
inline const ReaderOptions& getOptions();
|
||||
// Get the options passed to the constructor.
|
||||
|
||||
template <typename RootType>
|
||||
typename RootType::Reader getRoot();
|
||||
// Get the root struct of the message, interpreting it as the given struct type.
|
||||
|
||||
template <typename RootType, typename SchemaType>
|
||||
typename RootType::Reader getRoot(SchemaType schema);
|
||||
// Dynamically interpret the root struct of the message using the given schema (a StructSchema).
|
||||
// RootType in this case must be DynamicStruct, and you must #include <capnp/dynamic.h> to
|
||||
// use this.
|
||||
|
||||
bool isCanonical();
|
||||
// Returns whether the message encoded in the reader is in canonical form.
|
||||
|
||||
private:
|
||||
ReaderOptions options;
|
||||
|
||||
// Space in which we can construct a ReaderArena. We don't use ReaderArena directly here
|
||||
// because we don't want clients to have to #include arena.h, which itself includes a bunch of
|
||||
// big STL headers. We don't use a pointer to a ReaderArena because that would require an
|
||||
// extra malloc on every message which could be expensive when processing small messages.
|
||||
void* arenaSpace[15 + sizeof(kj::MutexGuarded<void*>) / sizeof(void*)];
|
||||
bool allocatedArena;
|
||||
|
||||
_::ReaderArena* arena() { return reinterpret_cast<_::ReaderArena*>(arenaSpace); }
|
||||
AnyPointer::Reader getRootInternal();
|
||||
};
|
||||
|
||||
class MessageBuilder {
|
||||
// Abstract interface for an object used to allocate and build a message. Subclasses of
|
||||
// MessageBuilder are responsible for allocating the space in which the message will be written.
|
||||
// The most common subclass is `MallocMessageBuilder`, but other subclasses may be used to do
|
||||
// tricky things like allocate messages in shared memory or mmap()ed files.
|
||||
//
|
||||
// Creating a new message ususually means allocating a new MessageBuilder (ideally on the stack)
|
||||
// and then calling `messageBuilder.initRoot<MyStructType>()` to get a `MyStructType::Builder`.
|
||||
// That, in turn, can be used to fill in the message content. When done, you can call
|
||||
// `messageBuilder.getSegmentsForOutput()` to get a list of flat data arrays containing the
|
||||
// message.
|
||||
|
||||
public:
|
||||
MessageBuilder();
|
||||
virtual ~MessageBuilder() noexcept(false);
|
||||
KJ_DISALLOW_COPY(MessageBuilder);
|
||||
|
||||
struct SegmentInit {
|
||||
kj::ArrayPtr<word> space;
|
||||
|
||||
size_t wordsUsed;
|
||||
// Number of words in `space` which are used; the rest are free space in which additional
|
||||
// objects may be allocated.
|
||||
};
|
||||
|
||||
explicit MessageBuilder(kj::ArrayPtr<SegmentInit> segments);
|
||||
// Create a MessageBuilder backed by existing memory. This is an advanced interface that most
|
||||
// people should not use. THIS METHOD IS INSECURE; see below.
|
||||
//
|
||||
// This allows a MessageBuilder to be constructed to modify an in-memory message without first
|
||||
// making a copy of the content. This is especially useful in conjunction with mmap().
|
||||
//
|
||||
// The contents of each segment must outlive the MessageBuilder, but the SegmentInit array itself
|
||||
// only need outlive the constructor.
|
||||
//
|
||||
// SECURITY: Do not use this in conjunction with untrusted data. This constructor assumes that
|
||||
// the input message is valid. This constructor is designed to be used with data you control,
|
||||
// e.g. an mmap'd file which is owned and accessed by only one program. When reading data you
|
||||
// do not trust, you *must* load it into a Reader and then copy into a Builder as a means of
|
||||
// validating the content.
|
||||
//
|
||||
// WARNING: It is NOT safe to initialize a MessageBuilder in this way from memory that is
|
||||
// currently in use by another MessageBuilder or MessageReader. Other readers/builders will
|
||||
// not observe changes to the segment sizes nor newly-allocated segments caused by allocating
|
||||
// new objects in this message.
|
||||
|
||||
virtual kj::ArrayPtr<word> allocateSegment(uint minimumSize) = 0;
|
||||
// Allocates an array of at least the given number of words, throwing an exception or crashing if
|
||||
// this is not possible. It is expected that this method will usually return more space than
|
||||
// requested, and the caller should use that extra space as much as possible before allocating
|
||||
// more. The returned space remains valid at least until the MessageBuilder is destroyed.
|
||||
//
|
||||
// Cap'n Proto will only call this once at a time, so the subclass need not worry about
|
||||
// thread-safety.
|
||||
|
||||
template <typename RootType>
|
||||
typename RootType::Builder initRoot();
|
||||
// Initialize the root struct of the message as the given struct type.
|
||||
|
||||
template <typename Reader>
|
||||
void setRoot(Reader&& value);
|
||||
// Set the root struct to a deep copy of the given struct.
|
||||
|
||||
template <typename RootType>
|
||||
typename RootType::Builder getRoot();
|
||||
// Get the root struct of the message, interpreting it as the given struct type.
|
||||
|
||||
template <typename RootType, typename SchemaType>
|
||||
typename RootType::Builder getRoot(SchemaType schema);
|
||||
// Dynamically interpret the root struct of the message using the given schema (a StructSchema).
|
||||
// RootType in this case must be DynamicStruct, and you must #include <capnp/dynamic.h> to
|
||||
// use this.
|
||||
|
||||
template <typename RootType, typename SchemaType>
|
||||
typename RootType::Builder initRoot(SchemaType schema);
|
||||
// Dynamically init the root struct of the message using the given schema (a StructSchema).
|
||||
// RootType in this case must be DynamicStruct, and you must #include <capnp/dynamic.h> to
|
||||
// use this.
|
||||
|
||||
template <typename T>
|
||||
void adoptRoot(Orphan<T>&& orphan);
|
||||
// Like setRoot() but adopts the orphan without copying.
|
||||
|
||||
kj::ArrayPtr<const kj::ArrayPtr<const word>> getSegmentsForOutput();
|
||||
// Get the raw data that makes up the message.
|
||||
|
||||
Orphanage getOrphanage();
|
||||
|
||||
bool isCanonical();
|
||||
// Check whether the message builder is in canonical form
|
||||
|
||||
private:
|
||||
void* arenaSpace[22];
|
||||
// Space in which we can construct a BuilderArena. We don't use BuilderArena directly here
|
||||
// because we don't want clients to have to #include arena.h, which itself includes a bunch of
|
||||
// big STL headers. We don't use a pointer to a BuilderArena because that would require an
|
||||
// extra malloc on every message which could be expensive when processing small messages.
|
||||
|
||||
bool allocatedArena = false;
|
||||
// We have to initialize the arena lazily because when we do so we want to allocate the root
|
||||
// pointer immediately, and this will allocate a segment, which requires a virtual function
|
||||
// call on the MessageBuilder. We can't do such a call in the constructor since the subclass
|
||||
// isn't constructed yet. This is kind of annoying because it means that getOrphanage() is
|
||||
// not thread-safe, but that shouldn't be a huge deal...
|
||||
|
||||
_::BuilderArena* arena() { return reinterpret_cast<_::BuilderArena*>(arenaSpace); }
|
||||
_::SegmentBuilder* getRootSegment();
|
||||
AnyPointer::Builder getRootInternal();
|
||||
};
|
||||
|
||||
template <typename RootType>
|
||||
typename RootType::Reader readMessageUnchecked(const word* data);
|
||||
// IF THE INPUT IS INVALID, THIS MAY CRASH, CORRUPT MEMORY, CREATE A SECURITY HOLE IN YOUR APP,
|
||||
// MURDER YOUR FIRST-BORN CHILD, AND/OR BRING ABOUT ETERNAL DAMNATION ON ALL OF HUMANITY. DO NOT
|
||||
// USE UNLESS YOU UNDERSTAND THE CONSEQUENCES.
|
||||
//
|
||||
// Given a pointer to a known-valid message located in a single contiguous memory segment,
|
||||
// returns a reader for that message. No bounds-checking will be done while traversing this
|
||||
// message. Use this only if you have already verified that all pointers are valid and in-bounds,
|
||||
// and there are no far pointers in the message.
|
||||
//
|
||||
// To create a message that can be passed to this function, build a message using a MallocAllocator
|
||||
// whose preferred segment size is larger than the message size. This guarantees that the message
|
||||
// will be allocated as a single segment, meaning getSegmentsForOutput() returns a single word
|
||||
// array. That word array is your message; you may pass a pointer to its first word into
|
||||
// readMessageUnchecked() to read the message.
|
||||
//
|
||||
// This can be particularly handy for embedding messages in generated code: you can
|
||||
// embed the raw bytes (using AlignedData) then make a Reader for it using this. This is the way
|
||||
// default values are embedded in code generated by the Cap'n Proto compiler. E.g., if you have
|
||||
// a message MyMessage, you can read its default value like so:
|
||||
// MyMessage::Reader reader = Message<MyMessage>::readMessageUnchecked(MyMessage::DEFAULT.words);
|
||||
//
|
||||
// To sanitize a message from an untrusted source such that it can be safely passed to
|
||||
// readMessageUnchecked(), use copyToUnchecked().
|
||||
|
||||
template <typename Reader>
|
||||
void copyToUnchecked(Reader&& reader, kj::ArrayPtr<word> uncheckedBuffer);
|
||||
// Copy the content of the given reader into the given buffer, such that it can safely be passed to
|
||||
// readMessageUnchecked(). The buffer's size must be exactly reader.totalSizeInWords() + 1,
|
||||
// otherwise an exception will be thrown. The buffer must be zero'd before calling.
|
||||
|
||||
template <typename RootType>
|
||||
typename RootType::Reader readDataStruct(kj::ArrayPtr<const word> data);
|
||||
// Interprets the given data as a single, data-only struct. Only primitive fields (booleans,
|
||||
// numbers, and enums) will be readable; all pointers will be null. This is useful if you want
|
||||
// to use Cap'n Proto as a language/platform-neutral way to pack some bits.
|
||||
//
|
||||
// The input is a word array rather than a byte array to enforce alignment. If you have a byte
|
||||
// array which you know is word-aligned (or if your platform supports unaligned reads and you don't
|
||||
// mind the performance penalty), then you can use `reinterpret_cast` to convert a byte array into
|
||||
// a word array:
|
||||
//
|
||||
// kj::arrayPtr(reinterpret_cast<const word*>(bytes.begin()),
|
||||
// reinterpret_cast<const word*>(bytes.end()))
|
||||
|
||||
template <typename BuilderType>
|
||||
typename kj::ArrayPtr<const word> writeDataStruct(BuilderType builder);
|
||||
// Given a struct builder, get the underlying data section as a word array, suitable for passing
|
||||
// to `readDataStruct()`.
|
||||
//
|
||||
// Note that you may call `.toBytes()` on the returned value to convert to `ArrayPtr<const byte>`.
|
||||
|
||||
template <typename Type>
|
||||
static typename Type::Reader defaultValue();
|
||||
// Get a default instance of the given struct or list type.
|
||||
//
|
||||
// TODO(cleanup): Find a better home for this function?
|
||||
|
||||
// =======================================================================================
|
||||
|
||||
class SegmentArrayMessageReader: public MessageReader {
|
||||
// A simple MessageReader that reads from an array of word arrays representing all segments.
|
||||
// In particular you can read directly from the output of MessageBuilder::getSegmentsForOutput()
|
||||
// (although it would probably make more sense to call builder.getRoot().asReader() in that case).
|
||||
|
||||
public:
|
||||
SegmentArrayMessageReader(kj::ArrayPtr<const kj::ArrayPtr<const word>> segments,
|
||||
ReaderOptions options = ReaderOptions());
|
||||
// Creates a message pointing at the given segment array, without taking ownership of the
|
||||
// segments. All arrays passed in must remain valid until the MessageReader is destroyed.
|
||||
|
||||
KJ_DISALLOW_COPY(SegmentArrayMessageReader);
|
||||
~SegmentArrayMessageReader() noexcept(false);
|
||||
|
||||
virtual kj::ArrayPtr<const word> getSegment(uint id) override;
|
||||
|
||||
private:
|
||||
kj::ArrayPtr<const kj::ArrayPtr<const word>> segments;
|
||||
};
|
||||
|
||||
enum class AllocationStrategy: uint8_t {
|
||||
FIXED_SIZE,
|
||||
// The builder will prefer to allocate the same amount of space for each segment with no
|
||||
// heuristic growth. It will still allocate larger segments when the preferred size is too small
|
||||
// for some single object. This mode is generally not recommended, but can be particularly useful
|
||||
// for testing in order to force a message to allocate a predictable number of segments. Note
|
||||
// that you can force every single object in the message to be located in a separate segment by
|
||||
// using this mode with firstSegmentWords = 0.
|
||||
|
||||
GROW_HEURISTICALLY
|
||||
// The builder will heuristically decide how much space to allocate for each segment. Each
|
||||
// allocated segment will be progressively larger than the previous segments on the assumption
|
||||
// that message sizes are exponentially distributed. The total number of segments that will be
|
||||
// allocated for a message of size n is O(log n).
|
||||
};
|
||||
|
||||
constexpr uint SUGGESTED_FIRST_SEGMENT_WORDS = 1024;
|
||||
constexpr AllocationStrategy SUGGESTED_ALLOCATION_STRATEGY = AllocationStrategy::GROW_HEURISTICALLY;
|
||||
|
||||
class MallocMessageBuilder: public MessageBuilder {
|
||||
// A simple MessageBuilder that uses malloc() (actually, calloc()) to allocate segments. This
|
||||
// implementation should be reasonable for any case that doesn't require writing the message to
|
||||
// a specific location in memory.
|
||||
|
||||
public:
|
||||
explicit MallocMessageBuilder(uint firstSegmentWords = SUGGESTED_FIRST_SEGMENT_WORDS,
|
||||
AllocationStrategy allocationStrategy = SUGGESTED_ALLOCATION_STRATEGY);
|
||||
// Creates a BuilderContext which allocates at least the given number of words for the first
|
||||
// segment, and then uses the given strategy to decide how much to allocate for subsequent
|
||||
// segments. When choosing a value for firstSegmentWords, consider that:
|
||||
// 1) Reading and writing messages gets slower when multiple segments are involved, so it's good
|
||||
// if most messages fit in a single segment.
|
||||
// 2) Unused bytes will not be written to the wire, so generally it is not a big deal to allocate
|
||||
// more space than you need. It only becomes problematic if you are allocating many messages
|
||||
// in parallel and thus use lots of memory, or if you allocate so much extra space that just
|
||||
// zeroing it out becomes a bottleneck.
|
||||
// The defaults have been chosen to be reasonable for most people, so don't change them unless you
|
||||
// have reason to believe you need to.
|
||||
|
||||
explicit MallocMessageBuilder(kj::ArrayPtr<word> firstSegment,
|
||||
AllocationStrategy allocationStrategy = SUGGESTED_ALLOCATION_STRATEGY);
|
||||
// This version always returns the given array for the first segment, and then proceeds with the
|
||||
// allocation strategy. This is useful for optimization when building lots of small messages in
|
||||
// a tight loop: you can reuse the space for the first segment.
|
||||
//
|
||||
// firstSegment MUST be zero-initialized. MallocMessageBuilder's destructor will write new zeros
|
||||
// over any space that was used so that it can be reused.
|
||||
|
||||
KJ_DISALLOW_COPY(MallocMessageBuilder);
|
||||
virtual ~MallocMessageBuilder() noexcept(false);
|
||||
|
||||
virtual kj::ArrayPtr<word> allocateSegment(uint minimumSize) override;
|
||||
|
||||
private:
|
||||
uint nextSize;
|
||||
AllocationStrategy allocationStrategy;
|
||||
|
||||
bool ownFirstSegment;
|
||||
bool returnedFirstSegment;
|
||||
|
||||
void* firstSegment;
|
||||
|
||||
struct MoreSegments;
|
||||
kj::Maybe<kj::Own<MoreSegments>> moreSegments;
|
||||
};
|
||||
|
||||
class FlatMessageBuilder: public MessageBuilder {
|
||||
// THIS IS NOT THE CLASS YOU'RE LOOKING FOR.
|
||||
//
|
||||
// If you want to write a message into already-existing scratch space, use `MallocMessageBuilder`
|
||||
// and pass the scratch space to its constructor. It will then only fall back to malloc() if
|
||||
// the scratch space is not large enough.
|
||||
//
|
||||
// Do NOT use this class unless you really know what you're doing. This class is problematic
|
||||
// because it requires advance knowledge of the size of your message, which is usually impossible
|
||||
// to determine without actually building the message. The class was created primarily to
|
||||
// implement `copyToUnchecked()`, which itself exists only to support other internal parts of
|
||||
// the Cap'n Proto implementation.
|
||||
|
||||
public:
|
||||
explicit FlatMessageBuilder(kj::ArrayPtr<word> array);
|
||||
KJ_DISALLOW_COPY(FlatMessageBuilder);
|
||||
virtual ~FlatMessageBuilder() noexcept(false);
|
||||
|
||||
void requireFilled();
|
||||
// Throws an exception if the flat array is not exactly full.
|
||||
|
||||
virtual kj::ArrayPtr<word> allocateSegment(uint minimumSize) override;
|
||||
|
||||
private:
|
||||
kj::ArrayPtr<word> array;
|
||||
bool allocated;
|
||||
};
|
||||
|
||||
// =======================================================================================
|
||||
// implementation details
|
||||
|
||||
inline const ReaderOptions& MessageReader::getOptions() {
|
||||
return options;
|
||||
}
|
||||
|
||||
template <typename RootType>
|
||||
inline typename RootType::Reader MessageReader::getRoot() {
|
||||
return getRootInternal().getAs<RootType>();
|
||||
}
|
||||
|
||||
template <typename RootType>
|
||||
inline typename RootType::Builder MessageBuilder::initRoot() {
|
||||
return getRootInternal().initAs<RootType>();
|
||||
}
|
||||
|
||||
template <typename Reader>
|
||||
inline void MessageBuilder::setRoot(Reader&& value) {
|
||||
getRootInternal().setAs<FromReader<Reader>>(value);
|
||||
}
|
||||
|
||||
template <typename RootType>
|
||||
inline typename RootType::Builder MessageBuilder::getRoot() {
|
||||
return getRootInternal().getAs<RootType>();
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void MessageBuilder::adoptRoot(Orphan<T>&& orphan) {
|
||||
return getRootInternal().adopt(kj::mv(orphan));
|
||||
}
|
||||
|
||||
template <typename RootType, typename SchemaType>
|
||||
typename RootType::Reader MessageReader::getRoot(SchemaType schema) {
|
||||
return getRootInternal().getAs<RootType>(schema);
|
||||
}
|
||||
|
||||
template <typename RootType, typename SchemaType>
|
||||
typename RootType::Builder MessageBuilder::getRoot(SchemaType schema) {
|
||||
return getRootInternal().getAs<RootType>(schema);
|
||||
}
|
||||
|
||||
template <typename RootType, typename SchemaType>
|
||||
typename RootType::Builder MessageBuilder::initRoot(SchemaType schema) {
|
||||
return getRootInternal().initAs<RootType>(schema);
|
||||
}
|
||||
|
||||
template <typename RootType>
|
||||
typename RootType::Reader readMessageUnchecked(const word* data) {
|
||||
return AnyPointer::Reader(_::PointerReader::getRootUnchecked(data)).getAs<RootType>();
|
||||
}
|
||||
|
||||
template <typename Reader>
|
||||
void copyToUnchecked(Reader&& reader, kj::ArrayPtr<word> uncheckedBuffer) {
|
||||
FlatMessageBuilder builder(uncheckedBuffer);
|
||||
builder.setRoot(kj::fwd<Reader>(reader));
|
||||
builder.requireFilled();
|
||||
}
|
||||
|
||||
template <typename RootType>
|
||||
typename RootType::Reader readDataStruct(kj::ArrayPtr<const word> data) {
|
||||
return typename RootType::Reader(_::StructReader(data));
|
||||
}
|
||||
|
||||
template <typename BuilderType>
|
||||
typename kj::ArrayPtr<const word> writeDataStruct(BuilderType builder) {
|
||||
auto bytes = _::PointerHelpers<FromBuilder<BuilderType>>::getInternalBuilder(kj::mv(builder))
|
||||
.getDataSectionAsBlob();
|
||||
return kj::arrayPtr(reinterpret_cast<word*>(bytes.begin()),
|
||||
reinterpret_cast<word*>(bytes.end()));
|
||||
}
|
||||
|
||||
template <typename Type>
|
||||
static typename Type::Reader defaultValue() {
|
||||
return typename Type::Reader(_::StructReader());
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
kj::Array<word> canonicalize(T&& reader) {
|
||||
return _::PointerHelpers<FromReader<T>>::getInternalReader(reader).canonicalize();
|
||||
}
|
||||
|
||||
} // namespace capnp
|
||||
|
||||
#endif // CAPNP_MESSAGE_H_
|
||||
440
phonelibs/capnp-cpp/include/capnp/orphan.h
Normal file
440
phonelibs/capnp-cpp/include/capnp/orphan.h
Normal file
@@ -0,0 +1,440 @@
|
||||
// Copyright (c) 2013-2014 Sandstorm Development Group, Inc. and contributors
|
||||
// Licensed under the MIT License:
|
||||
//
|
||||
// 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.
|
||||
|
||||
#ifndef CAPNP_ORPHAN_H_
|
||||
#define CAPNP_ORPHAN_H_
|
||||
|
||||
#if defined(__GNUC__) && !defined(CAPNP_HEADER_WARNINGS)
|
||||
#pragma GCC system_header
|
||||
#endif
|
||||
|
||||
#include "layout.h"
|
||||
|
||||
namespace capnp {
|
||||
|
||||
class StructSchema;
|
||||
class ListSchema;
|
||||
struct DynamicStruct;
|
||||
struct DynamicList;
|
||||
namespace _ { struct OrphanageInternal; }
|
||||
|
||||
template <typename T>
|
||||
class Orphan {
|
||||
// Represents an object which is allocated within some message builder but has no pointers
|
||||
// pointing at it. An Orphan can later be "adopted" by some other object as one of that object's
|
||||
// fields, without having to copy the orphan. For a field `foo` of pointer type, the generated
|
||||
// code will define builder methods `void adoptFoo(Orphan<T>)` and `Orphan<T> disownFoo()`.
|
||||
// Orphans can also be created independently of any parent using an Orphanage.
|
||||
//
|
||||
// `Orphan<T>` can be moved but not copied, like `Own<T>`, so that it is impossible for one
|
||||
// orphan to be adopted multiple times. If an orphan is destroyed without being adopted, its
|
||||
// contents are zero'd out (and possibly reused, if we ever implement the ability to reuse space
|
||||
// in a message arena).
|
||||
|
||||
public:
|
||||
Orphan() = default;
|
||||
KJ_DISALLOW_COPY(Orphan);
|
||||
Orphan(Orphan&&) = default;
|
||||
Orphan& operator=(Orphan&&) = default;
|
||||
inline Orphan(_::OrphanBuilder&& builder): builder(kj::mv(builder)) {}
|
||||
|
||||
inline BuilderFor<T> get();
|
||||
// Get the underlying builder. If the orphan is null, this will allocate and return a default
|
||||
// object rather than crash. This is done for security -- otherwise, you might enable a DoS
|
||||
// attack any time you disown a field and fail to check if it is null. In the case of structs,
|
||||
// this means that the orphan is no longer null after get() returns. In the case of lists,
|
||||
// no actual object is allocated since a simple empty ListBuilder can be returned.
|
||||
|
||||
inline ReaderFor<T> getReader() const;
|
||||
|
||||
inline bool operator==(decltype(nullptr)) const { return builder == nullptr; }
|
||||
inline bool operator!=(decltype(nullptr)) const { return builder != nullptr; }
|
||||
|
||||
inline void truncate(uint size);
|
||||
// Resize an object (which must be a list or a blob) to the given size.
|
||||
//
|
||||
// If the new size is less than the original, the remaining elements will be discarded. The
|
||||
// list is never moved in this case. If the list happens to be located at the end of its segment
|
||||
// (which is always true if the list was the last thing allocated), the removed memory will be
|
||||
// reclaimed (reducing the messag size), otherwise it is simply zeroed. The reclaiming behavior
|
||||
// is particularly useful for allocating buffer space when you aren't sure how much space you
|
||||
// actually need: you can pre-allocate, say, a 4k byte array, read() from a file into it, and
|
||||
// then truncate it back to the amount of space actually used.
|
||||
//
|
||||
// If the new size is greater than the original, the list is extended with default values. If
|
||||
// the list is the last object in its segment *and* there is enough space left in the segment to
|
||||
// extend it to cover the new values, then the list is extended in-place. Otherwise, it must be
|
||||
// moved to a new location, leaving a zero'd hole in the previous space that won't be filled.
|
||||
// This copy is shallow; sub-objects will simply be reparented, not copied.
|
||||
//
|
||||
// Any existing readers or builders pointing at the object are invalidated by this call (even if
|
||||
// it doesn't move). You must call `get()` or `getReader()` again to get the new, valid pointer.
|
||||
|
||||
private:
|
||||
_::OrphanBuilder builder;
|
||||
|
||||
template <typename, Kind>
|
||||
friend struct _::PointerHelpers;
|
||||
template <typename, Kind>
|
||||
friend struct List;
|
||||
template <typename U>
|
||||
friend class Orphan;
|
||||
friend class Orphanage;
|
||||
friend class MessageBuilder;
|
||||
};
|
||||
|
||||
class Orphanage: private kj::DisallowConstCopy {
|
||||
// Use to directly allocate Orphan objects, without having a parent object allocate and then
|
||||
// disown the object.
|
||||
|
||||
public:
|
||||
inline Orphanage(): arena(nullptr) {}
|
||||
|
||||
template <typename BuilderType>
|
||||
static Orphanage getForMessageContaining(BuilderType builder);
|
||||
// Construct an Orphanage that allocates within the message containing the given Builder. This
|
||||
// allows the constructed Orphans to be adopted by objects within said message.
|
||||
//
|
||||
// This constructor takes the builder rather than having the builder have a getOrphanage() method
|
||||
// because this is an advanced feature and we don't want to pollute the builder APIs with it.
|
||||
//
|
||||
// Note that if you have a direct pointer to the `MessageBuilder`, you can simply call its
|
||||
// `getOrphanage()` method.
|
||||
|
||||
template <typename RootType>
|
||||
Orphan<RootType> newOrphan() const;
|
||||
// Allocate a new orphaned struct.
|
||||
|
||||
template <typename RootType>
|
||||
Orphan<RootType> newOrphan(uint size) const;
|
||||
// Allocate a new orphaned list or blob.
|
||||
|
||||
Orphan<DynamicStruct> newOrphan(StructSchema schema) const;
|
||||
// Dynamically create an orphan struct with the given schema. You must
|
||||
// #include <capnp/dynamic.h> to use this.
|
||||
|
||||
Orphan<DynamicList> newOrphan(ListSchema schema, uint size) const;
|
||||
// Dynamically create an orphan list with the given schema. You must #include <capnp/dynamic.h>
|
||||
// to use this.
|
||||
|
||||
template <typename Reader>
|
||||
Orphan<FromReader<Reader>> newOrphanCopy(Reader copyFrom) const;
|
||||
// Allocate a new orphaned object (struct, list, or blob) and initialize it as a copy of the
|
||||
// given object.
|
||||
|
||||
template <typename T>
|
||||
Orphan<List<ListElementType<FromReader<T>>>> newOrphanConcat(kj::ArrayPtr<T> lists) const;
|
||||
template <typename T>
|
||||
Orphan<List<ListElementType<FromReader<T>>>> newOrphanConcat(kj::ArrayPtr<const T> lists) const;
|
||||
// Given an array of List readers, copy and concatenate the lists, creating a new Orphan.
|
||||
//
|
||||
// Note that compared to allocating the list yourself and using `setWithCaveats()` to set each
|
||||
// item, this method avoids the "caveats": the new list will be allocated with the element size
|
||||
// being the maximum of that from all the input lists. This is particularly important when
|
||||
// concatenating struct lists: if the lists were created using a newer version of the protocol
|
||||
// in which some new fields had been added to the struct, using `setWithCaveats()` would
|
||||
// truncate off those new fields.
|
||||
|
||||
Orphan<Data> referenceExternalData(Data::Reader data) const;
|
||||
// Creates an Orphan<Data> that points at an existing region of memory (e.g. from another message)
|
||||
// without copying it. There are some SEVERE restrictions on how this can be used:
|
||||
// - The memory must remain valid until the `MessageBuilder` is destroyed (even if the orphan is
|
||||
// abandoned).
|
||||
// - Because the data is const, you will not be allowed to obtain a `Data::Builder`
|
||||
// for this blob. Any call which would return such a builder will throw an exception. You
|
||||
// can, however, obtain a Reader, e.g. via orphan.getReader() or from a parent Reader (once
|
||||
// the orphan is adopted). It is your responsibility to make sure your code can deal with
|
||||
// these problems when using this optimization; if you can't, allocate a copy instead.
|
||||
// - `data.begin()` must be aligned to a machine word boundary (32-bit or 64-bit depending on
|
||||
// the CPU). Any pointer returned by malloc() as well as any data blob obtained from another
|
||||
// Cap'n Proto message satisfies this.
|
||||
// - If `data.size()` is not a multiple of 8, extra bytes past data.end() up until the next 8-byte
|
||||
// boundary will be visible in the raw message when it is written out. Thus, there must be no
|
||||
// secrets in these bytes. Data blobs obtained from other Cap'n Proto messages should be safe
|
||||
// as these bytes should be zero (unless the sender had the same problem).
|
||||
//
|
||||
// The array will actually become one of the message's segments. The data can thus be adopted
|
||||
// into the message tree without copying it. This is particularly useful when referencing very
|
||||
// large blobs, such as whole mmap'd files.
|
||||
|
||||
private:
|
||||
_::BuilderArena* arena;
|
||||
_::CapTableBuilder* capTable;
|
||||
|
||||
inline explicit Orphanage(_::BuilderArena* arena, _::CapTableBuilder* capTable)
|
||||
: arena(arena), capTable(capTable) {}
|
||||
|
||||
template <typename T, Kind = CAPNP_KIND(T)>
|
||||
struct GetInnerBuilder;
|
||||
template <typename T, Kind = CAPNP_KIND(T)>
|
||||
struct GetInnerReader;
|
||||
template <typename T>
|
||||
struct NewOrphanListImpl;
|
||||
|
||||
friend class MessageBuilder;
|
||||
friend struct _::OrphanageInternal;
|
||||
};
|
||||
|
||||
// =======================================================================================
|
||||
// Inline implementation details.
|
||||
|
||||
namespace _ { // private
|
||||
|
||||
template <typename T, Kind = CAPNP_KIND(T)>
|
||||
struct OrphanGetImpl;
|
||||
|
||||
template <typename T>
|
||||
struct OrphanGetImpl<T, Kind::PRIMITIVE> {
|
||||
static inline void truncateListOf(_::OrphanBuilder& builder, ElementCount size) {
|
||||
builder.truncate(size, _::elementSizeForType<T>());
|
||||
}
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct OrphanGetImpl<T, Kind::STRUCT> {
|
||||
static inline typename T::Builder apply(_::OrphanBuilder& builder) {
|
||||
return typename T::Builder(builder.asStruct(_::structSize<T>()));
|
||||
}
|
||||
static inline typename T::Reader applyReader(const _::OrphanBuilder& builder) {
|
||||
return typename T::Reader(builder.asStructReader(_::structSize<T>()));
|
||||
}
|
||||
static inline void truncateListOf(_::OrphanBuilder& builder, ElementCount size) {
|
||||
builder.truncate(size, _::structSize<T>());
|
||||
}
|
||||
};
|
||||
|
||||
#if !CAPNP_LITE
|
||||
template <typename T>
|
||||
struct OrphanGetImpl<T, Kind::INTERFACE> {
|
||||
static inline typename T::Client apply(_::OrphanBuilder& builder) {
|
||||
return typename T::Client(builder.asCapability());
|
||||
}
|
||||
static inline typename T::Client applyReader(const _::OrphanBuilder& builder) {
|
||||
return typename T::Client(builder.asCapability());
|
||||
}
|
||||
static inline void truncateListOf(_::OrphanBuilder& builder, ElementCount size) {
|
||||
builder.truncate(size, ElementSize::POINTER);
|
||||
}
|
||||
};
|
||||
#endif // !CAPNP_LITE
|
||||
|
||||
template <typename T, Kind k>
|
||||
struct OrphanGetImpl<List<T, k>, Kind::LIST> {
|
||||
static inline typename List<T>::Builder apply(_::OrphanBuilder& builder) {
|
||||
return typename List<T>::Builder(builder.asList(_::ElementSizeForType<T>::value));
|
||||
}
|
||||
static inline typename List<T>::Reader applyReader(const _::OrphanBuilder& builder) {
|
||||
return typename List<T>::Reader(builder.asListReader(_::ElementSizeForType<T>::value));
|
||||
}
|
||||
static inline void truncateListOf(_::OrphanBuilder& builder, ElementCount size) {
|
||||
builder.truncate(size, ElementSize::POINTER);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct OrphanGetImpl<List<T, Kind::STRUCT>, Kind::LIST> {
|
||||
static inline typename List<T>::Builder apply(_::OrphanBuilder& builder) {
|
||||
return typename List<T>::Builder(builder.asStructList(_::structSize<T>()));
|
||||
}
|
||||
static inline typename List<T>::Reader applyReader(const _::OrphanBuilder& builder) {
|
||||
return typename List<T>::Reader(builder.asListReader(_::ElementSizeForType<T>::value));
|
||||
}
|
||||
static inline void truncateListOf(_::OrphanBuilder& builder, ElementCount size) {
|
||||
builder.truncate(size, ElementSize::POINTER);
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct OrphanGetImpl<Text, Kind::BLOB> {
|
||||
static inline Text::Builder apply(_::OrphanBuilder& builder) {
|
||||
return Text::Builder(builder.asText());
|
||||
}
|
||||
static inline Text::Reader applyReader(const _::OrphanBuilder& builder) {
|
||||
return Text::Reader(builder.asTextReader());
|
||||
}
|
||||
static inline void truncateListOf(_::OrphanBuilder& builder, ElementCount size) {
|
||||
builder.truncate(size, ElementSize::POINTER);
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct OrphanGetImpl<Data, Kind::BLOB> {
|
||||
static inline Data::Builder apply(_::OrphanBuilder& builder) {
|
||||
return Data::Builder(builder.asData());
|
||||
}
|
||||
static inline Data::Reader applyReader(const _::OrphanBuilder& builder) {
|
||||
return Data::Reader(builder.asDataReader());
|
||||
}
|
||||
static inline void truncateListOf(_::OrphanBuilder& builder, ElementCount size) {
|
||||
builder.truncate(size, ElementSize::POINTER);
|
||||
}
|
||||
};
|
||||
|
||||
struct OrphanageInternal {
|
||||
static inline _::BuilderArena* getArena(Orphanage orphanage) { return orphanage.arena; }
|
||||
static inline _::CapTableBuilder* getCapTable(Orphanage orphanage) { return orphanage.capTable; }
|
||||
};
|
||||
|
||||
} // namespace _ (private)
|
||||
|
||||
template <typename T>
|
||||
inline BuilderFor<T> Orphan<T>::get() {
|
||||
return _::OrphanGetImpl<T>::apply(builder);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline ReaderFor<T> Orphan<T>::getReader() const {
|
||||
return _::OrphanGetImpl<T>::applyReader(builder);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline void Orphan<T>::truncate(uint size) {
|
||||
_::OrphanGetImpl<ListElementType<T>>::truncateListOf(builder, bounded(size) * ELEMENTS);
|
||||
}
|
||||
|
||||
template <>
|
||||
inline void Orphan<Text>::truncate(uint size) {
|
||||
builder.truncateText(bounded(size) * ELEMENTS);
|
||||
}
|
||||
|
||||
template <>
|
||||
inline void Orphan<Data>::truncate(uint size) {
|
||||
builder.truncate(bounded(size) * ELEMENTS, ElementSize::BYTE);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
struct Orphanage::GetInnerBuilder<T, Kind::STRUCT> {
|
||||
static inline _::StructBuilder apply(typename T::Builder& t) {
|
||||
return t._builder;
|
||||
}
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct Orphanage::GetInnerBuilder<T, Kind::LIST> {
|
||||
static inline _::ListBuilder apply(typename T::Builder& t) {
|
||||
return t.builder;
|
||||
}
|
||||
};
|
||||
|
||||
template <typename BuilderType>
|
||||
Orphanage Orphanage::getForMessageContaining(BuilderType builder) {
|
||||
auto inner = GetInnerBuilder<FromBuilder<BuilderType>>::apply(builder);
|
||||
return Orphanage(inner.getArena(), inner.getCapTable());
|
||||
}
|
||||
|
||||
template <typename RootType>
|
||||
Orphan<RootType> Orphanage::newOrphan() const {
|
||||
return Orphan<RootType>(_::OrphanBuilder::initStruct(arena, capTable, _::structSize<RootType>()));
|
||||
}
|
||||
|
||||
template <typename T, Kind k>
|
||||
struct Orphanage::NewOrphanListImpl<List<T, k>> {
|
||||
static inline _::OrphanBuilder apply(
|
||||
_::BuilderArena* arena, _::CapTableBuilder* capTable, uint size) {
|
||||
return _::OrphanBuilder::initList(
|
||||
arena, capTable, bounded(size) * ELEMENTS, _::ElementSizeForType<T>::value);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct Orphanage::NewOrphanListImpl<List<T, Kind::STRUCT>> {
|
||||
static inline _::OrphanBuilder apply(
|
||||
_::BuilderArena* arena, _::CapTableBuilder* capTable, uint size) {
|
||||
return _::OrphanBuilder::initStructList(
|
||||
arena, capTable, bounded(size) * ELEMENTS, _::structSize<T>());
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct Orphanage::NewOrphanListImpl<Text> {
|
||||
static inline _::OrphanBuilder apply(
|
||||
_::BuilderArena* arena, _::CapTableBuilder* capTable, uint size) {
|
||||
return _::OrphanBuilder::initText(arena, capTable, bounded(size) * BYTES);
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct Orphanage::NewOrphanListImpl<Data> {
|
||||
static inline _::OrphanBuilder apply(
|
||||
_::BuilderArena* arena, _::CapTableBuilder* capTable, uint size) {
|
||||
return _::OrphanBuilder::initData(arena, capTable, bounded(size) * BYTES);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename RootType>
|
||||
Orphan<RootType> Orphanage::newOrphan(uint size) const {
|
||||
return Orphan<RootType>(NewOrphanListImpl<RootType>::apply(arena, capTable, size));
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
struct Orphanage::GetInnerReader<T, Kind::STRUCT> {
|
||||
static inline _::StructReader apply(const typename T::Reader& t) {
|
||||
return t._reader;
|
||||
}
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct Orphanage::GetInnerReader<T, Kind::LIST> {
|
||||
static inline _::ListReader apply(const typename T::Reader& t) {
|
||||
return t.reader;
|
||||
}
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct Orphanage::GetInnerReader<T, Kind::BLOB> {
|
||||
static inline const typename T::Reader& apply(const typename T::Reader& t) {
|
||||
return t;
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Reader>
|
||||
inline Orphan<FromReader<Reader>> Orphanage::newOrphanCopy(Reader copyFrom) const {
|
||||
return Orphan<FromReader<Reader>>(_::OrphanBuilder::copy(
|
||||
arena, capTable, GetInnerReader<FromReader<Reader>>::apply(copyFrom)));
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline Orphan<List<ListElementType<FromReader<T>>>>
|
||||
Orphanage::newOrphanConcat(kj::ArrayPtr<T> lists) const {
|
||||
return newOrphanConcat(kj::implicitCast<kj::ArrayPtr<const T>>(lists));
|
||||
}
|
||||
template <typename T>
|
||||
inline Orphan<List<ListElementType<FromReader<T>>>>
|
||||
Orphanage::newOrphanConcat(kj::ArrayPtr<const T> lists) const {
|
||||
// Optimization / simplification: Rely on List<T>::Reader containing nothing except a
|
||||
// _::ListReader.
|
||||
static_assert(sizeof(T) == sizeof(_::ListReader), "lists are not bare readers?");
|
||||
kj::ArrayPtr<const _::ListReader> raw(
|
||||
reinterpret_cast<const _::ListReader*>(lists.begin()), lists.size());
|
||||
typedef ListElementType<FromReader<T>> Element;
|
||||
return Orphan<List<Element>>(
|
||||
_::OrphanBuilder::concat(arena, capTable,
|
||||
_::elementSizeForType<Element>(),
|
||||
_::minStructSizeForElement<Element>(), raw));
|
||||
}
|
||||
|
||||
inline Orphan<Data> Orphanage::referenceExternalData(Data::Reader data) const {
|
||||
return Orphan<Data>(_::OrphanBuilder::referenceExternalData(arena, data));
|
||||
}
|
||||
|
||||
} // namespace capnp
|
||||
|
||||
#endif // CAPNP_ORPHAN_H_
|
||||
139
phonelibs/capnp-cpp/include/capnp/persistent.capnp
Normal file
139
phonelibs/capnp-cpp/include/capnp/persistent.capnp
Normal file
@@ -0,0 +1,139 @@
|
||||
# Copyright (c) 2014 Sandstorm Development Group, Inc. and contributors
|
||||
# Licensed under the MIT License:
|
||||
#
|
||||
# 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.
|
||||
|
||||
@0xb8630836983feed7;
|
||||
|
||||
$import "/capnp/c++.capnp".namespace("capnp");
|
||||
|
||||
interface Persistent@0xc8cb212fcd9f5691(SturdyRef, Owner) {
|
||||
# Interface implemented by capabilities that outlive a single connection. A client may save()
|
||||
# the capability, producing a SturdyRef. The SturdyRef can be stored to disk, then later used to
|
||||
# obtain a new reference to the capability on a future connection.
|
||||
#
|
||||
# The exact format of SturdyRef depends on the "realm" in which the SturdyRef appears. A "realm"
|
||||
# is an abstract space in which all SturdyRefs have the same format and refer to the same set of
|
||||
# resources. Every vat is in exactly one realm. All capability clients within that vat must
|
||||
# produce SturdyRefs of the format appropriate for the realm.
|
||||
#
|
||||
# Similarly, every VatNetwork also resides in a particular realm. Usually, a vat's "realm"
|
||||
# corresponds to the realm of its main VatNetwork. However, a Vat can in fact communicate over
|
||||
# a VatNetwork in a different realm -- in this case, all SturdyRefs need to be transformed when
|
||||
# coming or going through said VatNetwork. The RPC system has hooks for registering
|
||||
# transformation callbacks for this purpose.
|
||||
#
|
||||
# Since the format of SturdyRef is realm-dependent, it is not defined here. An application should
|
||||
# choose an appropriate realm for itself as part of its design. Note that under Sandstorm, every
|
||||
# application exists in its own realm and is therefore free to define its own SturdyRef format;
|
||||
# the Sandstorm platform handles translating between realms.
|
||||
#
|
||||
# Note that whether a capability is persistent is often orthogonal to its type. In these cases,
|
||||
# the capability's interface should NOT inherit `Persistent`; instead, just perform a cast at
|
||||
# runtime. It's not type-safe, but trying to be type-safe in these cases will likely lead to
|
||||
# tears. In cases where a particular interface only makes sense on persistent capabilities, it
|
||||
# still should not explicitly inherit Persistent because the `SturdyRef` and `Owner` types will
|
||||
# vary between realms (they may even be different at the call site than they are on the
|
||||
# implementation). Instead, mark persistent interfaces with the $persistent annotation (defined
|
||||
# below).
|
||||
#
|
||||
# Sealing
|
||||
# -------
|
||||
#
|
||||
# As an added security measure, SturdyRefs may be "sealed" to a particular owner, such that
|
||||
# if the SturdyRef itself leaks to a third party, that party cannot actually restore it because
|
||||
# they are not the owner. To restore a sealed capability, you must first prove to its host that
|
||||
# you are the rightful owner. The precise mechanism for this authentication is defined by the
|
||||
# realm.
|
||||
#
|
||||
# Sealing is a defense-in-depth mechanism meant to mitigate damage in the case of catastrophic
|
||||
# attacks. For example, say an attacker temporarily gains read access to a database full of
|
||||
# SturdyRefs: it would be unfortunate if it were then necessary to revoke every single reference
|
||||
# in the database to prevent the attacker from using them.
|
||||
#
|
||||
# In general, an "owner" is a course-grained identity. Because capability-based security is still
|
||||
# the primary mechanism of security, it is not necessary nor desirable to have a separate "owner"
|
||||
# identity for every single process or object; that is exactly what capabilities are supposed to
|
||||
# avoid! Instead, it makes sense for an "owner" to literally identify the owner of the machines
|
||||
# where the capability is stored. If untrusted third parties are able to run arbitrary code on
|
||||
# said machines, then the sandbox for that code should be designed using Distributed Confinement
|
||||
# such that the third-party code never sees the bits of the SturdyRefs and cannot directly
|
||||
# exercise the owner's power to restore refs. See:
|
||||
#
|
||||
# http://www.erights.org/elib/capability/dist-confine.html
|
||||
#
|
||||
# Resist the urge to represent an Owner as a simple public key. The whole point of sealing is to
|
||||
# defend against leaked-storage attacks. Such attacks can easily result in the owner's private
|
||||
# key being stolen as well. A better solution is for `Owner` to contain a simple globally unique
|
||||
# identifier for the owner, and for everyone to separately maintain a mapping of owner IDs to
|
||||
# public keys. If an owner's private key is compromised, then humans will need to communicate
|
||||
# and agree on a replacement public key, then update the mapping.
|
||||
#
|
||||
# As a concrete example, an `Owner` could simply contain a domain name, and restoring a SturdyRef
|
||||
# would require signing a request using the domain's private key. Authenticating this key could
|
||||
# be accomplished through certificate authorities or web-of-trust techniques.
|
||||
|
||||
save @0 SaveParams -> SaveResults;
|
||||
# Save a capability persistently so that it can be restored by a future connection. Not all
|
||||
# capabilities can be saved -- application interfaces should define which capabilities support
|
||||
# this and which do not.
|
||||
|
||||
struct SaveParams {
|
||||
sealFor @0 :Owner;
|
||||
# Seal the SturdyRef so that it can only be restored by the specified Owner. This is meant
|
||||
# to mitigate damage when a SturdyRef is leaked. See comments above.
|
||||
#
|
||||
# Leaving this value null may or may not be allowed; it is up to the realm to decide. If a
|
||||
# realm does allow a null owner, this should indicate that anyone is allowed to restore the
|
||||
# ref.
|
||||
}
|
||||
struct SaveResults {
|
||||
sturdyRef @0 :SturdyRef;
|
||||
}
|
||||
}
|
||||
|
||||
interface RealmGateway(InternalRef, ExternalRef, InternalOwner, ExternalOwner) {
|
||||
# Interface invoked when a SturdyRef is about to cross realms. The RPC system supports providing
|
||||
# a RealmGateway as a callback hook when setting up RPC over some VatNetwork.
|
||||
|
||||
import @0 (cap :Persistent(ExternalRef, ExternalOwner),
|
||||
params :Persistent(InternalRef, InternalOwner).SaveParams)
|
||||
-> Persistent(InternalRef, InternalOwner).SaveResults;
|
||||
# Given an external capability, save it and return an internal reference. Used when someone
|
||||
# inside the realm tries to save a capability from outside the realm.
|
||||
|
||||
export @1 (cap :Persistent(InternalRef, InternalOwner),
|
||||
params :Persistent(ExternalRef, ExternalOwner).SaveParams)
|
||||
-> Persistent(ExternalRef, ExternalOwner).SaveResults;
|
||||
# Given an internal capability, save it and return an external reference. Used when someone
|
||||
# outside the realm tries to save a capability from inside the realm.
|
||||
}
|
||||
|
||||
annotation persistent(interface, field) :Void;
|
||||
# Apply this annotation to interfaces for objects that will always be persistent, instead of
|
||||
# extending the Persistent capability, since the correct type parameters to Persistent depend on
|
||||
# the realm, which is orthogonal to the interface type and therefore should not be defined
|
||||
# along-side it.
|
||||
#
|
||||
# You may also apply this annotation to a capability-typed field which will always contain a
|
||||
# persistent capability, but where the capability's interface itself is not already marked
|
||||
# persistent.
|
||||
#
|
||||
# Note that absence of the $persistent annotation doesn't mean a capability of that type isn't
|
||||
# persistent; it just means not *all* such capabilities are persistent.
|
||||
1328
phonelibs/capnp-cpp/include/capnp/persistent.capnp.h
Normal file
1328
phonelibs/capnp-cpp/include/capnp/persistent.capnp.h
Normal file
File diff suppressed because it is too large
Load Diff
160
phonelibs/capnp-cpp/include/capnp/pointer-helpers.h
Normal file
160
phonelibs/capnp-cpp/include/capnp/pointer-helpers.h
Normal file
@@ -0,0 +1,160 @@
|
||||
// Copyright (c) 2013-2014 Sandstorm Development Group, Inc. and contributors
|
||||
// Licensed under the MIT License:
|
||||
//
|
||||
// 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.
|
||||
|
||||
#ifndef CAPNP_POINTER_HELPERS_H_
|
||||
#define CAPNP_POINTER_HELPERS_H_
|
||||
|
||||
#if defined(__GNUC__) && !defined(CAPNP_HEADER_WARNINGS)
|
||||
#pragma GCC system_header
|
||||
#endif
|
||||
|
||||
#include "layout.h"
|
||||
#include "list.h"
|
||||
|
||||
namespace capnp {
|
||||
namespace _ { // private
|
||||
|
||||
// PointerHelpers is a template class that assists in wrapping/unwrapping the low-level types in
|
||||
// layout.h with the high-level public API and generated types. This way, the code generator
|
||||
// and other templates do not have to specialize on each kind of pointer.
|
||||
|
||||
template <typename T>
|
||||
struct PointerHelpers<T, Kind::STRUCT> {
|
||||
static inline typename T::Reader get(PointerReader reader, const word* defaultValue = nullptr) {
|
||||
return typename T::Reader(reader.getStruct(defaultValue));
|
||||
}
|
||||
static inline typename T::Builder get(PointerBuilder builder,
|
||||
const word* defaultValue = nullptr) {
|
||||
return typename T::Builder(builder.getStruct(structSize<T>(), defaultValue));
|
||||
}
|
||||
static inline void set(PointerBuilder builder, typename T::Reader value) {
|
||||
builder.setStruct(value._reader);
|
||||
}
|
||||
static inline void setCanonical(PointerBuilder builder, typename T::Reader value) {
|
||||
builder.setStruct(value._reader, true);
|
||||
}
|
||||
static inline typename T::Builder init(PointerBuilder builder) {
|
||||
return typename T::Builder(builder.initStruct(structSize<T>()));
|
||||
}
|
||||
static inline void adopt(PointerBuilder builder, Orphan<T>&& value) {
|
||||
builder.adopt(kj::mv(value.builder));
|
||||
}
|
||||
static inline Orphan<T> disown(PointerBuilder builder) {
|
||||
return Orphan<T>(builder.disown());
|
||||
}
|
||||
static inline _::StructReader getInternalReader(const typename T::Reader& reader) {
|
||||
return reader._reader;
|
||||
}
|
||||
static inline _::StructBuilder getInternalBuilder(typename T::Builder&& builder) {
|
||||
return builder._builder;
|
||||
}
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct PointerHelpers<List<T>, Kind::LIST> {
|
||||
static inline typename List<T>::Reader get(PointerReader reader,
|
||||
const word* defaultValue = nullptr) {
|
||||
return typename List<T>::Reader(List<T>::getFromPointer(reader, defaultValue));
|
||||
}
|
||||
static inline typename List<T>::Builder get(PointerBuilder builder,
|
||||
const word* defaultValue = nullptr) {
|
||||
return typename List<T>::Builder(List<T>::getFromPointer(builder, defaultValue));
|
||||
}
|
||||
static inline void set(PointerBuilder builder, typename List<T>::Reader value) {
|
||||
builder.setList(value.reader);
|
||||
}
|
||||
static inline void setCanonical(PointerBuilder builder, typename List<T>::Reader value) {
|
||||
builder.setList(value.reader, true);
|
||||
}
|
||||
static void set(PointerBuilder builder, kj::ArrayPtr<const ReaderFor<T>> value) {
|
||||
auto l = init(builder, value.size());
|
||||
uint i = 0;
|
||||
for (auto& element: value) {
|
||||
l.set(i++, element);
|
||||
}
|
||||
}
|
||||
static inline typename List<T>::Builder init(PointerBuilder builder, uint size) {
|
||||
return typename List<T>::Builder(List<T>::initPointer(builder, size));
|
||||
}
|
||||
static inline void adopt(PointerBuilder builder, Orphan<List<T>>&& value) {
|
||||
builder.adopt(kj::mv(value.builder));
|
||||
}
|
||||
static inline Orphan<List<T>> disown(PointerBuilder builder) {
|
||||
return Orphan<List<T>>(builder.disown());
|
||||
}
|
||||
static inline _::ListReader getInternalReader(const typename List<T>::Reader& reader) {
|
||||
return reader.reader;
|
||||
}
|
||||
static inline _::ListBuilder getInternalBuilder(typename List<T>::Builder&& builder) {
|
||||
return builder.builder;
|
||||
}
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct PointerHelpers<T, Kind::BLOB> {
|
||||
static inline typename T::Reader get(PointerReader reader,
|
||||
const void* defaultValue = nullptr,
|
||||
uint defaultBytes = 0) {
|
||||
return reader.getBlob<T>(defaultValue, bounded(defaultBytes) * BYTES);
|
||||
}
|
||||
static inline typename T::Builder get(PointerBuilder builder,
|
||||
const void* defaultValue = nullptr,
|
||||
uint defaultBytes = 0) {
|
||||
return builder.getBlob<T>(defaultValue, bounded(defaultBytes) * BYTES);
|
||||
}
|
||||
static inline void set(PointerBuilder builder, typename T::Reader value) {
|
||||
builder.setBlob<T>(value);
|
||||
}
|
||||
static inline void setCanonical(PointerBuilder builder, typename T::Reader value) {
|
||||
builder.setBlob<T>(value);
|
||||
}
|
||||
static inline typename T::Builder init(PointerBuilder builder, uint size) {
|
||||
return builder.initBlob<T>(bounded(size) * BYTES);
|
||||
}
|
||||
static inline void adopt(PointerBuilder builder, Orphan<T>&& value) {
|
||||
builder.adopt(kj::mv(value.builder));
|
||||
}
|
||||
static inline Orphan<T> disown(PointerBuilder builder) {
|
||||
return Orphan<T>(builder.disown());
|
||||
}
|
||||
};
|
||||
|
||||
struct UncheckedMessage {
|
||||
typedef const word* Reader;
|
||||
};
|
||||
|
||||
template <> struct Kind_<UncheckedMessage> { static constexpr Kind kind = Kind::OTHER; };
|
||||
|
||||
template <>
|
||||
struct PointerHelpers<UncheckedMessage> {
|
||||
// Reads an AnyPointer field as an unchecked message pointer. Requires that the containing
|
||||
// message is itself unchecked. This hack is currently private. It is used to locate default
|
||||
// values within encoded schemas.
|
||||
|
||||
static inline const word* get(PointerReader reader) {
|
||||
return reader.getUnchecked();
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace _ (private)
|
||||
} // namespace capnp
|
||||
|
||||
#endif // CAPNP_POINTER_HELPERS_H_
|
||||
47
phonelibs/capnp-cpp/include/capnp/pretty-print.h
Normal file
47
phonelibs/capnp-cpp/include/capnp/pretty-print.h
Normal file
@@ -0,0 +1,47 @@
|
||||
// Copyright (c) 2013-2014 Sandstorm Development Group, Inc. and contributors
|
||||
// Licensed under the MIT License:
|
||||
//
|
||||
// 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.
|
||||
|
||||
#ifndef CAPNP_PRETTY_PRINT_H_
|
||||
#define CAPNP_PRETTY_PRINT_H_
|
||||
|
||||
#if defined(__GNUC__) && !defined(CAPNP_HEADER_WARNINGS)
|
||||
#pragma GCC system_header
|
||||
#endif
|
||||
|
||||
#include "dynamic.h"
|
||||
#include <kj/string-tree.h>
|
||||
|
||||
namespace capnp {
|
||||
|
||||
kj::StringTree prettyPrint(DynamicStruct::Reader value);
|
||||
kj::StringTree prettyPrint(DynamicStruct::Builder value);
|
||||
kj::StringTree prettyPrint(DynamicList::Reader value);
|
||||
kj::StringTree prettyPrint(DynamicList::Builder value);
|
||||
// Print the given Cap'n Proto struct or list with nice indentation. Note that you can pass any
|
||||
// struct or list reader or builder type to this method, since they can be implicitly converted
|
||||
// to one of the dynamic types.
|
||||
//
|
||||
// If you don't want indentation, just use the value's KJ stringifier (e.g. pass it to kj::str(),
|
||||
// any of the KJ debug macros, etc.).
|
||||
|
||||
} // namespace capnp
|
||||
|
||||
#endif // PRETTY_PRINT_H_
|
||||
242
phonelibs/capnp-cpp/include/capnp/raw-schema.h
Normal file
242
phonelibs/capnp-cpp/include/capnp/raw-schema.h
Normal file
@@ -0,0 +1,242 @@
|
||||
// Copyright (c) 2013-2014 Sandstorm Development Group, Inc. and contributors
|
||||
// Licensed under the MIT License:
|
||||
//
|
||||
// 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.
|
||||
|
||||
#ifndef CAPNP_RAW_SCHEMA_H_
|
||||
#define CAPNP_RAW_SCHEMA_H_
|
||||
|
||||
#if defined(__GNUC__) && !defined(CAPNP_HEADER_WARNINGS)
|
||||
#pragma GCC system_header
|
||||
#endif
|
||||
|
||||
#include "common.h" // for uint and friends
|
||||
|
||||
#if _MSC_VER
|
||||
#include <atomic>
|
||||
#endif
|
||||
|
||||
namespace capnp {
|
||||
namespace _ { // private
|
||||
|
||||
struct RawSchema;
|
||||
|
||||
struct RawBrandedSchema {
|
||||
// Represents a combination of a schema and bindings for its generic parameters.
|
||||
//
|
||||
// Note that while we generate one `RawSchema` per type, we generate a `RawBrandedSchema` for
|
||||
// every _instance_ of a generic type -- or, at least, every instance that is actually used. For
|
||||
// generated-code types, we use template magic to initialize these.
|
||||
|
||||
const RawSchema* generic;
|
||||
// Generic type which we're branding.
|
||||
|
||||
struct Binding {
|
||||
uint8_t which; // Numeric value of one of schema::Type::Which.
|
||||
|
||||
bool isImplicitParameter;
|
||||
// For AnyPointer, true if it's an implicit method parameter.
|
||||
|
||||
uint16_t listDepth; // Number of times to wrap the base type in List().
|
||||
|
||||
uint16_t paramIndex;
|
||||
// For AnyPointer. If it's a type parameter (scopeId is non-zero) or it's an implicit parameter
|
||||
// (isImplicitParameter is true), then this is the parameter index. Otherwise this is a numeric
|
||||
// value of one of schema::Type::AnyPointer::Unconstrained::Which.
|
||||
|
||||
union {
|
||||
const RawBrandedSchema* schema; // for struct, enum, interface
|
||||
uint64_t scopeId; // for AnyPointer, if it's a type parameter
|
||||
};
|
||||
|
||||
Binding() = default;
|
||||
inline constexpr Binding(uint8_t which, uint16_t listDepth, const RawBrandedSchema* schema)
|
||||
: which(which), isImplicitParameter(false), listDepth(listDepth), paramIndex(0),
|
||||
schema(schema) {}
|
||||
inline constexpr Binding(uint8_t which, uint16_t listDepth,
|
||||
uint64_t scopeId, uint16_t paramIndex)
|
||||
: which(which), isImplicitParameter(false), listDepth(listDepth), paramIndex(paramIndex),
|
||||
scopeId(scopeId) {}
|
||||
inline constexpr Binding(uint8_t which, uint16_t listDepth, uint16_t implicitParamIndex)
|
||||
: which(which), isImplicitParameter(true), listDepth(listDepth),
|
||||
paramIndex(implicitParamIndex), scopeId(0) {}
|
||||
};
|
||||
|
||||
struct Scope {
|
||||
uint64_t typeId;
|
||||
// Type ID whose parameters are being bound.
|
||||
|
||||
const Binding* bindings;
|
||||
uint bindingCount;
|
||||
// Bindings for those parameters.
|
||||
|
||||
bool isUnbound;
|
||||
// This scope is unbound, in the sense of SchemaLoader::getUnbound().
|
||||
};
|
||||
|
||||
const Scope* scopes;
|
||||
// Array of enclosing scopes for which generic variables have been bound, sorted by type ID.
|
||||
|
||||
struct Dependency {
|
||||
uint location;
|
||||
const RawBrandedSchema* schema;
|
||||
};
|
||||
|
||||
const Dependency* dependencies;
|
||||
// Map of branded schemas for dependencies of this type, given our brand. Only dependencies that
|
||||
// are branded are included in this map; if a dependency is missing, use its `defaultBrand`.
|
||||
|
||||
uint32_t scopeCount;
|
||||
uint32_t dependencyCount;
|
||||
|
||||
enum class DepKind {
|
||||
// Component of a Dependency::location. Specifies what sort of dependency this is.
|
||||
|
||||
INVALID,
|
||||
// Mostly defined to ensure that zero is not a valid location.
|
||||
|
||||
FIELD,
|
||||
// Binding needed for a field's type. The index is the field index (NOT ordinal!).
|
||||
|
||||
METHOD_PARAMS,
|
||||
// Bindings needed for a method's params type. The index is the method number.
|
||||
|
||||
METHOD_RESULTS,
|
||||
// Bindings needed for a method's results type. The index is the method ordinal.
|
||||
|
||||
SUPERCLASS,
|
||||
// Bindings needed for a superclass type. The index is the superclass's index in the
|
||||
// "extends" list.
|
||||
|
||||
CONST_TYPE
|
||||
// Bindings needed for the type of a constant. The index is zero.
|
||||
};
|
||||
|
||||
static inline uint makeDepLocation(DepKind kind, uint index) {
|
||||
// Make a number representing the location of a particular dependency within its parent
|
||||
// schema.
|
||||
|
||||
return (static_cast<uint>(kind) << 24) | index;
|
||||
}
|
||||
|
||||
class Initializer {
|
||||
public:
|
||||
virtual void init(const RawBrandedSchema* generic) const = 0;
|
||||
};
|
||||
|
||||
const Initializer* lazyInitializer;
|
||||
// Lazy initializer, invoked by ensureInitialized().
|
||||
|
||||
inline void ensureInitialized() const {
|
||||
// Lazy initialization support. Invoke to ensure that initialization has taken place. This
|
||||
// is required in particular when traversing the dependency list. RawSchemas for compiled-in
|
||||
// types are always initialized; only dynamically-loaded schemas may be lazy.
|
||||
|
||||
#if __GNUC__
|
||||
const Initializer* i = __atomic_load_n(&lazyInitializer, __ATOMIC_ACQUIRE);
|
||||
#elif _MSC_VER
|
||||
const Initializer* i = *static_cast<Initializer const* const volatile*>(&lazyInitializer);
|
||||
std::atomic_thread_fence(std::memory_order_acquire);
|
||||
#else
|
||||
#error "Platform not supported"
|
||||
#endif
|
||||
if (i != nullptr) i->init(this);
|
||||
}
|
||||
|
||||
inline bool isUnbound() const;
|
||||
// Checks if this schema is the result of calling SchemaLoader::getUnbound(), in which case
|
||||
// binding lookups need to be handled specially.
|
||||
};
|
||||
|
||||
struct RawSchema {
|
||||
// The generated code defines a constant RawSchema for every compiled declaration.
|
||||
//
|
||||
// This is an internal structure which could change in the future.
|
||||
|
||||
uint64_t id;
|
||||
|
||||
const word* encodedNode;
|
||||
// Encoded SchemaNode, readable via readMessageUnchecked<schema::Node>(encodedNode).
|
||||
|
||||
uint32_t encodedSize;
|
||||
// Size of encodedNode, in words.
|
||||
|
||||
const RawSchema* const* dependencies;
|
||||
// Pointers to other types on which this one depends, sorted by ID. The schemas in this table
|
||||
// may be uninitialized -- you must call ensureInitialized() on the one you wish to use before
|
||||
// using it.
|
||||
//
|
||||
// TODO(someday): Make this a hashtable.
|
||||
|
||||
const uint16_t* membersByName;
|
||||
// Indexes of members sorted by name. Used to implement name lookup.
|
||||
// TODO(someday): Make this a hashtable.
|
||||
|
||||
uint32_t dependencyCount;
|
||||
uint32_t memberCount;
|
||||
// Sizes of above tables.
|
||||
|
||||
const uint16_t* membersByDiscriminant;
|
||||
// List of all member indexes ordered by discriminant value. Those which don't have a
|
||||
// discriminant value are listed at the end, in order by ordinal.
|
||||
|
||||
const RawSchema* canCastTo;
|
||||
// Points to the RawSchema of a compiled-in type to which it is safe to cast any DynamicValue
|
||||
// with this schema. This is null for all compiled-in types; it is only set by SchemaLoader on
|
||||
// dynamically-loaded types.
|
||||
|
||||
class Initializer {
|
||||
public:
|
||||
virtual void init(const RawSchema* schema) const = 0;
|
||||
};
|
||||
|
||||
const Initializer* lazyInitializer;
|
||||
// Lazy initializer, invoked by ensureInitialized().
|
||||
|
||||
inline void ensureInitialized() const {
|
||||
// Lazy initialization support. Invoke to ensure that initialization has taken place. This
|
||||
// is required in particular when traversing the dependency list. RawSchemas for compiled-in
|
||||
// types are always initialized; only dynamically-loaded schemas may be lazy.
|
||||
|
||||
#if __GNUC__
|
||||
const Initializer* i = __atomic_load_n(&lazyInitializer, __ATOMIC_ACQUIRE);
|
||||
#elif _MSC_VER
|
||||
const Initializer* i = *static_cast<Initializer const* const volatile*>(&lazyInitializer);
|
||||
std::atomic_thread_fence(std::memory_order_acquire);
|
||||
#else
|
||||
#error "Platform not supported"
|
||||
#endif
|
||||
if (i != nullptr) i->init(this);
|
||||
}
|
||||
|
||||
RawBrandedSchema defaultBrand;
|
||||
// Specifies the brand to use for this schema if no generic parameters have been bound to
|
||||
// anything. Generally, in the default brand, all generic parameters are treated as if they were
|
||||
// bound to `AnyPointer`.
|
||||
};
|
||||
|
||||
inline bool RawBrandedSchema::isUnbound() const {
|
||||
// The unbound schema is the only one that has no scopes but is not the default schema.
|
||||
return scopeCount == 0 && this != &generic->defaultBrand;
|
||||
}
|
||||
|
||||
} // namespace _ (private)
|
||||
} // namespace capnp
|
||||
|
||||
#endif // CAPNP_RAW_SCHEMA_H_
|
||||
130
phonelibs/capnp-cpp/include/capnp/rpc-prelude.h
Normal file
130
phonelibs/capnp-cpp/include/capnp/rpc-prelude.h
Normal file
@@ -0,0 +1,130 @@
|
||||
// Copyright (c) 2013-2014 Sandstorm Development Group, Inc. and contributors
|
||||
// Licensed under the MIT License:
|
||||
//
|
||||
// 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.
|
||||
|
||||
// This file contains a bunch of internal declarations that must appear before rpc.h can start.
|
||||
// We don't define these directly in rpc.h because it makes the file hard to read.
|
||||
|
||||
#ifndef CAPNP_RPC_PRELUDE_H_
|
||||
#define CAPNP_RPC_PRELUDE_H_
|
||||
|
||||
#if defined(__GNUC__) && !defined(CAPNP_HEADER_WARNINGS)
|
||||
#pragma GCC system_header
|
||||
#endif
|
||||
|
||||
#include "capability.h"
|
||||
#include "persistent.capnp.h"
|
||||
|
||||
namespace capnp {
|
||||
|
||||
class OutgoingRpcMessage;
|
||||
class IncomingRpcMessage;
|
||||
|
||||
template <typename SturdyRefHostId>
|
||||
class RpcSystem;
|
||||
|
||||
namespace _ { // private
|
||||
|
||||
class VatNetworkBase {
|
||||
// Non-template version of VatNetwork. Ignore this class; see VatNetwork in rpc.h.
|
||||
|
||||
public:
|
||||
class Connection;
|
||||
|
||||
struct ConnectionAndProvisionId {
|
||||
kj::Own<Connection> connection;
|
||||
kj::Own<OutgoingRpcMessage> firstMessage;
|
||||
Orphan<AnyPointer> provisionId;
|
||||
};
|
||||
|
||||
class Connection {
|
||||
public:
|
||||
virtual kj::Own<OutgoingRpcMessage> newOutgoingMessage(uint firstSegmentWordSize) = 0;
|
||||
virtual kj::Promise<kj::Maybe<kj::Own<IncomingRpcMessage>>> receiveIncomingMessage() = 0;
|
||||
virtual kj::Promise<void> shutdown() = 0;
|
||||
virtual AnyStruct::Reader baseGetPeerVatId() = 0;
|
||||
};
|
||||
virtual kj::Maybe<kj::Own<Connection>> baseConnect(AnyStruct::Reader vatId) = 0;
|
||||
virtual kj::Promise<kj::Own<Connection>> baseAccept() = 0;
|
||||
};
|
||||
|
||||
class SturdyRefRestorerBase {
|
||||
public:
|
||||
virtual Capability::Client baseRestore(AnyPointer::Reader ref) = 0;
|
||||
};
|
||||
|
||||
class BootstrapFactoryBase {
|
||||
// Non-template version of BootstrapFactory. Ignore this class; see BootstrapFactory in rpc.h.
|
||||
public:
|
||||
virtual Capability::Client baseCreateFor(AnyStruct::Reader clientId) = 0;
|
||||
};
|
||||
|
||||
class RpcSystemBase {
|
||||
// Non-template version of RpcSystem. Ignore this class; see RpcSystem in rpc.h.
|
||||
|
||||
public:
|
||||
RpcSystemBase(VatNetworkBase& network, kj::Maybe<Capability::Client> bootstrapInterface,
|
||||
kj::Maybe<RealmGateway<>::Client> gateway);
|
||||
RpcSystemBase(VatNetworkBase& network, BootstrapFactoryBase& bootstrapFactory,
|
||||
kj::Maybe<RealmGateway<>::Client> gateway);
|
||||
RpcSystemBase(VatNetworkBase& network, SturdyRefRestorerBase& restorer);
|
||||
RpcSystemBase(RpcSystemBase&& other) noexcept;
|
||||
~RpcSystemBase() noexcept(false);
|
||||
|
||||
private:
|
||||
class Impl;
|
||||
kj::Own<Impl> impl;
|
||||
|
||||
Capability::Client baseBootstrap(AnyStruct::Reader vatId);
|
||||
Capability::Client baseRestore(AnyStruct::Reader vatId, AnyPointer::Reader objectId);
|
||||
void baseSetFlowLimit(size_t words);
|
||||
|
||||
template <typename>
|
||||
friend class capnp::RpcSystem;
|
||||
};
|
||||
|
||||
template <typename T> struct InternalRefFromRealmGateway_;
|
||||
template <typename InternalRef, typename ExternalRef, typename InternalOwner,
|
||||
typename ExternalOwner>
|
||||
struct InternalRefFromRealmGateway_<RealmGateway<InternalRef, ExternalRef, InternalOwner,
|
||||
ExternalOwner>> {
|
||||
typedef InternalRef Type;
|
||||
};
|
||||
template <typename T>
|
||||
using InternalRefFromRealmGateway = typename InternalRefFromRealmGateway_<T>::Type;
|
||||
template <typename T>
|
||||
using InternalRefFromRealmGatewayClient = InternalRefFromRealmGateway<typename T::Calls>;
|
||||
|
||||
template <typename T> struct ExternalRefFromRealmGateway_;
|
||||
template <typename InternalRef, typename ExternalRef, typename InternalOwner,
|
||||
typename ExternalOwner>
|
||||
struct ExternalRefFromRealmGateway_<RealmGateway<InternalRef, ExternalRef, InternalOwner,
|
||||
ExternalOwner>> {
|
||||
typedef ExternalRef Type;
|
||||
};
|
||||
template <typename T>
|
||||
using ExternalRefFromRealmGateway = typename ExternalRefFromRealmGateway_<T>::Type;
|
||||
template <typename T>
|
||||
using ExternalRefFromRealmGatewayClient = ExternalRefFromRealmGateway<typename T::Calls>;
|
||||
|
||||
} // namespace _ (private)
|
||||
} // namespace capnp
|
||||
|
||||
#endif // CAPNP_RPC_PRELUDE_H_
|
||||
169
phonelibs/capnp-cpp/include/capnp/rpc-twoparty.capnp
Normal file
169
phonelibs/capnp-cpp/include/capnp/rpc-twoparty.capnp
Normal file
@@ -0,0 +1,169 @@
|
||||
# Copyright (c) 2013-2014 Sandstorm Development Group, Inc. and contributors
|
||||
# Licensed under the MIT License:
|
||||
#
|
||||
# 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.
|
||||
|
||||
@0xa184c7885cdaf2a1;
|
||||
# This file defines the "network-specific parameters" in rpc.capnp to support a network consisting
|
||||
# of two vats. Each of these vats may in fact be in communication with other vats, but any
|
||||
# capabilities they forward must be proxied. Thus, to each end of the connection, all capabilities
|
||||
# received from the other end appear to live in a single vat.
|
||||
#
|
||||
# Two notable use cases for this model include:
|
||||
# - Regular client-server communications, where a remote client machine (perhaps living on an end
|
||||
# user's personal device) connects to a server. The server may be part of a cluster, and may
|
||||
# call on other servers in the cluster to help service the user's request. It may even obtain
|
||||
# capabilities from these other servers which it passes on to the user. To simplify network
|
||||
# common traversal problems (e.g. if the user is behind a firewall), it is probably desirable to
|
||||
# multiplex all communications between the server cluster and the client over the original
|
||||
# connection rather than form new ones. This connection should use the two-party protocol, as
|
||||
# the client has no interest in knowing about additional servers.
|
||||
# - Applications running in a sandbox. A supervisor process may execute a confined application
|
||||
# such that all of the confined app's communications with the outside world must pass through
|
||||
# the supervisor. In this case, the connection between the confined app and the supervisor might
|
||||
# as well use the two-party protocol, because the confined app is intentionally prevented from
|
||||
# talking to any other vat anyway. Any external resources will be proxied through the supervisor,
|
||||
# and so to the contained app will appear as if they were hosted by the supervisor itself.
|
||||
#
|
||||
# Since there are only two vats in this network, there is never a need for three-way introductions,
|
||||
# so level 3 is free. Moreover, because it is never necessary to form new connections, the
|
||||
# two-party protocol can be used easily anywhere where a two-way byte stream exists, without regard
|
||||
# to where that byte stream goes or how it was initiated. This makes the two-party runtime library
|
||||
# highly reusable.
|
||||
#
|
||||
# Joins (level 4) _could_ be needed in cases where one or both vats are participating in other
|
||||
# networks that use joins. For instance, if Alice and Bob are speaking through the two-party
|
||||
# protocol, and Bob is also participating on another network, Bob may send Alice two or more
|
||||
# proxied capabilities which, unbeknownst to Bob at the time, are in fact pointing at the same
|
||||
# remote object. Alice may then request to join these capabilities, at which point Bob will have
|
||||
# to forward the join to the other network. Note, however, that if Alice is _not_ participating on
|
||||
# any other network, then Alice will never need to _receive_ a Join, because Alice would always
|
||||
# know when two locally-hosted capabilities are the same and would never export a redundant alias
|
||||
# to Bob. So, Alice can respond to all incoming joins with an error, and only needs to implement
|
||||
# outgoing joins if she herself desires to use this feature. Also, outgoing joins are relatively
|
||||
# easy to implement in this scenario.
|
||||
#
|
||||
# What all this means is that a level 4 implementation of the confined network is barely more
|
||||
# complicated than a level 2 implementation. However, such an implementation allows the "client"
|
||||
# or "confined" app to access the server's/supervisor's network with equal functionality to any
|
||||
# native participant. In other words, an application which implements only the two-party protocol
|
||||
# can be paired with a proxy app in order to participate in any network.
|
||||
#
|
||||
# So, when implementing Cap'n Proto in a new language, it makes sense to implement only the
|
||||
# two-party protocol initially, and then pair applications with an appropriate proxy written in
|
||||
# C++, rather than implement other parameterizations of the RPC protocol directly.
|
||||
|
||||
using Cxx = import "/capnp/c++.capnp";
|
||||
$Cxx.namespace("capnp::rpc::twoparty");
|
||||
|
||||
# Note: SturdyRef is not specified here. It is up to the application to define semantics of
|
||||
# SturdyRefs if desired.
|
||||
|
||||
enum Side {
|
||||
server @0;
|
||||
# The object lives on the "server" or "supervisor" end of the connection. Only the
|
||||
# server/supervisor knows how to interpret the ref; to the client, it is opaque.
|
||||
#
|
||||
# Note that containers intending to implement strong confinement should rewrite SturdyRefs
|
||||
# received from the external network before passing them on to the confined app. The confined
|
||||
# app thus does not ever receive the raw bits of the SturdyRef (which it could perhaps
|
||||
# maliciously leak), but instead receives only a thing that it can pass back to the container
|
||||
# later to restore the ref. See:
|
||||
# http://www.erights.org/elib/capability/dist-confine.html
|
||||
|
||||
client @1;
|
||||
# The object lives on the "client" or "confined app" end of the connection. Only the client
|
||||
# knows how to interpret the ref; to the server/supervisor, it is opaque. Most clients do not
|
||||
# actually know how to persist capabilities at all, so use of this is unusual.
|
||||
}
|
||||
|
||||
struct VatId {
|
||||
side @0 :Side;
|
||||
}
|
||||
|
||||
struct ProvisionId {
|
||||
# Only used for joins, since three-way introductions never happen on a two-party network.
|
||||
|
||||
joinId @0 :UInt32;
|
||||
# The ID from `JoinKeyPart`.
|
||||
}
|
||||
|
||||
struct RecipientId {}
|
||||
# Never used, because there are only two parties.
|
||||
|
||||
struct ThirdPartyCapId {}
|
||||
# Never used, because there is no third party.
|
||||
|
||||
struct JoinKeyPart {
|
||||
# Joins in the two-party case are simplified by a few observations.
|
||||
#
|
||||
# First, on a two-party network, a Join only ever makes sense if the receiving end is also
|
||||
# connected to other networks. A vat which is not connected to any other network can safely
|
||||
# reject all joins.
|
||||
#
|
||||
# Second, since a two-party connection bisects the network -- there can be no other connections
|
||||
# between the networks at either end of the connection -- if one part of a join crosses the
|
||||
# connection, then _all_ parts must cross it. Therefore, a vat which is receiving a Join request
|
||||
# off some other network which needs to be forwarded across the two-party connection can
|
||||
# collect all the parts on its end and only forward them across the two-party connection when all
|
||||
# have been received.
|
||||
#
|
||||
# For example, imagine that Alice and Bob are vats connected over a two-party connection, and
|
||||
# each is also connected to other networks. At some point, Alice receives one part of a Join
|
||||
# request off her network. The request is addressed to a capability that Alice received from
|
||||
# Bob and is proxying to her other network. Alice goes ahead and responds to the Join part as
|
||||
# if she hosted the capability locally (this is important so that if not all the Join parts end
|
||||
# up at Alice, the original sender can detect the failed Join without hanging). As other parts
|
||||
# trickle in, Alice verifies that each part is addressed to a capability from Bob and continues
|
||||
# to respond to each one. Once the complete set of join parts is received, Alice checks if they
|
||||
# were all for the exact same capability. If so, she doesn't need to send anything to Bob at
|
||||
# all. Otherwise, she collects the set of capabilities (from Bob) to which the join parts were
|
||||
# addressed and essentially initiates a _new_ Join request on those capabilities to Bob. Alice
|
||||
# does not forward the Join parts she received herself, but essentially forwards the Join as a
|
||||
# whole.
|
||||
#
|
||||
# On Bob's end, since he knows that Alice will always send all parts of a Join together, he
|
||||
# simply waits until he's received them all, then performs a join on the respective capabilities
|
||||
# as if it had been requested locally.
|
||||
|
||||
joinId @0 :UInt32;
|
||||
# A number identifying this join, chosen by the sender. May be reused once `Finish` messages are
|
||||
# sent corresponding to all of the `Join` messages.
|
||||
|
||||
partCount @1 :UInt16;
|
||||
# The number of capabilities to be joined.
|
||||
|
||||
partNum @2 :UInt16;
|
||||
# Which part this request targets -- a number in the range [0, partCount).
|
||||
}
|
||||
|
||||
struct JoinResult {
|
||||
joinId @0 :UInt32;
|
||||
# Matches `JoinKeyPart`.
|
||||
|
||||
succeeded @1 :Bool;
|
||||
# All JoinResults in the set will have the same value for `succeeded`. The receiver actually
|
||||
# implements the join by waiting for all the `JoinKeyParts` and then performing its own join on
|
||||
# them, then going back and answering all the join requests afterwards.
|
||||
|
||||
cap @2 :AnyPointer;
|
||||
# One of the JoinResults will have a non-null `cap` which is the joined capability.
|
||||
#
|
||||
# TODO(cleanup): Change `AnyPointer` to `Capability` when that is supported.
|
||||
}
|
||||
726
phonelibs/capnp-cpp/include/capnp/rpc-twoparty.capnp.h
Normal file
726
phonelibs/capnp-cpp/include/capnp/rpc-twoparty.capnp.h
Normal file
@@ -0,0 +1,726 @@
|
||||
// Generated by Cap'n Proto compiler, DO NOT EDIT
|
||||
// source: rpc-twoparty.capnp
|
||||
|
||||
#ifndef CAPNP_INCLUDED_a184c7885cdaf2a1_
|
||||
#define CAPNP_INCLUDED_a184c7885cdaf2a1_
|
||||
|
||||
#include <capnp/generated-header-support.h>
|
||||
|
||||
#if CAPNP_VERSION != 6001
|
||||
#error "Version mismatch between generated code and library headers. You must use the same version of the Cap'n Proto compiler and library."
|
||||
#endif
|
||||
|
||||
|
||||
namespace capnp {
|
||||
namespace schemas {
|
||||
|
||||
CAPNP_DECLARE_SCHEMA(9fd69ebc87b9719c);
|
||||
enum class Side_9fd69ebc87b9719c: uint16_t {
|
||||
SERVER,
|
||||
CLIENT,
|
||||
};
|
||||
CAPNP_DECLARE_ENUM(Side, 9fd69ebc87b9719c);
|
||||
CAPNP_DECLARE_SCHEMA(d20b909fee733a8e);
|
||||
CAPNP_DECLARE_SCHEMA(b88d09a9c5f39817);
|
||||
CAPNP_DECLARE_SCHEMA(89f389b6fd4082c1);
|
||||
CAPNP_DECLARE_SCHEMA(b47f4979672cb59d);
|
||||
CAPNP_DECLARE_SCHEMA(95b29059097fca83);
|
||||
CAPNP_DECLARE_SCHEMA(9d263a3630b7ebee);
|
||||
|
||||
} // namespace schemas
|
||||
} // namespace capnp
|
||||
|
||||
namespace capnp {
|
||||
namespace rpc {
|
||||
namespace twoparty {
|
||||
|
||||
typedef ::capnp::schemas::Side_9fd69ebc87b9719c Side;
|
||||
|
||||
struct VatId {
|
||||
VatId() = delete;
|
||||
|
||||
class Reader;
|
||||
class Builder;
|
||||
class Pipeline;
|
||||
|
||||
struct _capnpPrivate {
|
||||
CAPNP_DECLARE_STRUCT_HEADER(d20b909fee733a8e, 1, 0)
|
||||
#if !CAPNP_LITE
|
||||
static constexpr ::capnp::_::RawBrandedSchema const* brand() { return &schema->defaultBrand; }
|
||||
#endif // !CAPNP_LITE
|
||||
};
|
||||
};
|
||||
|
||||
struct ProvisionId {
|
||||
ProvisionId() = delete;
|
||||
|
||||
class Reader;
|
||||
class Builder;
|
||||
class Pipeline;
|
||||
|
||||
struct _capnpPrivate {
|
||||
CAPNP_DECLARE_STRUCT_HEADER(b88d09a9c5f39817, 1, 0)
|
||||
#if !CAPNP_LITE
|
||||
static constexpr ::capnp::_::RawBrandedSchema const* brand() { return &schema->defaultBrand; }
|
||||
#endif // !CAPNP_LITE
|
||||
};
|
||||
};
|
||||
|
||||
struct RecipientId {
|
||||
RecipientId() = delete;
|
||||
|
||||
class Reader;
|
||||
class Builder;
|
||||
class Pipeline;
|
||||
|
||||
struct _capnpPrivate {
|
||||
CAPNP_DECLARE_STRUCT_HEADER(89f389b6fd4082c1, 0, 0)
|
||||
#if !CAPNP_LITE
|
||||
static constexpr ::capnp::_::RawBrandedSchema const* brand() { return &schema->defaultBrand; }
|
||||
#endif // !CAPNP_LITE
|
||||
};
|
||||
};
|
||||
|
||||
struct ThirdPartyCapId {
|
||||
ThirdPartyCapId() = delete;
|
||||
|
||||
class Reader;
|
||||
class Builder;
|
||||
class Pipeline;
|
||||
|
||||
struct _capnpPrivate {
|
||||
CAPNP_DECLARE_STRUCT_HEADER(b47f4979672cb59d, 0, 0)
|
||||
#if !CAPNP_LITE
|
||||
static constexpr ::capnp::_::RawBrandedSchema const* brand() { return &schema->defaultBrand; }
|
||||
#endif // !CAPNP_LITE
|
||||
};
|
||||
};
|
||||
|
||||
struct JoinKeyPart {
|
||||
JoinKeyPart() = delete;
|
||||
|
||||
class Reader;
|
||||
class Builder;
|
||||
class Pipeline;
|
||||
|
||||
struct _capnpPrivate {
|
||||
CAPNP_DECLARE_STRUCT_HEADER(95b29059097fca83, 1, 0)
|
||||
#if !CAPNP_LITE
|
||||
static constexpr ::capnp::_::RawBrandedSchema const* brand() { return &schema->defaultBrand; }
|
||||
#endif // !CAPNP_LITE
|
||||
};
|
||||
};
|
||||
|
||||
struct JoinResult {
|
||||
JoinResult() = delete;
|
||||
|
||||
class Reader;
|
||||
class Builder;
|
||||
class Pipeline;
|
||||
|
||||
struct _capnpPrivate {
|
||||
CAPNP_DECLARE_STRUCT_HEADER(9d263a3630b7ebee, 1, 1)
|
||||
#if !CAPNP_LITE
|
||||
static constexpr ::capnp::_::RawBrandedSchema const* brand() { return &schema->defaultBrand; }
|
||||
#endif // !CAPNP_LITE
|
||||
};
|
||||
};
|
||||
|
||||
// =======================================================================================
|
||||
|
||||
class VatId::Reader {
|
||||
public:
|
||||
typedef VatId Reads;
|
||||
|
||||
Reader() = default;
|
||||
inline explicit Reader(::capnp::_::StructReader base): _reader(base) {}
|
||||
|
||||
inline ::capnp::MessageSize totalSize() const {
|
||||
return _reader.totalSize().asPublic();
|
||||
}
|
||||
|
||||
#if !CAPNP_LITE
|
||||
inline ::kj::StringTree toString() const {
|
||||
return ::capnp::_::structString(_reader, *_capnpPrivate::brand());
|
||||
}
|
||||
#endif // !CAPNP_LITE
|
||||
|
||||
inline ::capnp::rpc::twoparty::Side getSide() const;
|
||||
|
||||
private:
|
||||
::capnp::_::StructReader _reader;
|
||||
template <typename, ::capnp::Kind>
|
||||
friend struct ::capnp::ToDynamic_;
|
||||
template <typename, ::capnp::Kind>
|
||||
friend struct ::capnp::_::PointerHelpers;
|
||||
template <typename, ::capnp::Kind>
|
||||
friend struct ::capnp::List;
|
||||
friend class ::capnp::MessageBuilder;
|
||||
friend class ::capnp::Orphanage;
|
||||
};
|
||||
|
||||
class VatId::Builder {
|
||||
public:
|
||||
typedef VatId Builds;
|
||||
|
||||
Builder() = delete; // Deleted to discourage incorrect usage.
|
||||
// You can explicitly initialize to nullptr instead.
|
||||
inline Builder(decltype(nullptr)) {}
|
||||
inline explicit Builder(::capnp::_::StructBuilder base): _builder(base) {}
|
||||
inline operator Reader() const { return Reader(_builder.asReader()); }
|
||||
inline Reader asReader() const { return *this; }
|
||||
|
||||
inline ::capnp::MessageSize totalSize() const { return asReader().totalSize(); }
|
||||
#if !CAPNP_LITE
|
||||
inline ::kj::StringTree toString() const { return asReader().toString(); }
|
||||
#endif // !CAPNP_LITE
|
||||
|
||||
inline ::capnp::rpc::twoparty::Side getSide();
|
||||
inline void setSide( ::capnp::rpc::twoparty::Side value);
|
||||
|
||||
private:
|
||||
::capnp::_::StructBuilder _builder;
|
||||
template <typename, ::capnp::Kind>
|
||||
friend struct ::capnp::ToDynamic_;
|
||||
friend class ::capnp::Orphanage;
|
||||
template <typename, ::capnp::Kind>
|
||||
friend struct ::capnp::_::PointerHelpers;
|
||||
};
|
||||
|
||||
#if !CAPNP_LITE
|
||||
class VatId::Pipeline {
|
||||
public:
|
||||
typedef VatId Pipelines;
|
||||
|
||||
inline Pipeline(decltype(nullptr)): _typeless(nullptr) {}
|
||||
inline explicit Pipeline(::capnp::AnyPointer::Pipeline&& typeless)
|
||||
: _typeless(kj::mv(typeless)) {}
|
||||
|
||||
private:
|
||||
::capnp::AnyPointer::Pipeline _typeless;
|
||||
friend class ::capnp::PipelineHook;
|
||||
template <typename, ::capnp::Kind>
|
||||
friend struct ::capnp::ToDynamic_;
|
||||
};
|
||||
#endif // !CAPNP_LITE
|
||||
|
||||
class ProvisionId::Reader {
|
||||
public:
|
||||
typedef ProvisionId Reads;
|
||||
|
||||
Reader() = default;
|
||||
inline explicit Reader(::capnp::_::StructReader base): _reader(base) {}
|
||||
|
||||
inline ::capnp::MessageSize totalSize() const {
|
||||
return _reader.totalSize().asPublic();
|
||||
}
|
||||
|
||||
#if !CAPNP_LITE
|
||||
inline ::kj::StringTree toString() const {
|
||||
return ::capnp::_::structString(_reader, *_capnpPrivate::brand());
|
||||
}
|
||||
#endif // !CAPNP_LITE
|
||||
|
||||
inline ::uint32_t getJoinId() const;
|
||||
|
||||
private:
|
||||
::capnp::_::StructReader _reader;
|
||||
template <typename, ::capnp::Kind>
|
||||
friend struct ::capnp::ToDynamic_;
|
||||
template <typename, ::capnp::Kind>
|
||||
friend struct ::capnp::_::PointerHelpers;
|
||||
template <typename, ::capnp::Kind>
|
||||
friend struct ::capnp::List;
|
||||
friend class ::capnp::MessageBuilder;
|
||||
friend class ::capnp::Orphanage;
|
||||
};
|
||||
|
||||
class ProvisionId::Builder {
|
||||
public:
|
||||
typedef ProvisionId Builds;
|
||||
|
||||
Builder() = delete; // Deleted to discourage incorrect usage.
|
||||
// You can explicitly initialize to nullptr instead.
|
||||
inline Builder(decltype(nullptr)) {}
|
||||
inline explicit Builder(::capnp::_::StructBuilder base): _builder(base) {}
|
||||
inline operator Reader() const { return Reader(_builder.asReader()); }
|
||||
inline Reader asReader() const { return *this; }
|
||||
|
||||
inline ::capnp::MessageSize totalSize() const { return asReader().totalSize(); }
|
||||
#if !CAPNP_LITE
|
||||
inline ::kj::StringTree toString() const { return asReader().toString(); }
|
||||
#endif // !CAPNP_LITE
|
||||
|
||||
inline ::uint32_t getJoinId();
|
||||
inline void setJoinId( ::uint32_t value);
|
||||
|
||||
private:
|
||||
::capnp::_::StructBuilder _builder;
|
||||
template <typename, ::capnp::Kind>
|
||||
friend struct ::capnp::ToDynamic_;
|
||||
friend class ::capnp::Orphanage;
|
||||
template <typename, ::capnp::Kind>
|
||||
friend struct ::capnp::_::PointerHelpers;
|
||||
};
|
||||
|
||||
#if !CAPNP_LITE
|
||||
class ProvisionId::Pipeline {
|
||||
public:
|
||||
typedef ProvisionId Pipelines;
|
||||
|
||||
inline Pipeline(decltype(nullptr)): _typeless(nullptr) {}
|
||||
inline explicit Pipeline(::capnp::AnyPointer::Pipeline&& typeless)
|
||||
: _typeless(kj::mv(typeless)) {}
|
||||
|
||||
private:
|
||||
::capnp::AnyPointer::Pipeline _typeless;
|
||||
friend class ::capnp::PipelineHook;
|
||||
template <typename, ::capnp::Kind>
|
||||
friend struct ::capnp::ToDynamic_;
|
||||
};
|
||||
#endif // !CAPNP_LITE
|
||||
|
||||
class RecipientId::Reader {
|
||||
public:
|
||||
typedef RecipientId Reads;
|
||||
|
||||
Reader() = default;
|
||||
inline explicit Reader(::capnp::_::StructReader base): _reader(base) {}
|
||||
|
||||
inline ::capnp::MessageSize totalSize() const {
|
||||
return _reader.totalSize().asPublic();
|
||||
}
|
||||
|
||||
#if !CAPNP_LITE
|
||||
inline ::kj::StringTree toString() const {
|
||||
return ::capnp::_::structString(_reader, *_capnpPrivate::brand());
|
||||
}
|
||||
#endif // !CAPNP_LITE
|
||||
|
||||
private:
|
||||
::capnp::_::StructReader _reader;
|
||||
template <typename, ::capnp::Kind>
|
||||
friend struct ::capnp::ToDynamic_;
|
||||
template <typename, ::capnp::Kind>
|
||||
friend struct ::capnp::_::PointerHelpers;
|
||||
template <typename, ::capnp::Kind>
|
||||
friend struct ::capnp::List;
|
||||
friend class ::capnp::MessageBuilder;
|
||||
friend class ::capnp::Orphanage;
|
||||
};
|
||||
|
||||
class RecipientId::Builder {
|
||||
public:
|
||||
typedef RecipientId Builds;
|
||||
|
||||
Builder() = delete; // Deleted to discourage incorrect usage.
|
||||
// You can explicitly initialize to nullptr instead.
|
||||
inline Builder(decltype(nullptr)) {}
|
||||
inline explicit Builder(::capnp::_::StructBuilder base): _builder(base) {}
|
||||
inline operator Reader() const { return Reader(_builder.asReader()); }
|
||||
inline Reader asReader() const { return *this; }
|
||||
|
||||
inline ::capnp::MessageSize totalSize() const { return asReader().totalSize(); }
|
||||
#if !CAPNP_LITE
|
||||
inline ::kj::StringTree toString() const { return asReader().toString(); }
|
||||
#endif // !CAPNP_LITE
|
||||
|
||||
private:
|
||||
::capnp::_::StructBuilder _builder;
|
||||
template <typename, ::capnp::Kind>
|
||||
friend struct ::capnp::ToDynamic_;
|
||||
friend class ::capnp::Orphanage;
|
||||
template <typename, ::capnp::Kind>
|
||||
friend struct ::capnp::_::PointerHelpers;
|
||||
};
|
||||
|
||||
#if !CAPNP_LITE
|
||||
class RecipientId::Pipeline {
|
||||
public:
|
||||
typedef RecipientId Pipelines;
|
||||
|
||||
inline Pipeline(decltype(nullptr)): _typeless(nullptr) {}
|
||||
inline explicit Pipeline(::capnp::AnyPointer::Pipeline&& typeless)
|
||||
: _typeless(kj::mv(typeless)) {}
|
||||
|
||||
private:
|
||||
::capnp::AnyPointer::Pipeline _typeless;
|
||||
friend class ::capnp::PipelineHook;
|
||||
template <typename, ::capnp::Kind>
|
||||
friend struct ::capnp::ToDynamic_;
|
||||
};
|
||||
#endif // !CAPNP_LITE
|
||||
|
||||
class ThirdPartyCapId::Reader {
|
||||
public:
|
||||
typedef ThirdPartyCapId Reads;
|
||||
|
||||
Reader() = default;
|
||||
inline explicit Reader(::capnp::_::StructReader base): _reader(base) {}
|
||||
|
||||
inline ::capnp::MessageSize totalSize() const {
|
||||
return _reader.totalSize().asPublic();
|
||||
}
|
||||
|
||||
#if !CAPNP_LITE
|
||||
inline ::kj::StringTree toString() const {
|
||||
return ::capnp::_::structString(_reader, *_capnpPrivate::brand());
|
||||
}
|
||||
#endif // !CAPNP_LITE
|
||||
|
||||
private:
|
||||
::capnp::_::StructReader _reader;
|
||||
template <typename, ::capnp::Kind>
|
||||
friend struct ::capnp::ToDynamic_;
|
||||
template <typename, ::capnp::Kind>
|
||||
friend struct ::capnp::_::PointerHelpers;
|
||||
template <typename, ::capnp::Kind>
|
||||
friend struct ::capnp::List;
|
||||
friend class ::capnp::MessageBuilder;
|
||||
friend class ::capnp::Orphanage;
|
||||
};
|
||||
|
||||
class ThirdPartyCapId::Builder {
|
||||
public:
|
||||
typedef ThirdPartyCapId Builds;
|
||||
|
||||
Builder() = delete; // Deleted to discourage incorrect usage.
|
||||
// You can explicitly initialize to nullptr instead.
|
||||
inline Builder(decltype(nullptr)) {}
|
||||
inline explicit Builder(::capnp::_::StructBuilder base): _builder(base) {}
|
||||
inline operator Reader() const { return Reader(_builder.asReader()); }
|
||||
inline Reader asReader() const { return *this; }
|
||||
|
||||
inline ::capnp::MessageSize totalSize() const { return asReader().totalSize(); }
|
||||
#if !CAPNP_LITE
|
||||
inline ::kj::StringTree toString() const { return asReader().toString(); }
|
||||
#endif // !CAPNP_LITE
|
||||
|
||||
private:
|
||||
::capnp::_::StructBuilder _builder;
|
||||
template <typename, ::capnp::Kind>
|
||||
friend struct ::capnp::ToDynamic_;
|
||||
friend class ::capnp::Orphanage;
|
||||
template <typename, ::capnp::Kind>
|
||||
friend struct ::capnp::_::PointerHelpers;
|
||||
};
|
||||
|
||||
#if !CAPNP_LITE
|
||||
class ThirdPartyCapId::Pipeline {
|
||||
public:
|
||||
typedef ThirdPartyCapId Pipelines;
|
||||
|
||||
inline Pipeline(decltype(nullptr)): _typeless(nullptr) {}
|
||||
inline explicit Pipeline(::capnp::AnyPointer::Pipeline&& typeless)
|
||||
: _typeless(kj::mv(typeless)) {}
|
||||
|
||||
private:
|
||||
::capnp::AnyPointer::Pipeline _typeless;
|
||||
friend class ::capnp::PipelineHook;
|
||||
template <typename, ::capnp::Kind>
|
||||
friend struct ::capnp::ToDynamic_;
|
||||
};
|
||||
#endif // !CAPNP_LITE
|
||||
|
||||
class JoinKeyPart::Reader {
|
||||
public:
|
||||
typedef JoinKeyPart Reads;
|
||||
|
||||
Reader() = default;
|
||||
inline explicit Reader(::capnp::_::StructReader base): _reader(base) {}
|
||||
|
||||
inline ::capnp::MessageSize totalSize() const {
|
||||
return _reader.totalSize().asPublic();
|
||||
}
|
||||
|
||||
#if !CAPNP_LITE
|
||||
inline ::kj::StringTree toString() const {
|
||||
return ::capnp::_::structString(_reader, *_capnpPrivate::brand());
|
||||
}
|
||||
#endif // !CAPNP_LITE
|
||||
|
||||
inline ::uint32_t getJoinId() const;
|
||||
|
||||
inline ::uint16_t getPartCount() const;
|
||||
|
||||
inline ::uint16_t getPartNum() const;
|
||||
|
||||
private:
|
||||
::capnp::_::StructReader _reader;
|
||||
template <typename, ::capnp::Kind>
|
||||
friend struct ::capnp::ToDynamic_;
|
||||
template <typename, ::capnp::Kind>
|
||||
friend struct ::capnp::_::PointerHelpers;
|
||||
template <typename, ::capnp::Kind>
|
||||
friend struct ::capnp::List;
|
||||
friend class ::capnp::MessageBuilder;
|
||||
friend class ::capnp::Orphanage;
|
||||
};
|
||||
|
||||
class JoinKeyPart::Builder {
|
||||
public:
|
||||
typedef JoinKeyPart Builds;
|
||||
|
||||
Builder() = delete; // Deleted to discourage incorrect usage.
|
||||
// You can explicitly initialize to nullptr instead.
|
||||
inline Builder(decltype(nullptr)) {}
|
||||
inline explicit Builder(::capnp::_::StructBuilder base): _builder(base) {}
|
||||
inline operator Reader() const { return Reader(_builder.asReader()); }
|
||||
inline Reader asReader() const { return *this; }
|
||||
|
||||
inline ::capnp::MessageSize totalSize() const { return asReader().totalSize(); }
|
||||
#if !CAPNP_LITE
|
||||
inline ::kj::StringTree toString() const { return asReader().toString(); }
|
||||
#endif // !CAPNP_LITE
|
||||
|
||||
inline ::uint32_t getJoinId();
|
||||
inline void setJoinId( ::uint32_t value);
|
||||
|
||||
inline ::uint16_t getPartCount();
|
||||
inline void setPartCount( ::uint16_t value);
|
||||
|
||||
inline ::uint16_t getPartNum();
|
||||
inline void setPartNum( ::uint16_t value);
|
||||
|
||||
private:
|
||||
::capnp::_::StructBuilder _builder;
|
||||
template <typename, ::capnp::Kind>
|
||||
friend struct ::capnp::ToDynamic_;
|
||||
friend class ::capnp::Orphanage;
|
||||
template <typename, ::capnp::Kind>
|
||||
friend struct ::capnp::_::PointerHelpers;
|
||||
};
|
||||
|
||||
#if !CAPNP_LITE
|
||||
class JoinKeyPart::Pipeline {
|
||||
public:
|
||||
typedef JoinKeyPart Pipelines;
|
||||
|
||||
inline Pipeline(decltype(nullptr)): _typeless(nullptr) {}
|
||||
inline explicit Pipeline(::capnp::AnyPointer::Pipeline&& typeless)
|
||||
: _typeless(kj::mv(typeless)) {}
|
||||
|
||||
private:
|
||||
::capnp::AnyPointer::Pipeline _typeless;
|
||||
friend class ::capnp::PipelineHook;
|
||||
template <typename, ::capnp::Kind>
|
||||
friend struct ::capnp::ToDynamic_;
|
||||
};
|
||||
#endif // !CAPNP_LITE
|
||||
|
||||
class JoinResult::Reader {
|
||||
public:
|
||||
typedef JoinResult Reads;
|
||||
|
||||
Reader() = default;
|
||||
inline explicit Reader(::capnp::_::StructReader base): _reader(base) {}
|
||||
|
||||
inline ::capnp::MessageSize totalSize() const {
|
||||
return _reader.totalSize().asPublic();
|
||||
}
|
||||
|
||||
#if !CAPNP_LITE
|
||||
inline ::kj::StringTree toString() const {
|
||||
return ::capnp::_::structString(_reader, *_capnpPrivate::brand());
|
||||
}
|
||||
#endif // !CAPNP_LITE
|
||||
|
||||
inline ::uint32_t getJoinId() const;
|
||||
|
||||
inline bool getSucceeded() const;
|
||||
|
||||
inline bool hasCap() const;
|
||||
inline ::capnp::AnyPointer::Reader getCap() const;
|
||||
|
||||
private:
|
||||
::capnp::_::StructReader _reader;
|
||||
template <typename, ::capnp::Kind>
|
||||
friend struct ::capnp::ToDynamic_;
|
||||
template <typename, ::capnp::Kind>
|
||||
friend struct ::capnp::_::PointerHelpers;
|
||||
template <typename, ::capnp::Kind>
|
||||
friend struct ::capnp::List;
|
||||
friend class ::capnp::MessageBuilder;
|
||||
friend class ::capnp::Orphanage;
|
||||
};
|
||||
|
||||
class JoinResult::Builder {
|
||||
public:
|
||||
typedef JoinResult Builds;
|
||||
|
||||
Builder() = delete; // Deleted to discourage incorrect usage.
|
||||
// You can explicitly initialize to nullptr instead.
|
||||
inline Builder(decltype(nullptr)) {}
|
||||
inline explicit Builder(::capnp::_::StructBuilder base): _builder(base) {}
|
||||
inline operator Reader() const { return Reader(_builder.asReader()); }
|
||||
inline Reader asReader() const { return *this; }
|
||||
|
||||
inline ::capnp::MessageSize totalSize() const { return asReader().totalSize(); }
|
||||
#if !CAPNP_LITE
|
||||
inline ::kj::StringTree toString() const { return asReader().toString(); }
|
||||
#endif // !CAPNP_LITE
|
||||
|
||||
inline ::uint32_t getJoinId();
|
||||
inline void setJoinId( ::uint32_t value);
|
||||
|
||||
inline bool getSucceeded();
|
||||
inline void setSucceeded(bool value);
|
||||
|
||||
inline bool hasCap();
|
||||
inline ::capnp::AnyPointer::Builder getCap();
|
||||
inline ::capnp::AnyPointer::Builder initCap();
|
||||
|
||||
private:
|
||||
::capnp::_::StructBuilder _builder;
|
||||
template <typename, ::capnp::Kind>
|
||||
friend struct ::capnp::ToDynamic_;
|
||||
friend class ::capnp::Orphanage;
|
||||
template <typename, ::capnp::Kind>
|
||||
friend struct ::capnp::_::PointerHelpers;
|
||||
};
|
||||
|
||||
#if !CAPNP_LITE
|
||||
class JoinResult::Pipeline {
|
||||
public:
|
||||
typedef JoinResult Pipelines;
|
||||
|
||||
inline Pipeline(decltype(nullptr)): _typeless(nullptr) {}
|
||||
inline explicit Pipeline(::capnp::AnyPointer::Pipeline&& typeless)
|
||||
: _typeless(kj::mv(typeless)) {}
|
||||
|
||||
private:
|
||||
::capnp::AnyPointer::Pipeline _typeless;
|
||||
friend class ::capnp::PipelineHook;
|
||||
template <typename, ::capnp::Kind>
|
||||
friend struct ::capnp::ToDynamic_;
|
||||
};
|
||||
#endif // !CAPNP_LITE
|
||||
|
||||
// =======================================================================================
|
||||
|
||||
inline ::capnp::rpc::twoparty::Side VatId::Reader::getSide() const {
|
||||
return _reader.getDataField< ::capnp::rpc::twoparty::Side>(
|
||||
::capnp::bounded<0>() * ::capnp::ELEMENTS);
|
||||
}
|
||||
|
||||
inline ::capnp::rpc::twoparty::Side VatId::Builder::getSide() {
|
||||
return _builder.getDataField< ::capnp::rpc::twoparty::Side>(
|
||||
::capnp::bounded<0>() * ::capnp::ELEMENTS);
|
||||
}
|
||||
inline void VatId::Builder::setSide( ::capnp::rpc::twoparty::Side value) {
|
||||
_builder.setDataField< ::capnp::rpc::twoparty::Side>(
|
||||
::capnp::bounded<0>() * ::capnp::ELEMENTS, value);
|
||||
}
|
||||
|
||||
inline ::uint32_t ProvisionId::Reader::getJoinId() const {
|
||||
return _reader.getDataField< ::uint32_t>(
|
||||
::capnp::bounded<0>() * ::capnp::ELEMENTS);
|
||||
}
|
||||
|
||||
inline ::uint32_t ProvisionId::Builder::getJoinId() {
|
||||
return _builder.getDataField< ::uint32_t>(
|
||||
::capnp::bounded<0>() * ::capnp::ELEMENTS);
|
||||
}
|
||||
inline void ProvisionId::Builder::setJoinId( ::uint32_t value) {
|
||||
_builder.setDataField< ::uint32_t>(
|
||||
::capnp::bounded<0>() * ::capnp::ELEMENTS, value);
|
||||
}
|
||||
|
||||
inline ::uint32_t JoinKeyPart::Reader::getJoinId() const {
|
||||
return _reader.getDataField< ::uint32_t>(
|
||||
::capnp::bounded<0>() * ::capnp::ELEMENTS);
|
||||
}
|
||||
|
||||
inline ::uint32_t JoinKeyPart::Builder::getJoinId() {
|
||||
return _builder.getDataField< ::uint32_t>(
|
||||
::capnp::bounded<0>() * ::capnp::ELEMENTS);
|
||||
}
|
||||
inline void JoinKeyPart::Builder::setJoinId( ::uint32_t value) {
|
||||
_builder.setDataField< ::uint32_t>(
|
||||
::capnp::bounded<0>() * ::capnp::ELEMENTS, value);
|
||||
}
|
||||
|
||||
inline ::uint16_t JoinKeyPart::Reader::getPartCount() const {
|
||||
return _reader.getDataField< ::uint16_t>(
|
||||
::capnp::bounded<2>() * ::capnp::ELEMENTS);
|
||||
}
|
||||
|
||||
inline ::uint16_t JoinKeyPart::Builder::getPartCount() {
|
||||
return _builder.getDataField< ::uint16_t>(
|
||||
::capnp::bounded<2>() * ::capnp::ELEMENTS);
|
||||
}
|
||||
inline void JoinKeyPart::Builder::setPartCount( ::uint16_t value) {
|
||||
_builder.setDataField< ::uint16_t>(
|
||||
::capnp::bounded<2>() * ::capnp::ELEMENTS, value);
|
||||
}
|
||||
|
||||
inline ::uint16_t JoinKeyPart::Reader::getPartNum() const {
|
||||
return _reader.getDataField< ::uint16_t>(
|
||||
::capnp::bounded<3>() * ::capnp::ELEMENTS);
|
||||
}
|
||||
|
||||
inline ::uint16_t JoinKeyPart::Builder::getPartNum() {
|
||||
return _builder.getDataField< ::uint16_t>(
|
||||
::capnp::bounded<3>() * ::capnp::ELEMENTS);
|
||||
}
|
||||
inline void JoinKeyPart::Builder::setPartNum( ::uint16_t value) {
|
||||
_builder.setDataField< ::uint16_t>(
|
||||
::capnp::bounded<3>() * ::capnp::ELEMENTS, value);
|
||||
}
|
||||
|
||||
inline ::uint32_t JoinResult::Reader::getJoinId() const {
|
||||
return _reader.getDataField< ::uint32_t>(
|
||||
::capnp::bounded<0>() * ::capnp::ELEMENTS);
|
||||
}
|
||||
|
||||
inline ::uint32_t JoinResult::Builder::getJoinId() {
|
||||
return _builder.getDataField< ::uint32_t>(
|
||||
::capnp::bounded<0>() * ::capnp::ELEMENTS);
|
||||
}
|
||||
inline void JoinResult::Builder::setJoinId( ::uint32_t value) {
|
||||
_builder.setDataField< ::uint32_t>(
|
||||
::capnp::bounded<0>() * ::capnp::ELEMENTS, value);
|
||||
}
|
||||
|
||||
inline bool JoinResult::Reader::getSucceeded() const {
|
||||
return _reader.getDataField<bool>(
|
||||
::capnp::bounded<32>() * ::capnp::ELEMENTS);
|
||||
}
|
||||
|
||||
inline bool JoinResult::Builder::getSucceeded() {
|
||||
return _builder.getDataField<bool>(
|
||||
::capnp::bounded<32>() * ::capnp::ELEMENTS);
|
||||
}
|
||||
inline void JoinResult::Builder::setSucceeded(bool value) {
|
||||
_builder.setDataField<bool>(
|
||||
::capnp::bounded<32>() * ::capnp::ELEMENTS, value);
|
||||
}
|
||||
|
||||
inline bool JoinResult::Reader::hasCap() const {
|
||||
return !_reader.getPointerField(
|
||||
::capnp::bounded<0>() * ::capnp::POINTERS).isNull();
|
||||
}
|
||||
inline bool JoinResult::Builder::hasCap() {
|
||||
return !_builder.getPointerField(
|
||||
::capnp::bounded<0>() * ::capnp::POINTERS).isNull();
|
||||
}
|
||||
inline ::capnp::AnyPointer::Reader JoinResult::Reader::getCap() const {
|
||||
return ::capnp::AnyPointer::Reader(_reader.getPointerField(
|
||||
::capnp::bounded<0>() * ::capnp::POINTERS));
|
||||
}
|
||||
inline ::capnp::AnyPointer::Builder JoinResult::Builder::getCap() {
|
||||
return ::capnp::AnyPointer::Builder(_builder.getPointerField(
|
||||
::capnp::bounded<0>() * ::capnp::POINTERS));
|
||||
}
|
||||
inline ::capnp::AnyPointer::Builder JoinResult::Builder::initCap() {
|
||||
auto result = ::capnp::AnyPointer::Builder(_builder.getPointerField(
|
||||
::capnp::bounded<0>() * ::capnp::POINTERS));
|
||||
result.clear();
|
||||
return result;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
} // namespace
|
||||
} // namespace
|
||||
|
||||
#endif // CAPNP_INCLUDED_a184c7885cdaf2a1_
|
||||
160
phonelibs/capnp-cpp/include/capnp/rpc-twoparty.h
Normal file
160
phonelibs/capnp-cpp/include/capnp/rpc-twoparty.h
Normal file
@@ -0,0 +1,160 @@
|
||||
// Copyright (c) 2013-2014 Sandstorm Development Group, Inc. and contributors
|
||||
// Licensed under the MIT License:
|
||||
//
|
||||
// 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.
|
||||
|
||||
#ifndef CAPNP_RPC_TWOPARTY_H_
|
||||
#define CAPNP_RPC_TWOPARTY_H_
|
||||
|
||||
#if defined(__GNUC__) && !defined(CAPNP_HEADER_WARNINGS)
|
||||
#pragma GCC system_header
|
||||
#endif
|
||||
|
||||
#include "rpc.h"
|
||||
#include "message.h"
|
||||
#include <kj/async-io.h>
|
||||
#include <capnp/rpc-twoparty.capnp.h>
|
||||
|
||||
namespace capnp {
|
||||
|
||||
namespace rpc {
|
||||
namespace twoparty {
|
||||
typedef VatId SturdyRefHostId; // For backwards-compatibility with version 0.4.
|
||||
}
|
||||
}
|
||||
|
||||
typedef VatNetwork<rpc::twoparty::VatId, rpc::twoparty::ProvisionId,
|
||||
rpc::twoparty::RecipientId, rpc::twoparty::ThirdPartyCapId, rpc::twoparty::JoinResult>
|
||||
TwoPartyVatNetworkBase;
|
||||
|
||||
class TwoPartyVatNetwork: public TwoPartyVatNetworkBase,
|
||||
private TwoPartyVatNetworkBase::Connection {
|
||||
// A `VatNetwork` that consists of exactly two parties communicating over an arbitrary byte
|
||||
// stream. This is used to implement the common case of a client/server network.
|
||||
//
|
||||
// See `ez-rpc.h` for a simple interface for setting up two-party clients and servers.
|
||||
// Use `TwoPartyVatNetwork` only if you need the advanced features.
|
||||
|
||||
public:
|
||||
TwoPartyVatNetwork(kj::AsyncIoStream& stream, rpc::twoparty::Side side,
|
||||
ReaderOptions receiveOptions = ReaderOptions());
|
||||
KJ_DISALLOW_COPY(TwoPartyVatNetwork);
|
||||
|
||||
kj::Promise<void> onDisconnect() { return disconnectPromise.addBranch(); }
|
||||
// Returns a promise that resolves when the peer disconnects.
|
||||
|
||||
rpc::twoparty::Side getSide() { return side; }
|
||||
|
||||
// implements VatNetwork -----------------------------------------------------
|
||||
|
||||
kj::Maybe<kj::Own<TwoPartyVatNetworkBase::Connection>> connect(
|
||||
rpc::twoparty::VatId::Reader ref) override;
|
||||
kj::Promise<kj::Own<TwoPartyVatNetworkBase::Connection>> accept() override;
|
||||
|
||||
private:
|
||||
class OutgoingMessageImpl;
|
||||
class IncomingMessageImpl;
|
||||
|
||||
kj::AsyncIoStream& stream;
|
||||
rpc::twoparty::Side side;
|
||||
MallocMessageBuilder peerVatId;
|
||||
ReaderOptions receiveOptions;
|
||||
bool accepted = false;
|
||||
|
||||
kj::Maybe<kj::Promise<void>> previousWrite;
|
||||
// Resolves when the previous write completes. This effectively serves as the write queue.
|
||||
// Becomes null when shutdown() is called.
|
||||
|
||||
kj::Own<kj::PromiseFulfiller<kj::Own<TwoPartyVatNetworkBase::Connection>>> acceptFulfiller;
|
||||
// Fulfiller for the promise returned by acceptConnectionAsRefHost() on the client side, or the
|
||||
// second call on the server side. Never fulfilled, because there is only one connection.
|
||||
|
||||
kj::ForkedPromise<void> disconnectPromise = nullptr;
|
||||
|
||||
class FulfillerDisposer: public kj::Disposer {
|
||||
// Hack: TwoPartyVatNetwork is both a VatNetwork and a VatNetwork::Connection. When the RPC
|
||||
// system detects (or initiates) a disconnection, it drops its reference to the Connection.
|
||||
// When all references have been dropped, then we want disconnectPromise to be fulfilled.
|
||||
// So we hand out Own<Connection>s with this disposer attached, so that we can detect when
|
||||
// they are dropped.
|
||||
|
||||
public:
|
||||
mutable kj::Own<kj::PromiseFulfiller<void>> fulfiller;
|
||||
mutable uint refcount = 0;
|
||||
|
||||
void disposeImpl(void* pointer) const override;
|
||||
};
|
||||
FulfillerDisposer disconnectFulfiller;
|
||||
|
||||
kj::Own<TwoPartyVatNetworkBase::Connection> asConnection();
|
||||
// Returns a pointer to this with the disposer set to disconnectFulfiller.
|
||||
|
||||
// implements Connection -----------------------------------------------------
|
||||
|
||||
rpc::twoparty::VatId::Reader getPeerVatId() override;
|
||||
kj::Own<OutgoingRpcMessage> newOutgoingMessage(uint firstSegmentWordSize) override;
|
||||
kj::Promise<kj::Maybe<kj::Own<IncomingRpcMessage>>> receiveIncomingMessage() override;
|
||||
kj::Promise<void> shutdown() override;
|
||||
};
|
||||
|
||||
class TwoPartyServer: private kj::TaskSet::ErrorHandler {
|
||||
// Convenience class which implements a simple server which accepts connections on a listener
|
||||
// socket and serices them as two-party connections.
|
||||
|
||||
public:
|
||||
explicit TwoPartyServer(Capability::Client bootstrapInterface);
|
||||
|
||||
void accept(kj::Own<kj::AsyncIoStream>&& connection);
|
||||
// Accepts the connection for servicing.
|
||||
|
||||
kj::Promise<void> listen(kj::ConnectionReceiver& listener);
|
||||
// Listens for connections on the given listener. The returned promise never resolves unless an
|
||||
// exception is thrown while trying to accept. You may discard the returned promise to cancel
|
||||
// listening.
|
||||
|
||||
private:
|
||||
Capability::Client bootstrapInterface;
|
||||
kj::TaskSet tasks;
|
||||
|
||||
struct AcceptedConnection;
|
||||
|
||||
void taskFailed(kj::Exception&& exception) override;
|
||||
};
|
||||
|
||||
class TwoPartyClient {
|
||||
// Convenience class which implements a simple client.
|
||||
|
||||
public:
|
||||
explicit TwoPartyClient(kj::AsyncIoStream& connection);
|
||||
TwoPartyClient(kj::AsyncIoStream& connection, Capability::Client bootstrapInterface,
|
||||
rpc::twoparty::Side side = rpc::twoparty::Side::CLIENT);
|
||||
|
||||
Capability::Client bootstrap();
|
||||
// Get the server's bootstrap interface.
|
||||
|
||||
inline kj::Promise<void> onDisconnect() { return network.onDisconnect(); }
|
||||
|
||||
private:
|
||||
TwoPartyVatNetwork network;
|
||||
RpcSystem<rpc::twoparty::VatId> rpcSystem;
|
||||
};
|
||||
|
||||
} // namespace capnp
|
||||
|
||||
#endif // CAPNP_RPC_TWOPARTY_H_
|
||||
1399
phonelibs/capnp-cpp/include/capnp/rpc.capnp
Normal file
1399
phonelibs/capnp-cpp/include/capnp/rpc.capnp
Normal file
File diff suppressed because it is too large
Load Diff
4898
phonelibs/capnp-cpp/include/capnp/rpc.capnp.h
Normal file
4898
phonelibs/capnp-cpp/include/capnp/rpc.capnp.h
Normal file
File diff suppressed because it is too large
Load Diff
537
phonelibs/capnp-cpp/include/capnp/rpc.h
Normal file
537
phonelibs/capnp-cpp/include/capnp/rpc.h
Normal file
@@ -0,0 +1,537 @@
|
||||
// Copyright (c) 2013-2014 Sandstorm Development Group, Inc. and contributors
|
||||
// Licensed under the MIT License:
|
||||
//
|
||||
// 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.
|
||||
|
||||
#ifndef CAPNP_RPC_H_
|
||||
#define CAPNP_RPC_H_
|
||||
|
||||
#if defined(__GNUC__) && !defined(CAPNP_HEADER_WARNINGS)
|
||||
#pragma GCC system_header
|
||||
#endif
|
||||
|
||||
#include "capability.h"
|
||||
#include "rpc-prelude.h"
|
||||
|
||||
namespace capnp {
|
||||
|
||||
template <typename VatId, typename ProvisionId, typename RecipientId,
|
||||
typename ThirdPartyCapId, typename JoinResult>
|
||||
class VatNetwork;
|
||||
template <typename SturdyRefObjectId>
|
||||
class SturdyRefRestorer;
|
||||
|
||||
template <typename VatId>
|
||||
class BootstrapFactory: public _::BootstrapFactoryBase {
|
||||
// Interface that constructs per-client bootstrap interfaces. Use this if you want each client
|
||||
// who connects to see a different bootstrap interface based on their (authenticated) VatId.
|
||||
// This allows an application to bootstrap off of the authentication performed at the VatNetwork
|
||||
// level. (Typically VatId is some sort of public key.)
|
||||
//
|
||||
// This is only useful for multi-party networks. For TwoPartyVatNetwork, there's no reason to
|
||||
// use a BootstrapFactory; just specify a single bootstrap capability in this case.
|
||||
|
||||
public:
|
||||
virtual Capability::Client createFor(typename VatId::Reader clientId) = 0;
|
||||
// Create a bootstrap capability appropriate for exposing to the given client. VatNetwork will
|
||||
// have authenticated the client VatId before this is called.
|
||||
|
||||
private:
|
||||
Capability::Client baseCreateFor(AnyStruct::Reader clientId) override;
|
||||
};
|
||||
|
||||
template <typename VatId>
|
||||
class RpcSystem: public _::RpcSystemBase {
|
||||
// Represents the RPC system, which is the portal to objects available on the network.
|
||||
//
|
||||
// The RPC implementation sits on top of an implementation of `VatNetwork`. The `VatNetwork`
|
||||
// determines how to form connections between vats -- specifically, two-way, private, reliable,
|
||||
// sequenced datagram connections. The RPC implementation determines how to use such connections
|
||||
// to manage object references and make method calls.
|
||||
//
|
||||
// See `makeRpcServer()` and `makeRpcClient()` below for convenient syntax for setting up an
|
||||
// `RpcSystem` given a `VatNetwork`.
|
||||
//
|
||||
// See `ez-rpc.h` for an even simpler interface for setting up RPC in a typical two-party
|
||||
// client/server scenario.
|
||||
|
||||
public:
|
||||
template <typename ProvisionId, typename RecipientId,
|
||||
typename ThirdPartyCapId, typename JoinResult>
|
||||
RpcSystem(
|
||||
VatNetwork<VatId, ProvisionId, RecipientId, ThirdPartyCapId, JoinResult>& network,
|
||||
kj::Maybe<Capability::Client> bootstrapInterface,
|
||||
kj::Maybe<RealmGateway<>::Client> gateway = nullptr);
|
||||
|
||||
template <typename ProvisionId, typename RecipientId,
|
||||
typename ThirdPartyCapId, typename JoinResult>
|
||||
RpcSystem(
|
||||
VatNetwork<VatId, ProvisionId, RecipientId, ThirdPartyCapId, JoinResult>& network,
|
||||
BootstrapFactory<VatId>& bootstrapFactory,
|
||||
kj::Maybe<RealmGateway<>::Client> gateway = nullptr);
|
||||
|
||||
template <typename ProvisionId, typename RecipientId,
|
||||
typename ThirdPartyCapId, typename JoinResult,
|
||||
typename LocalSturdyRefObjectId>
|
||||
RpcSystem(
|
||||
VatNetwork<VatId, ProvisionId, RecipientId, ThirdPartyCapId, JoinResult>& network,
|
||||
SturdyRefRestorer<LocalSturdyRefObjectId>& restorer);
|
||||
|
||||
RpcSystem(RpcSystem&& other) = default;
|
||||
|
||||
Capability::Client bootstrap(typename VatId::Reader vatId);
|
||||
// Connect to the given vat and return its bootstrap interface.
|
||||
|
||||
Capability::Client restore(typename VatId::Reader hostId, AnyPointer::Reader objectId)
|
||||
KJ_DEPRECATED("Please transition to using a bootstrap interface instead.");
|
||||
// ** DEPRECATED **
|
||||
//
|
||||
// Restores the given SturdyRef from the network and return the capability representing it.
|
||||
//
|
||||
// `hostId` identifies the host from which to request the ref, in the format specified by the
|
||||
// `VatNetwork` in use. `objectId` is the object ID in whatever format is expected by said host.
|
||||
//
|
||||
// This method will be removed in a future version of Cap'n Proto. Instead, please transition
|
||||
// to using bootstrap(), which is equivalent to calling restore() with a null `objectId`.
|
||||
// You may emulate the old concept of object IDs by exporting a bootstrap interface which has
|
||||
// methods that can be used to obtain other capabilities by ID.
|
||||
|
||||
void setFlowLimit(size_t words);
|
||||
// Sets the incoming call flow limit. If more than `words` worth of call messages have not yet
|
||||
// received responses, the RpcSystem will not read further messages from the stream. This can be
|
||||
// used as a crude way to prevent a resource exhaustion attack (or bug) in which a peer makes an
|
||||
// excessive number of simultaneous calls that consume the receiver's RAM.
|
||||
//
|
||||
// There are some caveats. When over the flow limit, all messages are blocked, including returns.
|
||||
// If the outstanding calls are themselves waiting on calls going in the opposite direction, the
|
||||
// flow limit may prevent those calls from completing, leading to deadlock. However, a
|
||||
// sufficiently high limit should make this unlikely.
|
||||
//
|
||||
// Note that a call's parameter size counts against the flow limit until the call returns, even
|
||||
// if the recipient calls releaseParams() to free the parameter memory early. This is because
|
||||
// releaseParams() may simply indicate that the parameters have been forwarded to another
|
||||
// machine, but are still in-memory there. For illustration, say that Alice made a call to Bob
|
||||
// who forwarded the call to Carol. Bob has imposed a flow limit on Alice. Alice's calls are
|
||||
// being forwarded to Carol, so Bob never keeps the parameters in-memory for more than a brief
|
||||
// period. However, the flow limit counts all calls that haven't returned, even if Bob has
|
||||
// already freed the memory they consumed. You might argue that the right solution here is
|
||||
// instead for Carol to impose her own flow limit on Bob. This has a serious problem, though:
|
||||
// Bob might be forwarding requests to Carol on behalf of many different parties, not just Alice.
|
||||
// If Alice can pump enough data to hit the Bob -> Carol flow limit, then those other parties
|
||||
// will be disrupted. Thus, we can only really impose the limit on the Alice -> Bob link, which
|
||||
// only affects Alice. We need that one flow limit to limit Alice's impact on the whole system,
|
||||
// so it has to count all in-flight calls.
|
||||
//
|
||||
// In Sandstorm, flow limits are imposed by the supervisor on calls coming out of a grain, in
|
||||
// order to prevent a grain from inundating the system with in-flight calls. In practice, the
|
||||
// main time this happens is when a grain is pushing a large file download and doesn't implement
|
||||
// proper cooperative flow control.
|
||||
};
|
||||
|
||||
template <typename VatId, typename ProvisionId, typename RecipientId,
|
||||
typename ThirdPartyCapId, typename JoinResult>
|
||||
RpcSystem<VatId> makeRpcServer(
|
||||
VatNetwork<VatId, ProvisionId, RecipientId, ThirdPartyCapId, JoinResult>& network,
|
||||
Capability::Client bootstrapInterface);
|
||||
// Make an RPC server. Typical usage (e.g. in a main() function):
|
||||
//
|
||||
// MyEventLoop eventLoop;
|
||||
// kj::WaitScope waitScope(eventLoop);
|
||||
// MyNetwork network;
|
||||
// MyMainInterface::Client bootstrap = makeMain();
|
||||
// auto server = makeRpcServer(network, bootstrap);
|
||||
// kj::NEVER_DONE.wait(waitScope); // run forever
|
||||
//
|
||||
// See also ez-rpc.h, which has simpler instructions for the common case of a two-party
|
||||
// client-server RPC connection.
|
||||
|
||||
template <typename VatId, typename ProvisionId, typename RecipientId,
|
||||
typename ThirdPartyCapId, typename JoinResult, typename RealmGatewayClient,
|
||||
typename InternalRef = _::InternalRefFromRealmGatewayClient<RealmGatewayClient>,
|
||||
typename ExternalRef = _::ExternalRefFromRealmGatewayClient<RealmGatewayClient>>
|
||||
RpcSystem<VatId> makeRpcServer(
|
||||
VatNetwork<VatId, ProvisionId, RecipientId, ThirdPartyCapId, JoinResult>& network,
|
||||
Capability::Client bootstrapInterface, RealmGatewayClient gateway);
|
||||
// Make an RPC server for a VatNetwork that resides in a different realm from the application.
|
||||
// The given RealmGateway is used to translate SturdyRefs between the app's ("internal") format
|
||||
// and the network's ("external") format.
|
||||
|
||||
template <typename VatId, typename ProvisionId, typename RecipientId,
|
||||
typename ThirdPartyCapId, typename JoinResult>
|
||||
RpcSystem<VatId> makeRpcServer(
|
||||
VatNetwork<VatId, ProvisionId, RecipientId, ThirdPartyCapId, JoinResult>& network,
|
||||
BootstrapFactory<VatId>& bootstrapFactory);
|
||||
// Make an RPC server that can serve different bootstrap interfaces to different clients via a
|
||||
// BootstrapInterface.
|
||||
|
||||
template <typename VatId, typename ProvisionId, typename RecipientId,
|
||||
typename ThirdPartyCapId, typename JoinResult, typename RealmGatewayClient,
|
||||
typename InternalRef = _::InternalRefFromRealmGatewayClient<RealmGatewayClient>,
|
||||
typename ExternalRef = _::ExternalRefFromRealmGatewayClient<RealmGatewayClient>>
|
||||
RpcSystem<VatId> makeRpcServer(
|
||||
VatNetwork<VatId, ProvisionId, RecipientId, ThirdPartyCapId, JoinResult>& network,
|
||||
BootstrapFactory<VatId>& bootstrapFactory, RealmGatewayClient gateway);
|
||||
// Make an RPC server that can serve different bootstrap interfaces to different clients via a
|
||||
// BootstrapInterface and communicates with a different realm than the application is in via a
|
||||
// RealmGateway.
|
||||
|
||||
template <typename VatId, typename LocalSturdyRefObjectId,
|
||||
typename ProvisionId, typename RecipientId, typename ThirdPartyCapId, typename JoinResult>
|
||||
RpcSystem<VatId> makeRpcServer(
|
||||
VatNetwork<VatId, ProvisionId, RecipientId, ThirdPartyCapId, JoinResult>& network,
|
||||
SturdyRefRestorer<LocalSturdyRefObjectId>& restorer)
|
||||
KJ_DEPRECATED("Please transition to using a bootstrap interface instead.");
|
||||
// ** DEPRECATED **
|
||||
//
|
||||
// Create an RPC server which exports multiple main interfaces by object ID. The `restorer` object
|
||||
// can be used to look up objects by ID.
|
||||
//
|
||||
// Please transition to exporting only one interface, which is known as the "bootstrap" interface.
|
||||
// For backwards-compatibility with old clients, continue to implement SturdyRefRestorer, but
|
||||
// return the new bootstrap interface when the request object ID is null. When new clients connect
|
||||
// and request the bootstrap interface, they will get that interface. Eventually, once all clients
|
||||
// are updated to request only the bootstrap interface, stop implementing SturdyRefRestorer and
|
||||
// switch to passing the bootstrap capability itself as the second parameter to `makeRpcServer()`.
|
||||
|
||||
template <typename VatId, typename ProvisionId,
|
||||
typename RecipientId, typename ThirdPartyCapId, typename JoinResult>
|
||||
RpcSystem<VatId> makeRpcClient(
|
||||
VatNetwork<VatId, ProvisionId, RecipientId, ThirdPartyCapId, JoinResult>& network);
|
||||
// Make an RPC client. Typical usage (e.g. in a main() function):
|
||||
//
|
||||
// MyEventLoop eventLoop;
|
||||
// kj::WaitScope waitScope(eventLoop);
|
||||
// MyNetwork network;
|
||||
// auto client = makeRpcClient(network);
|
||||
// MyCapability::Client cap = client.restore(hostId, objId).castAs<MyCapability>();
|
||||
// auto response = cap.fooRequest().send().wait(waitScope);
|
||||
// handleMyResponse(response);
|
||||
//
|
||||
// See also ez-rpc.h, which has simpler instructions for the common case of a two-party
|
||||
// client-server RPC connection.
|
||||
|
||||
template <typename VatId, typename ProvisionId, typename RecipientId,
|
||||
typename ThirdPartyCapId, typename JoinResult, typename RealmGatewayClient,
|
||||
typename InternalRef = _::InternalRefFromRealmGatewayClient<RealmGatewayClient>,
|
||||
typename ExternalRef = _::ExternalRefFromRealmGatewayClient<RealmGatewayClient>>
|
||||
RpcSystem<VatId> makeRpcClient(
|
||||
VatNetwork<VatId, ProvisionId, RecipientId, ThirdPartyCapId, JoinResult>& network,
|
||||
RealmGatewayClient gateway);
|
||||
// Make an RPC client for a VatNetwork that resides in a different realm from the application.
|
||||
// The given RealmGateway is used to translate SturdyRefs between the app's ("internal") format
|
||||
// and the network's ("external") format.
|
||||
|
||||
template <typename SturdyRefObjectId>
|
||||
class SturdyRefRestorer: public _::SturdyRefRestorerBase {
|
||||
// ** DEPRECATED **
|
||||
//
|
||||
// In Cap'n Proto 0.4.x, applications could export multiple main interfaces identified by
|
||||
// object IDs. The callback used to map object IDs to objects was `SturdyRefRestorer`, as we
|
||||
// imagined this would eventually be used for restoring SturdyRefs as well. In practice, it was
|
||||
// never used for real SturdyRefs, only for exporting singleton objects under well-known names.
|
||||
//
|
||||
// The new preferred strategy is to export only a _single_ such interface, called the
|
||||
// "bootstrap interface". That interface can itself have methods for obtaining other objects, of
|
||||
// course, but that is up to the app. `SturdyRefRestorer` exists for backwards-compatibility.
|
||||
//
|
||||
// Hint: Use SturdyRefRestorer<capnp::Text> to define a server that exports services under
|
||||
// string names.
|
||||
|
||||
public:
|
||||
virtual Capability::Client restore(typename SturdyRefObjectId::Reader ref)
|
||||
KJ_DEPRECATED(
|
||||
"Please transition to using bootstrap interfaces instead of SturdyRefRestorer.") = 0;
|
||||
// Restore the given object, returning a capability representing it.
|
||||
|
||||
private:
|
||||
Capability::Client baseRestore(AnyPointer::Reader ref) override final;
|
||||
};
|
||||
|
||||
// =======================================================================================
|
||||
// VatNetwork
|
||||
|
||||
class OutgoingRpcMessage {
|
||||
// A message to be sent by a `VatNetwork`.
|
||||
|
||||
public:
|
||||
virtual AnyPointer::Builder getBody() = 0;
|
||||
// Get the message body, which the caller may fill in any way it wants. (The standard RPC
|
||||
// implementation initializes it as a Message as defined in rpc.capnp.)
|
||||
|
||||
virtual void send() = 0;
|
||||
// Send the message, or at least put it in a queue to be sent later. Note that the builder
|
||||
// returned by `getBody()` remains valid at least until the `OutgoingRpcMessage` is destroyed.
|
||||
};
|
||||
|
||||
class IncomingRpcMessage {
|
||||
// A message received from a `VatNetwork`.
|
||||
|
||||
public:
|
||||
virtual AnyPointer::Reader getBody() = 0;
|
||||
// Get the message body, to be interpreted by the caller. (The standard RPC implementation
|
||||
// interprets it as a Message as defined in rpc.capnp.)
|
||||
};
|
||||
|
||||
template <typename VatId, typename ProvisionId, typename RecipientId,
|
||||
typename ThirdPartyCapId, typename JoinResult>
|
||||
class VatNetwork: public _::VatNetworkBase {
|
||||
// Cap'n Proto RPC operates between vats, where a "vat" is some sort of host of objects.
|
||||
// Typically one Cap'n Proto process (in the Unix sense) is one vat. The RPC system is what
|
||||
// allows calls between objects hosted in different vats.
|
||||
//
|
||||
// The RPC implementation sits on top of an implementation of `VatNetwork`. The `VatNetwork`
|
||||
// determines how to form connections between vats -- specifically, two-way, private, reliable,
|
||||
// sequenced datagram connections. The RPC implementation determines how to use such connections
|
||||
// to manage object references and make method calls.
|
||||
//
|
||||
// The most common implementation of VatNetwork is TwoPartyVatNetwork (rpc-twoparty.h). Most
|
||||
// simple client-server apps will want to use it. (You may even want to use the EZ RPC
|
||||
// interfaces in `ez-rpc.h` and avoid all of this.)
|
||||
//
|
||||
// TODO(someday): Provide a standard implementation for the public internet.
|
||||
|
||||
public:
|
||||
class Connection;
|
||||
|
||||
struct ConnectionAndProvisionId {
|
||||
// Result of connecting to a vat introduced by another vat.
|
||||
|
||||
kj::Own<Connection> connection;
|
||||
// Connection to the new vat.
|
||||
|
||||
kj::Own<OutgoingRpcMessage> firstMessage;
|
||||
// An already-allocated `OutgoingRpcMessage` associated with `connection`. The RPC system will
|
||||
// construct this as an `Accept` message and send it.
|
||||
|
||||
Orphan<ProvisionId> provisionId;
|
||||
// A `ProvisionId` already allocated inside `firstMessage`, which the RPC system will use to
|
||||
// build the `Accept` message.
|
||||
};
|
||||
|
||||
class Connection: public _::VatNetworkBase::Connection {
|
||||
// A two-way RPC connection.
|
||||
//
|
||||
// This object may represent a connection that doesn't exist yet, but is expected to exist
|
||||
// in the future. In this case, sent messages will automatically be queued and sent once the
|
||||
// connection is ready, so that the caller doesn't need to know the difference.
|
||||
|
||||
public:
|
||||
// Level 0 features ----------------------------------------------
|
||||
|
||||
virtual typename VatId::Reader getPeerVatId() = 0;
|
||||
// Returns the connected vat's authenticated VatId. It is the VatNetwork's responsibility to
|
||||
// authenticate this, so that the caller can be assured that they are really talking to the
|
||||
// identified vat and not an imposter.
|
||||
|
||||
virtual kj::Own<OutgoingRpcMessage> newOutgoingMessage(uint firstSegmentWordSize) override = 0;
|
||||
// Allocate a new message to be sent on this connection.
|
||||
//
|
||||
// If `firstSegmentWordSize` is non-zero, it should be treated as a hint suggesting how large
|
||||
// to make the first segment. This is entirely a hint and the connection may adjust it up or
|
||||
// down. If it is zero, the connection should choose the size itself.
|
||||
|
||||
virtual kj::Promise<kj::Maybe<kj::Own<IncomingRpcMessage>>> receiveIncomingMessage() override = 0;
|
||||
// Wait for a message to be received and return it. If the read stream cleanly terminates,
|
||||
// return null. If any other problem occurs, throw an exception.
|
||||
|
||||
virtual kj::Promise<void> shutdown() override KJ_WARN_UNUSED_RESULT = 0;
|
||||
// Waits until all outgoing messages have been sent, then shuts down the outgoing stream. The
|
||||
// returned promise resolves after shutdown is complete.
|
||||
|
||||
private:
|
||||
AnyStruct::Reader baseGetPeerVatId() override;
|
||||
};
|
||||
|
||||
// Level 0 features ------------------------------------------------
|
||||
|
||||
virtual kj::Maybe<kj::Own<Connection>> connect(typename VatId::Reader hostId) = 0;
|
||||
// Connect to a VatId. Note that this method immediately returns a `Connection`, even
|
||||
// if the network connection has not yet been established. Messages can be queued to this
|
||||
// connection and will be delivered once it is open. The caller must attempt to read from the
|
||||
// connection to verify that it actually succeeded; the read will fail if the connection
|
||||
// couldn't be opened. Some network implementations may actually start sending messages before
|
||||
// hearing back from the server at all, to avoid a round trip.
|
||||
//
|
||||
// Returns nullptr if `hostId` refers to the local host.
|
||||
|
||||
virtual kj::Promise<kj::Own<Connection>> accept() = 0;
|
||||
// Wait for the next incoming connection and return it.
|
||||
|
||||
// Level 4 features ------------------------------------------------
|
||||
// TODO(someday)
|
||||
|
||||
private:
|
||||
kj::Maybe<kj::Own<_::VatNetworkBase::Connection>>
|
||||
baseConnect(AnyStruct::Reader hostId) override final;
|
||||
kj::Promise<kj::Own<_::VatNetworkBase::Connection>> baseAccept() override final;
|
||||
};
|
||||
|
||||
// =======================================================================================
|
||||
// ***************************************************************************************
|
||||
// Inline implementation details start here
|
||||
// ***************************************************************************************
|
||||
// =======================================================================================
|
||||
|
||||
template <typename VatId>
|
||||
Capability::Client BootstrapFactory<VatId>::baseCreateFor(AnyStruct::Reader clientId) {
|
||||
return createFor(clientId.as<VatId>());
|
||||
}
|
||||
|
||||
template <typename SturdyRef, typename ProvisionId, typename RecipientId,
|
||||
typename ThirdPartyCapId, typename JoinResult>
|
||||
kj::Maybe<kj::Own<_::VatNetworkBase::Connection>>
|
||||
VatNetwork<SturdyRef, ProvisionId, RecipientId, ThirdPartyCapId, JoinResult>::
|
||||
baseConnect(AnyStruct::Reader ref) {
|
||||
auto maybe = connect(ref.as<SturdyRef>());
|
||||
return maybe.map([](kj::Own<Connection>& conn) -> kj::Own<_::VatNetworkBase::Connection> {
|
||||
return kj::mv(conn);
|
||||
});
|
||||
}
|
||||
|
||||
template <typename SturdyRef, typename ProvisionId, typename RecipientId,
|
||||
typename ThirdPartyCapId, typename JoinResult>
|
||||
kj::Promise<kj::Own<_::VatNetworkBase::Connection>>
|
||||
VatNetwork<SturdyRef, ProvisionId, RecipientId, ThirdPartyCapId, JoinResult>::baseAccept() {
|
||||
return accept().then(
|
||||
[](kj::Own<Connection>&& connection) -> kj::Own<_::VatNetworkBase::Connection> {
|
||||
return kj::mv(connection);
|
||||
});
|
||||
}
|
||||
|
||||
template <typename SturdyRef, typename ProvisionId, typename RecipientId,
|
||||
typename ThirdPartyCapId, typename JoinResult>
|
||||
AnyStruct::Reader VatNetwork<
|
||||
SturdyRef, ProvisionId, RecipientId, ThirdPartyCapId, JoinResult>::
|
||||
Connection::baseGetPeerVatId() {
|
||||
return getPeerVatId();
|
||||
}
|
||||
|
||||
template <typename SturdyRef>
|
||||
Capability::Client SturdyRefRestorer<SturdyRef>::baseRestore(AnyPointer::Reader ref) {
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
|
||||
return restore(ref.getAs<SturdyRef>());
|
||||
#pragma GCC diagnostic pop
|
||||
}
|
||||
|
||||
template <typename VatId>
|
||||
template <typename ProvisionId, typename RecipientId,
|
||||
typename ThirdPartyCapId, typename JoinResult>
|
||||
RpcSystem<VatId>::RpcSystem(
|
||||
VatNetwork<VatId, ProvisionId, RecipientId, ThirdPartyCapId, JoinResult>& network,
|
||||
kj::Maybe<Capability::Client> bootstrap,
|
||||
kj::Maybe<RealmGateway<>::Client> gateway)
|
||||
: _::RpcSystemBase(network, kj::mv(bootstrap), kj::mv(gateway)) {}
|
||||
|
||||
template <typename VatId>
|
||||
template <typename ProvisionId, typename RecipientId,
|
||||
typename ThirdPartyCapId, typename JoinResult>
|
||||
RpcSystem<VatId>::RpcSystem(
|
||||
VatNetwork<VatId, ProvisionId, RecipientId, ThirdPartyCapId, JoinResult>& network,
|
||||
BootstrapFactory<VatId>& bootstrapFactory,
|
||||
kj::Maybe<RealmGateway<>::Client> gateway)
|
||||
: _::RpcSystemBase(network, bootstrapFactory, kj::mv(gateway)) {}
|
||||
|
||||
template <typename VatId>
|
||||
template <typename ProvisionId, typename RecipientId,
|
||||
typename ThirdPartyCapId, typename JoinResult,
|
||||
typename LocalSturdyRefObjectId>
|
||||
RpcSystem<VatId>::RpcSystem(
|
||||
VatNetwork<VatId, ProvisionId, RecipientId, ThirdPartyCapId, JoinResult>& network,
|
||||
SturdyRefRestorer<LocalSturdyRefObjectId>& restorer)
|
||||
: _::RpcSystemBase(network, restorer) {}
|
||||
|
||||
template <typename VatId>
|
||||
Capability::Client RpcSystem<VatId>::bootstrap(typename VatId::Reader vatId) {
|
||||
return baseBootstrap(_::PointerHelpers<VatId>::getInternalReader(vatId));
|
||||
}
|
||||
|
||||
template <typename VatId>
|
||||
Capability::Client RpcSystem<VatId>::restore(
|
||||
typename VatId::Reader hostId, AnyPointer::Reader objectId) {
|
||||
return baseRestore(_::PointerHelpers<VatId>::getInternalReader(hostId), objectId);
|
||||
}
|
||||
|
||||
template <typename VatId>
|
||||
inline void RpcSystem<VatId>::setFlowLimit(size_t words) {
|
||||
baseSetFlowLimit(words);
|
||||
}
|
||||
|
||||
template <typename VatId, typename ProvisionId, typename RecipientId,
|
||||
typename ThirdPartyCapId, typename JoinResult>
|
||||
RpcSystem<VatId> makeRpcServer(
|
||||
VatNetwork<VatId, ProvisionId, RecipientId, ThirdPartyCapId, JoinResult>& network,
|
||||
Capability::Client bootstrapInterface) {
|
||||
return RpcSystem<VatId>(network, kj::mv(bootstrapInterface));
|
||||
}
|
||||
|
||||
template <typename VatId, typename ProvisionId, typename RecipientId,
|
||||
typename ThirdPartyCapId, typename JoinResult,
|
||||
typename RealmGatewayClient, typename InternalRef, typename ExternalRef>
|
||||
RpcSystem<VatId> makeRpcServer(
|
||||
VatNetwork<VatId, ProvisionId, RecipientId, ThirdPartyCapId, JoinResult>& network,
|
||||
Capability::Client bootstrapInterface, RealmGatewayClient gateway) {
|
||||
return RpcSystem<VatId>(network, kj::mv(bootstrapInterface),
|
||||
gateway.template castAs<RealmGateway<>>());
|
||||
}
|
||||
|
||||
template <typename VatId, typename ProvisionId, typename RecipientId,
|
||||
typename ThirdPartyCapId, typename JoinResult>
|
||||
RpcSystem<VatId> makeRpcServer(
|
||||
VatNetwork<VatId, ProvisionId, RecipientId, ThirdPartyCapId, JoinResult>& network,
|
||||
BootstrapFactory<VatId>& bootstrapFactory) {
|
||||
return RpcSystem<VatId>(network, bootstrapFactory);
|
||||
}
|
||||
|
||||
template <typename VatId, typename ProvisionId, typename RecipientId,
|
||||
typename ThirdPartyCapId, typename JoinResult,
|
||||
typename RealmGatewayClient, typename InternalRef, typename ExternalRef>
|
||||
RpcSystem<VatId> makeRpcServer(
|
||||
VatNetwork<VatId, ProvisionId, RecipientId, ThirdPartyCapId, JoinResult>& network,
|
||||
BootstrapFactory<VatId>& bootstrapFactory, RealmGatewayClient gateway) {
|
||||
return RpcSystem<VatId>(network, bootstrapFactory, gateway.template castAs<RealmGateway<>>());
|
||||
}
|
||||
|
||||
template <typename VatId, typename LocalSturdyRefObjectId,
|
||||
typename ProvisionId, typename RecipientId, typename ThirdPartyCapId, typename JoinResult>
|
||||
RpcSystem<VatId> makeRpcServer(
|
||||
VatNetwork<VatId, ProvisionId, RecipientId, ThirdPartyCapId, JoinResult>& network,
|
||||
SturdyRefRestorer<LocalSturdyRefObjectId>& restorer) {
|
||||
return RpcSystem<VatId>(network, restorer);
|
||||
}
|
||||
|
||||
template <typename VatId, typename ProvisionId,
|
||||
typename RecipientId, typename ThirdPartyCapId, typename JoinResult>
|
||||
RpcSystem<VatId> makeRpcClient(
|
||||
VatNetwork<VatId, ProvisionId, RecipientId, ThirdPartyCapId, JoinResult>& network) {
|
||||
return RpcSystem<VatId>(network, nullptr);
|
||||
}
|
||||
|
||||
template <typename VatId, typename ProvisionId,
|
||||
typename RecipientId, typename ThirdPartyCapId, typename JoinResult,
|
||||
typename RealmGatewayClient, typename InternalRef, typename ExternalRef>
|
||||
RpcSystem<VatId> makeRpcClient(
|
||||
VatNetwork<VatId, ProvisionId, RecipientId, ThirdPartyCapId, JoinResult>& network,
|
||||
RealmGatewayClient gateway) {
|
||||
return RpcSystem<VatId>(network, nullptr, gateway.template castAs<RealmGateway<>>());
|
||||
}
|
||||
|
||||
} // namespace capnp
|
||||
|
||||
#endif // CAPNP_RPC_H_
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user