diff --git a/VNode/.editorconfig b/VNode/.editorconfig new file mode 100644 index 00000000..7053c49a --- /dev/null +++ b/VNode/.editorconfig @@ -0,0 +1,5 @@ +[*.{js,jsx,ts,tsx,vue}] +indent_style = space +indent_size = 2 +trim_trailing_whitespace = true +insert_final_newline = true diff --git a/VNode/.eslintrc.cjs b/VNode/.eslintrc.cjs new file mode 100644 index 00000000..0178f73a --- /dev/null +++ b/VNode/.eslintrc.cjs @@ -0,0 +1,10 @@ +/* eslint-env node */ +require('@rushstack/eslint-patch/modern-module-resolution') + +module.exports = { + root: true, + 'extends': [ 'plugin:vue/vue3-essential', 'eslint:recommended', '@vue/eslint-config-prettier/skip-formatting' + ], + parserOptions: { ecmaVersion: 'latest' + } +} diff --git a/VNode/.gitignore b/VNode/.gitignore new file mode 100644 index 00000000..ac70cb2c --- /dev/null +++ b/VNode/.gitignore @@ -0,0 +1,34 @@ +# Logs +logs +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* +pnpm-debug.log* +lerna-debug.log* + +node_modules +.DS_Store +dist +dist-ssr +coverage +*.local + +/cypress/videos/ +/cypress/screenshots/ + +# Editor directories and files +.vscode/* +!.vscode/extensions.json +.idea +*.suo +*.ntvs* +*.njsproj +*.sln +*.sw? + +*.tsbuildinfo + +# Local configuration file +/src/config.js +/components.d.ts diff --git a/VNode/.prettierrc.json b/VNode/.prettierrc.json new file mode 100644 index 00000000..66e23359 --- /dev/null +++ b/VNode/.prettierrc.json @@ -0,0 +1,8 @@ +{ + "$schema": "https://json.schemastore.org/prettierrc", + "semi": false, + "tabWidth": 2, + "singleQuote": true, + "printWidth": 100, + "trailingComma": "none" +} \ No newline at end of file diff --git a/VNode/_software_lib/nanomq-0.22.10/bin/libwinpthread-1.dll b/VNode/_software_lib/nanomq-0.22.10/bin/libwinpthread-1.dll new file mode 100644 index 00000000..e0649d7c Binary files /dev/null and b/VNode/_software_lib/nanomq-0.22.10/bin/libwinpthread-1.dll differ diff --git a/VNode/_software_lib/nanomq-0.22.10/bin/nanomq.conf b/VNode/_software_lib/nanomq-0.22.10/bin/nanomq.conf new file mode 100644 index 00000000..e8b57e9d --- /dev/null +++ b/VNode/_software_lib/nanomq-0.22.10/bin/nanomq.conf @@ -0,0 +1,59 @@ +# NanoMQ Configuration 0.18.0 + +# #============================================================ +# # NanoMQ Broker +# #============================================================ + +mqtt { + property_size = 32 + max_packet_size = 260MB + max_mqueue_len = 2048 + retry_interval = 10s + keepalive_multiplier = 1.25 + + # Three of below, unsupported now + max_inflight_window = 2048 + max_awaiting_rel = 10s + await_rel_timeout = 10s +} + +listeners.tcp { + bind = "192.168.1.30:1883" +} + +listeners.ws { + bind = "192.168.1.30:9001" +} + +http_server { + port = 8081 + limit_conn = 2 + username = admin + password = public + auth_type = basic + jwt { + public.keyfile = "/etc/certs/jwt/jwtRS256.key.pub" + } +} + +log { + to = [file, console] + level = warn + dir = "/tmp" + file = "nanomq.log" + rotation { + size = 10MB + count = 5 + } +} + +auth { + allow_anonymous = true + no_match = allow + deny_action = ignore + + cache = { + max_size = 32 + ttl = 1m + } +} diff --git a/VNode/_software_lib/nanomq-0.22.10/bin/nanomq.exe b/VNode/_software_lib/nanomq-0.22.10/bin/nanomq.exe new file mode 100644 index 00000000..11f94d46 Binary files /dev/null and b/VNode/_software_lib/nanomq-0.22.10/bin/nanomq.exe differ diff --git a/VNode/_software_lib/nanomq-0.22.10/bin/nanomq_cli.exe b/VNode/_software_lib/nanomq-0.22.10/bin/nanomq_cli.exe new file mode 100644 index 00000000..ce6bcddf Binary files /dev/null and b/VNode/_software_lib/nanomq-0.22.10/bin/nanomq_cli.exe differ diff --git a/VNode/_software_lib/nanomq-0.22.10/bin/nngcat.exe b/VNode/_software_lib/nanomq-0.22.10/bin/nngcat.exe new file mode 100644 index 00000000..2505d321 Binary files /dev/null and b/VNode/_software_lib/nanomq-0.22.10/bin/nngcat.exe differ diff --git a/VNode/_software_lib/nanomq-0.22.10/bin/start.bat b/VNode/_software_lib/nanomq-0.22.10/bin/start.bat new file mode 100644 index 00000000..fdffb92d --- /dev/null +++ b/VNode/_software_lib/nanomq-0.22.10/bin/start.bat @@ -0,0 +1 @@ +.\nanomq.exe start --conf .\nanomq.conf \ No newline at end of file diff --git a/VNode/_software_lib/nanomq-0.22.10/config/nanomq.conf b/VNode/_software_lib/nanomq-0.22.10/config/nanomq.conf new file mode 100644 index 00000000..52c09c90 --- /dev/null +++ b/VNode/_software_lib/nanomq-0.22.10/config/nanomq.conf @@ -0,0 +1,71 @@ +# NanoMQ Configuration 0.18.0 + +# #============================================================ +# # NanoMQ Broker +# #============================================================ + +mqtt { + property_size = 32 + max_packet_size = 260MB + max_mqueue_len = 2048 + retry_interval = 10s + keepalive_multiplier = 1.25 + + # Three of below, unsupported now + max_inflight_window = 2048 + max_awaiting_rel = 10s + await_rel_timeout = 10s +} + +listeners.tcp { + bind = "0.0.0.0:1883" +} + +# listeners.ssl { +# bind = "0.0.0.0:8883" +# keyfile = "/etc/certs/key.pem" +# certfile = "/etc/certs/cert.pem" +# cacertfile = "/etc/certs/cacert.pem" +# verify_peer = false +# fail_if_no_peer_cert = false +# } + +listeners.ws { + bind = "0.0.0.0:9001" +} + +http_server { + port = 8081 + limit_conn = 2 + username = admin + password = public + auth_type = basic + jwt { + public.keyfile = "/etc/certs/jwt/jwtRS256.key.pub" + } +} + +log { + to = [file, console] + level = warn + dir = "/tmp" + file = "nanomq.log" + rotation { + size = 10MB + count = 5 + } +} + +auth { + allow_anonymous = true + no_match = allow + deny_action = ignore + + cache = { + max_size = 32 + ttl = 1m + } + + # password = {include "/etc/nanomq_pwd.conf"} + # acl = {include "/etc/nanomq_acl.conf"} +} diff --git a/VNode/_software_lib/nanomq-0.22.10/config/nanomq_acl.conf b/VNode/_software_lib/nanomq-0.22.10/config/nanomq_acl.conf new file mode 100644 index 00000000..ce8a52f8 --- /dev/null +++ b/VNode/_software_lib/nanomq-0.22.10/config/nanomq_acl.conf @@ -0,0 +1,14 @@ +# #==================================================================== +# # Configuration for Acl +# #==================================================================== + +rules = [ + # # Allow MQTT client using username "dashboard" to subscribe to "$SYS/#" topics + {"permit": "allow", "username": "dashboard", "action": "subscribe", "topics": ["$SYS/#"]} + + # # Deny "All Users" subscribe to "$SYS/#" "#" Topics + # {"permit": "deny", "username": "#", "action": "subscribe", "topics": ["$SYS/#", "#"]} + + # # Allow any other publish/subscribe operation + {"permit": "allow"} +] \ No newline at end of file diff --git a/VNode/_software_lib/nanomq-0.22.10/config/nanomq_bridge.conf b/VNode/_software_lib/nanomq-0.22.10/config/nanomq_bridge.conf new file mode 100644 index 00000000..2cbe5fbe --- /dev/null +++ b/VNode/_software_lib/nanomq-0.22.10/config/nanomq_bridge.conf @@ -0,0 +1,399 @@ +# #==================================================================== +# # MQTT Broker Bridge +# #==================================================================== + +bridges.mqtt.emqx1 { + # # Bridge address: host:port . + # # + # # Value: String + # # Example: mqtt-tcp://127.0.0.1:1883 + # # tls+mqtt-tcp://127.0.0.1:8883 + # # mqtt-quic://54.75.171.11:14567 + + server = "mqtt-tcp://127.0.0.1:1883" + # # Protocol version of the bridge. + # # + # # Value: Enum + # # - 5: mqttv5 + # # - 4: mqttv311 + # # - 3: mqttv31 + proto_ver = 4 + # # The ClientId of a remote bridge. + # # Default random string. + # # + # # Value: String + # clientid="bridge_client" + + # # Ping: interval of a downward bridge. + # # + # # Value: Duration + # # Default: 10 seconds + keepalive = 60s + # # The maximum backoff timeout. + # # Reconnect after no more than backoff_max when bridge connection lost. + # # + # # Value: Duration + # # Default: 60s + backoff_max = 60s + # # The Clean start flag of a remote bridge. + # # + # # Value: boolean + # # Default: false + # # + # # NOTE: Some IoT platforms require clean_start + # # must be set to 'true' + clean_start = false + # # The username for a remote bridge. + # # + # # Value: String + username = username + # # The password for a remote bridge. + # # + # # Value: String + password = passwd + + # # Properties for MQTT V5 + conn_properties = { + # # Maximum Packet Size + # # + # # If the Maximum Packet Size is not present, no limit on the packet size is imposed beyond + # # the limitations in the protocol as a result of the remaining length encoding and the protocol header sizes. + # # Value: 1 ~ 4294967295 + maximum_packet_size = 1024 + + # # Receive Maximum + # # + # # The Client uses this value to limit the number of QoS 1 and QoS 2 publications that it is willing to process concurrently. + # # There is no mechanism to limit the QoS 0 publications that the Server might try to send. + # # The value of Receive Maximum applies only to the current Network Connection. + # # If the Receive Maximum value is absent then its value defaults to 65,535. + # # + # # Value: 1 ~ 65535 + receive_maximum = 65535 + + # # Topic Alias Maximum + # # + # # If the Topic Alias Maximum property is absent, the default value is 0. + # # This value indicates the highest value that the Client will accept as a Topic Alias sent by the Server. + # # The Client uses this value to limit the number of Topic Aliases that it is willing to hold on this Connection. + # # Default: 0 + # # Value: 0 ~ 65535 + topic_alias_maximum = 0 + + # # Request Problem Information + # # + # # If the Request Problem Information is absent, the value of 1 is used. + # # The Client uses this value to indicate whether the Reason String or User Properties are sent in the case of failures. + # # If the value of Request Problem Information is 0, the Server MAY return a Reason String or User Properties on a CONNACK or DISCONNECT packet, + # # but MUST NOT send a Reason String or User Properties on any packet other than PUBLISH, CONNACK, or DISCONNECT. + # # If the value is 0 and the Client receives a Reason String or User Properties in a packet other than PUBLISH, CONNACK, or DISCONNECT, + # # it uses a DISCONNECT packet with Reason Code 0x82 (Protocol Error) as described in section 4.13 Handling errors. + # # If this value is 1, the Server MAY return a Reason String or User Properties on any packet where it is allowed. + # # + # # Default: 1 + # # Value: 0 | 1 + request_problem_infomation = 1 + + # # Request Response Information + # # + # # If the Request Response Information is absent, the value of 0 is used. + # # The Client uses this value to request the Server to return Response Information in the CONNACK. + # # A value of 0 indicates that the Server MUST NOT return Response Information. + # # If the value is 1 the Server MAY return Response Information in the CONNACK packet. + # # + # # Default: 0 + # # Value: 0 | 1 + request_response_infomation = 0 + + # # Session Expiry Interval + # # + # # If the Session Expiry Interval is absent the value 0 is used. + # # If it is set to 0, or is absent, the Session ends when the Network Connection is closed. + # # If the Session Expiry Interval is 4294967295 (UINT_MAX), the Session does not expire. + # # + # # Value: 0 ~ 4294967295 + session_expiry_interval = 0 + + # # User Property + # # + # # The User Property is allowed to appear multiple times to represent multiple name, value pairs. + # # The same name is allowed to appear more than once. + # # Value: Map[key(String) - value(String)] + user_property = { + key1 = value1 + key2 = value2 + } + } + + will { + # # Will topic + topic = "will_topic" + # # Will QoS + qos = 1 + # # Will paylad retain flag + retain = false + # # Will payload + payload = "will_message" + + # # Will properties + properties = { + # # Payload Format Indicator + # # + # # 0 (0x00) Byte Indicates that the Will Message is unspecified bytes, + # # which is equivalent to not sending a Payload Format Indicator. + # # + # # 1 (0x01) Byte Indicates that the Will Message is UTF-8 Encoded Character Data. + # # + # # Default: 0 + # # Value: 0 | 1 + payload_format_indicator = 0 + + # # Message Expiry Interval + # # + # # If present, the Four Byte value is the lifetime of the Will Message in seconds + # # and is sent as the Publication Expiry Interval when the Server publishes the Will Message. + # # + # # If absent, no Message Expiry Interval is sent when the Server publishes the Will Message. + message_expiry_interval = 0 + + # # Content Type + # # The value of the Content Type is defined by the sending and receiving application. + content_type = "" + + # # Response Topic + # # The presence of a Response Topic identifies the Will Message as a Request. + response_topic = "" + + # # Correlation Data + # # The Correlation Data is used by the sender of the Request Message to identify which request + # # the Response Message is for when it is received. + correlation_data = "" + + # # Will Delay Interval + # # + # # If the Will Delay Interval is absent, the default value is 0 and there is no delay + # # before the Will Message is published. + # # + # # The Server delays publishing the Client’s Will Message until the Will Delay Interval + # # has passed or the Session ends, whichever happens first. + # # If a new Network Connection to this Session is made before the Will Delay Interval has passed, the Server MUST NOT send the Will Message + will_delay_interval = 0 + + # # User Property + # # + # # The User Property is allowed to appear multiple times to represent multiple name, value pairs. + # # The same name is allowed to appear more than once. + # # Value: Map[key(String) - value(String)] + user_property = { + key1 = value1 + key2 = value2 + } + } + } + + # # Ssl config ## + # # Ssl config is invalid when working in MQTT over QUIC mode ## + # ssl { + # # # Ssl key password + # # # String containing the user's password. Only used if the private keyfile + # # # is password-protected. + # # # + # # # Value: String + # # # key_password = "yourpass" + # # # Ssl keyfile + # # # Path of the file containing the client's private key. + # # # + # # # Value: File + # keyfile = "../etc/certs/key.pem" + # # # Ssl cert file + # # # Path of the file containing the client certificate. + # # # + # # # Value: File + # certfile = "../etc/certs/cert.pem" + # # # Ssl ca cert file + # # # Path of the file containing the server's root CA certificate. + # # # + # # # This certificate is used to identify the AWS IoT server and is publicly + # # # available. + # # # + # # # Value: File + # cacertfile = "../etc/certs/cacert.pem" + # } + + # # Topics that need to be forward to IoTHUB + # # + # # Value: String + # # Example: topic1/#,topic2/# + forwards = [ + { + # # Need to forward to remote broker topics + # # + # # Value: String + remote_topic = "fwd/topic1" + # # topic reflection with remote_topic + # # + # # Value: String + local_topic = "topic1" + } + { + remote_topic = "fwd/topic2" + local_topic = "topic2" + } + ] + + # #-------------------------------------------------------------------- + # # The following config params only effective when set QUIC as the + # # transport layer of bridging connection (mqtt-quic://{host}:{port})! + # # + + # # Ping: interval of a sending keepalive packet via QUIC transport. + # # + # # Value: Duration + # # Default: 120 seconds + quic_keepalive = 120s + # # Idle Timeout: How long a connection can go idle before it is gracefully shut down. + # # 0 to disable timeout, which may lost disconnect event msg. + # # Value: Duration + # # Default: 120 seconds + quic_idle_timeout = 120s + # # Disconnect Timeout: How long to wait for an ACK before declaring + # # a path dead and disconnecting, This affects stream living time. + # # Value: Duration + # # Default: 20 seconds + quic_discon_timeout = 20s + # # Handshake Timeout: the Max time NanoMQ waits for establishing QUIC connection + # # How long a handshake can idle before it is discarded + # # Value: Duration + # # Default: 60 seconds + quic_handshake_timeout = 60s + # # Send Idle Timeout: Reset congestion control after being idle `SendIdleTimeout` + # # Value: Duration + # # Default: 60 seconds + quic_send_idle_timeout = 2s + # # Initial RTT: Initial RTT estimate. (ms) + # # RTT: round trip time + # # Default: 800ms + quic_initial_rtt_ms = 800ms + # # Max Ack Delay: How long to wait after receiving data before sending an ACK. + # # Value: Duration + # # Default: 100ms + quic_max_ack_delay_ms = 100ms + # # multi-stream mode: enable or disable the multi-stream bridging mode + # # Warning: This is a feature WIP. Do not enable it! + # # Value: True/False + # # Default: False + quic_multi_stream = false + + # # qos_priority: send QoS 1/2 msg in high prority + # # QoS 0 messages remain as same + # # Value: true/false + # # Default: true + quic_qos_priority = true + + # # 0RTT: enable or diable 0RTT, 0RTT is a feature of QUIC to re-establish + # # connection quickly. + # # Value: true/false + # # Default: true + quic_0rtt = true + + subscription = [ + { + # # The topic filter of which subscribe to remote broker + # # This must present to enable the subscription of bridging + # # + # # Value: String + remote_topic = "cmd/topic3" + # # This is for Topic reflection, if you want the vanila way: + # # Leave `local_topic=""` to preserve the original topic in msg + # # Value: String + local_topic = "topic3" + # # Need to subscribe to remote topics QoS. + # # Please set QoS for each subscription topic + # # otherwise topic is invalid, NanoMQ won't sub to any topic + # # Value: Number + qos = 1 + } + { + remote_topic = "cmd/topic4" + local_topic = "topic4" + qos = 2 + } + ] + + # # Properties of subscribe for MQTT V5 + sub_properties { + # # Subscription Identifier + # # + # # The Subscription Identifier can have the value of 1 to 268,435,455. + # # It is a Protocol Error if the Subscription Identifier has a value of 0. + # # It is a Protocol Error to include the Subscription Identifier more than once. + # # The Subscription Identifier is associated with any subscription created or modified as the result of this SUBSCRIBE packet. + # # If there is a Subscription Identifier, it is stored with the subscription. + # # If this property is not specified, then the absence of a Subscription Identifier is stored with the subscription. + # # + # # Value: 1 ~ 268,435,455 + identifier = 1 + + # # User Property + # # + # # The User Property is allowed to appear multiple times to represent multiple name, value pairs. + # # The same name is allowed to appear more than once. + # # + # # Value: Map[key(String) - value(String)] + user_property = { + key1 = value1 + key2 = value2 + } + } + # # Hybrid bridging: enable or disable the hybrid bridging mode + # # Value: True/False + # # Default: False + hybrid_bridging = false + + # # Hybrid servers + # # When hybrid mode is enabled and the connection to server is + # # disconnected. Bridge will switch to hybrid_servers in roundrobin. + # # Value: Array + # # Default: [] + hybrid_servers = ["mqtt-quic://127.1:14567", "mqtt-tcp://127.1:1883"] + + # # max_parallel_processes + # # Handle a specified maximum number of outstanding requests + # # + # # Value: 1-infinity + max_parallel_processes = 2 + + # # max send queue length + # # Handle a specified maximum number of message send queue length + # # + # # Value: 1-infinity + max_send_queue_len = 32 + + # # max receive queue length + # # Handle a specified maximum number of message receive queue length + # # + # # Value: 1-infinity + max_recv_queue_len = 128 +} + +bridges.mqtt.cache { + # # Max message limitation for caching + # # ( 0 means ineffective ) + # # Value: 1-infinity + disk_cache_size = 102400 + # # Mounted file path + # # + # # Value: path + # mounted_file_path="/tmp/" + + # # The threshold of flushing messages to flash. + # # + # # Value: 1-infinity + flush_mem_threshold = 100 + + # # Resend interval (ms) + # # The interval for resending the messages after failure recovered. (not related to trigger) + # # + # # Value: 1-infinity + resend_interval = 5000 +} diff --git a/VNode/_software_lib/nanomq-0.22.10/config/nanomq_dds_gateway.conf b/VNode/_software_lib/nanomq-0.22.10/config/nanomq_dds_gateway.conf new file mode 100644 index 00000000..1c98667b --- /dev/null +++ b/VNode/_software_lib/nanomq-0.22.10/config/nanomq_dds_gateway.conf @@ -0,0 +1,164 @@ +# Example1. (default) +# This configure will make msgs with topic topic1 be shared in DDS network and MQTT network. +# It receive messages from MQTT network in topic DDSCMD/topic1 and send them to DDS network with topic MQTT/topic1. +# It receive messages from DDS network in topic MQTTCMD/topic1 and send them to MQTT network with topic DDS/topic1. + +forward_rules = { + dds_to_mqtt = [ + { + from_dds = "MQTTCMD/topic1" + to_mqtt = "DDS/topic1" + struct_name = "example_struct" + } + { + from_dds = "MQTTCMD/topic2" + to_mqtt = "DDS/topic2" + struct_name = "example_struct" + } + ], + + mqtt_to_dds = [ + { + from_mqtt = "DDSCMD/topic1" + to_dds = "MQTT/topic1" + struct_name = "example_struct" + } + { + from_mqtt = "DDSCMD/topic2" + to_dds = "MQTT/topic2" + struct_name = "example_struct" + } + ] +} + +dds { + # # dds domain id + # # default: 0 + # # Value: uint32 + domain_id = 0 + + # # dds subscriber partition. Setting multiple partitions is not supported yet. + # # default: "partition" + # # Value: string + subscriber_partition = "partition" + + # # dds publisher partition. Setting multiple partitions is not supported yet. + # # default: "partition" + # # Value: string + publisher_partition = "partition" + + shared_memory = { + # # Enable shared memory transport. + # # Iceoryx is required if enable shared memory transport. + # # + # # Default: false + # # Value: boolean + enable = false + + # # controls the output of the iceoryx runtime and can be set to, in order of decreasing output: + # # log level: verbose, debug, info, warn, error, fatal, off + # # Default: info + # # Value: enum + log_level = info + } +} + +mqtt { + connector { + # # Bridge address: host:port . + # # + # # Value: String + # # Example: mqtt-tcp://127.0.0.1:1883 + # # tls+mqtt-tcp://127.0.0.1:8883 + server = "mqtt-tcp://127.0.0.1:1883" + + # # Protocol version of the bridge. + # # + # # Value: Enum + # # - 5: mqttv5 + # # - 4: mqttv311 + # # - 3: mqttv31 + proto_ver = 4 + # # The ClientId of a remote bridge. + # # Default random string. + # # + # # Value: String + # clientid="bridge_client" + + # # Ping: interval of a downward bridge. + # # + # # Value: Duration + # # Default: 10 seconds + keepalive = 60s + # # The Clean start flag of a remote bridge. + # # + # # Value: boolean + # # Default: false + # # + # # NOTE: Some IoT platforms require clean_start + # # must be set to 'true' + clean_start = true + # # The username for a remote bridge. + # # + # # Value: String + username = username + # # The password for a remote bridge. + # # + # # Value: String + password = passwd + + // ssl { + // # # Ssl key password + // # # String containing the user's password. Only used if the private keyfile + // # # is password-protected. + // # # + // # # Value: String + // key_password = "yourpass" + // # # Ssl keyfile + // # # Path of the file containing the client's private key. + // # # + // # # Value: File + // keyfile = "/etc/certs/key.pem" + // # # Ssl cert file + // # # Path of the file containing the client certificate. + // # # + // # # Value: File + // certfile = "/etc/certs/cert.pem" + // # # Ssl ca cert file + // # # Path of the file containing the server's root CA certificate. + // # # + // # # This certificate is used to identify the AWS IoT server and is publicly + // # # available. + // # # + // # # Value: File + // cacertfile = "/etc/certs/cacert.pem" + // } + } +} + +# #============================================================ +# # Http server +# #============================================================ +http_server { + # # http server port + # # + # # Value: 0 - 65535 + port = 8082 + # # parallel for http server + # # Handle a specified maximum number of outstanding requests + # # + # # Value: 1-infinity + parallel = 2 + # # username + # # + # # Basic authorization + # # + # # Value: String + username = admin + # # password + # # + # # Basic authorization + # # + # # Value: String + password = public +} diff --git a/VNode/_software_lib/nanomq-0.22.10/config/nanomq_example.conf b/VNode/_software_lib/nanomq-0.22.10/config/nanomq_example.conf new file mode 100644 index 00000000..95c1ccea --- /dev/null +++ b/VNode/_software_lib/nanomq-0.22.10/config/nanomq_example.conf @@ -0,0 +1,1321 @@ +# NanoMQ Configuration 0.19.1 + +# #============================================================ +# # NanoMQ Broker +# #============================================================ + +system { + # # num_taskq_thread + # # Use a specified number of taskq threads + # # + # # Value: 1-255, Obtain automatically if 0 + num_taskq_thread = 0 + + # # max_taskq_thread + # # Use a specified maximunm number of taskq threads + # # + # # Value: 1-255, Obtain automatically if 0 + max_taskq_thread = 0 + + # # parallel + # # Handle a specified maximum number of outstanding requests + # # + # # Value: 1-255, Obtain automatically if 0 + parallel = 0 + + # # hook_ipc_url + # # Specify hook ipc url + # # + ## Value: ipc://path + hook_ipc_url = "ipc:///tmp/nanomq_hook.ipc" + + # # cmd_ipc_url + # # Specify cmd ipc url + # # + # # Value: ipc://path + cmd_ipc_url = "ipc:///tmp/nanomq_cmd.ipc" + +} + +mqtt { + # # max_packet_size + # # Defines the default max size of a packet that NanoMQ could accept and send + # # + # # Hot updatable + # # Value: 1 Byte-260 MB + max_packet_size = 1KB + + # # max_mqueue_len + # # The queue length in-flight window + # # This is essential for performance and memory consumption + # # + # # Hot updatable + # # Value: 1-infinity + max_mqueue_len = 2048 + + # # Unsupported now + max_inflight_window = 2048 + max_awaiting_rel = 10s + await_rel_timeout = 10s + + # # retry_interval (s) + # # The retry interval is nano qos duration which also controls timer + # # interval of each pipe + # # + # # Hot updatable + # # Value: 1-infinity + retry_interval = 10s + + # # The backoff for MQTT keepalive timeout. + # # broker will discolse client when there is no activity for + # # 'Keepalive * backoff * timeout. + # # + # # Hot updatable + # # Value: Float > 0.5 + keepalive_multiplier = 1.25 + + # # property_size + # # The max size for a MQTT user property + # # + # # Hot updatable + # # Value: 1-infinity + property_size = 32 + +} + +listeners.tcp { + # # bind + # # Connect with the host and port + # # + # # Value: host:port + bind = "0.0.0.0:1883" +} + +listeners.tcp.default_1 { + bind = "0.0.0.0:1884" +} + +listeners.tcp.default_2 { + bind = "0.0.0.0:1885" +} + +# #============================================================ +# # TLS/SSL +# #============================================================ + +listeners.ssl { + # # tls url + # # + # # Value: "host:port" + bind = "0.0.0.0:8883" + + # # tls key password + # # String containing the user's password. Only used if the private keyfile + # # is password-protected. + # # + # # Value: String + # key_password="yourpass" + + # # tls keyfile + # # Path to the file containing the user's private PEM-encoded key. + # # + # # Value: File + keyfile = "/etc/certs/key.pem" + + # # tls cert file + # # Path to a file containing the user certificate. + # # + # # Value: File + certfile = "/etc/certs/cert.pem" + + # # tls ca cert file + # # Path to the file containing PEM-encoded CA certificates. The CA certificates + # # are used during server authentication and when building the client certificate chain. + # # + # # Value: File + cacertfile = "/etc/certs/cacert.pem" + + # # A server only does x509-path validation in mode verify_peer, + # # as it then sends a certificate request to the client (this + # # message is not sent if the verify option is verify_none). + # # You can then also want to specify option fail_if_no_peer_cert. + # # + # # Value: true: verify_peer | false: verify_none + verify_peer = false + + # # Used together with {verify, verify_peer} by an SSL server. If set to true, + # # the server fails if the client does not have a certificate to send, that is, + # # sends an empty certificate. + # # + # # Value: true | false + fail_if_no_peer_cert = false +} + +listeners.ssl.default_1 { + bind = "0.0.0.0:8881" + keyfile = "/etc/certs/key.pem" + certfile = "/etc/certs/cert.pem" + cacertfile = "/etc/certs/cacert.pem" + verify_peer = false + fail_if_no_peer_cert = false +} + +listeners.ssl.default_2 { + bind = "0.0.0.0:8884" + keyfile = "/etc/certs/key.pem" + certfile = "/etc/certs/cert.pem" + cacertfile = "/etc/certs/cacert.pem" + verify_peer = false + fail_if_no_peer_cert = false +} + +# #============================================================ +# # WebSocket +# #============================================================ +listeners.ws { + # # websocket url + # # + # # Value: "host:port/path" + bind = "0.0.0.0:8083/mqtt" +} + +listeners.wss { + # # websocket tls url + # # + # # Value: "host:port/path" + bind = "0.0.0.0:8086/mqtt" +} + +# # -------------------- SQLite Config -------------------- ## +sqlite { + # # Max message limitation for caching + # # ( 0 means ineffective ) + # # Value: 1-infinity + disk_cache_size = 102400 + # # Mounted file path + # # + # # Value: path + # mounted_file_path="/tmp/" + + # # The threshold of flushing messages to flash. + # # + # # Hot updatable + # # Value: 1-infinity + flush_mem_threshold = 100 + + # # Resend interval (ms) + # # The interval for resending the messages after failure recovered. (not related to trigger) + # # + # # Value: 1-infinity + resend_interval = 5000 +} + +# #============================================================ +# # Http server +# #============================================================ +http_server { + # # http server port + # # + # # Value: 0 - 65535 + port = 8081 + # # limit connector + # # Handle a specified maximum number of outstanding requests + # # + # # Value: 1-infinity + limit_conn = 32 + # # http server username + # # + # # Value: String + username = admin + # # http server password + # # + # # Value: String + password = public + # # http server auth type + # # If set auth_type=jwt, make sure you have built JWT dependency with `-DENABLE_JWT=ON` first. + # # + # # Value: String basic | jwt + auth_type = basic + jwt { + # # http server jwt public key file + # # Used together with 'http_server.auth_type=jwt', + # # Path to the file containing the user's private key. + # # + # # Value: File + public.keyfile = "/etc/certs/jwt/jwtRS256.key.pub" + } +} + +# # ------------------ Logging Config ------------------ ## +log { + # # Where to emit the logs. + # # + # # - file: write logs to file + # # - console: write logs to standard I/O + # # - syslog: write logs to syslog + # # Value: file | console | syslog + # # Example: file,console,syslog + to = [file, console] + # # The log severity level. + # # + # # Value: trace | debug | info | warn | error | fatal + # # + # # Note: Only the messages with severity level higher than or equal to + # # this level will be logged. + # # + # # Default: warn + level = warn + # # The dir for log files. + # # + # # Value: Folder + dir = "/tmp" + # # The log filename for logs of level specified in "log.level". + # # + # # Value: String + # # Default: nanomq.log + file = "nanomq.log" + rotation { + # # Maximum size of each log file. + # # + # # Value: Number + # # Default: 10M + # # Supported Unit: KB | MB | GB + size = 10MB + # # Maximum rotation count of log files. + # # + # # Value: Number + # # Default: 5 + count = 5 + } +} + +# #============================================================ +# # WebHook +# #============================================================ + +# webhook { +# ## Webhook URL +# ## +# ## Value: String +# url="http://127.0.0.1:80" +# ## HTTP Headers +# ## +# ## Example: +# ## 1. web.hook.headers.content-type="application/json" +# ## 2. web.hook.headers.accept="*" +# ## +# ## Value: String +# headers.content-type="application/json" +# ## The encoding format of the payload field in the HTTP body +# ## The payload field only appears in the on_message_publish and on_message_delivered actions +# ## +# ## Value: plain | base64 | base62 +# body.encoding="plain" +# ## Connection process pool size +# ## +# ## Value: Number +# pool_size=32 +# +# # Unsupport now +# # tls { +# # keyfile="/etc/certs/key.pem" +# # certfile="/etc/certs/cert.pem" +# # cacertfile="/etc/certs/cacert.pem" +# # } +# +# } + +webhook { + url = "http://127.0.0.1:80" + headers.content-type = "application/json" + body.encoding = plain + pool_size = 32 + + events = [ + { + # # Webhook event. + # # + # # Value: String + # # Supported event list: + # # event: on_client_connect + # # event: on_client_connack + # # event: on_client_connected + # # event: on_client_disconnected + # # event: on_client_subscribe + # # event: on_client_unsubscribe + # # event: on_session_subscribed + # # event: on_session_unsubscribed + # # event: on_session_terminated + # # event: on_message_publish + # # event: on_message_delivered + # # event: on_message_acked + event = "on_message_publish" + + # # Webhook topic. + # # + # # Value: String + # # Support on message publish + topic = "a/b/c" + } + { + event = "on_client_connack" + } + ] +} + +auth { + # # anonymous + # # allow anonymous login + # # + # # Hot updatable + # # Value: true | false + allow_anonymous = true + + # # Allow or deny if no ACL rules matched. + # # + # # Value: allow | deny + no_match = allow + + # # The action when acl check reject current operation + # # + # # Value: ignore | disconnect + # # Default: ignore + deny_action = ignore + + cache = { + # # The maximum count of ACL entries can be cached for a client. + # # + # # Value: Integer greater than 0 + # # Default: 32 + max_size = 32 + + # # The time after which an ACL cache entry will be deleted + # # + # # Value: Duration + # # Default: 1 minute + ttl = 1m + } + + # # This is password conf file. + # # + # # Value: path string + # # Default: "/etc/pwd.conf" + password = {include "/etc/nanomq_pwd.conf"} + + # # This is acl conf file. + # # + # # Value: path string + # # Default: "/etc/acl.conf" + acl = {include "/etc/nanomq_acl.conf"} + + http_auth = { + auth_req { + # # HTTP URL API path for Auth Request + # # + # # Value: URL + # # + # # Examples: http://127.0.0.1:80/mqtt/auth, https://[::1]:80/mqtt/auth + url = "http://127.0.0.1:80/mqtt/auth" + # # HTTP Request Method for Auth Request + # # + # # Value: post | get + method = post + # # HTTP Request Headers for Auth Request, Content-Type header is configured by default. + # # The possible values of the Content-Type header: application/x-www-form-urlencoded, application/json + # # + # # Examples: auth.http.auth_req.headers.accept = */* + headers.content-type = "application/x-www-form-urlencoded" + # # Parameters used to construct the request body or query string parameters + # # When the request method is GET, these parameters will be converted into query string parameters + # # When the request method is POST, the final format is determined by content-type + # # + # # Available Variables: + # # - %u: username + # # - %c: clientid + # # - %a: ipaddress + # # - %r: protocol + # # - %P: password + # # - %p: sockport of server accepted + # # - %C: common name of client TLS cert + # # - %d: subject of client TLS cert + # # + # # Value: =,=,... + params = {clientid = "%c", username = "%u", password = "%p"} + # Unsupport now + # tls { + # keyfile="/etc/certs/key.pem" + # certfile="/etc/certs/cert.pem" + # cacertfile="/etc/certs/cacert.pem" + # } + } + + super_req { + url = "http://127.0.0.1:80/mqtt/superuser" + method = "post" + headers.content-type = "application/x-www-form-urlencoded" + params = {clientid = "%c", username = "%u", password = "%p"} + # Unsupport now + # tls { + # keyfile="/etc/certs/key.pem" + # certfile="/etc/certs/cert.pem" + # cacertfile="/etc/certs/cacert.pem" + # } + + } + # # HTTP ACL request is unsupported. + acl_req { + url = "http://127.0.0.1:8991/mqtt/acl" + method = "post" + headers.content-type = "application/x-www-form-urlencoded" + params = {clientid = "%c", username = "%u", access = "%A", ipaddr = "%a", topic = "%t", mountpoint = "%m"} + # Unsupport now + # tls { + # keyfile="/etc/certs/key.pem" + # certfile="/etc/certs/cert.pem" + # cacertfile="/etc/certs/cacert.pem" + # } + + } + + # # Time-out time for the request. + # # + # # Value: Duration + # # -h: hour, e.g. '2h' for 2 hours + # # -m: minute, e.g. '5m' for 5 minutes + # # -s: second, e.g. '30s' for 30 seconds + # # + # # Default: 5s + timeout = 5s + # # Connection time-out time, used during the initial request, + # # when the client is connecting to the server. + # # + # # Value: Duration + # # -h: hour, e.g. '2h' for 2 hours + # # -m: minute, e.g. '5m' for 5 minutes + # # -s: second, e.g. '30s' for 30 seconds + # # + # # Default: 5s + connect_timeout = 5s + # # Connection process pool size + # # + # # Value: Number + pool_size = 32 + } +} + +# #==================================================================== +# # MQTT Broker Bridge +# #==================================================================== +# # Here, you can use the include syntax of HOCON to put the +# # configuration file of the bridge into nanomq_bridge.conf. +# # include "path/to/nanomq_bridge.conf" +bridges.mqtt.emqx1 { + # # Bridge address: host:port . + # # + # # Value: String + # # Example: mqtt-tcp://127.0.0.1:1883 + # # tls+mqtt-tcp://127.0.0.1:8883 + # # mqtt-quic://54.75.171.11:14567 + + server = "mqtt-tcp://127.0.0.1:1883" + # # Protocol version of the bridge. + # # + # # Value: Enum + # # - 5: mqttv5 + # # - 4: mqttv311 + # # - 3: mqttv31 + proto_ver = 5 + # # The ClientId of a remote bridge. + # # Default random string. + # # + # # Value: String + # clientid="bridge_client" + + # # Ping: interval of a downward bridge. + # # + # # Value: Duration + # # Default: 10 seconds + keepalive = 60s + # # The maximum backoff timeout. + # # Reconnect after no more than backoff_max when bridge connection lost. + # # + # # Value: Duration + # # Default: 60s + backoff_max = 60s + # # The Clean start flag of a remote bridge. + # # + # # Value: boolean + # # Default: false + # # + # # NOTE: Some IoT platforms require clean_start + # # must be set to 'true' + clean_start = false + # # The username for a remote bridge. + # # + # # Value: String + username = username + # # The password for a remote bridge. + # # + # # Value: String + password = passwd + + # # Properties for MQTT V5 + conn_properties = { + # # Maximum Packet Size + # # + # # If the Maximum Packet Size is not present, no limit on the packet size is imposed beyond + # # the limitations in the protocol as a result of the remaining length encoding and the protocol header sizes. + # # Value: 1 ~ 4294967295 + maximum_packet_size = 1024 + + # # Receive Maximum + # # + # # The Client uses this value to limit the number of QoS 1 and QoS 2 publications that it is willing to process concurrently. + # # There is no mechanism to limit the QoS 0 publications that the Server might try to send. + # # The value of Receive Maximum applies only to the current Network Connection. + # # If the Receive Maximum value is absent then its value defaults to 65,535. + # # + # # Value: 1 ~ 65535 + receive_maximum = 65535 + + # # Topic Alias Maximum + # # + # # If the Topic Alias Maximum property is absent, the default value is 0. + # # This value indicates the highest value that the Client will accept as a Topic Alias sent by the Server. + # # The Client uses this value to limit the number of Topic Aliases that it is willing to hold on this Connection. + # # Default: 0 + # # Value: 0 ~ 65535 + topic_alias_maximum = 0 + + # # Request Problem Information + # # + # # If the Request Problem Information is absent, the value of 1 is used. + # # The Client uses this value to indicate whether the Reason String or User Properties are sent in the case of failures. + # # If the value of Request Problem Information is 0, the Server MAY return a Reason String or User Properties on a CONNACK or DISCONNECT packet, + # # but MUST NOT send a Reason String or User Properties on any packet other than PUBLISH, CONNACK, or DISCONNECT. + # # If the value is 0 and the Client receives a Reason String or User Properties in a packet other than PUBLISH, CONNACK, or DISCONNECT, + # # it uses a DISCONNECT packet with Reason Code 0x82 (Protocol Error) as described in section 4.13 Handling errors. + # # If this value is 1, the Server MAY return a Reason String or User Properties on any packet where it is allowed. + # # + # # Default: 1 + # # Value: 0 | 1 + request_problem_infomation = 1 + + # # Request Response Information + # # + # # If the Request Response Information is absent, the value of 0 is used. + # # The Client uses this value to request the Server to return Response Information in the CONNACK. + # # A value of 0 indicates that the Server MUST NOT return Response Information. + # # If the value is 1 the Server MAY return Response Information in the CONNACK packet. + # # + # # Default: 0 + # # Value: 0 | 1 + request_response_infomation = 0 + + # # Session Expiry Interval + # # + # # If the Session Expiry Interval is absent the value 0 is used. + # # If it is set to 0, or is absent, the Session ends when the Network Connection is closed. + # # If the Session Expiry Interval is 4294967295 (UINT_MAX), the Session does not expire. + # # + # # Value: 0 ~ 4294967295 + session_expiry_interval = 0 + + # # User Property + # # + # # The User Property is allowed to appear multiple times to represent multiple name, value pairs. + # # The same name is allowed to appear more than once. + # # Value: Map[key(String) - value(String)] + user_property = { + key1 = value1 + key2 = value2 + } + } + + will { + # # Will topic + topic = "will_topic" + # # Will QoS + qos = 1 + # # Will paylad retain flag + retain = false + # # Will payload + payload = "will_message" + + # # Will properties + properties = { + # # Payload Format Indicator + # # + # # 0 (0x00) Byte Indicates that the Will Message is unspecified bytes, + # # which is equivalent to not sending a Payload Format Indicator. + # # + # # 1 (0x01) Byte Indicates that the Will Message is UTF-8 Encoded Character Data. + # # + # # Default: 0 + # # Value: 0 | 1 + payload_format_indicator = 0 + + # # Message Expiry Interval + # # + # # If present, the Four Byte value is the lifetime of the Will Message in seconds + # # and is sent as the Publication Expiry Interval when the Server publishes the Will Message. + # # + # # If absent, no Message Expiry Interval is sent when the Server publishes the Will Message. + message_expiry_interval = 0 + + # # Content Type + # # The value of the Content Type is defined by the sending and receiving application. + content_type = "" + + # # Response Topic + # # The presence of a Response Topic identifies the Will Message as a Request. + response_topic = "" + + # # Correlation Data + # # The Correlation Data is used by the sender of the Request Message to identify which request + # # the Response Message is for when it is received. + correlation_data = "" + + # # Will Delay Interval + # # + # # If the Will Delay Interval is absent, the default value is 0 and there is no delay + # # before the Will Message is published. + # # + # # The Server delays publishing the Client’s Will Message until the Will Delay Interval + # # has passed or the Session ends, whichever happens first. + # # If a new Network Connection to this Session is made before the Will Delay Interval has passed, the Server MUST NOT send the Will Message + will_delay_interval = 0 + + # # User Property + # # + # # The User Property is allowed to appear multiple times to represent multiple name, value pairs. + # # The same name is allowed to appear more than once. + # # Value: Map[key(String) - value(String)] + user_property = { + key1 = value1 + key2 = value2 + } + } + } + + # # Ssl config ## + ## ssl { + ## # # Ssl key password + ## # # String containing the user's password. Only used if the private keyfile + ## # # is password-protected. + ## # # + ## # # Value: String + ## key_password = "yourpass" + ## # # Ssl keyfile + ## # # Path of the file containing the client's private key. + ## # # + ## # # Value: File + ## keyfile = "/etc/certs/key.pem" + ## # # Ssl cert file + ## # # Path of the file containing the client certificate. + ## # # + ## # # Value: File + ## certfile = "/etc/certs/cert.pem" + ## # # Ssl ca cert file + ## # # Path of the file containing the server's root CA certificate. + ## # # + ## # # Value: File + ## cacertfile = "/etc/certs/cacert.pem" + ##} + + # # Topics that need to be forward to IoTHUB + # # + # # Value: String + forwards = [ + { + # # This is for Topic reflection, if you want the vanila way: + # # Leave `remote_topic=""` to preserve the original topic in msg + # # + # # Value: String + remote_topic = "fwd/topic1" + # # The topic filter of which to forward to remote broker + # # + # # Local topic means the original topic of locale publish msg + # # msgs from local_topic will be reflected to remote_topic + # # This must present to enable the forwarding of bridging + # # Value: String + local_topic = "topic1" + # # Retain is used to override the ratain flag in the msg is about + # # to forward to remote. (0|1) stand for override the retain flag with (0|1). + # # 2 or not set this value will keep retain flag as it is. + # # Value: Number (0|1|2) + # # Default: 2 + # retain = 2 + + # # Prefix string adds to the remote topic.(or original topic if you leave remote_topic as "") + # # Value: String + # # Default: NULL + # prefix = "" + + # # Suffix string adds to the remote topic.(or original topic if you leave remote_topic as "") + # # Value: String + # # Default: NULL + # suffix = "" + } + { + remote_topic = "fwd/topic2" + local_topic = "topic2" + } + ] + + # #-------------------------------------------------------------------- + # # The following config params only effective when set QUIC as the + # # transport layer of bridging connection (mqtt-quic://{host}:{port})! + # # + + # # Ping: interval of a sending keepalive packet via QUIC transport. + # # + # # Value: Duration + # # Default: 120 seconds + quic_keepalive = 120s + # # Idle Timeout: How long a connection can go idle before it is gracefully shut down. + # # 0 to disable timeout, which may lost disconnect event msg. + # # Value: Duration + # # Default: 120 seconds + quic_idle_timeout = 120s + # # Disconnect Timeout: How long to wait for an ACK before declaring + # # a path dead and disconnecting, This affects stream living time. + # # Value: Duration + # # Default: 20 seconds + quic_discon_timeout = 20s + # # Handshake Timeout: the Max time NanoMQ waits for establishing QUIC connection + # # How long a handshake can idle before it is discarded + # # Value: Duration + # # Default: 60 seconds + quic_handshake_timeout = 60s + # # Send Idle Timeout: Reset congestion control after being idle `SendIdleTimeout` + # # Value: Duration + # # Default: 60 seconds + quic_send_idle_timeout = 2s + # # Initial RTT: Initial RTT estimate. (ms) + # # RTT: round trip time + # # Default: 800ms + quic_initial_rtt_ms = 800ms + # # Max Ack Delay: How long to wait after receiving data before sending an ACK. + # # Value: Duration + # # Default: 100ms + quic_max_ack_delay_ms = 100ms + # # multi-stream mode: enable or disable the multi-stream bridging mode + # # Warning: This is a feature WIP. Do not enable it! + # # Value: True/False + # # Default: False + quic_multi_stream = false + + # # qos_priority: send QoS 1/2 msg in high prority + # # QoS 0 messages remain as same + # # Value: true/false + # # Default: true + quic_qos_priority = true + + # # 0RTT: enable or diable 0RTT, 0RTT is a feature of QUIC to re-establish + # # connection quickly. + # # Value: true/false + # # Default: true + quic_0rtt = true + + subscription = [ + { + # # The topic filter of which subscribe to remote broker + # # This must present to enable the subscription of bridging + # # + # # Value: String + remote_topic = "cmd/topic3" + + # # This is for Topic reflection, if you want the vanila way: + # # Leave `local_topic=""` to preserve the original topic in msg + # # Value: String + local_topic = "topic3" + + # # Need to subscribe to remote topics QoS. + # # Please set QoS for each subscription topic + # # otherwise topic is invalid, NanoMQ won't sub to any topic + # # Value: Number + qos = 1 + + # # Retain is used to override the ratain flag in the msg is about + # # to forward to local. (0|1) stand for override the retain flag with (0|1). + # # 2 or not set this value will keep retain flag as it is. + # # Value: Number (0|1|2) + # # Default: 2 + # # retain = 2 + + # # Retain As Published is used to tell broker what to do with retain flag. + # # If 1, message forwarded using this subscription have the RETAIN flag they were published with. + # # If 0, message forwarded using this subscription have the RETAIN flag set to 0. + # # Value: Number (0|1) + retain_as_published = 1 + + # # Retain Handling is used to tell broker whether retain message should be sent. + # # If Retain Handing is set to 0, send all retain messages. + # # If Retain Handing is set to 1, send retain messages only if this subscription is not already exist. Otherwise do not send. + # # If Retain Handing is set to 2, do not send any retain message. + # # Value: Number (0|1|2) + retain_handling = 2 + + # # Prefix string adds to the local topic.(or original topic if you leave local_topic as "") + # # Value: String + # # Default: NULL + # prefix = "" + + # # Suffix string adds to the local topic.(or original topic if you leave local_topic as "") + # # Value: String + # # Default: NULL + # suffix = "" + } + { + remote_topic = "cmd/topic4" + local_topic = "topic4" + qos = 2 + } + ] + + # # Properties of subscribe for MQTT V5 + sub_properties { + # # Subscription Identifier + # # + # # The Subscription Identifier can have the value of 1 to 268,435,455. + # # It is a Protocol Error if the Subscription Identifier has a value of 0. + # # It is a Protocol Error to include the Subscription Identifier more than once. + # # The Subscription Identifier is associated with any subscription created or modified as the result of this SUBSCRIBE packet. + # # If there is a Subscription Identifier, it is stored with the subscription. + # # If this property is not specified, then the absence of a Subscription Identifier is stored with the subscription. + # # + # # Value: 1 ~ 268,435,455 + identifier = 1 + + # # User Property + # # + # # The User Property is allowed to appear multiple times to represent multiple name, value pairs. + # # The same name is allowed to appear more than once. + # # + # # Value: Map[key(String) - value(String)] + user_property = { + key1 = value1 + key2 = value2 + } + } + # # Hybrid bridging: enable or disable the hybrid bridging mode + # # Value: True/False + # # Default: False + hybrid_bridging = false + + # # Hybrid servers + # # When hybrid mode is enabled and the connection to server is + # # disconnected. Bridge will switch to hybrid_servers in roundrobin. + # # Value: Array + # # Default: [] + hybrid_servers = ["mqtt-quic://127.1:14567", "mqtt-tcp://127.1:1883"] + + # # max_parallel_processes + # # Handle a specified maximum number of outstanding requests + # # + # # Value: 1-infinity + max_parallel_processes = 2 + + # # max send queue length + # # Handle a specified maximum number of message send queue length + # # + # # Value: 1-infinity + max_send_queue_len = 32 + + # # max receive queue length + # # Handle a specified maximum number of message receive queue length + # # + # # Value: 1-infinity + max_recv_queue_len = 128 + + # # Resend interval (ms) + # # The interval for resending the messages after failure recovered. (not related to trigger) + # # move from cache to bridge since 0.22.8 + # # Value: 1-infinity (uint64) + resend_interval = 5000 + + # # Resend wait time (ms) + # # The waiting time for resending the messages after it is publiushed. + # # Tips: set it longer than keepalive if you dont want too much duplicated msg + # # Value: 1-infinity (uint64) + resend_wait = 3000 + + # # max Ack wait time for each QoS msg (ms) + # # The waiting time for Acknowledgment of every QoS msg. Does not affect normal sending. + # # Tips: QoS msg requries a delivered ack, which occupies an AIO. + # # set a max timeout time to cancel the ack action. + # # once it is canceled, there is no more retrying of this msg. + # # Value: 1-infinity (uint64) + cancel_timeout = 8000 +} + +# # The configuration of this cache is shared by all MQTT bridges. +bridges.mqtt.cache { + # # Max message limitation for caching + # # ( 0 means ineffective ) + # # Value: 1-infinity + disk_cache_size = 102400 + # # Mounted file path + # # + # # Value: path + # mounted_file_path="/tmp/" + + # # The threshold of flushing messages to flash. + # # + # # Value: 1-infinity + flush_mem_threshold = 100 +} + + + +# #==================================================================== +# # AWS IoT Core Bridge +# #==================================================================== +bridges.aws.c1 { + # # Aws address: host:port . + # # + # # Value: String + server = "127.0.0.1:8883" + # # Protocol version of the bridge. + # # + # # Value: Enum + # # - 5: mqttv5 + # # - 4: mqttv311 + proto_ver = 4 + # # The ClientId of a remote bridge. + # # Default random string. + # # + # # Value: String + clientid = "aws_bridge_client" + # # Ping interval of a down bridge. + # # + # # Value: Duration + # # Default: 10 seconds + keepalive = 60s + # # The Clean start flag of a remote bridge. + # # + # # Value: boolean + # # Default: true + # # + # # NOTE: Some IoT platforms require clean_start + # # must be set to 'true' + clean_start = true + # # The username for a remote bridge. + # # + # # Value: String + # username = "username" + # # The password for a remote bridge. + # # + # # Value: String + # password = "passwd" + + # ssl { + # # # Ssl key password + # # # String containing the user's password. Only used if the private keyfile + # # # is password-protected. + # # # + # # # Value: String + # key_password = "yourpass" + # # # Ssl keyfile + # # # Path of the file containing the client's private key. + # # # + # # # Value: File + # keyfile = "/etc/certs/key.pem" + # # # Ssl cert file + # # # Path of the file containing the client certificate. + # # # + # # # Value: File + # certfile = "/etc/certs/cert.pem" + # # # Ssl ca cert file + # # # Path of the file containing the server's root CA certificate. + # # # + # # # This certificate is used to identify the AWS IoT server and is publicly + # # # available. + # # # + # # # Value: File + # cacertfile = "/etc/certs/cacert.pem" + # } + + # # Topics that need to be forward to IoTHUB + # # + # # Value: String + forwards = [ + { + # # Need to forward to remote broker topics + # # + # # Value: String + remote_topic = "fwd/topic1" + # # topic reflection with remote_topic + # # + # # Value: String + local_topic = "topic1" + } + { + remote_topic = "fwd/topic2" + local_topic = "topic2" + } + ] + + subscription = [ + { + # # Need to subscribe to remote broker topics + # # + # # Value: String + remote_topic = "cmd/topic1" + # # topic reflection with remote_topic + # # + # # Value: String + local_topic = "topic1" + # # Need to subscribe to remote topics QoS. + # # + # # Value: Number + qos = 1 + }, + { + remote_topic = "cmd/topic2" + local_topic = "topic2" + qos = 2 + } + ] + # # max_parallel_processes + # # Handle a specified maximum number of outstanding requests + # # + # # Value: 1-infinity + max_parallel_processes = 2 + # # Ssl config ## + # # Ssl config is invalid when working in MQTT over QUIC mode ## +} + + +# #============================================================ +# # MQTT Rule Engine +# #============================================================ + +rules.sqlite { + # # Rule engine option SQLite3 database path + # # Rule engine db path, default is exec path. + # # + # # Value: File + path = "/tmp/sqlite_rule.db" + rules = [ + { + # # Rule engine option sql + # # Rule engine sql clause. + # # + # # Value: String + sql = "SELECT payload.x.y as y, payload.z as z FROM \"#\" WHERE y > 10 and z != 'str'" + # # Rule engine option SQLite3 database table name + # # Rule engine db table name. + # # + # # Value: String + table = broker + }, + { + sql = "SELECT topic, payload FROM \"abc\"" + table = broker1 + } + ] +} + +# #==================================================================== +# # MQTT Rule Engine for Repub +# #==================================================================== +rules.repub { + rules = [ + { + # # Repub address: host:port . + # # + # # Value: String + # # Example: mqtt-tcp://127.0.0.1:1883 + server = "mqtt-tcp://localhost:1883" + # # Repub topic . + # # + # # Value: String + # # Example: topic/repub + topic = "topic/repub1" + # # Protocol version of the Repub. + # # + # # Value: Enum + # # - 5: mqttv5 + # # - 4: mqttv311 + # # - 3: mqttv31 + proto_ver = 4 + # # The ClientId of a Repub client. + # # Default random string. + # # + # # Value: String + clientid = "repub_client1" + # # Ping interval of a Repub client. + # # + # # Value: Duration + # # Default: 60 seconds + keepalive = 60s + # # The Clean start flag of a Repub client. + # # + # # Value: boolean + # # Default: true + # # + # # NOTE: Some IoT platforms require clean_start + # # must be set to 'true' + clean_start = true + # # The username for a Repub client. + # # + # # Value: String + username = username + # # The password for a Repub. + # # + # # Value: String + password = passwd + # # Rule engine option sql + # # Rule engine sql clause. + # # + # # Value: String + sql = "SELECT payload.x.y as y, payload.z as z FROM \"#\" WHERE y > 10 and z != 'str'" + }, + { + server = "mqtt-tcp://localhost:1883" + topic = "topic/repub2" + proto_ver = 4 + clientid = "repub_client2" + keepalive = 60s + clean_start = true + username = username + password = passwd + sql = "SELECT topic, payload FROM \"abc\"" + } + ] +} + +# #==================================================================== +# # MQTT Rule Engine for Mysql +# #==================================================================== +# # Currently, MySQL rule only supports the configuration of one database. +rules.mysql.mysql_rule_db { + conn = { + # # The host for a mqsql client. + # # + # # Value: String + host = localhost + # # The username for a mqsql client. + # # + # # Value: String + username = username + # # The password for a mysql client. + # # + # # Value: String + password = password + # # Rule engine option mysql database name + # # Rule engine db path, default is exec path. + # # + # # Value: File + database = db_name + } + + rules = [ + { + # # Rule engine option mysql database table name + # # Rule engine db table name. + # # + # # Value: String + table = broker + # # Rule engine option sql + # # Rule engine sql clause. + # # + # # Value: String + sql = "SELECT payload.x.y as y, payload.z as z FROM \"#\" WHERE y > 10 and z != 'str'" + }, + { + table = broker1 + sql = "SELECT * FROM \"abc\"" + } + ] +} + +# #==================================================================== +# # Exchange configuration for Embedded Messaging Queue +# #==================================================================== +# # Initalize multiple MQ exchanger by giving them different name (mq1) +exchange_client.mq1 { + # # Currently NanoMQ only support one MQ object. URL shall be exactly same. + exchange_url = "tcp://127.0.0.1:10000" + # # exchanges contains multiple MQ exchanger + exchange { + # # MQTT Topic for filtering messages and saving to queue + topic = "exchange/topic1", + # # MQ name + name = "exchange_no1", + # # MQ category. Only support Ringbus for now + ringbus = { + # # ring buffer name + name = "ringbus", + # # max length of ring buffer (msg count) + cap = 1000, + # # 0: RB_FULL_NONE: When the ringbus is full, no action is taken and the message enqueue fail + # # 1: RB_FULL_DROP: When the ringbus is full, the data in the ringbus is discarded + # # 2: RB_FULL_RETURN: When the ringbus is full, the data in the ringbus is taken out and returned to the aio + # # 3: RB_FULL_FILE: When the ringbus is full, the data in the ringbus is written to the file + # + # # Value: 0-4 + # # Default: 0 + fullOp = 2 + } + } +} + + +# #==================================================================== +# # Parquet configuration (Apply to Exchange/Messaging_Queue) +# #==================================================================== +parquet { + # # Parquet compress type. + # # + # # Value: uncompressed | snappy | gzip | brotli | zstd | lz4 + compress = uncompressed + # # Encryption options + encryption { + # # Set a key retrieval metadata. + # # + # # Value: String + key_id = kf + # # Parquet encryption key. + # # + # # Value: String key must be either 16, 24 or 32 bytes. + key = "0123456789012345" + # # Set encryption algorithm. If not called, files + # # will be encrypted with AES_GCM_V1 (default). + # # + # # Value: AES_GCM_CTR_V1 | AES_GCM_V1 + type = AES_GCM_V1 + } + # # The dir for parquet files. + # # + # # Value: Folder + dir = "/tmp/nanomq-parquet" + # # The prefix of parquet files written. + # # + # # Value: string + file_name_prefix = "" + # # Maximum rotation count of parquet files. + # # + # # Value: Number + # # Default: 5 + file_count = 5 + # # The max size of parquet file written. + # # + # # Default: 10M + # # Value: Number + # # Supported Unit: KB | MB | GB + file_size = 1KB + # # The max number of searches per second. + # # + # # Default: 5 + # # Value: Number + limit_frequency = 5 +} + +plugin { + libs = [{ + path = "/path/to/plugin_user_property.so" + }] +} diff --git a/VNode/_software_lib/nanomq-0.22.10/config/nanomq_old.conf b/VNode/_software_lib/nanomq-0.22.10/config/nanomq_old.conf new file mode 100644 index 00000000..ed01aa92 --- /dev/null +++ b/VNode/_software_lib/nanomq-0.22.10/config/nanomq_old.conf @@ -0,0 +1,1513 @@ +# NanoMQ Configuration 0.18.0 + +##============================================================ +## NanoMQ Broker +##============================================================ + +## url +## Connect with the host and port +## +## Value: nmq-tcp://host:port +url=nmq-tcp://0.0.0.0:1883 + +## daemon +## Run the NanoMQ broker in a daemon mode +## +## Value: true | false +daemon=false + +## num_taskq_thread +## Use a specified number of taskq threads +## +## Value: 1-255, Obtain automatically if 0 +num_taskq_thread=0 + +## max_taskq_thread +## Use a specified maximunm number of taskq threads +## +## Value: 1-255, Obtain automatically if 0 +max_taskq_thread=0 + +## parallel +## Handle a specified maximum number of outstanding requests +## +## Value: 1-255, Obtain automatically if 0 +parallel=0 + +## Property_size +## The max size for a MQTT user property +## +## Hot updatable +## Value: 1-infinity +property_size=32 + +## The max packet size of NanoMQ (Kbytes) +## Defines the max size of a packet that NanoMQ could accept +## +## Hot updatable +## Value: 1 KByte-266240 KByte (260 Mb) +max_packet_size=10240 + +## The default max packet size of each client (Kbytes) +## Defines the default max size limit of sending packet to each client +## Will be overwrite if client set its own max size limit +## +## Hot updatable +## Value: 1 KByte-266240 KByte (260 Mb) +client_max_packet_size=10240 + +## msq_len +## The queue length in-flight window +## This is essential for performance and memory consumption +## +## Hot updatable +## Value: 1-infinity +msq_len=2048 + +## qos_duration (s) +## The nano qos duration which also controls timer interval of each pipe +## +## Hot updatable +## Value: 1-infinity +qos_duration=10 + +## The backoff for MQTT keepalive timeout. +## broker will discolse client when there is no activity for +## 'Keepalive * backoff * timeout. +## +## Hot updatable +## Value: Float > 0.5 +keepalive_backoff=1250 + +## anonymous +## allow anonymous login +## +## Hot updatable +## Value: true | false +allow_anonymous=true + +## enable internal IPC server +## allow IPC server +## +## This is for CMD parsing & Gateway/Plugins control +## Value: true | false +enable_ipc_internal=false + +## enable or disable ACL function +## +## Value: true | false +acl_enable=true + +## Allow or deny if no ACL rules matched. +## +## Value: allow | deny +acl_nomatch=allow + +## Whether to enable ACL cache. +## +## If enabled, ACLs roles for each client will be cached in the memory +## +## Value: on | off +enable_acl_cache=on + +## The maximum count of ACL entries can be cached for a client. +## +## Value: Integer greater than 0 +## Default: 32 +acl_cache_max_size=32 + +## The time after which an ACL cache entry will be deleted +## +## Value: Duration +## Default: 1 minute +acl_cache_ttl=1m + +## The action when acl check reject current operation +## +## Value: ignore | disconnect +## Default: ignore +acl_deny_action=ignore + +## ACL Rules +## Format: +## acl.rule.= + +## Allow MQTT client using username "dashboard" to subscribe to "$SYS/#" topics +# acl.rule.1={"permit": "allow", "username": "dashboard", "action": "subscribe", "topics": ["$SYS/#"]} + +## Allow users with IP address "127.0.0.1" to publish/subscribe to topics "$SYS/#", "#" +# acl.rule.2={"permit": "allow", "ipaddr": "127.0.0.1", "action": "pubsub", "topics": ["$SYS/#", "#"]} + +## Deny "All Users" subscribe to "$SYS/#" "#" Topics +# acl.rule.3={"permit": "deny", "username": "#", "action": "subscribe", "topics": ["$SYS/#", "#"]} + +## Allow any other publish/subscribe operation +# acl.rule.4={"permit": "allow"} + +## -------------------- SQLite Config -------------------- ## + +## Enable sqlite cache +## Whether to enable sqlite +## +## Value: boolean +sqlite.enable=false + +## Max message limitation for caching +## ( 0 means ineffective ) +## Value: 1-infinity +sqlite.disk_cache_size=102400 + +## Mounted file path +## +## Value: path +#sqlite.mounted_file_path=/tmp/ + +## The threshold of flushing messages to flash. +## +## Hot updatable +## Value: 1-infinity +sqlite.flush_mem_threshold=100 + +## Resend interval (ms) +## The interval for resending the messages after failure recovered. (not related to trigger) +## +## Value: 1-infinity +sqlite.resend_interval=5000 + +##============================================================ +## TLS/SSL +##============================================================ + +## enable tls +## +## Value: true | false +tls.enable=false + +## tls url +## +## Value: "tls+nmq-tcp://host:port" +tls.url=tls+nmq-tcp://0.0.0.0:8883 + +## tls key password +## String containing the user's password. Only used if the private keyfile +## is password-protected. +## Quote "" is not needed +## +## Value: String +## tls.key_password=yourpass + +## tls keyfile +## Path to the file containing the user's private PEM-encoded key. +## +## Value: File +tls.keyfile=/etc/certs/key.pem + +## tls cert file +## Path to a file containing the user certificate. +## +## Value: File +tls.certfile=/etc/certs/cert.pem + +## tls ca cert file +## Path to the file containing PEM-encoded CA certificates. The CA certificates +## are used during server authentication and when building the client certificate chain. +## +## Value: File +tls.cacertfile=/etc/certs/cacert.pem + +## A server only does x509-path validation in mode verify_peer, +## as it then sends a certificate request to the client (this +## message is not sent if the verify option is verify_none). +## You can then also want to specify option fail_if_no_peer_cert. +## +## Value: true: verify_peer | false: verify_none +tls.verify_peer=false + +## Used together with {verify, verify_peer} by an SSL server. If set to true, +## the server fails if the client does not have a certificate to send, that is, +## sends an empty certificate. +## +## Value: true | false +tls.fail_if_no_peer_cert=false + + +##============================================================ +## WebSocket +##============================================================ + +## allow websocket +## +## Value: true | false +websocket.enable=true + +## websocket url +## +## Value: "nmq-ws://host:port/path" +websocket.url=nmq-ws://0.0.0.0:8083/mqtt + +## websocket tls url +## +## Value: "nmq-wss://host:port/path" +websocket.tls_url=nmq-wss://0.0.0.0:8084/mqtt + + +##============================================================ +## Http server +##============================================================ + +## allow http server +## +## Value: true | false +http_server.enable=false + +## http server port +## +## Value: 0 - 65535 +http_server.port=8081 + +## parallel for http server +## Handle a specified maximum number of outstanding requests +## +## Value: 1-infinity +http_server.parallel=32 + +## http server username +## +## Value: String +http_server.username=admin + +## http server password +## +## Value: String +http_server.password=public + +## http server auth type +## If set auth_type=jwt, make sure you have built JWT dependency with `-DENABLE_JWT=ON` first. +## +## Value: basic | jwt +http_server.auth_type=basic + +## http server jwt public key file +## Used together with 'http_server.auth_type=jwt', +## Path to the file containing the user's private key. +## +## Value: File +http_server.jwt.public.keyfile=/etc/certs/jwt/jwtRS256.key.pub + +## http server jwt private key file +## Used together with 'http_server.auth_type=jwt', +## Path to the file containing the user's publick key. +## +## Value: File +http_server.jwt.private.keyfile=/etc/certs/jwt/jwtRS256.key + + + +## ------------------ Logging Config ------------------ ## + +## Where to emit the logs. +## +## - file: write logs to file +## - console: write logs to standard I/O +## - syslog: write logs to syslog +## Value: file | console | syslog +## Example: file,console,syslog +log.to=file,console + +## The log severity level. +## +## Value: trace | debug | info | warn | error | fatal +## +## Note: Only the messages with severity level higher than or equal to +## this level will be logged. +## +## Default: warn +log.level=info + +## The dir for log files. +## +## Value: Folder +log.dir=/tmp + +## The log filename for logs of level specified in "log.level". +## +## Value: String +## Default: nanomq.log +log.file=nanomq.log + +## Maximum size of each log file. +## +## Value: Number +## Default: 10M +## Supported Unit: KB | MB | GB +log.rotation.size=10MB + +## Maximum rotation count of log files. +## +## Value: Number +## Default: 5 +log.rotation.count=5 + +##============================================================ +## Authorization +##============================================================ + +##auth.1.login = admin +##auth.1.password = public + +##auth.2.login = client +##auth.2.password = public + + +##-------------------------------------------------------------------- +## HTTP Authorization +##-------------------------------------------------------------------- + +## Enable Authentication/ACL with HTTP API +## +## Value: true | false +auth.http.enable = false + +## HTTP URL API path for Auth Request +## +## Value: URL +## +## Examples: http://127.0.0.1:80/mqtt/auth, https://[::1]:80/mqtt/auth +auth.http.auth_req.url = http://127.0.0.1:80/mqtt/auth + +## HTTP Request Method for Auth Request +## +## Value: post | get +auth.http.auth_req.method = post + +## HTTP Request Headers for Auth Request, Content-Type header is configured by default. +## The possible values of the Content-Type header: application/x-www-form-urlencoded, application/json +## +## Examples: auth.http.auth_req.headers.accept = */* +auth.http.auth_req.headers.content-type = application/x-www-form-urlencoded + +## Parameters used to construct the request body or query string parameters +## When the request method is GET, these parameters will be converted into query string parameters +## When the request method is POST, the final format is determined by content-type +## +## Available Variables: +## - %u: username +## - %c: clientid +## - %a: ipaddress +## - %r: protocol +## - %P: password +## - %p: sockport of server accepted +## - %C: common name of client TLS cert +## - %d: subject of client TLS cert +## +## Value: =,=,... +auth.http.auth_req.params = clientid=%c,username=%u,password=%P + +## HTTP URL API path for SuperUser Request +## +## Value: URL +## +## Examples: http://127.0.0.1:80/mqtt/superuser, https://[::1]:80/mqtt/superuser +# auth.http.super_req.url = http://127.0.0.1:80/mqtt/superuser + +## Time-out time for the request. +## +## Value: Duration +## -h: hour, e.g. '2h' for 2 hours +## -m: minute, e.g. '5m' for 5 minutes +## -s: second, e.g. '30s' for 30 seconds +## +## Default: 5s +auth.http.timeout = 5s + +## Connection time-out time, used during the initial request, +## when the client is connecting to the server. +## +## Value: Duration +## -h: hour, e.g. '2h' for 2 hours +## -m: minute, e.g. '5m' for 5 minutes +## -s: second, e.g. '30s' for 30 seconds +## +## Default: 5s +auth.http.connect_timeout = 5s + +## Connection process pool size +## +## Value: Number +auth.http.pool_size = 32 + + +##============================================================ +## WebHook +##============================================================ + +## Enable web hook +## +## Value: boolean +web.hook.enable=false + +## Webhook URL +## +## Value: String +web.hook.url=http://127.0.0.1:80 + +## HTTP Headers +## +## Example: +## 1. web.hook.headers.content-type=application/json +## 2. web.hook.headers.accept=* +## +## Value: String +web.hook.headers.content-type=application/json + +## The encoding format of the payload field in the HTTP body +## The payload field only appears in the on_message_publish and on_message_delivered actions +## +## Value: plain | base64 | base62 +web.hook.body.encoding_of_payload_field=plain + +##-------------------------------------------------------------------- +## PEM format file of CA's +## +## Value: File +## web.hook.ssl.cacertfile = + +## Certificate file to use, PEM format assumed +## +## Value: File +## web.hook.ssl.certfile= + +## Private key file to use, PEM format assumed +## +## Value: File +## web.hook.ssl.keyfile= + +## Turn on peer certificate verification +## +## Value: true | false +## web.hook.ssl.verify=false + +## If not specified, the server's names returned in server's certificate is validated against +## what's provided `web.hook.url` config's host part. +## Setting to 'false' will make NanoMQ ignore unmatched server names. +## If set with a host name, the server's names returned in server's certificate is validated +## against this value. +## +## Value: true | false +## web.hook.ssl.server_name_indication=false + +## Connection process pool size +## +## Value: Number +web.hook.pool_size=32 + +## Hook Rules +## These configuration items represent a list of events should be forwarded +## +## Format: +## web.hook.rule..= +#web.hook.rule.client.connect.1={"action": "on_client_connect"} +#web.hook.rule.client.connack.1={"action": "on_client_connack"} +#web.hook.rule.client.connected.1={"action": "on_client_connected"} +#web.hook.rule.client.disconnected.1={"action": "on_client_disconnected"} +#web.hook.rule.client.subscribe.1={"action": "on_client_subscribe"} +#web.hook.rule.client.unsubscribe.1={"action": "on_client_unsubscribe"} +#web.hook.rule.session.subscribed.1={"action": "on_session_subscribed"} +#web.hook.rule.session.unsubscribed.1={"action": "on_session_unsubscribed"} +#web.hook.rule.session.terminated.1={"action": "on_session_terminated"} +#web.hook.rule.message.publish.1={"action": "on_message_publish"} +#web.hook.rule.message.delivered.1={"action": "on_message_delivered"} +#web.hook.rule.message.acked.1={"action": "on_message_acked"} + + +##==================================================================== +## MQTT Broker Bridge +##==================================================================== + +##-------------------------------------------------------------------- +## NanoMQ supports multi-channels of MQTT bridging. +## +## Format: +## bridge.mqtt.{name}.{item} = {value} +## Example: +## 1: +## bridge.mqtt.emqx.address = mqtt-tcp://{host}:{port} +## bridge.mqtt.emqx.bridge_mode = true +## bridge.mqtt.emqx.username = admin +## bridge.mqtt.emqx.password = public +## bridge.mqtt.emqx. = {value} +## +## 2: +## bridge.mqtt.aliyun.address = mqtt-tcp://{host}:{port} +## bridge.mqtt.aliyun.bridge_mode = true +## bridge.mqtt.aliyun.username = admin +## bridge.mqtt.aliyun.password = public +## bridge.mqtt.aliyun. = {value} + +## Whether to enable bridge mode for mqtt bridge +## +## This option is prepared for the mqtt broker which does not +## support bridge_mode such as the mqtt-plugin of the rabbitmq +## +## Value: boolean +bridge.mqtt.emqx.bridge_mode=false + +## Bridge address: host:port . +## +## Value: String +## Example: mqtt-tcp://127.0.0.1:1883 +## tls+mqtt-tcp://127.0.0.1:8883 +## mqtt-quic://54.75.171.11:14567 +bridge.mqtt.emqx.address=mqtt-tcp://broker.emqx.io:1883 + +## Protocol version of the bridge. +## +## Value: Enum +## - 5: mqttv5 +## - 4: mqttv311 +## - 3: mqttv31 +bridge.mqtt.emqx.proto_ver=4 + +##-------------------------------------------------------------------- +## The following config params only effective when set QUIC as the +## transport layer of bridging connection (mqtt-quic://{host}:{port})! +## + +## Ping: interval of a sending keepalive packet via QUIC transport. +## +## Value: Duration +## Default: 120 seconds +bridge.mqtt.emqx.quic_keepalive=120 + +## Idle Timeout: How long a connection can go idle before it is gracefully shut down. +## 0 to disable timeout, which may lost disconnect event msg. +## Value: Duration +## Default: 120 seconds +bridge.mqtt.emqx.quic_idle_timeout=120 + +## Disconnect Timeout: How long to wait for an ACK before declaring +## a path dead and disconnecting, This affects stream living time. +## Value: Duration +## Default: 20 seconds +bridge.mqtt.emqx.quic_discon_timeout=20 + +## Handshake Timeout: the Max time NanoMQ waits for establishing QUIC connection +## How long a handshake can idle before it is discarded +## Value: Duration +## Default: 60 seconds +bridge.mqtt.emqx.quic_handshake_timeout=60 + +## Send Idle Timeout: Reset congestion control after being idle `SendIdleTimeout` +## Value: Duration +## Default: 60 seconds +bridge.mqtt.emqx.quic_send_idle_timeout=2 + +## Initial RTT: Initial RTT estimate. (ms) +## RTT: round trip time +## Default: 800ms +bridge.mqtt.emqx.quic_initial_rtt_ms=800 + +## Max Ack Delay: How long to wait after receiving data before sending an ACK. +## Value: Duration +## Default: 100ms +bridge.mqtt.emqx.quic_max_ack_delay_ms=100 + +## congestion_control: pick an algorithm from bbr or cubic +## +## Value: String +## Default: cubic +bridge.mqtt.emqx.quic_congestion_control=cubic + +## Hybrid bridging: enable or disable the hybrid bridging mode +## Recommend to enable it when you want to take advantage of QUIC +## but not sure if the public network support QUIC. +## Value: true/false +## Default: false +bridge.mqtt.emqx.hybrid_bridging=false + +## multi-stream: enable or disable the multi-stream bridging mode +## Still a feature WIP, but basic func is ready +## Value: true/false +## Default: false +bridge.mqtt.emqx.quic_multi_stream=false + +## qos_priority: send QoS 1/2 msg in high prority +## QoS 0 messages remain as same +## Value: true/false +## Default: true +bridge.mqtt.emqx.quic_qos_priority=true + +## QUIC 0RTT: enable or diable 0RTT, 0RTT is a feature of QUIC to re-establish +## connection quickly. +## Value: true/false +## Default: true +bridge.mqtt.emqx.quic_0rtt=true + +## +##-------------------------------------------------------------------- + +## The ClientId of a remote bridge. +## Default random string. +## +## Value: String +#bridge.mqtt.emqx.clientid=bridge_client + +## Ping: interval of a downward bridge. +## +## Value: Duration +## Default: 10 seconds +bridge.mqtt.emqx.keepalive=60 + +## The maximum backoff timeout. +## Reconnect after no more than backoff_max when bridge connection lost. +## +## Value: Duration +## Default: 60 seconds +bridge.mqtt.emqx.backoff_max=60 + +## The Clean start flag of a remote bridge. +## +## Value: boolean +## Default: false +## +## NOTE: Some IoT platforms require clean_start +## must be set to 'true' +bridge.mqtt.emqx.clean_start=false + +## The username for a remote bridge. +## Quote "" is not needed +## +## Value: String +bridge.mqtt.emqx.username=username + +## The password for a remote bridge. +## +## Value: String +bridge.mqtt.emqx.password=passwd + +## Topics that need to be forward to IoTHUB +## +## The topic in msg send to remote will not be changed +## if nothing is filled in after the = +## Like this `bridge.mqtt.emqx.forwards.1.remote_topic=` +## +## Value: String +bridge.mqtt.emqx.forwards.1.remote_topic=fwd/topic1 +bridge.mqtt.emqx.forwards.1.local_topic=topic1 + +## Override flag for retain +## Override the retain flag in the msg is about to forward +## with this option. (0|1) stand for override the retain flag with (0|1). +## 2 stands for keeping retain flag as it is. +## +## Value: Number (0|1|2) +bridge.mqtt.emqx.forwards.1.retain=2 + +## Need to subscribe to remote broker topics +## +## The topic in msg send to local will not be changed +## if nothing is filled in after the = +## Like this `bridge.mqtt.emqx.subscription.1.local_topic=` +## +## Value: String +bridge.mqtt.emqx.subscription.1.remote_topic=cmd/topic1 +bridge.mqtt.emqx.subscription.1.local_topic=topic1 + +## Override flag for retain +## Override the retain flag in the msg is about to distribute to clients +## with this option. (0|1) stand for override the retain flag with (0|1). +## 2 stands for keeping retain flag as it is. +## +## Value: Number (0|1|2) +bridge.mqtt.emqx.subscription.1.retain=2 + +## Need to subscribe to remote topics QoS. +## Please set QoS for each subscription topic +## otherwise topic is invalid, NanoMQ won't sub to any topic +## Value: Number +bridge.mqtt.emqx.subscription.1.qos=1 + +## Need to subscribe to remote broker topics +## +## Value: String +bridge.mqtt.emqx.subscription.2.remote_topic=cmd/topic2 +bridge.mqtt.emqx.subscription.2.local_topic=topic2 + +## Override flag for retain +## +## Value: Number (0|1|2) +bridge.mqtt.emqx.subscription.2.retain=2 + +## Need to subscribe to remote topics QoS. +## +## Value: Number +bridge.mqtt.emqx.subscription.2.qos=2 + +## parallel +## Handle a specified maximum number of outstanding requests +## +## Value: 1-infinity +bridge.mqtt.emqx.parallel=2 + +## max send queue length +## Handle a specified maximum number of message send queue length +## +## Value: 1-infinity +bridge.mqtt.emqx.max_send_queue_len=32 + +## max receive queue length +## Handle a specified maximum number of message receive queue length +## +## Value: 1-infinity +bridge.mqtt.emqx.max_recv_queue_len=128 + +# # Resend interval (ms) +# # The interval for resending the messages after failure recovered. (not related to trigger) +# # move from cache to bridge since 0.22.8 +# # Value: 1-infinity (uint64) +bridge.mqtt.emqx.resend_interval=5000 + +# # Resend wait time (ms) +# # The waiting time for resending the messages after it is publiushed. +# # Tips: set it longer than keepalive if you dont want too much duplicated msg +# # Value: 1-infinity (uint64) +bridge.mqtt.emqx.resend_wait = 3000 + +# # max Ack wait time for each QoS msg (ms) +# # The waiting time for Acknowledgment of every QoS msg. Does not affect normal sending. +# # Tips: QoS msg requries a delivered ack, which occupies an AIO. +# # set a max timeout time to cancel the ack action. +# # once it is canceled, there is no more retrying of this msg. +# # Value: 1-infinity (uint64) +bridge.mqtt.emqx.cancel_timeout = 10000 + +## MQTT V5 Property for Connection ## + +# # Maximum Packet Size +# # +# # If the Maximum Packet Size is not present, no limit on the packet size is imposed beyond +# # the limitations in the protocol as a result of the remaining length encoding and the protocol header sizes. +# # Value: 1 ~ 4294967295 +# bridge.mqtt.emqx.connect.properties.maximum_packet_size=0 + +# # Receive Maximum +# # +# # The Client uses this value to limit the number of QoS 1 and QoS 2 publications that it is willing to process concurrently. +# # There is no mechanism to limit the QoS 0 publications that the Server might try to send. +# # The value of Receive Maximum applies only to the current Network Connection. +# # If the Receive Maximum value is absent then its value defaults to 65,535. +# # +# # Value: 1 ~ 65535 +# bridge.mqtt.emqx.connect.properties.receive_maximum=65535 + +# # Topic Alias Maximum +# # +# # If the Topic Alias Maximum property is absent, the default value is 0. +# # This value indicates the highest value that the Client will accept as a Topic Alias sent by the Server. +# # The Client uses this value to limit the number of Topic Aliases that it is willing to hold on this Connection. +# # Default: 0 +# # Value: 0 ~ 65535 +# bridge.mqtt.emqx.connect.properties.topic_alias_maximum=0 + +# # Request Problem Information +# # +# # If the Request Problem Information is absent, the value of 1 is used. +# # The Client uses this value to indicate whether the Reason String or User Properties are sent in the case of failures. +# # If the value of Request Problem Information is 0, the Server MAY return a Reason String or User Properties on a CONNACK or DISCONNECT packet, +# # but MUST NOT send a Reason String or User Properties on any packet other than PUBLISH, CONNACK, or DISCONNECT. +# # If the value is 0 and the Client receives a Reason String or User Properties in a packet other than PUBLISH, CONNACK, or DISCONNECT, +# # it uses a DISCONNECT packet with Reason Code 0x82 (Protocol Error) as described in section 4.13 Handling errors. +# # If this value is 1, the Server MAY return a Reason String or User Properties on any packet where it is allowed. +# # +# # Default: 1 +# # Value: 0 | 1 +# bridge.mqtt.emqx.connect.properties.request_problem_infomation=0 + +# # Request Response Information +# # +# # If the Request Response Information is absent, the value of 0 is used. +# # The Client uses this value to request the Server to return Response Information in the CONNACK. +# # A value of 0 indicates that the Server MUST NOT return Response Information. +# # If the value is 1 the Server MAY return Response Information in the CONNACK packet. +# # +# # Default: 0 +# # Value: 0 | 1 +# bridge.mqtt.emqx.connect.properties.request_response_infomation=1 + +# # Session Expiry Interval +# # +# # If the Session Expiry Interval is absent the value 0 is used. +# # If it is set to 0, or is absent, the Session ends when the Network Connection is closed. +# # If the Session Expiry Interval is 4294967295 (UINT_MAX), the Session does not expire. +# # +# # Value: 0 ~ 4294967295 +# bridge.mqtt.emqx.connect.properties.session_expiry_interval=0 + +# # User Property +# # +# # The User Property is allowed to appear multiple times to represent multiple name, value pairs. +# # The same name is allowed to appear more than once. +# # Value: Json string: key(String) - value(String) +# bridge.mqtt.emqx.connect.properties.user_property={"key1":"value1","key2":"value2"} + +## MQTT V5 Property for Subscription ## + +# # Subscription Identifier +# # +# # The Subscription Identifier can have the value of 1 to 268,435,455. +# # It is a Protocol Error if the Subscription Identifier has a value of 0. +# # It is a Protocol Error to include the Subscription Identifier more than once. +# # The Subscription Identifier is associated with any subscription created or modified as the result of this SUBSCRIBE packet. +# # If there is a Subscription Identifier, it is stored with the subscription. +# # If this property is not specified, then the absence of a Subscription Identifier is stored with the subscription. +# # +# # Value: 1 ~ 268,435,455 +# bridge.mqtt.emqx.subscription.properties.identifier=1 + +# # User Property +# # +# # The User Property is allowed to appear multiple times to represent multiple name, value pairs. +# # The same name is allowed to appear more than once. +# # Value: Json string: key(String) - value(String) +# bridge.mqtt.emqx.subscription.properties.user_property={"key1":"value1","key2":"value2"} + +# # Will topic +bridge.mqtt.emqx.will.topic=will_topic + +# # Will qos +bridge.mqtt.emqx.will.qos=2 + +# # Will retain +bridge.mqtt.emqx.will.retain=false + +# # Will payload +bridge.mqtt.emqx.will.payload=will_message + +## MQTT V5 Property for Will ## + +# # Payload Format Indicator +# # +# # 0 (0x00) Byte Indicates that the Will Message is unspecified bytes, +# # which is equivalent to not sending a Payload Format Indicator. +# # +# # 1 (0x01) Byte Indicates that the Will Message is UTF-8 Encoded Character Data. +# # +# # Default: 0 +# # Value: 0 | 1 +bridge.mqtt.emqx.will.properties.payload_format_indicator=0 + +# # Message Expiry Interval +# # +# # If present, the Four Byte value is the lifetime of the Will Message in seconds +# # and is sent as the Publication Expiry Interval when the Server publishes the Will Message. +# # +# # If absent, no Message Expiry Interval is sent when the Server publishes the Will Message. +bridge.mqtt.emqx.will.properties.message_expiry_interval=100 + +# # Content Type +# # The value of the Content Type is defined by the sending and receiving application. +# bridge.mqtt.emqx.will.properties.content_type= + +# # Response Topic +# # The presence of a Response Topic identifies the Will Message as a Request. +# bridge.mqtt.emqx.will.properties.response_topic= + +# # Correlation Data +# # The Correlation Data is used by the sender of the Request Message to identify which request +# # the Response Message is for when it is received. +# bridge.mqtt.emqx.will.properties.correlation_data= + +# # Will Delay Interval +# # +# # If the Will Delay Interval is absent, the default value is 0 and there is no delay +# # before the Will Message is published. +# # +# # The Server delays publishing the Client’s Will Message until the Will Delay Interval +# # has passed or the Session ends, whichever happens first. +# # If a new Network Connection to this Session is made before the Will Delay Interval has passed, the Server MUST NOT send the Will Message +bridge.mqtt.emqx.will.properties.will_delay_interval=30 + +# # User Property +# # +# # The User Property is allowed to appear multiple times to represent multiple name, value pairs. +# # The same name is allowed to appear more than once. +# # Value: Map[key(String) - value(String)] +bridge.mqtt.emqx.will.properties.user_property={"key1":"value1","key2":"value2"} + + +## enable tls +## +## Value: true | false +bridge.mqtt.emqx.tls.enable=false + +## tls key password +## String containing the user's password. Only used if the private keyfile +## is password-protected. +## +## Value: String +## bridge.mqtt.emqx.tls.key_password=yourpass + +## tls keyfile +## Path of the file containing the client's private key. +## +## Value: File +## bridge.mqtt.emqx.tls.keyfile=/etc/certs/key.pem + +## tls cert file +## Path of the file containing the client certificate. +## +## Value: File +## bridge.mqtt.emqx.tls.certfile=/etc/certs/cert.pem + +## tls ca cert file +## Path of the file containing the server's root CA certificate. +## +## This certificate is used to identify the Emqx IoT server and is publicly +## available. +## +## Value: File +## bridge.mqtt.emqx.tls.cacertfile=/etc/certs/cacert.pem + +##-------------------------------------------------------------------- +## Next bridge configuration +## +## bridge.mqtt..address=mqtt-tcp://{host}:{port} +## bridge.mqtt..bridge_mode=true +## bridge.mqtt..username=admin +## bridge.mqtt..password=public +## bridge.mqtt..={value} +## +##-------------------------------------------------------------------- + +## SQLite Config ## + +## Enable sqlite cache +## Whether to enable sqlite +## +## Value: boolean +bridge.sqlite.enable=false + +## Max message limitation for caching +## ( 0 means ineffective ) +## Value: 1-infinity +bridge.sqlite.disk_cache_size=102400 + +## Mounted file path +## +## Value: path +#bridge.sqlite.mounted_file_path=/tmp/ + +## The threshold of flushing messages to flash. +## +## Value: 1-infinity +bridge.sqlite.flush_mem_threshold=100 + +##==================================================================== +## AWS IoT Core Bridge +##==================================================================== + +##-------------------------------------------------------------------- +## NanoMQ supports multiple aws bridging. +## +## Format: +## aws.bridge.mqtt.{name}.{item} = {value} + +## aws endpoint +## +## Value: String +aws.bridge.mqtt.aws.host=localhost + +## aws mqtt port +## +## Value: String +aws.bridge.mqtt.aws.port=8883 + +## Protocol version of the bridge. +## +## Value: Enum +## - 5: mqttv5 +## - 4: mqttv311 +aws.bridge.mqtt.aws.proto_ver=4 + +## Whether to enable bridge mode for mqtt bridge +## +## This option is prepared for the mqtt broker which does not +## support bridge_mode such as the mqtt-plugin of the rabbitmq +## +## Value: boolean +aws.bridge.mqtt.aws.bridge_mode=false + +## The ClientId of a remote bridge. +## Default random string. +## +## Value: String +aws.bridge.mqtt.aws.clientid=aws_bridge_client + +## Ping interval of a down bridge. +## +## Value: Duration +## Default: 10 seconds +aws.bridge.mqtt.aws.keepalive=60 + +## The Clean start flag of a remote bridge. +## +## Value: boolean +## Default: true +## +## NOTE: Some IoT platforms require clean_start +## must be set to 'true' +aws.bridge.mqtt.aws.clean_start=true + +## The username for a remote bridge. +## +## Value: String +# aws.bridge.mqtt.aws.username=username + +## The password for a remote bridge. +## +## Value: String +# aws.bridge.mqtt.aws.password=passwd + +## Topics that need to be forward to IoTHUB +## +## Value: String +aws.bridge.mqtt.aws.forwards.1.remote_topic=fwd/topic1 +aws.bridge.mqtt.aws.forwards.1.local_topic=topic1 + +## Override flag for retain +## +## Value: Number (0|1|2) +aws.bridge.mqtt.aws.forwards.1.retain=2 + +## Need to subscribe to remote broker topics +## +## Value: String +aws.bridge.mqtt.aws.subscription.1.remote_topic=cmd/topic1 +aws.bridge.mqtt.aws.subscription.1.local_topic=topic1 + +## Override flag for retain +## +## Value: Number (0|1|2) +aws.bridge.mqtt.aws.subscription.1.retain=2 + +## Need to subscribe to remote topics QoS. +## +## Value: Number +aws..mqtt.aws.subscription.1.qos=1 + +## Need to subscribe to remote broker topics +## +## Value: String +aws.bridge.mqtt.aws.subscription.2.remote_topic=cmd/topic2 +aws.bridge.mqtt.aws.subscription.2.local_topic=topic2 + +## Need to subscribe to remote topics QoS. +## +## Value: Number +aws.bridge.mqtt.aws.subscription.2.qos=2 + +## parallel +## Handle a specified maximum number of outstanding requests +## +## Value: 1-infinity +aws.bridge.mqtt.aws.parallel=2 + +## tls config ## + +## enable tls +## +## Value: true | false +aws.bridge.mqtt.aws.tls.enable=true + +## tls key password +## String containing the user's password. Only used if the private keyfile +## is password-protected. +## +## Value: String +## aws.bridge.mqtt.aws.tls.key_password=yourpass + +## tls keyfile +## Path of the file containing the client's private key. +## +## Value: File +aws.bridge.mqtt.aws.tls.keyfile=/etc/certs/key.pem + +## tls cert file +## Path of the file containing the client certificate. +## +## Value: File +aws.bridge.mqtt.aws.tls.certfile=/etc/certs/cert.pem + +## tls ca cert file +## Path of the file containing the server's root CA certificate. +## +## This certificate is used to identify the AWS IoT server and is publicly +## available. +## +## Value: File +aws.bridge.mqtt.aws.tls.cacertfile=/etc/certs/cacert.pem + +## A server only does x509-path validation in mode verify_peer, +## as it then sends a certificate request to the client (this +## message is not sent if the verify option is verify_none). +## You can then also want to specify option fail_if_no_peer_cert. +## +## Value: true: verify_peer | false: verify_none +aws.bridge.mqtt.aws.tls.verify_peer=false + +## Used together with {verify, verify_peer} by an SSL server. If set to true, +## the server fails if the client does not have a certificate to send, that is, +## sends an empty certificate. +## +## Value: true | false +aws.bridge.mqtt.aws.tls.fail_if_no_peer_cert=false + + +##============================================================ +## MQTT Rule Engine +##============================================================ + +## Rule engine option, when persistence with +## rule engine, this option is must be ON. +## +## Value: ON | OFF +rule_option=ON + +## Rule engine plugins option +## Choose a plugin to enable +## +## Value: enable/disable +rule_option.sqlite=enable + +## Rule engine plugins option +## Choose a plugin to enable +## +## Value: enable/disable +rule_option.repub=enable + +## Rule engine plugins option +## Choose a plugin to enable +## +## Value: enable/disable +rule_option.mysql=enable + + +##==================================================================== +## MQTT Rule Engine for Sqlite +##==================================================================== + +## Hot updatable +## Rule engine option SQLite3 database path +## Rule engine db path, default is exec path. +## +## Value: File +rule.sqlite.path=/tmp/sqlite_rule.db + +## Rule engine option SQLite3 database table name +## Rule engine db table name. +## +## Value: String +rule.sqlite.1.table=broker + +## Rule engine option sql +## Rule engine sql clause. +## +## Value: String +rule.sqlite.event.publish.1.sql="SELECT payload.x.y as y, payload.z as z FROM "#" WHERE y > 10 and z != 'str'" + +## Rule engine option SQLite3 database table name +## Rule engine db table name. +## +## Value: String +rule.sqlite.2.table=broker1 + +## Rule engine option sql +## Rule engine sql clause. +## +## Value: String +rule.sqlite.event.publish.2.sql="SELECT * FROM "abc"" + +## Rule engine option SQLite3 database table name +## Rule engine db table name. +## +## Value: String +rule.sqlite.3.table=broker2 + +## Rule engine option sql +## Rule engine sql clause. +## +## Value: String +rule.sqlite.event.publish.3.sql="SELECT payload, qos FROM "#" WHERE qos > 0" + + +##==================================================================== +## MQTT Rule Engine for Repub +##==================================================================== + +## Repub address: host:port . +## +## Value: String +## Example: mqtt-tcp://127.0.0.1:1883 +rule.repub.1.address=mqtt-tcp://localhost:1883 + +## Repub topic . +## +## Value: String +## Example: topic/repub +rule.repub.1.topic=topic/repub1 + +## Protocol version of the Repub. +## +## Value: Enum +## - 5: mqttv5 +## - 4: mqttv311 +## - 3: mqttv31 +rule.repub.1.proto_ver=4 + +## The ClientId of a Repub client. +## Default random string. +## +## Value: String +rule.repub.1.clientid=repub_client1 + +## Ping interval of a Repub client. +## +## Value: Duration +## Default: 10 seconds +rule.repub.1.keepalive=60 + +## The Clean start flag of a Repub client. +## +## Value: boolean +## Default: true +## +## NOTE: Some IoT platforms require clean_start +## must be set to 'true' +rule.repub.1.clean_start=true + +## The username for a Repub client. +## +## Value: String +rule.repub.1.username=username + +## The password for a Repub. +## +## Value: String +rule.repub.1.password=passwd + + +## Rule engine option sql +## Rule engine sql clause. +## +## Value: String +rule.repub.event.publish.1.sql="SELECT payload.x.y as y, payload.z as z FROM "#" WHERE y > 10 and z != 'str'" + + +## Repub address: host:port . +## +## Value: String +## Example: mqtt-tcp://127.0.0.1:1883 +rule.repub.2.address=mqtt-tcp://localhost:1885 + +## Repub topic . +## +## Value: String +## Example: topic/repub +rule.repub.2.topic=topic/repub2 + +## Protocol version of the Repub. +## +## Value: Enum +## - 5: mqttv5 +## - 4: mqttv311 +## - 3: mqttv31 +rule.repub.2.proto_ver=4 + +## The ClientId of a Repub client. +## Default random string. +## +## Value: String +rule.repub.2.clientid=repub_client2 + +## Ping interval of a Repub client. +## +## Value: Duration +## Default: 10 seconds +rule.repub.2.keepalive=60 + +## The Clean start flag of a Repub client. +## +## Value: boolean +## Default: true +## +## NOTE: Some IoT platforms require clean_start +## must be set to 'true' +rule.repub.2.clean_start=true + +## The username for a Repub client. +## +## Value: String +rule.repub.2.username=username + +## The password for a Repub. +## +## Value: String +rule.repub.2.password=passwd + +## Rule engine option sql +## Rule engine sql clause. +## +## Value: String +rule.repub.event.publish.2.sql="SELECT topic, payload FROM "abc"" + + +## Repub address: host:port . +## +## Value: String +## Example: mqtt-tcp://127.0.0.1:1883 +rule.repub.3.address=mqtt-tcp://broker.emqx.io:1883 + +## Repub topic . +## +## Value: String +## Example: topic/repub +rule.repub.3.topic=topic/repub3 + +## Protocol version of the Repub. +## +## Value: Enum +## - 5: mqttv5 +## - 4: mqttv311 +## - 3: mqttv31 +rule.repub.3.proto_ver=4 + +## The ClientId of a Repub client. +## Default random string. +## +## Value: String +rule.repub.3.clientid=repub_client3 + +## Ping interval of a Repub client. +## +## Value: Duration +## Default: 10 seconds +rule.repub.3.keepalive=60 + +## The Clean start flag of a Repub client. +## +## Value: boolean +## Default: true +## +## NOTE: Some IoT platforms require clean_start +## must be set to 'true' +rule.repub.3.clean_start=true + +## The username for a Repub client. +## +## Value: String +rule.repub.3.username=username + +## The password for a Repub. +## +## Value: String +rule.repub.3.password=passwd + +## Rule engine option sql +## Rule engine sql clause. +## +## Value: String +rule.repub.event.publish.3.sql="SELECT * FROM "#" " + + +##==================================================================== +## MQTT Rule Engine for Mysql +##==================================================================== + +## Rule engine option mysql database name +## Rule engine db path, default is exec path. +## +## Value: File +rule.mysql.name=mysql_rule.db + +## Rule engine option mysql database table name +## Rule engine db table name. +## +## Value: String +rule.mysql.1.table=broker + +## The host for a mqsql client. +## +## Value: String +rule.mysql.1.host=localhost + +## The username for a mqsql client. +## +## Value: String +rule.mysql.1.username=username + +## The password for a Repub. +## +## Value: String +rule.mysql.1.password=password + +## Rule engine option sql +## Rule engine sql clause. +## +## Value: String +rule.mysql.event.publish.1.sql="SELECT payload.x.y as y, payload.z as z FROM "#" WHERE y > 10 and z != 'str'" + +## Rule engine option mysql database table name +## Rule engine db table name. +## +## Value: String +rule.mysql.2.table=broker1 + +## The host for a mqsql client. +## +## Value: String +rule.mysql.2.host=localhost + +## The username for a mqsql client. +## +## Value: String +rule.mysql.2.username=username + +## The password for a Repub. +## +## Value: String +rule.mysql.2.password=password + +## Rule engine option sql +## Rule engine sql clause. +## +## Value: String +rule.mysql.event.publish.2.sql="SELECT * FROM "abc"" + +## Rule engine option mysql database table name +## Rule engine db table name. +## +## Value: String +rule.mysql.3.table=broker2 + +## The host for a mqsql client. +## +## Value: String +rule.mysql.3.host=localhost + +## The username for a mqsql client. +## +## Value: String +rule.mysql.3.username=username + +## The password for a Repub. +## +## Value: String +rule.mysql.3.password=password + +## Rule engine option sql +## Rule engine sql clause. +## +## Value: String +rule.mysql.event.publish.3.sql="SELECT payload, qos FROM "#" WHERE qos > 0" + + diff --git a/VNode/_software_lib/nanomq-0.22.10/config/nanomq_pwd.conf b/VNode/_software_lib/nanomq-0.22.10/config/nanomq_pwd.conf new file mode 100644 index 00000000..d6f9964a --- /dev/null +++ b/VNode/_software_lib/nanomq-0.22.10/config/nanomq_pwd.conf @@ -0,0 +1,8 @@ + +# #==================================================================== +# # Configuration for Password +# #==================================================================== + +# # Write "username":"password" in this way. +"admin": "public" +"client": "public" \ No newline at end of file diff --git a/VNode/_software_lib/nanomq-0.22.10/config/nanomq_vsomeip_gateway.conf b/VNode/_software_lib/nanomq-0.22.10/config/nanomq_vsomeip_gateway.conf new file mode 100644 index 00000000..5787f26b --- /dev/null +++ b/VNode/_software_lib/nanomq-0.22.10/config/nanomq_vsomeip_gateway.conf @@ -0,0 +1,53 @@ +##==================================================================== +# # Configuration for MQTT VSOMEIP Gateway +# #==================================================================== +gateway.mqtt { + address = "mqtt-tcp://localhost:1885" + sub_topic = "topic/sub" + sub_qos = 0 + proto_ver = 4 + keepalive = 60 + clean_start = true + username = "username" + password = "passwd" + clientid = "vsomeip_gateway" + forward = "topic/pub" + parallel = 2 +} + +gateway.vsomeip { + service_id = "0x1111" + service_instance_id = "0x2222" + service_method_id = "0x3333" + service_event_id = "0x8778" + service_eventgroup_id = "0x4465" + conf_path = "/etc/vsomeip.json" +} + + +# #============================================================ +# # Http server +# #============================================================ +http_server { + # # http server port + # # + # # Value: 0 - 65535 + port = 8082 + # # parallel for http server + # # Handle a specified maximum number of outstanding requests + # # + # # Value: 1-infinity + parallel = 2 + # # username + # # + # # Basic authorization + # # + # # Value: String + username = admin + # # password + # # + # # Basic authorization + # # + # # Value: String + password = public +} diff --git a/VNode/_software_lib/nanomq-0.22.10/config/nanomq_zmq_gateway.conf b/VNode/_software_lib/nanomq-0.22.10/config/nanomq_zmq_gateway.conf new file mode 100644 index 00000000..da080caf --- /dev/null +++ b/VNode/_software_lib/nanomq-0.22.10/config/nanomq_zmq_gateway.conf @@ -0,0 +1,102 @@ +##==================================================================== +## Configuration for MQTT ZeroMQ Gateway +##==================================================================== + +gateway.mqtt { + ## MQTT Broker address: host:port . + ## + ## Value: String + ## Example: mqtt-tcp://127.0.0.1:1883 + address="mqtt-tcp://broker.emqx.io:1883" + ## Need to subscribe to remote broker topics + ## + ## Value: String + sub_topic="topic/sub" + ## Protocol version of the mqtt client. + ## + ## Value: Enum + ## - 5: mqttv5 + ## - 4: mqttv4 + ## - 3: mqttv3 + proto_ver=4 + ## Ping interval of a down mqtt client. + ## + ## Value: Duration + ## Default: 10 seconds + keepalive=60 + ## The Clean start flag of mqtt client. + ## + ## Value: boolean + ## Default: true + ## + ## NOTE: Some IoT platforms require clean_start + ## must be set to 'true' + clean_start=true + ## The username for mqtt client. + ## + ## Value: String + username="username" + ## The password for mqtt client. + ## + ## Value: String + password="passwd" + ## Topics that need to be forward to IoTHUB + ## + ## Value: String + ## Example: topic1/pub + forward="topic/pub" + ## parallel + ## Handle a specified maximum number of outstanding requests + ## + ## Value: 1-infinity + parallel=2 +} +gateway.zmq { + ## ZeroMQ Subscribe address: host:port . + ## + ## Value: String + ## Example: tcp://127.0.0.1:5560 + sub_address="tcp://127.0.0.1:5560" + ## ZeroMQ Publish address: host:port . + ## + ## Value: String + ## Example: tcp://127.0.0.1:5559 + pub_address="tcp://127.0.0.1:5559" + ## ZeroMQ subscription prefix + ## + ## Value: String + ## Example: sub_prefix + sub_pre="sub_prefix" + ## ZeroMQ publish prefix + ## + ## Value: String + ## Example: pub_prefix + pub_pre="pub_prefix" +} + +# #============================================================ +# # Http server +# #============================================================ +http_server { + # # http server port + # # + # # Value: 0 - 65535 + port = 8082 + # # parallel for http server + # # Handle a specified maximum number of outstanding requests + # # + # # Value: 1-infinity + parallel = 2 + # # username + # # + # # Basic authorization + # # + # # Value: String + username = admin + # # password + # # + # # Basic authorization + # # + # # Value: String + password = public +} diff --git a/VNode/_software_lib/nanomq-0.22.10/include/nanomq/CMakeLists.txt b/VNode/_software_lib/nanomq-0.22.10/include/nanomq/CMakeLists.txt new file mode 100644 index 00000000..d57bf829 --- /dev/null +++ b/VNode/_software_lib/nanomq-0.22.10/include/nanomq/CMakeLists.txt @@ -0,0 +1 @@ +aux_source_directory(. DIR_LIB_SRCS) diff --git a/VNode/_software_lib/nanomq-0.22.10/include/nanomq/acl_handler.h b/VNode/_software_lib/nanomq-0.22.10/include/nanomq/acl_handler.h new file mode 100644 index 00000000..45fe2d9b --- /dev/null +++ b/VNode/_software_lib/nanomq-0.22.10/include/nanomq/acl_handler.h @@ -0,0 +1,12 @@ +#ifndef NANOMQ_ACL_HANDLER_H +#define NANOMQ_ACL_HANDLER_H + +#include "nng/nng.h" +#include "nng/supplemental/nanolib/conf.h" +#include "nng/supplemental/nanolib/acl_conf.h" + +#ifdef ACL_SUPP +extern bool auth_acl( + conf *config, acl_action_type type, conn_param *param, const char *topic); +#endif +#endif diff --git a/VNode/_software_lib/nanomq-0.22.10/include/nanomq/aws_bridge.h b/VNode/_software_lib/nanomq-0.22.10/include/nanomq/aws_bridge.h new file mode 100644 index 00000000..9a81eca8 --- /dev/null +++ b/VNode/_software_lib/nanomq-0.22.10/include/nanomq/aws_bridge.h @@ -0,0 +1,10 @@ +#ifndef AWS_BRIDGE_H +#define AWS_BRIDGE_H + +#include "nng/supplemental/nanolib/conf.h" +#include "broker.h" + +extern int aws_bridge_client(conf_bridge_node *node); +extern void aws_bridge_forward(nano_work *work); + +#endif diff --git a/VNode/_software_lib/nanomq-0.22.10/include/nanomq/bridge.h b/VNode/_software_lib/nanomq-0.22.10/include/nanomq/bridge.h new file mode 100644 index 00000000..1e0f943c --- /dev/null +++ b/VNode/_software_lib/nanomq-0.22.10/include/nanomq/bridge.h @@ -0,0 +1,42 @@ +#ifndef NANOMQ_BRIDGE_H +#define NANOMQ_BRIDGE_H + +#include "nng/mqtt/mqtt_client.h" +#include "nng/nng.h" +#include "nng/supplemental/nanolib/conf.h" +#include "nng/supplemental/util/platform.h" +#include +#include +#include "broker.h" +#include "pub_handler.h" + +typedef struct { + nng_socket *sock; + conf_bridge_node *config; // bridge conf file + nng_mqtt_client *client; + nng_msg *connmsg; + conf *conf; //parent conf file + nng_mtx *switch_mtx; + nng_cv *switch_cv; + nng_mtx *exec_mtx; + nng_cv *exec_cv; + nng_duration cancel_timeout; +} bridge_param; + +extern bool topic_filter(const char *origin, const char *input); +extern int bridge_client( + nng_socket *sock, conf *config, conf_bridge_node *bridge_conf); +extern int hybrid_bridge_client( + nng_socket *sock, conf *config, conf_bridge_node *node); +extern void bridge_handle_topic_reflection(nano_work *work, conf_bridge *bridge); +extern nng_msg *bridge_publish_msg(const char *topic, uint8_t *payload, + uint32_t len, bool dup, uint8_t qos, bool retain, property *props); + +extern int bridge_reload(nng_socket *sock, conf *config, conf_bridge_node *node); + +extern int bridge_subscribe(nng_socket *sock, conf_bridge_node *node, + nng_mqtt_topic_qos *topic_qos, size_t sub_count, property *properties); +extern int bridge_unsubscribe(nng_socket *sock, conf_bridge_node *node, + nng_mqtt_topic *topic, size_t unsub_count, property *properties); + +#endif // NANOMQ_BRIDGE_H diff --git a/VNode/_software_lib/nanomq-0.22.10/include/nanomq/broker.h b/VNode/_software_lib/nanomq-0.22.10/include/nanomq/broker.h new file mode 100644 index 00000000..7af47fd3 --- /dev/null +++ b/VNode/_software_lib/nanomq-0.22.10/include/nanomq/broker.h @@ -0,0 +1,106 @@ +#ifndef NANOMQ_BROKER_H +#define NANOMQ_BROKER_H + +#define HTTP_CTX_NUM 4 + +#include "nng/supplemental/nanolib/conf.h" +#include "nng/supplemental/nanolib/nanolib.h" +#include "nng/nng.h" +#include "nng/protocol/mqtt/mqtt.h" +#include "nng/supplemental/util/platform.h" +#include "nng/mqtt/packet.h" +#include "hashmap.h" + +#define PROTO_MQTT_BROKER 0x00 +#define PROTO_MQTT_BRIDGE 0x01 +#define PROTO_AWS_BRIDGE 0x02 +#define PROTO_HTTP_SERVER 0x03 +#define PROTO_ICEORYX_BRIDGE 0x04 + +#define STATISTICS + +#if defined(ENABLE_NANOMQ_TESTS) + #undef STATISTICS +#endif + +typedef struct work nano_work; +struct work { + enum { + INIT, + RECV, + WAIT, + SEND, // Actions after sending msg + HOOK, // Rule Engine + END, // Clear state and cache before disconnect + CLOSE // sending disconnect packet and err code + } state; + uint8_t proto; // logic proto + uint8_t proto_ver; // MQTT version cache + uint8_t flag; // flag for webhook & rule_engine + nng_aio * aio; + nng_msg * msg; + nng_msg ** msg_ret; + nng_ctx ctx; // ctx for mqtt broker + nng_ctx extra_ctx; // ctx for bridging/http post + nng_pipe pid; + dbtree * db; + dbtree * db_ret; + conf * config; + + conf_bridge_node *node; // only works for bridge ctx + reason_code code; // MQTT reason code + + nng_socket hook_sock; + + struct pipe_content * pipe_ct; + conn_param * cparam; + struct pub_packet_struct *pub_packet; + packet_subscribe * sub_pkt; + packet_unsubscribe * unsub_pkt; + + void *sqlite_db; + + +#if defined(SUPP_PLUGIN) + property *user_property; +#endif +#if defined(SUPP_ICEORYX) + void *iceoryx_suber; + void *iceoryx_puber; + nng_socket iceoryx_sock; +#endif +}; + +struct client_ctx { + nng_pipe pid; +#ifdef STATISTICS + nng_atomic_u64 *recv_cnt; +#endif + conn_param *cparam; + uint32_t prop_len; + property *properties; + uint8_t proto_ver; +}; + +static int broker_start_rc; + +typedef struct client_ctx client_ctx; + +extern int broker_start(int argc, char **argv); +extern int broker_stop(int argc, char **argv); +extern int broker_restart(int argc, char **argv); +extern int broker_reload(int argc, char **argv); +extern int broker_dflt(int argc, char **argv); +extern void bridge_send_cb(void *arg); +extern void *broker_start_with_conf(void *nmq_conf); + +#ifdef STATISTICS +extern uint64_t nanomq_get_message_in(void); +extern uint64_t nanomq_get_message_out(void); +extern uint64_t nanomq_get_message_drop(void); +#endif +extern dbtree * get_broker_db(void); +extern struct hashmap_s *get_hashmap(void); +extern int rule_engine_insert_sql(nano_work *work); + +#endif diff --git a/VNode/_software_lib/nanomq-0.22.10/include/nanomq/cmd_proc.h b/VNode/_software_lib/nanomq-0.22.10/include/nanomq/cmd_proc.h new file mode 100644 index 00000000..7ccf8a03 --- /dev/null +++ b/VNode/_software_lib/nanomq-0.22.10/include/nanomq/cmd_proc.h @@ -0,0 +1,20 @@ +#ifndef NANOMQ_CMD_PROC_H +#define NANOMQ_CMD_PROC_H + +#define CMD_IPC_URL "ipc:///tmp/nanomq_cmd.ipc" +#define IPC_URL_PATH "/tmp/nanomq_cmd.ipc" +// #define CMD_IPC_URL "tcp://127.0.0.1:10000" +#define CMD_PROC_PARALLEL 1 + +#include "nng/nng.h" +#include "nng/supplemental/nanolib/conf.h" +#include "nng/supplemental/nanolib/log.h" + +typedef struct cmd_work cmd_work; + +extern void cmd_server_cb(void *arg); +extern cmd_work *alloc_cmd_work(nng_socket sock, conf *config); +extern void start_cmd_client(const char *cmd, const char *url); +extern char * encode_client_cmd(const char *conf_file, int type); + +#endif // NANOMQ_CMD_PROC_H diff --git a/VNode/_software_lib/nanomq-0.22.10/include/nanomq/conf_api.h b/VNode/_software_lib/nanomq-0.22.10/include/nanomq/conf_api.h new file mode 100644 index 00000000..210f5f1c --- /dev/null +++ b/VNode/_software_lib/nanomq-0.22.10/include/nanomq/conf_api.h @@ -0,0 +1,43 @@ +#ifndef NANOMQ_CONF_API_H +#define NANOMQ_CONF_API_H + +#include "nng/supplemental/nanolib/conf.h" +#include "nng/supplemental/nanolib/cJSON.h" +#include "nng/supplemental/nanolib/file.h" +#include "nng/supplemental/nanolib/utils.h" +#include "nng/supplemental/nanolib/cvector.h" +#include "rest_api.h" + +extern cJSON *get_reload_config(conf *config); +extern cJSON *get_basic_config(conf *config); +extern cJSON *get_tls_config(conf_tls *tls, bool is_server); +extern cJSON *get_auth_config(conf_auth *auth); +extern cJSON *get_auth_http_config(conf_auth_http *auth_http); +extern cJSON *get_websocket_config(conf_websocket *ws); +extern cJSON *get_http_config(conf_http_server *http); +extern cJSON *get_sqlite_config(conf_sqlite *sqlite); +extern cJSON *get_bridge_config(conf_bridge *bridge, const char *node_name); +extern void set_bridge_node_conf( + conf_bridge *config, cJSON *node_obj, const char *name); + +extern void set_reload_config(cJSON *json, conf *config); +extern void set_basic_config(cJSON *json, conf *config); +extern void set_tls_config( + cJSON *json, const char *conf_path, conf_tls *tls, const char *key_prefix); +extern void set_auth_config( + cJSON *json, const char *conf_path, conf_auth *auth); +extern void set_auth_http_config( + cJSON *json, const char *conf_path, conf_auth_http *auth); +extern void set_http_config( + cJSON *json, const char *conf_path, conf_http_server *http); +extern void set_websocket_config( + cJSON *json, const char *conf_path, conf_websocket *ws); +extern void set_sqlite_config(cJSON *json, const char *conf_path, + conf_sqlite *sqlite, const char *key_prefix); + +extern void reload_basic_config(conf *cur_conf, conf *new_conf); +extern void reload_sqlite_config(conf_sqlite *cur_conf, conf_sqlite *new_conf); +extern void reload_auth_config(conf_auth *cur_conf, conf_auth *new_conf); +extern void reload_log_config(conf *cur_conf, conf *new_conf); + +#endif diff --git a/VNode/_software_lib/nanomq-0.22.10/include/nanomq/const_strings.h b/VNode/_software_lib/nanomq-0.22.10/include/nanomq/const_strings.h new file mode 100644 index 00000000..077fe655 --- /dev/null +++ b/VNode/_software_lib/nanomq-0.22.10/include/nanomq/const_strings.h @@ -0,0 +1,2 @@ + +extern const char tmp_example[]; diff --git a/VNode/_software_lib/nanomq-0.22.10/include/nanomq/core_mqtt_config.h b/VNode/_software_lib/nanomq-0.22.10/include/nanomq/core_mqtt_config.h new file mode 100644 index 00000000..07ba5145 --- /dev/null +++ b/VNode/_software_lib/nanomq-0.22.10/include/nanomq/core_mqtt_config.h @@ -0,0 +1,79 @@ +/* + * AWS IoT Device SDK for Embedded C 202108.00 + * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * 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 CORE_MQTT_CONFIG_H_ +#define CORE_MQTT_CONFIG_H_ + +/**************************************************/ +/******* DO NOT CHANGE the following order ********/ +/**************************************************/ + +/* Include logging header files and define logging macros in the following order: + * 1. Include the header file "logging_levels.h". + * 2. Define the LIBRARY_LOG_NAME and LIBRARY_LOG_LEVEL macros depending on + * the logging configuration for MQTT. + * 3. Include the header file "logging_stack.h", if logging is enabled for MQTT. + */ + +#include + +/* Logging configuration for the MQTT library. */ +#ifndef LIBRARY_LOG_NAME + #define LIBRARY_LOG_NAME "MQTT" +#endif + +#ifndef LIBRARY_LOG_LEVEL + #define LIBRARY_LOG_LEVEL LOG_NONE +#endif + +#include + +/************ End of logging configuration ****************/ + +/** + * @brief Determines the maximum number of MQTT PUBLISH messages, pending + * acknowledgement at a time, that are supported for incoming and outgoing + * direction of messages, separately. + * + * QoS 1 and 2 MQTT PUBLISHes require acknowledgement from the server before + * they can be completed. While they are awaiting the acknowledgement, the + * client must maintain information about their state. The value of this + * macro sets the limit on how many simultaneous PUBLISH states an MQTT + * context maintains, separately, for both incoming and outgoing direction of + * PUBLISHes. + * + * @note The MQTT context maintains separate state records for outgoing + * and incoming PUBLISHes, and thus, 2 * MQTT_STATE_ARRAY_MAX_COUNT amount + * of memory is statically allocated for the state records. + */ +#define MQTT_STATE_ARRAY_MAX_COUNT ( 10U ) + +/** + * @brief Number of milliseconds to wait for a ping response to a ping + * request as part of the keep-alive mechanism. + * + * If a ping response is not received before this timeout, then + * #MQTT_ProcessLoop will return #MQTTKeepAliveTimeout. + */ +#define MQTT_PINGRESP_TIMEOUT_MS ( 5000U ) + +#endif /* ifndef CORE_MQTT_CONFIG_H_ */ diff --git a/VNode/_software_lib/nanomq-0.22.10/include/nanomq/db_cli.h b/VNode/_software_lib/nanomq-0.22.10/include/nanomq/db_cli.h new file mode 100644 index 00000000..14715d74 --- /dev/null +++ b/VNode/_software_lib/nanomq-0.22.10/include/nanomq/db_cli.h @@ -0,0 +1,12 @@ +#ifndef DB_CLI_H +#define DB_CLI_H + +#include "fdb_version.h" +#include +#include + +#include +#include + +FDBDatabase* openDatabase(pthread_t* netThread); +#endif \ No newline at end of file diff --git a/VNode/_software_lib/nanomq-0.22.10/include/nanomq/hashmap.h b/VNode/_software_lib/nanomq-0.22.10/include/nanomq/hashmap.h new file mode 100644 index 00000000..8bb60d23 --- /dev/null +++ b/VNode/_software_lib/nanomq-0.22.10/include/nanomq/hashmap.h @@ -0,0 +1,113 @@ +#ifndef SHEREDOM_HASHMAP_H_INCLUDED +#define SHEREDOM_HASHMAP_H_INCLUDED + +#if defined(_MSC_VER) +// Workaround a bug in the MSVC runtime where it uses __cplusplus when not +// defined. +#pragma warning(push, 0) +#pragma warning(disable : 4668) +#endif +#include +#include +#include +#include "nng/nng.h" +#include "nng/supplemental/util/platform.h" + + +#if (defined(_MSC_VER) && defined(__AVX__)) || \ + (!defined(_MSC_VER) && defined(__SSE4_2__)) +#define HASHMAP_SSE42 +#endif + +#if defined(HASHMAP_SSE42) +#include +#endif + +#if defined(_MSC_VER) +#pragma warning(pop) +#endif + +#if defined(_MSC_VER) +#pragma warning(push) +/* Stop MSVC complaining about unreferenced functions */ +#pragma warning(disable : 4505) +/* Stop MSVC complaining about not inlining functions */ +#pragma warning(disable : 4710) +/* Stop MSVC complaining about inlining functions! */ +#pragma warning(disable : 4711) +#elif defined(__clang__) +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wunused-function" +#endif + +#if defined(_MSC_VER) +#define HASHMAP_USED +#elif defined(__GNUC__) +#define HASHMAP_USED __attribute__((used)) +#else +#define HASHMAP_USED +#endif + +typedef struct hashmap_s hashmap_s; +/* We need to keep keys and values. */ +struct hashmap_element_s { + const char *key; + unsigned key_len; + int in_use; + uint32_t data; +}; + +/* A hashmap has some maximum size and current size, as well as the data to + * hold. */ +struct hashmap_s { + unsigned table_size; + unsigned size; + struct hashmap_element_s *data; + +}; + + +#define HASHMAP_MAX_CHAIN_LENGTH (8) + +#if defined(__cplusplus) +extern "C" { +#endif + +int nano_hashmap_create(const unsigned initial_size, + struct hashmap_s * out_hashmap) HASHMAP_USED; + +int nano_hashmap_put(struct hashmap_s * hashmap, const char *const key, + const unsigned len, uint32_t value) HASHMAP_USED; + +uint32_t nano_hashmap_get(const struct hashmap_s *const hashmap, + const char *const key, + const unsigned len) HASHMAP_USED; + +int nano_hashmap_remove(struct hashmap_s * m, const char *const key, + const unsigned len); + +void nano_hashmap_destroy(struct hashmap_s * m); + + +#if defined(__cplusplus) +} +#endif + +#if defined(__cplusplus) +#define HASHMAP_CAST(type, x) static_cast(x) +#define HASHMAP_PTR_CAST(type, x) reinterpret_cast(x) +#define HASHMAP_NULL NULL +#else +#define HASHMAP_CAST(type, x) ((type)x) +#define HASHMAP_PTR_CAST(type, x) ((type)x) +#define HASHMAP_NULL 0 +#endif + + +#if defined(_MSC_VER) +#pragma warning(pop) +#elif defined(__clang__) +#pragma clang diagnostic pop +#endif + +#endif \ No newline at end of file diff --git a/VNode/_software_lib/nanomq-0.22.10/include/nanomq/mqtt_api.h b/VNode/_software_lib/nanomq-0.22.10/include/nanomq/mqtt_api.h new file mode 100644 index 00000000..445c751e --- /dev/null +++ b/VNode/_software_lib/nanomq-0.22.10/include/nanomq/mqtt_api.h @@ -0,0 +1,38 @@ +#ifndef MQTT_API_H +#define MQTT_API_H + +#include "nng/mqtt/mqtt_client.h" +#include "nng/protocol/mqtt/mqtt.h" +#include "nng/supplemental/nanolib/conf.h" +#include "nng/supplemental/tls/tls.h" +#include "nng/supplemental/util/options.h" +#include "nng/supplemental/util/platform.h" + +#define INPROC_SERVER_URL "inproc://inproc_server" + +int nano_listen( + nng_socket sid, const char *addr, nng_listener *lp, int flags, conf *conf); +int init_listener_tls(nng_listener l, conf_tls *tls); + +extern int decode_common_mqtt_msg(nng_msg **dest, nng_msg *src); +extern int encode_common_mqtt_msg( + nng_msg **dest, nng_msg *src, const char *clientid, uint8_t proto_ver); + +extern int log_init(conf_log *log); +extern int log_fini(conf_log *log); + +extern char *nano_pipe_get_local_address(nng_pipe p); +extern uint8_t *nano_pipe_get_local_address6(nng_pipe p); +extern uint16_t nano_pipe_get_local_port(nng_pipe p); +extern uint16_t nano_pipe_get_local_port6(nng_pipe p); + +#if defined(SUPP_ICEORYX) +#include "nng/iceoryx_shm/iceoryx_shm.h" +extern int nano_iceoryx_send_nng_msg( + nng_iceoryx_puber *puber, nng_msg *msg, nng_socket *sock); +extern int nano_iceoryx_recv_nng_msg( + nng_iceoryx_suber *suber, nng_msg *icemsg, nng_msg **msg); +extern bool nano_iceoryx_topic_filter(char *icetopic, char *topic, uint32_t topicsz); +#endif + +#endif // MQTT_API_H diff --git a/VNode/_software_lib/nanomq-0.22.10/include/nanomq/nanomq.h b/VNode/_software_lib/nanomq-0.22.10/include/nanomq/nanomq.h new file mode 100644 index 00000000..701dc75b --- /dev/null +++ b/VNode/_software_lib/nanomq-0.22.10/include/nanomq/nanomq.h @@ -0,0 +1,67 @@ +#ifndef NANOMQ_NANOMQ_H +#define NANOMQ_NANOMQ_H + +#include "nng/supplemental/nanolib/log.h" + +#ifndef _GNU_SOURCE +#define _GNU_SOURCE +#endif + +#define NNI_PUT16(ptr, u) \ + do { \ + (ptr)[0] = (uint8_t)(((uint16_t)(u)) >> 8u); \ + (ptr)[1] = (uint8_t)((uint16_t)(u)); \ + } while (0) + +#define NNI_PUT32(ptr, u) \ + do { \ + (ptr)[0] = (uint8_t)(((uint32_t)(u)) >> 24u); \ + (ptr)[1] = (uint8_t)(((uint32_t)(u)) >> 16u); \ + (ptr)[2] = (uint8_t)(((uint32_t)(u)) >> 8u); \ + (ptr)[3] = (uint8_t)((uint32_t)(u)); \ + } while (0) + +#define NNI_PUT64(ptr, u) \ + do { \ + (ptr)[0] = (uint8_t)(((uint64_t)(u)) >> 56u); \ + (ptr)[1] = (uint8_t)(((uint64_t)(u)) >> 48u); \ + (ptr)[2] = (uint8_t)(((uint64_t)(u)) >> 40u); \ + (ptr)[3] = (uint8_t)(((uint64_t)(u)) >> 32u); \ + (ptr)[4] = (uint8_t)(((uint64_t)(u)) >> 24u); \ + (ptr)[5] = (uint8_t)(((uint64_t)(u)) >> 16u); \ + (ptr)[6] = (uint8_t)(((uint64_t)(u)) >> 8u); \ + (ptr)[7] = (uint8_t)((uint64_t)(u)); \ + } while (0) + +#define NNI_GET16(ptr, v) \ + v = (((uint16_t)((uint8_t)(ptr)[0])) << 8u) + \ + (((uint16_t)(uint8_t)(ptr)[1])) + +#define NNI_GET32(ptr, v) \ + v = (((uint32_t)((uint8_t)(ptr)[0])) << 24u) + \ + (((uint32_t)((uint8_t)(ptr)[1])) << 16u) + \ + (((uint32_t)((uint8_t)(ptr)[2])) << 8u) + \ + (((uint32_t)(uint8_t)(ptr)[3])) + +#define NNI_GET64(ptr, v) \ + v = (((uint64_t)((uint8_t)(ptr)[0])) << 56u) + \ + (((uint64_t)((uint8_t)(ptr)[1])) << 48u) + \ + (((uint64_t)((uint8_t)(ptr)[2])) << 40u) + \ + (((uint64_t)((uint8_t)(ptr)[3])) << 32u) + \ + (((uint64_t)((uint8_t)(ptr)[4])) << 24u) + \ + (((uint64_t)((uint8_t)(ptr)[5])) << 16u) + \ + (((uint64_t)((uint8_t)(ptr)[6])) << 8u) + \ + (((uint64_t)(uint8_t)(ptr)[7])) + +#define NANO_UNUSED(x) (x) __attribute__((unused)) + +#define NANO_NNG_FATAL(s, rv) \ + do { \ + log_fatal(s); \ + nng_fatal((s), (rv)); \ + } while(0) + +extern int get_cache_argc(); +extern char **get_cache_argv(); + +#endif diff --git a/VNode/_software_lib/nanomq-0.22.10/include/nanomq/nanomq_rule.h b/VNode/_software_lib/nanomq-0.22.10/include/nanomq/nanomq_rule.h new file mode 100644 index 00000000..e0581024 --- /dev/null +++ b/VNode/_software_lib/nanomq-0.22.10/include/nanomq/nanomq_rule.h @@ -0,0 +1,19 @@ +#ifndef NANOMQ_RULE_H +#define NANOMQ_RULE_H + +#include "nng/mqtt/mqtt_client.h" +#include "nng/supplemental/sqlite/sqlite3.h" +#include "nng/supplemental/nanolib/conf.h" +#include "nng/nng.h" +#include +#include + +#if defined(SUPP_RULE_ENGINE) +extern int nano_client(nng_socket *sock, repub_t *repub); +extern int nano_client_publish(nng_socket *sock, const char *topic, + uint8_t *payload, uint32_t len, uint8_t qos, property *props); +extern int nanomq_client_sqlite(conf_rule *cr, bool init_last); +extern int nanomq_client_mysql(conf_rule *cr, bool init_last); +#endif + +#endif // NANOMQ_RULE_H \ No newline at end of file diff --git a/VNode/_software_lib/nanomq-0.22.10/include/nanomq/plugin.h b/VNode/_software_lib/nanomq-0.22.10/include/nanomq/plugin.h new file mode 100644 index 00000000..6a0146b1 --- /dev/null +++ b/VNode/_software_lib/nanomq-0.22.10/include/nanomq/plugin.h @@ -0,0 +1,36 @@ +// +// Copyright 2024 NanoMQ Team, Inc. +// +// This software is supplied under the terms of the MIT License, a +// copy of which should be located in the distribution where this +// file was obtained (LICENSE.txt). A copy of the license may also be +// found online at https://opensource.org/licenses/MIT. +// +#ifndef NANOMQ_PLUGIN_H +#define NANOMQ_PLUGIN_H + +#include "nng/nng.h" +#include "nng/supplemental/nanolib/conf.h" +#include "nng/supplemental/nanolib/log.h" + +struct nano_plugin { + char *path; + int (*init)(void); +}; + +enum hook_point { + HOOK_USER_PROPERTY, +}; + +struct plugin_hook { + unsigned int point; + int (*cb)(void *data); +}; + +extern int plugin_hook_register(unsigned int point, int (*cb)(void *data)); +extern int plugin_hook_call(unsigned int point, void *data); +extern int plugin_register(char *path); +extern void plugins_clear(); +extern int plugin_init(struct nano_plugin *plugin); + +#endif // NANOMQ_PLUGIN_H diff --git a/VNode/_software_lib/nanomq-0.22.10/include/nanomq/process.h b/VNode/_software_lib/nanomq-0.22.10/include/nanomq/process.h new file mode 100644 index 00000000..d74ae251 --- /dev/null +++ b/VNode/_software_lib/nanomq-0.22.10/include/nanomq/process.h @@ -0,0 +1,14 @@ +#ifndef PROCESS_H +#define PROCESS_H + +#ifndef _GNU_SOURCE +#define _GNU_SOURCE +#endif + +extern int process_is_alive(int pid); +extern int process_send_signal(int pid, int signal); +extern int pidgrp_send_signal(int pid, int signal); +extern int process_daemonize(void); +extern int process_create_child(int (*child_run)(void *), void *data); + +#endif \ No newline at end of file diff --git a/VNode/_software_lib/nanomq-0.22.10/include/nanomq/pub_handler.h b/VNode/_software_lib/nanomq-0.22.10/include/nanomq/pub_handler.h new file mode 100644 index 00000000..5d54b127 --- /dev/null +++ b/VNode/_software_lib/nanomq-0.22.10/include/nanomq/pub_handler.h @@ -0,0 +1,71 @@ +/** + * Created by Alvin on 2020/7/25. + */ + +#ifndef NANOMQ_PUB_HANDLER_H +#define NANOMQ_PUB_HANDLER_H + +#include "broker.h" +#include +#include +#include + +typedef uint32_t variable_integer; + +// MQTT Fixed header +struct fixed_header { + // flag_bits + uint8_t retain : 1; + uint8_t qos : 2; + uint8_t dup : 1; + // packet_types + uint8_t packet_type : 4; + // remaining length + uint32_t remain_len; +}; + +// MQTT Variable header +union variable_header { + struct { + uint16_t packet_id; + struct mqtt_string topic_name; + property *properties; + uint32_t prop_len; + } publish; + + struct { + uint16_t packet_id; + reason_code reason_code; + property *properties; + uint32_t prop_len; + } pub_arrc, puback, pubrec, pubrel, pubcomp; +}; + +struct mqtt_payload { + uint8_t *data; + uint32_t len; +}; + +struct pub_packet_struct { + struct fixed_header fixed_header; + union variable_header var_header; + struct mqtt_payload payload; +}; + +struct pipe_content { + mqtt_msg_info *msg_infos; +}; + +bool encode_pub_message( + nng_msg *dest_msg, nano_work *work, mqtt_control_packet_types cmd); +reason_code decode_pub_message(nano_work *work, uint8_t proto); +void free_pub_packet(struct pub_packet_struct *pub_packet); +void free_msg_infos(mqtt_msg_info *msg_infos); +void init_pipe_content(struct pipe_content *pipe_ct); +void init_pub_packet_property(struct pub_packet_struct *pub_packet); +bool check_msg_exp(nng_msg *msg, property *prop); + +reason_code handle_pub(nano_work *work, struct pipe_content *pipe_ct, + uint8_t proto, bool is_event); + +#endif // NNG_PUB_HANDLER_H diff --git a/VNode/_software_lib/nanomq-0.22.10/include/nanomq/rest_api.h b/VNode/_software_lib/nanomq-0.22.10/include/nanomq/rest_api.h new file mode 100644 index 00000000..2e4f2c1d --- /dev/null +++ b/VNode/_software_lib/nanomq-0.22.10/include/nanomq/rest_api.h @@ -0,0 +1,130 @@ +// +// Copyright 2020 NanoMQ Team, Inc. +// +// This software is supplied under the terms of the MIT License, a +// copy of which should be located in the distribution where this +// file was obtained (LICENSE.txt). A copy of the license may also be +// found online at https://opensource.org/licenses/MIT. +// + +#ifndef REST_API_H +#define REST_API_H + +#include "web_server.h" +#include "mqtt_api.h" +#include +#include +#include +#include +#include + +#define REST_URI_ROOT "/api/v4" +#define REST_HOST "http://0.0.0.0:%u" +#define REST_URL REST_HOST REST_URI_ROOT + +#define getNumberValue(obj, item, key, value, rv) \ + { \ + item = cJSON_GetObjectItem(obj, key); \ + if (cJSON_IsNumber(item)) { \ + value = cJSON_GetNumberValue(item); \ + rv = (0); \ + } else { \ + rv = (-1); \ + } \ + } + +#define getBoolValue(obj, item, key, value, rv) \ + { \ + item = cJSON_GetObjectItem(obj, key); \ + if (cJSON_IsBool(item)) { \ + value = cJSON_IsTrue(item); \ + rv = (0); \ + } else { \ + rv = (-1); \ + } \ + } + +#define getStringValue(obj, item, key, value, rv) \ + { \ + item = cJSON_GetObjectItem(obj, key); \ + if (cJSON_IsString(item)) { \ + value = cJSON_GetStringValue(item); \ + rv = (0); \ + } else { \ + rv = (-1); \ + } \ + } + +enum result_code { + SUCCEED = 0, + RPC_ERROR = 101, + UNKNOWN_MISTAKE = 102, + WRONG_USERNAME_OR_PASSWORD = 103, + EMPTY_USERNAME_OR_PASSWORD = 104, + USER_DOES_NOT_EXIST = 105, + ADMIN_CANNOT_BE_DELETED = 106, + MISSING_KEY_REQUEST_PARAMES = 107, + REQ_PARAM_ERROR = 108, + REQ_PARAMS_JSON_FORMAT_ILLEGAL = 109, + PLUGIN_IS_ENABLED = 110, + PLUGIN_IS_CLOSED = 111, + CLIENT_IS_OFFLINE = 112, + USER_ALREADY_EXISTS = 113, + OLD_PASSWORD_IS_WRONG = 114, + ILLEGAL_SUBJECT = 115, + TOKEN_EXPIRED = 116, + PARAMS_HOCON_FORMAT_ILLEGAL = 117, + WRITE_CONFIG_FAILED = 118, +}; + +typedef struct http_msg { + uint16_t status; + int request; + size_t content_type_len; + char * content_type; + size_t method_len; + char * method; + size_t uri_len; + char * uri; + size_t token_len; + char * token; + size_t data_len; + char * data; + bool encrypt_data; +} http_msg; + +extern void put_http_msg(http_msg *msg, const char *content_type, + const char *method, const char *uri, const char *token, const char *data, + size_t data_sz); +extern void destory_http_msg(http_msg *msg); +extern http_msg process_request( + http_msg *msg, conf_http_server *config, nng_socket *sock); + +#define GET_METHOD "GET" +#define POST_METHOD "POST" +#define PUT_METHOD "PUT" +#define DELETE_METHOD "DELETE" + +#define REQ_ENDPOINTS 1 +#define REQ_BROKERS 2 +#define REQ_NODES 3 +#define REQ_SUBSCRIPTIONS 4 +#define REQ_CLIENTS 5 +#define REQ_LOGIN 6 +#define REQ_LOGOUT 7 + +#define REQ_CTRL 10 +#define REQ_GET_CONFIG 11 +#define REQ_SET_CONFIG 12 +#define REQ_TREE 13 + +#define cJSON_AddStringOrNullToObject(obj, name, value) \ + { \ + if (value) { \ + cJSON_AddStringToObject(obj, name, value); \ + } else { \ + cJSON_AddNullToObject(obj, name); \ + } \ + } + +#endif \ No newline at end of file diff --git a/VNode/_software_lib/nanomq-0.22.10/include/nanomq/sub_handler.h b/VNode/_software_lib/nanomq-0.22.10/include/nanomq/sub_handler.h new file mode 100644 index 00000000..a05e926f --- /dev/null +++ b/VNode/_software_lib/nanomq-0.22.10/include/nanomq/sub_handler.h @@ -0,0 +1,51 @@ +#ifndef MQTT_SUBSCRIBE_HANDLE_H +#define MQTT_SUBSCRIBE_HANDLE_H + +#include +#include + +#include "broker.h" + +typedef struct { + uint32_t pid; + dbtree *db; +} sub_destroy_info; + +/* + * Use to decode sub msg. + */ +int decode_sub_msg(nano_work *); + +/* + * Use to encode an ack for sub msg + */ +int encode_suback_msg(nng_msg *, nano_work *); + +int sub_ctx_handle(nano_work *); + +/* + * Delete a client ctx from topic node in dbtree + */ +int sub_ctx_del(void *db, char *topic, uint32_t pid); + +/* + * Free the client ctx + */ +void sub_ctx_free(client_ctx *); + +/* + * A wrap for sub ctx free + */ +void * wrap_sub_ctx_free_cb(void *arg); + +/* + * Free a packet_subscribe. + */ +void sub_pkt_free(packet_subscribe *); + +/* + * Delete all refs in dbtree about client ctx + */ +void destroy_sub_client(uint32_t pid, dbtree * db); + +#endif diff --git a/VNode/_software_lib/nanomq-0.22.10/include/nanomq/unsub_handler.h b/VNode/_software_lib/nanomq-0.22.10/include/nanomq/unsub_handler.h new file mode 100644 index 00000000..5e6ed040 --- /dev/null +++ b/VNode/_software_lib/nanomq-0.22.10/include/nanomq/unsub_handler.h @@ -0,0 +1,14 @@ +#ifndef MQTT_UNSUBSCRIBE_HANDLE_H +#define MQTT_UNSUBSCRIBE_HANDLE_H + +#include + +#include "broker.h" +#include + +int decode_unsub_msg(nano_work *); +int encode_unsuback_msg(nng_msg *, nano_work *); +int unsub_ctx_handle(nano_work *); +void unsub_pkt_free(packet_unsubscribe *); + +#endif // MQTT_UNSUBSCRIBE_HANDLE_H diff --git a/VNode/_software_lib/nanomq-0.22.10/include/nanomq/version.h b/VNode/_software_lib/nanomq-0.22.10/include/nanomq/version.h new file mode 100644 index 00000000..029a0584 --- /dev/null +++ b/VNode/_software_lib/nanomq-0.22.10/include/nanomq/version.h @@ -0,0 +1,5 @@ +#define NANO_VER_MAJOR 0 +#define NANO_VER_MINOR 22 +#define NANO_VER_PATCH 10 +#define NANO_VER_ID_SHORT "15" + diff --git a/VNode/_software_lib/nanomq-0.22.10/include/nanomq/web_server.h b/VNode/_software_lib/nanomq-0.22.10/include/nanomq/web_server.h new file mode 100644 index 00000000..e0958545 --- /dev/null +++ b/VNode/_software_lib/nanomq-0.22.10/include/nanomq/web_server.h @@ -0,0 +1,35 @@ +// +// Copyright 2020 NanoMQ Team, Inc. +// +// This software is supplied under the terms of the MIT License, a +// copy of which should be located in the distribution where this +// file was obtained (LICENSE.txt). A copy of the license may also be +// found online at https://opensource.org/licenses/MIT. +// + +#ifndef WEB_SERVER_H +#define WEB_SERVER_H + +#include "nng/nng.h" +#include "nng/supplemental/util/platform.h" +#include "nng/supplemental/nanolib/conf.h" +#include +#include +#include +#include + +#define HTTP_DEFAULT_USER "admin" +#define HTTP_DEFAULT_PASSWORD "public" +#define HTTP_DEFAULT_PORT 8081 + +extern int start_rest_server(conf *conf); +extern void stop_rest_server(void); + +extern void set_http_server_conf(conf_http_server *conf); +extern conf_http_server *get_http_server_conf(void); + +extern void set_global_conf(conf *config); +extern conf * get_global_conf(void); +extern char * get_jwt_key(void); +extern nng_time get_boot_time(void); +#endif diff --git a/VNode/_software_lib/nanomq-0.22.10/include/nanomq/webhook_inproc.h b/VNode/_software_lib/nanomq-0.22.10/include/nanomq/webhook_inproc.h new file mode 100644 index 00000000..d573f8dd --- /dev/null +++ b/VNode/_software_lib/nanomq-0.22.10/include/nanomq/webhook_inproc.h @@ -0,0 +1,13 @@ +#ifndef WEBHOOK_INPROC_H +#define WEBHOOK_INPROC_H + +#include "nng/supplemental/nanolib/conf.h" +#include "nng/nng.h" + +#define HOOK_IPC_URL "ipc:///tmp/nanomq_hook.ipc" +#define EXTERNAL2NANO_IPC "EX2NANO" + +extern int start_hook_service(conf *conf); +extern int stop_hook_service(void); + +#endif diff --git a/VNode/_software_lib/nanomq-0.22.10/include/nanomq/webhook_post.h b/VNode/_software_lib/nanomq-0.22.10/include/nanomq/webhook_post.h new file mode 100644 index 00000000..970fc04b --- /dev/null +++ b/VNode/_software_lib/nanomq-0.22.10/include/nanomq/webhook_post.h @@ -0,0 +1,20 @@ +#ifndef WEBHOOK_POST_H +#define WEBHOOK_POST_H + +#include "webhook_inproc.h" +#include "broker.h" + +extern int webhook_msg_publish(nng_socket *sock, conf_web_hook *hook_conf, + pub_packet_struct *pub_packet, const char *username, + const char *client_id); +extern int webhook_client_connack(nng_socket *sock, conf_web_hook *hook_conf, + uint8_t proto_ver, uint16_t keepalive, uint8_t reason, + const char *username, const char *client_id); +extern int webhook_client_disconnect(nng_socket *sock, + conf_web_hook *hook_conf, uint8_t proto_ver, uint16_t keepalive, + uint8_t reason, const char *username, const char *client_id); +extern int hook_entry(nano_work *work, uint8_t reason); +extern int hook_exchange_init(conf *nanomq_conf, uint64_t num_ctx); +extern int hook_exchange_sender_init(conf *nanomq_conf, struct work **works, uint64_t num_ctx); + +#endif diff --git a/VNode/_software_lib/nanomq-0.22.10/include/nng/compat/nanomsg/bus.h b/VNode/_software_lib/nanomq-0.22.10/include/nng/compat/nanomsg/bus.h new file mode 100644 index 00000000..004a9ac6 --- /dev/null +++ b/VNode/_software_lib/nanomq-0.22.10/include/nng/compat/nanomsg/bus.h @@ -0,0 +1,33 @@ +// +// Copyright 2018 Staysail Systems, Inc. +// Copyright 2018 Capitar IT Group BV +// +// This software is supplied under the terms of the MIT License, a +// copy of which should be located in the distribution where this +// file was obtained (LICENSE.txt). A copy of the license may also be +// found online at https://opensource.org/licenses/MIT. +// + +#ifndef NNG_COMPAT_BUS_H +#define NNG_COMPAT_BUS_H + +// This header contains interfaces that are intended to offer compatibility +// with nanomsg v1.0. These are not the "preferred" interfaces for nng, +// and consumers should only use these if they are porting software that +// previously used nanomsg. New programs should use the nng native APIs. + +#ifdef __cplusplus +extern "C" { +#endif + +// BUS sockopt level. +#define NN_PROTO_BUS 7 +#define NN_BUS (NN_PROTO_BUS * 16 + 0) + +// BUS has no options. + +#ifdef __cplusplus +} +#endif + +#endif // NNG_COMPAT_BUS_H diff --git a/VNode/_software_lib/nanomq-0.22.10/include/nng/compat/nanomsg/inproc.h b/VNode/_software_lib/nanomq-0.22.10/include/nng/compat/nanomsg/inproc.h new file mode 100644 index 00000000..9c71a1ee --- /dev/null +++ b/VNode/_software_lib/nanomq-0.22.10/include/nng/compat/nanomsg/inproc.h @@ -0,0 +1,31 @@ +// +// Copyright 2018 Staysail Systems, Inc. +// Copyright 2018 Capitar IT Group BV +// +// This software is supplied under the terms of the MIT License, a +// copy of which should be located in the distribution where this +// file was obtained (LICENSE.txt). A copy of the license may also be +// found online at https://opensource.org/licenses/MIT. +// + +#ifndef NNG_COMPAT_INPROC_H +#define NNG_COMPAT_INPROC_H + +// This header contains interfaces that are intended to offer compatibility +// with nanomsg v1.0. These are not the "preferred" interfaces for nng, +// and consumers should only use these if they are porting software that +// previously used nanomsg. New programs should use the nng native APIs. + +#ifdef __cplusplus +extern "C" { +#endif + +// inproc sockopt level. +// There are no inproc tunables. +#define NN_INPROC (-1) + +#ifdef __cplusplus +} +#endif + +#endif // NNG_COMPAT_INPROC_H diff --git a/VNode/_software_lib/nanomq-0.22.10/include/nng/compat/nanomsg/ipc.h b/VNode/_software_lib/nanomq-0.22.10/include/nng/compat/nanomsg/ipc.h new file mode 100644 index 00000000..fad520d3 --- /dev/null +++ b/VNode/_software_lib/nanomq-0.22.10/include/nng/compat/nanomsg/ipc.h @@ -0,0 +1,39 @@ +// +// Copyright 2018 Staysail Systems, Inc. +// Copyright 2018 Capitar IT Group BV +// +// This software is supplied under the terms of the MIT License, a +// copy of which should be located in the distribution where this +// file was obtained (LICENSE.txt). A copy of the license may also be +// found online at https://opensource.org/licenses/MIT. +// + +#ifndef NNG_COMPAT_IPC_H +#define NNG_COMPAT_IPC_H + +// This header contains interfaces that are intended to offer compatibility +// with nanomsg v1.0. These are not the "preferred" interfaces for nng, +// and consumers should only use these if they are porting software that +// previously used nanomsg. New programs should use the nng native APIs. + +#ifdef __cplusplus +extern "C" { +#endif + +// IPC sockopt level. +#define NN_IPC (-2) + +// IPC options. Note that these are not currently supported. +// IPC_SEC_ATTR works quite differently in NNG, and must be +// configured using the new API. The buffer sizing options are +// not supported at all. None of these were ever documented, and +// are offered here only for source compatibility. +#define NN_IPC_SEC_ATTR 1 +#define NN_IPC_OUTBUFSZ 2 +#define NN_IPC_INBUFSZ 3 + +#ifdef __cplusplus +} +#endif + +#endif // NNG_COMPAT_IPC_H diff --git a/VNode/_software_lib/nanomq-0.22.10/include/nng/compat/nanomsg/nn.h b/VNode/_software_lib/nanomq-0.22.10/include/nng/compat/nanomsg/nn.h new file mode 100644 index 00000000..60c33c60 --- /dev/null +++ b/VNode/_software_lib/nanomq-0.22.10/include/nng/compat/nanomsg/nn.h @@ -0,0 +1,284 @@ +// +// Copyright 2018 Staysail Systems, Inc. +// Copyright 2018 Capitar IT Group BV +// +// This software is supplied under the terms of the MIT License, a +// copy of which should be located in the distribution where this +// file was obtained (LICENSE.txt). A copy of the license may also be +// found online at https://opensource.org/licenses/MIT. +// + +#ifndef NNG_COMPAT_NN_H +#define NNG_COMPAT_NN_H + +// This header contains interfaces that are intended to offer compatibility +// with nanomsg v1.0. These are not the "preferred" interfaces for nng, +// and consumers should only use these if they are porting software that +// previously used nanomsg. New programs should use the nng native APIs. + +// Note that compatibility promises are limited to public portions of the +// nanomsg API, and specifically do NOT extend to the ABI. Furthermore, +// there may be other limitations around less commonly used portions of the +// API; for example only SP headers may be transported in control data for +// messages, there is almost no compatibility offered for statistics. +// Error values may differ from those returned by nanomsg as well; the nng +// error reporting facility expresses only a subset of the possibilities of +// nanomsg. + +// Note that unlike nanomsg, nng does not aggressively recycle socket or +// endpoint IDs, which means applications which made assumptions that these +// would be relatively small integers (e.g. to use them as array indices) +// may break. (No promise about values was ever made.) + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include +#include + +// clang-format gets in the way of most of this file. +// We turn it off, at least until it gets smarter about aligning +// macro definitions or we adopt enums or somesuch. +// clang-format off + +// NNG_DECL is used on declarations to deal with scope. +// For building Windows DLLs, it should be the appropriate __declspec(). +// For shared libraries with platforms that support hidden visibility, +// it should evaluate to __attribute__((visibility("default"))). +#ifndef NN_DECL +#if defined(_WIN32) && !defined(NNG_STATIC_LIB) +#if defined(NNG_SHARED_LIB) +#define NN_DECL __declspec(dllexport) +#else +#define NN_DECL __declspec(dllimport) +#endif // NNG_SHARED_LIB +#else +#if defined(NNG_SHARED_LIB) && defined(NNG_HIDDEN_VISIBILITY) +#define NN_DECL __attribute__((visibility("default"))) +#else +#define NN_DECL extern +#endif +#endif // _WIN32 && !NNG_STATIC_LIB +#endif // NN_DECL + +#define AF_SP 1 +#define AF_SP_RAW 2 + +#define NN_SOCKADDR_MAX 128 +#define NN_SOL_SOCKET 0 + +// Flag for send/recv (nonblocking) +#define NN_DONTWAIT 1 + +// CMSG data type +#define PROTO_SP 1 +#define SP_HDR 1 + +// Errnos. Legacy nanomsg uses posix errnos where possible. +// If a define is not set, use add NN_ERRBASE. nng does not +// return all of these values, so there may be some loss of +// of information for edge cases, but we don't expect that to be +// a problem really. +#define NN_ERRBASE (0x10000000) +#ifndef ENOTSUP +#define ENOTSUP (NN_ERRBASE+1) +#endif +#ifndef EPROTONOSUPPORT +#define EPROTONOSUPPORT (NN_ERRBASE+2) +#endif +#ifndef ENOBUFS +#define ENOBUFS (NN_ERRBASE+3) +#endif +#ifndef ENETDOWN +#define ENETDOWN (NN_ERRBASE+4) +#endif +#ifndef EADDRINUSE +#define EADDRINUSE (NN_ERRBASE+5) +#endif +#ifndef EADDRNOTAVAIL +#define EADDRNOTAVAIL (NN_ERRBASE+6) +#endif +#ifndef ENOTSOCK +#define ENOTSOCK (NN_ERRBASE+7) +#endif +#ifndef EAGAIN +#define EAGAIN (NN_ERRBASE+8) +#endif +#ifndef EBADF +#define EBADF (NN_ERRBASE+9) +#endif +#ifndef EINVAL +#define EINVAL (NN_ERRBASE+10) +#endif +#ifndef EMFILE +#define EMFILE (NN_ERRBASE+11) +#endif +#ifndef EFAULT +#define EFAULT (NN_ERRBASE+12) +#endif +#ifndef EACCES +#define EACCES (NN_ERRBASE+13) +#endif +#ifndef ENETRESET +#define ENETRESET (NN_ERRBASE+14) +#endif +#ifndef ENETUNREACH +#define ENETUNREACH (NN_ERRBASE+15) +#endif +#ifndef EHOSTUNREACH +#define EHOSTUNREACH (NN_ERRBASE+16) +#endif +#ifndef EAFNOSUPPORT +#define EAFNOSUPPORT (NN_ERRBASE+17) +#endif +#ifndef EINPROGRESS +#define EINPROGRESS (NN_ERRBASE+18) +#endif +#ifndef EPROTO +#define EPROTO (NN_ERRBASE+19) +#endif +#ifndef ECONNREFUSED +#define ECONNREFUSED (NN_ERRBASE+20) +#endif +#ifndef ENOTCONN +#define ENOTCONN (NN_ERRBASE+21) +#endif +#ifndef EMSGSIZE +#define EMSGSIZE (NN_ERRBASE+22) +#endif +#ifndef ETIMEDOUT +#define ETIMEDOUT (NN_ERRBASE+23) +#endif +#ifndef ECONNABORTED +#define ECONNABORTED (NN_ERRBASE+24) +#endif +#ifndef ECONNRESET +#define ECONNRESET (NN_ERRBASE+25) +#endif +#ifndef ENOPROTOOPT +#define ENOPROTOOPT (NN_ERRBASE+26) +#endif +#ifndef EISCONN +#define EISCONN (NN_ERRBASE+27) +#endif +#ifndef ESOCKNOSUPPORT +#define ESOCKNOSPPORT (NN_ERRBASE+28) +#endif +#ifndef ETERM +#define ETERM (NN_ERRBASE+29) +#endif +#ifndef EFSM +#define EFSM (NN_ERRBASE+30) +#endif +#ifndef ENOENT +#define ENOENT (NN_ERRBASE+31) +#endif +#ifndef EIO +#define EIO (NN_ERRBASE+32) +#endif +#ifndef EEXIST +#define EEXIST (NN_ERRBASE+33) +#endif +#ifndef ENOSPC +#define ENOSPC (NN_ERRBASE+34) +#endif + + +// Socket options +#define NN_LINGER 1 +#define NN_SNDBUF 2 +#define NN_RCVBUF 3 +#define NN_SNDTIMEO 4 +#define NN_RCVTIMEO 5 +#define NN_RECONNECT_IVL 6 +#define NN_RECONNECT_IVL_MAX 7 +#define NN_SNDPRIO 8 +#define NN_RCVPRIO 9 +#define NN_SNDFD 10 +#define NN_RCVFD 11 +#define NN_DOMAIN 12 +#define NN_PROTOCOL 13 +#define NN_IPV4ONLY 14 +#define NN_SOCKET_NAME 15 +#define NN_RCVMAXSIZE 16 +#define NN_MAXTTL 17 + +// from this point on formatting is fine +// clang-format on + +// Poll stuff +#define NN_POLLIN 1 +#define NN_POLLOUT 2 +struct nn_pollfd { + int fd; + uint16_t events; + uint16_t revents; +}; + +// Magical size for allocation +#define NN_MSG ((size_t) -1) + +struct nn_iovec { + void * iov_base; + size_t iov_len; +}; + +struct nn_msghdr { + struct nn_iovec *msg_iov; + int msg_iovlen; + void * msg_control; + size_t msg_controllen; +}; + +struct nn_cmsghdr { + size_t cmsg_len; + int cmsg_level; + int cmsg_type; +}; + +#define NN_CMSG_ALIGN(len) \ + (((len) + sizeof(size_t) - 1) & (size_t) ~(sizeof(size_t) - 1)) + +// Unlike old nanomsg, we explicitly only support the SP header as attached +// cmsg data. It turns out that old nanomsg didn't really store anything +// useful otherwise anyway. (One specific exception was that it stored the +// message type of text or binary for the websocket transport. We don't think +// anyone used that in practice though.) +#define NN_CMSG_FIRSTHDR(mh) nn_cmsg_next((struct nn_msghdr *) (mh), NULL) +#define NN_CMSG_NXTHDR(mh, ch) \ + nn_cmsg_next((struct nn_msghdr *) (mh), (struct nn_cmsghdr *) ch) +#define NN_CMSG_DATA(ch) ((unsigned char *) (((struct nn_cmsghdr *) (ch)) + 1)) +#define NN_CMSG_SPACE(len) \ + (NN_CMSG_ALIGN(len) + NN_CMSG_ALIGN(sizeof(struct nn_cmsghdr))) +#define NN_CMSG_LEN(len) (NN_CMSG_ALIGN(sizeof(struct nn_cmsghdr)) + (len)) + +NN_DECL struct nn_cmsghdr *nn_cmsg_next( + struct nn_msghdr *, struct nn_cmsghdr *); +NN_DECL int nn_socket(int, int); +NN_DECL int nn_setsockopt(int, int, int, const void *, size_t); +NN_DECL int nn_getsockopt(int, int, int, void *, size_t *); +NN_DECL int nn_bind(int, const char *); +NN_DECL int nn_connect(int, const char *); +NN_DECL int nn_shutdown(int, int); +NN_DECL int nn_send(int, const void *, size_t, int); +NN_DECL int nn_recv(int, void *, size_t, int); +NN_DECL int nn_sendmsg(int, const struct nn_msghdr *, int); +NN_DECL int nn_recvmsg(int, struct nn_msghdr *, int); +NN_DECL int nn_close(int); +NN_DECL int nn_poll(struct nn_pollfd *, int, int); +NN_DECL int nn_device(int, int); +NN_DECL uint64_t nn_get_statistic(int, int); +NN_DECL void * nn_allocmsg(size_t, int); +NN_DECL void * nn_reallocmsg(void *, size_t); +NN_DECL int nn_freemsg(void *); +NN_DECL int nn_errno(void); +NN_DECL const char *nn_strerror(int); +NN_DECL void nn_term(void); + +#ifdef __cplusplus +} +#endif + +#endif // NNG_COMPAT_NN_H diff --git a/VNode/_software_lib/nanomq-0.22.10/include/nng/compat/nanomsg/pair.h b/VNode/_software_lib/nanomq-0.22.10/include/nng/compat/nanomsg/pair.h new file mode 100644 index 00000000..458aac8c --- /dev/null +++ b/VNode/_software_lib/nanomq-0.22.10/include/nng/compat/nanomsg/pair.h @@ -0,0 +1,39 @@ +// +// Copyright 2018 Staysail Systems, Inc. +// Copyright 2018 Capitar IT Group BV +// +// This software is supplied under the terms of the MIT License, a +// copy of which should be located in the distribution where this +// file was obtained (LICENSE.txt). A copy of the license may also be +// found online at https://opensource.org/licenses/MIT. +// + +#ifndef NNG_COMPAT_PAIR_H +#define NNG_COMPAT_PAIR_H + +// This header contains interfaces that are intended to offer compatibility +// with nanomsg v1.0. These are not the "preferred" interfaces for nng, +// and consumers should only use these if they are porting software that +// previously used nanomsg. New programs should use the nng native APIs. + +#ifdef __cplusplus +extern "C" { +#endif + +// PAIR sockopt level. +#define NN_PROTO_PAIR 1 +#define NN_PAIR (NN_PROTO_PAIR * 16 + 0) + +// These are technically "new", and not available in nanomsg, but +// offered here as a transition aid. If you want to use the advanced +// PAIRv1 options (POLYAMOROUS mode) you still need to use the new API. +#define NN_PAIR_v0 (NN_PROTO_PAIR * 16 + 0) +#define NN_PAIR_V1 (NN_PROTO_PAIR * 16 + 1) + +// PAIR has no options. + +#ifdef __cplusplus +} +#endif + +#endif // NNG_COMPAT_PAIR_H diff --git a/VNode/_software_lib/nanomq-0.22.10/include/nng/compat/nanomsg/pipeline.h b/VNode/_software_lib/nanomq-0.22.10/include/nng/compat/nanomsg/pipeline.h new file mode 100644 index 00000000..187a4b4e --- /dev/null +++ b/VNode/_software_lib/nanomq-0.22.10/include/nng/compat/nanomsg/pipeline.h @@ -0,0 +1,34 @@ +// +// Copyright 2018 Staysail Systems, Inc. +// Copyright 2018 Capitar IT Group BV +// +// This software is supplied under the terms of the MIT License, a +// copy of which should be located in the distribution where this +// file was obtained (LICENSE.txt). A copy of the license may also be +// found online at https://opensource.org/licenses/MIT. +// + +#ifndef NNG_COMPAT_PIPELINE_H +#define NNG_COMPAT_PIPELINE_H + +// This header contains interfaces that are intended to offer compatibility +// with nanomsg v1.0. These are not the "preferred" interfaces for nng, +// and consumers should only use these if they are porting software that +// previously used nanomsg. New programs should use the nng native APIs. + +#ifdef __cplusplus +extern "C" { +#endif + +// PUSH and PULL sockopt level. +#define NN_PROTO_PIPELINE 5 +#define NN_PUSH (NN_PROTO_PIPELINE * 16 + 0) +#define NN_PULL (NN_PROTO_PIPELINE * 16 + 1) + +// PUSH and PULL have no options. + +#ifdef __cplusplus +} +#endif + +#endif // NNG_COMPAT_PIPELINE_H diff --git a/VNode/_software_lib/nanomq-0.22.10/include/nng/compat/nanomsg/pubsub.h b/VNode/_software_lib/nanomq-0.22.10/include/nng/compat/nanomsg/pubsub.h new file mode 100644 index 00000000..43118f68 --- /dev/null +++ b/VNode/_software_lib/nanomq-0.22.10/include/nng/compat/nanomsg/pubsub.h @@ -0,0 +1,36 @@ +// +// Copyright 2018 Staysail Systems, Inc. +// Copyright 2018 Capitar IT Group BV +// +// This software is supplied under the terms of the MIT License, a +// copy of which should be located in the distribution where this +// file was obtained (LICENSE.txt). A copy of the license may also be +// found online at https://opensource.org/licenses/MIT. +// + +#ifndef NNG_COMPAT_PUBSUB_H +#define NNG_COMPAT_PUBSUB_H + +// This header contains interfaces that are intended to offer compatibility +// with nanomsg v1.0. These are not the "preferred" interfaces for nng, +// and consumers should only use these if they are porting software that +// previously used nanomsg. New programs should use the nng native APIs. + +#ifdef __cplusplus +extern "C" { +#endif + +// PUB and SUB sockopt level. +#define NN_PROTO_PUBSUB 2 +#define NN_PUB (NN_PROTO_PUBSUB * 16 + 0) +#define NN_SUB (NN_PROTO_PUBSUB * 16 + 1) + +// SUB options. (PUB has none.) +#define NN_SUB_SUBSCRIBE (NN_SUB * 16 + 1) +#define NN_SUB_UNSUBSCRIBE (NN_SUB * 16 + 2) + +#ifdef __cplusplus +} +#endif + +#endif // NNG_COMPAT_PUBSUB_H diff --git a/VNode/_software_lib/nanomq-0.22.10/include/nng/compat/nanomsg/reqrep.h b/VNode/_software_lib/nanomq-0.22.10/include/nng/compat/nanomsg/reqrep.h new file mode 100644 index 00000000..9490a8f1 --- /dev/null +++ b/VNode/_software_lib/nanomq-0.22.10/include/nng/compat/nanomsg/reqrep.h @@ -0,0 +1,35 @@ +// +// Copyright 2018 Staysail Systems, Inc. +// Copyright 2018 Capitar IT Group BV +// +// This software is supplied under the terms of the MIT License, a +// copy of which should be located in the distribution where this +// file was obtained (LICENSE.txt). A copy of the license may also be +// found online at https://opensource.org/licenses/MIT. +// + +#ifndef NNG_COMPAT_REQREP_H +#define NNG_COMPAT_REQREP_H + +// This header contains interfaces that are intended to offer compatibility +// with nanomsg v1.0. These are not the "preferred" interfaces for nng, +// and consumers should only use these if they are porting software that +// previously used nanomsg. New programs should use the nng native APIs. + +#ifdef __cplusplus +extern "C" { +#endif + +// REQ and REP sockopt level. +#define NN_PROTO_REQREP 3 +#define NN_REQ (NN_PROTO_REQREP * 16 + 0) +#define NN_REP (NN_PROTO_REQREP * 16 + 1) + +// REQ options. (REP has none.) +#define NN_REQ_RESEND_IVL (NN_REQ * 16 + 1) + +#ifdef __cplusplus +} +#endif + +#endif // NNG_COMPAT_REQREP_H diff --git a/VNode/_software_lib/nanomq-0.22.10/include/nng/compat/nanomsg/survey.h b/VNode/_software_lib/nanomq-0.22.10/include/nng/compat/nanomsg/survey.h new file mode 100644 index 00000000..fdef10cb --- /dev/null +++ b/VNode/_software_lib/nanomq-0.22.10/include/nng/compat/nanomsg/survey.h @@ -0,0 +1,36 @@ +// +// Copyright 2018 Staysail Systems, Inc. +// Copyright 2018 Capitar IT Group BV +// +// This software is supplied under the terms of the MIT License, a +// copy of which should be located in the distribution where this +// file was obtained (LICENSE.txt). A copy of the license may also be +// found online at https://opensource.org/licenses/MIT. +// + +#ifndef NNG_COMPAT_SURVEY_H +#define NNG_COMPAT_SURVEY_H + +// This header contains interfaces that are intended to offer compatibility +// with nanomsg v1.0. These are not the "preferred" interfaces for nng, +// and consumers should only use these if they are porting software that +// previously used nanomsg. New programs should use the nng native APIs. + +#ifdef __cplusplus +extern "C" { +#endif + +// SURVEYOR and RESPONDENT sockopt level. +#define NN_PROTO_SURVEY 6 +#define NN_SURVEYOR (NN_PROTO_SURVEY * 16 + 2) +#define NN_RESPONDENT (NN_PROTO_SURVEY * 16 + 3) + +// SURVEYOR options. (RESPONDENT has none.) + +#define NN_SURVEYOR_DEADLINE (NN_SURVEYOR * 16 + 1) + +#ifdef __cplusplus +} +#endif + +#endif // NNG_COMPAT_SURVEY_H diff --git a/VNode/_software_lib/nanomq-0.22.10/include/nng/compat/nanomsg/tcp.h b/VNode/_software_lib/nanomq-0.22.10/include/nng/compat/nanomsg/tcp.h new file mode 100644 index 00000000..5a305c49 --- /dev/null +++ b/VNode/_software_lib/nanomq-0.22.10/include/nng/compat/nanomsg/tcp.h @@ -0,0 +1,33 @@ +// +// Copyright 2018 Staysail Systems, Inc. +// Copyright 2018 Capitar IT Group BV +// +// This software is supplied under the terms of the MIT License, a +// copy of which should be located in the distribution where this +// file was obtained (LICENSE.txt). A copy of the license may also be +// found online at https://opensource.org/licenses/MIT. +// + +#ifndef NNG_COMPAT_TCP_H +#define NNG_COMPAT_TCP_H + +// This header contains interfaces that are intended to offer compatibility +// with nanomsg v1.0. These are not the "preferred" interfaces for nng, +// and consumers should only use these if they are porting software that +// previously used nanomsg. New programs should use the nng native APIs. + +#ifdef __cplusplus +extern "C" { +#endif + +// TCP sockopt level. +#define NN_TCP (-3) + +// TCP options. +#define NN_TCP_NODELAY 1 + +#ifdef __cplusplus +} +#endif + +#endif // NNG_COMPAT_TCP_H diff --git a/VNode/_software_lib/nanomq-0.22.10/include/nng/compat/nanomsg/ws.h b/VNode/_software_lib/nanomq-0.22.10/include/nng/compat/nanomsg/ws.h new file mode 100644 index 00000000..3072a3b5 --- /dev/null +++ b/VNode/_software_lib/nanomq-0.22.10/include/nng/compat/nanomsg/ws.h @@ -0,0 +1,41 @@ +// +// Copyright 2018 Staysail Systems, Inc. +// Copyright 2018 Capitar IT Group BV +// +// This software is supplied under the terms of the MIT License, a +// copy of which should be located in the distribution where this +// file was obtained (LICENSE.txt). A copy of the license may also be +// found online at https://opensource.org/licenses/MIT. +// + +#ifndef NNG_COMPAT_WS_H +#define NNG_COMPAT_WS_H + +// This header contains interfaces that are intended to offer compatibility +// with nanomsg v1.0. These are not the "preferred" interfaces for nng, +// and consumers should only use these if they are porting software that +// previously used nanomsg. New programs should use the nng native APIs. + +#ifdef __cplusplus +extern "C" { +#endif + +// WS sockopt level. +#define NN_WS (-4) + +// WS options. + +// Note that while legacy libnanomsg had *some* support for text messages, +// NNG only supports binary. Binary types are required to pass protocol +// headers with NNG and nanomsg in any event. This means that the NNG +// WebSocket support will not be compatible with some very old browsers. +#define NN_WS_MSG_TYPE 1 + +#define NN_WS_MSG_TYPE_TEXT 0x1 +#define NN_WS_MSG_TYPE_BINARY 0x2 + +#ifdef __cplusplus +} +#endif + +#endif // NNG_COMPAT_WS_H diff --git a/VNode/_software_lib/nanomq-0.22.10/include/nng/exchange/exchange.h b/VNode/_software_lib/nanomq-0.22.10/include/nng/exchange/exchange.h new file mode 100644 index 00000000..e4823dc0 --- /dev/null +++ b/VNode/_software_lib/nanomq-0.22.10/include/nng/exchange/exchange.h @@ -0,0 +1,34 @@ +#ifndef EXCHANGE_H +#define EXCHANGE_H + +#include +#include "core/nng_impl.h" +#include "nng/supplemental/nanolib/conf.h" + +// Exchange MQ +#define EXCHANGE_NAME_LEN 32 +#define TOPIC_NAME_LEN 128 +#define RINGBUFFER_MAX 64 + +typedef struct exchange_s exchange_t; +struct exchange_s { + char name[EXCHANGE_NAME_LEN]; + char topic[TOPIC_NAME_LEN]; + + ringBuffer_t *rbs[RINGBUFFER_MAX]; + unsigned int rb_count; +}; + +NNG_DECL int exchange_client_get_msg_by_key(void *arg, uint64_t key, nni_msg **msg); +NNG_DECL int exchange_client_get_msgs_by_key(void *arg, uint64_t key, uint32_t count, nng_msg ***list); + +NNG_DECL int exchange_client_get_msgs_fuzz(void *arg, uint64_t start, uint64_t end, uint32_t *count, nng_msg ***list); + +NNG_DECL int exchange_init(exchange_t **ex, char *name, char *topic, + unsigned int *rbsCaps, char **rbsName, uint8_t *rbsFullOp, unsigned int rbsCount); +NNG_DECL int exchange_add_rb(exchange_t *ex, ringBuffer_t *rb); +NNG_DECL int exchange_release(exchange_t *ex); +NNG_DECL int exchange_handle_msg(exchange_t *ex, uint64_t key, void *msg, nng_aio *aio); +NNG_DECL int exchange_get_ringBuffer(exchange_t *ex, char *rbName, ringBuffer_t **rb); + +#endif diff --git a/VNode/_software_lib/nanomq-0.22.10/include/nng/exchange/exchange_client.h b/VNode/_software_lib/nanomq-0.22.10/include/nng/exchange/exchange_client.h new file mode 100644 index 00000000..1c371cd7 --- /dev/null +++ b/VNode/_software_lib/nanomq-0.22.10/include/nng/exchange/exchange_client.h @@ -0,0 +1,42 @@ +// +// Copyright 2023 NanoMQ Team, Inc. +// +// This software is supplied under the terms of the MIT License, a +// copy of which should be located in the distribution where this +// file was obtained (LICENSE.txt). A copy of the license may also be +// found online at https://opensource.org/licenses/MIT. +// + +#ifndef EXCHANGE_CLIENT_H +#define EXCHANGE_CLIENT_H + +#ifdef __cplusplus +extern "C" { +#endif + +#define nng_exchange_self 0 +#define nng_exchange_self_name "exchange-client" +#define nng_exchange_peer 0 +#define nng_exchange_peer_name "exchange-server" +#define nng_opt_exchange_add "exchange-client-add" + +#define NNG_EXCHANGE_SELF 0 +#define NNG_EXCHANGE_SELF_NAME "exchange-client" +#define NNG_EXCHANGE_PEER 0 +#define NNG_EXCHANGE_PEER_NAME "exchange-server" +#define NNG_OPT_EXCHANGE_BIND "exchange-client-bind" +#define NNG_OPT_EXCHANGE_GET_EX_QUEUE "exchange-client-get-ex-queue" +#define NNG_OPT_EXCHANGE_GET_RBMSGMAP "exchange-client-get-rbmsgmap" + +NNG_DECL int nng_exchange_client_open(nng_socket *sock); + +#ifndef nng_exchange_open +#define nng_exchange_open nng_exchange_client_open +#endif + +#ifdef __cplusplus +} +#endif + +#endif // #define EXCHANGE_CLIENT_H + diff --git a/VNode/_software_lib/nanomq-0.22.10/include/nng/exchange/producer.h b/VNode/_software_lib/nanomq-0.22.10/include/nng/exchange/producer.h new file mode 100644 index 00000000..867f50e7 --- /dev/null +++ b/VNode/_software_lib/nanomq-0.22.10/include/nng/exchange/producer.h @@ -0,0 +1,23 @@ +#ifndef PRODUCER_H +#define PRODUCER_H + +#include + +typedef struct producer_s producer_t; +struct producer_s { + /* + * return: 0: success, -1: failed + */ + int (*match)(void *data); + /* + * return: 0: continue, -1: stop and return + */ + int (*target)(void *data); +}; + +int producer_init(producer_t **p, + int (*match)(void *data), + int (*target)(void *data)); +int producer_release(producer_t *p); + +#endif diff --git a/VNode/_software_lib/nanomq-0.22.10/include/nng/iceoryx_shm/iceoryx_shm.h b/VNode/_software_lib/nanomq-0.22.10/include/nng/iceoryx_shm/iceoryx_shm.h new file mode 100644 index 00000000..c9597f3d --- /dev/null +++ b/VNode/_software_lib/nanomq-0.22.10/include/nng/iceoryx_shm/iceoryx_shm.h @@ -0,0 +1,54 @@ +// +// Copyright 2024 NanoMQ Team, Inc. +// +// This software is supplied under the terms of the MIT License, a +// copy of which should be located in the distribution where this +// file was obtained (LICENSE.txt). A copy of the license may also be +// found online at https://opensource.org/licenses/MIT. +// + +#if defined(SUPP_ICEORYX) + +#ifndef NNG_ICEORYX_SHM_H +#define NNG_ICEORYX_SHM_H + +#ifdef __cplusplus +extern "C" { +#endif + +// TODO +#include "../../../src/supplemental/iceoryx/iceoryx_api.h" + +struct nng_iceoryx_suber { + nano_iceoryx_suber *suber; +}; +typedef struct nng_iceoryx_suber nng_iceoryx_suber; + +struct nng_iceoryx_puber { + nano_iceoryx_puber *puber; +}; +typedef struct nng_iceoryx_puber nng_iceoryx_puber; + + +NNG_DECL int nng_iceoryx_open(nng_socket *sock, const char *runtimename); + +NNG_DECL int nng_iceoryx_sub(nng_socket *sock, const char *subername, + const char *const service_name, const char *const instance_name, + const char *const event, nng_iceoryx_suber **nsp); + +NNG_DECL int nng_iceoryx_pub(nng_socket *sock, const char *pubername, + const char *const service_name, const char *const instance_name, + const char *const event, nng_iceoryx_puber **npp); + +NNG_DECL int nng_msg_iceoryx_alloc(nng_msg **msgp, nng_iceoryx_puber *puber, size_t sz); +NNG_DECL int nng_msg_iceoryx_free(nng_msg *msg, nng_iceoryx_suber *suber); +NNG_DECL int nng_msg_iceoryx_append(nng_msg *msg, const void *data, size_t sz); + +#ifdef __cplusplus +} +#endif + +#endif + +#endif + diff --git a/VNode/_software_lib/nanomq-0.22.10/include/nng/mqtt/mqtt_client.h b/VNode/_software_lib/nanomq-0.22.10/include/nng/mqtt/mqtt_client.h new file mode 100644 index 00000000..d92d8e88 --- /dev/null +++ b/VNode/_software_lib/nanomq-0.22.10/include/nng/mqtt/mqtt_client.h @@ -0,0 +1,596 @@ +// +// Copyright 2023 NanoMQ Team, Inc. +// +// This software is supplied under the terms of the MIT License, a +// copy of which should be located in the distribution where this +// file was obtained (LICENSE.txt). A copy of the license may also be +// found online at https://opensource.org/licenses/MIT. +// + +// This file is for the MQTT client implementation. +// Note that while there are some similarities, MQTT is sufficiently +// different enough from SP that many of the APIs cannot be easily +// shared. +// +// At this time there is no server provided by NNG itself, although +// the nanomq project provides such a server (and is based on NNG.) +// +// About our semantics: +// +// 1. MQTT client sockets have a single implicit dialer, and cannot +// support creation of additional dialers or listeners. +// 2. MQTT client sockets do support contexts; each context will +// maintain its own subscriptions, and the socket will keep a +// per-socket list of them and manage the full list. +// 3. Send sends PUBLISH messages. +// 4. Receive is used to receive published data from the server. +// 5. Most of the MQTT specific "features" are as options on the socket, +// dialer, or even the message. (For example message topics are set +// as options on the message.) +// 6. Pipe events can be used to detect connect/disconnect events. +// 7. Any QoS details such as retransmit, etc. are handled under the hood. +// This includes packet IDs. +// 8. PING and keep-alive is handled under the hood. +// 9. For publish actions, a separate method is used (not send/receive). + +#ifndef NNG_MQTT_CLIENT_H +#define NNG_MQTT_CLIENT_H + +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#define MQTT_PROTOCOL_NAME_v31 "MQIsdp" +#define MQTT_PROTOCOL_VERSION_v31 3 +#define MQTT_PROTOCOL_NAME "MQTT" +#define MQTT_PROTOCOL_VERSION_v311 4 +#define MQTT_PROTOCOL_VERSION_v5 5 + +// NNG_OPT_MQTT_EXPIRES is a 32-bit integer representing the expiration in +// seconds. This can be applied to a message. +// (TODO: What about session expiry?) +#define NNG_OPT_MQTT_EXPIRES "expires" + +#define NNG_OPT_MQTT_CONNMSG "mqtt-connect-msg" + +#define NNG_OPT_MQTT_CONNECT_PROPERTY "mqtt-connack-property" + +#define NNG_OPT_MQTT_CONNECT_REASON "mqtt-connack-reason" + +#define NNG_OPT_MQTT_RECONNECT_BACKOFF_MAX "mqtt-reconnect-backoff-max" + +#define NNG_OPT_MQTT_DISCONNECT_PROPERTY "mqtt-disconnect-property" + +#define NNG_OPT_MQTT_RETRY_INTERVAL "mqtt-client-retry-interval" + +#define NNG_OPT_MQTT_RETRY_WAIT_TIME "mqtt-client-retry-wait-time" + +#define NNG_OPT_MQTT_DISCONNECT_REASON "mqtt-disconnect-reason" + +#define NNG_OPT_MQTT_SQLITE "mqtt-sqlite-option" + +#define NNG_OPT_MQTT_ENABLE_SCRAM "mqtt-scram-option" + +// NNG_OPT_MQTT_QOS is a byte (only lower two bits significant) representing +// the quality of service. At this time, only level zero is supported. +// TODO: level 1 and level 2 QoS +#define NNG_OPT_MQTT_QOS "qos" + +// NNG_OPT_MQTT_RETAIN indicates that the message should be retained on +// the server as the single retained message for the associated topic. +// This is a boolean. +#define NNG_OPT_MQTT_RETAIN "retain" + +// NNG_OPT_MQTT_DUP indicates that the message is a duplicate. This can +// only be returned on a message -- this client will add this flag if +// sending a duplicate message (QoS 1 and 2 only). +#define NNG_OPT_MQTT_DUP "dup" + +// NNG_OPT_MQTT_TOPIC is the message topic. It is encoded as an "Encoded +// UTF-8 string" (uint16 length followed by UTF-8 data). At the API, it +// is just a UTF-8 string (C style, with a terminating byte.) Note that +// we do not support embedded NUL bytes in our UTF-8 strings. Every +// MQTT published message must have a topic. +#define NNG_OPT_MQTT_TOPIC "topic" + +// NNG_OPT_MQTT_REASON is a reason that can be conveyed with a message. +// It is a UTF-8 string. +#define NNG_OPT_MQTT_REASON "reason" + +// NNG_OPT_MQTT_USER_PROPS is an array of user properties. These are +// send with the message, and used for application specific purposes. +// The properties are of the type nng_mqtt_user_props_t. +#define NNG_OPT_MQTT_USER_PROPS "user-props" + +// NNG_OPT_MQTT_PAYLOAD_FORMAT is the format of the payload for a message. +// It can be 0, indicating binary data, or 1, indicating UTF-8. +#define NNG_OPT_MQTT_PAYLOAD_FORMAT "mqtt-payload-format" + +// NNG_OPT_MQTT_CONTENT_TYPE is the mime type as UTF-8 for PUBLISH +// or Will messages. +#define NNG_OPT_MQTT_CONTENT_TYPE "content-type" + +// The following options are reserved for MQTT v5.0 request/reply support. +#define NNG_OPT_MQTT_RESPONSE_TOPIC "response-topic" +#define NNG_OPT_MQTT_CORRELATION_DATA "correlation-data" + +// NNG_OPT_MQTT_CLIENT_ID is the UTF-8 string corresponding to the client +// identification. We automatically generate an initial value fo this, +// which is the UUID. +// TODO: Should applications be permitted to change this? +#define NNG_OPT_MQTT_CLIENT_ID "client-id" // UTF-8 string + +#define NNG_OPT_MQTT_WILL_DELAY "will-delay" + +// NNG_OPT_MQTT_RECEIVE_MAX is used with QoS 1 or 2 (not implemented), +// and indicates the level of concurrent receives it is willing to +// process. (TODO: Implementation note: we will need to preallocate a complete +// state machine (aio, plus any state) for each value of this > 0. +// It's not clear whether this should be tunable.) This is read-only +// property on the socket, and records the value given from the server. +// It will be 64K if the server did not indicate a specific value. +#define NNG_OPT_MQTT_RECEIVE_MAX "mqtt-receive-max" + +// NNG_OPT_MQTT_SESSION_EXPIRES is an nng_duration. +// If set to NNG_DURATION_ZERO, then the session will expire automatically +// when the connection is closed. +// If it set to NNG_DURATION_INFINITE, the session never expires. +// Otherwise it will be a whole number of seconds indicating the session +// expiry interval. +#define NNG_OPT_MQTT_SESSION_EXPIRES "session-expires" + +#define NNG_OPT_MQTT_TOPIC_ALIAS_MAX "alias-max" +#define NNG_OPT_MQTT_TOPIC_ALIAS "topic-alias" +#define NNG_OPT_MQTT_MAX_QOS "max-qos" + +// NNG_MAX_RECV_LMQ and NNG_MAX_SEND_LMQ define the length of waiting queue +// they are the length of nni_lmq, please be ware it affects the memory usage +// significantly while having heavy throughput +#define NNG_MAX_RECV_LMQ 64 +#define NNG_MAX_SEND_LMQ 64 +#define NNG_TRAN_MAX_LMQ_SIZE 128 + +// NNG_TLS_xxx options can be set on the client as well. +// E.g. NNG_OPT_TLS_CA_CERT, etc. + +// TBD: Extended authentication. I think we should skip it -- everyone +// should just use TLS if they need security. + +// NNG_OPT_MQTT_KEEP_ALIVE is set on the client, and can be retrieved +// by the client. This is an nng_duration but will always be zero or +// a whole number of seconds less than 65536. If setting the value, +// it must be set before the client connects. When retrieved, the +// server's value will be returned (if it is different from what we +// requested.) If we reconnect, we will try again with the configured +// value rather than the value that we got from the server last time. +#define NNG_OPT_MQTT_KEEP_ALIVE "mqtt-keep-alive" + +// NNG_OPT_MQTT_MAX_PACKET_SIZE is the maximum packet size that can +// be used. It needs to be set before the client dials. +#define NNG_OPT_MQTT_MAX_PACKET_SIZE "mqtt-max-packet-size" +#define NNG_OPT_MQTT_USERNAME "username" +#define NNG_OPT_MQTT_PASSWORD "password" + +// Message handling. Note that topic aliases are handled by the library +// automatically on behalf of the consumer. + +typedef enum { + nng_mqtt_msg_format_binary = 0, + nng_mqtt_msg_format_utf8 = 1, +} nng_mqtt_msg_format_t; + +/* Message types & flags */ +#define CMD_UNKNOWN 0x00 +#define CMD_CONNECT 0x10 +#define CMD_CONNACK 0x20 +#define CMD_PUBLISH 0x30 // indicates PUBLISH packet & MQTTV4 pub packet +#define CMD_PUBLISH_V5 0x31 // this is the flag for differing MQTTV5 from V4 V3 +#define CMD_PUBACK 0x40 +#define CMD_PUBREC 0x50 +#define CMD_PUBREL 0x60 +#define CMD_PUBCOMP 0x70 +#define CMD_SUBSCRIBE 0x80 +#define CMD_SUBACK 0x90 +#define CMD_UNSUBSCRIBE 0xA0 +#define CMD_UNSUBACK 0xB0 +#define CMD_PINGREQ 0xC0 +#define CMD_PINGRESP 0xD0 +#define CMD_DISCONNECT 0xE0 +#define CMD_AUTH_V5 0xF0 +#define CMD_DISCONNECT_EV 0xE2 +#define CMD_LASTWILL 0XE3 + +typedef enum { + NNG_MQTT_CONNECT = 0x01, + NNG_MQTT_CONNACK = 0x02, + NNG_MQTT_PUBLISH = 0x03, + NNG_MQTT_PUBACK = 0x04, + NNG_MQTT_PUBREC = 0x05, + NNG_MQTT_PUBREL = 0x06, + NNG_MQTT_PUBCOMP = 0x07, + NNG_MQTT_SUBSCRIBE = 0x08, + NNG_MQTT_SUBACK = 0x09, + NNG_MQTT_UNSUBSCRIBE = 0x0A, + NNG_MQTT_UNSUBACK = 0x0B, + NNG_MQTT_PINGREQ = 0x0C, + NNG_MQTT_PINGRESP = 0x0D, + NNG_MQTT_DISCONNECT = 0x0E, + NNG_MQTT_AUTH = 0x0F +} nng_mqtt_packet_type; + +//TODO Enum is not fitting here +typedef enum { + SUCCESS = 0, + NORMAL_DISCONNECTION = 0, + GRANTED_QOS_0 = 0, + GRANTED_QOS_1 = 1, + GRANTED_QOS_2 = 2, + DISCONNECT_WITH_WILL_MESSAGE = 4, + NO_MATCHING_SUBSCRIBERS = 16, + NO_SUBSCRIPTION_EXISTED = 17, + CONTINUE_AUTHENTICATION = 24, + RE_AUTHENTICATE = 25, + UNSPECIFIED_ERROR = 128, + MALFORMED_PACKET = 129, + PROTOCOL_ERROR = 130, + IMPLEMENTATION_SPECIFIC_ERROR = 131, + UNSUPPORTED_PROTOCOL_VERSION = 132, + CLIENT_IDENTIFIER_NOT_VALID = 133, + BAD_USER_NAME_OR_PASSWORD = 134, + NOT_AUTHORIZED = 135, + SERVER_UNAVAILABLE = 136, + SERVER_BUSY = 137, + BANNED = 138, + SERVER_SHUTTING_DOWN = 139, + BAD_AUTHENTICATION_METHOD = 140, + KEEP_ALIVE_TIMEOUT = 141, + SESSION_TAKEN_OVER = 142, + TOPIC_FILTER_INVALID = 143, + TOPIC_NAME_INVALID = 144, + PACKET_IDENTIFIER_IN_USE = 145, + PACKET_IDENTIFIER_NOT_FOUND = 146, + RECEIVE_MAXIMUM_EXCEEDED = 147, + TOPIC_ALIAS_INVALID = 148, + PACKET_TOO_LARGE = 149, + MESSAGE_RATE_TOO_HIGH = 150, + QUOTA_EXCEEDED = 151, + ADMINISTRATIVE_ACTION = 152, + PAYLOAD_FORMAT_INVALID = 153, + RETAIN_NOT_SUPPORTED = 154, + QOS_NOT_SUPPORTED = 155, + USE_ANOTHER_SERVER = 156, + SERVER_MOVED = 157, + SHARED_SUBSCRIPTIONS_NOT_SUPPORTED = 158, + CONNECTION_RATE_EXCEEDED = 159, + MAXIMUM_CONNECT_TIME = 160, + SUBSCRIPTION_IDENTIFIERS_NOT_SUPPORTED = 161, + WILDCARD_SUBSCRIPTIONS_NOT_SUPPORTED = 162 + +} reason_code; + +typedef enum { + PAYLOAD_FORMAT_INDICATOR = 1, + MESSAGE_EXPIRY_INTERVAL = 2, + CONTENT_TYPE = 3, + RESPONSE_TOPIC = 8, + CORRELATION_DATA = 9, + SUBSCRIPTION_IDENTIFIER = 11, + SESSION_EXPIRY_INTERVAL = 17, + ASSIGNED_CLIENT_IDENTIFIER = 18, + SERVER_KEEP_ALIVE = 19, + AUTHENTICATION_METHOD = 21, + AUTHENTICATION_DATA = 22, + REQUEST_PROBLEM_INFORMATION = 23, + WILL_DELAY_INTERVAL = 24, + REQUEST_RESPONSE_INFORMATION = 25, + RESPONSE_INFORMATION = 26, + SERVER_REFERENCE = 28, + REASON_STRING = 31, + RECEIVE_MAXIMUM = 33, + TOPIC_ALIAS_MAXIMUM = 34, + TOPIC_ALIAS = 35, + PUBLISH_MAXIMUM_QOS = 36, + RETAIN_AVAILABLE = 37, + USER_PROPERTY = 38, + MAXIMUM_PACKET_SIZE = 39, + WILDCARD_SUBSCRIPTION_AVAILABLE = 40, + SUBSCRIPTION_IDENTIFIER_AVAILABLE = 41, + SHARED_SUBSCRIPTION_AVAILABLE = 42 +} properties_type; + +struct mqtt_buf_t { + uint32_t length; + uint8_t *buf; +}; + +typedef struct mqtt_buf_t mqtt_buf; +typedef struct mqtt_buf_t nng_mqtt_buffer; +typedef struct mqtt_buf_t nng_mqtt_topic; + +struct mqtt_kv_t { + mqtt_buf key; + mqtt_buf value; +}; +typedef struct mqtt_kv_t mqtt_kv; + +typedef struct mqtt_topic_qos_t { + nng_mqtt_topic topic; + uint8_t qos; + uint8_t nolocal; + uint8_t rap; + uint8_t retain_handling; +} mqtt_topic_qos; + +typedef struct mqtt_topic_qos_t nng_mqtt_topic_qos; + +extern uint16_t nni_msg_get_pub_pid(nng_msg *m); +struct mqtt_string { + char * body; + uint32_t len; +}; +typedef struct mqtt_string mqtt_string; + +struct mqtt_string_node { + struct mqtt_string_node *next; + mqtt_string * it; +}; +typedef struct mqtt_string_node mqtt_string_node; + +struct mqtt_binary { + uint8_t *body; + uint32_t len; +}; +typedef struct mqtt_binary mqtt_binary; + +struct mqtt_str_pair { + char * key; // key + uint32_t len_key; + char * val; // value + uint32_t len_val; +}; +typedef struct mqtt_str_pair mqtt_str_pair; + +union Property_type { + uint8_t u8; + uint16_t u16; + uint32_t u32; + uint32_t varint; + mqtt_buf binary; + mqtt_buf str; + mqtt_kv strpair; +}; + +typedef enum { + U8, + U16, + U32, + VARINT, + BINARY, + STR, + STR_PAIR, + UNKNOWN +} property_type_enum; + +struct property_data { + property_type_enum p_type; + union Property_type p_value; + bool is_copy; +}; + +typedef struct property_data property_data; + +struct property { + uint8_t id; + property_data data; + struct property *next; +}; +typedef struct property property; + +NNG_DECL int nng_mqtt_msg_alloc(nng_msg **, size_t); +NNG_DECL int nng_mqtt_msg_proto_data_alloc(nng_msg *); +NNG_DECL void nng_mqtt_msg_proto_data_free(nng_msg *); +NNG_DECL int nng_mqtt_msg_encode(nng_msg *); +NNG_DECL int nng_mqtt_msg_decode(nng_msg *); +NNG_DECL int nng_mqttv5_msg_encode(nng_msg *); +NNG_DECL int nng_mqttv5_msg_decode(nng_msg *); +NNG_DECL int nng_mqtt_msg_validate(nng_msg *, uint8_t); +NNG_DECL void nng_mqtt_msg_set_packet_type(nng_msg *, nng_mqtt_packet_type); +NNG_DECL nng_mqtt_packet_type nng_mqtt_msg_get_packet_type(nng_msg *); +NNG_DECL void nng_mqtt_msg_set_bridge_bool(nng_msg *msg, bool bridged); +NNG_DECL bool nng_mqtt_msg_get_bridge_bool(nng_msg *msg); +NNG_DECL void nng_mqtt_msg_set_sub_retain_bool(nng_msg *msg, bool retain); +NNG_DECL bool nng_mqtt_msg_get_sub_retain_bool(nng_msg *msg); +NNG_DECL void nng_mqtt_msg_set_connect_proto_version(nng_msg *, uint8_t); +NNG_DECL void nng_mqtt_msg_set_connect_keep_alive(nng_msg *, uint16_t); +NNG_DECL void nng_mqtt_msg_set_connect_client_id(nng_msg *, const char *); +NNG_DECL void nng_mqtt_msg_set_connect_user_name(nng_msg *, const char *); +NNG_DECL void nng_mqtt_msg_set_connect_password(nng_msg *, const char *); +NNG_DECL void nng_mqtt_msg_set_connect_clean_session(nng_msg *, bool); +NNG_DECL void nng_mqtt_msg_set_connect_will_topic(nng_msg *, const char *); +NNG_DECL void nng_mqtt_msg_set_connect_will_msg( + nng_msg *, uint8_t *, uint32_t); +NNG_DECL void nng_mqtt_msg_set_connect_will_retain(nng_msg *, bool); +NNG_DECL void nng_mqtt_msg_set_connect_will_qos(nng_msg *, uint8_t); +NNG_DECL void nng_mqtt_msg_set_connect_property(nng_msg *, property *); +NNG_DECL property *nng_mqtt_msg_get_connect_will_property(nng_msg *); +NNG_DECL void nng_mqtt_msg_set_connect_will_property(nng_msg *, property *); +NNG_DECL const char *nng_mqtt_msg_get_connect_user_name(nng_msg *); +NNG_DECL const char *nng_mqtt_msg_get_connect_password(nng_msg *); +NNG_DECL bool nng_mqtt_msg_get_connect_clean_session(nng_msg *); +NNG_DECL uint8_t nng_mqtt_msg_get_connect_proto_version(nng_msg *); +NNG_DECL uint16_t nng_mqtt_msg_get_connect_keep_alive(nng_msg *); +NNG_DECL const char *nng_mqtt_msg_get_connect_client_id(nng_msg *); +NNG_DECL const char *nng_mqtt_msg_get_connect_will_topic(nng_msg *); +NNG_DECL uint8_t *nng_mqtt_msg_get_connect_will_msg(nng_msg *, uint32_t *); +NNG_DECL bool nng_mqtt_msg_get_connect_will_retain(nng_msg *); +NNG_DECL uint8_t nng_mqtt_msg_get_connect_will_qos(nng_msg *); +NNG_DECL property *nng_mqtt_msg_get_connect_property(nng_msg *); + +NNG_DECL void nng_mqtt_msg_set_connack_return_code(nng_msg *, uint8_t); +NNG_DECL void nng_mqtt_msg_set_connack_flags(nng_msg *, uint8_t); +NNG_DECL void nng_mqtt_msg_set_connack_property(nng_msg *, property *); +NNG_DECL uint8_t nng_mqtt_msg_get_connack_return_code(nng_msg *); +NNG_DECL uint8_t nng_mqtt_msg_get_connack_flags(nng_msg *); +NNG_DECL property *nng_mqtt_msg_get_connack_property(nng_msg *); + +NNG_DECL void nng_mqtt_msg_set_publish_qos(nng_msg *, uint8_t); +NNG_DECL uint8_t nng_mqtt_msg_get_publish_qos(nng_msg *); +NNG_DECL void nng_mqtt_msg_set_publish_retain(nng_msg *, bool); +NNG_DECL bool nng_mqtt_msg_get_publish_retain(nng_msg *); +NNG_DECL void nng_mqtt_msg_set_publish_dup(nng_msg *, bool); +NNG_DECL bool nng_mqtt_msg_get_publish_dup(nng_msg *); +NNG_DECL int nng_mqtt_msg_set_publish_topic(nng_msg *, const char *); +NNG_DECL int nng_mqtt_msg_set_publish_topic_len(nng_msg *msg, uint32_t len); + +NNG_DECL const char *nng_mqtt_msg_get_publish_topic(nng_msg *, uint32_t *); +NNG_DECL int nng_mqtt_msg_set_publish_payload(nng_msg *, uint8_t *, uint32_t); +NNG_DECL uint8_t *nng_mqtt_msg_get_publish_payload(nng_msg *, uint32_t *); +NNG_DECL property *nng_mqtt_msg_get_publish_property(nng_msg *); +NNG_DECL void nng_mqtt_msg_set_publish_property(nng_msg *, property *); + +NNG_DECL uint16_t nng_mqtt_msg_get_puback_packet_id(nng_msg *); +NNG_DECL property *nng_mqtt_msg_get_puback_property(nng_msg *); +NNG_DECL void nng_mqtt_msg_set_puback_property(nng_msg *, property *); + +NNG_DECL uint16_t nng_mqtt_msg_get_pubrec_packet_id(nng_msg *); +NNG_DECL property *nng_mqtt_msg_get_pubrec_property(nng_msg *); +NNG_DECL void nng_mqtt_msg_set_pubrec_property(nng_msg *, property *); + +NNG_DECL uint16_t nng_mqtt_msg_get_pubrel_packet_id(nng_msg *); +NNG_DECL property *nng_mqtt_msg_get_pubrel_property(nng_msg *); +NNG_DECL void nng_mqtt_msg_set_pubrel_property(nng_msg *, property *); + +NNG_DECL uint16_t nng_mqtt_msg_get_pubcomp_packet_id(nng_msg *); +NNG_DECL property *nng_mqtt_msg_get_pubcomp_property(nng_msg *); +NNG_DECL void nng_mqtt_msg_set_pubcomp_property(nng_msg *, property *); + +NNG_DECL nng_mqtt_topic_qos *nng_mqtt_msg_get_subscribe_topics( + nng_msg *, uint32_t *); +NNG_DECL void nng_mqtt_msg_set_subscribe_topics( + nng_msg *, nng_mqtt_topic_qos *, uint32_t); +NNG_DECL property *nng_mqtt_msg_get_subscribe_property(nng_msg *); +NNG_DECL void nng_mqtt_msg_set_subscribe_property(nng_msg *, property *); + +NNG_DECL void nng_mqtt_msg_set_suback_return_codes( + nng_msg *, uint8_t *, uint32_t); +NNG_DECL uint8_t *nng_mqtt_msg_get_suback_return_codes(nng_msg *, uint32_t *); +NNG_DECL property *nng_mqtt_msg_get_suback_property(nng_msg *); +NNG_DECL void nng_mqtt_msg_set_suback_property(nng_msg *, property *); + +NNG_DECL void nng_mqtt_msg_set_unsubscribe_topics( + nng_msg *, nng_mqtt_topic *, uint32_t); +NNG_DECL nng_mqtt_topic *nng_mqtt_msg_get_unsubscribe_topics( + nng_msg *, uint32_t *); +NNG_DECL property *nng_mqtt_msg_get_unsubscribe_property(nng_msg *); +NNG_DECL void nng_mqtt_msg_set_unsubscribe_property(nng_msg *, property *); + +NNG_DECL void nng_mqtt_msg_set_unsuback_return_codes( + nng_msg *, uint8_t *, uint32_t); +NNG_DECL uint8_t *nng_mqtt_msg_get_unsuback_return_codes(nng_msg *, uint32_t *); +NNG_DECL property *nng_mqtt_msg_get_unsuback_property(nng_msg *); +NNG_DECL void nng_mqtt_msg_set_unsuback_property(nng_msg *, property *); + +NNG_DECL property *nng_mqtt_msg_get_disconnect_property(nng_msg *); +NNG_DECL void nng_mqtt_msg_set_disconnect_property(nng_msg *, property *); + +NNG_DECL nng_mqtt_topic *nng_mqtt_topic_array_create(size_t); +NNG_DECL void nng_mqtt_topic_array_set(nng_mqtt_topic *, size_t, const char *); +NNG_DECL void nng_mqtt_topic_array_free(nng_mqtt_topic *, size_t); +NNG_DECL nng_mqtt_topic_qos *nng_mqtt_topic_qos_array_create(size_t); +NNG_DECL void nng_mqtt_topic_qos_array_set(nng_mqtt_topic_qos *, size_t, + const char *, uint8_t, uint8_t, uint8_t, uint8_t); +NNG_DECL void nng_mqtt_topic_qos_array_free(nng_mqtt_topic_qos *, size_t); +NNG_DECL int nng_mqtt_set_connect_cb(nng_socket, nng_pipe_cb, void *); +NNG_DECL int nng_mqtt_set_disconnect_cb(nng_socket, nng_pipe_cb, void *); +NNG_DECL void nng_mqtt_msg_dump(nng_msg *, uint8_t *, uint32_t, bool); + +NNG_DECL conn_param *nng_get_conn_param_from_msg(nng_msg *); +NNG_DECL void nng_msg_proto_set_property(nng_msg *msg, void *p); +NNG_DECL void nng_mqtt_msg_set_disconnect_reason_code(nng_msg *msg, uint8_t reason_code); + +NNG_DECL uint32_t get_mqtt_properties_len(property *prop); +NNG_DECL int mqtt_property_free(property *prop); +NNG_DECL void mqtt_property_foreach(property *prop, void (*cb)(property *)); +NNG_DECL int mqtt_property_dup(property **dup, const property *src); +NNG_DECL property *mqtt_property_pub_by_will(property *will_prop); +NNG_DECL int mqtt_property_value_copy(property *dst, const property *src); + +NNG_DECL property *mqtt_property_alloc(void); +NNG_DECL property *mqtt_property_set_value_u8(uint8_t prop_id, uint8_t value); +NNG_DECL property *mqtt_property_set_value_u16(uint8_t prop_id, uint16_t value); +NNG_DECL property *mqtt_property_set_value_u32(uint8_t prop_id, uint32_t value); +NNG_DECL property *mqtt_property_set_value_varint(uint8_t prop_id, uint32_t value); +NNG_DECL property *mqtt_property_set_value_binary(uint8_t prop_id, uint8_t *value, uint32_t len, bool copy_value); +NNG_DECL property *mqtt_property_set_value_str( uint8_t prop_id, const char *value, uint32_t len, bool copy_value); +NNG_DECL property *mqtt_property_set_value_strpair(uint8_t prop_id, const char *key, uint32_t key_len, const char *value, uint32_t value_len, bool copy_value); + +NNG_DECL property_type_enum mqtt_property_get_value_type(uint8_t prop_id); +NNG_DECL property_data *mqtt_property_get_value(property *prop, uint8_t prop_id); +NNG_DECL void mqtt_property_append(property *prop_list, property *last); + +// Note that MQTT sockets can be connected to at most a single server. +// Creating the client does not connect it. +NNG_DECL int nng_mqtt_client_open(nng_socket *); +NNG_DECL int nng_mqttv5_client_open(nng_socket *); + +// Note that there is a single implicit dialer for the client, +// and options may be set on the socket to configure dial options. +// Those options should be set before doing nng_dial(). + +// close done via nng_close(). + +// Question: session resumption. Should we resume sessions under the hood +// as part of reconnection, or do we want to expose this to the API user? +// My inclination is not to expose. + +// nng_dial or nng_dialer_create can be used, but this protocol only +// allows a single dialer to be created on the socket. + +// Subscriptions are normally run synchronously from the view of the +// caller. Because there is a round-trip message involved, we use +// a separate method instead of merely relying upon socket options. +// TODO: shared subscriptions. Subscription options (retain, QoS) +typedef struct nng_mqtt_client nng_mqtt_client; +typedef void(nng_mqtt_send_cb)(nng_mqtt_client *client, nng_msg *msg, void *); +struct nng_mqtt_client{ + nng_socket sock; + nng_aio *send_aio; + nng_aio *recv_aio; + void *msgq; + void *obj; // user defined callback obj + bool async; + + nng_mqtt_send_cb *cb; +}; + + +NNG_DECL nng_mqtt_client *nng_mqtt_client_alloc(nng_socket, nng_mqtt_send_cb, bool); +NNG_DECL void nng_mqtt_client_free(nng_mqtt_client*, bool); +NNG_DECL int nng_mqtt_subscribe(nng_socket, nng_mqtt_topic_qos *, uint32_t, property *); +NNG_DECL int nng_mqtt_subscribe_async(nng_mqtt_client *, nng_mqtt_topic_qos *, size_t, property *); +NNG_DECL int nng_mqtt_unsubscribe(nng_socket, nng_mqtt_topic *, size_t, property *); +NNG_DECL int nng_mqtt_unsubscribe_async(nng_mqtt_client *, nng_mqtt_topic *, size_t, property *); +// as with other ctx based methods, we use the aio form exclusively +NNG_DECL int nng_mqtt_ctx_subscribe(nng_ctx *, const char *, nng_aio *, ...); +NNG_DECL int nng_mqtt_disconnect(nng_socket *, uint8_t, property *); + +typedef struct nng_mqtt_sqlite_option nng_mqtt_sqlite_option; + +#if defined(NNG_SUPP_SQLITE) +NNG_DECL int nng_mqtt_alloc_sqlite_opt(nng_mqtt_sqlite_option **); +NNG_DECL int nng_mqtt_free_sqlite_opt(nng_mqtt_sqlite_option *); +NNG_DECL void nng_mqtt_set_sqlite_conf( + nng_mqtt_sqlite_option *sqlite, void *config); +NNG_DECL void nng_mqtt_sqlite_db_init(nng_mqtt_sqlite_option *, const char *); +NNG_DECL void nng_mqtt_sqlite_db_fini(nng_mqtt_sqlite_option *); +#endif + +#ifdef __cplusplus +} +#endif + +#endif // NNG_MQTT_CLIENT_H diff --git a/VNode/_software_lib/nanomq-0.22.10/include/nng/mqtt/mqtt_quic_client.h b/VNode/_software_lib/nanomq-0.22.10/include/nng/mqtt/mqtt_quic_client.h new file mode 100644 index 00000000..cdfb1f7b --- /dev/null +++ b/VNode/_software_lib/nanomq-0.22.10/include/nng/mqtt/mqtt_quic_client.h @@ -0,0 +1,40 @@ +// +// Copyright 2022 NanoMQ Team, Inc. +// +// This software is supplied under the terms of the MIT License, a +// copy of which should be located in the distribution where this +// file was obtained (LICENSE.txt). A copy of the license may also be +// found online at https://opensource.org/licenses/MIT. +// + +#ifndef NNG_MQTT_QUIC_CLIENT_H +#define NNG_MQTT_QUIC_CLIENT_H + +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif +#if defined(SUPP_QUIC) + +NNG_DECL int nng_mqttv5_quic_client_open(nng_socket *); +NNG_DECL int nng_mqtt_quic_client_open(nng_socket *); + +NNG_DECL int nng_mqtt_quic_set_connect_cb(nng_socket *sock, int (*cb)(void *, void *), void *arg); +NNG_DECL int nng_mqtt_quic_set_msg_send_cb(nng_socket *sock, int (*cb)(void *, void *), void *arg); +NNG_DECL int nng_mqtt_quic_set_msg_recv_cb(nng_socket *sock, int (*cb)(void *, void *), void *arg); +NNG_DECL int nng_mqtt_quic_set_disconnect_cb(nng_socket *sock, int (*cb)(void *, void *), void *arg); + +NNG_DECL int nng_mqttv5_quic_set_connect_cb(nng_socket *sock, int (*cb)(void *, void *), void *arg); +NNG_DECL int nng_mqttv5_quic_set_msg_send_cb(nng_socket *sock, int (*cb)(void *, void *), void *arg); +NNG_DECL int nng_mqttv5_quic_set_msg_recv_cb(nng_socket *sock, int (*cb)(void *, void *), void *arg); +NNG_DECL int nng_mqttv5_quic_set_disconnect_cb(nng_socket *sock, int (*cb)(void *, void *), void *arg); + +#endif +#ifdef __cplusplus +} +#endif + +#endif // NNG_MQTT_QUIC_CLIENT_H diff --git a/VNode/_software_lib/nanomq-0.22.10/include/nng/mqtt/packet.h b/VNode/_software_lib/nanomq-0.22.10/include/nng/mqtt/packet.h new file mode 100644 index 00000000..e477e7e9 --- /dev/null +++ b/VNode/_software_lib/nanomq-0.22.10/include/nng/mqtt/packet.h @@ -0,0 +1,87 @@ +// This software is supplied under the terms of the MIT License, a +// copy of which should be located in the distribution where this +// file was obtained (LICENSE.txt). A copy of the license may also be +// found online at https://opensource.org/licenses/MIT. +// +// +// The Struct to store mqtt_packet. + +#ifndef NNG_MQTT_PACKET_H +#define NNG_MQTT_PACKET_H + +#include "nng/nng.h" +#include "nng/mqtt/mqtt_client.h" +#include +#include +#include +#include + +#define UPDATE_FIELD_INT(field, new_obj, old_obj) \ + do { \ + new_obj->field = old_obj->field; \ + } while (0) + +#define UPDATE_FIELD_MQTT_STRING(field, sub_field, new_obj, old_obj) \ + do { \ + if (new_obj->field.sub_field == NULL && \ + old_obj->field.sub_field != NULL) { \ + new_obj->field = old_obj->field; \ + new_obj->field.sub_field = \ + strdup((char *) old_obj->field.sub_field); \ + } \ + } while (0) + +#define UPDATE_FIELD_MQTT_STRING_PAIR( \ + field, sub_field1, sub_field2, new_obj, old_obj) \ + do { \ + if ((new_obj->field.sub_field1 == NULL && \ + old_obj->field.sub_field1 != NULL) || \ + (new_obj->field.sub_field2 == NULL && \ + old_obj->field.sub_field2 != NULL)) { \ + new_obj->field = old_obj->field; \ + new_obj->field.sub_field1 = \ + strdup((char *) old_obj->field.sub_field1); \ + new_obj->field.sub_field2 = \ + strdup((char *) old_obj->field.sub_field2); \ + } \ + } while (0) + +struct mqtt_msg_info { + uint32_t pipe; +}; +typedef struct mqtt_msg_info mqtt_msg_info; + +struct topic_node { + uint8_t qos : 2; + uint8_t no_local : 1; + uint8_t rap : 1; + uint8_t retain_handling : 2; + + struct { + char *body; + int len; + } topic; + + uint8_t reason_code; + + struct topic_node *next; +}; +typedef struct topic_node topic_node; + +struct packet_subscribe { + uint16_t packet_id; + uint32_t prop_len; + property *properties; + topic_node *node; // stored topic and option +}; +typedef struct packet_subscribe packet_subscribe; + +struct packet_unsubscribe { + uint16_t packet_id; + uint32_t prop_len; + property *properties; + topic_node *node; // stored topic and option +}; +typedef struct packet_unsubscribe packet_unsubscribe; + +#endif diff --git a/VNode/_software_lib/nanomq-0.22.10/include/nng/mqtt/transport/quic/mqtt_quic.h b/VNode/_software_lib/nanomq-0.22.10/include/nng/mqtt/transport/quic/mqtt_quic.h new file mode 100644 index 00000000..75c93063 --- /dev/null +++ b/VNode/_software_lib/nanomq-0.22.10/include/nng/mqtt/transport/quic/mqtt_quic.h @@ -0,0 +1,30 @@ +// +// Copyright 2021 Staysail Systems, Inc. +// Copyright 2017 Capitar IT Group BV +// +// This software is supplied under the terms of the MIT License, a +// copy of which should be located in the distribution where this +// file was obtained (LICENSE.txt). A copy of the license may also be +// found online at https://opensource.org/licenses/MIT. +// + +#ifndef NNG_TRANSPORT_MQTT_QUIC_H +#define NNG_TRANSPORT_MQTT_QUIC_H + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +// QUIC transport. This is used for communication over QUIC/UDP/IP. + +#ifndef NNG_ELIDE_DEPRECATED +NNG_DECL int nng_mqtt_quic_register(void); +#endif + +#ifdef __cplusplus +} +#endif + +#endif // NNG_TRANSPORT_MQTT_QUIC_H diff --git a/VNode/_software_lib/nanomq-0.22.10/include/nng/mqtt/transport/tcp/mqtt_tcp.h b/VNode/_software_lib/nanomq-0.22.10/include/nng/mqtt/transport/tcp/mqtt_tcp.h new file mode 100644 index 00000000..31a3c61a --- /dev/null +++ b/VNode/_software_lib/nanomq-0.22.10/include/nng/mqtt/transport/tcp/mqtt_tcp.h @@ -0,0 +1,30 @@ +// +// Copyright 2021 Staysail Systems, Inc. +// Copyright 2017 Capitar IT Group BV +// +// This software is supplied under the terms of the MIT License, a +// copy of which should be located in the distribution where this +// file was obtained (LICENSE.txt). A copy of the license may also be +// found online at https://opensource.org/licenses/MIT. +// + +#ifndef NNG_TRANSPORT_MQTT_TCP_TCP_H +#define NNG_TRANSPORT_MQTT_TCP_TCP_H + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +// TCP transport. This is used for communication over TCP/IP. + +#ifndef NNG_ELIDE_DEPRECATED +NNG_DECL int nng_mqtt_tcp_register(void); +#endif + +#ifdef __cplusplus +} +#endif + +#endif // NNG_TRANSPORT_MQTT_TCP_TCP_H diff --git a/VNode/_software_lib/nanomq-0.22.10/include/nng/mqtt/transport/tls/mqtt_tls.h b/VNode/_software_lib/nanomq-0.22.10/include/nng/mqtt/transport/tls/mqtt_tls.h new file mode 100644 index 00000000..5606d04e --- /dev/null +++ b/VNode/_software_lib/nanomq-0.22.10/include/nng/mqtt/transport/tls/mqtt_tls.h @@ -0,0 +1,30 @@ +// +// Copyright 2021 Staysail Systems, Inc. +// Copyright 2017 Capitar IT Group BV +// +// This software is supplied under the terms of the MIT License, a +// copy of which should be located in the distribution where this +// file was obtained (LICENSE.txt). A copy of the license may also be +// found online at https://opensource.org/licenses/MIT. +// + +#ifndef NNG_TRANSPORT_MQTT_TLS_TLS_H +#define NNG_TRANSPORT_MQTT_TLS_TLS_H + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +// TCP transport. This is used for communication over TCP/IP. + +#ifndef NNG_ELIDE_DEPRECATED +NNG_DECL int nng_mqtts_tcp_register(void); +#endif + +#ifdef __cplusplus +} +#endif + +#endif // NNG_TRANSPORT_MQTT_TLS_TLS_H diff --git a/VNode/_software_lib/nanomq-0.22.10/include/nng/nng.h b/VNode/_software_lib/nanomq-0.22.10/include/nng/nng.h new file mode 100644 index 00000000..4a6d8190 --- /dev/null +++ b/VNode/_software_lib/nanomq-0.22.10/include/nng/nng.h @@ -0,0 +1,1753 @@ +// Copyright 2024 Jaylin +// Copyright 2024 Staysail Systems, Inc. +// Copyright 2018 Capitar IT Group BV +// +// This software is supplied under the terms of the MIT License, a +// copy of which should be located in the distribution where this +// file was obtained (LICENSE.txt). A copy of the license may also be +// found online at https://opensource.org/licenses/MIT. +// + +#ifndef NNG_NNG_H +#define NNG_NNG_H + +// NNG (nanomsg-next-gen) is an improved implementation of the SP protocols. +// The APIs have changed, and there is no attempt to provide API compatibility +// with legacy libnanomsg. This file defines the library consumer-facing +// Public API. Use of definitions or declarations not found in this header +// file is specifically unsupported and strongly discouraged. + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include +#include + +// NNG_DECL is used on declarations to deal with scope. +// For building Windows DLLs, it should be the appropriate __declspec(). +// For shared libraries with platforms that support hidden visibility, +// it should evaluate to __attribute__((visibility("default"))). +#ifndef NNG_DECL +#if defined(_WIN32) && !defined(NNG_STATIC_LIB) +#if defined(NNG_SHARED_LIB) +#define NNG_DECL __declspec(dllexport) +#else +#define NNG_DECL __declspec(dllimport) +#endif // NNG_SHARED_LIB +#else +#if defined(NNG_SHARED_LIB) && defined(NNG_HIDDEN_VISIBILITY) +#define NNG_DECL __attribute__((visibility("default"))) +#else +#define NNG_DECL extern +#endif +#endif // _WIN32 && !NNG_STATIC_LIB +#endif // NNG_DECL + +#ifndef NNG_DEPRECATED +#if defined(__GNUC__) || defined(__clang__) +#define NNG_DEPRECATED __attribute__((deprecated)) +#else +#define NNG_DEPRECATED +#endif +#endif + +// NNG Library & API version. +// We use SemVer, and these versions are about the API, and +// may not necessarily match the ABI versions. +#define NNG_MAJOR_VERSION 1 +#define NNG_MINOR_VERSION 8 +#define NNG_PATCH_VERSION 0 +#define NNG_RELEASE_SUFFIX \ + "" // if non-empty (i.e. "pre"), this is a pre-release + +// Maximum length of a socket address. This includes the terminating NUL. +// This limit is built into other implementations, so do not change it. +// Note that some transports are quite happy to let you use addresses +// in excess of this, but if you do you may not be able to communicate +// with other implementations. +#define NNG_MAXADDRLEN (128) + +// NNG_PROTOCOL_NUMBER is used by protocol headers to calculate their +// protocol number from a major and minor number. Applications should +// probably not need to use this. +#define NNG_PROTOCOL_NUMBER(maj, min) (((x) * 16) + (y)) + +// Types common to nng. + +// Identifiers are wrapped in a structure to improve compiler validation +// of incorrect passing. This gives us strong type checking. Modern +// compilers compile passing these by value to identical code as passing +// the integer type (at least with optimization applied). Please do not +// access the ID member directly. + +typedef struct nng_ctx_s { + uint32_t id; +} nng_ctx; + +typedef struct nng_dialer_s { + uint32_t id; +} nng_dialer; + +typedef struct nng_listener_s { + uint32_t id; +} nng_listener; + +typedef struct nng_pipe_s { + uint32_t id; +} nng_pipe; + +typedef struct nng_socket_s { + uint32_t id; + void * data; +} nng_socket; + +typedef int32_t nng_duration; // in milliseconds + +// nng_time represents an absolute time since some arbitrary point in the +// past, measured in milliseconds. The values are always positive. +typedef uint64_t nng_time; + +typedef struct nng_msg nng_msg; +typedef struct nng_stat nng_stat; +typedef struct nng_aio nng_aio; + +// Initializers. +// clang-format off +#define NNG_PIPE_INITIALIZER { 0 } +#define NNG_SOCKET_INITIALIZER { 0 } +#define NNG_DIALER_INITIALIZER { 0 } +#define NNG_LISTENER_INITIALIZER { 0 } +#define NNG_CTX_INITIALIZER { 0 } +// clang-format on + +// Some address details. This is in some ways like a traditional sockets +// sockaddr, but we have our own to cope with our unique families, etc. +// The details of this structure are directly exposed to applications. +// These structures can be obtained via property lookups, etc. +struct nng_sockaddr_inproc { + uint16_t sa_family; + char sa_name[NNG_MAXADDRLEN]; +}; + +struct nng_sockaddr_path { + uint16_t sa_family; + char sa_path[NNG_MAXADDRLEN]; +}; + +struct nng_sockaddr_in6 { + uint16_t sa_family; + uint16_t sa_port; + uint8_t sa_addr[16]; + uint32_t sa_scope; +}; +struct nng_sockaddr_in { + uint16_t sa_family; + uint16_t sa_port; + uint32_t sa_addr; +}; + +struct nng_sockaddr_zt { + uint16_t sa_family; + uint64_t sa_nwid; + uint64_t sa_nodeid; + uint32_t sa_port; +}; + +struct nng_sockaddr_abstract { + uint16_t sa_family; + uint16_t sa_len; // will be 0 - 107 max. + uint8_t sa_name[107]; // 108 linux/windows, without leading NUL +}; + +// nng_sockaddr_storage is the size required to store any nng_sockaddr. +// This size must not change, and no individual nng_sockaddr type may grow +// larger than this without breaking binary compatibility. +struct nng_sockaddr_storage { + uint16_t sa_family; + uint64_t sa_pad[16]; +}; + +typedef struct nng_sockaddr_inproc nng_sockaddr_inproc; +typedef struct nng_sockaddr_path nng_sockaddr_path; +typedef struct nng_sockaddr_path nng_sockaddr_ipc; +typedef struct nng_sockaddr_in nng_sockaddr_in; +typedef struct nng_sockaddr_in6 nng_sockaddr_in6; +typedef struct nng_sockaddr_zt nng_sockaddr_zt; +typedef struct nng_sockaddr_abstract nng_sockaddr_abstract; +typedef struct nng_sockaddr_storage nng_sockaddr_storage; + +typedef union nng_sockaddr { + uint16_t s_family; + nng_sockaddr_ipc s_ipc; + nng_sockaddr_inproc s_inproc; + nng_sockaddr_in6 s_in6; + nng_sockaddr_in s_in; + nng_sockaddr_zt s_zt; + nng_sockaddr_abstract s_abstract; + nng_sockaddr_storage s_storage; +} nng_sockaddr; + +enum nng_sockaddr_family { + NNG_AF_UNSPEC = 0, + NNG_AF_INPROC = 1, + NNG_AF_IPC = 2, + NNG_AF_INET = 3, + NNG_AF_INET6 = 4, + NNG_AF_ZT = 5, // ZeroTier + NNG_AF_ABSTRACT = 6 +}; + +// Scatter/gather I/O. +typedef struct nng_iov { + void *iov_buf; + size_t iov_len; +} nng_iov; + +// Some definitions for durations used with timeouts. +#define NNG_DURATION_INFINITE (-1) +#define NNG_DURATION_DEFAULT (-2) +#define NNG_DURATION_ZERO (0) + +// nng_fini is used to terminate the library, freeing certain global resources. +// This should only be called during atexit() or just before dlclose(). +// THIS FUNCTION MUST NOT BE CALLED CONCURRENTLY WITH ANY OTHER FUNCTION +// IN THIS LIBRARY; IT IS NOT REENTRANT OR THREADSAFE. +// +// For most cases, this call is unnecessary, but it is provided to assist +// when debugging with memory checkers (e.g. valgrind). Calling this +// function prevents global library resources from being reported incorrectly +// as memory leaks. In those cases, we recommend doing this with atexit(). +NNG_DECL void nng_fini(void); + +// nng_close closes the socket, terminating all activity and +// closing any underlying connections and releasing any associated +// resources. +NNG_DECL int nng_close(nng_socket); + +// nng_socket_id returns the positive socket id for the socket, or -1 +// if the socket is not valid. +NNG_DECL int nng_socket_id(nng_socket); + +NNG_DECL int nng_socket_set(nng_socket, const char *, const void *, size_t); +NNG_DECL int nng_socket_set_bool(nng_socket, const char *, bool); +NNG_DECL int nng_socket_set_int(nng_socket, const char *, int); +NNG_DECL int nng_socket_set_size(nng_socket, const char *, size_t); +NNG_DECL int nng_socket_set_uint64(nng_socket, const char *, uint64_t); +NNG_DECL int nng_socket_set_string(nng_socket, const char *, const char *); +NNG_DECL int nng_socket_set_ptr(nng_socket, const char *, void *); +NNG_DECL int nng_socket_set_ms(nng_socket, const char *, nng_duration); +NNG_DECL int nng_socket_set_addr( + nng_socket, const char *, const nng_sockaddr *); + +NNG_DECL int nng_socket_get(nng_socket, const char *, void *, size_t *); +NNG_DECL int nng_socket_get_bool(nng_socket, const char *, bool *); +NNG_DECL int nng_socket_get_int(nng_socket, const char *, int *); +NNG_DECL int nng_socket_get_size(nng_socket, const char *, size_t *); +NNG_DECL int nng_socket_get_uint64(nng_socket, const char *, uint64_t *); +NNG_DECL int nng_socket_get_string(nng_socket, const char *, char **); +NNG_DECL int nng_socket_get_ptr(nng_socket, const char *, void **); +NNG_DECL int nng_socket_get_ms(nng_socket, const char *, nng_duration *); +NNG_DECL int nng_socket_get_addr(nng_socket, const char *, nng_sockaddr *); + +// Utility function for getting a printable form of the socket address +// for display in logs, etc. It is not intended to be parsed, and the +// display format may change without notice. Generally you should alow +// at least NNG_MAXADDRSTRLEN if you want to avoid typical truncations. +// It is still possible for very long IPC paths to be truncated, but that +// is an edge case and applications that pass such long paths should +// expect some truncation (but they may pass larger values). +#define NNG_MAXADDRSTRLEN (NNG_MAXADDRLEN + 16) // extra bytes for scheme +NNG_DECL const char *nng_str_sockaddr( + const nng_sockaddr *sa, char *buf, size_t bufsz); + +// Arguably the pipe callback functions could be handled as an option, +// but with the need to specify an argument, we find it best to unify +// this as a separate function to pass in the argument and the callback. +// Only one callback can be set on a given socket, and there is no way +// to retrieve the old value. +typedef enum { + NNG_PIPE_EV_ADD_PRE, // Called just before pipe added to socket + NNG_PIPE_EV_ADD_POST, // Called just after pipe added to socket + NNG_PIPE_EV_REM_POST, // Called just after pipe removed from socket + NNG_PIPE_EV_NUM, // Used internally, must be last. +} nng_pipe_ev; + +typedef void (*nng_pipe_cb)(nng_pipe, nng_pipe_ev, void *); + +// nng_pipe_notify registers a callback to be executed when the +// given event is triggered. To watch for different events, register +// multiple times. Each event can have at most one callback registered. +NNG_DECL int nng_pipe_notify(nng_socket, nng_pipe_ev, nng_pipe_cb, void *); + +// nng_listen creates a listening endpoint with no special options, +// and starts it listening. It is functionally equivalent to the legacy +// nn_bind(). The underlying endpoint is returned back to the caller in the +// endpoint pointer, if it is not NULL. The flags are ignored at present. +NNG_DECL int nng_listen(nng_socket, const char *, nng_listener *, int); + +// nng_dial creates a dialing endpoint, with no special options, and +// starts it dialing. Dialers have at most one active connection at a time +// This is similar to the legacy nn_connect(). The underlying endpoint +// is returned back to the caller in the endpoint pointer, if it is not NULL. +// The flags may be NNG_FLAG_NONBLOCK to indicate that the first attempt to +// dial will be made in the background, returning control to the caller +// immediately. In this case, if the connection fails, the function will +// keep retrying in the background. (If the connection is dropped in either +// case, it will still be reconnected in the background -- only the initial +// connection attempt is normally synchronous.) +NNG_DECL int nng_dial(nng_socket, const char *, nng_dialer *, int); + +// nng_dialer_create creates a new dialer, that is not yet started. +NNG_DECL int nng_dialer_create(nng_dialer *, nng_socket, const char *); + +// nng_listener_create creates a new listener, that is not yet started. +NNG_DECL int nng_listener_create(nng_listener *, nng_socket, const char *); + +// nng_dialer_start starts the endpoint dialing. This is only possible if +// the dialer is not already dialing. +NNG_DECL int nng_dialer_start(nng_dialer, int); + +// nng_listener_start starts the endpoint listening. This is only possible if +// the listener is not already listening. +NNG_DECL int nng_listener_start(nng_listener, int); + +// nng_dialer_close closes the dialer, shutting down all underlying +// connections and releasing all associated resources. +NNG_DECL int nng_dialer_close(nng_dialer); + +// nng_listener_close closes the listener, shutting down all underlying +// connections and releasing all associated resources. +NNG_DECL int nng_listener_close(nng_listener); + +// nng_dialer_id returns the positive dialer ID, or -1 if the dialer is +// invalid. +NNG_DECL int nng_dialer_id(nng_dialer); + +// nng_listener_id returns the positive listener ID, or -1 if the listener is +// invalid. +NNG_DECL int nng_listener_id(nng_listener); + +NNG_DECL int nng_dialer_set(nng_dialer, const char *, const void *, size_t); +NNG_DECL int nng_dialer_set_bool(nng_dialer, const char *, bool); +NNG_DECL int nng_dialer_set_int(nng_dialer, const char *, int); +NNG_DECL int nng_dialer_set_size(nng_dialer, const char *, size_t); +NNG_DECL int nng_dialer_set_uint64(nng_dialer, const char *, uint64_t); +NNG_DECL int nng_dialer_set_string(nng_dialer, const char *, const char *); +NNG_DECL int nng_dialer_set_ptr(nng_dialer, const char *, void *); +NNG_DECL int nng_dialer_set_ms(nng_dialer, const char *, nng_duration); +NNG_DECL int nng_dialer_set_addr( + nng_dialer, const char *, const nng_sockaddr *); + +NNG_DECL int nng_dialer_get(nng_dialer, const char *, void *, size_t *); +NNG_DECL int nng_dialer_get_bool(nng_dialer, const char *, bool *); +NNG_DECL int nng_dialer_get_int(nng_dialer, const char *, int *); +NNG_DECL int nng_dialer_get_size(nng_dialer, const char *, size_t *); +NNG_DECL int nng_dialer_get_uint64(nng_dialer, const char *, uint64_t *); +NNG_DECL int nng_dialer_get_string(nng_dialer, const char *, char **); +NNG_DECL int nng_dialer_get_ptr(nng_dialer, const char *, void **); +NNG_DECL int nng_dialer_get_ms(nng_dialer, const char *, nng_duration *); +NNG_DECL int nng_dialer_get_addr(nng_dialer, const char *, nng_sockaddr *); + +NNG_DECL int nng_listener_set( + nng_listener, const char *, const void *, size_t); +NNG_DECL int nng_listener_set_bool(nng_listener, const char *, bool); +NNG_DECL int nng_listener_set_int(nng_listener, const char *, int); +NNG_DECL int nng_listener_set_size(nng_listener, const char *, size_t); +NNG_DECL int nng_listener_set_uint64(nng_listener, const char *, uint64_t); +NNG_DECL int nng_listener_set_string(nng_listener, const char *, const char *); +NNG_DECL int nng_listener_set_ptr(nng_listener, const char *, void *); +NNG_DECL int nng_listener_set_ms(nng_listener, const char *, nng_duration); +NNG_DECL int nng_listener_set_addr( + nng_listener, const char *, const nng_sockaddr *); + +NNG_DECL int nng_listener_get(nng_listener, const char *, void *, size_t *); +NNG_DECL int nng_listener_get_bool(nng_listener, const char *, bool *); +NNG_DECL int nng_listener_get_int(nng_listener, const char *, int *); +NNG_DECL int nng_listener_get_size(nng_listener, const char *, size_t *); +NNG_DECL int nng_listener_get_uint64(nng_listener, const char *, uint64_t *); +NNG_DECL int nng_listener_get_string(nng_listener, const char *, char **); +NNG_DECL int nng_listener_get_ptr(nng_listener, const char *, void **); +NNG_DECL int nng_listener_get_ms(nng_listener, const char *, nng_duration *); +NNG_DECL int nng_listener_get_addr(nng_listener, const char *, nng_sockaddr *); + +// nng_strerror returns a human-readable string associated with the error +// code supplied. +NNG_DECL const char *nng_strerror(int); + +// nng_send sends (or arranges to send) the data on the socket. Note that +// this function may (will!) return before any receiver has actually +// received the data. The return value will be zero to indicate that the +// socket has accepted the entire data for send, or an errno to indicate +// failure. The flags may include NNG_FLAG_NONBLOCK or NNG_FLAG_ALLOC. +// If the flag includes NNG_FLAG_ALLOC, then the function will call +// nng_free() on the supplied pointer & size on success. (If the call +// fails then the memory is not freed.) +NNG_DECL int nng_send(nng_socket, void *, size_t, int); + +// nng_recv receives message data into the socket, up to the supplied size. +// The actual size of the message data will be written to the value pointed +// to by size. The flags may include NNG_FLAG_NONBLOCK and NNG_FLAG_ALLOC. +// If NNG_FLAG_ALLOC is supplied then the library will allocate memory for +// the caller. In that case the pointer to the allocated will be stored +// instead of the data itself. The caller is responsible for freeing the +// associated memory with nng_free(). +NNG_DECL int nng_recv(nng_socket, void *, size_t *, int); + +// nng_sendmsg is like nng_send, but offers up a message structure, which +// gives the ability to provide more control over the message, including +// providing backtrace information. It also can take a message that was +// obtained via nn_recvmsg, allowing for zero copy forwarding. +NNG_DECL int nng_sendmsg(nng_socket, nng_msg *, int); + +// nng_recvmsg is like nng_recv, but is used to obtain a message structure +// as well as the data buffer. This can be used to obtain more information +// about where the message came from, access raw headers, etc. It also +// can be passed off directly to nng_sendmsg. +NNG_DECL int nng_recvmsg(nng_socket, nng_msg **, int); + +// nng_send_aio sends data on the socket asynchronously. As with nng_send, +// the completion may be executed before the data has actually been delivered, +// but only when it is accepted for delivery. The supplied AIO must have +// been initialized, and have an associated message. The message will be +// "owned" by the socket if the operation completes successfully. Otherwise, +// the caller is responsible for freeing it. +NNG_DECL void nng_send_aio(nng_socket, nng_aio *); + +// nng_recv_aio receives data on the socket asynchronously. On a successful +// result, the AIO will have an associated message, that can be obtained +// with nng_aio_get_msg(). The caller takes ownership of the message at +// this point. +NNG_DECL void nng_recv_aio(nng_socket, nng_aio *); + +// Context support. User contexts are not supported by all protocols, +// but for those that do, they give a way to create multiple contexts +// on a single socket, each of which runs the protocol's state machinery +// independently, offering a way to achieve concurrent protocol support +// without resorting to raw mode sockets. See the protocol specific +// documentation for further details. (Note that at this time, only +// asynchronous send/recv are supported for contexts, but its easy enough +// to make synchronous versions with nng_aio_wait().) Note that nng_close +// of the parent socket will *block* as long as any contexts are open. + +// nng_ctx_open creates a context. This returns NNG_ENOTSUP if the +// protocol implementation does not support separate contexts. +NNG_DECL int nng_ctx_open(nng_ctx *, nng_socket); + +// move ctx from socket 1 to socket 2 +// For dynamic bridging use only +NNG_DECL int nng_sock_replace(nng_socket, nng_socket); + +// nng_ctx_close closes the context. +NNG_DECL int nng_ctx_close(nng_ctx); + +// nng_ctx_id returns the numeric id for the context; this will be +// a positive value for a valid context, or < 0 for an invalid context. +// A valid context is not necessarily an *open* context. +NNG_DECL int nng_ctx_id(nng_ctx); + +// nng_ctx_recv receives asynchronously. It works like nng_recv_aio, but +// uses a local context instead of the socket global context. +NNG_DECL void nng_ctx_recv(nng_ctx, nng_aio *); + +// nng_ctx_recvmsg allows for receiving a message synchronously using +// a context. It has the same semantics as nng_recvmsg, but operates +// on a context instead of a socket. +NNG_DECL int nng_ctx_recvmsg(nng_ctx, nng_msg **, int); + +// nng_ctx_send sends asynchronously. It works like nng_send_aio, but +// uses a local context instead of the socket global context. +NNG_DECL void nng_ctx_send(nng_ctx, nng_aio *); + +// nng_ctx_sendmsg is allows for sending a message synchronously using +// a context. It has the same semantics as nng_sendmsg, but operates +// on a context instead of a socket. +NNG_DECL int nng_ctx_sendmsg(nng_ctx, nng_msg *, int); + +NNG_DECL int nng_ctx_get(nng_ctx, const char *, void *, size_t *); +NNG_DECL int nng_ctx_get_bool(nng_ctx, const char *, bool *); +NNG_DECL int nng_ctx_get_int(nng_ctx, const char *, int *); +NNG_DECL int nng_ctx_get_size(nng_ctx, const char *, size_t *); +NNG_DECL int nng_ctx_get_uint64(nng_ctx, const char *, uint64_t *); +NNG_DECL int nng_ctx_get_string(nng_ctx, const char *, char **); +NNG_DECL int nng_ctx_get_ptr(nng_ctx, const char *, void **); +NNG_DECL int nng_ctx_get_ms(nng_ctx, const char *, nng_duration *); +NNG_DECL int nng_ctx_get_addr(nng_ctx, const char *, nng_sockaddr *); + +NNG_DECL int nng_ctx_set(nng_ctx, const char *, const void *, size_t); +NNG_DECL int nng_ctx_set_bool(nng_ctx, const char *, bool); +NNG_DECL int nng_ctx_set_int(nng_ctx, const char *, int); +NNG_DECL int nng_ctx_set_size(nng_ctx, const char *, size_t); +NNG_DECL int nng_ctx_set_uint64(nng_ctx, const char *, uint64_t); +NNG_DECL int nng_ctx_set_string(nng_ctx, const char *, const char *); +NNG_DECL int nng_ctx_set_ptr(nng_ctx, const char *, void *); +NNG_DECL int nng_ctx_set_ms(nng_ctx, const char *, nng_duration); +NNG_DECL int nng_ctx_set_addr(nng_ctx, const char *, const nng_sockaddr *); + +// nng_alloc is used to allocate memory. It's intended purpose is for +// allocating memory suitable for message buffers with nng_send(). +// Applications that need memory for other purposes should use their platform +// specific API. +NNG_DECL void *nng_alloc(size_t); + +// nng_free is used to free memory allocated with nng_alloc, which includes +// memory allocated by nng_recv() when the NNG_FLAG_ALLOC message is supplied. +// As the application is required to keep track of the size of memory, this +// is probably less convenient for general uses than the C library malloc and +// calloc. +NNG_DECL void *nng_zalloc(size_t sz); +NNG_DECL void nng_zfree(void *ptr); +NNG_DECL void nng_free(void *, size_t); + +// nng_strdup duplicates the source string, using nng_alloc. The result +// should be freed with nng_strfree (or nng_free(strlen(s)+1)). +NNG_DECL char *nng_strdup(const char *); +NNG_DECL char *nng_strndup(const char *, size_t); +NNG_DECL char *nng_strnins(char *, const char *, size_t, size_t); +NNG_DECL char *nng_strncat(char *, const char *, size_t, size_t); + +// nng_strfree is equivalent to nng_free(strlen(s)+1). +NNG_DECL void nng_strfree(char *); + +NNG_DECL char *nng_strcasestr(const char *, const char *); +NNG_DECL int nng_strcasecmp(const char *, const char *); +NNG_DECL int nng_strncasecmp(const char *, const char *, size_t); + +// Async IO API. AIO structures can be thought of as "handles" to +// support asynchronous operations. They contain the completion callback, and +// a pointer to consumer data. This is similar to how overlapped I/O +// works in Windows, when used with a completion callback. +// +// AIO structures can carry up to 4 distinct input values, and up to +// 4 distinct output values, and up to 4 distinct "private state" values. +// The meaning of the inputs and the outputs are determined by the +// I/O functions being called. + +// nng_aio_alloc allocates a new AIO, and associated the completion +// callback and its opaque argument. If NULL is supplied for the +// callback, then the caller must use nng_aio_wait() to wait for the +// operation to complete. If the completion callback is not NULL, then +// when a submitted operation completes (or is canceled or fails) the +// callback will be executed, generally in a different thread, with no +// locks held. +NNG_DECL int nng_aio_alloc(nng_aio **, void (*)(void *), void *); + +// nng_aio_free frees the AIO and any associated resources. +// It *must not* be in use at the time it is freed. +NNG_DECL void nng_aio_free(nng_aio *); + +// nng_aio_reap is like nng_aio_free, but calls it from a background +// reaper thread. This can be useful to free aio objects from aio +// callbacks (e.g. when the result of the callback is to discard +// the object in question.) The aio object must be in further use +// when this is called. +NNG_DECL void nng_aio_reap(nng_aio *); + +// nng_aio_stop stops any outstanding operation, and waits for the +// AIO to be free, including for the callback to have completed +// execution. Therefore, the caller must NOT hold any locks that +// are acquired in the callback, or deadlock will occur. +NNG_DECL void nng_aio_stop(nng_aio *); + +// nng_aio_result returns the status/result of the operation. This +// will be zero on successful completion, or an nng error code on +// failure. +NNG_DECL int nng_aio_result(nng_aio *); + +// nng_aio_count returns the number of bytes transferred for certain +// I/O operations. This is meaningless for other operations (e.g. +// DNS lookups or TCP connection setup). +NNG_DECL size_t nng_aio_count(nng_aio *); + +// nng_aio_cancel attempts to cancel any in-progress I/O operation. +// The AIO callback will still be executed, but if the cancellation is +// successful then the status will be NNG_ECANCELED. +NNG_DECL void nng_aio_cancel(nng_aio *); + +// nng_aio_abort is like nng_aio_cancel, but allows for a different +// error result to be returned. +NNG_DECL void nng_aio_abort(nng_aio *, int); + +// nng_aio_wait waits synchronously for any pending operation to complete. +// It also waits for the callback to have completed execution. Therefore, +// the caller of this function must not hold any locks acquired by the +// callback or deadlock may occur. +NNG_DECL void nng_aio_wait(nng_aio *); + +// nng_aio_busy returns true if the aio is still busy processing the +// operation, or executing associated completion functions. Note that +// if the completion function schedules a new operation using the aio, +// then this function will continue to return true. +NNG_DECL bool nng_aio_busy(nng_aio *); + +// nng_aio_set_msg sets the message structure to use for asynchronous +// message send operations. +NNG_DECL void nng_aio_set_msg(nng_aio *, nng_msg *); + +// nng_aio_get_msg returns the message structure associated with a completed +// receive operation. +NNG_DECL nng_msg *nng_aio_get_msg(nng_aio *); + +// nng_aio_set_input sets an input parameter at the given index. +NNG_DECL int nng_aio_set_input(nng_aio *, unsigned, void *); + +// nng_aio_get_input retrieves the input parameter at the given index. +NNG_DECL void *nng_aio_get_input(nng_aio *, unsigned); + +// nng_aio_set_output sets an output result at the given index. +NNG_DECL int nng_aio_set_output(nng_aio *, unsigned, void *); + +// nng_aio_get_output retrieves the output result at the given index. +NNG_DECL void *nng_aio_get_output(nng_aio *, unsigned); + +NNG_DECL void nng_aio_set_prov_data(nng_aio *, void *); +NNG_DECL void *nng_aio_get_prov_data(nng_aio *); + +// nng_aio_set_timeout sets a timeout on the AIO. This should be called for +// operations that should time out after a period. The timeout should be +// either a positive number of milliseconds, or NNG_DURATION_INFINITE to +// indicate that the operation has no timeout. A poll may be done by +// specifying NNG_DURATION_ZERO. The value NNG_DURATION_DEFAULT indicates +// that any socket specific timeout should be used. +NNG_DECL void nng_aio_set_timeout(nng_aio *, nng_duration); + +// nng_aio_set_expire is like nng_aio_set_timeout, except it sets an absolute +// expiration time. This is useful when chaining actions on a single aio +// as part of a state machine. +NNG_DECL void nng_aio_set_expire(nng_aio *, nng_time); + +// nng_aio_set_iov sets a scatter/gather vector on the aio. The iov array +// itself is copied. Data members (the memory regions referenced) *may* be +// copied as well, depending on the operation. This operation is guaranteed +// to succeed if n <= 4, otherwise it may fail due to NNG_ENOMEM. +NNG_DECL int nng_aio_set_iov(nng_aio *, unsigned, const nng_iov *); + +// nng_aio_begin is called by the provider to mark the operation as +// beginning. If it returns false, then the provider must take no +// further action on the aio. +NNG_DECL bool nng_aio_begin(nng_aio *); + +// nng_aio_finish is used to "finish" an asynchronous operation. +// It should only be called by "providers" (such as HTTP server API users). +// The argument is the value that nng_aio_result() should return. +// IMPORTANT: Callers must ensure that this is called EXACTLY ONCE on any +// given aio. +NNG_DECL void nng_aio_finish(nng_aio *, int); + +// nng_aio_defer is used to register a cancellation routine, and indicate +// that the operation will be completed asynchronously. It must only be +// called once per operation on an aio, and must only be called by providers. +// If the operation is canceled by the consumer, the cancellation callback +// will be called. The provider *must* still ensure that the nng_aio_finish() +// function is called EXACTLY ONCE. If the operation cannot be canceled +// for any reason, the cancellation callback should do nothing. The +// final argument is passed to the cancelfn. The final argument of the +// cancellation function is the error number (will not be zero) corresponding +// to the reason for cancellation, e.g. NNG_ETIMEDOUT or NNG_ECANCELED. +typedef void (*nng_aio_cancelfn)(nng_aio *, void *, int); +NNG_DECL void nng_aio_defer(nng_aio *, nng_aio_cancelfn, void *); + +// nng_aio_sleep does a "sleeping" operation, basically does nothing +// but wait for the specified number of milliseconds to expire, then +// calls the callback. This returns 0, rather than NNG_ETIMEDOUT. +NNG_DECL void nng_sleep_aio(nng_duration, nng_aio *); + +// Message API. +NNG_DECL int nng_msg_alloc(nng_msg **, size_t); +NNG_DECL void nng_msg_free(nng_msg *); +NNG_DECL int nng_msg_realloc(nng_msg *, size_t); +NNG_DECL int nng_msg_reserve(nng_msg *, size_t); +NNG_DECL size_t nng_msg_capacity(nng_msg *); +NNG_DECL void *nng_msg_header(nng_msg *); +NNG_DECL size_t nng_msg_header_len(const nng_msg *); +NNG_DECL void *nng_msg_body(nng_msg *); +NNG_DECL size_t nng_msg_len(const nng_msg *); +NNG_DECL int nng_msg_append(nng_msg *, const void *, size_t); +NNG_DECL int nng_msg_insert(nng_msg *, const void *, size_t); +NNG_DECL int nng_msg_trim(nng_msg *, size_t); +NNG_DECL int nng_msg_chop(nng_msg *, size_t); +NNG_DECL int nng_msg_header_append(nng_msg *, const void *, size_t); +NNG_DECL int nng_msg_header_insert(nng_msg *, const void *, size_t); +NNG_DECL int nng_msg_header_trim(nng_msg *, size_t); +NNG_DECL int nng_msg_header_chop(nng_msg *, size_t); +NNG_DECL int nng_msg_header_append_u16(nng_msg *, uint16_t); +NNG_DECL int nng_msg_header_append_u32(nng_msg *, uint32_t); +NNG_DECL int nng_msg_header_append_u64(nng_msg *, uint64_t); +NNG_DECL int nng_msg_header_insert_u16(nng_msg *, uint16_t); +NNG_DECL int nng_msg_header_insert_u32(nng_msg *, uint32_t); +NNG_DECL int nng_msg_header_insert_u64(nng_msg *, uint64_t); +NNG_DECL int nng_msg_header_chop_u16(nng_msg *, uint16_t *); +NNG_DECL int nng_msg_header_chop_u32(nng_msg *, uint32_t *); +NNG_DECL int nng_msg_header_chop_u64(nng_msg *, uint64_t *); +NNG_DECL int nng_msg_header_trim_u16(nng_msg *, uint16_t *); +NNG_DECL int nng_msg_header_trim_u32(nng_msg *, uint32_t *); +NNG_DECL int nng_msg_header_trim_u64(nng_msg *, uint64_t *); +NNG_DECL int nng_msg_append_u16(nng_msg *, uint16_t); +NNG_DECL int nng_msg_append_u32(nng_msg *, uint32_t); +NNG_DECL int nng_msg_append_u64(nng_msg *, uint64_t); +NNG_DECL int nng_msg_insert_u16(nng_msg *, uint16_t); +NNG_DECL int nng_msg_insert_u32(nng_msg *, uint32_t); +NNG_DECL int nng_msg_insert_u64(nng_msg *, uint64_t); +NNG_DECL int nng_msg_chop_u16(nng_msg *, uint16_t *); +NNG_DECL int nng_msg_chop_u32(nng_msg *, uint32_t *); +NNG_DECL int nng_msg_chop_u64(nng_msg *, uint64_t *); +NNG_DECL int nng_msg_trim_u16(nng_msg *, uint16_t *); +NNG_DECL int nng_msg_trim_u32(nng_msg *, uint32_t *); +NNG_DECL int nng_msg_trim_u64(nng_msg *, uint64_t *); +NNG_DECL int nng_msg_dup(nng_msg **, const nng_msg *); +NNG_DECL void nng_msg_clear(nng_msg *); +NNG_DECL void nng_msg_header_clear(nng_msg *); +NNG_DECL void nng_msg_set_pipe(nng_msg *, nng_pipe); +NNG_DECL nng_pipe nng_msg_get_pipe(const nng_msg *); + +// Pipe API. Generally pipes are only "observable" to applications, but +// we do permit an application to close a pipe. This can be useful, for +// example during a connection notification, to disconnect a pipe that +// is associated with an invalid or untrusted remote peer. +NNG_DECL int nng_pipe_get(nng_pipe, const char *, void *, size_t *); +NNG_DECL int nng_pipe_get_bool(nng_pipe, const char *, bool *); +NNG_DECL int nng_pipe_get_int(nng_pipe, const char *, int *); +NNG_DECL int nng_pipe_get_ms(nng_pipe, const char *, nng_duration *); +NNG_DECL int nng_pipe_get_size(nng_pipe, const char *, size_t *); +NNG_DECL int nng_pipe_get_uint64(nng_pipe, const char *, uint64_t *); +NNG_DECL int nng_pipe_get_string(nng_pipe, const char *, char **); +NNG_DECL int nng_pipe_get_ptr(nng_pipe, const char *, void **); +NNG_DECL int nng_pipe_get_addr(nng_pipe, const char *, nng_sockaddr *); + +NNG_DECL int nng_pipe_close(nng_pipe); +NNG_DECL int nng_pipe_id(nng_pipe); +NNG_DECL nng_socket nng_pipe_socket(nng_pipe); +NNG_DECL nng_dialer nng_pipe_dialer(nng_pipe); +NNG_DECL nng_listener nng_pipe_listener(nng_pipe); + +// Flags. +#define NNG_FLAG_ALLOC 1u // Recv to allocate receive buffer +#define NNG_FLAG_NONBLOCK 2u // Non-blocking operations + +// Options. +#define NNG_OPT_SOCKNAME "socket-name" +#define NNG_OPT_RAW "raw" +#define NNG_OPT_PROTO "protocol" +#define NNG_OPT_PROTONAME "protocol-name" +#define NNG_OPT_PEER "peer" +#define NNG_OPT_PEERNAME "peer-name" +#define NNG_OPT_RECVBUF "recv-buffer" +#define NNG_OPT_SENDBUF "send-buffer" +#define NNG_OPT_RECVFD "recv-fd" +#define NNG_OPT_SENDFD "send-fd" +#define NNG_OPT_RECVTIMEO "recv-timeout" +#define NNG_OPT_SENDTIMEO "send-timeout" +#define NNG_OPT_LOCADDR "local-address" +#define NNG_OPT_REMADDR "remote-address" +#define NNG_OPT_URL "url" +#define NNG_OPT_MAXTTL "ttl-max" +#define NNG_OPT_RECVMAXSZ "recv-size-max" +#define NNG_OPT_RECONNMINT "reconnect-time-min" +#define NNG_OPT_RECONNMAXT "reconnect-time-max" + +// NNG-MQTT +#define NNG_OPT_MQTT_CONNMSG "mqtt-connect-msg" +#define NNG_OPT_MQTT_BRIDGE_CONF "mqtt-bridge-config" + +// NNG-QUIC +#define NNG_OPT_QUIC_ENABLE_0RTT "quic-0rtt" +#define NNG_OPT_QUIC_ENABLE_MULTISTREAM "quic-multistream" +#define NNG_OPT_QUIC_IDLE_TIMEOUT "quic-idle-timeout" +#define NNG_OPT_QUIC_KEEPALIVE "quic-keepalive" +#define NNG_OPT_QUIC_CONNECT_TIMEOUT "quic-connect-timeout" +#define NNG_OPT_QUIC_DISCONNECT_TIMEOUT "quic-disconnect-timeout" +#define NNG_OPT_QUIC_SEND_IDLE_TIMEOUT "quic-send-idle-timeout" +#define NNG_OPT_QUIC_INITIAL_RTT_MS "quic-initial-ms" +#define NNG_OPT_QUIC_MAX_ACK_DELAY_MS "quic-max-ack-delay-ms" +#define NNG_OPT_MQTT_QUIC_PRIORITY "quic-mqtt-stream-priority" +#define NNG_OPT_QUIC_PRIORITY "quic-stream-priority" + +#define NNG_OPT_QUIC_CONGESTION_CTL_CUBIC "quic-congestion-cubic" + +#define NNG_OPT_QUIC_TLS_CACERT_PATH "quic-tls-cacert" +#define NNG_OPT_QUIC_TLS_KEY_PATH "quic-tls-key" +#define NNG_OPT_QUIC_TLS_KEY_PASSWORD "quic-tls-pwd" +#define NNG_OPT_QUIC_TLS_VERIFY_PEER "quic-tls-verify" +#define NNG_OPT_QUIC_TLS_CA_PATH "quic-tls-ca" + +// TLS options are only used when the underlying transport supports TLS. + +// NNG_OPT_TLS_CONFIG is a pointer to a nng_tls_config object. Generally +// this can be used with endpoints, although once an endpoint is started, or +// once a configuration is used, the value becomes read-only. Note that +// when configuring the object, a hold is placed on the TLS configuration, +// using a reference count. When retrieving the object, no such hold is +// placed, and so the caller must take care not to use the associated object +// after the endpoint it is associated with is closed. +#define NNG_OPT_TLS_CONFIG "tls-config" + +// NNG_OPT_TLS_AUTH_MODE is a write-only integer (int) option that specifies +// whether peer authentication is needed. The option can take one of the +// values of NNG_TLS_AUTH_MODE_NONE, NNG_TLS_AUTH_MODE_OPTIONAL, or +// NNG_TLS_AUTH_MODE_REQUIRED. The default is typically NNG_TLS_AUTH_MODE_NONE +// for listeners, and NNG_TLS_AUTH_MODE_REQUIRED for dialers. If set to +// REQUIRED, then connections will be rejected if the peer cannot be verified. +// If set to OPTIONAL, then a verification step takes place, but the connection +// is still permitted. (The result can be checked with NNG_OPT_TLS_VERIFIED). +#define NNG_OPT_TLS_AUTH_MODE "tls-authmode" + +// NNG_OPT_TLS_CERT_KEY_FILE names a single file that contains a certificate +// and key identifying the endpoint. This is a write-only value. This can be +// set multiple times for different keys/certs corresponding to +// different algorithms on listeners, whereas dialers only support one. The +// file must contain both cert and key as PEM blocks, and the key must +// not be encrypted. (If more flexibility is needed, use the TLS configuration +// directly, via NNG_OPT_TLS_CONFIG.) +#define NNG_OPT_TLS_CERT_KEY_FILE "tls-cert-key-file" + +// NNG_OPT_TLS_CA_FILE names a single file that contains certificate(s) for a +// CA, and optionally CRLs, which are used to validate the peer's certificate. +// This is a write-only value, but multiple CAs can be loaded by setting this +// multiple times. +#define NNG_OPT_TLS_CA_FILE "tls-ca-file" + +// NNG_OPT_TLS_SERVER_NAME is a write-only string that can typically be +// set on dialers to check the CN of the server for a match. This +// can also affect SNI (server name indication). It usually has no effect +// on listeners. +#define NNG_OPT_TLS_SERVER_NAME "tls-server-name" + +// NNG_OPT_TLS_VERIFIED returns a boolean indicating whether the peer has +// been verified (true) or not (false). Typically, this is read-only, and +// only available for pipes. This option may return incorrect results if +// peer authentication is disabled with `NNG_TLS_AUTH_MODE_NONE`. +#define NNG_OPT_TLS_VERIFIED "tls-verified" + +// NNG_OPT_TLS_PEER_CN returns the string with the common name +// of the peer certificate. Typically, this is read-only and +// only available for pipes. This option may return incorrect results if +// peer authentication is disabled with `NNG_TLS_AUTH_MODE_NONE`. +#define NNG_OPT_TLS_PEER_CN "tls-peer-cn" + +// NNG_OPT_TLS_PEER_ALT_NAMES returns string list with the +// subject alternative names of the peer certificate. Typically this is +// read-only and only available for pipes. This option may return +// incorrect results if peer authentication is disabled with +// `NNG_TLS_AUTH_MODE_NONE`. +#define NNG_OPT_TLS_PEER_ALT_NAMES "tls-peer-alt-names" + +// TCP options. These may be supported on various transports that use +// TCP underneath such as TLS, or not. + +// TCP nodelay disables the use of Nagle, so that messages are sent +// as soon as data is available. This tends to reduce latency, but +// can come at the cost of extra messages being sent, and may have +// a detrimental effect on performance. For most uses, we recommend +// enabling this. (Disable it if you are on a very slow network.) +// This is a boolean. +#define NNG_OPT_TCP_NODELAY "tcp-nodelay" + +// TCP keepalive causes the underlying transport to send keep-alive +// messages, and keep the session active. Keepalives are zero length +// messages with the ACK flag turned on. If we don't get an ACK back, +// then we know the other side is gone. This is useful for detecting +// dead peers, and is also used to prevent disconnections caused by +// middle boxes thinking the session has gone idle (e.g. keeping NAT +// state current). This is a boolean. +#define NNG_OPT_TCP_KEEPALIVE "tcp-keepalive" + +// TODO: more notes +#define NNG_OPT_TCP_QUICKACK "tcp-quickack" + +#define NNG_OPT_TCP_KEEPIDLE "tcp-keepidle" + +#define NNG_OPT_TCP_KEEPINTVL "tcp-keepintvl" + +#define NNG_OPT_TCP_KEEPCNT "tcp-keepcnt" + +#define NNG_OPT_TCP_SENDTIMEO "tcp-sendtimeo" + +#define NNG_OPT_TCP_RECVTIMEO "tcp-recvtimeo" + +// Local TCP port number. This is used on a listener, and is intended +// to be used after starting the listener in combination with a wildcard +// (0) local port. This determines the actual ephemeral port that was +// selected and bound. The value is provided as an int, but only the +// low order 16 bits will be set. This is provided in native byte order, +// which makes it more convenient than using the NNG_OPT_LOCADDR option. +#define NNG_OPT_TCP_BOUND_PORT "tcp-bound-port" + +// IPC options. These will largely vary depending on the platform, +// as POSIX systems have very different options than Windows. + +// Security Descriptor. This option may only be set on listeners +// on the Windows platform, where the object is a pointer to a +// a Windows SECURITY_DESCRIPTOR. +#define NNG_OPT_IPC_SECURITY_DESCRIPTOR "ipc:security-descriptor" + +// Permissions bits. This option is only valid for listeners on +// POSIX platforms and others that honor UNIX style permission bits. +// Note that some platforms may not honor the permissions here, although +// at least Linux and macOS seem to do so. Check before you rely on +// this for security. +#define NNG_OPT_IPC_PERMISSIONS "ipc:permissions" + +// IPC peer options may also be used in some cases with other socket types. + +// Peer UID. This is only available on POSIX style systems. +#define NNG_OPT_PEER_UID "ipc:peer-uid" +#define NNG_OPT_IPC_PEER_UID NNG_OPT_PEER_UID + +// Peer GID (primary group). This is only available on POSIX style systems. +#define NNG_OPT_PEER_GID "ipc:peer-gid" +#define NNG_OPT_IPC_PEER_GID NNG_OPT_PEER_GID + +// Peer process ID. Available on Windows, Linux, and SunOS. +// In theory, we could obtain this with the first message sent, +// but we have elected not to do this for now. (Nice RFE for a FreeBSD +// guru though.) +#define NNG_OPT_PEER_PID "ipc:peer-pid" +#define NNG_OPT_IPC_PEER_PID NNG_OPT_PEER_PID + +// Peer Zone ID. Only on SunOS systems. (Linux containers have no +// definable kernel identity; they are a user-land fabrication made up +// from various pieces of different namespaces. FreeBSD does have +// something called JailIDs, but it isn't obvious how to determine this, +// or even if processes can use IPC across jail boundaries.) +#define NNG_OPT_PEER_ZONEID "ipc:peer-zoneid" +#define NNG_OPT_IPC_PEER_ZONEID NNG_OPT_PEER_ZONEID + +// WebSocket Options. + +// NNG_OPT_WS_REQUEST_HEADERS is a string containing the +// request headers, formatted as CRLF terminated lines. +#define NNG_OPT_WS_REQUEST_HEADERS "ws:request-headers" + +// NNG_OPT_WS_RESPONSE_HEADERS is a string containing the +// response headers, formatted as CRLF terminated lines. +#define NNG_OPT_WS_RESPONSE_HEADERS "ws:response-headers" + +// NNG_OPT_WS_REQUEST_HEADER is a prefix, for a dynamic +// property name. This allows direct access to any named header. +// Concatenate this with the name of the property (case is not sensitive). +// Only the first such header is returned. +#define NNG_OPT_WS_RESPONSE_HEADER "ws:response-header:" + +// NNG_OPT_WS_RESPONSE_HEADER is like NNG_OPT_REQUEST_HEADER, but used for +// accessing the request headers. +#define NNG_OPT_WS_REQUEST_HEADER "ws:request-header:" + +// NNG_OPT_WS_REQUEST_URI is used to obtain the URI sent by the client. +// This can be useful when a handler supports an entire directory tree. +#define NNG_OPT_WS_REQUEST_URI "ws:request-uri" + +// NNG_OPT_WS_SENDMAXFRAME is used to configure the fragmentation size +// used for frames. This has a default value of 64k. Large values +// are good for throughput, but penalize latency. They also require +// additional buffering on the peer. This value must not be larger +// than what the peer will accept, and unfortunately there is no way +// to negotiate this. +#define NNG_OPT_WS_SENDMAXFRAME "ws:txframe-max" + +// NNG_OPT_WS_RECVMAXFRAME is the largest frame we will accept. This should +// probably not be larger than NNG_OPT_RECVMAXSZ. If the sender attempts +// to send more data than this in a single message, it will be dropped. +#define NNG_OPT_WS_RECVMAXFRAME "ws:rxframe-max" + +// NNG_OPT_WS_PROTOCOL is the "websocket sub-protocol" -- it's a string. +// This is also known as the Sec-WebSocket-Protocol header. It is treated +// specially. This is part of the websocket handshake. +#define NNG_OPT_WS_PROTOCOL "ws:protocol" + +// NNG_OPT_WS_SEND_TEXT is a boolean used to tell the WS stream +// transport to send text messages. This is not supported for the +// core WebSocket transport, but when using streams it might be useful +// to speak with 3rd party WebSocket applications. This mode should +// not be used unless absolutely required. No validation of the message +// contents is performed by NNG; applications are expected to honor +// the requirement to send only valid UTF-8. (Compliant applications +// will close the socket if they see this message type with invalid UTF-8.) +#define NNG_OPT_WS_SEND_TEXT "ws:send-text" + +// NNG_OPT_WS_RECV_TEXT is a boolean that enables NNG to receive +// TEXT frames. This is only useful for stream mode applications -- +// SP protocol requires the use of binary frames. Note also that +// NNG does not validate the message contents for valid UTF-8; this +// means it will not be conformant with RFC-6455 on it's own. Applications +// that need this should check the message contents themselves, and +// close the connection if invalid UTF-8 is received. This option +// should not be used unless required to communication with 3rd party +// peers that cannot be coerced into sending binary frames. +#define NNG_OPT_WS_RECV_TEXT "ws:recv-text" + +// NNG_OPT_SOCKET_FD is a write-only integer property that is used to +// file descriptors (or FILE HANDLE objects on Windows) to a +// socket:// based listener. This file descriptor will be taken +// over and used as a stream connection. The protocol is compatible +// with SP over TCP. This facility is experimental, and intended to +// allow use with descriptors created via socketpair() or similar. +// Note that unidirectional pipes (such as those from pipe(2) or mkfifo) +// are not supported. +#define NNG_OPT_SOCKET_FD "socket:fd" + +// XXX: TBD: priorities, ipv4only + +// Statistics. These are for informational purposes only, and subject +// to change without notice. The API for accessing these is stable, +// but the individual statistic names, values, and meanings are all +// subject to change. + +// nng_stats_get takes a snapshot of the entire set of statistics. +// While the operation can be somewhat expensive (allocations), it +// is done in a way that minimizes impact to running operations. +// Note that the statistics are provided as a tree, with parents +// used for grouping, and with child statistics underneath. The +// top stat returned will be of type NNG_STAT_SCOPE with name "". +// Applications may choose to consider this root scope as "root", if +// the empty string is not suitable. +NNG_DECL int nng_stats_get(nng_stat **); + +// nng_stats_free frees a previous list of snapshots. This should only +// be called on the parent statistic that obtained via nng_stats_get. +NNG_DECL void nng_stats_free(nng_stat *); + +// nng_stats_dump is a debugging function that dumps the entire set of +// statistics to stdout. +NNG_DECL void nng_stats_dump(nng_stat *); + +// nng_stat_next finds the next sibling for the current stat. If there +// are no more siblings, it returns NULL. +NNG_DECL nng_stat *nng_stat_next(nng_stat *); + +// nng_stat_child finds the first child of the current stat. If no children +// exist, then NULL is returned. +NNG_DECL nng_stat *nng_stat_child(nng_stat *); + +// nng_stat_name is used to determine the name of the statistic. +// This is a human-readable name. Statistic names, as well as the presence +// or absence or semantic of any particular statistic are not part of any +// stable API, and may be changed without notice in future updates. +NNG_DECL const char *nng_stat_name(nng_stat *); + +// nng_stat_type is used to determine the type of the statistic. +// Counters generally increment, and therefore changes in the value over +// time are likely more interesting than the actual level. Level +// values reflect some absolute state however, and should be presented to the +// user as is. +NNG_DECL int nng_stat_type(nng_stat *); + +// nng_stat_find is used to find a specific named statistic within +// a statistic tree. NULL is returned if no such statistic exists. +NNG_DECL nng_stat *nng_stat_find(nng_stat *, const char *); + +// nng_stat_find_socket is used to find the stats for the given socket. +NNG_DECL nng_stat *nng_stat_find_socket(nng_stat *, nng_socket); + +// nng_stat_find_dialer is used to find the stats for the given dialer. +NNG_DECL nng_stat *nng_stat_find_dialer(nng_stat *, nng_dialer); + +// nng_stat_find_listener is used to find the stats for the given listener. +NNG_DECL nng_stat *nng_stat_find_listener(nng_stat *, nng_listener); + +enum nng_stat_type_enum { + NNG_STAT_SCOPE = 0, // Stat is for scoping, and carries no value + NNG_STAT_LEVEL = 1, // Numeric "absolute" value, diffs meaningless + NNG_STAT_COUNTER = 2, // Incrementing value (diffs are meaningful) + NNG_STAT_STRING = 3, // Value is a string + NNG_STAT_BOOLEAN = 4, // Value is a boolean + NNG_STAT_ID = 5, // Value is a numeric ID +}; + +// nng_stat_unit provides information about the unit for the statistic, +// such as NNG_UNIT_BYTES or NNG_UNIT_BYTES. If no specific unit is +// applicable, such as a relative priority, then NN_UNIT_NONE is returned. +NNG_DECL int nng_stat_unit(nng_stat *); + +enum nng_unit_enum { + NNG_UNIT_NONE = 0, // No special units + NNG_UNIT_BYTES = 1, // Bytes, e.g. bytes sent, etc. + NNG_UNIT_MESSAGES = 2, // Messages, one per message + NNG_UNIT_MILLIS = 3, // Milliseconds + NNG_UNIT_EVENTS = 4 // Some other type of event +}; + +// nng_stat_value returns the actual value of the statistic. +// Statistic values reflect their value at the time that the corresponding +// snapshot was updated, and are undefined until an update is performed. +NNG_DECL uint64_t nng_stat_value(nng_stat *); + +// nng_stat_bool returns the boolean value of the statistic. +NNG_DECL bool nng_stat_bool(nng_stat *); + +// nng_stat_string returns the string associated with a string statistic, +// or NULL if the statistic is not part of the string. The value returned +// is valid until the associated statistic is freed. +NNG_DECL const char *nng_stat_string(nng_stat *); + +// nng_stat_desc returns a human-readable description of the statistic. +// This may be useful for display in diagnostic interfaces, etc. +NNG_DECL const char *nng_stat_desc(nng_stat *); + +// nng_stat_timestamp returns a timestamp (milliseconds) when the statistic +// was captured. The base offset is the same as used by nng_clock(). +// We don't use nng_time though, because that's in the supplemental header. +NNG_DECL uint64_t nng_stat_timestamp(nng_stat *); + +// Device functionality. This connects two sockets together in a device, +// which means that messages from one side are forwarded to the other. +// This version is synchronous, which means the caller will block until +// one of the sockets is closed. Note that caller is responsible for +// finally closing both sockets when this function returns. +NNG_DECL int nng_device(nng_socket, nng_socket); + +// Asynchronous form of nng_device. When this succeeds, the device is +// left intact and functioning in the background, until one of the sockets +// is closed or the application exits. The sockets may be shut down if +// the device fails, but the caller is responsible for ultimately closing +// the sockets properly after the device is torn down. +NNG_DECL void nng_device_aio(nng_aio *, nng_socket, nng_socket); + +// Symbol name and visibility. TBD. The only symbols that really should +// be directly exported to runtimes IMO are the option symbols. And frankly +// they have enough special logic around them that it might be best not to +// automate the promotion of them to other APIs. This is an area open +// for discussion. + +// Error codes. These generally have different values from UNIX errnos, +// so take care about converting them. The one exception is that 0 is +// unambiguously "success". +// +// NNG_SYSERR is a special code, which allows us to wrap errors from the +// underlying operating system. We generally prefer to map errors to one +// of the above, but if we cannot, then we just encode an error this way. +// The bit is large enough to accommodate all known UNIX and Win32 error +// codes. We try hard to match things semantically to one of our standard +// errors. For example, a connection reset or aborted we treat as a +// closed connection, because that's basically what it means. (The remote +// peer closed the connection.) For certain kinds of resource exhaustion +// we treat it the same as memory. But for files, etc. that's OS-specific, +// and we use the generic below. Some of the above error codes we use +// internally, and the application should never see (e.g. NNG_EINTR). +// +// NNG_ETRANERR is like ESYSERR, but is used to wrap transport specific +// errors, from different transports. It should only be used when none +// of the other options are available. + +enum nng_errno_enum { + NNG_EINTR = 1, + NNG_ENOMEM = 2, + NNG_EINVAL = 3, + NNG_EBUSY = 4, + NNG_ETIMEDOUT = 5, + NNG_ECONNREFUSED = 6, + NNG_ECLOSED = 7, + NNG_EAGAIN = 8, + NNG_ENOTSUP = 9, + NNG_EADDRINUSE = 10, + NNG_ESTATE = 11, + NNG_ENOENT = 12, + NNG_EPROTO = 13, + NNG_EUNREACHABLE = 14, + NNG_EADDRINVAL = 15, + NNG_EPERM = 16, + NNG_EMSGSIZE = 17, + NNG_ECONNABORTED = 18, + NNG_ECONNRESET = 19, + NNG_ECANCELED = 20, + NNG_ENOFILES = 21, + NNG_ENOSPC = 22, + NNG_EEXIST = 23, + NNG_EREADONLY = 24, + NNG_EWRITEONLY = 25, + NNG_ECRYPTO = 26, + NNG_EPEERAUTH = 27, + NNG_ENOARG = 28, + NNG_EAMBIGUOUS = 29, + NNG_EBADTYPE = 30, + NNG_ECONNSHUT = 31, + NNG_EINTERNAL = 1000, + NNG_ESYSERR = 0x10000000, + NNG_ETRANERR = 0x20000000 +}; + +// URL support. We frequently want to process a URL, and these methods +// give us a convenient way of doing so. + +typedef struct nng_url { + char *u_rawurl; // never NULL + char *u_scheme; // never NULL + char *u_userinfo; // will be NULL if not specified + char *u_host; // including colon and port + char *u_hostname; // name only, will be "" if not specified + char *u_port; // port, will be "" if not specified + char *u_path; // path, will be "" if not specified + char *u_query; // without '?', will be NULL if not specified + char *u_fragment; // without '#', will be NULL if not specified + char *u_requri; // includes query and fragment, "" if not specified +} nng_url; + +// nng_url_parse parses a URL string into a structured form. +// Note that the u_port member will be filled out with a numeric +// port if one isn't specified and a default port is appropriate for +// the scheme. The URL structure is allocated, along with individual +// members. It can be freed with nng_url_free. +NNG_DECL int nng_url_parse(nng_url **, const char *); + +// nng_url_free frees a URL structure that was created by nng_url_parse(). +NNG_DECL void nng_url_free(nng_url *); + +// nng_url_clone clones a URL structure. +NNG_DECL int nng_url_clone(nng_url **, const nng_url *); + +// nng_version returns the library version as a human readable string. +NNG_DECL const char *nng_version(void); + +// nng_stream operations permit direct access to low level streams, +// which can have a variety of uses. Internally most of the transports +// are built on top of these. Streams are created by other dialers or +// listeners. The API for creating dialers and listeners varies. + +typedef struct nng_stream nng_stream; +typedef struct nng_stream_dialer nng_stream_dialer; +typedef struct nng_stream_listener nng_stream_listener; + +NNG_DECL void nng_stream_free(nng_stream *); +NNG_DECL void nng_stream_close(nng_stream *); +NNG_DECL void nng_stream_send(nng_stream *, nng_aio *); +NNG_DECL void nng_stream_recv(nng_stream *, nng_aio *); +NNG_DECL int nng_stream_get(nng_stream *, const char *, void *, size_t *); +NNG_DECL int nng_stream_get_bool(nng_stream *, const char *, bool *); +NNG_DECL int nng_stream_get_int(nng_stream *, const char *, int *); +NNG_DECL int nng_stream_get_ms(nng_stream *, const char *, nng_duration *); +NNG_DECL int nng_stream_get_size(nng_stream *, const char *, size_t *); +NNG_DECL int nng_stream_get_uint64(nng_stream *, const char *, uint64_t *); +NNG_DECL int nng_stream_get_string(nng_stream *, const char *, char **); +NNG_DECL int nng_stream_get_ptr(nng_stream *, const char *, void **); +NNG_DECL int nng_stream_get_addr(nng_stream *, const char *, nng_sockaddr *); +NNG_DECL int nng_stream_set(nng_stream *, const char *, const void *, size_t); +NNG_DECL int nng_stream_set_bool(nng_stream *, const char *, bool); +NNG_DECL int nng_stream_set_int(nng_stream *, const char *, int); +NNG_DECL int nng_stream_set_ms(nng_stream *, const char *, nng_duration); +NNG_DECL int nng_stream_set_size(nng_stream *, const char *, size_t); +NNG_DECL int nng_stream_set_uint64(nng_stream *, const char *, uint64_t); +NNG_DECL int nng_stream_set_string(nng_stream *, const char *, const char *); +NNG_DECL int nng_stream_set_ptr(nng_stream *, const char *, void *); +NNG_DECL int nng_stream_set_addr( + nng_stream *, const char *, const nng_sockaddr *); + +NNG_DECL int nng_stream_dialer_alloc(nng_stream_dialer **, const char *); +NNG_DECL int nng_stream_dialer_alloc_url( + nng_stream_dialer **, const nng_url *); +NNG_DECL void nng_stream_dialer_free(nng_stream_dialer *); +NNG_DECL void nng_stream_dialer_close(nng_stream_dialer *); +NNG_DECL void nng_stream_dialer_dial(nng_stream_dialer *, nng_aio *); +NNG_DECL int nng_stream_dialer_set( + nng_stream_dialer *, const char *, const void *, size_t); +NNG_DECL int nng_stream_dialer_get( + nng_stream_dialer *, const char *, void *, size_t *); +NNG_DECL int nng_stream_dialer_get_bool( + nng_stream_dialer *, const char *, bool *); +NNG_DECL int nng_stream_dialer_get_int( + nng_stream_dialer *, const char *, int *); +NNG_DECL int nng_stream_dialer_get_ms( + nng_stream_dialer *, const char *, nng_duration *); +NNG_DECL int nng_stream_dialer_get_size( + nng_stream_dialer *, const char *, size_t *); +NNG_DECL int nng_stream_dialer_get_uint64( + nng_stream_dialer *, const char *, uint64_t *); +NNG_DECL int nng_stream_dialer_get_string( + nng_stream_dialer *, const char *, char **); +NNG_DECL int nng_stream_dialer_get_ptr( + nng_stream_dialer *, const char *, void **); +NNG_DECL int nng_stream_dialer_get_addr( + nng_stream_dialer *, const char *, nng_sockaddr *); +NNG_DECL int nng_stream_dialer_set_bool( + nng_stream_dialer *, const char *, bool); +NNG_DECL int nng_stream_dialer_set_int(nng_stream_dialer *, const char *, int); +NNG_DECL int nng_stream_dialer_set_ms( + nng_stream_dialer *, const char *, nng_duration); +NNG_DECL int nng_stream_dialer_set_size( + nng_stream_dialer *, const char *, size_t); +NNG_DECL int nng_stream_dialer_set_uint64( + nng_stream_dialer *, const char *, uint64_t); +NNG_DECL int nng_stream_dialer_set_string( + nng_stream_dialer *, const char *, const char *); +NNG_DECL int nng_stream_dialer_set_ptr( + nng_stream_dialer *, const char *, void *); +NNG_DECL int nng_stream_dialer_set_addr( + nng_stream_dialer *, const char *, const nng_sockaddr *); + +NNG_DECL int nng_stream_listener_alloc(nng_stream_listener **, const char *); +NNG_DECL int nng_stream_listener_alloc_url( + nng_stream_listener **, const nng_url *); +NNG_DECL void nng_stream_listener_free(nng_stream_listener *); +NNG_DECL void nng_stream_listener_close(nng_stream_listener *); +NNG_DECL int nng_stream_listener_listen(nng_stream_listener *); +NNG_DECL void nng_stream_listener_accept(nng_stream_listener *, nng_aio *); +NNG_DECL int nng_stream_listener_set( + nng_stream_listener *, const char *, const void *, size_t); +NNG_DECL int nng_stream_listener_get( + nng_stream_listener *, const char *, void *, size_t *); +NNG_DECL int nng_stream_listener_get_bool( + nng_stream_listener *, const char *, bool *); +NNG_DECL int nng_stream_listener_get_int( + nng_stream_listener *, const char *, int *); +NNG_DECL int nng_stream_listener_get_ms( + nng_stream_listener *, const char *, nng_duration *); +NNG_DECL int nng_stream_listener_get_size( + nng_stream_listener *, const char *, size_t *); +NNG_DECL int nng_stream_listener_get_uint64( + nng_stream_listener *, const char *, uint64_t *); +NNG_DECL int nng_stream_listener_get_string( + nng_stream_listener *, const char *, char **); +NNG_DECL int nng_stream_listener_get_ptr( + nng_stream_listener *, const char *, void **); +NNG_DECL int nng_stream_listener_get_addr( + nng_stream_listener *, const char *, nng_sockaddr *); +NNG_DECL int nng_stream_listener_set_bool( + nng_stream_listener *, const char *, bool); +NNG_DECL int nng_stream_listener_set_int( + nng_stream_listener *, const char *, int); +NNG_DECL int nng_stream_listener_set_ms( + nng_stream_listener *, const char *, nng_duration); +NNG_DECL int nng_stream_listener_set_size( + nng_stream_listener *, const char *, size_t); +NNG_DECL int nng_stream_listener_set_uint64( + nng_stream_listener *, const char *, uint64_t); +NNG_DECL int nng_stream_listener_set_string( + nng_stream_listener *, const char *, const char *); +NNG_DECL int nng_stream_listener_set_ptr( + nng_stream_listener *, const char *, void *); +NNG_DECL int nng_stream_listener_set_addr( + nng_stream_listener *, const char *, const nng_sockaddr *); + +typedef struct nng_lmq nng_lmq; + +NNG_DECL int nng_lmq_alloc(nng_lmq **, size_t ); +NNG_DECL void nng_lmq_free(nng_lmq *); +NNG_DECL void nng_lmq_flush(nng_lmq *); +NNG_DECL size_t nng_lmq_len(nng_lmq *); +NNG_DECL size_t nng_lmq_cap(nng_lmq *); +NNG_DECL int nng_lmq_put(nng_lmq *, nng_msg *); +NNG_DECL int nng_lmq_get(nng_lmq *, nng_msg **); +NNG_DECL int nng_lmq_resize(nng_lmq *, size_t ); +NNG_DECL bool nng_lmq_full(nng_lmq *); +NNG_DECL bool nng_lmq_empty(nng_lmq *); + +// typedef struct nng_id_map nng_id_map; + +// NNG_DECL void nng_id_map_init( +// nng_id_map *, uint32_t , uint32_t , bool ); +// NNG_DECL void nng_id_map_fini(nng_id_map *); +// NNG_DECL void *nng_id_get(nng_id_map *, uint32_t ); +// NNG_DECL int nng_id_set(nng_id_map *, uint32_t , void *); +// NNG_DECL int nng_id_alloc(nng_id_map *, uint32_t *, void *); +// NNG_DECL int nng_id_remove(nng_id_map *, uint32_t ); + +// NANOMQ MQTT variables & APIs +typedef struct conn_param conn_param; +typedef struct pub_packet_struct pub_packet_struct; +typedef struct pipe_db nano_pipe_db; + +NNG_DECL int nng_access(const char* name, int flag); + +// NANOMQ MQTT API ends +// UDP operations. These are provided for convenience, +// and should be considered somewhat experimental. + +// nng_udp represents a socket / file descriptor for use with UDP +typedef struct nng_udp nng_udp; + +// nng_udp_open initializes a UDP socket. The socket is bound +// to the specified address. +NNG_DECL int nng_udp_open(nng_udp **udpp, nng_sockaddr *sa); + +// nng_udp_close closes the underlying UDP socket. +NNG_DECL void nng_udp_close(nng_udp *udp); + +// nng_udp_sockname determines the locally bound address. +// This is useful to determine a chosen port after binding to port 0. +NNG_DECL int nng_udp_sockname(nng_udp *udp, nng_sockaddr *sa); + +// nng_udp_send sends the data in the aio to the the +// destination specified in the nng_aio. The iovs are the UDP payload. +// The destination address is the first input (0th) for the aio. +NNG_DECL void nng_udp_send(nng_udp *udp, nng_aio *aio); + +// nng_udp_recv receives a message, storing it in the iovs +// from the UDP payload. If the UDP payload will not fit, then +// NNG_EMSGSIZE results. The senders address is stored in the +// socket address (nng_sockaddr), which should have been specified +// in the aio's first input. +NNG_DECL void nng_udp_recv(nng_udp *udp, nng_aio *aio); + +// nng_udp_membership provides for joining or leaving multicast groups. +NNG_DECL int nng_udp_multicast_membership( + nng_udp *udp, nng_sockaddr *sa, bool join); + +#ifndef NNG_ELIDE_DEPRECATED +// These are legacy APIs that have been deprecated. +// Their use is strongly discouraged. + +// nng_msg_getopt is defunct, and should not be used by programs. It +// always returns NNG_ENOTSUP. +NNG_DECL int nng_msg_getopt(nng_msg *, int, void *, size_t *) NNG_DEPRECATED; + +// Socket options. Use nng_socket_get and nng_socket_set instead. +NNG_DECL int nng_getopt( + nng_socket, const char *, void *, size_t *) NNG_DEPRECATED; +NNG_DECL int nng_getopt_bool(nng_socket, const char *, bool *) NNG_DEPRECATED; +NNG_DECL int nng_getopt_int(nng_socket, const char *, int *) NNG_DEPRECATED; +NNG_DECL int nng_getopt_ms( + nng_socket, const char *, nng_duration *) NNG_DEPRECATED; +NNG_DECL int nng_getopt_size( + nng_socket, const char *, size_t *) NNG_DEPRECATED; +NNG_DECL int nng_getopt_uint64( + nng_socket, const char *, uint64_t *) NNG_DEPRECATED; +NNG_DECL int nng_getopt_ptr(nng_socket, const char *, void **) NNG_DEPRECATED; +NNG_DECL int nng_getopt_string( + nng_socket, const char *, char **) NNG_DEPRECATED; +NNG_DECL int nng_setopt( + nng_socket, const char *, const void *, size_t) NNG_DEPRECATED; +NNG_DECL int nng_setopt_bool(nng_socket, const char *, bool) NNG_DEPRECATED; +NNG_DECL int nng_setopt_int(nng_socket, const char *, int) NNG_DEPRECATED; +NNG_DECL int nng_setopt_ms( + nng_socket, const char *, nng_duration) NNG_DEPRECATED; +NNG_DECL int nng_setopt_size(nng_socket, const char *, size_t) NNG_DEPRECATED; +NNG_DECL int nng_setopt_uint64( + nng_socket, const char *, uint64_t) NNG_DEPRECATED; +NNG_DECL int nng_setopt_string( + nng_socket, const char *, const char *) NNG_DEPRECATED; +NNG_DECL int nng_setopt_ptr(nng_socket, const char *, void *) NNG_DEPRECATED; + +// Context options. Use nng_ctx_get and nng_ctx_set instead. +NNG_DECL int nng_ctx_getopt( + nng_ctx, const char *, void *, size_t *) NNG_DEPRECATED; +NNG_DECL int nng_ctx_getopt_bool(nng_ctx, const char *, bool *) NNG_DEPRECATED; +NNG_DECL int nng_ctx_getopt_int(nng_ctx, const char *, int *) NNG_DEPRECATED; +NNG_DECL int nng_ctx_getopt_ms( + nng_ctx, const char *, nng_duration *) NNG_DEPRECATED; +NNG_DECL int nng_ctx_getopt_size( + nng_ctx, const char *, size_t *) NNG_DEPRECATED; +NNG_DECL int nng_ctx_setopt( + nng_ctx, const char *, const void *, size_t) NNG_DEPRECATED; +NNG_DECL int nng_ctx_setopt_bool(nng_ctx, const char *, bool) NNG_DEPRECATED; +NNG_DECL int nng_ctx_setopt_int(nng_ctx, const char *, int) NNG_DEPRECATED; +NNG_DECL int nng_ctx_setopt_ms( + nng_ctx, const char *, nng_duration) NNG_DEPRECATED; +NNG_DECL int nng_ctx_setopt_size(nng_ctx, const char *, size_t) NNG_DEPRECATED; + +// Dialer options. Use nng_dialer_get and nng_dialer_set instead. +NNG_DECL int nng_dialer_getopt( + nng_dialer, const char *, void *, size_t *) NNG_DEPRECATED; +NNG_DECL int nng_dialer_getopt_bool( + nng_dialer, const char *, bool *) NNG_DEPRECATED; +NNG_DECL int nng_dialer_getopt_int( + nng_dialer, const char *, int *) NNG_DEPRECATED; +NNG_DECL int nng_dialer_getopt_ms( + nng_dialer, const char *, nng_duration *) NNG_DEPRECATED; +NNG_DECL int nng_dialer_getopt_size( + nng_dialer, const char *, size_t *) NNG_DEPRECATED; +NNG_DECL int nng_dialer_getopt_sockaddr( + nng_dialer, const char *, nng_sockaddr *) NNG_DEPRECATED; +NNG_DECL int nng_dialer_getopt_uint64( + nng_dialer, const char *, uint64_t *) NNG_DEPRECATED; +NNG_DECL int nng_dialer_getopt_ptr( + nng_dialer, const char *, void **) NNG_DEPRECATED; +NNG_DECL int nng_dialer_getopt_string( + nng_dialer, const char *, char **) NNG_DEPRECATED; +NNG_DECL int nng_dialer_setopt( + nng_dialer, const char *, const void *, size_t) NNG_DEPRECATED; +NNG_DECL int nng_dialer_setopt_bool( + nng_dialer, const char *, bool) NNG_DEPRECATED; +NNG_DECL int nng_dialer_setopt_int( + nng_dialer, const char *, int) NNG_DEPRECATED; +NNG_DECL int nng_dialer_setopt_ms( + nng_dialer, const char *, nng_duration) NNG_DEPRECATED; +NNG_DECL int nng_dialer_setopt_size( + nng_dialer, const char *, size_t) NNG_DEPRECATED; +NNG_DECL int nng_dialer_setopt_uint64( + nng_dialer, const char *, uint64_t) NNG_DEPRECATED; +NNG_DECL int nng_dialer_setopt_ptr( + nng_dialer, const char *, void *) NNG_DEPRECATED; +NNG_DECL int nng_dialer_setopt_string( + nng_dialer, const char *, const char *) NNG_DEPRECATED; + +// Listener options. Use nng_listener_get and nng_listener_set instead. +NNG_DECL int nng_listener_getopt( + nng_listener, const char *, void *, size_t *) NNG_DEPRECATED; +NNG_DECL int nng_listener_getopt_bool( + nng_listener, const char *, bool *) NNG_DEPRECATED; +NNG_DECL int nng_listener_getopt_int( + nng_listener, const char *, int *) NNG_DEPRECATED; +NNG_DECL int nng_listener_getopt_ms( + nng_listener, const char *, nng_duration *) NNG_DEPRECATED; +NNG_DECL int nng_listener_getopt_size( + nng_listener, const char *, size_t *) NNG_DEPRECATED; +NNG_DECL int nng_listener_getopt_sockaddr( + nng_listener, const char *, nng_sockaddr *) NNG_DEPRECATED; +NNG_DECL int nng_listener_getopt_uint64( + nng_listener, const char *, uint64_t *) NNG_DEPRECATED; +NNG_DECL int nng_listener_getopt_ptr( + nng_listener, const char *, void **) NNG_DEPRECATED; +NNG_DECL int nng_listener_getopt_string( + nng_listener, const char *, char **) NNG_DEPRECATED; +NNG_DECL int nng_listener_setopt( + nng_listener, const char *, const void *, size_t) NNG_DEPRECATED; +NNG_DECL int nng_listener_setopt_bool( + nng_listener, const char *, bool) NNG_DEPRECATED; +NNG_DECL int nng_listener_setopt_int( + nng_listener, const char *, int) NNG_DEPRECATED; +NNG_DECL int nng_listener_setopt_ms( + nng_listener, const char *, nng_duration) NNG_DEPRECATED; +NNG_DECL int nng_listener_setopt_size( + nng_listener, const char *, size_t) NNG_DEPRECATED; +NNG_DECL int nng_listener_setopt_uint64( + nng_listener, const char *, uint64_t) NNG_DEPRECATED; +NNG_DECL int nng_listener_setopt_ptr( + nng_listener, const char *, void *) NNG_DEPRECATED; +NNG_DECL int nng_listener_setopt_string( + nng_listener, const char *, const char *) NNG_DEPRECATED; + +// Pipe options. Use nng_pipe_get instead. +NNG_DECL int nng_pipe_getopt( + nng_pipe, const char *, void *, size_t *) NNG_DEPRECATED; +NNG_DECL int nng_pipe_getopt_bool( + nng_pipe, const char *, bool *) NNG_DEPRECATED; +NNG_DECL int nng_pipe_getopt_int(nng_pipe, const char *, int *) NNG_DEPRECATED; +NNG_DECL int nng_pipe_getopt_ms( + nng_pipe, const char *, nng_duration *) NNG_DEPRECATED; +NNG_DECL int nng_pipe_getopt_size( + nng_pipe, const char *, size_t *) NNG_DEPRECATED; +NNG_DECL int nng_pipe_getopt_sockaddr( + nng_pipe, const char *, nng_sockaddr *) NNG_DEPRECATED; +NNG_DECL int nng_pipe_getopt_uint64( + nng_pipe, const char *, uint64_t *) NNG_DEPRECATED; +NNG_DECL int nng_pipe_getopt_ptr( + nng_pipe, const char *, void **) NNG_DEPRECATED; +NNG_DECL int nng_pipe_getopt_string( + nng_pipe, const char *, char **) NNG_DEPRECATED; + +// nng_closeall closes all open sockets. Do not call this from +// a library; it will affect all sockets. +NNG_DECL void nng_closeall(void) NNG_DEPRECATED; + +#endif // NNG_ELIDE_DEPRECATED + +// nng_init_parameter is used by applications to change a tunable setting. +// This function must be called before any other NNG function for the setting +// to have any effect. This function is also not thread-safe! +// +// The list of parameters supported is *not* documented, and subject to change. +// +// We try to provide sane defaults, so the use here is intended to provide +// more control for applications that cannot use compile-time configuration. +// +// Applications should not depend on this API for correct operation. +// +// This API is intentionally undocumented. +// +// Parameter settings are lost after nng_fini() is called. +typedef int nng_init_parameter; +NNG_DECL void nng_init_set_parameter(nng_init_parameter, uint64_t); + +// The following list of parameters is not part of our API stability promise. +// In particular the set of parameters that are supported, the default values, +// the range of valid values, and semantics associated therein are subject to +// change at any time. We won't go out of our way to break these, and we will +// try to prevent changes here from breaking working applications, but this is +// on a best effort basis only. +// +// NOTE: When removing a value, please leave the enumeration in place and add +// a suffix _RETIRED ... this will preserve the binary values for binary +// compatibility. +enum { + NNG_INIT_PARAMETER_NONE = 0, // ensure values start at 1. + + // Fix the number of threads used for tasks (callbacks), + // Default is 2 threads per core, capped to NNG_INIT_MAX_TASK_THREADS. + // At least 2 threads will be created in any case. + NNG_INIT_NUM_TASK_THREADS, + + // Fix the number of threads used for expiration. Default is one + // thread per core, capped to NNG_INIT_MAX_EXPIRE_THREADS. At least + // one thread will be created. + NNG_INIT_NUM_EXPIRE_THREADS, + + // Fix the number of poller threads (used for I/O). Support varies + // by platform (many platforms only support a single poller thread.) + NNG_INIT_NUM_POLLER_THREADS, + + // Fix the number of threads used for DNS resolution. At least one + // will be used. Default is controlled by NNG_RESOLV_CONCURRENCY + // compile time variable. + NNG_INIT_NUM_RESOLVER_THREADS, + + // Limit the number of threads of created for tasks. + // NNG will always create at least 2 of these in order to prevent + // deadlocks. Zero means no limit. Default is determined by + // NNG_MAX_TASKQ_THREADS compile time variable. + NNG_INIT_MAX_TASK_THREADS, + + // Limit the number of threads created for expiration. Zero means no + // limit. Default is determined by the NNG_MAX_EXPIRE_THREADS compile + // time variable. + NNG_INIT_MAX_EXPIRE_THREADS, + + // Limit the number of poller/IO threads created. Zero means no limit. + // Default is determined by NNG_MAX_POLLER_THREADS compile time + // variable. + NNG_INIT_MAX_POLLER_THREADS, +}; + +NNG_DECL void nng_aio_finish_error(nng_aio *aio, int rv); +NNG_DECL void nng_aio_finish_sync(nng_aio *aio, int rv); +NNG_DECL uint8_t nng_msg_cmd_type(nng_msg *msg); +NNG_DECL uint8_t nng_msg_get_type(nng_msg *msg); +NNG_DECL size_t nng_msg_remaining_len(nng_msg *msg); +NNG_DECL uint8_t *nng_msg_header_ptr(nng_msg *msg); +NNG_DECL uint8_t *nng_msg_payload_ptr(nng_msg *msg); +NNG_DECL void nng_msg_set_payload_ptr(nng_msg *msg, uint8_t *ptr); +NNG_DECL void nng_msg_set_remaining_len(nng_msg *msg, size_t len); +NNG_DECL void nng_msg_clone(nng_msg *msg); +NNG_DECL void nng_msg_set_cmd_type(nng_msg *m, uint8_t cmd); +NNG_DECL nng_msg *nng_msg_unique(nng_msg *m); +NNG_DECL int nng_make_parent_dirs(const char *name); +NNG_DECL int nng_file_put(const char *name, const void *data, size_t sz); +NNG_DECL int nng_file_get(const char *name, void **datap, size_t *szp); +NNG_DECL bool nng_file_is_dir(const char *path); +NNG_DECL int nng_file_delete(const char *name); +NNG_DECL void nng_msg_set_timestamp(nng_msg *m, uint64_t time); +NNG_DECL uint64_t nng_msg_get_timestamp(nng_msg *m); + +NNG_DECL void *nng_msg_get_conn_param(nng_msg *msg); +NNG_DECL void nng_msg_set_conn_param(nng_msg *msg, void *ptr); + +NNG_DECL const uint8_t *conn_param_get_clientid(conn_param *cparam); +NNG_DECL const uint8_t *conn_param_get_pro_name(conn_param *cparam); +NNG_DECL const void * conn_param_get_will_topic(conn_param *cparam); +NNG_DECL const void * conn_param_get_will_msg(conn_param *cparam); +NNG_DECL const uint8_t *conn_param_get_username(conn_param *cparam); +NNG_DECL const uint8_t *conn_param_get_password(conn_param *cparam); +NNG_DECL uint8_t conn_param_get_con_flag(conn_param *cparam); +NNG_DECL uint8_t conn_param_get_clean_start(conn_param *cparam); +NNG_DECL uint8_t conn_param_get_will_flag(conn_param *cparam); +NNG_DECL uint8_t conn_param_get_will_qos(conn_param *cparam); +NNG_DECL uint8_t conn_param_get_will_retain(conn_param *cparam); +NNG_DECL uint16_t conn_param_get_keepalive(conn_param *cparam); +NNG_DECL uint8_t conn_param_get_protover(conn_param *cparam); +NNG_DECL void *conn_param_get_qos_db(conn_param *cparam); +NNG_DECL void *conn_param_get_ip_addr_v4(conn_param *cparam); +NNG_DECL void *conn_param_get_property(conn_param *cparam); +NNG_DECL void *conn_param_get_will_property(conn_param *cparam); +NNG_DECL void conn_param_set_qos_db(conn_param *cparam, void *); +NNG_DECL void conn_param_set_clientid( + conn_param *cparam, const char *clientid); +NNG_DECL void conn_param_set_username( + conn_param *cparam, const char *username); +NNG_DECL void conn_param_set_password( + conn_param *cparam, const char *password); +NNG_DECL void conn_param_set_proto_ver(conn_param *cparam, uint8_t ver); +NNG_DECL uint64_t conn_param_get_will_delay_timestamp(conn_param *cparam); +NNG_DECL uint64_t conn_param_get_will_mexp(conn_param *cparam); +NNG_DECL void nng_msg_set_proto_data(nng_msg *m, void *ops, void *data); +NNG_DECL void *nng_msg_get_proto_data(nng_msg *m); +NNG_DECL conn_param *nng_pipe_cparam(nng_pipe p); +NNG_DECL bool nng_pipe_status(nng_pipe p); + +NNG_DECL void nng_taskq_setter(int num_taskq_threads, int max_taskq_threads); + +#if defined(NNG_SUPP_SQLITE) + +NNG_DECL int nng_mqtt_qos_db_set_retain( + void *, const char *, nng_msg *, uint8_t); +NNG_DECL nng_msg *nng_mqtt_qos_db_get_retain(void *, const char *); +NNG_DECL int nng_mqtt_qos_db_remove_retain(void *, const char *); +NNG_DECL nng_msg **nng_mqtt_qos_db_find_retain(void *, const char *); + +#endif + + +// Return an absolute time from some arbitrary point. The value is +// provided in milliseconds, and is of limited resolution based on the +// system clock. (Do not use it for fine-grained performance measurements.) +NNG_DECL nng_time nng_clock(void); + +// Sleep for specified msecs. +NNG_DECL void nng_msleep(nng_duration); + +// nng_random returns a "strong" (cryptographic sense) random number. +NNG_DECL uint32_t nng_random(void); + +// nng_socket_pair is used to create a bound pair of file descriptors +// typically using the socketpair() call. The descriptors are backed +// by reliable, bidirectional, byte streams. This will return NNG_ENOTSUP +// if the platform lacks support for this. The argument is a pointer +// to an array of file descriptors (or HANDLES or similar). +NNG_DECL int nng_socket_pair(int[2]); + +// Multithreading and synchronization functions. + +// nng_thread is a handle to a "thread", which may be a real system +// thread, or a coroutine on some platforms. +typedef struct nng_thread nng_thread; + +// Create and start a thread. Note that on some platforms, this might +// actually be a coroutine, with limitations about what system APIs +// you can call. Therefore, these threads should only be used with the +// I/O APIs provided by nng. The thread runs until completion. +NNG_DECL int nng_thread_create(nng_thread **, void (*)(void *), void *); + +// Set the thread name. Support for this is platform specific and varies. +// It is intended to provide information for use when debugging applications, +// and not for programmatic use beyond that. +NNG_DECL void nng_thread_set_name(nng_thread *, const char *); + +// Destroy a thread (waiting for it to complete.) When this function +// returns all resources for the thread are cleaned up. +NNG_DECL void nng_thread_destroy(nng_thread *); + +// nng_mtx represents a mutex, which is a simple, non-reentrant, boolean lock. +typedef struct nng_mtx nng_mtx; + +// nng_mtx_alloc allocates a mutex structure. +NNG_DECL int nng_mtx_alloc(nng_mtx **); + +// nng_mtx_free frees the mutex. It must not be locked. +NNG_DECL void nng_mtx_free(nng_mtx *); + +// nng_mtx_lock locks the mutex; if it is already locked it will block +// until it can be locked. If the caller already holds the lock, the +// results are undefined (a panic may occur). +NNG_DECL void nng_mtx_lock(nng_mtx *); + +// nng_mtx_unlock unlocks a previously locked mutex. It is an error to +// call this on a mutex which is not owned by caller. +NNG_DECL void nng_mtx_unlock(nng_mtx *); + +// nng_cv is a condition variable. It is always allocated with an +// associated mutex, which must be held when waiting for it, or +// when signaling it. +typedef struct nng_cv nng_cv; + +NNG_DECL int nng_cv_alloc(nng_cv **, nng_mtx *); + +// nng_cv_free frees the condition variable. +NNG_DECL void nng_cv_free(nng_cv *); + +// nng_cv_wait waits until the condition variable is "signaled". +NNG_DECL void nng_cv_wait(nng_cv *); + +// nng_cv_until waits until either the condition is signaled, or +// the timeout expires. It returns NNG_ETIMEDOUT in that case. +NNG_DECL int nng_cv_until(nng_cv *, nng_time); + +// nng_cv_wake wakes all threads waiting on the condition. +NNG_DECL void nng_cv_wake(nng_cv *); + +// nng_cv_wake1 wakes only one thread waiting on the condition. This may +// reduce the thundering herd problem, but care must be taken to ensure +// that no waiter starves forever. +NNG_DECL void nng_cv_wake1(nng_cv *); + +#ifdef __cplusplus +} +#endif + +#endif // NNG_NNG_H diff --git a/VNode/_software_lib/nanomq-0.22.10/include/nng/protocol/bus0/bus.h b/VNode/_software_lib/nanomq-0.22.10/include/nng/protocol/bus0/bus.h new file mode 100644 index 00000000..31167d75 --- /dev/null +++ b/VNode/_software_lib/nanomq-0.22.10/include/nng/protocol/bus0/bus.h @@ -0,0 +1,39 @@ +// +// Copyright 2021 Staysail Systems, Inc. +// Copyright 2018 Capitar IT Group BV +// +// This software is supplied under the terms of the MIT License, a +// copy of which should be located in the distribution where this +// file was obtained (LICENSE.txt). A copy of the license may also be +// found online at https://opensource.org/licenses/MIT. +// + +#ifndef NNG_PROTOCOL_BUS0_BUS_H +#define NNG_PROTOCOL_BUS0_BUS_H + +#ifdef __cplusplus +extern "C" { +#endif + +NNG_DECL int nng_bus0_open(nng_socket *); + +NNG_DECL int nng_bus0_open_raw(nng_socket *); + +#ifndef nng_bus_open +#define nng_bus_open nng_bus0_open +#endif + +#ifndef nng_bus_open_raw +#define nng_bus_open_raw nng_bus0_open_raw +#endif + +#define NNG_BUS0_SELF 0x70 +#define NNG_BUS0_PEER 0x70 +#define NNG_BUS0_SELF_NAME "bus" +#define NNG_BUS0_PEER_NAME "bus" + +#ifdef __cplusplus +} +#endif + +#endif // NNG_PROTOCOL_BUS0_BUS_H diff --git a/VNode/_software_lib/nanomq-0.22.10/include/nng/protocol/mqtt/mqtt.h b/VNode/_software_lib/nanomq-0.22.10/include/nng/protocol/mqtt/mqtt.h new file mode 100644 index 00000000..e25b2e3c --- /dev/null +++ b/VNode/_software_lib/nanomq-0.22.10/include/nng/protocol/mqtt/mqtt.h @@ -0,0 +1,112 @@ +// +// Copyright 2022 NanoMQ Team, Inc. +// +// This software is supplied under the terms of the MIT License, a +// copy of which should be located in the distribution where this +// file was obtained (LICENSE.txt). A copy of the license may also be +// found online at https://opensource.org/licenses/MIT. +// + +#ifndef MQTT_PROTOCOL_H +#define MQTT_PROTOCOL_H + +#define MQTT_PROTOCOL_NAME_v31 "MQIsdp" +#define MQTT_PROTOCOL_VERSION_v31 3 +#define MQTT_PROTOCOL_NAME "MQTT" +#define MQTT_PROTOCOL_VERSION_v311 4 +#define MQTT_PROTOCOL_VERSION_v5 5 + +/* NNG OPTs */ +#define NANO_CONF "nano:conf" + + +/* Length defination */ +// Maximum Packet Size of broker +#define NANO_MAX_RECV_PACKET_SIZE (2*1024*1024) +#define NANO_MIN_PACKET_LEN sizeof(uint8_t) * 8 +#define NANO_CONNECT_PACKET_LEN sizeof(uint8_t) * 12 +#define NANO_MIN_FIXED_HEADER_LEN sizeof(uint8_t) * 2 +//flow control:how many QoS packet broker willing to process at same time. +#define NANO_MAX_QOS_PACKET 1024 + +#ifdef NANO_PACKET_SIZE +#define NNI_NANO_MAX_PACKET_SIZE sizeof(uint8_t) * NANO_PACKET_SIZE +#else +#define NNI_NANO_MAX_PACKET_SIZE sizeof(uint8_t) * 16 +#endif + +/* Error values */ +enum err_t { + ERR_AUTH_CONTINUE = -4, + ERR_NO_SUBSCRIBERS = -3, + ERR_SUB_EXISTS = -2, + ERR_CONN_PENDING = -1, + ERR_SUCCESS = 0, + ERR_NOMEM = 1, + ERR_PROTOCOL = 2, + ERR_INVAL = 3, + ERR_NO_CONN = 4, + ERR_CONN_REFUSED = 5, + ERR_NOT_FOUND = 6, + ERR_CONN_LOST = 7, + ERR_TLS = 8, + ERR_PAYLOAD_SIZE = 9, + ERR_NOT_SUPPORTED = 10, + ERR_AUTH = 11, + ERR_ACL_DENIED = 12, + ERR_UNKNOWN = 13, + ERR_ERRNO = 14, + ERR_EAI = 15, + ERR_PROXY = 16, + ERR_PLUGIN_DEFER = 17, + ERR_MALFORMED_UTF8 = 18, + ERR_KEEPALIVE = 19, + ERR_LOOKUP = 20, + ERR_MALFORMED_PACKET = 21, + ERR_DUPLICATE_PROPERTY = 22, + ERR_TLS_HANDSHAKE = 23, + ERR_QOS_NOT_SUPPORTED = 24, + ERR_OVERSIZE_PACKET = 25, + ERR_OCSP = 26, +}; + +// mqtt5 macro +#define NMQ_RECEIVE_MAXIMUM_EXCEEDED 0X93 +#define NMQ_PACKET_TOO_LARGE 0x95 +#define NMQ_UNSEPECIFY_ERROR 0X80 +#define NMQ_SERVER_UNAVAILABLE 0x88 +#define NMQ_SERVER_BUSY 0x89 +#define NMQ_SERVER_SHUTTING_DOWN 0x8B +#define NMQ_KEEP_ALIVE_TIMEOUT 0x8D +#define NMQ_AUTH_SUB_ERROR 0X87 + +// MQTT Control Packet types +typedef enum { + RESERVED = 0, + CONNECT = 1, + CONNACK = 2, + PUBLISH = 3, + PUBACK = 4, + PUBREC = 5, + PUBREL = 6, + PUBCOMP = 7, + SUBSCRIBE = 8, + SUBACK = 9, + UNSUBSCRIBE = 10, + UNSUBACK = 11, + PINGREQ = 12, + PINGRESP = 13, + DISCONNECT = 14, + AUTH = 15 +} mqtt_control_packet_types; + +//MQTTV5 +typedef enum { + // 0 : V4 1: V5 5: V4 to V5 4: V5 to V4 + MQTTV4 = 0, + MQTTV5 = 1, + MQTTV4_V5 = 2, + MQTTV5_V4 = 3, +} target_prover; + +#endif diff --git a/VNode/_software_lib/nanomq-0.22.10/include/nng/protocol/mqtt/mqtt_parser.h b/VNode/_software_lib/nanomq-0.22.10/include/nng/protocol/mqtt/mqtt_parser.h new file mode 100644 index 00000000..2a81f131 --- /dev/null +++ b/VNode/_software_lib/nanomq-0.22.10/include/nng/protocol/mqtt/mqtt_parser.h @@ -0,0 +1,152 @@ + +#ifndef NNG_MQTT_H +#define NNG_MQTT_H + +#include "nng/supplemental/nanolib/conf.h" +#include "nng/supplemental/nanolib/hash_table.h" +#include "nng/mqtt/packet.h" +#include "mqtt.h" +#include "nng/supplemental/util/platform.h" +#include "nng/nng.h" +#include + +#ifdef _WIN32 +#define PRIu64 "I64u" +#define PRIu64_FORMAT "%I64u" +#else +#include +#define PRIu64_FORMAT "%" PRIu64 +#endif + +// Do not change to %lu! just suppress the warning of the compiler! +#define DISCONNECT_MSG \ + "{\"username\":\"%s\"," \ + "\"ts\":" PRIu64_FORMAT ",\"reason_code\":\"%x\",\"client_id\":\"%s\",\"IPv4\":\"%s\"}" + +#define CONNECT_MSG \ + "{\"username\":\"%s\", " \ + "\"ts\":" PRIu64_FORMAT ",\"proto_name\":\"%s\",\"keepalive\":%d,\"return_code\":" \ + "\"%x\",\"proto_ver\":%d,\"client_id\":\"%s\",\"clean_start\":%d, \"IPv4\":\"%s\"}" + +#define DISCONNECT_TOPIC "$SYS/brokers/disconnected" + +#define CONNECT_TOPIC "$SYS/brokers/connected" + +//Strip off and return the QoS bits +#define NANO_NNI_LMQ_GET_QOS_BITS(msg) ((size_t) (msg) &0x03) + +// strip off and return the msg pointer +#define NANO_NNI_LMQ_GET_MSG_POINTER(msg) \ + ((nng_msg *) ((size_t) (msg) & (~0x03))) + +// packed QoS bits to the least two significant bits of msg pointer +#define NANO_NNI_LMQ_PACKED_MSG_QOS(msg, qos) \ + ((nng_msg *) ((size_t) (msg) | ((qos) &0x03))) + +// Variables & Structs +typedef struct pub_extra pub_extra; + +// int hex_to_oct(char *str); +// uint32_t htoi(char *str); + +NNG_DECL pub_extra *pub_extra_alloc(pub_extra *); +NNG_DECL void pub_extra_free(pub_extra *); +NNG_DECL uint8_t pub_extra_get_qos(pub_extra *); +NNG_DECL uint16_t pub_extra_get_packet_id(pub_extra *); +NNG_DECL void pub_extra_set_qos(pub_extra *, uint8_t); +NNG_DECL void *pub_extra_get_msg(pub_extra *); +NNG_DECL void pub_extra_set_msg(pub_extra *, void *); +NNG_DECL void pub_extra_set_packet_id(pub_extra *, uint16_t); + +// MQTT CONNECT +NNG_DECL int32_t conn_handler(uint8_t *packet, conn_param *conn_param, size_t max); +NNG_DECL int conn_param_alloc(conn_param **cparam); +NNG_DECL void conn_param_free(conn_param *cparam); +NNG_DECL void conn_param_clone(conn_param *cparam); +NNG_DECL int ws_msg_adaptor(uint8_t *packet, nng_msg *dst); + +// parser +NNG_DECL uint8_t put_var_integer(uint8_t *dest, uint32_t value); + +NNG_DECL uint32_t get_var_integer(const uint8_t *buf, uint8_t *pos); + +NNG_DECL int32_t get_utf8_str( + char **dest, const uint8_t *src, uint32_t *pos, size_t max); +NNG_DECL uint8_t *copy_utf8_str( + const uint8_t *src, uint32_t *pos, int *str_len); +NNG_DECL uint8_t *copyn_utf8_str( + const uint8_t *src, uint32_t *pos, int *str_len, int limit); + +// NNG_DECL char *convert_to_utf8(char *src, char *format, size_t *len); +NNG_DECL uint8_t *copyn_str( + const uint8_t *src, uint32_t *pos, int *str_len, int limit); + +NNG_DECL int utf8_check(const char *str, size_t length); + +NNG_DECL uint16_t get_variable_binary(uint8_t **dest, const uint8_t *src); + +NNG_DECL uint32_t DJBHash(char *str); +NNG_DECL uint32_t DJBHashn(char *str, uint16_t len); +NNG_DECL uint64_t DJBHash64(char *str); +NNG_DECL uint64_t DJBHash64n(uint8_t* str, uint32_t len); +NNG_DECL uint32_t fnv1a_hashn(char *str, size_t n); +NNG_DECL uint8_t crc_hashn(char *str, size_t n); +NNG_DECL uint32_t crc32_hashn(char *str, size_t n); +NNG_DECL uint32_t crc32c_hashn(char *str, size_t n); +NNG_DECL uint8_t verify_connect(conn_param *cparam, conf *conf); + +// repack +NNG_DECL void nano_msg_set_dup(nng_msg *msg); +NNG_DECL nng_msg *nano_pubmsg_composer(nng_msg **, uint8_t retain, uint8_t qos, + mqtt_string *payload, mqtt_string *topic, uint8_t proto_ver, + nng_time time); +NNG_DECL nng_msg *nano_dismsg_composer( + reason_code code, char *rstr, uint8_t *ref, property *prop); +NNG_DECL nng_msg *nano_msg_notify_disconnect(conn_param *cparam, uint8_t code); +NNG_DECL nng_msg *nano_msg_notify_connect(conn_param *cparam, uint8_t code); +NNG_DECL nano_pipe_db *nano_msg_get_subtopic( + nng_msg *msg, nano_pipe_db *root, conn_param *cparam); +NNG_DECL void nano_msg_free_pipedb(nano_pipe_db *db); +NNG_DECL void nano_msg_ubsub_free(nano_pipe_db *db); +NNG_DECL void nmq_connack_encode( + nng_msg *msg, conn_param *cparam, uint8_t reason); +NNG_DECL void nmq_connack_session(nng_msg *msg, bool session); +// TODO : check duplicated declaration +NNG_DECL reason_code check_properties(property *prop, nng_msg *msg); +NNG_DECL property *decode_buf_properties(uint8_t *packet, uint32_t packet_len, + uint32_t *pos, uint32_t *len, bool copy_value); +NNG_DECL property *decode_properties( + nng_msg *msg, uint32_t *pos, uint32_t *len, bool copy_value); +NNG_DECL int encode_properties(nng_msg *msg, property *prop, uint8_t cmd); +NNG_DECL int property_free(property *prop); +NNG_DECL property_data *property_get_value(property *prop, uint8_t prop_id); +NNG_DECL void property_foreach(property *prop, void (*cb)(property *)); +NNG_DECL int property_dup(property **dup, const property *src); +NNG_DECL property *property_pub_by_will(property *will_prop); + +NNG_DECL property *property_alloc(void); +NNG_DECL property_type_enum property_get_value_type(uint8_t prop_id); +NNG_DECL property *property_set_value_u8(uint8_t prop_id, uint8_t value); +NNG_DECL property *property_set_value_u16(uint8_t prop_id, uint16_t value); +NNG_DECL property *property_set_value_u32(uint8_t prop_id, uint32_t value); +NNG_DECL property *property_set_value_varint(uint8_t prop_id, uint32_t value); +NNG_DECL property *property_set_value_binary( + uint8_t prop_id, uint8_t *value, uint32_t len, bool copy_value); +NNG_DECL property *property_set_value_str( + uint8_t prop_id, const char *value, uint32_t len, bool copy_value); +NNG_DECL property *property_set_value_strpair(uint8_t prop_id, const char *key, + uint32_t key_len, const char *value, uint32_t value_len, bool copy_value); +NNG_DECL void property_append(property *prop_list, property *last); + +NNG_DECL int nmq_subtopic_decode(nng_msg *msg, uint8_t ver, topic_queue **ptq); +NNG_DECL int nmq_subinfo_decode(nng_msg *msg, void *l, uint8_t ver); +NNG_DECL int nmq_unsubinfo_decode(nng_msg *msg, void *l, uint8_t ver); +NNG_DECL bool topic_filter(const char *origin, const char *input); +NNG_DECL bool topic_filtern(const char *origin, const char *input, size_t n); + +NNG_DECL int nmq_auth_http_connect(conn_param *cparam, conf_auth_http *conf); + +NNG_DECL int nmq_auth_http_sub_pub( + conn_param *cparam, bool is_sub, topic_queue *topics, conf_auth_http *conf); + +#endif // NNG_MQTT_H diff --git a/VNode/_software_lib/nanomq-0.22.10/include/nng/protocol/mqtt/nmq_mqtt.h b/VNode/_software_lib/nanomq-0.22.10/include/nng/protocol/mqtt/nmq_mqtt.h new file mode 100644 index 00000000..f1f62bb7 --- /dev/null +++ b/VNode/_software_lib/nanomq-0.22.10/include/nng/protocol/mqtt/nmq_mqtt.h @@ -0,0 +1,35 @@ +// +// Copyright 2020 NanoMQ Team, Inc. +// +// This software is supplied under the terms of the MIT License, a +// copy of which should be located in the distribution where this +// file was obtained (LICENSE.txt). A copy of the license may also be +// found online at https://opensource.org/licenses/MIT. +// + +#ifndef NNG_PROTOCOL_MQTT_BROKER_H +#define NNG_PROTOCOL_MQTT_BROKER_H + +#ifdef __cplusplus +extern "C" { +#endif + +NNG_DECL int nng_nmq_tcp0_open(nng_socket *); + +#ifndef nng_nmq_tcp_open +#define nng_nmq_tcp_open nng_nmq_tcp0_open +#endif + +#define NNG_NMQ_TCP_SELF 0x31 +#define NNG_NMQ_TCP_PEER 0x30 +#define NNG_NMQ_TCP_SELF_NAME "nmq_broker" +#define NNG_NMQ_TCP_PEER_NAME "nmq_client" + +#define NMQ_OPT_MQTT_PIPES "mqtt-clients-pipes" +#define NMQ_OPT_MQTT_QOS_DB "mqtt-clients-qos-db" + +#ifdef __cplusplus +} +#endif + +#endif // NNG_PROTOCOL_MQTT_BROKER_H diff --git a/VNode/_software_lib/nanomq-0.22.10/include/nng/protocol/pair0/pair.h b/VNode/_software_lib/nanomq-0.22.10/include/nng/protocol/pair0/pair.h new file mode 100644 index 00000000..1356f1cd --- /dev/null +++ b/VNode/_software_lib/nanomq-0.22.10/include/nng/protocol/pair0/pair.h @@ -0,0 +1,34 @@ +// +// Copyright 2018 Staysail Systems, Inc. +// Copyright 2018 Capitar IT Group BV +// +// This software is supplied under the terms of the MIT License, a +// copy of which should be located in the distribution where this +// file was obtained (LICENSE.txt). A copy of the license may also be +// found online at https://opensource.org/licenses/MIT. +// + +#ifndef NNG_PROTOCOL_PAIR0_PAIR_H +#define NNG_PROTOCOL_PAIR0_PAIR_H + +#ifdef __cplusplus +extern "C" { +#endif + +NNG_DECL int nng_pair0_open(nng_socket *); + +NNG_DECL int nng_pair0_open_raw(nng_socket *); + +#ifndef nng_pair_open +#define nng_pair_open nng_pair0_open +#endif + +#ifndef nng_pair_open_raw +#define nng_pair_open_raw nng_pair0_open_raw +#endif + +#ifdef __cplusplus +} +#endif + +#endif // NNG_PROTOCOL_PAIR0_PAIR_H diff --git a/VNode/_software_lib/nanomq-0.22.10/include/nng/protocol/pair1/pair.h b/VNode/_software_lib/nanomq-0.22.10/include/nng/protocol/pair1/pair.h new file mode 100644 index 00000000..c48b2021 --- /dev/null +++ b/VNode/_software_lib/nanomq-0.22.10/include/nng/protocol/pair1/pair.h @@ -0,0 +1,40 @@ +// +// Copyright 2020 Staysail Systems, Inc. +// Copyright 2018 Capitar IT Group BV +// +// This software is supplied under the terms of the MIT License, a +// copy of which should be located in the distribution where this +// file was obtained (LICENSE.txt). A copy of the license may also be +// found online at https://opensource.org/licenses/MIT. +// + +#ifndef NNG_PROTOCOL_PAIR1_PAIR_H +#define NNG_PROTOCOL_PAIR1_PAIR_H + +#ifdef __cplusplus +extern "C" { +#endif + +NNG_DECL int nng_pair1_open(nng_socket *); +NNG_DECL int nng_pair1_open_raw(nng_socket *); +NNG_DECL int nng_pair1_open_poly(nng_socket *); + +#ifndef nng_pair_open +#define nng_pair_open nng_pair1_open +#endif + +#ifndef nng_pair_open_raw +#define nng_pair_open_raw nng_pair1_open_raw +#endif + +#define NNG_OPT_PAIR1_POLY "pair1:polyamorous" +#define NNG_PAIR1_SELF 0x11 +#define NNG_PAIR1_PEER 0x11 +#define NNG_PAIR1_SELF_NAME "pair1" +#define NNG_PAIR1_PEER_NAME "pair1" + +#ifdef __cplusplus +} +#endif + +#endif // NNG_PROTOCOL_PAIR1_PAIR_H diff --git a/VNode/_software_lib/nanomq-0.22.10/include/nng/protocol/pipeline0/pull.h b/VNode/_software_lib/nanomq-0.22.10/include/nng/protocol/pipeline0/pull.h new file mode 100644 index 00000000..1c5d63e3 --- /dev/null +++ b/VNode/_software_lib/nanomq-0.22.10/include/nng/protocol/pipeline0/pull.h @@ -0,0 +1,33 @@ +// +// Copyright 2018 Staysail Systems, Inc. +// Copyright 2018 Capitar IT Group BV +// +// This software is supplied under the terms of the MIT License, a +// copy of which should be located in the distribution where this +// file was obtained (LICENSE.txt). A copy of the license may also be +// found online at https://opensource.org/licenses/MIT. +// + +#ifndef NNG_PROTOCOL_PIPELINE0_PULL_H +#define NNG_PROTOCOL_PIPELINE0_PULL_H + +#ifdef __cplusplus +extern "C" { +#endif + +NNG_DECL int nng_pull0_open(nng_socket *); +NNG_DECL int nng_pull0_open_raw(nng_socket *); + +#ifndef nng_pull_open +#define nng_pull_open nng_pull0_open +#endif + +#ifndef nng_pull_open_raw +#define nng_pull_open_raw nng_pull0_open_raw +#endif + +#ifdef __cplusplus +} +#endif + +#endif // NNG_PROTOCOL_PIPELINE0_PULL_H diff --git a/VNode/_software_lib/nanomq-0.22.10/include/nng/protocol/pipeline0/push.h b/VNode/_software_lib/nanomq-0.22.10/include/nng/protocol/pipeline0/push.h new file mode 100644 index 00000000..a1384e0a --- /dev/null +++ b/VNode/_software_lib/nanomq-0.22.10/include/nng/protocol/pipeline0/push.h @@ -0,0 +1,33 @@ +// +// Copyright 2018 Staysail Systems, Inc. +// Copyright 2018 Capitar IT Group BV +// +// This software is supplied under the terms of the MIT License, a +// copy of which should be located in the distribution where this +// file was obtained (LICENSE.txt). A copy of the license may also be +// found online at https://opensource.org/licenses/MIT. +// + +#ifndef NNG_PROTOCOL_PIPELINE0_PUSH_H +#define NNG_PROTOCOL_PIPELINE0_PUSH_H + +#ifdef __cplusplus +extern "C" { +#endif + +NNG_DECL int nng_push0_open(nng_socket *); +NNG_DECL int nng_push0_open_raw(nng_socket *); + +#ifndef nng_push_open +#define nng_push_open nng_push0_open +#endif + +#ifndef nng_push_open_raw +#define nng_push_open_raw nng_push0_open_raw +#endif + +#ifdef __cplusplus +} +#endif + +#endif // NNG_PROTOCOL_PIPELINE0_PUSH_H diff --git a/VNode/_software_lib/nanomq-0.22.10/include/nng/protocol/pubsub0/pub.h b/VNode/_software_lib/nanomq-0.22.10/include/nng/protocol/pubsub0/pub.h new file mode 100644 index 00000000..877f2f1c --- /dev/null +++ b/VNode/_software_lib/nanomq-0.22.10/include/nng/protocol/pubsub0/pub.h @@ -0,0 +1,33 @@ +// +// Copyright 2018 Staysail Systems, Inc. +// Copyright 2018 Capitar IT Group BV +// +// This software is supplied under the terms of the MIT License, a +// copy of which should be located in the distribution where this +// file was obtained (LICENSE.txt). A copy of the license may also be +// found online at https://opensource.org/licenses/MIT. +// + +#ifndef NNG_PROTOCOL_PUBSUB0_PUB_H +#define NNG_PROTOCOL_PUBSUB0_PUB_H + +#ifdef __cplusplus +extern "C" { +#endif + +NNG_DECL int nng_pub0_open(nng_socket *); +NNG_DECL int nng_pub0_open_raw(nng_socket *); + +#ifndef nng_pub_open +#define nng_pub_open nng_pub0_open +#endif + +#ifndef nng_pub_open_raw +#define nng_pub_open_raw nng_pub0_open_raw +#endif + +#ifdef __cplusplus +} +#endif + +#endif // NNG_PROTOCOL_PUBSUB0_PUB_H diff --git a/VNode/_software_lib/nanomq-0.22.10/include/nng/protocol/pubsub0/sub.h b/VNode/_software_lib/nanomq-0.22.10/include/nng/protocol/pubsub0/sub.h new file mode 100644 index 00000000..81f50a80 --- /dev/null +++ b/VNode/_software_lib/nanomq-0.22.10/include/nng/protocol/pubsub0/sub.h @@ -0,0 +1,39 @@ +// +// Copyright 2018 Staysail Systems, Inc. +// Copyright 2018 Capitar IT Group BV +// +// This software is supplied under the terms of the MIT License, a +// copy of which should be located in the distribution where this +// file was obtained (LICENSE.txt). A copy of the license may also be +// found online at https://opensource.org/licenses/MIT. +// + +#ifndef NNG_PROTOCOL_PUBSUB0_SUB_H +#define NNG_PROTOCOL_PUBSUB0_SUB_H + +#ifdef __cplusplus +extern "C" { +#endif + +NNG_DECL int nng_sub0_open(nng_socket *); + +NNG_DECL int nng_sub0_open_raw(nng_socket *); + +#ifndef nng_sub_open +#define nng_sub_open nng_sub0_open +#endif + +#ifndef nng_sub_open_raw +#define nng_sub_open_raw nng_sub0_open_raw +#endif + +#define NNG_OPT_SUB_SUBSCRIBE "sub:subscribe" +#define NNG_OPT_SUB_UNSUBSCRIBE "sub:unsubscribe" + +#define NNG_OPT_SUB_PREFNEW "sub:prefnew" + +#ifdef __cplusplus +} +#endif + +#endif // NNG_PROTOCOL_PUBSUB0_SUB_H diff --git a/VNode/_software_lib/nanomq-0.22.10/include/nng/protocol/reqrep0/rep.h b/VNode/_software_lib/nanomq-0.22.10/include/nng/protocol/reqrep0/rep.h new file mode 100644 index 00000000..04fe18bf --- /dev/null +++ b/VNode/_software_lib/nanomq-0.22.10/include/nng/protocol/reqrep0/rep.h @@ -0,0 +1,38 @@ +// +// Copyright 2020 Staysail Systems, Inc. +// Copyright 2018 Capitar IT Group BV +// +// This software is supplied under the terms of the MIT License, a +// copy of which should be located in the distribution where this +// file was obtained (LICENSE.txt). A copy of the license may also be +// found online at https://opensource.org/licenses/MIT. +// + +#ifndef NNG_PROTOCOL_REQREP0_REP_H +#define NNG_PROTOCOL_REQREP0_REP_H + +#ifdef __cplusplus +extern "C" { +#endif + +NNG_DECL int nng_rep0_open(nng_socket *); +NNG_DECL int nng_rep0_open_raw(nng_socket *); + +#ifndef nng_rep_open +#define nng_rep_open nng_rep0_open +#endif + +#ifndef nng_rep_open_raw +#define nng_rep_open_raw nng_rep0_open_raw +#endif + +#define NNG_REP0_SELF 0x31 +#define NNG_REP0_PEER 0x30 +#define NNG_REP0_SELF_NAME "rep" +#define NNG_REP0_PEER_NAME "req" + +#ifdef __cplusplus +} +#endif + +#endif // NNG_PROTOCOL_REQREP0_REP_H diff --git a/VNode/_software_lib/nanomq-0.22.10/include/nng/protocol/reqrep0/req.h b/VNode/_software_lib/nanomq-0.22.10/include/nng/protocol/reqrep0/req.h new file mode 100644 index 00000000..0c9fde3f --- /dev/null +++ b/VNode/_software_lib/nanomq-0.22.10/include/nng/protocol/reqrep0/req.h @@ -0,0 +1,40 @@ +// +// Copyright 2020 Staysail Systems, Inc. +// Copyright 2018 Capitar IT Group BV +// +// This software is supplied under the terms of the MIT License, a +// copy of which should be located in the distribution where this +// file was obtained (LICENSE.txt). A copy of the license may also be +// found online at https://opensource.org/licenses/MIT. +// + +#ifndef NNG_PROTOCOL_REQREP0_REQ_H +#define NNG_PROTOCOL_REQREP0_REQ_H + +#ifdef __cplusplus +extern "C" { +#endif + +NNG_DECL int nng_req0_open(nng_socket *); +NNG_DECL int nng_req0_open_raw(nng_socket *); + +#ifndef nng_req_open +#define nng_req_open nng_req0_open +#endif +#ifndef nng_req_open_raw +#define nng_req_open_raw nng_req0_open_raw +#endif + +#define NNG_REQ0_SELF 0x30 +#define NNG_REQ0_PEER 0x31 +#define NNG_REQ0_SELF_NAME "req" +#define NNG_REQ0_PEER_NAME "rep" + +#define NNG_OPT_REQ_RESENDTIME "req:resend-time" +#define NNG_OPT_REQ_RESENDTICK "req:resend-tick" + +#ifdef __cplusplus +} +#endif + +#endif // NNG_PROTOCOL_REQREP0_REQ_H diff --git a/VNode/_software_lib/nanomq-0.22.10/include/nng/protocol/survey0/respond.h b/VNode/_software_lib/nanomq-0.22.10/include/nng/protocol/survey0/respond.h new file mode 100644 index 00000000..d7dab61d --- /dev/null +++ b/VNode/_software_lib/nanomq-0.22.10/include/nng/protocol/survey0/respond.h @@ -0,0 +1,38 @@ +// +// Copyright 2020 Staysail Systems, Inc. +// Copyright 2018 Capitar IT Group BV +// +// This software is supplied under the terms of the MIT License, a +// copy of which should be located in the distribution where this +// file was obtained (LICENSE.txt). A copy of the license may also be +// found online at https://opensource.org/licenses/MIT. +// + +#ifndef NNG_PROTOCOL_SURVEY0_RESPOND_H +#define NNG_PROTOCOL_SURVEY0_RESPOND_H + +#ifdef __cplusplus +extern "C" { +#endif + +NNG_DECL int nng_respondent0_open(nng_socket *); +NNG_DECL int nng_respondent0_open_raw(nng_socket *); + +#ifndef nng_respondent_open +#define nng_respondent_open nng_respondent0_open +#endif + +#ifndef nng_respondent_open_raw +#define nng_respondent_open_raw nng_respondent0_open_raw +#endif + +#define NNG_RESPONDENT0_SELF 0x63 +#define NNG_RESPONDENT0_PEER 0x62 +#define NNG_RESPONDENT0_SELF_NAME "respondent" +#define NNG_RESPONDENT0_PEER_NAME "surveyor" + +#ifdef __cplusplus +} +#endif + +#endif // NNG_PROTOCOL_SURVEY0_RESPOND_H diff --git a/VNode/_software_lib/nanomq-0.22.10/include/nng/protocol/survey0/survey.h b/VNode/_software_lib/nanomq-0.22.10/include/nng/protocol/survey0/survey.h new file mode 100644 index 00000000..cea4d58b --- /dev/null +++ b/VNode/_software_lib/nanomq-0.22.10/include/nng/protocol/survey0/survey.h @@ -0,0 +1,40 @@ +// +// Copyright 2020 Staysail Systems, Inc. +// Copyright 2018 Capitar IT Group BV +// +// This software is supplied under the terms of the MIT License, a +// copy of which should be located in the distribution where this +// file was obtained (LICENSE.txt). A copy of the license may also be +// found online at https://opensource.org/licenses/MIT. +// + +#ifndef NNG_PROTOCOL_SURVEY0_SURVEY_H +#define NNG_PROTOCOL_SURVEY0_SURVEY_H + +#ifdef __cplusplus +extern "C" { +#endif + +NNG_DECL int nng_surveyor0_open(nng_socket *); +NNG_DECL int nng_surveyor0_open_raw(nng_socket *); + +#ifndef nng_surveyor_open +#define nng_surveyor_open nng_surveyor0_open +#endif + +#ifndef nng_surveyor_open_raw +#define nng_surveyor_open_raw nng_surveyor0_open_raw +#endif + +#define NNG_SURVEYOR0_SELF 0x62 +#define NNG_SURVEYOR0_PEER 0x63 +#define NNG_SURVEYOR0_SELF_NAME "surveyor" +#define NNG_SURVEYOR0_PEER_NAME "respondent" + +#define NNG_OPT_SURVEYOR_SURVEYTIME "surveyor:survey-time" + +#ifdef __cplusplus +} +#endif + +#endif // NNG_PROTOCOL_SURVEY0_SURVEY_H diff --git a/VNode/_software_lib/nanomq-0.22.10/include/nng/supplemental/http/http.h b/VNode/_software_lib/nanomq-0.22.10/include/nng/supplemental/http/http.h new file mode 100644 index 00000000..ff8616ca --- /dev/null +++ b/VNode/_software_lib/nanomq-0.22.10/include/nng/supplemental/http/http.h @@ -0,0 +1,539 @@ +// +// Copyright 2020 Staysail Systems, Inc. +// Copyright 2018 Capitar IT Group BV +// Copyright 2020 Dirac Research +// +// This software is supplied under the terms of the MIT License, a +// copy of which should be located in the distribution where this +// file was obtained (LICENSE.txt). A copy of the license may also be +// found online at https://opensource.org/licenses/MIT. +// + +#ifndef NNG_SUPPLEMENTAL_HTTP_HTTP_H +#define NNG_SUPPLEMENTAL_HTTP_HTTP_H + +// HTTP API. Only present if HTTP support compiled into the library. +// Functions will return NNG_ENOTSUP (or NULL or 0 as appropriate) +// if the library lacks support for HTTP. + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +struct nng_tls_config; + +// HTTP status codes. This list is not exhaustive. +enum nng_http_status { + NNG_HTTP_STATUS_CONTINUE = 100, + NNG_HTTP_STATUS_SWITCHING = 101, + NNG_HTTP_STATUS_PROCESSING = 102, + NNG_HTTP_STATUS_OK = 200, + NNG_HTTP_STATUS_CREATED = 201, + NNG_HTTP_STATUS_ACCEPTED = 202, + NNG_HTTP_STATUS_NOT_AUTHORITATIVE = 203, + NNG_HTTP_STATUS_NO_CONTENT = 204, + NNG_HTTP_STATUS_RESET_CONTENT = 205, + NNG_HTTP_STATUS_PARTIAL_CONTENT = 206, + NNG_HTTP_STATUS_MULTI_STATUS = 207, + NNG_HTTP_STATUS_ALREADY_REPORTED = 208, + NNG_HTTP_STATUS_IM_USED = 226, + NNG_HTTP_STATUS_MULTIPLE_CHOICES = 300, + NNG_HTTP_STATUS_STATUS_MOVED_PERMANENTLY = 301, + NNG_HTTP_STATUS_FOUND = 302, + NNG_HTTP_STATUS_SEE_OTHER = 303, + NNG_HTTP_STATUS_NOT_MODIFIED = 304, + NNG_HTTP_STATUS_USE_PROXY = 305, + NNG_HTTP_STATUS_TEMPORARY_REDIRECT = 307, + NNG_HTTP_STATUS_PERMANENT_REDIRECT = 308, + NNG_HTTP_STATUS_BAD_REQUEST = 400, + NNG_HTTP_STATUS_UNAUTHORIZED = 401, + NNG_HTTP_STATUS_PAYMENT_REQUIRED = 402, + NNG_HTTP_STATUS_FORBIDDEN = 403, + NNG_HTTP_STATUS_NOT_FOUND = 404, + NNG_HTTP_STATUS_METHOD_NOT_ALLOWED = 405, + NNG_HTTP_STATUS_NOT_ACCEPTABLE = 406, + NNG_HTTP_STATUS_PROXY_AUTH_REQUIRED = 407, + NNG_HTTP_STATUS_REQUEST_TIMEOUT = 408, + NNG_HTTP_STATUS_CONFLICT = 409, + NNG_HTTP_STATUS_GONE = 410, + NNG_HTTP_STATUS_LENGTH_REQUIRED = 411, + NNG_HTTP_STATUS_PRECONDITION_FAILED = 412, + NNG_HTTP_STATUS_PAYLOAD_TOO_LARGE = 413, + NNG_HTTP_STATUS_ENTITY_TOO_LONG = 414, + NNG_HTTP_STATUS_UNSUPPORTED_MEDIA_TYPE = 415, + NNG_HTTP_STATUS_RANGE_NOT_SATISFIABLE = 416, + NNG_HTTP_STATUS_EXPECTATION_FAILED = 417, + NNG_HTTP_STATUS_TEAPOT = 418, + NNG_HTTP_STATUS_UNPROCESSABLE_ENTITY = 422, + NNG_HTTP_STATUS_LOCKED = 423, + NNG_HTTP_STATUS_FAILED_DEPENDENCY = 424, + NNG_HTTP_STATUS_UPGRADE_REQUIRED = 426, + NNG_HTTP_STATUS_PRECONDITION_REQUIRED = 428, + NNG_HTTP_STATUS_TOO_MANY_REQUESTS = 429, + NNG_HTTP_STATUS_HEADERS_TOO_LARGE = 431, + NNG_HTTP_STATUS_UNAVAIL_LEGAL_REASONS = 451, + NNG_HTTP_STATUS_INTERNAL_SERVER_ERROR = 500, + NNG_HTTP_STATUS_NOT_IMPLEMENTED = 501, + NNG_HTTP_STATUS_BAD_GATEWAY = 502, + NNG_HTTP_STATUS_SERVICE_UNAVAILABLE = 503, + NNG_HTTP_STATUS_GATEWAY_TIMEOUT = 504, + NNG_HTTP_STATUS_HTTP_VERSION_NOT_SUPP = 505, + NNG_HTTP_STATUS_VARIANT_ALSO_NEGOTIATES = 506, + NNG_HTTP_STATUS_INSUFFICIENT_STORAGE = 507, + NNG_HTTP_STATUS_LOOP_DETECTED = 508, + NNG_HTTP_STATUS_NOT_EXTENDED = 510, + NNG_HTTP_STATUS_NETWORK_AUTH_REQUIRED = 511, +}; + +// nng_http_req represents an HTTP request. +typedef struct nng_http_req nng_http_req; + +// nng_http_req_alloc creates a vanilla HTTP request object. The object is +// initialized with the given URL object for an HTTP/1.1 GET request by +// default. It also adds the Host: header required for HTTP/1.1. If the +// url is NULL, then the uri and Host: header are uninitialized, and will +// need to be set explicitly. +NNG_DECL int nng_http_req_alloc(nng_http_req **, const nng_url *); + +// nng_http_req_free frees an HTTP request object. +NNG_DECL void nng_http_req_free(nng_http_req *); + +// nng_http_req_get_method returns the method. +NNG_DECL const char *nng_http_req_get_method(nng_http_req *); + +// nng_http_req_get_version returns the version, usually HTTP/1.1. +NNG_DECL const char *nng_http_req_get_version(nng_http_req *); + +// nng_http_req_get_uri returns the "abs-uri", which is URL without +// the scheme, host, or port. +NNG_DECL const char *nng_http_req_get_uri(nng_http_req *); + +// nng_http_req_set_header sets an HTTP header, replacing any previous value +// that might have been present. +NNG_DECL int nng_http_req_set_header( + nng_http_req *, const char *, const char *); + +// nng_http_req_add_header adds an HTTP header, without disrupting any other +// with the same name that might have been present. +NNG_DECL int nng_http_req_add_header( + nng_http_req *, const char *, const char *); + +// nng_http_req_del_header deletes all occurrences of a named header. +NNG_DECL int nng_http_req_del_header(nng_http_req *, const char *); + +// nng_http_req_get_header looks up a header with the named, returns NULL +// if not found. +NNG_DECL const char *nng_http_req_get_header(nng_http_req *, const char *); + +// nng_http_req_set_method is used to change the method of a request. +// The method should be an upper case HTTP method, like POST, or DELETE. +// Null sets the default ("GET"). +NNG_DECL int nng_http_req_set_method(nng_http_req *, const char *); + +// nng_http_req_set_version is used to change the version of a request. +// Normally the version is "HTTP/1.1". Note that the framework does +// not support HTTP/2 at all. Null sets the default ("HTTP/1.1"). +NNG_DECL int nng_http_req_set_version(nng_http_req *, const char *); + +// nng_http_req_set_uri is used to change the URI of a request. This +// should be an "abs-uri", that is a path, plus query and fragment if +// needed. The scheme, host, and port don't belong here. The URI should +// start with a leading '/' per HTTP. +NNG_DECL int nng_http_req_set_uri(nng_http_req *, const char *); + +// nng_http_req_set_data adds entity data to the request. The +// data object must persist (so only really useful for static data). +// The content-length header is updated as well, but the caller should +// probably set the content-type header. +NNG_DECL int nng_http_req_set_data(nng_http_req *, const void *, size_t); + +// nng_http_req_copy_data adds entity data to the response. A private +// copy of the data is made (will be freed with the request). +// The content-length header is updated as well, but the caller should +// probably set the content-type header. +NNG_DECL int nng_http_req_copy_data(nng_http_req *, const void *, size_t); + +// nng_http_req_get_data gets the data for the response. +NNG_DECL void nng_http_req_get_data(nng_http_req *, void **, size_t *); + +// nng_http_res represents an HTTP response. +typedef struct nng_http_res nng_http_res; + +// nng_http_res_alloc creates a vanilla HTTP response object. The object is +// initialized for an HTTP/1.1 200 OK response by default. +NNG_DECL int nng_http_res_alloc(nng_http_res **); + +// nng_http_res_alloc_error creates an error HTTP response object. The object +// is initialized for an HTTP/1.1 response, and contains an associated +// generic HTML error page. +NNG_DECL int nng_http_res_alloc_error(nng_http_res **, uint16_t); + +// nng_http_res_free frees an HTTP response object. +NNG_DECL void nng_http_res_free(nng_http_res *); + +// nng_http_res_get_status returns the HTTP status code from the server. +NNG_DECL uint16_t nng_http_res_get_status(nng_http_res *); + +// nng_http_res_set_status sets the HTTP status code. +NNG_DECL int nng_http_res_set_status(nng_http_res *, uint16_t); + +// nng_http_res_get_reason returns the human readable status message +// that the server responds (or responded) with. +NNG_DECL const char *nng_http_res_get_reason(nng_http_res *); + +// nng_http_res_set_reason sets the human readable status message. +// NULL means that a default reason is used based on the status code. +NNG_DECL int nng_http_res_set_reason(nng_http_res *, const char *); + +// nng_http_res_set_header sets an HTTP header, replacing any previous value +// that might have been present. +NNG_DECL int nng_http_res_set_header( + nng_http_res *, const char *, const char *); + +// nng_http_res_add_header adds an HTTP header, without disrupting any other +// with the same name that might have been present. +NNG_DECL int nng_http_res_add_header( + nng_http_res *, const char *, const char *); + +// nng_http_res_del_header deletes all occurrences of a named header. +NNG_DECL int nng_http_res_del_header(nng_http_res *, const char *); + +// nng_http_res_get_header looks up a header with the named, returns NULL +// if not found. +NNG_DECL const char *nng_http_res_get_header(nng_http_res *, const char *); + +// nng_http_res_set_version is used to change the version of a response. +// Normally the version is "HTTP/1.1". Note that the framework does +// not support HTTP/2 at all. NULL sets the default ("HTTP/1.1"). +NNG_DECL int nng_http_res_set_version(nng_http_res *, const char *); + +// nng_http_res_get_version returns the version, usually HTTP/1.1. +NNG_DECL const char *nng_http_res_get_version(nng_http_res *); + +// nng_http_res_get_data gets the data for the response. +NNG_DECL void nng_http_res_get_data(nng_http_res *, void **, size_t *); + +// nng_http_res_set_data adds entity data to the response. The +// data object must persist (so only really useful for static data). +// The content-length header is updated as well, but the caller should +// probably set the content-type header. +NNG_DECL int nng_http_res_set_data(nng_http_res *, const void *, size_t); + +// nng_http_res_copy_data adds entity data to the response. A private +// copy of the data is made (will be freed with the request). +// The content-length header is updated as well, but the caller should +// probably set the content-type header. +NNG_DECL int nng_http_res_copy_data(nng_http_res *, const void *, size_t); + +// An nng_http_conn represents an underlying "connection". It may be +// a TCP channel, or a TLS channel, but the main thing is that this is +// normally only used for exchanging HTTP requests and responses. +typedef struct nng_http_conn nng_http_conn; + +// nng_http_conn_close closes the underlying channel. Applications should +// not use this channel after this operation is performed. +NNG_DECL void nng_http_conn_close(nng_http_conn *); + +// nng_http_conn_read attempts to read data from the connection. This +// completes as soon as at least one byte is read; it does not wait +// for the entire aio to be filled. +NNG_DECL void nng_http_conn_read(nng_http_conn *, nng_aio *); + +// nng_http_conn_read_all is like nng_http_conn_read, but it does not +// finish until either all the requested data is read, or an error occurs. +NNG_DECL void nng_http_conn_read_all(nng_http_conn *, nng_aio *); + +// nng_http_conn_write attempts to write data, but it can write less +// than the amount requested. (It completes as soon as at least one +// byte is written.) +NNG_DECL void nng_http_conn_write(nng_http_conn *, nng_aio *); + +// nng_http_conn_write_all is like nng_http_conn_write, but it does not +// finish until either all the requested data is written, or an error occurs. +NNG_DECL void nng_http_conn_write_all(nng_http_conn *, nng_aio *); + +// nng_http_conn_write_req writes the entire request. It will also write any +// data that has been attached. +NNG_DECL void nng_http_conn_write_req( + nng_http_conn *, nng_http_req *, nng_aio *); + +// nng_http_conn_write_res writes the entire response. It will also write any +// data that has been attached. +NNG_DECL void nng_http_conn_write_res( + nng_http_conn *, nng_http_res *, nng_aio *); + +// nng_http_conn_read_req reads an entire request, EXCEPT for any entity +// data. The caller is responsible for processing the headers in the request +// and reading any submitted entity data itself. +NNG_DECL void nng_http_conn_read_req( + nng_http_conn *, nng_http_req *, nng_aio *); + +// nng_http_conn_read_res reads an entire response, EXCEPT for any entity +// data. The caller is responsible for processing the headers in the response +// and reading any submitted entity data itself. +NNG_DECL void nng_http_conn_read_res( + nng_http_conn *, nng_http_res *, nng_aio *); + +// nng_http_req_reset resets the request to an initially allocated state. +NNG_DECL void nng_http_req_reset(nng_http_req *); + +// nng_http_res_reset resets the response to an initially allocated state. +NNG_DECL void nng_http_res_reset(nng_http_res *); + +// nng_http_handler is a handler used on the server side to handle HTTP +// requests coming into a specific URL. +typedef struct nng_http_handler nng_http_handler; + +// nng_http_handler_alloc creates a server handler object, for the supplied +// absolute URI (path only) with the callback. By default the handler +// is assumed to handle only GET requests (and implictly HEAD requests +// as well.) +// +// Note that methods which modify a handler cannot be called while the handler +// is registered with the server, and that a handler can only be registered +// once per server. +// +// The callback function will receive the following arguments (via +// nng_aio_get_input(): nng_http_request *, nng_http_handler *, and +// nng_http_conn *. The first is a request object, for convenience. +// The second is the handler, from which the callback can obtain any other +// data it has set. The final is the http connection, which can be used +// to hijack the session. +// +// Upon completion, the handler should store an nng_http_res * as the +// first output using nng_aio_set_output. If it does not do so, or supplies +// NULL, then it must send a response itself. +// +// The callback should complete with a result of 0 in most circumstances. +// If it completes with an error, then the connection is terminated, after +// possibly sending a 500 error response to the client. +NNG_DECL int nng_http_handler_alloc( + nng_http_handler **, const char *, void (*)(nng_aio *)); + +// nng_http_handler_free frees the handler. This actually just drops a +// reference count on the handler, as it may be in use by an existing +// server. The server will also call this when it is destroyed. +NNG_DECL void nng_http_handler_free(nng_http_handler *); + +// nng_http_handler_alloc_file creates a "file" based handler, that +// serves up static content from the given file path. The content-type +// supplied is determined from the file name using a simple built-in map. +NNG_DECL int nng_http_handler_alloc_file( + nng_http_handler **, const char *, const char *); + +// nng_http_handler_alloc_static creates a static-content handler. +// The last argument is the content-type, which may be NULL (in which case +// "application/octet-stream" is assumed.) +NNG_DECL int nng_http_handler_alloc_static( + nng_http_handler **, const char *, const void *, size_t, const char *); + +// nng_http_handler_alloc_redirect creates an HTTP redirect handler. +// The status is given, along with the new URL. If the status is 0, +// then 301 will be used instead. +NNG_DECL int nng_http_handler_alloc_redirect( + nng_http_handler **, const char *, uint16_t, const char *); + +// nng_http_handler_alloc_file creates a "directory" based handler, that +// serves up static content from the given directory tree. Directories +// that contain an index.html or index.htm file use that file for the +// directory content, otherwise a suitable error page is returned (the server +// does not generate index pages automatically.) The content-type for +// files is determined from the file name using a simple built-in map. +NNG_DECL int nng_http_handler_alloc_directory( + nng_http_handler **, const char *, const char *); + +// nng_http_handler_set_method sets the method that the handler will be +// called for. By default this is GET. If NULL is supplied for the +// method, then the handler is executed regardless of method, and must +// inspect the method itself. +NNG_DECL int nng_http_handler_set_method(nng_http_handler *, const char *); + +// nng_http_handler_set_host sets the Host: that the handler will be +// called for (to allow for virtual hosts). If the value is NULL (the +// default, then the Host: header is not considered when matching the +// handler.) Note that the Host: header must match *exactly* (except +// that case is not considered.) +NNG_DECL int nng_http_handler_set_host(nng_http_handler *, const char *); + +// nng_http_handler_collect_body is used to indicate the server should +// check for, and process, data sent by the client, which will be attached +// to the request. If this is false, then the handler will need to check +// for and process any content data. By default the server will accept +// up to 1MB. If the client attempts to send more data than requested, +// then a 400 Bad Request will be sent back to the client. To set an +// unlimited value, use (size_t)-1. To preclude the client from sending +// *any* data, use 0. (The static and file handlers use 0 by default.) +NNG_DECL int nng_http_handler_collect_body(nng_http_handler *, bool, size_t); + +// nng_http_handler_set_tree indicates that the handler is being registered +// for a hierarchical tree, rather than just a single path, so it will be +// called for all child paths supplied. By default the handler is only +// called for an exact path match. +NNG_DECL int nng_http_handler_set_tree(nng_http_handler *); + +// nng_http_handler_set_tree_exclusive indicates that the handler is being +// registered for a heirarchical tree *exclusively*, rather than just a single +// path, so it will be called for all child paths supplied. By default the +// handler is only called for an exact path match. Exclusive means that any +// other handler on a conflicting path will induce an address conflict error +// when added to a server. +NNG_DECL int nng_http_handler_set_tree_exclusive(nng_http_handler *); + +// nng_http_handler_set_data is used to store additional data, along with +// a possible clean up routine. (The clean up is a custom de-allocator and +// will be called with the supplied data as an argument, when the handler +// is being de-allocated.) +NNG_DECL int nng_http_handler_set_data( + nng_http_handler *, void *, void (*)(void *)); + +// nng_http_handler_get_data returns the data that was previously stored. +NNG_DECL void *nng_http_handler_get_data(nng_http_handler *); + +// nng_http_server is a handle to an HTTP server instance. Servers +// only serve a single port / address at this time. + +typedef struct nng_http_server nng_http_server; + +// nng_http_server_hold gets a server structure, using the address determined +// from the URL. If a server already exists, then a hold is placed on it, and +// that instance is returned. If no such server exists, then a new instance +// is created. +NNG_DECL int nng_http_server_hold(nng_http_server **, const nng_url *); + +// nng_http_server_release releases the hold on the server. If this is the +// last instance of the server, then it is shutdown and resources are freed. +NNG_DECL void nng_http_server_release(nng_http_server *); + +// nng_http_server_start starts the server handling HTTP. Once this is +// called, it will not be possible to change certain parameters (such as +// any TLS configuration). +NNG_DECL int nng_http_server_start(nng_http_server *); + +// nng_http_server_stop stops the server. No new client connections are +// accepted after this returns. Once a server is stopped fully, the +// instance will no longer be returned by nng_http_server_hold, as the +// server may not be reused. +NNG_DECL void nng_http_server_stop(nng_http_server *); + +// nng_http_server_add_handler registers a handler on the server. +// This function will return NNG_EADDRINUSE if a conflicting handler +// is already registered (i.e. a handler with the same value for Host, +// Method, and URL.) +NNG_DECL int nng_http_server_add_handler( + nng_http_server *, nng_http_handler *); + +// nni_http_del_handler removes the given handler. The caller is +// responsible for finalizing it afterwards. If the handler was not found +// (not registered), NNG_ENOENT is returned. In this case it is unsafe +// to make assumptions about the validity of the handler. +NNG_DECL int nng_http_server_del_handler( + nng_http_server *, nng_http_handler *); + +// nng_http_server_set_tls adds a TLS configuration to the server, +// and enables the use of it. This returns NNG_EBUSY if the server is +// already started. This wipes out the entire TLS configuration on the +// server client, so the caller must have configured it reasonably. +// This API is not recommended unless the caller needs complete control +// over the TLS configuration. +NNG_DECL int nng_http_server_set_tls( + nng_http_server *, struct nng_tls_config *); + +// nng_http_server_get_tls obtains the TLS configuration if one is present, +// or returns NNG_EINVAL. The TLS configuration is invalidated if the +// nng_http_server_set_tls function is called, so be careful. +NNG_DECL int nng_http_server_get_tls( + nng_http_server *, struct nng_tls_config **); + +// nng_http_server_get_addr obtains the address with which the server was +// initialized or returns NNG_EINVAL. Useful for instance when the port has +// been automatically assigned. +NNG_DECL int nng_http_server_get_addr(nng_http_server *, nng_sockaddr *); + +// nng_http_server_set_error_page sets a custom error page (HTML) content +// to be sent for the given error code. This is used when the error is +// generated internally by the framework, or when the application returns +// the response back to the server via the handler's aio, and the response +// was allocated with nng_http_res_alloc_error. If the response was not +// allocated this way, or the application writes the response itself instead +// of letting the server do so, then this setting will be ignored. +NNG_DECL int nng_http_server_set_error_page( + nng_http_server *, uint16_t, const char *); + +// nng_http_server_set_error_file works like nng_http_server_error_page, +// except that the content is loaded from the named file path. The contents +// are loaded at the time this function is called, so this function should be +// called anytime the contents of the named file have changed. +NNG_DECL int nng_http_server_set_error_file( + nng_http_server *, uint16_t, const char *); + +// nng_http_server_res_error takes replaces the body of the response with +// a custom error page previously set for the server, using the status +// of the response. The response must have the status set first using +// nng_http_res_set_status or implicitly via nng_http_res_alloc_error. +NNG_DECL int nng_http_server_res_error(nng_http_server *, nng_http_res *); + +// nng_http_hijack is intended to be called by a handler that wishes to +// take over the processing of the HTTP session -- usually to change protocols +// (such as in the case of websocket). The caller is responsible for the +// final disposal of the associated nng_http_conn. Also, this completely +// disassociates the http session from the server, so the server may be +// stopped or destroyed without affecting the hijacked session. Note also +// that the hijacker will need to issue any HTTP reply itself. Finally, +// when a session is hijacked, the caller is also responsible for disposing +// of the request structure. (Some hijackers may keep the request for +// further processing.) + +NNG_DECL int nng_http_hijack(nng_http_conn *); + +// nng_http_client represents a "client" object. Clients can be used +// to create HTTP connections. At present, connections are not cached +// or reused, but that could change in the future. +typedef struct nng_http_client nng_http_client; + +// nng_http_client_alloc allocates a client object, associated with +// the given URL. +NNG_DECL int nng_http_client_alloc(nng_http_client **, const nng_url *); + +// nng_http_client_free frees the client. Connections created by the +// the client are not necessarily closed. +NNG_DECL void nng_http_client_free(nng_http_client *); + +// nng_http_client_set_tls sets the TLS configuration. This wipes out +// the entire TLS configuration on the client, so the caller must have +// configured it reasonably. This API is not recommended unless the +// caller needs complete control over the TLS configuration. +NNG_DECL int nng_http_client_set_tls( + nng_http_client *, struct nng_tls_config *); + +// nng_http_client_get_tls obtains the TLS configuration if one is present, +// or returns NNG_EINVAL. The supplied TLS configuration object may +// be invalidated by any future calls to nni_http_client_set_tls. +NNG_DECL int nng_http_client_get_tls( + nng_http_client *, struct nng_tls_config **); + +// nng_http_client_connect establishes a new connection with the server +// named in the URL used when the client was created. Once the connection +// is established, the associated nng_http_conn object pointer is returned +// in the first (index 0) output for the aio. +NNG_DECL void nng_http_client_connect(nng_http_client *, nng_aio *); + +// nng_http_conn_transact is used to perform a round-trip exchange (i.e. a +// single HTTP transaction). It will not automatically close the connection, +// unless some kind of significant error occurs. The caller should close +// the connection if the aio does not complete successfully. +NNG_DECL void nng_http_conn_transact( + nng_http_conn *, nng_http_req *, nng_http_res *, nng_aio *); + +// nng_http_client_transact is used to execute a single transaction to a +// server. The connection is opened, and will be closed when the transaction is +// complete. +NNG_DECL void nng_http_client_transact( + nng_http_client *, nng_http_req *, nng_http_res *, nng_aio *); + +#ifdef __cplusplus +} +#endif + +#endif // NNG_H diff --git a/VNode/_software_lib/nanomq-0.22.10/include/nng/supplemental/nanolib/acl_conf.h b/VNode/_software_lib/nanomq-0.22.10/include/nng/supplemental/nanolib/acl_conf.h new file mode 100644 index 00000000..a67f0dff --- /dev/null +++ b/VNode/_software_lib/nanomq-0.22.10/include/nng/supplemental/nanolib/acl_conf.h @@ -0,0 +1,80 @@ +#ifndef NANOLIB_ACL_CONF_H +#define NANOLIB_ACL_CONF_H + +#include +#include "nng/nng.h" +#include "nng/supplemental/nanolib/cJSON.h" + +typedef enum { + ACL_ALLOW, + ACL_DENY, +} acl_permit; + +typedef enum { + ACL_USERNAME, + ACL_CLIENTID, + ACL_IPADDR, + ACL_AND, + ACL_OR, + ACL_NONE, +} acl_rule_type; + +typedef enum { + ACL_PUB, + ACL_SUB, + ACL_ALL, +} acl_action_type; + +typedef enum { + ACL_RULE_SINGLE_STRING, + ACL_RULE_STRING_ARRAY, + ACL_RULE_INT_ARRAY, + ACL_RULE_ALL, +} acl_value_type; + +typedef struct acl_rule_ct { + acl_value_type type; + size_t count; + union { + char * str; + char **str_array; + int * int_array; + } value; +} acl_rule_ct; + +typedef struct { + acl_rule_type rule_type; + acl_rule_ct rule_ct; +} acl_sub_rule; + +typedef struct { + size_t count; + acl_sub_rule **rules; +} acl_sub_rules_array; + +typedef struct acl_rule { + size_t id; + acl_permit permit; + acl_rule_type rule_type; + union { + acl_rule_ct ct; + acl_sub_rules_array array; + } rule_ct; + acl_action_type action; + size_t topic_count; + char ** topics; +} acl_rule; + +typedef struct { + bool enable; + size_t rule_count; + acl_rule **rules; +} conf_acl; + +extern void conf_acl_parse(conf_acl *acl, const char *path); +extern void conf_acl_init(conf_acl *acl); +extern void conf_acl_destroy(conf_acl *acl); +extern bool acl_parse_json_rule(cJSON *obj, size_t id, acl_rule **rule); +extern void print_acl_conf(conf_acl *acl); + +#endif /* NANOLIB_ACL_CONF_H */ diff --git a/VNode/_software_lib/nanomq-0.22.10/include/nng/supplemental/nanolib/base64.h b/VNode/_software_lib/nanomq-0.22.10/include/nng/supplemental/nanolib/base64.h new file mode 100644 index 00000000..81564638 --- /dev/null +++ b/VNode/_software_lib/nanomq-0.22.10/include/nng/supplemental/nanolib/base64.h @@ -0,0 +1,21 @@ +#ifndef BASE64_H +#define BASE64_H +#include "nng/nng.h" + +#define BASE64_ENCODE_OUT_SIZE(s) ((unsigned int)((((s) + 2) / 3) * 4 + 1)) +#define BASE64_DECODE_OUT_SIZE(s) ((unsigned int)(((s) / 4) * 3)) + +/* + * out is null-terminated encode string. + * return values is out length, exclusive terminating `\0' + */ +NNG_DECL unsigned int +base64_encode(const unsigned char *in, unsigned int inlen, char *out); + +/* + * return values is out length + */ +NNG_DECL unsigned int +base64_decode(const char *in, unsigned int inlen, unsigned char *out); + +#endif /* BASE64_H */ \ No newline at end of file diff --git a/VNode/_software_lib/nanomq-0.22.10/include/nng/supplemental/nanolib/binary_search.h b/VNode/_software_lib/nanomq-0.22.10/include/nng/supplemental/nanolib/binary_search.h new file mode 100644 index 00000000..10878767 --- /dev/null +++ b/VNode/_software_lib/nanomq-0.22.10/include/nng/supplemental/nanolib/binary_search.h @@ -0,0 +1,116 @@ +# ifndef BINARY_SEARCH_H +# define BINARY_SEARCH_H + +#include "cvector.h" +#include +#include + +/** + * @brief binary_search - vec is an dynamic array + * @param l - it is the left boundry of the vec + * @param index - index is the result we search + * @param e - e contain message we want to search + * @param cmp - cmp is a compare method + * @return true or false, if we find or not + */ +static inline bool +_binary_search( + void **vec, int l, size_t *index, void *e, int (*cmp)(void *x, void *y)) +{ + + int r = cvector_size(vec) - 1; + int m = 0; + + // if we do not find the element + // vec = [0, 1, 3, 4], e = 2 , + // m will be 2, index = 2 ok + // vec = [0, 1, 2, 4], e = 3 , + // m will be 2, index = 2 error, + // index = 2 + add(1) ok + int add = 0; + + // log_info("l: %d", l); + // log_info("r: %d", r); + + while ( l <= r) { + m = l + (r - l) / 2; + + // Check if x is present at mid + if (cmp(vec[m], e) == 0) { + *index = m; + return true; + } + // log_info("m: %d", m); + + // If x greater, ignore left half + if (cmp(vec[m], e) < 0) { + l = m + 1; + add = 1; + + // If x is smaller, ignore right half + } else { + r = m - 1; + add = 0; + } + } + // log_info("m: %d", m); + + // if we reach here, then element was + // not present + *index = m + add; + return false; +} + +static inline bool +_binary_search_uint32(uint32_t *vec, int l, size_t *index, uint32_t e, + int (*cmp)(uint32_t x, uint32_t y)) +{ + int r = cvector_size(vec) - 1; + int m = 0; + + // if we do not find the element + // vec = [0, 1, 3, 4], e = 2 , + // m will be 2, index = 2 ok + // vec = [0, 1, 2, 4], e = 3 , + // m will be 2, index = 2 error, + // index = 2 + add(1) ok + int add = 0; + + // log_info("l: %d", l); + // log_info("r: %d", r); + + while ( l <= r) { + m = l + (r - l) / 2; + + // Check if x is present at mid + if (cmp(vec[m], e) == 0) { + *index = m; + return true; + } + // log_info("m: %d", m); + + // If x greater, ignore left half + if (cmp(vec[m], e) < 0) { + l = m + 1; + add = 1; + + // If x is smaller, ignore right half + } else { + r = m - 1; + add = 0; + } + } + // log_info("m: %d", m); + + // if we reach here, then element was + // not present + *index = m + add; + return false; +} + +#define binary_search(vec, l, index, e, cmp) \ + _binary_search(vec, l, index, e, cmp) +#define binary_search_uint32(vec, l, index, e, cmp) \ + _binary_search_uint32(vec, l, index, e, cmp) + +#endif diff --git a/VNode/_software_lib/nanomq-0.22.10/include/nng/supplemental/nanolib/blf.h b/VNode/_software_lib/nanomq-0.22.10/include/nng/supplemental/nanolib/blf.h new file mode 100644 index 00000000..96dbbf38 --- /dev/null +++ b/VNode/_software_lib/nanomq-0.22.10/include/nng/supplemental/nanolib/blf.h @@ -0,0 +1,62 @@ +#ifndef BLF_H +#define BLF_H +#include "nng/nng.h" +#include "nng/supplemental/nanolib/conf.h" +#include + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct blf_object blf_object; +typedef void (*blf_cb)(blf_object *arg); + +typedef enum { + WRITE_TO_NORMAL1, + WRITE_TO_TEMP1, +} blf_write_type; + +typedef struct { + uint32_t start_idx; + uint32_t end_idx; + char *filename; +} blf_file_range; + +typedef struct { + blf_file_range **range; + int size; + int start; // file range start index +} blf_file_ranges; + +typedef struct { + uint8_t *data; + uint32_t size; +} blf_data_packet; + +struct blf_object { + uint64_t *keys; + uint8_t **darray; + uint32_t *dsize; + uint32_t size; + nng_aio *aio; + void *arg; + blf_file_ranges *ranges; + blf_write_type type; +}; + +blf_object *blf_object_alloc(uint64_t *keys, uint8_t **darray, uint32_t *dsize, + uint32_t size, nng_aio *aio, void *arg); +void blf_object_free(blf_object *elem); + +int blf_write_batch_async(blf_object *elem); +int blf_write_launcher(conf_blf *conf); + +const char *blf_find(uint64_t key); +const char **blf_find_span( + uint64_t start_key, uint64_t end_key, uint32_t *size); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/VNode/_software_lib/nanomq-0.22.10/include/nng/supplemental/nanolib/cJSON.h b/VNode/_software_lib/nanomq-0.22.10/include/nng/supplemental/nanolib/cJSON.h new file mode 100644 index 00000000..b32fba45 --- /dev/null +++ b/VNode/_software_lib/nanomq-0.22.10/include/nng/supplemental/nanolib/cJSON.h @@ -0,0 +1,294 @@ +/* + Copyright (c) 2009-2017 Dave Gamble and cJSON contributors + + 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 cJSON__h +#define cJSON__h + +#ifdef __cplusplus +extern "C" +{ +#endif + +#if !defined(__WINDOWS__) && (defined(WIN32) || defined(WIN64) || defined(_MSC_VER) || defined(_WIN32)) +#define __WINDOWS__ +#endif + +#ifdef __WINDOWS__ + +/* When compiling for windows, we specify a specific calling convention to avoid issues where we are being called from a project with a different default calling convention. For windows you have 3 define options: + +CJSON_HIDE_SYMBOLS - Define this in the case where you don't want to ever dllexport symbols +CJSON_EXPORT_SYMBOLS - Define this on library build when you want to dllexport symbols (default) +CJSON_IMPORT_SYMBOLS - Define this if you want to dllimport symbol + +For *nix builds that support visibility attribute, you can define similar behavior by + +setting default visibility to hidden by adding +-fvisibility=hidden (for gcc) +or +-xldscope=hidden (for sun cc) +to CFLAGS + +then using the CJSON_API_VISIBILITY flag to "export" the same symbols the way CJSON_EXPORT_SYMBOLS does + +*/ + +#define CJSON_CDECL __cdecl +#define CJSON_STDCALL __stdcall + +/* export symbols by default, this is necessary for copy pasting the C and header file */ +#if !defined(CJSON_HIDE_SYMBOLS) && !defined(CJSON_IMPORT_SYMBOLS) && !defined(CJSON_EXPORT_SYMBOLS) +#define CJSON_EXPORT_SYMBOLS +#endif + +#if defined(CJSON_HIDE_SYMBOLS) +#define CJSON_PUBLIC(type) type CJSON_STDCALL +#elif defined(CJSON_EXPORT_SYMBOLS) +#define CJSON_PUBLIC(type) __declspec(dllexport) type CJSON_STDCALL +#elif defined(CJSON_IMPORT_SYMBOLS) +#define CJSON_PUBLIC(type) __declspec(dllimport) type CJSON_STDCALL +#endif +#else /* !__WINDOWS__ */ +#define CJSON_CDECL +#define CJSON_STDCALL + + +#if defined(NNG_SHARED_LIB) && defined(NNG_HIDDEN_VISIBILITY) +#define CJSON_PUBLIC(type) __attribute__((visibility("default"))) type +#else +#define CJSON_PUBLIC(type) type +#endif +#endif + +/* project version */ +#define CJSON_VERSION_MAJOR 1 +#define CJSON_VERSION_MINOR 7 +#define CJSON_VERSION_PATCH 15 + +#include + +/* cJSON Types: */ +#define cJSON_Invalid (0) +#define cJSON_False (1 << 0) +#define cJSON_True (1 << 1) +#define cJSON_NULL (1 << 2) +#define cJSON_Number (1 << 3) +#define cJSON_String (1 << 4) +#define cJSON_Array (1 << 5) +#define cJSON_Object (1 << 6) +#define cJSON_Raw (1 << 7) /* raw json */ + +#define cJSON_IsReference 256 +#define cJSON_StringIsConst 512 + +/* The cJSON structure: */ +typedef struct cJSON +{ + /* next/prev allow you to walk array/object chains. Alternatively, use GetArraySize/GetArrayItem/GetObjectItem */ + struct cJSON *next; + struct cJSON *prev; + /* An array or object item will have a child pointer pointing to a chain of the items in the array/object. */ + struct cJSON *child; + + /* The type of the item, as above. */ + int type; + + /* The item's string, if type==cJSON_String and type == cJSON_Raw */ + char *valuestring; + /* writing to valueint is DEPRECATED, use cJSON_SetNumberValue instead */ + int valueint; + /* The item's number, if type==cJSON_Number */ + double valuedouble; + + /* The item's name string, if this item is the child of, or is in the list of subitems of an object. */ + char *string; +} cJSON; + +typedef struct cJSON_Hooks +{ + /* malloc/free are CDECL on Windows regardless of the default calling convention of the compiler, so ensure the hooks allow passing those functions directly. */ + void *(CJSON_CDECL *malloc_fn)(size_t sz); + void (CJSON_CDECL *free_fn)(void *ptr); +} cJSON_Hooks; + +typedef int cJSON_bool; + +/* Limits how deeply nested arrays/objects can be before cJSON rejects to parse them. + * This is to prevent stack overflows. */ +#ifndef CJSON_NESTING_LIMIT +#define CJSON_NESTING_LIMIT 1000 +#endif + +/* returns the version of cJSON as a string */ +CJSON_PUBLIC(const char*) cJSON_Version(void); + +/* Supply malloc, realloc and free functions to cJSON */ +CJSON_PUBLIC(void) cJSON_InitHooks(cJSON_Hooks* hooks); + +/* Memory Management: the caller is always responsible to free the results from all variants of cJSON_Parse (with cJSON_Delete) and cJSON_Print (with stdlib free, cJSON_Hooks.free_fn, or cJSON_free as appropriate). The exception is cJSON_PrintPreallocated, where the caller has full responsibility of the buffer. */ +/* Supply a block of JSON, and this returns a cJSON object you can interrogate. */ +CJSON_PUBLIC(cJSON *) cJSON_Parse(const char *value); +CJSON_PUBLIC(cJSON *) cJSON_ParseWithLength(const char *value, size_t buffer_length); +/* ParseWithOpts allows you to require (and check) that the JSON is null terminated, and to retrieve the pointer to the final byte parsed. */ +/* If you supply a ptr in return_parse_end and parsing fails, then return_parse_end will contain a pointer to the error so will match cJSON_GetErrorPtr(). */ +CJSON_PUBLIC(cJSON *) cJSON_ParseWithOpts(const char *value, const char **return_parse_end, cJSON_bool require_null_terminated); +CJSON_PUBLIC(cJSON *) cJSON_ParseWithLengthOpts(const char *value, size_t buffer_length, const char **return_parse_end, cJSON_bool require_null_terminated); + +/* Render a cJSON entity to text for transfer/storage. */ +CJSON_PUBLIC(char *) cJSON_Print(const cJSON *item); +/* Render a cJSON entity to text for transfer/storage without any formatting. */ +CJSON_PUBLIC(char *) cJSON_PrintUnformatted(const cJSON *item); +/* Render a cJSON entity to text using a buffered strategy. prebuffer is a guess at the final size. guessing well reduces reallocation. fmt=0 gives unformatted, =1 gives formatted */ +CJSON_PUBLIC(char *) cJSON_PrintBuffered(const cJSON *item, int prebuffer, cJSON_bool fmt); +/* Render a cJSON entity to text using a buffer already allocated in memory with given length. Returns 1 on success and 0 on failure. */ +/* NOTE: cJSON is not always 100% accurate in estimating how much memory it will use, so to be safe allocate 5 bytes more than you actually need */ +CJSON_PUBLIC(cJSON_bool) cJSON_PrintPreallocated(cJSON *item, char *buffer, const int length, const cJSON_bool format); +/* Delete a cJSON entity and all subentities. */ +CJSON_PUBLIC(void) cJSON_Delete(cJSON *item); + +/* Returns the number of items in an array (or object). */ +CJSON_PUBLIC(int) cJSON_GetArraySize(const cJSON *array); +/* Retrieve item number "index" from array "array". Returns NULL if unsuccessful. */ +CJSON_PUBLIC(cJSON *) cJSON_GetArrayItem(const cJSON *array, int index); +/* Get item "string" from object. Case insensitive. */ +CJSON_PUBLIC(cJSON *) cJSON_GetObjectItem(const cJSON * const object, const char * const string); +CJSON_PUBLIC(cJSON *) cJSON_GetObjectItemCaseSensitive(const cJSON * const object, const char * const string); +CJSON_PUBLIC(cJSON_bool) cJSON_HasObjectItem(const cJSON *object, const char *string); +/* For analysing failed parses. This returns a pointer to the parse error. You'll probably need to look a few chars back to make sense of it. Defined when cJSON_Parse() returns 0. 0 when cJSON_Parse() succeeds. */ +CJSON_PUBLIC(const char *) cJSON_GetErrorPtr(void); + +/* Check item type and return its value */ +CJSON_PUBLIC(char *) cJSON_GetStringValue(const cJSON * const item); +CJSON_PUBLIC(double) cJSON_GetNumberValue(const cJSON * const item); + +/* These functions check the type of an item */ +CJSON_PUBLIC(cJSON_bool) cJSON_IsInvalid(const cJSON * const item); +CJSON_PUBLIC(cJSON_bool) cJSON_IsFalse(const cJSON * const item); +CJSON_PUBLIC(cJSON_bool) cJSON_IsTrue(const cJSON * const item); +CJSON_PUBLIC(cJSON_bool) cJSON_IsBool(const cJSON * const item); +CJSON_PUBLIC(cJSON_bool) cJSON_IsNull(const cJSON * const item); +CJSON_PUBLIC(cJSON_bool) cJSON_IsNumber(const cJSON * const item); +CJSON_PUBLIC(cJSON_bool) cJSON_IsString(const cJSON * const item); +CJSON_PUBLIC(cJSON_bool) cJSON_IsArray(const cJSON * const item); +CJSON_PUBLIC(cJSON_bool) cJSON_IsObject(const cJSON * const item); +CJSON_PUBLIC(cJSON_bool) cJSON_IsRaw(const cJSON * const item); + +/* These calls create a cJSON item of the appropriate type. */ +CJSON_PUBLIC(cJSON *) cJSON_CreateNull(void); +CJSON_PUBLIC(cJSON *) cJSON_CreateTrue(void); +CJSON_PUBLIC(cJSON *) cJSON_CreateFalse(void); +CJSON_PUBLIC(cJSON *) cJSON_CreateBool(cJSON_bool boolean); +CJSON_PUBLIC(cJSON *) cJSON_CreateNumber(double num); +CJSON_PUBLIC(cJSON *) cJSON_CreateString(const char *string); +/* raw json */ +CJSON_PUBLIC(cJSON *) cJSON_CreateRaw(const char *raw); +CJSON_PUBLIC(cJSON *) cJSON_CreateArray(void); +CJSON_PUBLIC(cJSON *) cJSON_CreateObject(void); + +/* Create a string where valuestring references a string so + * it will not be freed by cJSON_Delete */ +CJSON_PUBLIC(cJSON *) cJSON_CreateStringReference(const char *string); +/* Create an object/array that only references it's elements so + * they will not be freed by cJSON_Delete */ +CJSON_PUBLIC(cJSON *) cJSON_CreateObjectReference(const cJSON *child); +CJSON_PUBLIC(cJSON *) cJSON_CreateArrayReference(const cJSON *child); + +/* These utilities create an Array of count items. + * The parameter count cannot be greater than the number of elements in the number array, otherwise array access will be out of bounds.*/ +CJSON_PUBLIC(cJSON *) cJSON_CreateIntArray(const int *numbers, int count); +CJSON_PUBLIC(cJSON *) cJSON_CreateFloatArray(const float *numbers, int count); +CJSON_PUBLIC(cJSON *) cJSON_CreateDoubleArray(const double *numbers, int count); +CJSON_PUBLIC(cJSON *) cJSON_CreateStringArray(const char *const *strings, int count); + +/* Append item to the specified array/object. */ +CJSON_PUBLIC(cJSON_bool) cJSON_AddItemToArray(cJSON *array, cJSON *item); +CJSON_PUBLIC(cJSON_bool) cJSON_AddItemToObject(cJSON *object, const char *string, cJSON *item); +/* Use this when string is definitely const (i.e. a literal, or as good as), and will definitely survive the cJSON object. + * WARNING: When this function was used, make sure to always check that (item->type & cJSON_StringIsConst) is zero before + * writing to `item->string` */ +CJSON_PUBLIC(cJSON_bool) cJSON_AddItemToObjectCS(cJSON *object, const char *string, cJSON *item); +/* Append reference to item to the specified array/object. Use this when you want to add an existing cJSON to a new cJSON, but don't want to corrupt your existing cJSON. */ +CJSON_PUBLIC(cJSON_bool) cJSON_AddItemReferenceToArray(cJSON *array, cJSON *item); +CJSON_PUBLIC(cJSON_bool) cJSON_AddItemReferenceToObject(cJSON *object, const char *string, cJSON *item); + +/* Remove/Detach items from Arrays/Objects. */ +CJSON_PUBLIC(cJSON *) cJSON_DetachItemViaPointer(cJSON *parent, cJSON * const item); +CJSON_PUBLIC(cJSON *) cJSON_DetachItemFromArray(cJSON *array, int which); +CJSON_PUBLIC(void) cJSON_DeleteItemFromArray(cJSON *array, int which); +CJSON_PUBLIC(cJSON *) cJSON_DetachItemFromObject(cJSON *object, const char *string); +CJSON_PUBLIC(cJSON *) cJSON_DetachItemFromObjectCaseSensitive(cJSON *object, const char *string); +CJSON_PUBLIC(void) cJSON_DeleteItemFromObject(cJSON *object, const char *string); +CJSON_PUBLIC(void) cJSON_DeleteItemFromObjectCaseSensitive(cJSON *object, const char *string); + +/* Update array items. */ +CJSON_PUBLIC(cJSON_bool) cJSON_InsertItemInArray(cJSON *array, int which, cJSON *newitem); /* Shifts pre-existing items to the right. */ +CJSON_PUBLIC(cJSON_bool) cJSON_ReplaceItemViaPointer(cJSON * const parent, cJSON * const item, cJSON * replacement); +CJSON_PUBLIC(cJSON_bool) cJSON_ReplaceItemInArray(cJSON *array, int which, cJSON *newitem); +CJSON_PUBLIC(cJSON_bool) cJSON_ReplaceItemInObject(cJSON *object,const char *string,cJSON *newitem); +CJSON_PUBLIC(cJSON_bool) cJSON_ReplaceItemInObjectCaseSensitive(cJSON *object,const char *string,cJSON *newitem); + +/* Duplicate a cJSON item */ +CJSON_PUBLIC(cJSON *) cJSON_Duplicate(const cJSON *item, cJSON_bool recurse); +/* Duplicate will create a new, identical cJSON item to the one you pass, in new memory that will + * need to be released. With recurse!=0, it will duplicate any children connected to the item. + * The item->next and ->prev pointers are always zero on return from Duplicate. */ +/* Recursively compare two cJSON items for equality. If either a or b is NULL or invalid, they will be considered unequal. + * case_sensitive determines if object keys are treated case sensitive (1) or case insensitive (0) */ +CJSON_PUBLIC(cJSON_bool) cJSON_Compare(const cJSON * const a, const cJSON * const b, const cJSON_bool case_sensitive); + +/* Minify a strings, remove blank characters(such as ' ', '\t', '\r', '\n') from strings. + * The input pointer json cannot point to a read-only address area, such as a string constant, + * but should point to a readable and writable address area. */ +CJSON_PUBLIC(void) cJSON_Minify(char *json); + +/* Helper functions for creating and adding items to an object at the same time. + * They return the added item or NULL on failure. */ +CJSON_PUBLIC(cJSON*) cJSON_AddNullToObject(cJSON * const object, const char * const name); +CJSON_PUBLIC(cJSON*) cJSON_AddTrueToObject(cJSON * const object, const char * const name); +CJSON_PUBLIC(cJSON*) cJSON_AddFalseToObject(cJSON * const object, const char * const name); +CJSON_PUBLIC(cJSON*) cJSON_AddBoolToObject(cJSON * const object, const char * const name, const cJSON_bool boolean); +CJSON_PUBLIC(cJSON*) cJSON_AddNumberToObject(cJSON * const object, const char * const name, const double number); +CJSON_PUBLIC(cJSON*) cJSON_AddStringToObject(cJSON * const object, const char * const name, const char * const string); +CJSON_PUBLIC(cJSON*) cJSON_AddRawToObject(cJSON * const object, const char * const name, const char * const raw); +CJSON_PUBLIC(cJSON*) cJSON_AddObjectToObject(cJSON * const object, const char * const name); +CJSON_PUBLIC(cJSON*) cJSON_AddArrayToObject(cJSON * const object, const char * const name); + +/* When assigning an integer value, it needs to be propagated to valuedouble too. */ +#define cJSON_SetIntValue(object, number) ((object) ? (object)->valueint = (object)->valuedouble = (number) : (number)) +/* helper for the cJSON_SetNumberValue macro */ +CJSON_PUBLIC(double) cJSON_SetNumberHelper(cJSON *object, double number); +#define cJSON_SetNumberValue(object, number) ((object != NULL) ? cJSON_SetNumberHelper(object, (double)number) : (number)) +/* Change the valuestring of a cJSON_String object, only takes effect when type of object is cJSON_String */ +CJSON_PUBLIC(char*) cJSON_SetValuestring(cJSON *object, const char *valuestring); + +/* Macro for iterating over an array or object */ +#define cJSON_ArrayForEach(element, array) for(element = (array != NULL) ? (array)->child : NULL; element != NULL; element = element->next) + +/* malloc/free objects using the malloc/free functions that have been set with cJSON_InitHooks */ +CJSON_PUBLIC(void *) cJSON_malloc(size_t size); +CJSON_PUBLIC(void) cJSON_free(void *object); + +#ifdef __cplusplus +} +#endif + +#endif \ No newline at end of file diff --git a/VNode/_software_lib/nanomq-0.22.10/include/nng/supplemental/nanolib/cmd.h b/VNode/_software_lib/nanomq-0.22.10/include/nng/supplemental/nanolib/cmd.h new file mode 100644 index 00000000..065a37a3 --- /dev/null +++ b/VNode/_software_lib/nanomq-0.22.10/include/nng/supplemental/nanolib/cmd.h @@ -0,0 +1,37 @@ +// +// Copyright 2020 NanoMQ Team, Inc. +// +// This software is supplied under the terms of the MIT License, a +// copy of which should be located in the distribution where this +// file was obtained (LICENSE.txt). A copy of the license may also be +// found online at https://opensource.org/licenses/MIT. +// +#include + +#define CMD_BUFF_LEN 1024 +extern char *cmd_output_buff; +extern int cmd_output_len; + +#ifndef NNG_PLATFORM_WINDOWS + +#define CMD_RUN(cmd) \ + do { \ + ret = cmd_run(cmd); \ + if (ret < 0) \ + goto err; \ + } while (0) + +#define CMD_FRUN(fcmd, ...) \ + do { \ + ret = nano_cmd_frun(fcmd, __VA_ARGS__); \ + if (ret < 0) \ + goto err; \ + } while (0) + +extern int nano_cmd_run(const char *cmd); +extern int nano_cmd_run_status(const char *cmd); +extern int nano_cmd_frun(const char *format, ...); + +#endif + +extern void nano_cmd_cleanup(void); diff --git a/VNode/_software_lib/nanomq-0.22.10/include/nng/supplemental/nanolib/conf.h b/VNode/_software_lib/nanomq-0.22.10/include/nng/supplemental/nanolib/conf.h new file mode 100644 index 00000000..20616304 --- /dev/null +++ b/VNode/_software_lib/nanomq-0.22.10/include/nng/supplemental/nanolib/conf.h @@ -0,0 +1,691 @@ +#ifndef CONF_H +#define CONF_H + +#include +#include +#include +#include +#include +#include +#include +#include "nng/nng.h" +#include "rule.h" +#include "acl_conf.h" +#include "log.h" +#include "ringbuffer.h" +#include "nng/supplemental/util/platform.h" + +#define PID_PATH_NAME "/tmp/nanomq/nanomq.pid" +#define CONF_PATH_NAME "/etc/nanomq.conf" +#define CONF_ZMQ_GATEWAY_PATH_NAME "/etc/nanomq_zmq_gateway.conf" +#define CONF_VSOMEIP_GATEWAY_PATH_NAME "/etc/nanomq_vsomeip_gateway.conf" + +#define CONF_DDS_GATEWAY_PATH_NAME "/etc/nanomq_dds_gateway.conf" + +#define CONF_TCP_URL_DEFAULT "nmq-tcp://0.0.0.0:1883" +#define CONF_TLS_URL_DEFAULT "tls+nmq-tcp://0.0.0.0:8883" +#define CONF_WS_URL_DEFAULT "nmq-ws://0.0.0.0:8083/mqtt" +#define CONF_WSS_URL_DEFAULT "nmq-wss://0.0.0.0:8086/mqtt" + +#define BROKER_NMQ_TCP_URL_PREFIX "nmq-tcp" +#define BROKER_NMQ_TCP_TLS_URL_PREFIX "tls+nmq-tcp" +#define BROKER_NMQ_WS_URL_PREFIX "nmq-ws" +#define BROKER_NMQ_WSS_URL_PREFIX "nmq-wss" + +#define BROKER_TCP_URL_PREFIX "broker+tcp" +#define BROKER_WS_URL_PREFIX "nmq+ws" +#define BROKER_WSS_URL_PREFIX "nmq+wss" + +#define RULE_ENG_OFF 0 +#define RULE_ENG_SDB 1 +#define RULE_ENG_FDB (1 << 1) +#define RULE_ENG_MDB (1 << 2) +#define RULE_ENG_RPB (1 << 3) + + +#define FREE_NONULL(p) \ + if (p) { \ + free(p); \ + p = NULL; \ + } + +struct conf_auth { + bool enable; + size_t count; + char **usernames; + char **passwords; +}; + +typedef struct conf_auth conf_auth; + +struct conf_tls { + bool enable; + char *url; // "tls+nmq-tcp://addr:port" + char *cafile; + char *certfile; + char *keyfile; + char *ca; + char *cert; + char *key; + char *key_password; + bool verify_peer; + bool set_fail; // fail_if_no_peer_cert +}; + +typedef struct conf_tls conf_tls; + +// TODO: params for one single tcp node should be in here. +typedef struct { + bool enable; + char *url; + uint8_t nodelay; + uint8_t keepalive; + uint8_t quickack; + uint16_t keepidle; + uint16_t keepintvl; + uint16_t keepcnt; + uint16_t sendtimeo; + uint16_t recvtimeo; +} conf_tcp; + +typedef struct { + size_t count; + conf_tls **nodes; +} conf_tls_list; + +typedef struct { + size_t count; + conf_tcp **nodes; +} conf_tcp_list; + +struct conf_sqlite { + bool enable; + size_t disk_cache_size; // specify the max rows of sqlite table + char * mounted_file_path; // specify the db file path + size_t + flush_mem_threshold; // flush to sqlite table when count of message + // is equal or greater than this value + uint64_t resend_interval; // resend caching message interval (ms) +}; + +typedef struct conf_sqlite conf_sqlite; + +struct conf_http_header { + char *key; + char *value; +}; + +typedef struct conf_http_header conf_http_header; + +typedef enum { + ACCESS, + USERNAME, + CLIENTID, + IPADDRESS, + PROTOCOL, + PASSWORD, + SOCKPORT, // sockport of server accepted + COMMON_NAME, // common name of client TLS cert + SUBJECT, // subject of client TLS cert + TOPIC, + MOUNTPOINT, +} http_param_type; + +struct conf_http_param { + char * name; + http_param_type type; +}; + +typedef struct conf_http_param conf_http_param; + +struct conf_auth_http_req { + char *url; + char *method; + size_t header_count; + conf_http_header **headers; + size_t param_count; + conf_http_param **params; + // TODO not support yet + conf_tls tls; +}; + +typedef struct conf_auth_http_req conf_auth_http_req; + +struct conf_auth_http { + bool enable; + conf_auth_http_req auth_req; + conf_auth_http_req super_req; + conf_auth_http_req acl_req; + uint64_t timeout; // seconds + uint64_t connect_timeout; // seconds + size_t pool_size; +}; + +typedef struct conf_auth_http conf_auth_http; + +struct conf_jwt { + char *iss; + char *public_keyfile; + char *private_keyfile; + char *public_key; + char *private_key; + size_t public_key_len; + size_t private_key_len; +}; + +typedef struct conf_jwt conf_jwt; + +typedef enum { + BASIC, + JWT, + NONE_AUTH, +} auth_type_t; + +struct conf_http_server { + bool enable; + uint16_t port; + char *username; + char *password; + size_t parallel; + auth_type_t auth_type; + conf_jwt jwt; + nng_socket *broker_sock; +}; + +typedef struct conf_http_server conf_http_server; + +struct conf_websocket { + bool enable; + char *url; // "nmq-ws://addr:port/path" + char *tls_url; // "nmq-wss://addr:port/path" +}; + +typedef struct conf_websocket conf_websocket; + +#define NO_RETAIN 2 // default retain flag value, none 0, 1 +#define NO_QOS 3 // default QoS level value for forwarding bridge msg, 3 = keep old qos + +typedef struct { + char *remote_topic; + uint32_t remote_topic_len; + char *local_topic; + uint32_t local_topic_len; + char *prefix; + uint32_t prefix_len; + char *suffix; + uint32_t suffix_len; + uint8_t nolocal; + uint8_t retain; // override for retain + uint8_t qos; // override for QoS + uint8_t retain_as_published; + uint8_t retain_handling; + uint32_t stream_id; // only effective when multi_stream is enabled +} topics; + +typedef struct { + char *key; + char *value; +}conf_user_property; + +typedef struct { + uint32_t session_expiry_interval; + uint8_t request_problem_info; + uint8_t request_response_info; + uint16_t receive_maximum; + uint16_t topic_alias_maximum; + uint32_t maximum_packet_size; + size_t user_property_size; + conf_user_property **user_property; +} conf_bridge_conn_properties; + +typedef struct { + uint8_t payload_format_indicator; + uint32_t message_expiry_interval; + char * content_type; + char * response_topic; + char * correlation_data; + uint32_t will_delay_interval; + size_t user_property_size; + conf_user_property **user_property; +} conf_bridge_conn_will_properties; + +typedef struct { + uint32_t identifier; + size_t user_property_size; + conf_user_property **user_property; +} conf_bridge_sub_properties; + +struct conf_bridge_node { + bool enable; + bool dynamic; + bool clean_start; + bool transparent; + bool will_flag; + bool will_retain; + void *sock; + void *bridge_arg; // for reloading bridge case + char *name; + char *address; + char *host; + char *clientid; + char *username; + char *password; + char *will_payload; + char *will_topic; + uint8_t proto_ver; + uint8_t will_qos; + uint16_t port; + uint16_t keepalive; + uint16_t backoff_max; + uint64_t cancel_timeout; + uint64_t resend_interval; // resend caching message interval (ms) + uint64_t resend_wait; + size_t sub_count; + size_t forwards_count; + size_t max_recv_queue_len; + size_t max_send_queue_len; + topics **forwards_list; + uint64_t parallel; + topics **sub_list; + conf_tls tls; + conf_tcp tcp; + conf_sqlite *sqlite; + nng_aio **bridge_aio; + nng_mtx *mtx; + + bool hybrid; // enable/disable hybrid bridging + char **hybrid_servers; + + // MQTT v5 property + conf_bridge_conn_properties * conn_properties; + conf_bridge_conn_will_properties *will_properties; + conf_bridge_sub_properties * sub_properties; + +#if defined(SUPP_QUIC) + // config params for QUIC only + bool multi_stream; + bool stream_auto_genid; // generate stream id automatically for each stream + bool qos_first; // send QoS msg in high priority + uint64_t qkeepalive; //keepalive timeout interval of QUIC transport + uint64_t qconnect_timeout; // HandshakeIdleTimeoutMs of QUIC + uint32_t qdiscon_timeout; // DisconnectTimeoutMs + uint32_t qidle_timeout; // Disconnect after idle + uint32_t qsend_idle_timeout; // SendIdleTimeoutMs + uint32_t qinitial_rtt_ms; // Initial RTT estimate. + uint32_t qmax_ack_delay_ms; // MaxAckDelayMs How long to wait after receiving data before sending an ACK. + uint8_t qcongestion_control; // congestion control algorithm 1: bbr 0: cubic + bool quic_0rtt; // 0RTT. +#endif +}; + +typedef struct conf_bridge_node conf_bridge_node; + +typedef struct ringBuffer_node ringBuffer_node; +struct ringBuffer_node { + char *name; + uint32_t fullOp; + uint64_t cap; +}; + +typedef struct conf_exchange_node conf_exchange_node; +struct conf_exchange_node { + char *name; + char *topic; + ringBuffer_node **rbufs; + size_t rbufs_sz; + + nng_socket *sock; + nng_mtx *mtx; + char *exchange_url; +}; + +typedef struct conf_exchange_encryption conf_exchange_encryption; +struct conf_exchange_encryption { + bool enable; + char *key; +}; + +typedef struct conf_exchange conf_exchange; +struct conf_exchange { + size_t count; + conf_exchange_node **nodes; + conf_exchange_encryption *encryption; +}; + +#if defined(SUPP_PLUGIN) +typedef struct conf_plugin_lib conf_plugin_lib; +struct conf_plugin_lib { + char *path; +}; + +typedef struct conf_plugin conf_plugin; +struct conf_plugin { + struct conf_plugin_lib **libs; + size_t path_sz; +}; +#endif + +typedef enum { + UNCOMPRESSED, + SNAPPY, + GZIP, + BROTLI, + ZSTD, + LZ4 +} compression_type; + +typedef enum { AES_GCM_V1 = 0, AES_GCM_CTR_V1 = 1 } cipher_type; + +struct conf_parquet_encryption { + bool enable; + char *key_id; + char *key; + cipher_type type; +}; + +typedef struct conf_parquet_encryption conf_parquet_encryption; + +struct conf_parquet { + bool enable; + char *dir; + char *file_name_prefix; + uint8_t file_count; + uint32_t limit_frequency; + uint8_t file_index; + int32_t file_size; + compression_type comp_type; + conf_parquet_encryption encryption; +}; +typedef struct conf_parquet conf_parquet; + +struct conf_blf { + bool enable; + char *dir; + char *file_name_prefix; + uint8_t file_count; + uint8_t file_index; + int32_t file_size; + compression_type comp_type; +}; +typedef struct conf_blf conf_blf; + +struct conf_bridge { + size_t count; + conf_bridge_node **nodes; + conf_sqlite sqlite; +}; + +typedef struct conf_bridge conf_bridge; +typedef struct { + char *zmq_sub_url; + char *zmq_pub_url; + char *mqtt_url; + char *sub_topic; + char *pub_topic; + char *zmq_sub_pre; + char *zmq_pub_pre; + char *path; + char *username; + char *password; + void *zmq_sender; + int proto_ver; + int keepalive; + bool clean_start; + int parallel; + enum { PUB_SUB, REQ_REP } type; + conf_http_server http_server; +} zmq_gateway_conf; + +typedef struct { + nng_socket *sock; + char *mqtt_url; + char *sub_topic; + char *pub_topic; + char *username; + char *password; + char *clientid; + char *path; + int proto_ver; + int keepalive; + bool clean_start; + uint8_t sub_qos; + int parallel; + + conf_http_server http_server; + + // vsomeip parameter + uint16_t service_id; + uint16_t service_instance_id; + uint16_t service_method_id; + uint16_t service_event_id; + uint16_t service_eventgroup_id; + char *conf_path; +} vsomeip_gateway_conf; + +typedef struct { + char *from; + char *to; + char *struct_name; +} dds_gateway_topic; + +typedef struct { + dds_gateway_topic **dds2mqtt; + size_t dds2mqtt_sz; + dds_gateway_topic **mqtt2dds; + size_t mqtt2dds_sz; +} dds_gateway_forward; + +typedef struct { + nng_socket *sock; + bool clean_start; + uint8_t proto_ver; + uint16_t port; + uint16_t keepalive; + char * address; + char * clientid; + char * username; + char * password; + conf_tls tls; +} dds_gateway_mqtt; + +typedef struct { + char * idl_type; + size_t domain_id; + char * subscriber_partition; + char * publisher_partition; + bool shm_mode; + char * shm_log_level; +} dds_gateway_dds; + +typedef struct { + char * path; + dds_gateway_mqtt mqtt; + dds_gateway_dds dds; + dds_gateway_forward forward; + conf_http_server http_server; +} dds_gateway_conf; + +typedef enum { + CLIENT_CONNECT, + CLIENT_CONNACK, + CLIENT_CONNECTED, + CLIENT_DISCONNECTED, + CLIENT_SUBSCRIBE, + CLIENT_UNSUBSCRIBE, + SESSION_SUBSCRIBED, + SESSION_UNSUBSCRIBED, + SESSION_TERMINATED, + MESSAGE_PUBLISH, + MESSAGE_DELIVERED, + MESSAGE_ACKED, + UNKNOWN_EVENT, +} webhook_event; + +typedef enum { + plain, + base64, + base62 +} hook_payload_type; + +struct conf_web_hook_rule { + uint16_t rule_num; + webhook_event event; + char * action; + char * topic; +}; + +typedef struct conf_web_hook_rule conf_web_hook_rule; + +struct conf_web_hook { + bool enable; + char * url; + size_t pool_size; + hook_payload_type encode_payload; + size_t header_count; + conf_http_header **headers; + + uint16_t rule_count; + conf_web_hook_rule **rules; + + nng_mtx *ex_mtx; // mutex for saios + nng_aio *ex_aio; // Await flush + nng_aio **saios; // Aios for sending message + + // TODO not support yet + conf_tls tls; +}; + +typedef struct conf_web_hook conf_web_hook; + +typedef enum { + memory, + sqlite, +} persistence_type; + +struct conf { + char *vin; + char *cmd_ipc_url; + char *hook_ipc_url; + char *conf_file; + char *url; + bool enable; + int property_size; + int msq_len; + uint32_t num_taskq_thread; + uint32_t max_taskq_thread; + uint32_t parallel; // broker ctx + uint64_t total_ctx; // Total ctx of work (bridge + AWS + broker + HTTP) + uint64_t max_packet_size; // byte + uint32_t client_max_packet_size; // byte + uint32_t max_inflight_window; + uint32_t max_awaiting_rel; + uint32_t await_rel_timeout; + uint32_t qos_duration; + float backoff; + void *db_root; + bool allow_anonymous; + bool daemon; + bool ipc_internal; + bool bridge_mode; + + conf_tcp_list tcp_list; + conf_tls_list tls_list; + conf_sqlite sqlite; + conf_tls tls; + conf_http_server http_server; + conf_websocket websocket; + conf_bridge bridge; //standard MQTT + conf_bridge aws_bridge; // AWS IoT Core + conf_exchange exchange; + conf_parquet parquet; + conf_blf blf; +#if defined(SUPP_PLUGIN) + conf_plugin plugin; +#endif + conf_web_hook web_hook; +#if defined(ENABLE_LOG) + conf_log log; +#endif +#if defined(SUPP_RULE_ENGINE) + conf_rule rule_eng; +#endif +#ifdef ACL_SUPP + conf_acl acl; + acl_permit acl_nomatch; + bool enable_acl_cache; + size_t acl_cache_max_size; + size_t acl_cache_ttl; + enum { ACL_IGNORE, ACL_DISCONNECT } acl_deny_action; +#endif + conf_auth auths; + conf_auth_http auth_http; + struct hashmap_s *cid_table; +}; + +typedef struct conf conf; + +webhook_event get_webhook_event(const char *hook_type, const char *hook_name); + +NNG_DECL int get_size(const char *str, uint64_t *size); +NNG_DECL int get_time(const char *str, uint64_t *second); +NNG_DECL void conf_parse(conf *nanomq_conf); +NNG_DECL void conf_parse_ver2(conf *nanomq_conf); +NNG_DECL void conf_gateway_parse_ver2(zmq_gateway_conf *gateway); +NNG_DECL void conf_vsomeip_gateway_parse_ver2(vsomeip_gateway_conf *config); +NNG_DECL void conf_dds_gateway_init(dds_gateway_conf *config); +NNG_DECL void conf_dds_gateway_parse_ver2(dds_gateway_conf *config); +NNG_DECL void conf_dds_gateway_destory(dds_gateway_conf *config); +NNG_DECL void conf_init(conf *nanomq_conf); +NNG_DECL void print_conf(conf *nanomq_conf); +NNG_DECL void conf_set_threads(conf *nanomq_conf); +NNG_DECL void conf_fini(conf *nanomq_conf); +NNG_DECL void conf_update(const char *fpath, const char *key, char *value); +NNG_DECL void conf_update2(const char *fpath, const char *key1, + const char *key2, const char *key3, char *value); +NNG_DECL void +conf_bridge_node_parse( + conf_bridge_node *node, conf_sqlite *bridge_sqlite, cJSON *obj); +NNG_DECL void conf_bridge_node_destroy(conf_bridge_node *node); + +NNG_DECL void conf_update_var( + const char *fpath, const char *key, uint8_t type, void *var); +NNG_DECL void conf_update_var2(const char *fpath, const char *key1, + const char *key2, const char *key3, uint8_t type, void *var); +NNG_DECL const char* conf_get_vin(void); +NNG_DECL void conf_free_vin(); + +#define conf_update_int(path, key, var) \ + conf_update_var(path, key, 0, (void *) &(var)) +#define conf_update_u8(path, key, var) \ + conf_update_var(path, key, 1, (void *) &(var)) +#define conf_update_u16(path, key, var) \ + conf_update_var(path, key, 2, (void *) &(var)) +#define conf_update_u32(path, key, var) \ + conf_update_var(path, key, 3, (void *) &(var)) +#define conf_update_u64(path, key, var) \ + conf_update_var(path, key, 4, (void *) &(var)) +#define conf_update_long(path, key, var) \ + conf_update_var(path, key, 5, (void *) &(var)) +#define conf_update_double(path, key, var) \ + conf_update_var(path, key, 6, (void *) &(var)) +#define conf_update_bool(path, key, var) \ + conf_update_var(path, key, 7, (void *) &(var)) + +#define conf_update2_int(path, key1, key2, key3, var) \ + conf_update_var2(path, key1, key2, key3, 0, (void *) &(var)) +#define conf_update2_u8(path, key1, key2, key3, var) \ + conf_update_var2(path, key1, key2, key3, 1, (void *) &(var)) +#define conf_update2_u16(path, key1, key2, key3, var) \ + conf_update_var2(path, key1, key2, key3, 2, (void *) &(var)) +#define conf_update2_u32(path, key1, key2, key3, var) \ + conf_update_var2(path, key1, key2, key3, 3, (void *) &(var)) +#define conf_update2_u64(path, key1, key2, key3, var) \ + conf_update_var2(path, key1, key2, key3, 4, (void *) &(var)) +#define conf_update2_long(path, key1, key2, key3, var) \ + conf_update_var2(path, key1, key2, key3, 5, (void *) &(var)) +#define conf_update2_double(path, key1, key2, key3, var) \ + conf_update_var2(path, key1, key2, key3, 6, (void *) &(var)) +#define conf_update2_bool(path, key1, key2, key3, var) \ + conf_update_var2(path, key1, key2, key3, 7, (void *) &(var)) + +#endif diff --git a/VNode/_software_lib/nanomq-0.22.10/include/nng/supplemental/nanolib/cvector.h b/VNode/_software_lib/nanomq-0.22.10/include/nng/supplemental/nanolib/cvector.h new file mode 100644 index 00000000..38b7e95f --- /dev/null +++ b/VNode/_software_lib/nanomq-0.22.10/include/nng/supplemental/nanolib/cvector.h @@ -0,0 +1,228 @@ + +#ifndef CVECTOR_H_ +#define CVECTOR_H_ + +#include /* for assert */ +#include /* for malloc/realloc/free */ + +/** + * @brief cvector_vector_type - The vector type used in this library + */ +#define cvector(type) type * +/** + * @brief cvector_set_capacity - For internal use, sets the capacity variable + * of the vector + * @param vec - the vector + * @param size - the new capacity to set + * @return void + */ +#define cvector_set_capacity(vec, size) \ + do { \ + if (vec) { \ + ((size_t *) (vec))[-1] = (size); \ + } \ + } while (0) + +/** + * @brief cvector_set_size - For internal use, sets the size variable of the + * vector + * @param vec - the vector + * @param size - the new capacity to set + * @return void + */ +#define cvector_set_size(vec, size) \ + do { \ + if (vec) { \ + ((size_t *) (vec))[-2] = (size); \ + } \ + } while (0) + +/** + * @brief cvector_capacity - gets the current capacity of the vector + * @param vec - the vector + * @return the capacity as a size_t + */ +#define cvector_capacity(vec) ((vec) ? ((size_t *) (vec))[-1] : (size_t) 0) + +/** + * @brief cvector_size - gets the current size of the vector + * @param vec - the vector + * @return the size as a size_t + */ +#define cvector_size(vec) ((vec) ? ((size_t *) (vec))[-2] : (size_t) 0) + +/** + * @brief cvector_empty - returns non-zero if the vector is empty + * @param vec - the vector + * @return non-zero if empty, zero if non-empty + */ +#define cvector_empty(vec) (cvector_size(vec) == 0) + +/** + * @brief cvector_grow - For internal use, ensures that the vector is at least + * elements big + * @param vec - the vector + * @param count - the new capacity to set + * @return void + */ +#define cvector_grow(vec, count) \ + do { \ + const size_t cv_sz = \ + (count) * sizeof(*(vec)) + (sizeof(size_t) * 2); \ + if (!(vec)) { \ + size_t *cv_p = malloc(cv_sz); \ + assert(cv_p); \ + (vec) = (void *) (&cv_p[2]); \ + cvector_set_capacity((vec), (count)); \ + cvector_set_size((vec), 0); \ + } else { \ + size_t *cv_p1 = &((size_t *) (vec))[-2]; \ + size_t *cv_p2 = realloc(cv_p1, (cv_sz)); \ + assert(cv_p2); \ + (vec) = (void *) (&cv_p2[2]); \ + cvector_set_capacity((vec), (count)); \ + } \ + } while (0) + +/** + * @brief cvector_pop_back - removes the last element from the vector + * @param vec - the vector + * @return void + */ +#define cvector_pop_back(vec) \ + do { \ + cvector_set_size((vec), cvector_size(vec) - 1); \ + } while (0) + +/** + * @brief cvector_erase - removes the element at index i from the vector + * @param vec - the vector + * @param i - index of element to remove + * @return void + */ +#define cvector_erase(vec, i) \ + do { \ + if (vec) { \ + const size_t cv_sz = cvector_size(vec); \ + if ((i) < cv_sz) { \ + cvector_set_size((vec), cv_sz - 1); \ + size_t cv_x; \ + for (cv_x = (i); cv_x < (cv_sz - 1); \ + ++cv_x) { \ + (vec)[cv_x] = (vec)[cv_x + 1]; \ + } \ + } \ + } \ + } while (0) + +/** + * @brief cvector_free - frees all memory associated with the vector + * @param vec - the vector + * @return void + */ +#define cvector_free(vec) \ + do { \ + if (vec) { \ + size_t *p1 = &((size_t *) (vec))[-2]; \ + free(p1); \ + } \ + } while (0) + +/** + * @brief cvector_begin - returns an iterator to first element of the vector + * @param vec - the vector + * @return a pointer to the first element (or NULL) + */ +#define cvector_begin(vec) (vec) + +/** + * @brief cvector_end - returns an iterator to one past the last element of the + * vector + * @param vec - the vector + * @return a pointer to one past the last element (or NULL) + */ +#define cvector_end(vec) ((vec) ? &((vec)[cvector_size(vec)]) : NULL) + +/* user request to use logarithmic growth algorithm */ +#ifdef CVECTOR_LOGARITHMIC_GROWTH + +/** + * @brief cvector_push_back - adds an element to the end of the vector + * @param vec - the vector + * @param value - the value to add + * @return void + */ +#define cvector_push_back(vec, value) \ + do { \ + size_t cv_cap = cvector_capacity(vec); \ + if (cv_cap <= cvector_size(vec)) { \ + cvector_grow( \ + (vec), !cv_cap ? cv_cap + 1 : cv_cap * 2); \ + } \ + vec[cvector_size(vec)] = (value); \ + cvector_set_size((vec), cvector_size(vec) + 1); \ + } while (0) + +#else + +/** + * @brief cvector_push_back - adds an element to the end of the vector + * @param vec - the vector + * @param value - the value to add + * @return void + */ +#define cvector_push_back(vec, value) \ + do { \ + size_t cv_cap = cvector_capacity(vec); \ + if (cv_cap <= cvector_size(vec)) { \ + cvector_grow((vec), cv_cap + 1); \ + } \ + vec[cvector_size(vec)] = (value); \ + cvector_set_size((vec), cvector_size(vec) + 1); \ + } while (0) + +#endif /* CVECTOR_LOGARITHMIC_GROWTH */ + +/** + * @brief cvector_copy - copy a vector + * @param from - the original vector + * @param to - destination to which the function copy to + * @return void + */ +#define cvector_copy(from, to) \ + do { \ + for (size_t i = 0; i < cvector_size(from); i++) { \ + cvector_push_back(to, from[i]); \ + } \ + } while (0) + +#endif /* CVECTOR_H_ */ + +/** + * @brief cvector_insert - insert the element at index i to the vector + * @param vec - the vector + * @param i - index of element to insert + * @param value - value to insert + * @return void + */ +#define cvector_insert(vec, i, value) \ + do { \ + if (cvector_empty(vec)) { \ + cvector_push_back(vec, value); \ + } else { \ + size_t cv_cap = cvector_capacity(vec); \ + if (cv_cap <= cvector_size(vec)) { \ + cvector_grow((vec), \ + !cv_cap ? cv_cap + 1 : cv_cap * 2); \ + } \ + const size_t cv_sz = cvector_size(vec); \ + if ((i) < cv_sz) { \ + cvector_set_size((vec), cv_sz + 1); \ + size_t cv_x; \ + for (cv_x = (cv_sz); cv_x > (i); cv_x--) { \ + (vec)[cv_x] = (vec)[cv_x - 1]; \ + } \ + vec[i] = (value); \ + } \ + } \ + } while (0) diff --git a/VNode/_software_lib/nanomq-0.22.10/include/nng/supplemental/nanolib/env.h b/VNode/_software_lib/nanomq-0.22.10/include/nng/supplemental/nanolib/env.h new file mode 100644 index 00000000..691b09fd --- /dev/null +++ b/VNode/_software_lib/nanomq-0.22.10/include/nng/supplemental/nanolib/env.h @@ -0,0 +1,63 @@ +#ifndef NANOLIB_ENV_H +#define NANOLIB_ENV_H + +#include "conf.h" +#include "nng/nng.h" + +#define NANOMQ_BROKER_URL "NANOMQ_BROKER_URL" +#define NANOMQ_EXCHANGER_URL "NANOMQ_EXCHANGER_URL" +#define NANOMQ_DAEMON "NANOMQ_DAEMON" +#define NANOMQ_TCP_ENABLE "NANOMQ_TCP_ENABLE" +#define NANOMQ_NUM_TASKQ_THREAD "NANOMQ_MAX_TASKQ_THREAD" +#define NANOMQ_MAX_TASKQ_THREAD "NANOMQ_MAX_TASKQ_THREAD" +#define NANOMQ_PARALLEL "NANOMQ_PARALLEL" +#define NANOMQ_PROPERTY_SIZE "NANOMQ_PROPERTY_SIZE" +#define NANOMQ_MAX_PACKET_SIZE "NANOMQ_MAX_PACKET_SIZE" +#define NANOMQ_CLIENT_MAX_PACKET_SIZE "NANOMQ_CLIENT_MAX_PACKET_SIZE" +#define NANOMQ_MSQ_LEN "NANOMQ_MSQ_LEN" +#define NANOMQ_QOS_DURATION "NANOMQ_QOS_DURATION" +#define NANOMQ_ALLOW_ANONYMOUS "NANOMQ_ALLOW_ANONYMOUS" +#define NANOMQ_MSG_PERSISTENCE "NANOMQ_MSG_PERSISTENCE" + +#define NANOMQ_WEBSOCKET_ENABLE "NANOMQ_WEBSOCKET_ENABLE" +#define NANOMQ_WEBSOCKET_URL "NANOMQ_WEBSOCKET_URL" +#define NANOMQ_WEBSOCKET_TLS_URL "NANOMQ_WEBSOCKET_TLS_URL" + +#define NANOMQ_HTTP_SERVER_ENABLE "NANOMQ_HTTP_SERVER_ENABLE" +#define NANOMQ_HTTP_SERVER_PORT "NANOMQ_HTTP_SERVER_PORT" +#define NANOMQ_HTTP_SERVER_PARALLEL "NANOMQ_HTTP_SERVER_PARALLEL" +#define NANOMQ_HTTP_SERVER_USERNAME "NANOMQ_HTTP_SERVER_USERNAME" +#define NANOMQ_HTTP_SERVER_PASSWORD "NANOMQ_HTTP_SERVER_PASSWORD" +#define NANOMQ_HTTP_SERVER_AUTH_TYPE "NANOMQ_HTTP_SERVER_AUTH_TYPE" +#define NANOMQ_HTTP_SERVER_JWT_PUBLIC_KEYFILE \ + "NANOMQ_HTTP_SERVER_JWT_PUBLIC_KEYFILE" +#define NANOMQ_HTTP_SERVER_JWT_PRIVATE_KEYFILE \ + "NANOMQ_HTTP_SERVER_JWT_PRIVATE_KEYFILE" + +#define NANOMQ_TLS_ENABLE "NANOMQ_TLS_ENABLE" +#define NANOMQ_TLS_URL "NANOMQ_TLS_URL" +#define NANOMQ_TLS_CA_CERT_PATH "NANOMQ_TLS_CA_CERT_PATH" +#define NANOMQ_TLS_CERT_PATH "NANOMQ_TLS_CERT_PATH" +#define NANOMQ_TLS_KEY_PATH "NANOMQ_TLS_KEY_PATH" +#define NANOMQ_TLS_KEY_PASSWORD "NANOMQ_TLS_KEY_PASSWORD" +#define NANOMQ_TLS_VERIFY_PEER "NANOMQ_TLS_VERIFY_PEER" +#define NANOMQ_TLS_FAIL_IF_NO_PEER_CERT "NANOMQ_TLS_FAIL_IF_NO_PEER_CERT" + +#define NANOMQ_LOG_LEVEL "NANOMQ_LOG_LEVEL" +#define NANOMQ_LOG_TO "NANOMQ_LOG_TO" +#define NANOMQ_LOG_UDS_ADDR "NANOMQ_LOG_UDS_ADDR" +#define NANOMQ_LOG_DIR "NANOMQ_LOG_DIR" +#define NANOMQ_LOG_FILE "NANOMQ_LOG_FILE" +#define NANOMQ_LOG_ROTATION_SIZE "NANOMQ_LOG_ROTATION_SIZE" +#define NANOMQ_LOG_ROTATION_COUNT "NANOMQ_LOG_ROTATION_COUNT" + +#define NANOMQ_CONF_PATH "NANOMQ_CONF_PATH" + +#define NANOMQ_VIN "NANOMQ_VIN" +#define NANOMQ_PID_FILE "NANOMQ_PID_FILE" + +NNG_DECL void read_env_conf(conf *config); +NNG_DECL char *read_env_vin(); +NNG_DECL char *read_env_pid_file(); + +#endif \ No newline at end of file diff --git a/VNode/_software_lib/nanomq-0.22.10/include/nng/supplemental/nanolib/file.h b/VNode/_software_lib/nanomq-0.22.10/include/nng/supplemental/nanolib/file.h new file mode 100644 index 00000000..2bc0b84f --- /dev/null +++ b/VNode/_software_lib/nanomq-0.22.10/include/nng/supplemental/nanolib/file.h @@ -0,0 +1,18 @@ +#ifndef NANO_FILE_H +#define NANO_FILE_H + +#include +#include +#include +#include "nng/nng.h" + +NNG_DECL bool nano_file_exists(const char *fpath); +NNG_DECL char * nano_getcwd(char *buf, size_t size); +NNG_DECL int64_t nano_getline( + char **restrict line, size_t *restrict len, FILE *restrict fp); +NNG_DECL char * nano_concat_path(const char *dir, const char *file_name); +NNG_DECL int file_write_string(const char *fpath, const char *string); +NNG_DECL int file_create_dir(const char *fpath); +NNG_DECL size_t file_load_data(const char *filepath, void **data); + +#endif diff --git a/VNode/_software_lib/nanomq-0.22.10/include/nng/supplemental/nanolib/hash_table.h b/VNode/_software_lib/nanomq-0.22.10/include/nng/supplemental/nanolib/hash_table.h new file mode 100644 index 00000000..25d74d2b --- /dev/null +++ b/VNode/_software_lib/nanomq-0.22.10/include/nng/supplemental/nanolib/hash_table.h @@ -0,0 +1,121 @@ +#ifndef HASH_TABLE_H +#define HASH_TABLE_H + +#include "cvector.h" +#include +#include +#include "nng/nng.h" +#include "nng/mqtt/packet.h" + +struct topic_queue { + uint8_t qos; + char *topic; + struct topic_queue *next; +}; + +typedef struct topic_queue topic_queue; + +struct msg_queue { + char * msg; + struct msg_queue *next; +}; + +typedef struct msg_queue msg_queue; + +// atpair is alias topic pair +typedef struct dbhash_atpair_s dbhash_atpair_t; + +struct dbhash_atpair_s { + uint32_t alias; + char * topic; +}; + +typedef struct dbhash_ptpair_s dbhash_ptpair_t; + +// ptpair is pipe topic pair +struct dbhash_ptpair_s { + uint32_t pipe; + char * topic; +}; + +/** + * @brief alias_cmp - A callback to compare different alias + * @param x - normally x is pointer of dbhash_atpair_t + * @param y - normally y is pointer of alias + * @return 0, minus or plus + */ +static inline int +alias_cmp(void *x_, void *y_) +{ + uint32_t * alias = (uint32_t *) y_; + dbhash_atpair_t *ele_x = (dbhash_atpair_t *) x_; + return *alias - ele_x->alias; +} + +NNG_DECL void dbhash_init_alias_table(void); + +NNG_DECL void dbhash_destroy_alias_table(void); +// This function do not verify value of alias and topic, +// therefore you should make sure alias and topic is +// not illegal. +NNG_DECL void dbhash_insert_atpair(uint32_t pipe_id, uint32_t alias, const char *topic); + +NNG_DECL const char *dbhash_find_atpair(uint32_t pipe_id, uint32_t alias); + +NNG_DECL void dbhash_del_atpair_queue(uint32_t pipe_id); + +NNG_DECL void dbhash_init_pipe_table(void); + +NNG_DECL void dbhash_destroy_pipe_table(void); + +NNG_DECL void dbhash_insert_topic(uint32_t id, char *val, uint8_t qos); + +NNG_DECL bool dbhash_check_topic(uint32_t id, char *val); + +NNG_DECL char *dbhash_get_first_topic(uint32_t id); + +NNG_DECL topic_queue *topic_queue_init(char *topic, int topic_len); + +NNG_DECL void topic_queue_release(topic_queue *tq); + +NNG_DECL topic_queue *init_topic_queue_with_topic_node(topic_node *tn); + +NNG_DECL struct topic_queue *dbhash_get_topic_queue(uint32_t id); + +NNG_DECL struct topic_queue *dbhash_copy_topic_queue(uint32_t id); + +NNG_DECL void dbhash_del_topic(uint32_t id, char *topic); + +NNG_DECL void *dbhash_del_topic_queue( + uint32_t id, void *(*cb)(void *, char *), void *args); + +NNG_DECL bool dbhash_check_id(uint32_t id); + +NNG_DECL void *dbhash_check_id_and_do(uint32_t id, void *(*cb)(void *), void *arg); + +NNG_DECL void dbhash_print_topic_queue(uint32_t id); + +NNG_DECL topic_queue **dbhash_get_topic_queue_all(size_t *sz); + +NNG_DECL dbhash_ptpair_t *dbhash_ptpair_alloc(uint32_t p, char *t); + +NNG_DECL void dbhash_ptpair_free(dbhash_ptpair_t *pt); + +NNG_DECL dbhash_ptpair_t **dbhash_get_ptpair_all(void); + +NNG_DECL size_t dbhash_get_pipe_cnt(void); + +NNG_DECL void dbhash_init_cached_table(void); +NNG_DECL void dbhash_destroy_cached_table(void); + +NNG_DECL void dbhash_cache_topic_all(uint32_t pid, uint32_t cid); + +NNG_DECL void dbhash_restore_topic_all(uint32_t cid, uint32_t pid); + +NNG_DECL struct topic_queue *dbhash_get_cached_topic(uint32_t cid); + +NNG_DECL void dbhash_del_cached_topic_all(uint32_t key); + +NNG_DECL bool dbhash_cached_check_id(uint32_t key); + +#endif diff --git a/VNode/_software_lib/nanomq-0.22.10/include/nng/supplemental/nanolib/hocon.h b/VNode/_software_lib/nanomq-0.22.10/include/nng/supplemental/nanolib/hocon.h new file mode 100644 index 00000000..20750c5d --- /dev/null +++ b/VNode/_software_lib/nanomq-0.22.10/include/nng/supplemental/nanolib/hocon.h @@ -0,0 +1,9 @@ +#ifndef HOCON_H +#define HOCON_H +#include "cJSON.h" + +cJSON *hocon_parse_file(const char *file); +cJSON *hocon_parse_str(char *str, size_t len); + + +#endif \ No newline at end of file diff --git a/VNode/_software_lib/nanomq-0.22.10/include/nng/supplemental/nanolib/khash.h b/VNode/_software_lib/nanomq-0.22.10/include/nng/supplemental/nanolib/khash.h new file mode 100644 index 00000000..f75f3474 --- /dev/null +++ b/VNode/_software_lib/nanomq-0.22.10/include/nng/supplemental/nanolib/khash.h @@ -0,0 +1,627 @@ +/* The MIT License + + Copyright (c) 2008, 2009, 2011 by Attractive Chaos + + 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. +*/ + +/* + An example: + +#include "khash.h" +KHASH_MAP_INIT_INT(32, char) +int main() { + int ret, is_missing; + khiter_t k; + khash_t(32) *h = kh_init(32); + k = kh_put(32, h, 5, &ret); + kh_value(h, k) = 10; + k = kh_get(32, h, 10); + is_missing = (k == kh_end(h)); + k = kh_get(32, h, 5); + kh_del(32, h, k); + for (k = kh_begin(h); k != kh_end(h); ++k) + if (kh_exist(h, k)) kh_value(h, k) = 1; + kh_destroy(32, h); + return 0; +} +*/ + +/* + 2013-05-02 (0.2.8): + + * Use quadratic probing. When the capacity is power of 2, stepping function + i*(i+1)/2 guarantees to traverse each bucket. It is better than double + hashing on cache performance and is more robust than linear probing. + + In theory, double hashing should be more robust than quadratic probing. + However, my implementation is probably not for large hash tables, because + the second hash function is closely tied to the first hash function, + which reduce the effectiveness of double hashing. + + Reference: http://research.cs.vt.edu/AVresearch/hashing/quadratic.php + + 2011-12-29 (0.2.7): + + * Minor code clean up; no actual effect. + + 2011-09-16 (0.2.6): + + * The capacity is a power of 2. This seems to dramatically improve the + speed for simple keys. Thank Zilong Tan for the suggestion. Reference: + + - http://code.google.com/p/ulib/ + - http://nothings.org/computer/judy/ + + * Allow to optionally use linear probing which usually has better + performance for random input. Double hashing is still the default as it + is more robust to certain non-random input. + + * Added Wang's integer hash function (not used by default). This hash + function is more robust to certain non-random input. + + 2011-02-14 (0.2.5): + + * Allow to declare global functions. + + 2009-09-26 (0.2.4): + + * Improve portability + + 2008-09-19 (0.2.3): + + * Corrected the example + * Improved interfaces + + 2008-09-11 (0.2.2): + + * Improved speed a little in kh_put() + + 2008-09-10 (0.2.1): + + * Added kh_clear() + * Fixed a compiling error + + 2008-09-02 (0.2.0): + + * Changed to token concatenation which increases flexibility. + + 2008-08-31 (0.1.2): + + * Fixed a bug in kh_get(), which has not been tested previously. + + 2008-08-31 (0.1.1): + + * Added destructor +*/ + + +#ifndef __AC_KHASH_H +#define __AC_KHASH_H + +/*! + @header + + Generic hash table library. + */ + +#define AC_VERSION_KHASH_H "0.2.8" + +#include +#include +#include + +/* compiler specific configuration */ + +#if UINT_MAX == 0xffffffffu +typedef unsigned int khint32_t; +#elif ULONG_MAX == 0xffffffffu +typedef unsigned long khint32_t; +#endif + +#if ULONG_MAX == ULLONG_MAX +typedef unsigned long khint64_t; +#else +typedef unsigned long long khint64_t; +#endif + +#ifndef kh_inline +#ifdef _MSC_VER +#define kh_inline __inline +#else +#define kh_inline inline +#endif +#endif /* kh_inline */ + +#ifndef klib_unused +#if (defined __clang__ && __clang_major__ >= 3) || (defined __GNUC__ && __GNUC__ >= 3) +#define klib_unused __attribute__ ((__unused__)) +#else +#define klib_unused +#endif +#endif /* klib_unused */ + +typedef khint32_t khint_t; +typedef khint_t khiter_t; + +#define __ac_isempty(flag, i) ((flag[i>>4]>>((i&0xfU)<<1))&2) +#define __ac_isdel(flag, i) ((flag[i>>4]>>((i&0xfU)<<1))&1) +#define __ac_iseither(flag, i) ((flag[i>>4]>>((i&0xfU)<<1))&3) +#define __ac_set_isdel_false(flag, i) (flag[i>>4]&=~(1ul<<((i&0xfU)<<1))) +#define __ac_set_isempty_false(flag, i) (flag[i>>4]&=~(2ul<<((i&0xfU)<<1))) +#define __ac_set_isboth_false(flag, i) (flag[i>>4]&=~(3ul<<((i&0xfU)<<1))) +#define __ac_set_isdel_true(flag, i) (flag[i>>4]|=1ul<<((i&0xfU)<<1)) + +#define __ac_fsize(m) ((m) < 16? 1 : (m)>>4) + +#ifndef kroundup32 +#define kroundup32(x) (--(x), (x)|=(x)>>1, (x)|=(x)>>2, (x)|=(x)>>4, (x)|=(x)>>8, (x)|=(x)>>16, ++(x)) +#endif + +#ifndef kcalloc +#define kcalloc(N,Z) calloc(N,Z) +#endif +#ifndef kmalloc +#define kmalloc(Z) malloc(Z) +#endif +#ifndef krealloc +#define krealloc(P,Z) realloc(P,Z) +#endif +#ifndef kfree +#define kfree(P) free(P) +#endif + +static const double __ac_HASH_UPPER = 0.77; + +#define __KHASH_TYPE(name, khkey_t, khval_t) \ + typedef struct kh_##name##_s { \ + khint_t n_buckets, size, n_occupied, upper_bound; \ + khint32_t *flags; \ + khkey_t *keys; \ + khval_t *vals; \ + } kh_##name##_t; + +#define __KHASH_PROTOTYPES(name, khkey_t, khval_t) \ + extern kh_##name##_t *kh_init_##name(void); \ + extern void kh_destroy_##name(kh_##name##_t *h); \ + extern void kh_clear_##name(kh_##name##_t *h); \ + extern khint_t kh_get_##name(const kh_##name##_t *h, khkey_t key); \ + extern int kh_resize_##name(kh_##name##_t *h, khint_t new_n_buckets); \ + extern khint_t kh_put_##name(kh_##name##_t *h, khkey_t key, int *ret); \ + extern void kh_del_##name(kh_##name##_t *h, khint_t x); + +#define __KHASH_IMPL(name, SCOPE, khkey_t, khval_t, kh_is_map, __hash_func, __hash_equal) \ + SCOPE kh_##name##_t *kh_init_##name(void) { \ + return (kh_##name##_t*)kcalloc(1, sizeof(kh_##name##_t)); \ + } \ + SCOPE void kh_destroy_##name(kh_##name##_t *h) \ + { \ + if (h) { \ + kfree((void *)h->keys); kfree(h->flags); \ + kfree((void *)h->vals); \ + kfree(h); \ + } \ + } \ + SCOPE void kh_clear_##name(kh_##name##_t *h) \ + { \ + if (h && h->flags) { \ + memset(h->flags, 0xaa, __ac_fsize(h->n_buckets) * sizeof(khint32_t)); \ + h->size = h->n_occupied = 0; \ + } \ + } \ + SCOPE khint_t kh_get_##name(const kh_##name##_t *h, khkey_t key) \ + { \ + if (h->n_buckets) { \ + khint_t k, i, last, mask, step = 0; \ + mask = h->n_buckets - 1; \ + k = __hash_func(key); i = k & mask; \ + last = i; \ + while (!__ac_isempty(h->flags, i) && (__ac_isdel(h->flags, i) || !__hash_equal(h->keys[i], key))) { \ + i = (i + (++step)) & mask; \ + if (i == last) return h->n_buckets; \ + } \ + return __ac_iseither(h->flags, i)? h->n_buckets : i; \ + } else return 0; \ + } \ + SCOPE int kh_resize_##name(kh_##name##_t *h, khint_t new_n_buckets) \ + { /* This function uses 0.25*n_buckets bytes of working space instead of [sizeof(key_t+val_t)+.25]*n_buckets. */ \ + khint32_t *new_flags = 0; \ + khint_t j = 1; \ + { \ + kroundup32(new_n_buckets); \ + if (new_n_buckets < 4) new_n_buckets = 4; \ + if (h->size >= (khint_t)(new_n_buckets * __ac_HASH_UPPER + 0.5)) j = 0; /* requested size is too small */ \ + else { /* hash table size to be changed (shrink or expand); rehash */ \ + new_flags = (khint32_t*)kmalloc(__ac_fsize(new_n_buckets) * sizeof(khint32_t)); \ + if (!new_flags) return -1; \ + memset(new_flags, 0xaa, __ac_fsize(new_n_buckets) * sizeof(khint32_t)); \ + if (h->n_buckets < new_n_buckets) { /* expand */ \ + khkey_t *new_keys = (khkey_t*)krealloc((void *)h->keys, new_n_buckets * sizeof(khkey_t)); \ + if (!new_keys) { kfree(new_flags); return -1; } \ + h->keys = new_keys; \ + if (kh_is_map) { \ + khval_t *new_vals = (khval_t*)krealloc((void *)h->vals, new_n_buckets * sizeof(khval_t)); \ + if (!new_vals) { kfree(new_flags); return -1; } \ + h->vals = new_vals; \ + } \ + } /* otherwise shrink */ \ + } \ + } \ + if (j) { /* rehashing is needed */ \ + for (j = 0; j != h->n_buckets; ++j) { \ + if (__ac_iseither(h->flags, j) == 0) { \ + khkey_t key = h->keys[j]; \ + khval_t val; \ + khint_t new_mask; \ + new_mask = new_n_buckets - 1; \ + if (kh_is_map) val = h->vals[j]; \ + __ac_set_isdel_true(h->flags, j); \ + while (1) { /* kick-out process; sort of like in Cuckoo hashing */ \ + khint_t k, i, step = 0; \ + k = __hash_func(key); \ + i = k & new_mask; \ + while (!__ac_isempty(new_flags, i)) i = (i + (++step)) & new_mask; \ + __ac_set_isempty_false(new_flags, i); \ + if (i < h->n_buckets && __ac_iseither(h->flags, i) == 0) { /* kick out the existing element */ \ + { khkey_t tmp = h->keys[i]; h->keys[i] = key; key = tmp; } \ + if (kh_is_map) { khval_t tmp = h->vals[i]; h->vals[i] = val; val = tmp; } \ + __ac_set_isdel_true(h->flags, i); /* mark it as deleted in the old hash table */ \ + } else { /* write the element and jump out of the loop */ \ + h->keys[i] = key; \ + if (kh_is_map) h->vals[i] = val; \ + break; \ + } \ + } \ + } \ + } \ + if (h->n_buckets > new_n_buckets) { /* shrink the hash table */ \ + h->keys = (khkey_t*)krealloc((void *)h->keys, new_n_buckets * sizeof(khkey_t)); \ + if (kh_is_map) h->vals = (khval_t*)krealloc((void *)h->vals, new_n_buckets * sizeof(khval_t)); \ + } \ + kfree(h->flags); /* free the working space */ \ + h->flags = new_flags; \ + h->n_buckets = new_n_buckets; \ + h->n_occupied = h->size; \ + h->upper_bound = (khint_t)(h->n_buckets * __ac_HASH_UPPER + 0.5); \ + } \ + return 0; \ + } \ + SCOPE khint_t kh_put_##name(kh_##name##_t *h, khkey_t key, int *ret) \ + { \ + khint_t x; \ + if (h->n_occupied >= h->upper_bound) { /* update the hash table */ \ + if (h->n_buckets > (h->size<<1)) { \ + if (kh_resize_##name(h, h->n_buckets - 1) < 0) { /* clear "deleted" elements */ \ + *ret = -1; return h->n_buckets; \ + } \ + } else if (kh_resize_##name(h, h->n_buckets + 1) < 0) { /* expand the hash table */ \ + *ret = -1; return h->n_buckets; \ + } \ + } /* TODO: to implement automatically shrinking; resize() already support shrinking */ \ + { \ + khint_t k, i, site, last, mask = h->n_buckets - 1, step = 0; \ + x = site = h->n_buckets; k = __hash_func(key); i = k & mask; \ + if (__ac_isempty(h->flags, i)) x = i; /* for speed up */ \ + else { \ + last = i; \ + while (!__ac_isempty(h->flags, i) && (__ac_isdel(h->flags, i) || !__hash_equal(h->keys[i], key))) { \ + if (__ac_isdel(h->flags, i)) site = i; \ + i = (i + (++step)) & mask; \ + if (i == last) { x = site; break; } \ + } \ + if (x == h->n_buckets) { \ + if (__ac_isempty(h->flags, i) && site != h->n_buckets) x = site; \ + else x = i; \ + } \ + } \ + } \ + if (__ac_isempty(h->flags, x)) { /* not present at all */ \ + h->keys[x] = key; \ + __ac_set_isboth_false(h->flags, x); \ + ++h->size; ++h->n_occupied; \ + *ret = 1; \ + } else if (__ac_isdel(h->flags, x)) { /* deleted */ \ + h->keys[x] = key; \ + __ac_set_isboth_false(h->flags, x); \ + ++h->size; \ + *ret = 2; \ + } else *ret = 0; /* Don't touch h->keys[x] if present and not deleted */ \ + return x; \ + } \ + SCOPE void kh_del_##name(kh_##name##_t *h, khint_t x) \ + { \ + if (x != h->n_buckets && !__ac_iseither(h->flags, x)) { \ + __ac_set_isdel_true(h->flags, x); \ + --h->size; \ + } \ + } + +#define KHASH_DECLARE(name, khkey_t, khval_t) \ + __KHASH_TYPE(name, khkey_t, khval_t) \ + __KHASH_PROTOTYPES(name, khkey_t, khval_t) + +#define KHASH_INIT2(name, SCOPE, khkey_t, khval_t, kh_is_map, __hash_func, __hash_equal) \ + __KHASH_TYPE(name, khkey_t, khval_t) \ + __KHASH_IMPL(name, SCOPE, khkey_t, khval_t, kh_is_map, __hash_func, __hash_equal) + +#define KHASH_INIT(name, khkey_t, khval_t, kh_is_map, __hash_func, __hash_equal) \ + KHASH_INIT2(name, static kh_inline klib_unused, khkey_t, khval_t, kh_is_map, __hash_func, __hash_equal) + +/* --- BEGIN OF HASH FUNCTIONS --- */ + +/*! @function + @abstract Integer hash function + @param key The integer [khint32_t] + @return The hash value [khint_t] + */ +#define kh_int_hash_func(key) (khint32_t)(key) +/*! @function + @abstract Integer comparison function + */ +#define kh_int_hash_equal(a, b) ((a) == (b)) +/*! @function + @abstract 64-bit integer hash function + @param key The integer [khint64_t] + @return The hash value [khint_t] + */ +#define kh_int64_hash_func(key) (khint32_t)((key)>>33^(key)^(key)<<11) +/*! @function + @abstract 64-bit integer comparison function + */ +#define kh_int64_hash_equal(a, b) ((a) == (b)) +/*! @function + @abstract const char* hash function + @param s Pointer to a null terminated string + @return The hash value + */ +static kh_inline khint_t __ac_X31_hash_string(const char *s) +{ + khint_t h = (khint_t)*s; + if (h) for (++s ; *s; ++s) h = (h << 5) - h + (khint_t)*s; + return h; +} +/*! @function + @abstract Another interface to const char* hash function + @param key Pointer to a null terminated string [const char*] + @return The hash value [khint_t] + */ +#define kh_str_hash_func(key) __ac_X31_hash_string(key) +/*! @function + @abstract Const char* comparison function + */ +#define kh_str_hash_equal(a, b) (strcmp(a, b) == 0) + +static kh_inline khint_t __ac_Wang_hash(khint_t key) +{ + key += ~(key << 15); + key ^= (key >> 10); + key += (key << 3); + key ^= (key >> 6); + key += ~(key << 11); + key ^= (key >> 16); + return key; +} +#define kh_int_hash_func2(key) __ac_Wang_hash((khint_t)key) + +/* --- END OF HASH FUNCTIONS --- */ + +/* Other convenient macros... */ + +/*! + @abstract Type of the hash table. + @param name Name of the hash table [symbol] + */ +#define khash_t(name) kh_##name##_t + +/*! @function + @abstract Initiate a hash table. + @param name Name of the hash table [symbol] + @return Pointer to the hash table [khash_t(name)*] + */ +#define kh_init(name) kh_init_##name() + +/*! @function + @abstract Destroy a hash table. + @param name Name of the hash table [symbol] + @param h Pointer to the hash table [khash_t(name)*] + */ +#define kh_destroy(name, h) kh_destroy_##name(h) + +/*! @function + @abstract Reset a hash table without deallocating memory. + @param name Name of the hash table [symbol] + @param h Pointer to the hash table [khash_t(name)*] + */ +#define kh_clear(name, h) kh_clear_##name(h) + +/*! @function + @abstract Resize a hash table. + @param name Name of the hash table [symbol] + @param h Pointer to the hash table [khash_t(name)*] + @param s New size [khint_t] + */ +#define kh_resize(name, h, s) kh_resize_##name(h, s) + +/*! @function + @abstract Insert a key to the hash table. + @param name Name of the hash table [symbol] + @param h Pointer to the hash table [khash_t(name)*] + @param k Key [type of keys] + @param r Extra return code: -1 if the operation failed; + 0 if the key is present in the hash table; + 1 if the bucket is empty (never used); 2 if the element in + the bucket has been deleted [int*] + @return Iterator to the inserted element [khint_t] + */ +#define kh_put(name, h, k, r) kh_put_##name(h, k, r) + +/*! @function + @abstract Retrieve a key from the hash table. + @param name Name of the hash table [symbol] + @param h Pointer to the hash table [khash_t(name)*] + @param k Key [type of keys] + @return Iterator to the found element, or kh_end(h) if the element is absent [khint_t] + */ +#define kh_get(name, h, k) kh_get_##name(h, k) + +/*! @function + @abstract Remove a key from the hash table. + @param name Name of the hash table [symbol] + @param h Pointer to the hash table [khash_t(name)*] + @param k Iterator to the element to be deleted [khint_t] + */ +#define kh_del(name, h, k) kh_del_##name(h, k) + +/*! @function + @abstract Test whether a bucket contains data. + @param h Pointer to the hash table [khash_t(name)*] + @param x Iterator to the bucket [khint_t] + @return 1 if containing data; 0 otherwise [int] + */ +#define kh_exist(h, x) (!__ac_iseither((h)->flags, (x))) + +/*! @function + @abstract Get key given an iterator + @param h Pointer to the hash table [khash_t(name)*] + @param x Iterator to the bucket [khint_t] + @return Key [type of keys] + */ +#define kh_key(h, x) ((h)->keys[x]) + +/*! @function + @abstract Get value given an iterator + @param h Pointer to the hash table [khash_t(name)*] + @param x Iterator to the bucket [khint_t] + @return Value [type of values] + @discussion For hash sets, calling this results in segfault. + */ +#define kh_val(h, x) ((h)->vals[x]) + +/*! @function + @abstract Alias of kh_val() + */ +#define kh_value(h, x) ((h)->vals[x]) + +/*! @function + @abstract Get the start iterator + @param h Pointer to the hash table [khash_t(name)*] + @return The start iterator [khint_t] + */ +#define kh_begin(h) (khint_t)(0) + +/*! @function + @abstract Get the end iterator + @param h Pointer to the hash table [khash_t(name)*] + @return The end iterator [khint_t] + */ +#define kh_end(h) ((h)->n_buckets) + +/*! @function + @abstract Get the number of elements in the hash table + @param h Pointer to the hash table [khash_t(name)*] + @return Number of elements in the hash table [khint_t] + */ +#define kh_size(h) ((h)->size) + +/*! @function + @abstract Get the number of buckets in the hash table + @param h Pointer to the hash table [khash_t(name)*] + @return Number of buckets in the hash table [khint_t] + */ +#define kh_n_buckets(h) ((h)->n_buckets) + +/*! @function + @abstract Iterate over the entries in the hash table + @param h Pointer to the hash table [khash_t(name)*] + @param kvar Variable to which key will be assigned + @param vvar Variable to which value will be assigned + @param code Block of code to execute + */ +#define kh_foreach(h, kvar, vvar, code) { khint_t __i; \ + for (__i = kh_begin(h); __i != kh_end(h); ++__i) { \ + if (!kh_exist(h,__i)) continue; \ + (kvar) = kh_key(h,__i); \ + (vvar) = kh_val(h,__i); \ + code; \ + } } + +/*! @function + @abstract Iterate over the values in the hash table + @param h Pointer to the hash table [khash_t(name)*] + @param vvar Variable to which value will be assigned + @param code Block of code to execute + */ +#define kh_foreach_value(h, vvar, code) { khint_t __i; \ + for (__i = kh_begin(h); __i != kh_end(h); ++__i) { \ + if (!kh_exist(h,__i)) continue; \ + (vvar) = kh_val(h,__i); \ + code; \ + } } + +/* More convenient interfaces */ + +/*! @function + @abstract Instantiate a hash set containing integer keys + @param name Name of the hash table [symbol] + */ +#define KHASH_SET_INIT_INT(name) \ + KHASH_INIT(name, khint32_t, char, 0, kh_int_hash_func, kh_int_hash_equal) + +/*! @function + @abstract Instantiate a hash map containing integer keys + @param name Name of the hash table [symbol] + @param khval_t Type of values [type] + */ +#define KHASH_MAP_INIT_INT(name, khval_t) \ + KHASH_INIT(name, khint32_t, khval_t, 1, kh_int_hash_func, kh_int_hash_equal) + +/*! @function + @abstract Instantiate a hash set containing 64-bit integer keys + @param name Name of the hash table [symbol] + */ +#define KHASH_SET_INIT_INT64(name) \ + KHASH_INIT(name, khint64_t, char, 0, kh_int64_hash_func, kh_int64_hash_equal) + +/*! @function + @abstract Instantiate a hash map containing 64-bit integer keys + @param name Name of the hash table [symbol] + @param khval_t Type of values [type] + */ +#define KHASH_MAP_INIT_INT64(name, khval_t) \ + KHASH_INIT(name, khint64_t, khval_t, 1, kh_int64_hash_func, kh_int64_hash_equal) + +typedef const char *kh_cstr_t; +/*! @function + @abstract Instantiate a hash map containing const char* keys + @param name Name of the hash table [symbol] + */ +#define KHASH_SET_INIT_STR(name) \ + KHASH_INIT(name, kh_cstr_t, char, 0, kh_str_hash_func, kh_str_hash_equal) + +/*! @function + @abstract Instantiate a hash map containing const char* keys + @param name Name of the hash table [symbol] + @param khval_t Type of values [type] + */ +#define KHASH_MAP_INIT_STR(name, khval_t) \ + KHASH_INIT(name, kh_cstr_t, khval_t, 1, kh_str_hash_func, kh_str_hash_equal) + +#endif /* __AC_KHASH_H */ diff --git a/VNode/_software_lib/nanomq-0.22.10/include/nng/supplemental/nanolib/linkedlist.h b/VNode/_software_lib/nanomq-0.22.10/include/nng/supplemental/nanolib/linkedlist.h new file mode 100644 index 00000000..18c14323 --- /dev/null +++ b/VNode/_software_lib/nanomq-0.22.10/include/nng/supplemental/nanolib/linkedlist.h @@ -0,0 +1,33 @@ +#include +#include + +struct linkedListNode { + void *data; + unsigned long long expiredAt; + struct linkedListNode *next; + struct linkedListNode *prev; +}; + +struct linkedList { + unsigned int cap; + unsigned int size; + unsigned int overWrite; + unsigned long long expiredAt; + + struct linkedListNode *head; + struct linkedListNode *tail; +}; + +int linkedList_replace_head(struct linkedList *list, + void *data, + unsigned long long expiredAt); +int linkedList_init(struct linkedList **list, + unsigned int cap, + unsigned int overWrite, + unsigned long long expiredAt); +int linkedList_enqueue(struct linkedList *list, + void *data, + unsigned long long expiredAt); +int linkedList_dequeue(struct linkedList *list, + void **data); +int linkedList_release(struct linkedList *list); diff --git a/VNode/_software_lib/nanomq-0.22.10/include/nng/supplemental/nanolib/log.h b/VNode/_software_lib/nanomq-0.22.10/include/nng/supplemental/nanolib/log.h new file mode 100644 index 00000000..3d4a3af6 --- /dev/null +++ b/VNode/_software_lib/nanomq-0.22.10/include/nng/supplemental/nanolib/log.h @@ -0,0 +1,111 @@ +#ifndef NNG_NANOLIB_LOG_H +#define NNG_NANOLIB_LOG_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include +#include +#include +#include + +#include "nng/nng.h" + +#define LOG_VERSION "0.2.1" + +/** + * 2023-12-08 move conf_log to log.h +*/ + +// log type +#define LOG_TO_FILE (1 << 0) +#define LOG_TO_CONSOLE (1 << 1) +#define LOG_TO_SYSLOG (1 << 2) +#define LOG_TO_UDS (1 << 3) + +typedef struct conf_log conf_log; +struct conf_log { + uint8_t type; + int level; + char *dir; + char *file; + char *uds_addr; + FILE *fp; + char *abs_path; // absolut path of log file + char *rotation_sz_str; // 1000KB, 100MB, 10GB + uint64_t rotation_sz; // unit: byte + size_t rotation_count; // rotation count +}; + +typedef struct { + va_list ap; + const char *fmt; + const char *file; + const char *func; + struct tm time; + void * udata; + int line; + int level; + conf_log * config; +} log_event; + +typedef void (*log_func)(log_event *ev); + +enum { + NNG_LOG_FATAL = 0, + NNG_LOG_ERROR, + NNG_LOG_WARN, + NNG_LOG_INFO, + NNG_LOG_DEBUG, + NNG_LOG_TRACE, +}; + +NNG_DECL const char *log_level_string(int level); +NNG_DECL int log_level_num(const char *level); +NNG_DECL void log_set_level(int level); +NNG_DECL int log_add_callback( + log_func fn, void *udata, int level, void *mtx, conf_log *config); +NNG_DECL void log_add_console(int level, void *mtx); +NNG_DECL int log_add_fp(FILE *fp, int level, void *mtx, conf_log *config); +NNG_DECL void log_add_syslog(const char *log_name, uint8_t level, void *mtx); +NNG_DECL void log_add_uds(const char *uds_path, const char *log_name, uint8_t level, void *mtx); +NNG_DECL void uds_closelog(void); +NNG_DECL void log_log(int level, const char *file, int line, const char *func, + const char *fmt, ...); +NNG_DECL void log_clear_callback(); +#ifdef ENABLE_LOG + +#define log_trace(...) \ + log_log(NNG_LOG_TRACE, __FILE__, __LINE__, __FUNCTION__, __VA_ARGS__) +#define log_debug(...) \ + log_log(NNG_LOG_DEBUG, __FILE__, __LINE__, __FUNCTION__, __VA_ARGS__) +#define log_info(...) \ + log_log(NNG_LOG_INFO, __FILE__, __LINE__, __FUNCTION__, __VA_ARGS__) +#define log_warn(...) \ + log_log(NNG_LOG_WARN, __FILE__, __LINE__, __FUNCTION__, __VA_ARGS__) +#define log_error(...) \ + log_log(NNG_LOG_ERROR, __FILE__, __LINE__, __FUNCTION__, __VA_ARGS__) +#define log_fatal(...) \ + log_log(NNG_LOG_FATAL, __FILE__, __LINE__, __FUNCTION__, __VA_ARGS__) + +#else + +static inline void dummy_log_function(const char *fmt, ...) { (void)fmt; } + +#define log_trace(...) dummy_log_function(__VA_ARGS__) +#define log_debug(...) dummy_log_function(__VA_ARGS__) +#define log_info(...) dummy_log_function(__VA_ARGS__) +#define log_warn(...) dummy_log_function(__VA_ARGS__) +#define log_error(...) dummy_log_function(__VA_ARGS__) +#define log_fatal(...) dummy_log_function(__VA_ARGS__) + +#endif + + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/VNode/_software_lib/nanomq-0.22.10/include/nng/supplemental/nanolib/md5.h b/VNode/_software_lib/nanomq-0.22.10/include/nng/supplemental/nanolib/md5.h new file mode 100644 index 00000000..2d367447 --- /dev/null +++ b/VNode/_software_lib/nanomq-0.22.10/include/nng/supplemental/nanolib/md5.h @@ -0,0 +1,77 @@ +#ifndef NANOLIB_MD5_H +#define NANOLIB_MD5_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include +#include +#if defined(__WINDOWS__) || defined(WIN32) || defined(WIN64) || defined(_MSC_VER) || defined(_WIN32) +#else +#include +#endif +#include +#include +#include + +#define READ_DATA_SIZE 1024 +#define MD5_SIZE 16 +#define MD5_STR_LEN (MD5_SIZE * 2) +#define MD5_LEN 32 + +typedef struct +{ + unsigned int count[2]; + unsigned int state[4]; + unsigned char buffer[64]; +} MD5_CTX; + + +#define F(x,y,z) ((x & y) | (~x & z)) +#define G(x,y,z) ((x & z) | (y & ~z)) +#define H(x,y,z) (x^y^z) +#define I(x,y,z) (y ^ (x | ~z)) +#define ROTATE_LEFT(x,n) ((x << n) | (x >> (32-n))) + +#define FF(a,b,c,d,x,s,ac) \ +{ \ + a += F(b,c,d) + x + ac; \ + a = ROTATE_LEFT(a,s); \ + a += b; \ +} +#define GG(a,b,c,d,x,s,ac) \ +{ \ + a += G(b,c,d) + x + ac; \ + a = ROTATE_LEFT(a,s); \ + a += b; \ +} +#define HH(a,b,c,d,x,s,ac) \ +{ \ + a += H(b,c,d) + x + ac; \ + a = ROTATE_LEFT(a,s); \ + a += b; \ +} +#define II(a,b,c,d,x,s,ac) \ +{ \ + a += I(b,c,d) + x + ac; \ + a = ROTATE_LEFT(a,s); \ + a += b; \ +} + +int ComputeStringMD5(unsigned char *dest_str, unsigned int dest_len, char *md5_str); +int ComputeFileMD5(const char *file_path, char *md5_str); + +void MD5Init(MD5_CTX *context); +void MD5Update(MD5_CTX *context, unsigned char *input, unsigned int inputlen); +void MD5Final(MD5_CTX *context, unsigned char digest[16]); +void MD5Transform(unsigned int state[4], unsigned char block[64]); +void MD5Encode(unsigned char *output, unsigned int *input, unsigned int len); +void MD5Decode(unsigned int *output, unsigned char *input, unsigned int len); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/VNode/_software_lib/nanomq-0.22.10/include/nng/supplemental/nanolib/mqtt_db.h b/VNode/_software_lib/nanomq-0.22.10/include/nng/supplemental/nanolib/mqtt_db.h new file mode 100644 index 00000000..67762317 --- /dev/null +++ b/VNode/_software_lib/nanomq-0.22.10/include/nng/supplemental/nanolib/mqtt_db.h @@ -0,0 +1,138 @@ +#ifndef MQTT_DB_H +#define MQTT_DB_H + +#include "cvector.h" +#include +#include +#include +#include "nng/nng.h" + + +typedef enum { + MQTT_VERSION_V311 = 4, + MQTT_VERSION_V5 = 5, +} mqtt_version_t; + +typedef struct dbtree dbtree; + +typedef struct { + char * topic; + char **clients; + int cld_cnt; +} dbtree_info; + +/** + * @brief dbtree_create - Create a dbtree. + * @param dbtree - dbtree + * @return void + */ +NNG_DECL void dbtree_create(dbtree **db); + +/** + * @brief dbtree_destory - Destory dbtree tree + * @param dbtree - dbtree + * @return void + */ +NNG_DECL void dbtree_destory(dbtree *db); + +/** + * @brief dbtree_print - Print dbtree for debug. + * @param dbtree - dbtree + * @return void + */ +NNG_DECL void dbtree_print(dbtree *db); + +/** + * @brief dbtree_insert_client - check if this + * topic and pipe id is exist on the tree, if + * there is not exist, this func will insert node + * recursively until find all topic then insert + * client on the node. + * @param dbtree - dbtree_node + * @param topic - topic + * @param pipe_id - pipe id + * @return + */ +NNG_DECL void *dbtree_insert_client( + dbtree *db, char *topic, uint32_t pipe_id); + +/** + * @brief dbtree_find_client - check if this + * topic and pipe id is exist on the tree, if + * there is not exist, return it. + * @param dbtree - dbtree_node + * @param topic - topic + * @param ctxt - data related with pipe_id + * @param pipe_id - pipe id + * @return + */ +// void *dbtree_find_client(dbtree *db, char *topic, uint32_t pipe_id); + +/** + * @brief dbtree_delete_client - This function will + * be called when disconnection and cleansession = 1. + * check if this topic and client id is exist on the + * tree, if there is exist, this func will delete + * related node and client on the tree + * @param dbtree - dbtree + * @param topic - topic + * @param pipe_id - pipe id + * @return + */ +NNG_DECL void *dbtree_delete_client( + dbtree *db, char *topic, uint32_t pipe_id); + +/** + * @brief dbtree_find_clients_and_cache_msg - Get all + * subscribers online to this topic + * @param dbtree - dbtree + * @param topic - topic + * @return pipe id array + */ +NNG_DECL uint32_t *dbtree_find_clients(dbtree *db, char *topic); + +/** + * @brief dbtree_insert_retain - Insert retain message to this topic. + * @param db - dbtree + * @param topic - topic + * @param ret_msg - dbtree_retain_msg + * @return + */ +NNG_DECL nng_msg *dbtree_insert_retain( + dbtree *db, char *topic, nng_msg *ret_msg); + +/** + * @brief dbtree_delete_retain - Delete all retain message to this topic. + * @param db - dbtree + * @param topic - topic + * @return ctxt or NULL, if client can be delete or not + */ +NNG_DECL nng_msg *dbtree_delete_retain(dbtree *db, char *topic); + +/** + * @brief dbtree_find_retain - Get all retain message to this topic. + * @param db - dbtree + * @param topic - topic + * @return dbtree_retain_msg pointer vector + */ +NNG_DECL nng_msg **dbtree_find_retain(dbtree *db, char *topic); + +/** + * @brief dbtree_find_shared_clients - This function + * will Find shared subscribe client. + * @param dbtree - dbtree + * @param topic - topic + * @return pipe id array + */ +NNG_DECL uint32_t *dbtree_find_shared_clients(dbtree *db, char *topic); + +/** + * @brief dbtree_get_tree - This function will + * get all info about this tree. + * @param dbtree - dbtree + * @param cb - a callback function + * @return all info about this tree + */ +NNG_DECL void ***dbtree_get_tree(dbtree *db, void *(*cb)(uint32_t pipe_id)); + +#endif diff --git a/VNode/_software_lib/nanomq-0.22.10/include/nng/supplemental/nanolib/nanolib.h b/VNode/_software_lib/nanomq-0.22.10/include/nng/supplemental/nanolib/nanolib.h new file mode 100644 index 00000000..fd10b8b4 --- /dev/null +++ b/VNode/_software_lib/nanomq-0.22.10/include/nng/supplemental/nanolib/nanolib.h @@ -0,0 +1,10 @@ +#ifndef NANOLIB_H +#define NANOLIB_H + +#include "hash_table.h" +#include "mqtt_db.h" +#include +#include +#include + +#endif diff --git a/VNode/_software_lib/nanomq-0.22.10/include/nng/supplemental/nanolib/parquet.h b/VNode/_software_lib/nanomq-0.22.10/include/nng/supplemental/nanolib/parquet.h new file mode 100644 index 00000000..5803e2f7 --- /dev/null +++ b/VNode/_software_lib/nanomq-0.22.10/include/nng/supplemental/nanolib/parquet.h @@ -0,0 +1,76 @@ +#ifndef PARQUET_H +#define PARQUET_H +#include "nng/nng.h" +#include "nng/supplemental/nanolib/conf.h" +#include + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct parquet_object parquet_object; +typedef void (*parquet_cb)(parquet_object *arg); + +typedef enum { + WRITE_TO_NORMAL, + WRITE_TO_TEMP, +} parquet_write_type; + +typedef struct { + uint32_t start_idx; + uint32_t end_idx; + char *filename; +} parquet_file_range; + +typedef struct { + parquet_file_range **range; + int size; + int start; // file range start index +} parquet_file_ranges; + +typedef struct { + uint8_t *data; + uint32_t size; +} parquet_data_packet; + +struct parquet_object { + uint64_t *keys; + uint8_t **darray; + uint32_t *dsize; + uint32_t size; + nng_aio *aio; + void *arg; + parquet_file_ranges *ranges; + parquet_write_type type; + char *topic; +}; + +parquet_object *parquet_object_alloc(uint64_t *keys, uint8_t **darray, + uint32_t *dsize, uint32_t size, nng_aio *aio, void *arg); +void parquet_object_free(parquet_object *elem); + +parquet_file_range *parquet_file_range_alloc(uint32_t start_idx, uint32_t end_idx, char *filename); +void parquet_file_range_free(parquet_file_range *range); + +void parquet_object_set_cb(parquet_object *obj, parquet_cb cb); +int parquet_write_batch_async(parquet_object *elem); +// Write a batch to a temporary Parquet file, utilize it in scenarios where a single +// file is sufficient for writing, sending, and subsequent deletion. +int parquet_write_batch_tmp_async(parquet_object *elem); +int parquet_write_launcher(conf_parquet *conf); + +const char *parquet_find(uint64_t key); +const char **parquet_find_span( + uint64_t start_key, uint64_t end_key, uint32_t *size); + +parquet_data_packet *parquet_find_data_packet(conf_parquet *conf, char *filename, uint64_t key); + +parquet_data_packet **parquet_find_data_packets(conf_parquet *conf, char **filenames, uint64_t *keys, uint32_t len); + +parquet_data_packet **parquet_find_data_span_packets(conf_parquet *conf, uint64_t start_key, uint64_t end_key, uint32_t *size, char *topic); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/VNode/_software_lib/nanomq-0.22.10/include/nng/supplemental/nanolib/parser.h b/VNode/_software_lib/nanomq-0.22.10/include/nng/supplemental/nanolib/parser.h new file mode 100644 index 00000000..0e2553cd --- /dev/null +++ b/VNode/_software_lib/nanomq-0.22.10/include/nng/supplemental/nanolib/parser.h @@ -0,0 +1,105 @@ +/* A Bison parser, made by GNU Bison 3.8.2. */ + +/* Bison interface for Yacc-like parsers in C + + Copyright (C) 1984, 1989-1990, 2000-2015, 2018-2021 Free Software Foundation, + Inc. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +/* As a special exception, you may create a larger work that contains + part or all of the Bison parser skeleton and distribute that work + under terms of your choice, so long as that work isn't itself a + parser generator using the skeleton or a modified version thereof + as a parser skeleton. Alternatively, if you modify or redistribute + the parser skeleton itself, you may (at your option) remove this + special exception, which will cause the skeleton and the resulting + Bison output files to be licensed under the GNU General Public + License without this special exception. + + This special exception was added by the Free Software Foundation in + version 2.2 of Bison. */ + +/* DO NOT RELY ON FEATURES THAT ARE NOT DOCUMENTED in the manual, + especially those whose name start with YY_ or yy_. They are + private implementation details that can be changed or removed. */ + +#ifndef YY_YY_NANOMQ_NNG_SRC_SUPPLEMENTAL_NANOLIB_PARSER_H_INCLUDED +# define YY_YY_NANOMQ_NNG_SRC_SUPPLEMENTAL_NANOLIB_PARSER_H_INCLUDED +/* Debug traces. */ +#ifndef YYDEBUG +# define YYDEBUG 0 +#endif +#if YYDEBUG +extern int yydebug; +#endif + +/* Token kinds. */ +#ifndef YYTOKENTYPE +# define YYTOKENTYPE + enum yytokentype + { + YYEMPTY = -2, + YYEOF = 0, /* "end of file" */ + YYerror = 256, /* error */ + YYUNDEF = 257, /* "invalid token" */ + LCURLY = 258, /* LCURLY */ + RCURLY = 259, /* RCURLY */ + LBRAC = 260, /* LBRAC */ + RBRAC = 261, /* RBRAC */ + COMMA = 262, /* COMMA */ + PUNCT = 263, /* PUNCT */ + VTRUE = 264, /* VTRUE */ + VFALSE = 265, /* VFALSE */ + VNULL = 266, /* VNULL */ + STRING = 267, /* STRING */ + USTRING = 268, /* USTRING */ + RSTRING = 269, /* RSTRING */ + BYTESIZE = 270, /* BYTESIZE */ + PERCENT = 271, /* PERCENT */ + DURATION = 272, /* DURATION */ + DECIMAL = 273, /* DECIMAL */ + INTEGER = 274 /* INTEGER */ + }; + typedef enum yytokentype yytoken_kind_t; +#endif + +/* Value type. */ +#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED +union YYSTYPE +{ +#line 25 "parser.y" + + double intval; + double floatval; + char *strval; + struct cJSON *jsonval; + struct jso_kv *jkval; + +#line 91 "nng/src/supplemental/nanolib/parser.h" + +}; +typedef union YYSTYPE YYSTYPE; +# define YYSTYPE_IS_TRIVIAL 1 +# define YYSTYPE_IS_DECLARED 1 +#endif + + +extern YYSTYPE yylval; + + +int yyparse (struct cJSON **jso); + + +#endif /* !YY_YY_NANOMQ_NNG_SRC_SUPPLEMENTAL_NANOLIB_PARSER_H_INCLUDED */ diff --git a/VNode/_software_lib/nanomq-0.22.10/include/nng/supplemental/nanolib/queue.h b/VNode/_software_lib/nanomq-0.22.10/include/nng/supplemental/nanolib/queue.h new file mode 100644 index 00000000..14ed0210 --- /dev/null +++ b/VNode/_software_lib/nanomq-0.22.10/include/nng/supplemental/nanolib/queue.h @@ -0,0 +1,87 @@ +#ifndef QUEUE_H +#define QUEUE_H +#include +#include + +#define INITIAL_SIZE 5 + +typedef struct { + void** array; + int front; + int rear; + int size; + int capacity; +} CircularQueue; + + +#define INIT_QUEUE(queue) \ + do { \ + (queue).array = (void**)malloc(INITIAL_SIZE * sizeof(void*)); \ + (queue).front = -1; \ + (queue).rear = -1; \ + (queue).size = 0; \ + (queue).capacity = INITIAL_SIZE; \ + } while(0) + +#define NEXT_INDEX(index, size) (((index) + 1) % (size)) + +#define IS_EMPTY(queue) ((queue).size == 0) + +#define QUEUE_SIZE(queue) ((queue).size) + +#define ENQUEUE(queue, element) \ + do { \ + if ((queue).size == (queue).capacity) { \ + int new_capacity = (queue).capacity * 2; \ + void** new_array = (void**)malloc(new_capacity * sizeof(void*)); \ + int i = 0; \ + int j = (queue).front; \ + while (i < (queue).size) { \ + new_array[i] = (queue).array[j]; \ + i++; \ + j = NEXT_INDEX(j, (queue).capacity); \ + } \ + free((queue).array); \ + (queue).array = new_array; \ + (queue).front = 0; \ + (queue).rear = (queue).size - 1; \ + (queue).capacity = new_capacity; \ + } \ + if (IS_EMPTY(queue)) { \ + (queue).front = 0; \ + } \ + (queue).rear = NEXT_INDEX((queue).rear, (queue).capacity); \ + (queue).array[(queue).rear] = (element); \ + (queue).size++; \ + } while(0) + +#define DEQUEUE(queue) \ + ({ \ + void* dequeued_element = NULL; \ + if (IS_EMPTY(queue)) { \ + printf("Queue is empty. Cannot dequeue.\n"); \ + } else { \ + dequeued_element = (queue).array[(queue).front]; \ + (queue).front = NEXT_INDEX((queue).front, (queue).capacity); \ + (queue).size--; \ + if (IS_EMPTY(queue)) { \ + (queue).front = -1; \ + (queue).rear = -1; \ + } \ + } \ + dequeued_element; \ + }) + + +#define FOREACH_QUEUE(queue, elem) \ + for (int i = (queue).front, _count = 0; \ + (queue).size != 0 && _count < (queue).size; \ + i = NEXT_INDEX(i, (queue).capacity), _count++) \ + \ + for (elem = (queue).array[i]; \ + elem != NULL; \ + elem = NULL) + +#define DESTROY_QUEUE(queue) free((queue).array) + +#endif \ No newline at end of file diff --git a/VNode/_software_lib/nanomq-0.22.10/include/nng/supplemental/nanolib/ringbuffer.h b/VNode/_software_lib/nanomq-0.22.10/include/nng/supplemental/nanolib/ringbuffer.h new file mode 100644 index 00000000..3facb1e7 --- /dev/null +++ b/VNode/_software_lib/nanomq-0.22.10/include/nng/supplemental/nanolib/ringbuffer.h @@ -0,0 +1,138 @@ +// +// Copyright 2023 NanoMQ Team, Inc. +// +// This software is supplied under the terms of the MIT License, a +// copy of which should be located in the distribution where this +// file was obtained (LICENSE.txt). A copy of the license may also be +// found online at https://opensource.org/licenses/MIT. +// + +#ifndef RINGBUFFER_H +#define RINGBUFFER_H +#include +#include +#include "nng/nng.h" +#include "nng/supplemental/util/platform.h" +#include "nng/supplemental/nanolib/cvector.h" + +#define RBNAME_LEN 100 +#define RINGBUFFER_MAX_SIZE 0xffffffff +#define RBRULELIST_MAX_SIZE 0xff + +#define ENQUEUE_IN_HOOK 0x0001 +#define ENQUEUE_OUT_HOOK 0x0010 +#define DEQUEUE_IN_HOOK 0x0100 +#define DEQUEUE_OUT_HOOK 0x1000 +#define HOOK_MASK ((ENQUEUE_IN_HOOK) | (ENQUEUE_OUT_HOOK) | (DEQUEUE_IN_HOOK) | (DEQUEUE_OUT_HOOK)) + +typedef struct ringBuffer_s ringBuffer_t; +typedef struct ringBufferMsg_s ringBufferMsg_t; +typedef struct ringBufferRule_s ringBufferRule_t; + +/* For RB_FULL_FILE */ +typedef struct ringBufferFile_s ringBufferFile_t; +typedef struct ringBufferFileRange_s ringBufferFileRange_t; + +struct ringBufferMsg_s { + uint64_t key; + void *data; + /* TTL of each message */ + unsigned long long expiredAt; +}; + +enum fullOption { + RB_FULL_NONE, + RB_FULL_DROP, + RB_FULL_RETURN, + RB_FULL_FILE, + + RB_FULL_MAX +}; + +struct ringBufferFileRange_s { + uint64_t startidx; + uint64_t endidx; + char *filename; +}; + +struct ringBufferFile_s { + uint64_t *keys; + nng_aio *aio; + ringBufferFileRange_t **ranges; +}; + +struct ringBuffer_s { + char name[RBNAME_LEN]; + unsigned int head; + unsigned int tail; + unsigned int size; + unsigned int cap; + /* TTL of all messages in ringbuffer */ + unsigned long long expiredAt; + unsigned int enqinRuleListLen; + unsigned int enqoutRuleListLen; + unsigned int deqinRuleListLen; + unsigned int deqoutRuleListLen; + ringBufferRule_t *enqinRuleList[RBRULELIST_MAX_SIZE]; + ringBufferRule_t *enqoutRuleList[RBRULELIST_MAX_SIZE]; + ringBufferRule_t *deqinRuleList[RBRULELIST_MAX_SIZE]; + ringBufferRule_t *deqoutRuleList[RBRULELIST_MAX_SIZE]; + + enum fullOption fullOp; + + /* FOR RB_FULL_FILE */ + ringBufferFile_t **files; + + nng_mtx *ring_lock; + + ringBufferMsg_t *msgs; +}; + +struct ringBufferRule_s { + /* + * flag: ENQUEUE_IN_HOOK/ENQUEUE_OUT_HOOK/DEQUEUE_IN_HOOK/DEQUEUE_OUT_HOOK + * return: 0: success, -1: failed + */ + int (*match)(ringBuffer_t *rb, void *data, int flag); + /* + * return: 0: continue, -1: stop and return + */ + int (*target)(ringBuffer_t *rb, void *data, int flag); +}; + + +int ringBuffer_add_rule(ringBuffer_t *rb, + int (*match)(ringBuffer_t *rb, void *data, int flag), + int (*target)(ringBuffer_t *rb, void *data, int flag), + int flag); + +int ringBuffer_init(ringBuffer_t **rb, + unsigned int cap, + enum fullOption fullOp, + unsigned long long expiredAt); +int ringBuffer_enqueue(ringBuffer_t *rb, + uint64_t key, + void *data, + unsigned long long expiredAt, + nng_aio *aio); +int ringBuffer_dequeue(ringBuffer_t *rb, void **data); +int ringBuffer_release(ringBuffer_t *rb); + +int ringBuffer_search_msg_by_key(ringBuffer_t *rb, uint64_t key, nng_msg **msg); +int ringBuffer_search_msgs_by_key(ringBuffer_t *rb, uint64_t key, uint32_t count, nng_msg ***list); +int ringBuffer_search_msgs_fuzz(ringBuffer_t *rb, + uint64_t start, + uint64_t end, + uint32_t *count, + nng_msg ***list); +int ringBuffer_get_and_clean_msgs(ringBuffer_t *rb, + unsigned int *count, nng_msg ***list); + +int ringBuffer_set_fullOp(ringBuffer_t *rb, enum fullOption fullOp); +#ifdef SUPP_PARQUET +int ringBuffer_get_msgs_from_file(ringBuffer_t *rb, void ***msgs, int **msgLen); +int ringBuffer_get_msgs_from_file_by_keys(ringBuffer_t *rb, uint64_t *keys, uint32_t count, + void ***msgs, int **msgLen); +#endif + +#endif diff --git a/VNode/_software_lib/nanomq-0.22.10/include/nng/supplemental/nanolib/rule.h b/VNode/_software_lib/nanomq-0.22.10/include/nng/supplemental/nanolib/rule.h new file mode 100644 index 00000000..e62aa7fa --- /dev/null +++ b/VNode/_software_lib/nanomq-0.22.10/include/nng/supplemental/nanolib/rule.h @@ -0,0 +1,138 @@ +#ifndef RULE_H +#define RULE_H +#include +#include "nng/nng.h" +#include "nng/supplemental/util/platform.h" + +typedef enum { + RULE_QOS, + RULE_ID, + RULE_TOPIC, + RULE_CLIENTID, + RULE_USERNAME, + RULE_PASSWORD, + RULE_TIMESTAMP, + RULE_PAYLOAD_ALL, + RULE_PAYLOAD_FIELD, +} rule_type; + +typedef enum { + RULE_CMP_NONE, // compare type init value + RULE_CMP_EQUAL, // compare symbol '=' + RULE_CMP_UNEQUAL, // compare symbol '!=' or '<>' + RULE_CMP_GREATER, // compare symbol '>' + RULE_CMP_LESS, // compare symbol '<' + RULE_CMP_GREATER_AND_EQUAL, // compare symbol '>=' + RULE_CMP_LESS_AND_EQUAL, // compare symbol '<=' +} rule_cmp_type; + +typedef enum { + RULE_FORWORD_SQLITE, + RULE_FORWORD_FDB, + RULE_FORWORD_MYSQL, + RULE_FORWORD_REPUB +} rule_forword_type; + +typedef struct { + char **psa; // payload string array, for multi level json + char *pas; // payload field string or alias + char *filter; // payload field related filter + rule_cmp_type cmp_type; // payload field compare type + bool is_store; // payload value is store or not + uint8_t type; // payload field value type + void *value; // payload field value +} rule_payload; + +typedef struct { + bool flag[9]; + bool auto_inc; + uint8_t type; + void *value; + char **key_arr; +} rule_key; + +typedef struct { + char *address; + uint8_t proto_ver; + char *clientid; + bool clean_start; + char *username; + char *password; + uint16_t keepalive; + char *topic; + void *sock; +} repub_t; + +typedef struct { + char *table; + char *host; + char *username; + char *password; + void *conn; +} rule_mysql; + +typedef struct { + /* + ** flag[0] == RULE_QOS, + ** flag[1] == RULE_ID, + ** flag[2] == RULE_TOPIC, + ** flag[3] == RULE_CLIENTID, + ** flag[4] == RULE_USERNAME, + ** flag[5] == RULE_PASSWORD, + ** flag[6] == RULE_TIMESTAMP, + ** flag[7] == RULE_PAYLOAD_ALL, + ** flag[8] == RULE_PAYLOAD_FIELD, + */ + bool flag[9]; // if this field need to store + bool enabled; // if this rule is enabled + rule_cmp_type cmp_type[8]; // filter compare type + rule_forword_type forword_type; // forword type + char *topic; // topic parse from sql 'from' + char *as[8]; // if field string as a new string + rule_payload **payload; // this is for payload info + char **filter; // filter parse from sql 'where' + char *sqlite_table; + char *raw_sql; + uint32_t rule_id; + rule_key *key; + repub_t *repub; + rule_mysql *mysql; +} rule; + +typedef struct { + /* + ** 00000000 == OFF, + ** 00000001 == Sqlite ON, + ** 00000010 == Fdb ON, + ** 00000100 == MySOL ON + ** 00001000 == Repub ON + ** 00010000 + ** 00100000 + ** 01000000 + */ + uint8_t option; + /* + ** rdb[0] == Sqlite + ** rdb[1] == Fdb + ** rdb[2] == MySOL + ** rdb[3] == RePub + */ + void *rdb[3]; + rule *rules; + char *sqlite_db; + char *mysql_db; + nng_mtx *rule_mutex; +} conf_rule; + +int rule_find_key(const char *str, size_t len); +uint32_t rule_generate_rule_id(void); +char *rule_get_key_arr(char *p, rule_key *key); +bool rule_sql_parse(conf_rule *cr, char *sql); +repub_t *rule_repub_init(void); +void rule_repub_free(repub_t *repub); +void rule_free(rule *r); +bool rule_mysql_check(rule_mysql *mysql); +void rule_mysql_free(rule_mysql *mysql); +rule_mysql *rule_mysql_init(void); + +#endif \ No newline at end of file diff --git a/VNode/_software_lib/nanomq-0.22.10/include/nng/supplemental/nanolib/scanner.h b/VNode/_software_lib/nanomq-0.22.10/include/nng/supplemental/nanolib/scanner.h new file mode 100644 index 00000000..413e89f4 --- /dev/null +++ b/VNode/_software_lib/nanomq-0.22.10/include/nng/supplemental/nanolib/scanner.h @@ -0,0 +1,479 @@ +#ifndef yyHEADER_H +#define yyHEADER_H 1 +#define yyIN_HEADER 1 + +#line 6 "nng/src/supplemental/nanolib/scanner.h" + +#line 8 "nng/src/supplemental/nanolib/scanner.h" + +#define YY_INT_ALIGNED short int + +/* A lexical scanner generated by flex */ + +#define FLEX_SCANNER +#define YY_FLEX_MAJOR_VERSION 2 +#define YY_FLEX_MINOR_VERSION 6 +#define YY_FLEX_SUBMINOR_VERSION 4 +#if YY_FLEX_SUBMINOR_VERSION > 0 +#define FLEX_BETA +#endif + +/* First, we deal with platform-specific or compiler-specific issues. */ + +/* begin standard C headers. */ +#include +#include +#include +#include + +/* end standard C headers. */ + +/* flex integer type definitions */ + +#ifndef FLEXINT_H +#define FLEXINT_H + +/* C99 systems have . Non-C99 systems may or may not. */ + +#if defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L + +/* C99 says to define __STDC_LIMIT_MACROS before including stdint.h, + * if you want the limit (max/min) macros for int types. + */ +#ifndef __STDC_LIMIT_MACROS +#define __STDC_LIMIT_MACROS 1 +#endif + +#include +typedef int8_t flex_int8_t; +typedef uint8_t flex_uint8_t; +typedef int16_t flex_int16_t; +typedef uint16_t flex_uint16_t; +typedef int32_t flex_int32_t; +typedef uint32_t flex_uint32_t; +#else +typedef signed char flex_int8_t; +typedef short int flex_int16_t; +typedef int flex_int32_t; +typedef unsigned char flex_uint8_t; +typedef unsigned short int flex_uint16_t; +typedef unsigned int flex_uint32_t; + +/* Limits of integral types. */ +#ifndef INT8_MIN +#define INT8_MIN (-128) +#endif +#ifndef INT16_MIN +#define INT16_MIN (-32767-1) +#endif +#ifndef INT32_MIN +#define INT32_MIN (-2147483647-1) +#endif +#ifndef INT8_MAX +#define INT8_MAX (127) +#endif +#ifndef INT16_MAX +#define INT16_MAX (32767) +#endif +#ifndef INT32_MAX +#define INT32_MAX (2147483647) +#endif +#ifndef UINT8_MAX +#define UINT8_MAX (255U) +#endif +#ifndef UINT16_MAX +#define UINT16_MAX (65535U) +#endif +#ifndef UINT32_MAX +#define UINT32_MAX (4294967295U) +#endif + +#ifndef SIZE_MAX +#define SIZE_MAX (~(size_t)0) +#endif + +#endif /* ! C99 */ + +#endif /* ! FLEXINT_H */ + +/* begin standard C++ headers. */ + +/* TODO: this is always defined, so inline it */ +#define yyconst const + +#if defined(__GNUC__) && __GNUC__ >= 3 +#define yynoreturn __attribute__((__noreturn__)) +#else +#define yynoreturn +#endif + +/* Size of default input buffer. */ +#ifndef YY_BUF_SIZE +#ifdef __ia64__ +/* On IA-64, the buffer size is 16k, not 8k. + * Moreover, YY_BUF_SIZE is 2*YY_READ_BUF_SIZE in the general case. + * Ditto for the __ia64__ case accordingly. + */ +#define YY_BUF_SIZE 32768 +#else +#define YY_BUF_SIZE 16384 +#endif /* __ia64__ */ +#endif + +#ifndef YY_TYPEDEF_YY_BUFFER_STATE +#define YY_TYPEDEF_YY_BUFFER_STATE +typedef struct yy_buffer_state *YY_BUFFER_STATE; +#endif + +#ifndef YY_TYPEDEF_YY_SIZE_T +#define YY_TYPEDEF_YY_SIZE_T +typedef size_t yy_size_t; +#endif + +extern int yyleng; + +extern FILE *yyin, *yyout; + +#ifndef YY_STRUCT_YY_BUFFER_STATE +#define YY_STRUCT_YY_BUFFER_STATE +struct yy_buffer_state + { + FILE *yy_input_file; + + char *yy_ch_buf; /* input buffer */ + char *yy_buf_pos; /* current position in input buffer */ + + /* Size of input buffer in bytes, not including room for EOB + * characters. + */ + int yy_buf_size; + + /* Number of characters read into yy_ch_buf, not including EOB + * characters. + */ + int yy_n_chars; + + /* Whether we "own" the buffer - i.e., we know we created it, + * and can realloc() it to grow it, and should free() it to + * delete it. + */ + int yy_is_our_buffer; + + /* Whether this is an "interactive" input source; if so, and + * if we're using stdio for input, then we want to use getc() + * instead of fread(), to make sure we stop fetching input after + * each newline. + */ + int yy_is_interactive; + + /* Whether we're considered to be at the beginning of a line. + * If so, '^' rules will be active on the next match, otherwise + * not. + */ + int yy_at_bol; + + int yy_bs_lineno; /**< The line count. */ + int yy_bs_column; /**< The column count. */ + + /* Whether to try to fill the input buffer when we reach the + * end of it. + */ + int yy_fill_buffer; + + int yy_buffer_status; + + }; +#endif /* !YY_STRUCT_YY_BUFFER_STATE */ + +void yyrestart ( FILE *input_file ); +void yy_switch_to_buffer ( YY_BUFFER_STATE new_buffer ); +YY_BUFFER_STATE yy_create_buffer ( FILE *file, int size ); +void yy_delete_buffer ( YY_BUFFER_STATE b ); +void yy_flush_buffer ( YY_BUFFER_STATE b ); +void yypush_buffer_state ( YY_BUFFER_STATE new_buffer ); +void yypop_buffer_state ( void ); + +YY_BUFFER_STATE yy_scan_buffer ( char *base, yy_size_t size ); +YY_BUFFER_STATE yy_scan_string ( const char *yy_str ); +YY_BUFFER_STATE yy_scan_bytes ( const char *bytes, int len ); + +void *yyalloc ( yy_size_t ); +void *yyrealloc ( void *, yy_size_t ); +void yyfree ( void * ); + +/* Begin user sect3 */ + +#define yywrap() (/*CONSTCOND*/1) +#define YY_SKIP_YYWRAP + +extern int yylineno; + +extern char *yytext; +#ifdef yytext_ptr +#undef yytext_ptr +#endif +#define yytext_ptr yytext + +#ifdef YY_HEADER_EXPORT_START_CONDITIONS +#define INITIAL 0 +#define incl 1 +#define inclr 2 + +#endif + +#ifndef YY_NO_UNISTD_H +/* Special case for "unistd.h", since it is non-ANSI. We include it way + * down here because we want the user's section 1 to have been scanned first. + * The user has a chance to override it with an option. + */ +#include +#endif + +#ifndef YY_EXTRA_TYPE +#define YY_EXTRA_TYPE void * +#endif + +/* Accessor methods to globals. + These are made visible to non-reentrant scanners for convenience. */ + +int yylex_destroy ( void ); + +int yyget_debug ( void ); + +void yyset_debug ( int debug_flag ); + +YY_EXTRA_TYPE yyget_extra ( void ); + +void yyset_extra ( YY_EXTRA_TYPE user_defined ); + +FILE *yyget_in ( void ); + +void yyset_in ( FILE * _in_str ); + +FILE *yyget_out ( void ); + +void yyset_out ( FILE * _out_str ); + + int yyget_leng ( void ); + +char *yyget_text ( void ); + +int yyget_lineno ( void ); + +void yyset_lineno ( int _line_number ); + +/* Macros after this point can all be overridden by user definitions in + * section 1. + */ + +#ifndef YY_SKIP_YYWRAP +#ifdef __cplusplus +extern "C" int yywrap ( void ); +#else +extern int yywrap ( void ); +#endif +#endif + +#ifndef yytext_ptr +static void yy_flex_strncpy ( char *, const char *, int ); +#endif + +#ifdef YY_NEED_STRLEN +static int yy_flex_strlen ( const char * ); +#endif + +#ifndef YY_NO_INPUT + +#endif + +/* Amount of stuff to slurp up with each read. */ +#ifndef YY_READ_BUF_SIZE +#ifdef __ia64__ +/* On IA-64, the buffer size is 16k, not 8k */ +#define YY_READ_BUF_SIZE 16384 +#else +#define YY_READ_BUF_SIZE 8192 +#endif /* __ia64__ */ +#endif + +/* Number of entries by which start-condition stack grows. */ +#ifndef YY_START_STACK_INCR +#define YY_START_STACK_INCR 25 +#endif + +/* Default declaration of generated scanner - a define so the user can + * easily add parameters. + */ +#ifndef YY_DECL +#define YY_DECL_IS_OURS 1 + +extern int yylex (void); + +#define YY_DECL int yylex (void) +#endif /* !YY_DECL */ + +/* yy_get_previous_state - get the state just before the EOB char was reached */ + +#undef YY_NEW_FILE +#undef YY_FLUSH_BUFFER +#undef yy_set_bol +#undef yy_new_buffer +#undef yy_set_interactive +#undef YY_DO_BEFORE_ACTION + +#ifdef YY_DECL_IS_OURS +#undef YY_DECL_IS_OURS +#undef YY_DECL +#endif + +#ifndef yy_create_buffer_ALREADY_DEFINED +#undef yy_create_buffer +#endif +#ifndef yy_delete_buffer_ALREADY_DEFINED +#undef yy_delete_buffer +#endif +#ifndef yy_scan_buffer_ALREADY_DEFINED +#undef yy_scan_buffer +#endif +#ifndef yy_scan_string_ALREADY_DEFINED +#undef yy_scan_string +#endif +#ifndef yy_scan_bytes_ALREADY_DEFINED +#undef yy_scan_bytes +#endif +#ifndef yy_init_buffer_ALREADY_DEFINED +#undef yy_init_buffer +#endif +#ifndef yy_flush_buffer_ALREADY_DEFINED +#undef yy_flush_buffer +#endif +#ifndef yy_load_buffer_state_ALREADY_DEFINED +#undef yy_load_buffer_state +#endif +#ifndef yy_switch_to_buffer_ALREADY_DEFINED +#undef yy_switch_to_buffer +#endif +#ifndef yypush_buffer_state_ALREADY_DEFINED +#undef yypush_buffer_state +#endif +#ifndef yypop_buffer_state_ALREADY_DEFINED +#undef yypop_buffer_state +#endif +#ifndef yyensure_buffer_stack_ALREADY_DEFINED +#undef yyensure_buffer_stack +#endif +#ifndef yylex_ALREADY_DEFINED +#undef yylex +#endif +#ifndef yyrestart_ALREADY_DEFINED +#undef yyrestart +#endif +#ifndef yylex_init_ALREADY_DEFINED +#undef yylex_init +#endif +#ifndef yylex_init_extra_ALREADY_DEFINED +#undef yylex_init_extra +#endif +#ifndef yylex_destroy_ALREADY_DEFINED +#undef yylex_destroy +#endif +#ifndef yyget_debug_ALREADY_DEFINED +#undef yyget_debug +#endif +#ifndef yyset_debug_ALREADY_DEFINED +#undef yyset_debug +#endif +#ifndef yyget_extra_ALREADY_DEFINED +#undef yyget_extra +#endif +#ifndef yyset_extra_ALREADY_DEFINED +#undef yyset_extra +#endif +#ifndef yyget_in_ALREADY_DEFINED +#undef yyget_in +#endif +#ifndef yyset_in_ALREADY_DEFINED +#undef yyset_in +#endif +#ifndef yyget_out_ALREADY_DEFINED +#undef yyget_out +#endif +#ifndef yyset_out_ALREADY_DEFINED +#undef yyset_out +#endif +#ifndef yyget_leng_ALREADY_DEFINED +#undef yyget_leng +#endif +#ifndef yyget_text_ALREADY_DEFINED +#undef yyget_text +#endif +#ifndef yyget_lineno_ALREADY_DEFINED +#undef yyget_lineno +#endif +#ifndef yyset_lineno_ALREADY_DEFINED +#undef yyset_lineno +#endif +#ifndef yyget_column_ALREADY_DEFINED +#undef yyget_column +#endif +#ifndef yyset_column_ALREADY_DEFINED +#undef yyset_column +#endif +#ifndef yywrap_ALREADY_DEFINED +#undef yywrap +#endif +#ifndef yyget_lval_ALREADY_DEFINED +#undef yyget_lval +#endif +#ifndef yyset_lval_ALREADY_DEFINED +#undef yyset_lval +#endif +#ifndef yyget_lloc_ALREADY_DEFINED +#undef yyget_lloc +#endif +#ifndef yyset_lloc_ALREADY_DEFINED +#undef yyset_lloc +#endif +#ifndef yyalloc_ALREADY_DEFINED +#undef yyalloc +#endif +#ifndef yyrealloc_ALREADY_DEFINED +#undef yyrealloc +#endif +#ifndef yyfree_ALREADY_DEFINED +#undef yyfree +#endif +#ifndef yytext_ALREADY_DEFINED +#undef yytext +#endif +#ifndef yyleng_ALREADY_DEFINED +#undef yyleng +#endif +#ifndef yyin_ALREADY_DEFINED +#undef yyin +#endif +#ifndef yyout_ALREADY_DEFINED +#undef yyout +#endif +#ifndef yy_flex_debug_ALREADY_DEFINED +#undef yy_flex_debug +#endif +#ifndef yylineno_ALREADY_DEFINED +#undef yylineno +#endif +#ifndef yytables_fload_ALREADY_DEFINED +#undef yytables_fload +#endif +#ifndef yytables_destroy_ALREADY_DEFINED +#undef yytables_destroy +#endif +#ifndef yyTABLES_NAME_ALREADY_DEFINED +#undef yyTABLES_NAME +#endif + +#line 74 "scanner.l" + + +#line 476 "nng/src/supplemental/nanolib/scanner.h" +#undef yyIN_HEADER +#endif /* yyHEADER_H */ diff --git a/VNode/_software_lib/nanomq-0.22.10/include/nng/supplemental/nanolib/utils.h b/VNode/_software_lib/nanomq-0.22.10/include/nng/supplemental/nanolib/utils.h new file mode 100644 index 00000000..2fef65a7 --- /dev/null +++ b/VNode/_software_lib/nanomq-0.22.10/include/nng/supplemental/nanolib/utils.h @@ -0,0 +1,11 @@ +#ifndef _NNG_SUPPLEMENTAL_NANOLIB_UTILS_H +#define _NNG_SUPPLEMENTAL_NANOLIB_UTILS_H + +#include "nng/nng.h" +#include +#include + +NNG_DECL void fatal(const char *msg, ...); +NNG_DECL void nng_fatal(const char *msg, int rv); + +#endif diff --git a/VNode/_software_lib/nanomq-0.22.10/include/nng/supplemental/sqlite/sqlite3.h b/VNode/_software_lib/nanomq-0.22.10/include/nng/supplemental/sqlite/sqlite3.h new file mode 100644 index 00000000..d7f21648 --- /dev/null +++ b/VNode/_software_lib/nanomq-0.22.10/include/nng/supplemental/sqlite/sqlite3.h @@ -0,0 +1,12806 @@ +/* +** 2001-09-15 +** +** The author disclaims copyright to this source code. In place of +** a legal notice, here is a blessing: +** +** May you do good and not evil. +** May you find forgiveness for yourself and forgive others. +** May you share freely, never taking more than you give. +** +************************************************************************* +** This header file defines the interface that the SQLite library +** presents to client programs. If a C-function, structure, datatype, +** or constant definition does not appear in this file, then it is +** not a published API of SQLite, is subject to change without +** notice, and should not be referenced by programs that use SQLite. +** +** Some of the definitions that are in this file are marked as +** "experimental". Experimental interfaces are normally new +** features recently added to SQLite. We do not anticipate changes +** to experimental interfaces but reserve the right to make minor changes +** if experience from use "in the wild" suggest such changes are prudent. +** +** The official C-language API documentation for SQLite is derived +** from comments in this file. This file is the authoritative source +** on how SQLite interfaces are supposed to operate. +** +** The name of this file under configuration management is "sqlite.h.in". +** The makefile makes some minor changes to this file (such as inserting +** the version number) and changes its name to "sqlite3.h" as +** part of the build process. +*/ +#ifndef SQLITE3_H +#define SQLITE3_H +#include /* Needed for the definition of va_list */ + +/* +** Make sure we can call this stuff from C++. +*/ +#ifdef __cplusplus +extern "C" { +#endif + + +/* +** Facilitate override of interface linkage and calling conventions. +** Be aware that these macros may not be used within this particular +** translation of the amalgamation and its associated header file. +** +** The SQLITE_EXTERN and SQLITE_API macros are used to instruct the +** compiler that the target identifier should have external linkage. +** +** The SQLITE_CDECL macro is used to set the calling convention for +** public functions that accept a variable number of arguments. +** +** The SQLITE_APICALL macro is used to set the calling convention for +** public functions that accept a fixed number of arguments. +** +** The SQLITE_STDCALL macro is no longer used and is now deprecated. +** +** The SQLITE_CALLBACK macro is used to set the calling convention for +** function pointers. +** +** The SQLITE_SYSAPI macro is used to set the calling convention for +** functions provided by the operating system. +** +** Currently, the SQLITE_CDECL, SQLITE_APICALL, SQLITE_CALLBACK, and +** SQLITE_SYSAPI macros are used only when building for environments +** that require non-default calling conventions. +*/ +#ifndef SQLITE_EXTERN +# define SQLITE_EXTERN extern +#endif +#ifndef SQLITE_API +# define SQLITE_API +#endif +#ifndef SQLITE_CDECL +# define SQLITE_CDECL +#endif +#ifndef SQLITE_APICALL +# define SQLITE_APICALL +#endif +#ifndef SQLITE_STDCALL +# define SQLITE_STDCALL SQLITE_APICALL +#endif +#ifndef SQLITE_CALLBACK +# define SQLITE_CALLBACK +#endif +#ifndef SQLITE_SYSAPI +# define SQLITE_SYSAPI +#endif + +/* +** These no-op macros are used in front of interfaces to mark those +** interfaces as either deprecated or experimental. New applications +** should not use deprecated interfaces - they are supported for backwards +** compatibility only. Application writers should be aware that +** experimental interfaces are subject to change in point releases. +** +** These macros used to resolve to various kinds of compiler magic that +** would generate warning messages when they were used. But that +** compiler magic ended up generating such a flurry of bug reports +** that we have taken it all out and gone back to using simple +** noop macros. +*/ +#define SQLITE_DEPRECATED +#define SQLITE_EXPERIMENTAL + +/* +** Ensure these symbols were not defined by some previous header file. +*/ +#ifdef SQLITE_VERSION +# undef SQLITE_VERSION +#endif +#ifdef SQLITE_VERSION_NUMBER +# undef SQLITE_VERSION_NUMBER +#endif + +/* +** CAPI3REF: Compile-Time Library Version Numbers +** +** ^(The [SQLITE_VERSION] C preprocessor macro in the sqlite3.h header +** evaluates to a string literal that is the SQLite version in the +** format "X.Y.Z" where X is the major version number (always 3 for +** SQLite3) and Y is the minor version number and Z is the release number.)^ +** ^(The [SQLITE_VERSION_NUMBER] C preprocessor macro resolves to an integer +** with the value (X*1000000 + Y*1000 + Z) where X, Y, and Z are the same +** numbers used in [SQLITE_VERSION].)^ +** The SQLITE_VERSION_NUMBER for any given release of SQLite will also +** be larger than the release from which it is derived. Either Y will +** be held constant and Z will be incremented or else Y will be incremented +** and Z will be reset to zero. +** +** Since [version 3.6.18] ([dateof:3.6.18]), +** SQLite source code has been stored in the +** Fossil configuration management +** system. ^The SQLITE_SOURCE_ID macro evaluates to +** a string which identifies a particular check-in of SQLite +** within its configuration management system. ^The SQLITE_SOURCE_ID +** string contains the date and time of the check-in (UTC) and a SHA1 +** or SHA3-256 hash of the entire source tree. If the source code has +** been edited in any way since it was last checked in, then the last +** four hexadecimal digits of the hash may be modified. +** +** See also: [sqlite3_libversion()], +** [sqlite3_libversion_number()], [sqlite3_sourceid()], +** [sqlite_version()] and [sqlite_source_id()]. +*/ +#define SQLITE_VERSION "3.38.1" +#define SQLITE_VERSION_NUMBER 3038001 +#define SQLITE_SOURCE_ID "2022-03-12 13:37:29 38c210fdd258658321c85ec9c01a072fda3ada94540e3239d29b34dc547a8cbc" + +/* +** CAPI3REF: Run-Time Library Version Numbers +** KEYWORDS: sqlite3_version sqlite3_sourceid +** +** These interfaces provide the same information as the [SQLITE_VERSION], +** [SQLITE_VERSION_NUMBER], and [SQLITE_SOURCE_ID] C preprocessor macros +** but are associated with the library instead of the header file. ^(Cautious +** programmers might include assert() statements in their application to +** verify that values returned by these interfaces match the macros in +** the header, and thus ensure that the application is +** compiled with matching library and header files. +** +**
+** assert( sqlite3_libversion_number()==SQLITE_VERSION_NUMBER );
+** assert( strncmp(sqlite3_sourceid(),SQLITE_SOURCE_ID,80)==0 );
+** assert( strcmp(sqlite3_libversion(),SQLITE_VERSION)==0 );
+** 
)^ +** +** ^The sqlite3_version[] string constant contains the text of [SQLITE_VERSION] +** macro. ^The sqlite3_libversion() function returns a pointer to the +** to the sqlite3_version[] string constant. The sqlite3_libversion() +** function is provided for use in DLLs since DLL users usually do not have +** direct access to string constants within the DLL. ^The +** sqlite3_libversion_number() function returns an integer equal to +** [SQLITE_VERSION_NUMBER]. ^(The sqlite3_sourceid() function returns +** a pointer to a string constant whose value is the same as the +** [SQLITE_SOURCE_ID] C preprocessor macro. Except if SQLite is built +** using an edited copy of [the amalgamation], then the last four characters +** of the hash might be different from [SQLITE_SOURCE_ID].)^ +** +** See also: [sqlite_version()] and [sqlite_source_id()]. +*/ +SQLITE_API SQLITE_EXTERN const char sqlite3_version[]; +SQLITE_API const char *sqlite3_libversion(void); +SQLITE_API const char *sqlite3_sourceid(void); +SQLITE_API int sqlite3_libversion_number(void); + +/* +** CAPI3REF: Run-Time Library Compilation Options Diagnostics +** +** ^The sqlite3_compileoption_used() function returns 0 or 1 +** indicating whether the specified option was defined at +** compile time. ^The SQLITE_ prefix may be omitted from the +** option name passed to sqlite3_compileoption_used(). +** +** ^The sqlite3_compileoption_get() function allows iterating +** over the list of options that were defined at compile time by +** returning the N-th compile time option string. ^If N is out of range, +** sqlite3_compileoption_get() returns a NULL pointer. ^The SQLITE_ +** prefix is omitted from any strings returned by +** sqlite3_compileoption_get(). +** +** ^Support for the diagnostic functions sqlite3_compileoption_used() +** and sqlite3_compileoption_get() may be omitted by specifying the +** [SQLITE_OMIT_COMPILEOPTION_DIAGS] option at compile time. +** +** See also: SQL functions [sqlite_compileoption_used()] and +** [sqlite_compileoption_get()] and the [compile_options pragma]. +*/ +#ifndef SQLITE_OMIT_COMPILEOPTION_DIAGS +SQLITE_API int sqlite3_compileoption_used(const char *zOptName); +SQLITE_API const char *sqlite3_compileoption_get(int N); +#else +# define sqlite3_compileoption_used(X) 0 +# define sqlite3_compileoption_get(X) ((void*)0) +#endif + +/* +** CAPI3REF: Test To See If The Library Is Threadsafe +** +** ^The sqlite3_threadsafe() function returns zero if and only if +** SQLite was compiled with mutexing code omitted due to the +** [SQLITE_THREADSAFE] compile-time option being set to 0. +** +** SQLite can be compiled with or without mutexes. When +** the [SQLITE_THREADSAFE] C preprocessor macro is 1 or 2, mutexes +** are enabled and SQLite is threadsafe. When the +** [SQLITE_THREADSAFE] macro is 0, +** the mutexes are omitted. Without the mutexes, it is not safe +** to use SQLite concurrently from more than one thread. +** +** Enabling mutexes incurs a measurable performance penalty. +** So if speed is of utmost importance, it makes sense to disable +** the mutexes. But for maximum safety, mutexes should be enabled. +** ^The default behavior is for mutexes to be enabled. +** +** This interface can be used by an application to make sure that the +** version of SQLite that it is linking against was compiled with +** the desired setting of the [SQLITE_THREADSAFE] macro. +** +** This interface only reports on the compile-time mutex setting +** of the [SQLITE_THREADSAFE] flag. If SQLite is compiled with +** SQLITE_THREADSAFE=1 or =2 then mutexes are enabled by default but +** can be fully or partially disabled using a call to [sqlite3_config()] +** with the verbs [SQLITE_CONFIG_SINGLETHREAD], [SQLITE_CONFIG_MULTITHREAD], +** or [SQLITE_CONFIG_SERIALIZED]. ^(The return value of the +** sqlite3_threadsafe() function shows only the compile-time setting of +** thread safety, not any run-time changes to that setting made by +** sqlite3_config(). In other words, the return value from sqlite3_threadsafe() +** is unchanged by calls to sqlite3_config().)^ +** +** See the [threading mode] documentation for additional information. +*/ +SQLITE_API int sqlite3_threadsafe(void); + +/* +** CAPI3REF: Database Connection Handle +** KEYWORDS: {database connection} {database connections} +** +** Each open SQLite database is represented by a pointer to an instance of +** the opaque structure named "sqlite3". It is useful to think of an sqlite3 +** pointer as an object. The [sqlite3_open()], [sqlite3_open16()], and +** [sqlite3_open_v2()] interfaces are its constructors, and [sqlite3_close()] +** and [sqlite3_close_v2()] are its destructors. There are many other +** interfaces (such as +** [sqlite3_prepare_v2()], [sqlite3_create_function()], and +** [sqlite3_busy_timeout()] to name but three) that are methods on an +** sqlite3 object. +*/ +typedef struct sqlite3 sqlite3; + +/* +** CAPI3REF: 64-Bit Integer Types +** KEYWORDS: sqlite_int64 sqlite_uint64 +** +** Because there is no cross-platform way to specify 64-bit integer types +** SQLite includes typedefs for 64-bit signed and unsigned integers. +** +** The sqlite3_int64 and sqlite3_uint64 are the preferred type definitions. +** The sqlite_int64 and sqlite_uint64 types are supported for backwards +** compatibility only. +** +** ^The sqlite3_int64 and sqlite_int64 types can store integer values +** between -9223372036854775808 and +9223372036854775807 inclusive. ^The +** sqlite3_uint64 and sqlite_uint64 types can store integer values +** between 0 and +18446744073709551615 inclusive. +*/ +#ifdef SQLITE_INT64_TYPE + typedef SQLITE_INT64_TYPE sqlite_int64; +# ifdef SQLITE_UINT64_TYPE + typedef SQLITE_UINT64_TYPE sqlite_uint64; +# else + typedef unsigned SQLITE_INT64_TYPE sqlite_uint64; +# endif +#elif defined(_MSC_VER) || defined(__BORLANDC__) + typedef __int64 sqlite_int64; + typedef unsigned __int64 sqlite_uint64; +#else + typedef long long int sqlite_int64; + typedef unsigned long long int sqlite_uint64; +#endif +typedef sqlite_int64 sqlite3_int64; +typedef sqlite_uint64 sqlite3_uint64; + +/* +** If compiling for a processor that lacks floating point support, +** substitute integer for floating-point. +*/ +#ifdef SQLITE_OMIT_FLOATING_POINT +# define double sqlite3_int64 +#endif + +/* +** CAPI3REF: Closing A Database Connection +** DESTRUCTOR: sqlite3 +** +** ^The sqlite3_close() and sqlite3_close_v2() routines are destructors +** for the [sqlite3] object. +** ^Calls to sqlite3_close() and sqlite3_close_v2() return [SQLITE_OK] if +** the [sqlite3] object is successfully destroyed and all associated +** resources are deallocated. +** +** Ideally, applications should [sqlite3_finalize | finalize] all +** [prepared statements], [sqlite3_blob_close | close] all [BLOB handles], and +** [sqlite3_backup_finish | finish] all [sqlite3_backup] objects associated +** with the [sqlite3] object prior to attempting to close the object. +** ^If the database connection is associated with unfinalized prepared +** statements, BLOB handlers, and/or unfinished sqlite3_backup objects then +** sqlite3_close() will leave the database connection open and return +** [SQLITE_BUSY]. ^If sqlite3_close_v2() is called with unfinalized prepared +** statements, unclosed BLOB handlers, and/or unfinished sqlite3_backups, +** it returns [SQLITE_OK] regardless, but instead of deallocating the database +** connection immediately, it marks the database connection as an unusable +** "zombie" and makes arrangements to automatically deallocate the database +** connection after all prepared statements are finalized, all BLOB handles +** are closed, and all backups have finished. The sqlite3_close_v2() interface +** is intended for use with host languages that are garbage collected, and +** where the order in which destructors are called is arbitrary. +** +** ^If an [sqlite3] object is destroyed while a transaction is open, +** the transaction is automatically rolled back. +** +** The C parameter to [sqlite3_close(C)] and [sqlite3_close_v2(C)] +** must be either a NULL +** pointer or an [sqlite3] object pointer obtained +** from [sqlite3_open()], [sqlite3_open16()], or +** [sqlite3_open_v2()], and not previously closed. +** ^Calling sqlite3_close() or sqlite3_close_v2() with a NULL pointer +** argument is a harmless no-op. +*/ +SQLITE_API int sqlite3_close(sqlite3*); +SQLITE_API int sqlite3_close_v2(sqlite3*); + +/* +** The type for a callback function. +** This is legacy and deprecated. It is included for historical +** compatibility and is not documented. +*/ +typedef int (*sqlite3_callback)(void*,int,char**, char**); + +/* +** CAPI3REF: One-Step Query Execution Interface +** METHOD: sqlite3 +** +** The sqlite3_exec() interface is a convenience wrapper around +** [sqlite3_prepare_v2()], [sqlite3_step()], and [sqlite3_finalize()], +** that allows an application to run multiple statements of SQL +** without having to use a lot of C code. +** +** ^The sqlite3_exec() interface runs zero or more UTF-8 encoded, +** semicolon-separate SQL statements passed into its 2nd argument, +** in the context of the [database connection] passed in as its 1st +** argument. ^If the callback function of the 3rd argument to +** sqlite3_exec() is not NULL, then it is invoked for each result row +** coming out of the evaluated SQL statements. ^The 4th argument to +** sqlite3_exec() is relayed through to the 1st argument of each +** callback invocation. ^If the callback pointer to sqlite3_exec() +** is NULL, then no callback is ever invoked and result rows are +** ignored. +** +** ^If an error occurs while evaluating the SQL statements passed into +** sqlite3_exec(), then execution of the current statement stops and +** subsequent statements are skipped. ^If the 5th parameter to sqlite3_exec() +** is not NULL then any error message is written into memory obtained +** from [sqlite3_malloc()] and passed back through the 5th parameter. +** To avoid memory leaks, the application should invoke [sqlite3_free()] +** on error message strings returned through the 5th parameter of +** sqlite3_exec() after the error message string is no longer needed. +** ^If the 5th parameter to sqlite3_exec() is not NULL and no errors +** occur, then sqlite3_exec() sets the pointer in its 5th parameter to +** NULL before returning. +** +** ^If an sqlite3_exec() callback returns non-zero, the sqlite3_exec() +** routine returns SQLITE_ABORT without invoking the callback again and +** without running any subsequent SQL statements. +** +** ^The 2nd argument to the sqlite3_exec() callback function is the +** number of columns in the result. ^The 3rd argument to the sqlite3_exec() +** callback is an array of pointers to strings obtained as if from +** [sqlite3_column_text()], one for each column. ^If an element of a +** result row is NULL then the corresponding string pointer for the +** sqlite3_exec() callback is a NULL pointer. ^The 4th argument to the +** sqlite3_exec() callback is an array of pointers to strings where each +** entry represents the name of corresponding result column as obtained +** from [sqlite3_column_name()]. +** +** ^If the 2nd parameter to sqlite3_exec() is a NULL pointer, a pointer +** to an empty string, or a pointer that contains only whitespace and/or +** SQL comments, then no SQL statements are evaluated and the database +** is not changed. +** +** Restrictions: +** +**
    +**
  • The application must ensure that the 1st parameter to sqlite3_exec() +** is a valid and open [database connection]. +**
  • The application must not close the [database connection] specified by +** the 1st parameter to sqlite3_exec() while sqlite3_exec() is running. +**
  • The application must not modify the SQL statement text passed into +** the 2nd parameter of sqlite3_exec() while sqlite3_exec() is running. +**
+*/ +SQLITE_API int sqlite3_exec( + sqlite3*, /* An open database */ + const char *sql, /* SQL to be evaluated */ + int (*callback)(void*,int,char**,char**), /* Callback function */ + void *, /* 1st argument to callback */ + char **errmsg /* Error msg written here */ +); + +/* +** CAPI3REF: Result Codes +** KEYWORDS: {result code definitions} +** +** Many SQLite functions return an integer result code from the set shown +** here in order to indicate success or failure. +** +** New error codes may be added in future versions of SQLite. +** +** See also: [extended result code definitions] +*/ +#define SQLITE_OK 0 /* Successful result */ +/* beginning-of-error-codes */ +#define SQLITE_ERROR 1 /* Generic error */ +#define SQLITE_INTERNAL 2 /* Internal logic error in SQLite */ +#define SQLITE_PERM 3 /* Access permission denied */ +#define SQLITE_ABORT 4 /* Callback routine requested an abort */ +#define SQLITE_BUSY 5 /* The database file is locked */ +#define SQLITE_LOCKED 6 /* A table in the database is locked */ +#define SQLITE_NOMEM 7 /* A malloc() failed */ +#define SQLITE_READONLY 8 /* Attempt to write a readonly database */ +#define SQLITE_INTERRUPT 9 /* Operation terminated by sqlite3_interrupt()*/ +#define SQLITE_IOERR 10 /* Some kind of disk I/O error occurred */ +#define SQLITE_CORRUPT 11 /* The database disk image is malformed */ +#define SQLITE_NOTFOUND 12 /* Unknown opcode in sqlite3_file_control() */ +#define SQLITE_FULL 13 /* Insertion failed because database is full */ +#define SQLITE_CANTOPEN 14 /* Unable to open the database file */ +#define SQLITE_PROTOCOL 15 /* Database lock protocol error */ +#define SQLITE_EMPTY 16 /* Internal use only */ +#define SQLITE_SCHEMA 17 /* The database schema changed */ +#define SQLITE_TOOBIG 18 /* String or BLOB exceeds size limit */ +#define SQLITE_CONSTRAINT 19 /* Abort due to constraint violation */ +#define SQLITE_MISMATCH 20 /* Data type mismatch */ +#define SQLITE_MISUSE 21 /* Library used incorrectly */ +#define SQLITE_NOLFS 22 /* Uses OS features not supported on host */ +#define SQLITE_AUTH 23 /* Authorization denied */ +#define SQLITE_FORMAT 24 /* Not used */ +#define SQLITE_RANGE 25 /* 2nd parameter to sqlite3_bind out of range */ +#define SQLITE_NOTADB 26 /* File opened that is not a database file */ +#define SQLITE_NOTICE 27 /* Notifications from sqlite3_log() */ +#define SQLITE_WARNING 28 /* Warnings from sqlite3_log() */ +#define SQLITE_ROW 100 /* sqlite3_step() has another row ready */ +#define SQLITE_DONE 101 /* sqlite3_step() has finished executing */ +/* end-of-error-codes */ + +/* +** CAPI3REF: Extended Result Codes +** KEYWORDS: {extended result code definitions} +** +** In its default configuration, SQLite API routines return one of 30 integer +** [result codes]. However, experience has shown that many of +** these result codes are too coarse-grained. They do not provide as +** much information about problems as programmers might like. In an effort to +** address this, newer versions of SQLite (version 3.3.8 [dateof:3.3.8] +** and later) include +** support for additional result codes that provide more detailed information +** about errors. These [extended result codes] are enabled or disabled +** on a per database connection basis using the +** [sqlite3_extended_result_codes()] API. Or, the extended code for +** the most recent error can be obtained using +** [sqlite3_extended_errcode()]. +*/ +#define SQLITE_ERROR_MISSING_COLLSEQ (SQLITE_ERROR | (1<<8)) +#define SQLITE_ERROR_RETRY (SQLITE_ERROR | (2<<8)) +#define SQLITE_ERROR_SNAPSHOT (SQLITE_ERROR | (3<<8)) +#define SQLITE_IOERR_READ (SQLITE_IOERR | (1<<8)) +#define SQLITE_IOERR_SHORT_READ (SQLITE_IOERR | (2<<8)) +#define SQLITE_IOERR_WRITE (SQLITE_IOERR | (3<<8)) +#define SQLITE_IOERR_FSYNC (SQLITE_IOERR | (4<<8)) +#define SQLITE_IOERR_DIR_FSYNC (SQLITE_IOERR | (5<<8)) +#define SQLITE_IOERR_TRUNCATE (SQLITE_IOERR | (6<<8)) +#define SQLITE_IOERR_FSTAT (SQLITE_IOERR | (7<<8)) +#define SQLITE_IOERR_UNLOCK (SQLITE_IOERR | (8<<8)) +#define SQLITE_IOERR_RDLOCK (SQLITE_IOERR | (9<<8)) +#define SQLITE_IOERR_DELETE (SQLITE_IOERR | (10<<8)) +#define SQLITE_IOERR_BLOCKED (SQLITE_IOERR | (11<<8)) +#define SQLITE_IOERR_NOMEM (SQLITE_IOERR | (12<<8)) +#define SQLITE_IOERR_ACCESS (SQLITE_IOERR | (13<<8)) +#define SQLITE_IOERR_CHECKRESERVEDLOCK (SQLITE_IOERR | (14<<8)) +#define SQLITE_IOERR_LOCK (SQLITE_IOERR | (15<<8)) +#define SQLITE_IOERR_CLOSE (SQLITE_IOERR | (16<<8)) +#define SQLITE_IOERR_DIR_CLOSE (SQLITE_IOERR | (17<<8)) +#define SQLITE_IOERR_SHMOPEN (SQLITE_IOERR | (18<<8)) +#define SQLITE_IOERR_SHMSIZE (SQLITE_IOERR | (19<<8)) +#define SQLITE_IOERR_SHMLOCK (SQLITE_IOERR | (20<<8)) +#define SQLITE_IOERR_SHMMAP (SQLITE_IOERR | (21<<8)) +#define SQLITE_IOERR_SEEK (SQLITE_IOERR | (22<<8)) +#define SQLITE_IOERR_DELETE_NOENT (SQLITE_IOERR | (23<<8)) +#define SQLITE_IOERR_MMAP (SQLITE_IOERR | (24<<8)) +#define SQLITE_IOERR_GETTEMPPATH (SQLITE_IOERR | (25<<8)) +#define SQLITE_IOERR_CONVPATH (SQLITE_IOERR | (26<<8)) +#define SQLITE_IOERR_VNODE (SQLITE_IOERR | (27<<8)) +#define SQLITE_IOERR_AUTH (SQLITE_IOERR | (28<<8)) +#define SQLITE_IOERR_BEGIN_ATOMIC (SQLITE_IOERR | (29<<8)) +#define SQLITE_IOERR_COMMIT_ATOMIC (SQLITE_IOERR | (30<<8)) +#define SQLITE_IOERR_ROLLBACK_ATOMIC (SQLITE_IOERR | (31<<8)) +#define SQLITE_IOERR_DATA (SQLITE_IOERR | (32<<8)) +#define SQLITE_IOERR_CORRUPTFS (SQLITE_IOERR | (33<<8)) +#define SQLITE_LOCKED_SHAREDCACHE (SQLITE_LOCKED | (1<<8)) +#define SQLITE_LOCKED_VTAB (SQLITE_LOCKED | (2<<8)) +#define SQLITE_BUSY_RECOVERY (SQLITE_BUSY | (1<<8)) +#define SQLITE_BUSY_SNAPSHOT (SQLITE_BUSY | (2<<8)) +#define SQLITE_BUSY_TIMEOUT (SQLITE_BUSY | (3<<8)) +#define SQLITE_CANTOPEN_NOTEMPDIR (SQLITE_CANTOPEN | (1<<8)) +#define SQLITE_CANTOPEN_ISDIR (SQLITE_CANTOPEN | (2<<8)) +#define SQLITE_CANTOPEN_FULLPATH (SQLITE_CANTOPEN | (3<<8)) +#define SQLITE_CANTOPEN_CONVPATH (SQLITE_CANTOPEN | (4<<8)) +#define SQLITE_CANTOPEN_DIRTYWAL (SQLITE_CANTOPEN | (5<<8)) /* Not Used */ +#define SQLITE_CANTOPEN_SYMLINK (SQLITE_CANTOPEN | (6<<8)) +#define SQLITE_CORRUPT_VTAB (SQLITE_CORRUPT | (1<<8)) +#define SQLITE_CORRUPT_SEQUENCE (SQLITE_CORRUPT | (2<<8)) +#define SQLITE_CORRUPT_INDEX (SQLITE_CORRUPT | (3<<8)) +#define SQLITE_READONLY_RECOVERY (SQLITE_READONLY | (1<<8)) +#define SQLITE_READONLY_CANTLOCK (SQLITE_READONLY | (2<<8)) +#define SQLITE_READONLY_ROLLBACK (SQLITE_READONLY | (3<<8)) +#define SQLITE_READONLY_DBMOVED (SQLITE_READONLY | (4<<8)) +#define SQLITE_READONLY_CANTINIT (SQLITE_READONLY | (5<<8)) +#define SQLITE_READONLY_DIRECTORY (SQLITE_READONLY | (6<<8)) +#define SQLITE_ABORT_ROLLBACK (SQLITE_ABORT | (2<<8)) +#define SQLITE_CONSTRAINT_CHECK (SQLITE_CONSTRAINT | (1<<8)) +#define SQLITE_CONSTRAINT_COMMITHOOK (SQLITE_CONSTRAINT | (2<<8)) +#define SQLITE_CONSTRAINT_FOREIGNKEY (SQLITE_CONSTRAINT | (3<<8)) +#define SQLITE_CONSTRAINT_FUNCTION (SQLITE_CONSTRAINT | (4<<8)) +#define SQLITE_CONSTRAINT_NOTNULL (SQLITE_CONSTRAINT | (5<<8)) +#define SQLITE_CONSTRAINT_PRIMARYKEY (SQLITE_CONSTRAINT | (6<<8)) +#define SQLITE_CONSTRAINT_TRIGGER (SQLITE_CONSTRAINT | (7<<8)) +#define SQLITE_CONSTRAINT_UNIQUE (SQLITE_CONSTRAINT | (8<<8)) +#define SQLITE_CONSTRAINT_VTAB (SQLITE_CONSTRAINT | (9<<8)) +#define SQLITE_CONSTRAINT_ROWID (SQLITE_CONSTRAINT |(10<<8)) +#define SQLITE_CONSTRAINT_PINNED (SQLITE_CONSTRAINT |(11<<8)) +#define SQLITE_CONSTRAINT_DATATYPE (SQLITE_CONSTRAINT |(12<<8)) +#define SQLITE_NOTICE_RECOVER_WAL (SQLITE_NOTICE | (1<<8)) +#define SQLITE_NOTICE_RECOVER_ROLLBACK (SQLITE_NOTICE | (2<<8)) +#define SQLITE_WARNING_AUTOINDEX (SQLITE_WARNING | (1<<8)) +#define SQLITE_AUTH_USER (SQLITE_AUTH | (1<<8)) +#define SQLITE_OK_LOAD_PERMANENTLY (SQLITE_OK | (1<<8)) +#define SQLITE_OK_SYMLINK (SQLITE_OK | (2<<8)) /* internal use only */ + +/* +** CAPI3REF: Flags For File Open Operations +** +** These bit values are intended for use in the +** 3rd parameter to the [sqlite3_open_v2()] interface and +** in the 4th parameter to the [sqlite3_vfs.xOpen] method. +** +** Only those flags marked as "Ok for sqlite3_open_v2()" may be +** used as the third argument to the [sqlite3_open_v2()] interface. +** The other flags have historically been ignored by sqlite3_open_v2(), +** though future versions of SQLite might change so that an error is +** raised if any of the disallowed bits are passed into sqlite3_open_v2(). +** Applications should not depend on the historical behavior. +** +** Note in particular that passing the SQLITE_OPEN_EXCLUSIVE flag into +** [sqlite3_open_v2()] does *not* cause the underlying database file +** to be opened using O_EXCL. Passing SQLITE_OPEN_EXCLUSIVE into +** [sqlite3_open_v2()] has historically be a no-op and might become an +** error in future versions of SQLite. +*/ +#define SQLITE_OPEN_READONLY 0x00000001 /* Ok for sqlite3_open_v2() */ +#define SQLITE_OPEN_READWRITE 0x00000002 /* Ok for sqlite3_open_v2() */ +#define SQLITE_OPEN_CREATE 0x00000004 /* Ok for sqlite3_open_v2() */ +#define SQLITE_OPEN_DELETEONCLOSE 0x00000008 /* VFS only */ +#define SQLITE_OPEN_EXCLUSIVE 0x00000010 /* VFS only */ +#define SQLITE_OPEN_AUTOPROXY 0x00000020 /* VFS only */ +#define SQLITE_OPEN_URI 0x00000040 /* Ok for sqlite3_open_v2() */ +#define SQLITE_OPEN_MEMORY 0x00000080 /* Ok for sqlite3_open_v2() */ +#define SQLITE_OPEN_MAIN_DB 0x00000100 /* VFS only */ +#define SQLITE_OPEN_TEMP_DB 0x00000200 /* VFS only */ +#define SQLITE_OPEN_TRANSIENT_DB 0x00000400 /* VFS only */ +#define SQLITE_OPEN_MAIN_JOURNAL 0x00000800 /* VFS only */ +#define SQLITE_OPEN_TEMP_JOURNAL 0x00001000 /* VFS only */ +#define SQLITE_OPEN_SUBJOURNAL 0x00002000 /* VFS only */ +#define SQLITE_OPEN_SUPER_JOURNAL 0x00004000 /* VFS only */ +#define SQLITE_OPEN_NOMUTEX 0x00008000 /* Ok for sqlite3_open_v2() */ +#define SQLITE_OPEN_FULLMUTEX 0x00010000 /* Ok for sqlite3_open_v2() */ +#define SQLITE_OPEN_SHAREDCACHE 0x00020000 /* Ok for sqlite3_open_v2() */ +#define SQLITE_OPEN_PRIVATECACHE 0x00040000 /* Ok for sqlite3_open_v2() */ +#define SQLITE_OPEN_WAL 0x00080000 /* VFS only */ +#define SQLITE_OPEN_NOFOLLOW 0x01000000 /* Ok for sqlite3_open_v2() */ +#define SQLITE_OPEN_EXRESCODE 0x02000000 /* Extended result codes */ + +/* Reserved: 0x00F00000 */ +/* Legacy compatibility: */ +#define SQLITE_OPEN_MASTER_JOURNAL 0x00004000 /* VFS only */ + + +/* +** CAPI3REF: Device Characteristics +** +** The xDeviceCharacteristics method of the [sqlite3_io_methods] +** object returns an integer which is a vector of these +** bit values expressing I/O characteristics of the mass storage +** device that holds the file that the [sqlite3_io_methods] +** refers to. +** +** The SQLITE_IOCAP_ATOMIC property means that all writes of +** any size are atomic. The SQLITE_IOCAP_ATOMICnnn values +** mean that writes of blocks that are nnn bytes in size and +** are aligned to an address which is an integer multiple of +** nnn are atomic. The SQLITE_IOCAP_SAFE_APPEND value means +** that when data is appended to a file, the data is appended +** first then the size of the file is extended, never the other +** way around. The SQLITE_IOCAP_SEQUENTIAL property means that +** information is written to disk in the same order as calls +** to xWrite(). The SQLITE_IOCAP_POWERSAFE_OVERWRITE property means that +** after reboot following a crash or power loss, the only bytes in a +** file that were written at the application level might have changed +** and that adjacent bytes, even bytes within the same sector are +** guaranteed to be unchanged. The SQLITE_IOCAP_UNDELETABLE_WHEN_OPEN +** flag indicates that a file cannot be deleted when open. The +** SQLITE_IOCAP_IMMUTABLE flag indicates that the file is on +** read-only media and cannot be changed even by processes with +** elevated privileges. +** +** The SQLITE_IOCAP_BATCH_ATOMIC property means that the underlying +** filesystem supports doing multiple write operations atomically when those +** write operations are bracketed by [SQLITE_FCNTL_BEGIN_ATOMIC_WRITE] and +** [SQLITE_FCNTL_COMMIT_ATOMIC_WRITE]. +*/ +#define SQLITE_IOCAP_ATOMIC 0x00000001 +#define SQLITE_IOCAP_ATOMIC512 0x00000002 +#define SQLITE_IOCAP_ATOMIC1K 0x00000004 +#define SQLITE_IOCAP_ATOMIC2K 0x00000008 +#define SQLITE_IOCAP_ATOMIC4K 0x00000010 +#define SQLITE_IOCAP_ATOMIC8K 0x00000020 +#define SQLITE_IOCAP_ATOMIC16K 0x00000040 +#define SQLITE_IOCAP_ATOMIC32K 0x00000080 +#define SQLITE_IOCAP_ATOMIC64K 0x00000100 +#define SQLITE_IOCAP_SAFE_APPEND 0x00000200 +#define SQLITE_IOCAP_SEQUENTIAL 0x00000400 +#define SQLITE_IOCAP_UNDELETABLE_WHEN_OPEN 0x00000800 +#define SQLITE_IOCAP_POWERSAFE_OVERWRITE 0x00001000 +#define SQLITE_IOCAP_IMMUTABLE 0x00002000 +#define SQLITE_IOCAP_BATCH_ATOMIC 0x00004000 + +/* +** CAPI3REF: File Locking Levels +** +** SQLite uses one of these integer values as the second +** argument to calls it makes to the xLock() and xUnlock() methods +** of an [sqlite3_io_methods] object. +*/ +#define SQLITE_LOCK_NONE 0 +#define SQLITE_LOCK_SHARED 1 +#define SQLITE_LOCK_RESERVED 2 +#define SQLITE_LOCK_PENDING 3 +#define SQLITE_LOCK_EXCLUSIVE 4 + +/* +** CAPI3REF: Synchronization Type Flags +** +** When SQLite invokes the xSync() method of an +** [sqlite3_io_methods] object it uses a combination of +** these integer values as the second argument. +** +** When the SQLITE_SYNC_DATAONLY flag is used, it means that the +** sync operation only needs to flush data to mass storage. Inode +** information need not be flushed. If the lower four bits of the flag +** equal SQLITE_SYNC_NORMAL, that means to use normal fsync() semantics. +** If the lower four bits equal SQLITE_SYNC_FULL, that means +** to use Mac OS X style fullsync instead of fsync(). +** +** Do not confuse the SQLITE_SYNC_NORMAL and SQLITE_SYNC_FULL flags +** with the [PRAGMA synchronous]=NORMAL and [PRAGMA synchronous]=FULL +** settings. The [synchronous pragma] determines when calls to the +** xSync VFS method occur and applies uniformly across all platforms. +** The SQLITE_SYNC_NORMAL and SQLITE_SYNC_FULL flags determine how +** energetic or rigorous or forceful the sync operations are and +** only make a difference on Mac OSX for the default SQLite code. +** (Third-party VFS implementations might also make the distinction +** between SQLITE_SYNC_NORMAL and SQLITE_SYNC_FULL, but among the +** operating systems natively supported by SQLite, only Mac OSX +** cares about the difference.) +*/ +#define SQLITE_SYNC_NORMAL 0x00002 +#define SQLITE_SYNC_FULL 0x00003 +#define SQLITE_SYNC_DATAONLY 0x00010 + +/* +** CAPI3REF: OS Interface Open File Handle +** +** An [sqlite3_file] object represents an open file in the +** [sqlite3_vfs | OS interface layer]. Individual OS interface +** implementations will +** want to subclass this object by appending additional fields +** for their own use. The pMethods entry is a pointer to an +** [sqlite3_io_methods] object that defines methods for performing +** I/O operations on the open file. +*/ +typedef struct sqlite3_file sqlite3_file; +struct sqlite3_file { + const struct sqlite3_io_methods *pMethods; /* Methods for an open file */ +}; + +/* +** CAPI3REF: OS Interface File Virtual Methods Object +** +** Every file opened by the [sqlite3_vfs.xOpen] method populates an +** [sqlite3_file] object (or, more commonly, a subclass of the +** [sqlite3_file] object) with a pointer to an instance of this object. +** This object defines the methods used to perform various operations +** against the open file represented by the [sqlite3_file] object. +** +** If the [sqlite3_vfs.xOpen] method sets the sqlite3_file.pMethods element +** to a non-NULL pointer, then the sqlite3_io_methods.xClose method +** may be invoked even if the [sqlite3_vfs.xOpen] reported that it failed. The +** only way to prevent a call to xClose following a failed [sqlite3_vfs.xOpen] +** is for the [sqlite3_vfs.xOpen] to set the sqlite3_file.pMethods element +** to NULL. +** +** The flags argument to xSync may be one of [SQLITE_SYNC_NORMAL] or +** [SQLITE_SYNC_FULL]. The first choice is the normal fsync(). +** The second choice is a Mac OS X style fullsync. The [SQLITE_SYNC_DATAONLY] +** flag may be ORed in to indicate that only the data of the file +** and not its inode needs to be synced. +** +** The integer values to xLock() and xUnlock() are one of +**
    +**
  • [SQLITE_LOCK_NONE], +**
  • [SQLITE_LOCK_SHARED], +**
  • [SQLITE_LOCK_RESERVED], +**
  • [SQLITE_LOCK_PENDING], or +**
  • [SQLITE_LOCK_EXCLUSIVE]. +**
+** xLock() increases the lock. xUnlock() decreases the lock. +** The xCheckReservedLock() method checks whether any database connection, +** either in this process or in some other process, is holding a RESERVED, +** PENDING, or EXCLUSIVE lock on the file. It returns true +** if such a lock exists and false otherwise. +** +** The xFileControl() method is a generic interface that allows custom +** VFS implementations to directly control an open file using the +** [sqlite3_file_control()] interface. The second "op" argument is an +** integer opcode. The third argument is a generic pointer intended to +** point to a structure that may contain arguments or space in which to +** write return values. Potential uses for xFileControl() might be +** functions to enable blocking locks with timeouts, to change the +** locking strategy (for example to use dot-file locks), to inquire +** about the status of a lock, or to break stale locks. The SQLite +** core reserves all opcodes less than 100 for its own use. +** A [file control opcodes | list of opcodes] less than 100 is available. +** Applications that define a custom xFileControl method should use opcodes +** greater than 100 to avoid conflicts. VFS implementations should +** return [SQLITE_NOTFOUND] for file control opcodes that they do not +** recognize. +** +** The xSectorSize() method returns the sector size of the +** device that underlies the file. The sector size is the +** minimum write that can be performed without disturbing +** other bytes in the file. The xDeviceCharacteristics() +** method returns a bit vector describing behaviors of the +** underlying device: +** +**
    +**
  • [SQLITE_IOCAP_ATOMIC] +**
  • [SQLITE_IOCAP_ATOMIC512] +**
  • [SQLITE_IOCAP_ATOMIC1K] +**
  • [SQLITE_IOCAP_ATOMIC2K] +**
  • [SQLITE_IOCAP_ATOMIC4K] +**
  • [SQLITE_IOCAP_ATOMIC8K] +**
  • [SQLITE_IOCAP_ATOMIC16K] +**
  • [SQLITE_IOCAP_ATOMIC32K] +**
  • [SQLITE_IOCAP_ATOMIC64K] +**
  • [SQLITE_IOCAP_SAFE_APPEND] +**
  • [SQLITE_IOCAP_SEQUENTIAL] +**
  • [SQLITE_IOCAP_UNDELETABLE_WHEN_OPEN] +**
  • [SQLITE_IOCAP_POWERSAFE_OVERWRITE] +**
  • [SQLITE_IOCAP_IMMUTABLE] +**
  • [SQLITE_IOCAP_BATCH_ATOMIC] +**
+** +** The SQLITE_IOCAP_ATOMIC property means that all writes of +** any size are atomic. The SQLITE_IOCAP_ATOMICnnn values +** mean that writes of blocks that are nnn bytes in size and +** are aligned to an address which is an integer multiple of +** nnn are atomic. The SQLITE_IOCAP_SAFE_APPEND value means +** that when data is appended to a file, the data is appended +** first then the size of the file is extended, never the other +** way around. The SQLITE_IOCAP_SEQUENTIAL property means that +** information is written to disk in the same order as calls +** to xWrite(). +** +** If xRead() returns SQLITE_IOERR_SHORT_READ it must also fill +** in the unread portions of the buffer with zeros. A VFS that +** fails to zero-fill short reads might seem to work. However, +** failure to zero-fill short reads will eventually lead to +** database corruption. +*/ +typedef struct sqlite3_io_methods sqlite3_io_methods; +struct sqlite3_io_methods { + int iVersion; + int (*xClose)(sqlite3_file*); + int (*xRead)(sqlite3_file*, void*, int iAmt, sqlite3_int64 iOfst); + int (*xWrite)(sqlite3_file*, const void*, int iAmt, sqlite3_int64 iOfst); + int (*xTruncate)(sqlite3_file*, sqlite3_int64 size); + int (*xSync)(sqlite3_file*, int flags); + int (*xFileSize)(sqlite3_file*, sqlite3_int64 *pSize); + int (*xLock)(sqlite3_file*, int); + int (*xUnlock)(sqlite3_file*, int); + int (*xCheckReservedLock)(sqlite3_file*, int *pResOut); + int (*xFileControl)(sqlite3_file*, int op, void *pArg); + int (*xSectorSize)(sqlite3_file*); + int (*xDeviceCharacteristics)(sqlite3_file*); + /* Methods above are valid for version 1 */ + int (*xShmMap)(sqlite3_file*, int iPg, int pgsz, int, void volatile**); + int (*xShmLock)(sqlite3_file*, int offset, int n, int flags); + void (*xShmBarrier)(sqlite3_file*); + int (*xShmUnmap)(sqlite3_file*, int deleteFlag); + /* Methods above are valid for version 2 */ + int (*xFetch)(sqlite3_file*, sqlite3_int64 iOfst, int iAmt, void **pp); + int (*xUnfetch)(sqlite3_file*, sqlite3_int64 iOfst, void *p); + /* Methods above are valid for version 3 */ + /* Additional methods may be added in future releases */ +}; + +/* +** CAPI3REF: Standard File Control Opcodes +** KEYWORDS: {file control opcodes} {file control opcode} +** +** These integer constants are opcodes for the xFileControl method +** of the [sqlite3_io_methods] object and for the [sqlite3_file_control()] +** interface. +** +**
    +**
  • [[SQLITE_FCNTL_LOCKSTATE]] +** The [SQLITE_FCNTL_LOCKSTATE] opcode is used for debugging. This +** opcode causes the xFileControl method to write the current state of +** the lock (one of [SQLITE_LOCK_NONE], [SQLITE_LOCK_SHARED], +** [SQLITE_LOCK_RESERVED], [SQLITE_LOCK_PENDING], or [SQLITE_LOCK_EXCLUSIVE]) +** into an integer that the pArg argument points to. This capability +** is used during testing and is only available when the SQLITE_TEST +** compile-time option is used. +** +**
  • [[SQLITE_FCNTL_SIZE_HINT]] +** The [SQLITE_FCNTL_SIZE_HINT] opcode is used by SQLite to give the VFS +** layer a hint of how large the database file will grow to be during the +** current transaction. This hint is not guaranteed to be accurate but it +** is often close. The underlying VFS might choose to preallocate database +** file space based on this hint in order to help writes to the database +** file run faster. +** +**
  • [[SQLITE_FCNTL_SIZE_LIMIT]] +** The [SQLITE_FCNTL_SIZE_LIMIT] opcode is used by in-memory VFS that +** implements [sqlite3_deserialize()] to set an upper bound on the size +** of the in-memory database. The argument is a pointer to a [sqlite3_int64]. +** If the integer pointed to is negative, then it is filled in with the +** current limit. Otherwise the limit is set to the larger of the value +** of the integer pointed to and the current database size. The integer +** pointed to is set to the new limit. +** +**
  • [[SQLITE_FCNTL_CHUNK_SIZE]] +** The [SQLITE_FCNTL_CHUNK_SIZE] opcode is used to request that the VFS +** extends and truncates the database file in chunks of a size specified +** by the user. The fourth argument to [sqlite3_file_control()] should +** point to an integer (type int) containing the new chunk-size to use +** for the nominated database. Allocating database file space in large +** chunks (say 1MB at a time), may reduce file-system fragmentation and +** improve performance on some systems. +** +**
  • [[SQLITE_FCNTL_FILE_POINTER]] +** The [SQLITE_FCNTL_FILE_POINTER] opcode is used to obtain a pointer +** to the [sqlite3_file] object associated with a particular database +** connection. See also [SQLITE_FCNTL_JOURNAL_POINTER]. +** +**
  • [[SQLITE_FCNTL_JOURNAL_POINTER]] +** The [SQLITE_FCNTL_JOURNAL_POINTER] opcode is used to obtain a pointer +** to the [sqlite3_file] object associated with the journal file (either +** the [rollback journal] or the [write-ahead log]) for a particular database +** connection. See also [SQLITE_FCNTL_FILE_POINTER]. +** +**
  • [[SQLITE_FCNTL_SYNC_OMITTED]] +** No longer in use. +** +**
  • [[SQLITE_FCNTL_SYNC]] +** The [SQLITE_FCNTL_SYNC] opcode is generated internally by SQLite and +** sent to the VFS immediately before the xSync method is invoked on a +** database file descriptor. Or, if the xSync method is not invoked +** because the user has configured SQLite with +** [PRAGMA synchronous | PRAGMA synchronous=OFF] it is invoked in place +** of the xSync method. In most cases, the pointer argument passed with +** this file-control is NULL. However, if the database file is being synced +** as part of a multi-database commit, the argument points to a nul-terminated +** string containing the transactions super-journal file name. VFSes that +** do not need this signal should silently ignore this opcode. Applications +** should not call [sqlite3_file_control()] with this opcode as doing so may +** disrupt the operation of the specialized VFSes that do require it. +** +**
  • [[SQLITE_FCNTL_COMMIT_PHASETWO]] +** The [SQLITE_FCNTL_COMMIT_PHASETWO] opcode is generated internally by SQLite +** and sent to the VFS after a transaction has been committed immediately +** but before the database is unlocked. VFSes that do not need this signal +** should silently ignore this opcode. Applications should not call +** [sqlite3_file_control()] with this opcode as doing so may disrupt the +** operation of the specialized VFSes that do require it. +** +**
  • [[SQLITE_FCNTL_WIN32_AV_RETRY]] +** ^The [SQLITE_FCNTL_WIN32_AV_RETRY] opcode is used to configure automatic +** retry counts and intervals for certain disk I/O operations for the +** windows [VFS] in order to provide robustness in the presence of +** anti-virus programs. By default, the windows VFS will retry file read, +** file write, and file delete operations up to 10 times, with a delay +** of 25 milliseconds before the first retry and with the delay increasing +** by an additional 25 milliseconds with each subsequent retry. This +** opcode allows these two values (10 retries and 25 milliseconds of delay) +** to be adjusted. The values are changed for all database connections +** within the same process. The argument is a pointer to an array of two +** integers where the first integer is the new retry count and the second +** integer is the delay. If either integer is negative, then the setting +** is not changed but instead the prior value of that setting is written +** into the array entry, allowing the current retry settings to be +** interrogated. The zDbName parameter is ignored. +** +**
  • [[SQLITE_FCNTL_PERSIST_WAL]] +** ^The [SQLITE_FCNTL_PERSIST_WAL] opcode is used to set or query the +** persistent [WAL | Write Ahead Log] setting. By default, the auxiliary +** write ahead log ([WAL file]) and shared memory +** files used for transaction control +** are automatically deleted when the latest connection to the database +** closes. Setting persistent WAL mode causes those files to persist after +** close. Persisting the files is useful when other processes that do not +** have write permission on the directory containing the database file want +** to read the database file, as the WAL and shared memory files must exist +** in order for the database to be readable. The fourth parameter to +** [sqlite3_file_control()] for this opcode should be a pointer to an integer. +** That integer is 0 to disable persistent WAL mode or 1 to enable persistent +** WAL mode. If the integer is -1, then it is overwritten with the current +** WAL persistence setting. +** +**
  • [[SQLITE_FCNTL_POWERSAFE_OVERWRITE]] +** ^The [SQLITE_FCNTL_POWERSAFE_OVERWRITE] opcode is used to set or query the +** persistent "powersafe-overwrite" or "PSOW" setting. The PSOW setting +** determines the [SQLITE_IOCAP_POWERSAFE_OVERWRITE] bit of the +** xDeviceCharacteristics methods. The fourth parameter to +** [sqlite3_file_control()] for this opcode should be a pointer to an integer. +** That integer is 0 to disable zero-damage mode or 1 to enable zero-damage +** mode. If the integer is -1, then it is overwritten with the current +** zero-damage mode setting. +** +**
  • [[SQLITE_FCNTL_OVERWRITE]] +** ^The [SQLITE_FCNTL_OVERWRITE] opcode is invoked by SQLite after opening +** a write transaction to indicate that, unless it is rolled back for some +** reason, the entire database file will be overwritten by the current +** transaction. This is used by VACUUM operations. +** +**
  • [[SQLITE_FCNTL_VFSNAME]] +** ^The [SQLITE_FCNTL_VFSNAME] opcode can be used to obtain the names of +** all [VFSes] in the VFS stack. The names are of all VFS shims and the +** final bottom-level VFS are written into memory obtained from +** [sqlite3_malloc()] and the result is stored in the char* variable +** that the fourth parameter of [sqlite3_file_control()] points to. +** The caller is responsible for freeing the memory when done. As with +** all file-control actions, there is no guarantee that this will actually +** do anything. Callers should initialize the char* variable to a NULL +** pointer in case this file-control is not implemented. This file-control +** is intended for diagnostic use only. +** +**
  • [[SQLITE_FCNTL_VFS_POINTER]] +** ^The [SQLITE_FCNTL_VFS_POINTER] opcode finds a pointer to the top-level +** [VFSes] currently in use. ^(The argument X in +** sqlite3_file_control(db,SQLITE_FCNTL_VFS_POINTER,X) must be +** of type "[sqlite3_vfs] **". This opcodes will set *X +** to a pointer to the top-level VFS.)^ +** ^When there are multiple VFS shims in the stack, this opcode finds the +** upper-most shim only. +** +**
  • [[SQLITE_FCNTL_PRAGMA]] +** ^Whenever a [PRAGMA] statement is parsed, an [SQLITE_FCNTL_PRAGMA] +** file control is sent to the open [sqlite3_file] object corresponding +** to the database file to which the pragma statement refers. ^The argument +** to the [SQLITE_FCNTL_PRAGMA] file control is an array of +** pointers to strings (char**) in which the second element of the array +** is the name of the pragma and the third element is the argument to the +** pragma or NULL if the pragma has no argument. ^The handler for an +** [SQLITE_FCNTL_PRAGMA] file control can optionally make the first element +** of the char** argument point to a string obtained from [sqlite3_mprintf()] +** or the equivalent and that string will become the result of the pragma or +** the error message if the pragma fails. ^If the +** [SQLITE_FCNTL_PRAGMA] file control returns [SQLITE_NOTFOUND], then normal +** [PRAGMA] processing continues. ^If the [SQLITE_FCNTL_PRAGMA] +** file control returns [SQLITE_OK], then the parser assumes that the +** VFS has handled the PRAGMA itself and the parser generates a no-op +** prepared statement if result string is NULL, or that returns a copy +** of the result string if the string is non-NULL. +** ^If the [SQLITE_FCNTL_PRAGMA] file control returns +** any result code other than [SQLITE_OK] or [SQLITE_NOTFOUND], that means +** that the VFS encountered an error while handling the [PRAGMA] and the +** compilation of the PRAGMA fails with an error. ^The [SQLITE_FCNTL_PRAGMA] +** file control occurs at the beginning of pragma statement analysis and so +** it is able to override built-in [PRAGMA] statements. +** +**
  • [[SQLITE_FCNTL_BUSYHANDLER]] +** ^The [SQLITE_FCNTL_BUSYHANDLER] +** file-control may be invoked by SQLite on the database file handle +** shortly after it is opened in order to provide a custom VFS with access +** to the connection's busy-handler callback. The argument is of type (void**) +** - an array of two (void *) values. The first (void *) actually points +** to a function of type (int (*)(void *)). In order to invoke the connection's +** busy-handler, this function should be invoked with the second (void *) in +** the array as the only argument. If it returns non-zero, then the operation +** should be retried. If it returns zero, the custom VFS should abandon the +** current operation. +** +**
  • [[SQLITE_FCNTL_TEMPFILENAME]] +** ^Applications can invoke the [SQLITE_FCNTL_TEMPFILENAME] file-control +** to have SQLite generate a +** temporary filename using the same algorithm that is followed to generate +** temporary filenames for TEMP tables and other internal uses. The +** argument should be a char** which will be filled with the filename +** written into memory obtained from [sqlite3_malloc()]. The caller should +** invoke [sqlite3_free()] on the result to avoid a memory leak. +** +**
  • [[SQLITE_FCNTL_MMAP_SIZE]] +** The [SQLITE_FCNTL_MMAP_SIZE] file control is used to query or set the +** maximum number of bytes that will be used for memory-mapped I/O. +** The argument is a pointer to a value of type sqlite3_int64 that +** is an advisory maximum number of bytes in the file to memory map. The +** pointer is overwritten with the old value. The limit is not changed if +** the value originally pointed to is negative, and so the current limit +** can be queried by passing in a pointer to a negative number. This +** file-control is used internally to implement [PRAGMA mmap_size]. +** +**
  • [[SQLITE_FCNTL_TRACE]] +** The [SQLITE_FCNTL_TRACE] file control provides advisory information +** to the VFS about what the higher layers of the SQLite stack are doing. +** This file control is used by some VFS activity tracing [shims]. +** The argument is a zero-terminated string. Higher layers in the +** SQLite stack may generate instances of this file control if +** the [SQLITE_USE_FCNTL_TRACE] compile-time option is enabled. +** +**
  • [[SQLITE_FCNTL_HAS_MOVED]] +** The [SQLITE_FCNTL_HAS_MOVED] file control interprets its argument as a +** pointer to an integer and it writes a boolean into that integer depending +** on whether or not the file has been renamed, moved, or deleted since it +** was first opened. +** +**
  • [[SQLITE_FCNTL_WIN32_GET_HANDLE]] +** The [SQLITE_FCNTL_WIN32_GET_HANDLE] opcode can be used to obtain the +** underlying native file handle associated with a file handle. This file +** control interprets its argument as a pointer to a native file handle and +** writes the resulting value there. +** +**
  • [[SQLITE_FCNTL_WIN32_SET_HANDLE]] +** The [SQLITE_FCNTL_WIN32_SET_HANDLE] opcode is used for debugging. This +** opcode causes the xFileControl method to swap the file handle with the one +** pointed to by the pArg argument. This capability is used during testing +** and only needs to be supported when SQLITE_TEST is defined. +** +**
  • [[SQLITE_FCNTL_WAL_BLOCK]] +** The [SQLITE_FCNTL_WAL_BLOCK] is a signal to the VFS layer that it might +** be advantageous to block on the next WAL lock if the lock is not immediately +** available. The WAL subsystem issues this signal during rare +** circumstances in order to fix a problem with priority inversion. +** Applications should not use this file-control. +** +**
  • [[SQLITE_FCNTL_ZIPVFS]] +** The [SQLITE_FCNTL_ZIPVFS] opcode is implemented by zipvfs only. All other +** VFS should return SQLITE_NOTFOUND for this opcode. +** +**
  • [[SQLITE_FCNTL_RBU]] +** The [SQLITE_FCNTL_RBU] opcode is implemented by the special VFS used by +** the RBU extension only. All other VFS should return SQLITE_NOTFOUND for +** this opcode. +** +**
  • [[SQLITE_FCNTL_BEGIN_ATOMIC_WRITE]] +** If the [SQLITE_FCNTL_BEGIN_ATOMIC_WRITE] opcode returns SQLITE_OK, then +** the file descriptor is placed in "batch write mode", which +** means all subsequent write operations will be deferred and done +** atomically at the next [SQLITE_FCNTL_COMMIT_ATOMIC_WRITE]. Systems +** that do not support batch atomic writes will return SQLITE_NOTFOUND. +** ^Following a successful SQLITE_FCNTL_BEGIN_ATOMIC_WRITE and prior to +** the closing [SQLITE_FCNTL_COMMIT_ATOMIC_WRITE] or +** [SQLITE_FCNTL_ROLLBACK_ATOMIC_WRITE], SQLite will make +** no VFS interface calls on the same [sqlite3_file] file descriptor +** except for calls to the xWrite method and the xFileControl method +** with [SQLITE_FCNTL_SIZE_HINT]. +** +**
  • [[SQLITE_FCNTL_COMMIT_ATOMIC_WRITE]] +** The [SQLITE_FCNTL_COMMIT_ATOMIC_WRITE] opcode causes all write +** operations since the previous successful call to +** [SQLITE_FCNTL_BEGIN_ATOMIC_WRITE] to be performed atomically. +** This file control returns [SQLITE_OK] if and only if the writes were +** all performed successfully and have been committed to persistent storage. +** ^Regardless of whether or not it is successful, this file control takes +** the file descriptor out of batch write mode so that all subsequent +** write operations are independent. +** ^SQLite will never invoke SQLITE_FCNTL_COMMIT_ATOMIC_WRITE without +** a prior successful call to [SQLITE_FCNTL_BEGIN_ATOMIC_WRITE]. +** +**
  • [[SQLITE_FCNTL_ROLLBACK_ATOMIC_WRITE]] +** The [SQLITE_FCNTL_ROLLBACK_ATOMIC_WRITE] opcode causes all write +** operations since the previous successful call to +** [SQLITE_FCNTL_BEGIN_ATOMIC_WRITE] to be rolled back. +** ^This file control takes the file descriptor out of batch write mode +** so that all subsequent write operations are independent. +** ^SQLite will never invoke SQLITE_FCNTL_ROLLBACK_ATOMIC_WRITE without +** a prior successful call to [SQLITE_FCNTL_BEGIN_ATOMIC_WRITE]. +** +**
  • [[SQLITE_FCNTL_LOCK_TIMEOUT]] +** The [SQLITE_FCNTL_LOCK_TIMEOUT] opcode is used to configure a VFS +** to block for up to M milliseconds before failing when attempting to +** obtain a file lock using the xLock or xShmLock methods of the VFS. +** The parameter is a pointer to a 32-bit signed integer that contains +** the value that M is to be set to. Before returning, the 32-bit signed +** integer is overwritten with the previous value of M. +** +**
  • [[SQLITE_FCNTL_DATA_VERSION]] +** The [SQLITE_FCNTL_DATA_VERSION] opcode is used to detect changes to +** a database file. The argument is a pointer to a 32-bit unsigned integer. +** The "data version" for the pager is written into the pointer. The +** "data version" changes whenever any change occurs to the corresponding +** database file, either through SQL statements on the same database +** connection or through transactions committed by separate database +** connections possibly in other processes. The [sqlite3_total_changes()] +** interface can be used to find if any database on the connection has changed, +** but that interface responds to changes on TEMP as well as MAIN and does +** not provide a mechanism to detect changes to MAIN only. Also, the +** [sqlite3_total_changes()] interface responds to internal changes only and +** omits changes made by other database connections. The +** [PRAGMA data_version] command provides a mechanism to detect changes to +** a single attached database that occur due to other database connections, +** but omits changes implemented by the database connection on which it is +** called. This file control is the only mechanism to detect changes that +** happen either internally or externally and that are associated with +** a particular attached database. +** +**
  • [[SQLITE_FCNTL_CKPT_START]] +** The [SQLITE_FCNTL_CKPT_START] opcode is invoked from within a checkpoint +** in wal mode before the client starts to copy pages from the wal +** file to the database file. +** +**
  • [[SQLITE_FCNTL_CKPT_DONE]] +** The [SQLITE_FCNTL_CKPT_DONE] opcode is invoked from within a checkpoint +** in wal mode after the client has finished copying pages from the wal +** file to the database file, but before the *-shm file is updated to +** record the fact that the pages have been checkpointed. +**
+** +**
  • [[SQLITE_FCNTL_EXTERNAL_READER]] +** The EXPERIMENTAL [SQLITE_FCNTL_EXTERNAL_READER] opcode is used to detect +** whether or not there is a database client in another process with a wal-mode +** transaction open on the database or not. It is only available on unix.The +** (void*) argument passed with this file-control should be a pointer to a +** value of type (int). The integer value is set to 1 if the database is a wal +** mode database and there exists at least one client in another process that +** currently has an SQL transaction open on the database. It is set to 0 if +** the database is not a wal-mode db, or if there is no such connection in any +** other process. This opcode cannot be used to detect transactions opened +** by clients within the current process, only within other processes. +** +** +**
  • [[SQLITE_FCNTL_CKSM_FILE]] +** Used by the cksmvfs VFS module only. +** +*/ +#define SQLITE_FCNTL_LOCKSTATE 1 +#define SQLITE_FCNTL_GET_LOCKPROXYFILE 2 +#define SQLITE_FCNTL_SET_LOCKPROXYFILE 3 +#define SQLITE_FCNTL_LAST_ERRNO 4 +#define SQLITE_FCNTL_SIZE_HINT 5 +#define SQLITE_FCNTL_CHUNK_SIZE 6 +#define SQLITE_FCNTL_FILE_POINTER 7 +#define SQLITE_FCNTL_SYNC_OMITTED 8 +#define SQLITE_FCNTL_WIN32_AV_RETRY 9 +#define SQLITE_FCNTL_PERSIST_WAL 10 +#define SQLITE_FCNTL_OVERWRITE 11 +#define SQLITE_FCNTL_VFSNAME 12 +#define SQLITE_FCNTL_POWERSAFE_OVERWRITE 13 +#define SQLITE_FCNTL_PRAGMA 14 +#define SQLITE_FCNTL_BUSYHANDLER 15 +#define SQLITE_FCNTL_TEMPFILENAME 16 +#define SQLITE_FCNTL_MMAP_SIZE 18 +#define SQLITE_FCNTL_TRACE 19 +#define SQLITE_FCNTL_HAS_MOVED 20 +#define SQLITE_FCNTL_SYNC 21 +#define SQLITE_FCNTL_COMMIT_PHASETWO 22 +#define SQLITE_FCNTL_WIN32_SET_HANDLE 23 +#define SQLITE_FCNTL_WAL_BLOCK 24 +#define SQLITE_FCNTL_ZIPVFS 25 +#define SQLITE_FCNTL_RBU 26 +#define SQLITE_FCNTL_VFS_POINTER 27 +#define SQLITE_FCNTL_JOURNAL_POINTER 28 +#define SQLITE_FCNTL_WIN32_GET_HANDLE 29 +#define SQLITE_FCNTL_PDB 30 +#define SQLITE_FCNTL_BEGIN_ATOMIC_WRITE 31 +#define SQLITE_FCNTL_COMMIT_ATOMIC_WRITE 32 +#define SQLITE_FCNTL_ROLLBACK_ATOMIC_WRITE 33 +#define SQLITE_FCNTL_LOCK_TIMEOUT 34 +#define SQLITE_FCNTL_DATA_VERSION 35 +#define SQLITE_FCNTL_SIZE_LIMIT 36 +#define SQLITE_FCNTL_CKPT_DONE 37 +#define SQLITE_FCNTL_RESERVE_BYTES 38 +#define SQLITE_FCNTL_CKPT_START 39 +#define SQLITE_FCNTL_EXTERNAL_READER 40 +#define SQLITE_FCNTL_CKSM_FILE 41 + +/* deprecated names */ +#define SQLITE_GET_LOCKPROXYFILE SQLITE_FCNTL_GET_LOCKPROXYFILE +#define SQLITE_SET_LOCKPROXYFILE SQLITE_FCNTL_SET_LOCKPROXYFILE +#define SQLITE_LAST_ERRNO SQLITE_FCNTL_LAST_ERRNO + + +/* +** CAPI3REF: Mutex Handle +** +** The mutex module within SQLite defines [sqlite3_mutex] to be an +** abstract type for a mutex object. The SQLite core never looks +** at the internal representation of an [sqlite3_mutex]. It only +** deals with pointers to the [sqlite3_mutex] object. +** +** Mutexes are created using [sqlite3_mutex_alloc()]. +*/ +typedef struct sqlite3_mutex sqlite3_mutex; + +/* +** CAPI3REF: Loadable Extension Thunk +** +** A pointer to the opaque sqlite3_api_routines structure is passed as +** the third parameter to entry points of [loadable extensions]. This +** structure must be typedefed in order to work around compiler warnings +** on some platforms. +*/ +typedef struct sqlite3_api_routines sqlite3_api_routines; + +/* +** CAPI3REF: OS Interface Object +** +** An instance of the sqlite3_vfs object defines the interface between +** the SQLite core and the underlying operating system. The "vfs" +** in the name of the object stands for "virtual file system". See +** the [VFS | VFS documentation] for further information. +** +** The VFS interface is sometimes extended by adding new methods onto +** the end. Each time such an extension occurs, the iVersion field +** is incremented. The iVersion value started out as 1 in +** SQLite [version 3.5.0] on [dateof:3.5.0], then increased to 2 +** with SQLite [version 3.7.0] on [dateof:3.7.0], and then increased +** to 3 with SQLite [version 3.7.6] on [dateof:3.7.6]. Additional fields +** may be appended to the sqlite3_vfs object and the iVersion value +** may increase again in future versions of SQLite. +** Note that due to an oversight, the structure +** of the sqlite3_vfs object changed in the transition from +** SQLite [version 3.5.9] to [version 3.6.0] on [dateof:3.6.0] +** and yet the iVersion field was not increased. +** +** The szOsFile field is the size of the subclassed [sqlite3_file] +** structure used by this VFS. mxPathname is the maximum length of +** a pathname in this VFS. +** +** Registered sqlite3_vfs objects are kept on a linked list formed by +** the pNext pointer. The [sqlite3_vfs_register()] +** and [sqlite3_vfs_unregister()] interfaces manage this list +** in a thread-safe way. The [sqlite3_vfs_find()] interface +** searches the list. Neither the application code nor the VFS +** implementation should use the pNext pointer. +** +** The pNext field is the only field in the sqlite3_vfs +** structure that SQLite will ever modify. SQLite will only access +** or modify this field while holding a particular static mutex. +** The application should never modify anything within the sqlite3_vfs +** object once the object has been registered. +** +** The zName field holds the name of the VFS module. The name must +** be unique across all VFS modules. +** +** [[sqlite3_vfs.xOpen]] +** ^SQLite guarantees that the zFilename parameter to xOpen +** is either a NULL pointer or string obtained +** from xFullPathname() with an optional suffix added. +** ^If a suffix is added to the zFilename parameter, it will +** consist of a single "-" character followed by no more than +** 11 alphanumeric and/or "-" characters. +** ^SQLite further guarantees that +** the string will be valid and unchanged until xClose() is +** called. Because of the previous sentence, +** the [sqlite3_file] can safely store a pointer to the +** filename if it needs to remember the filename for some reason. +** If the zFilename parameter to xOpen is a NULL pointer then xOpen +** must invent its own temporary name for the file. ^Whenever the +** xFilename parameter is NULL it will also be the case that the +** flags parameter will include [SQLITE_OPEN_DELETEONCLOSE]. +** +** The flags argument to xOpen() includes all bits set in +** the flags argument to [sqlite3_open_v2()]. Or if [sqlite3_open()] +** or [sqlite3_open16()] is used, then flags includes at least +** [SQLITE_OPEN_READWRITE] | [SQLITE_OPEN_CREATE]. +** If xOpen() opens a file read-only then it sets *pOutFlags to +** include [SQLITE_OPEN_READONLY]. Other bits in *pOutFlags may be set. +** +** ^(SQLite will also add one of the following flags to the xOpen() +** call, depending on the object being opened: +** +**
      +**
    • [SQLITE_OPEN_MAIN_DB] +**
    • [SQLITE_OPEN_MAIN_JOURNAL] +**
    • [SQLITE_OPEN_TEMP_DB] +**
    • [SQLITE_OPEN_TEMP_JOURNAL] +**
    • [SQLITE_OPEN_TRANSIENT_DB] +**
    • [SQLITE_OPEN_SUBJOURNAL] +**
    • [SQLITE_OPEN_SUPER_JOURNAL] +**
    • [SQLITE_OPEN_WAL] +**
    )^ +** +** The file I/O implementation can use the object type flags to +** change the way it deals with files. For example, an application +** that does not care about crash recovery or rollback might make +** the open of a journal file a no-op. Writes to this journal would +** also be no-ops, and any attempt to read the journal would return +** SQLITE_IOERR. Or the implementation might recognize that a database +** file will be doing page-aligned sector reads and writes in a random +** order and set up its I/O subsystem accordingly. +** +** SQLite might also add one of the following flags to the xOpen method: +** +**
      +**
    • [SQLITE_OPEN_DELETEONCLOSE] +**
    • [SQLITE_OPEN_EXCLUSIVE] +**
    +** +** The [SQLITE_OPEN_DELETEONCLOSE] flag means the file should be +** deleted when it is closed. ^The [SQLITE_OPEN_DELETEONCLOSE] +** will be set for TEMP databases and their journals, transient +** databases, and subjournals. +** +** ^The [SQLITE_OPEN_EXCLUSIVE] flag is always used in conjunction +** with the [SQLITE_OPEN_CREATE] flag, which are both directly +** analogous to the O_EXCL and O_CREAT flags of the POSIX open() +** API. The SQLITE_OPEN_EXCLUSIVE flag, when paired with the +** SQLITE_OPEN_CREATE, is used to indicate that file should always +** be created, and that it is an error if it already exists. +** It is not used to indicate the file should be opened +** for exclusive access. +** +** ^At least szOsFile bytes of memory are allocated by SQLite +** to hold the [sqlite3_file] structure passed as the third +** argument to xOpen. The xOpen method does not have to +** allocate the structure; it should just fill it in. Note that +** the xOpen method must set the sqlite3_file.pMethods to either +** a valid [sqlite3_io_methods] object or to NULL. xOpen must do +** this even if the open fails. SQLite expects that the sqlite3_file.pMethods +** element will be valid after xOpen returns regardless of the success +** or failure of the xOpen call. +** +** [[sqlite3_vfs.xAccess]] +** ^The flags argument to xAccess() may be [SQLITE_ACCESS_EXISTS] +** to test for the existence of a file, or [SQLITE_ACCESS_READWRITE] to +** test whether a file is readable and writable, or [SQLITE_ACCESS_READ] +** to test whether a file is at least readable. The SQLITE_ACCESS_READ +** flag is never actually used and is not implemented in the built-in +** VFSes of SQLite. The file is named by the second argument and can be a +** directory. The xAccess method returns [SQLITE_OK] on success or some +** non-zero error code if there is an I/O error or if the name of +** the file given in the second argument is illegal. If SQLITE_OK +** is returned, then non-zero or zero is written into *pResOut to indicate +** whether or not the file is accessible. +** +** ^SQLite will always allocate at least mxPathname+1 bytes for the +** output buffer xFullPathname. The exact size of the output buffer +** is also passed as a parameter to both methods. If the output buffer +** is not large enough, [SQLITE_CANTOPEN] should be returned. Since this is +** handled as a fatal error by SQLite, vfs implementations should endeavor +** to prevent this by setting mxPathname to a sufficiently large value. +** +** The xRandomness(), xSleep(), xCurrentTime(), and xCurrentTimeInt64() +** interfaces are not strictly a part of the filesystem, but they are +** included in the VFS structure for completeness. +** The xRandomness() function attempts to return nBytes bytes +** of good-quality randomness into zOut. The return value is +** the actual number of bytes of randomness obtained. +** The xSleep() method causes the calling thread to sleep for at +** least the number of microseconds given. ^The xCurrentTime() +** method returns a Julian Day Number for the current date and time as +** a floating point value. +** ^The xCurrentTimeInt64() method returns, as an integer, the Julian +** Day Number multiplied by 86400000 (the number of milliseconds in +** a 24-hour day). +** ^SQLite will use the xCurrentTimeInt64() method to get the current +** date and time if that method is available (if iVersion is 2 or +** greater and the function pointer is not NULL) and will fall back +** to xCurrentTime() if xCurrentTimeInt64() is unavailable. +** +** ^The xSetSystemCall(), xGetSystemCall(), and xNestSystemCall() interfaces +** are not used by the SQLite core. These optional interfaces are provided +** by some VFSes to facilitate testing of the VFS code. By overriding +** system calls with functions under its control, a test program can +** simulate faults and error conditions that would otherwise be difficult +** or impossible to induce. The set of system calls that can be overridden +** varies from one VFS to another, and from one version of the same VFS to the +** next. Applications that use these interfaces must be prepared for any +** or all of these interfaces to be NULL or for their behavior to change +** from one release to the next. Applications must not attempt to access +** any of these methods if the iVersion of the VFS is less than 3. +*/ +typedef struct sqlite3_vfs sqlite3_vfs; +typedef void (*sqlite3_syscall_ptr)(void); +struct sqlite3_vfs { + int iVersion; /* Structure version number (currently 3) */ + int szOsFile; /* Size of subclassed sqlite3_file */ + int mxPathname; /* Maximum file pathname length */ + sqlite3_vfs *pNext; /* Next registered VFS */ + const char *zName; /* Name of this virtual file system */ + void *pAppData; /* Pointer to application-specific data */ + int (*xOpen)(sqlite3_vfs*, const char *zName, sqlite3_file*, + int flags, int *pOutFlags); + int (*xDelete)(sqlite3_vfs*, const char *zName, int syncDir); + int (*xAccess)(sqlite3_vfs*, const char *zName, int flags, int *pResOut); + int (*xFullPathname)(sqlite3_vfs*, const char *zName, int nOut, char *zOut); + void *(*xDlOpen)(sqlite3_vfs*, const char *zFilename); + void (*xDlError)(sqlite3_vfs*, int nByte, char *zErrMsg); + void (*(*xDlSym)(sqlite3_vfs*,void*, const char *zSymbol))(void); + void (*xDlClose)(sqlite3_vfs*, void*); + int (*xRandomness)(sqlite3_vfs*, int nByte, char *zOut); + int (*xSleep)(sqlite3_vfs*, int microseconds); + int (*xCurrentTime)(sqlite3_vfs*, double*); + int (*xGetLastError)(sqlite3_vfs*, int, char *); + /* + ** The methods above are in version 1 of the sqlite_vfs object + ** definition. Those that follow are added in version 2 or later + */ + int (*xCurrentTimeInt64)(sqlite3_vfs*, sqlite3_int64*); + /* + ** The methods above are in versions 1 and 2 of the sqlite_vfs object. + ** Those below are for version 3 and greater. + */ + int (*xSetSystemCall)(sqlite3_vfs*, const char *zName, sqlite3_syscall_ptr); + sqlite3_syscall_ptr (*xGetSystemCall)(sqlite3_vfs*, const char *zName); + const char *(*xNextSystemCall)(sqlite3_vfs*, const char *zName); + /* + ** The methods above are in versions 1 through 3 of the sqlite_vfs object. + ** New fields may be appended in future versions. The iVersion + ** value will increment whenever this happens. + */ +}; + +/* +** CAPI3REF: Flags for the xAccess VFS method +** +** These integer constants can be used as the third parameter to +** the xAccess method of an [sqlite3_vfs] object. They determine +** what kind of permissions the xAccess method is looking for. +** With SQLITE_ACCESS_EXISTS, the xAccess method +** simply checks whether the file exists. +** With SQLITE_ACCESS_READWRITE, the xAccess method +** checks whether the named directory is both readable and writable +** (in other words, if files can be added, removed, and renamed within +** the directory). +** The SQLITE_ACCESS_READWRITE constant is currently used only by the +** [temp_store_directory pragma], though this could change in a future +** release of SQLite. +** With SQLITE_ACCESS_READ, the xAccess method +** checks whether the file is readable. The SQLITE_ACCESS_READ constant is +** currently unused, though it might be used in a future release of +** SQLite. +*/ +#define SQLITE_ACCESS_EXISTS 0 +#define SQLITE_ACCESS_READWRITE 1 /* Used by PRAGMA temp_store_directory */ +#define SQLITE_ACCESS_READ 2 /* Unused */ + +/* +** CAPI3REF: Flags for the xShmLock VFS method +** +** These integer constants define the various locking operations +** allowed by the xShmLock method of [sqlite3_io_methods]. The +** following are the only legal combinations of flags to the +** xShmLock method: +** +**
      +**
    • SQLITE_SHM_LOCK | SQLITE_SHM_SHARED +**
    • SQLITE_SHM_LOCK | SQLITE_SHM_EXCLUSIVE +**
    • SQLITE_SHM_UNLOCK | SQLITE_SHM_SHARED +**
    • SQLITE_SHM_UNLOCK | SQLITE_SHM_EXCLUSIVE +**
    +** +** When unlocking, the same SHARED or EXCLUSIVE flag must be supplied as +** was given on the corresponding lock. +** +** The xShmLock method can transition between unlocked and SHARED or +** between unlocked and EXCLUSIVE. It cannot transition between SHARED +** and EXCLUSIVE. +*/ +#define SQLITE_SHM_UNLOCK 1 +#define SQLITE_SHM_LOCK 2 +#define SQLITE_SHM_SHARED 4 +#define SQLITE_SHM_EXCLUSIVE 8 + +/* +** CAPI3REF: Maximum xShmLock index +** +** The xShmLock method on [sqlite3_io_methods] may use values +** between 0 and this upper bound as its "offset" argument. +** The SQLite core will never attempt to acquire or release a +** lock outside of this range +*/ +#define SQLITE_SHM_NLOCK 8 + + +/* +** CAPI3REF: Initialize The SQLite Library +** +** ^The sqlite3_initialize() routine initializes the +** SQLite library. ^The sqlite3_shutdown() routine +** deallocates any resources that were allocated by sqlite3_initialize(). +** These routines are designed to aid in process initialization and +** shutdown on embedded systems. Workstation applications using +** SQLite normally do not need to invoke either of these routines. +** +** A call to sqlite3_initialize() is an "effective" call if it is +** the first time sqlite3_initialize() is invoked during the lifetime of +** the process, or if it is the first time sqlite3_initialize() is invoked +** following a call to sqlite3_shutdown(). ^(Only an effective call +** of sqlite3_initialize() does any initialization. All other calls +** are harmless no-ops.)^ +** +** A call to sqlite3_shutdown() is an "effective" call if it is the first +** call to sqlite3_shutdown() since the last sqlite3_initialize(). ^(Only +** an effective call to sqlite3_shutdown() does any deinitialization. +** All other valid calls to sqlite3_shutdown() are harmless no-ops.)^ +** +** The sqlite3_initialize() interface is threadsafe, but sqlite3_shutdown() +** is not. The sqlite3_shutdown() interface must only be called from a +** single thread. All open [database connections] must be closed and all +** other SQLite resources must be deallocated prior to invoking +** sqlite3_shutdown(). +** +** Among other things, ^sqlite3_initialize() will invoke +** sqlite3_os_init(). Similarly, ^sqlite3_shutdown() +** will invoke sqlite3_os_end(). +** +** ^The sqlite3_initialize() routine returns [SQLITE_OK] on success. +** ^If for some reason, sqlite3_initialize() is unable to initialize +** the library (perhaps it is unable to allocate a needed resource such +** as a mutex) it returns an [error code] other than [SQLITE_OK]. +** +** ^The sqlite3_initialize() routine is called internally by many other +** SQLite interfaces so that an application usually does not need to +** invoke sqlite3_initialize() directly. For example, [sqlite3_open()] +** calls sqlite3_initialize() so the SQLite library will be automatically +** initialized when [sqlite3_open()] is called if it has not be initialized +** already. ^However, if SQLite is compiled with the [SQLITE_OMIT_AUTOINIT] +** compile-time option, then the automatic calls to sqlite3_initialize() +** are omitted and the application must call sqlite3_initialize() directly +** prior to using any other SQLite interface. For maximum portability, +** it is recommended that applications always invoke sqlite3_initialize() +** directly prior to using any other SQLite interface. Future releases +** of SQLite may require this. In other words, the behavior exhibited +** when SQLite is compiled with [SQLITE_OMIT_AUTOINIT] might become the +** default behavior in some future release of SQLite. +** +** The sqlite3_os_init() routine does operating-system specific +** initialization of the SQLite library. The sqlite3_os_end() +** routine undoes the effect of sqlite3_os_init(). Typical tasks +** performed by these routines include allocation or deallocation +** of static resources, initialization of global variables, +** setting up a default [sqlite3_vfs] module, or setting up +** a default configuration using [sqlite3_config()]. +** +** The application should never invoke either sqlite3_os_init() +** or sqlite3_os_end() directly. The application should only invoke +** sqlite3_initialize() and sqlite3_shutdown(). The sqlite3_os_init() +** interface is called automatically by sqlite3_initialize() and +** sqlite3_os_end() is called by sqlite3_shutdown(). Appropriate +** implementations for sqlite3_os_init() and sqlite3_os_end() +** are built into SQLite when it is compiled for Unix, Windows, or OS/2. +** When [custom builds | built for other platforms] +** (using the [SQLITE_OS_OTHER=1] compile-time +** option) the application must supply a suitable implementation for +** sqlite3_os_init() and sqlite3_os_end(). An application-supplied +** implementation of sqlite3_os_init() or sqlite3_os_end() +** must return [SQLITE_OK] on success and some other [error code] upon +** failure. +*/ +SQLITE_API int sqlite3_initialize(void); +SQLITE_API int sqlite3_shutdown(void); +SQLITE_API int sqlite3_os_init(void); +SQLITE_API int sqlite3_os_end(void); + +/* +** CAPI3REF: Configuring The SQLite Library +** +** The sqlite3_config() interface is used to make global configuration +** changes to SQLite in order to tune SQLite to the specific needs of +** the application. The default configuration is recommended for most +** applications and so this routine is usually not necessary. It is +** provided to support rare applications with unusual needs. +** +** The sqlite3_config() interface is not threadsafe. The application +** must ensure that no other SQLite interfaces are invoked by other +** threads while sqlite3_config() is running. +** +** The sqlite3_config() interface +** may only be invoked prior to library initialization using +** [sqlite3_initialize()] or after shutdown by [sqlite3_shutdown()]. +** ^If sqlite3_config() is called after [sqlite3_initialize()] and before +** [sqlite3_shutdown()] then it will return SQLITE_MISUSE. +** Note, however, that ^sqlite3_config() can be called as part of the +** implementation of an application-defined [sqlite3_os_init()]. +** +** The first argument to sqlite3_config() is an integer +** [configuration option] that determines +** what property of SQLite is to be configured. Subsequent arguments +** vary depending on the [configuration option] +** in the first argument. +** +** ^When a configuration option is set, sqlite3_config() returns [SQLITE_OK]. +** ^If the option is unknown or SQLite is unable to set the option +** then this routine returns a non-zero [error code]. +*/ +SQLITE_API int sqlite3_config(int, ...); + +/* +** CAPI3REF: Configure database connections +** METHOD: sqlite3 +** +** The sqlite3_db_config() interface is used to make configuration +** changes to a [database connection]. The interface is similar to +** [sqlite3_config()] except that the changes apply to a single +** [database connection] (specified in the first argument). +** +** The second argument to sqlite3_db_config(D,V,...) is the +** [SQLITE_DBCONFIG_LOOKASIDE | configuration verb] - an integer code +** that indicates what aspect of the [database connection] is being configured. +** Subsequent arguments vary depending on the configuration verb. +** +** ^Calls to sqlite3_db_config() return SQLITE_OK if and only if +** the call is considered successful. +*/ +SQLITE_API int sqlite3_db_config(sqlite3*, int op, ...); + +/* +** CAPI3REF: Memory Allocation Routines +** +** An instance of this object defines the interface between SQLite +** and low-level memory allocation routines. +** +** This object is used in only one place in the SQLite interface. +** A pointer to an instance of this object is the argument to +** [sqlite3_config()] when the configuration option is +** [SQLITE_CONFIG_MALLOC] or [SQLITE_CONFIG_GETMALLOC]. +** By creating an instance of this object +** and passing it to [sqlite3_config]([SQLITE_CONFIG_MALLOC]) +** during configuration, an application can specify an alternative +** memory allocation subsystem for SQLite to use for all of its +** dynamic memory needs. +** +** Note that SQLite comes with several [built-in memory allocators] +** that are perfectly adequate for the overwhelming majority of applications +** and that this object is only useful to a tiny minority of applications +** with specialized memory allocation requirements. This object is +** also used during testing of SQLite in order to specify an alternative +** memory allocator that simulates memory out-of-memory conditions in +** order to verify that SQLite recovers gracefully from such +** conditions. +** +** The xMalloc, xRealloc, and xFree methods must work like the +** malloc(), realloc() and free() functions from the standard C library. +** ^SQLite guarantees that the second argument to +** xRealloc is always a value returned by a prior call to xRoundup. +** +** xSize should return the allocated size of a memory allocation +** previously obtained from xMalloc or xRealloc. The allocated size +** is always at least as big as the requested size but may be larger. +** +** The xRoundup method returns what would be the allocated size of +** a memory allocation given a particular requested size. Most memory +** allocators round up memory allocations at least to the next multiple +** of 8. Some allocators round up to a larger multiple or to a power of 2. +** Every memory allocation request coming in through [sqlite3_malloc()] +** or [sqlite3_realloc()] first calls xRoundup. If xRoundup returns 0, +** that causes the corresponding memory allocation to fail. +** +** The xInit method initializes the memory allocator. For example, +** it might allocate any required mutexes or initialize internal data +** structures. The xShutdown method is invoked (indirectly) by +** [sqlite3_shutdown()] and should deallocate any resources acquired +** by xInit. The pAppData pointer is used as the only parameter to +** xInit and xShutdown. +** +** SQLite holds the [SQLITE_MUTEX_STATIC_MAIN] mutex when it invokes +** the xInit method, so the xInit method need not be threadsafe. The +** xShutdown method is only called from [sqlite3_shutdown()] so it does +** not need to be threadsafe either. For all other methods, SQLite +** holds the [SQLITE_MUTEX_STATIC_MEM] mutex as long as the +** [SQLITE_CONFIG_MEMSTATUS] configuration option is turned on (which +** it is by default) and so the methods are automatically serialized. +** However, if [SQLITE_CONFIG_MEMSTATUS] is disabled, then the other +** methods must be threadsafe or else make their own arrangements for +** serialization. +** +** SQLite will never invoke xInit() more than once without an intervening +** call to xShutdown(). +*/ +typedef struct sqlite3_mem_methods sqlite3_mem_methods; +struct sqlite3_mem_methods { + void *(*xMalloc)(int); /* Memory allocation function */ + void (*xFree)(void*); /* Free a prior allocation */ + void *(*xRealloc)(void*,int); /* Resize an allocation */ + int (*xSize)(void*); /* Return the size of an allocation */ + int (*xRoundup)(int); /* Round up request size to allocation size */ + int (*xInit)(void*); /* Initialize the memory allocator */ + void (*xShutdown)(void*); /* Deinitialize the memory allocator */ + void *pAppData; /* Argument to xInit() and xShutdown() */ +}; + +/* +** CAPI3REF: Configuration Options +** KEYWORDS: {configuration option} +** +** These constants are the available integer configuration options that +** can be passed as the first argument to the [sqlite3_config()] interface. +** +** New configuration options may be added in future releases of SQLite. +** Existing configuration options might be discontinued. Applications +** should check the return code from [sqlite3_config()] to make sure that +** the call worked. The [sqlite3_config()] interface will return a +** non-zero [error code] if a discontinued or unsupported configuration option +** is invoked. +** +**
    +** [[SQLITE_CONFIG_SINGLETHREAD]]
    SQLITE_CONFIG_SINGLETHREAD
    +**
    There are no arguments to this option. ^This option sets the +** [threading mode] to Single-thread. In other words, it disables +** all mutexing and puts SQLite into a mode where it can only be used +** by a single thread. ^If SQLite is compiled with +** the [SQLITE_THREADSAFE | SQLITE_THREADSAFE=0] compile-time option then +** it is not possible to change the [threading mode] from its default +** value of Single-thread and so [sqlite3_config()] will return +** [SQLITE_ERROR] if called with the SQLITE_CONFIG_SINGLETHREAD +** configuration option.
    +** +** [[SQLITE_CONFIG_MULTITHREAD]]
    SQLITE_CONFIG_MULTITHREAD
    +**
    There are no arguments to this option. ^This option sets the +** [threading mode] to Multi-thread. In other words, it disables +** mutexing on [database connection] and [prepared statement] objects. +** The application is responsible for serializing access to +** [database connections] and [prepared statements]. But other mutexes +** are enabled so that SQLite will be safe to use in a multi-threaded +** environment as long as no two threads attempt to use the same +** [database connection] at the same time. ^If SQLite is compiled with +** the [SQLITE_THREADSAFE | SQLITE_THREADSAFE=0] compile-time option then +** it is not possible to set the Multi-thread [threading mode] and +** [sqlite3_config()] will return [SQLITE_ERROR] if called with the +** SQLITE_CONFIG_MULTITHREAD configuration option.
    +** +** [[SQLITE_CONFIG_SERIALIZED]]
    SQLITE_CONFIG_SERIALIZED
    +**
    There are no arguments to this option. ^This option sets the +** [threading mode] to Serialized. In other words, this option enables +** all mutexes including the recursive +** mutexes on [database connection] and [prepared statement] objects. +** In this mode (which is the default when SQLite is compiled with +** [SQLITE_THREADSAFE=1]) the SQLite library will itself serialize access +** to [database connections] and [prepared statements] so that the +** application is free to use the same [database connection] or the +** same [prepared statement] in different threads at the same time. +** ^If SQLite is compiled with +** the [SQLITE_THREADSAFE | SQLITE_THREADSAFE=0] compile-time option then +** it is not possible to set the Serialized [threading mode] and +** [sqlite3_config()] will return [SQLITE_ERROR] if called with the +** SQLITE_CONFIG_SERIALIZED configuration option.
    +** +** [[SQLITE_CONFIG_MALLOC]]
    SQLITE_CONFIG_MALLOC
    +**
    ^(The SQLITE_CONFIG_MALLOC option takes a single argument which is +** a pointer to an instance of the [sqlite3_mem_methods] structure. +** The argument specifies +** alternative low-level memory allocation routines to be used in place of +** the memory allocation routines built into SQLite.)^ ^SQLite makes +** its own private copy of the content of the [sqlite3_mem_methods] structure +** before the [sqlite3_config()] call returns.
    +** +** [[SQLITE_CONFIG_GETMALLOC]]
    SQLITE_CONFIG_GETMALLOC
    +**
    ^(The SQLITE_CONFIG_GETMALLOC option takes a single argument which +** is a pointer to an instance of the [sqlite3_mem_methods] structure. +** The [sqlite3_mem_methods] +** structure is filled with the currently defined memory allocation routines.)^ +** This option can be used to overload the default memory allocation +** routines with a wrapper that simulations memory allocation failure or +** tracks memory usage, for example.
    +** +** [[SQLITE_CONFIG_SMALL_MALLOC]]
    SQLITE_CONFIG_SMALL_MALLOC
    +**
    ^The SQLITE_CONFIG_SMALL_MALLOC option takes single argument of +** type int, interpreted as a boolean, which if true provides a hint to +** SQLite that it should avoid large memory allocations if possible. +** SQLite will run faster if it is free to make large memory allocations, +** but some application might prefer to run slower in exchange for +** guarantees about memory fragmentation that are possible if large +** allocations are avoided. This hint is normally off. +**
    +** +** [[SQLITE_CONFIG_MEMSTATUS]]
    SQLITE_CONFIG_MEMSTATUS
    +**
    ^The SQLITE_CONFIG_MEMSTATUS option takes single argument of type int, +** interpreted as a boolean, which enables or disables the collection of +** memory allocation statistics. ^(When memory allocation statistics are +** disabled, the following SQLite interfaces become non-operational: +**
      +**
    • [sqlite3_hard_heap_limit64()] +**
    • [sqlite3_memory_used()] +**
    • [sqlite3_memory_highwater()] +**
    • [sqlite3_soft_heap_limit64()] +**
    • [sqlite3_status64()] +**
    )^ +** ^Memory allocation statistics are enabled by default unless SQLite is +** compiled with [SQLITE_DEFAULT_MEMSTATUS]=0 in which case memory +** allocation statistics are disabled by default. +**
    +** +** [[SQLITE_CONFIG_SCRATCH]]
    SQLITE_CONFIG_SCRATCH
    +**
    The SQLITE_CONFIG_SCRATCH option is no longer used. +**
    +** +** [[SQLITE_CONFIG_PAGECACHE]]
    SQLITE_CONFIG_PAGECACHE
    +**
    ^The SQLITE_CONFIG_PAGECACHE option specifies a memory pool +** that SQLite can use for the database page cache with the default page +** cache implementation. +** This configuration option is a no-op if an application-defined page +** cache implementation is loaded using the [SQLITE_CONFIG_PCACHE2]. +** ^There are three arguments to SQLITE_CONFIG_PAGECACHE: A pointer to +** 8-byte aligned memory (pMem), the size of each page cache line (sz), +** and the number of cache lines (N). +** The sz argument should be the size of the largest database page +** (a power of two between 512 and 65536) plus some extra bytes for each +** page header. ^The number of extra bytes needed by the page header +** can be determined using [SQLITE_CONFIG_PCACHE_HDRSZ]. +** ^It is harmless, apart from the wasted memory, +** for the sz parameter to be larger than necessary. The pMem +** argument must be either a NULL pointer or a pointer to an 8-byte +** aligned block of memory of at least sz*N bytes, otherwise +** subsequent behavior is undefined. +** ^When pMem is not NULL, SQLite will strive to use the memory provided +** to satisfy page cache needs, falling back to [sqlite3_malloc()] if +** a page cache line is larger than sz bytes or if all of the pMem buffer +** is exhausted. +** ^If pMem is NULL and N is non-zero, then each database connection +** does an initial bulk allocation for page cache memory +** from [sqlite3_malloc()] sufficient for N cache lines if N is positive or +** of -1024*N bytes if N is negative, . ^If additional +** page cache memory is needed beyond what is provided by the initial +** allocation, then SQLite goes to [sqlite3_malloc()] separately for each +** additional cache line.
    +** +** [[SQLITE_CONFIG_HEAP]]
    SQLITE_CONFIG_HEAP
    +**
    ^The SQLITE_CONFIG_HEAP option specifies a static memory buffer +** that SQLite will use for all of its dynamic memory allocation needs +** beyond those provided for by [SQLITE_CONFIG_PAGECACHE]. +** ^The SQLITE_CONFIG_HEAP option is only available if SQLite is compiled +** with either [SQLITE_ENABLE_MEMSYS3] or [SQLITE_ENABLE_MEMSYS5] and returns +** [SQLITE_ERROR] if invoked otherwise. +** ^There are three arguments to SQLITE_CONFIG_HEAP: +** An 8-byte aligned pointer to the memory, +** the number of bytes in the memory buffer, and the minimum allocation size. +** ^If the first pointer (the memory pointer) is NULL, then SQLite reverts +** to using its default memory allocator (the system malloc() implementation), +** undoing any prior invocation of [SQLITE_CONFIG_MALLOC]. ^If the +** memory pointer is not NULL then the alternative memory +** allocator is engaged to handle all of SQLites memory allocation needs. +** The first pointer (the memory pointer) must be aligned to an 8-byte +** boundary or subsequent behavior of SQLite will be undefined. +** The minimum allocation size is capped at 2**12. Reasonable values +** for the minimum allocation size are 2**5 through 2**8.
    +** +** [[SQLITE_CONFIG_MUTEX]]
    SQLITE_CONFIG_MUTEX
    +**
    ^(The SQLITE_CONFIG_MUTEX option takes a single argument which is a +** pointer to an instance of the [sqlite3_mutex_methods] structure. +** The argument specifies alternative low-level mutex routines to be used +** in place the mutex routines built into SQLite.)^ ^SQLite makes a copy of +** the content of the [sqlite3_mutex_methods] structure before the call to +** [sqlite3_config()] returns. ^If SQLite is compiled with +** the [SQLITE_THREADSAFE | SQLITE_THREADSAFE=0] compile-time option then +** the entire mutexing subsystem is omitted from the build and hence calls to +** [sqlite3_config()] with the SQLITE_CONFIG_MUTEX configuration option will +** return [SQLITE_ERROR].
    +** +** [[SQLITE_CONFIG_GETMUTEX]]
    SQLITE_CONFIG_GETMUTEX
    +**
    ^(The SQLITE_CONFIG_GETMUTEX option takes a single argument which +** is a pointer to an instance of the [sqlite3_mutex_methods] structure. The +** [sqlite3_mutex_methods] +** structure is filled with the currently defined mutex routines.)^ +** This option can be used to overload the default mutex allocation +** routines with a wrapper used to track mutex usage for performance +** profiling or testing, for example. ^If SQLite is compiled with +** the [SQLITE_THREADSAFE | SQLITE_THREADSAFE=0] compile-time option then +** the entire mutexing subsystem is omitted from the build and hence calls to +** [sqlite3_config()] with the SQLITE_CONFIG_GETMUTEX configuration option will +** return [SQLITE_ERROR].
    +** +** [[SQLITE_CONFIG_LOOKASIDE]]
    SQLITE_CONFIG_LOOKASIDE
    +**
    ^(The SQLITE_CONFIG_LOOKASIDE option takes two arguments that determine +** the default size of lookaside memory on each [database connection]. +** The first argument is the +** size of each lookaside buffer slot and the second is the number of +** slots allocated to each database connection.)^ ^(SQLITE_CONFIG_LOOKASIDE +** sets the default lookaside size. The [SQLITE_DBCONFIG_LOOKASIDE] +** option to [sqlite3_db_config()] can be used to change the lookaside +** configuration on individual connections.)^
    +** +** [[SQLITE_CONFIG_PCACHE2]]
    SQLITE_CONFIG_PCACHE2
    +**
    ^(The SQLITE_CONFIG_PCACHE2 option takes a single argument which is +** a pointer to an [sqlite3_pcache_methods2] object. This object specifies +** the interface to a custom page cache implementation.)^ +** ^SQLite makes a copy of the [sqlite3_pcache_methods2] object.
    +** +** [[SQLITE_CONFIG_GETPCACHE2]]
    SQLITE_CONFIG_GETPCACHE2
    +**
    ^(The SQLITE_CONFIG_GETPCACHE2 option takes a single argument which +** is a pointer to an [sqlite3_pcache_methods2] object. SQLite copies of +** the current page cache implementation into that object.)^
    +** +** [[SQLITE_CONFIG_LOG]]
    SQLITE_CONFIG_LOG
    +**
    The SQLITE_CONFIG_LOG option is used to configure the SQLite +** global [error log]. +** (^The SQLITE_CONFIG_LOG option takes two arguments: a pointer to a +** function with a call signature of void(*)(void*,int,const char*), +** and a pointer to void. ^If the function pointer is not NULL, it is +** invoked by [sqlite3_log()] to process each logging event. ^If the +** function pointer is NULL, the [sqlite3_log()] interface becomes a no-op. +** ^The void pointer that is the second argument to SQLITE_CONFIG_LOG is +** passed through as the first parameter to the application-defined logger +** function whenever that function is invoked. ^The second parameter to +** the logger function is a copy of the first parameter to the corresponding +** [sqlite3_log()] call and is intended to be a [result code] or an +** [extended result code]. ^The third parameter passed to the logger is +** log message after formatting via [sqlite3_snprintf()]. +** The SQLite logging interface is not reentrant; the logger function +** supplied by the application must not invoke any SQLite interface. +** In a multi-threaded application, the application-defined logger +** function must be threadsafe.
    +** +** [[SQLITE_CONFIG_URI]]
    SQLITE_CONFIG_URI +**
    ^(The SQLITE_CONFIG_URI option takes a single argument of type int. +** If non-zero, then URI handling is globally enabled. If the parameter is zero, +** then URI handling is globally disabled.)^ ^If URI handling is globally +** enabled, all filenames passed to [sqlite3_open()], [sqlite3_open_v2()], +** [sqlite3_open16()] or +** specified as part of [ATTACH] commands are interpreted as URIs, regardless +** of whether or not the [SQLITE_OPEN_URI] flag is set when the database +** connection is opened. ^If it is globally disabled, filenames are +** only interpreted as URIs if the SQLITE_OPEN_URI flag is set when the +** database connection is opened. ^(By default, URI handling is globally +** disabled. The default value may be changed by compiling with the +** [SQLITE_USE_URI] symbol defined.)^ +** +** [[SQLITE_CONFIG_COVERING_INDEX_SCAN]]
    SQLITE_CONFIG_COVERING_INDEX_SCAN +**
    ^The SQLITE_CONFIG_COVERING_INDEX_SCAN option takes a single integer +** argument which is interpreted as a boolean in order to enable or disable +** the use of covering indices for full table scans in the query optimizer. +** ^The default setting is determined +** by the [SQLITE_ALLOW_COVERING_INDEX_SCAN] compile-time option, or is "on" +** if that compile-time option is omitted. +** The ability to disable the use of covering indices for full table scans +** is because some incorrectly coded legacy applications might malfunction +** when the optimization is enabled. Providing the ability to +** disable the optimization allows the older, buggy application code to work +** without change even with newer versions of SQLite. +** +** [[SQLITE_CONFIG_PCACHE]] [[SQLITE_CONFIG_GETPCACHE]] +**
    SQLITE_CONFIG_PCACHE and SQLITE_CONFIG_GETPCACHE +**
    These options are obsolete and should not be used by new code. +** They are retained for backwards compatibility but are now no-ops. +**
    +** +** [[SQLITE_CONFIG_SQLLOG]] +**
    SQLITE_CONFIG_SQLLOG +**
    This option is only available if sqlite is compiled with the +** [SQLITE_ENABLE_SQLLOG] pre-processor macro defined. The first argument should +** be a pointer to a function of type void(*)(void*,sqlite3*,const char*, int). +** The second should be of type (void*). The callback is invoked by the library +** in three separate circumstances, identified by the value passed as the +** fourth parameter. If the fourth parameter is 0, then the database connection +** passed as the second argument has just been opened. The third argument +** points to a buffer containing the name of the main database file. If the +** fourth parameter is 1, then the SQL statement that the third parameter +** points to has just been executed. Or, if the fourth parameter is 2, then +** the connection being passed as the second parameter is being closed. The +** third parameter is passed NULL In this case. An example of using this +** configuration option can be seen in the "test_sqllog.c" source file in +** the canonical SQLite source tree.
    +** +** [[SQLITE_CONFIG_MMAP_SIZE]] +**
    SQLITE_CONFIG_MMAP_SIZE +**
    ^SQLITE_CONFIG_MMAP_SIZE takes two 64-bit integer (sqlite3_int64) values +** that are the default mmap size limit (the default setting for +** [PRAGMA mmap_size]) and the maximum allowed mmap size limit. +** ^The default setting can be overridden by each database connection using +** either the [PRAGMA mmap_size] command, or by using the +** [SQLITE_FCNTL_MMAP_SIZE] file control. ^(The maximum allowed mmap size +** will be silently truncated if necessary so that it does not exceed the +** compile-time maximum mmap size set by the +** [SQLITE_MAX_MMAP_SIZE] compile-time option.)^ +** ^If either argument to this option is negative, then that argument is +** changed to its compile-time default. +** +** [[SQLITE_CONFIG_WIN32_HEAPSIZE]] +**
    SQLITE_CONFIG_WIN32_HEAPSIZE +**
    ^The SQLITE_CONFIG_WIN32_HEAPSIZE option is only available if SQLite is +** compiled for Windows with the [SQLITE_WIN32_MALLOC] pre-processor macro +** defined. ^SQLITE_CONFIG_WIN32_HEAPSIZE takes a 32-bit unsigned integer value +** that specifies the maximum size of the created heap. +** +** [[SQLITE_CONFIG_PCACHE_HDRSZ]] +**
    SQLITE_CONFIG_PCACHE_HDRSZ +**
    ^The SQLITE_CONFIG_PCACHE_HDRSZ option takes a single parameter which +** is a pointer to an integer and writes into that integer the number of extra +** bytes per page required for each page in [SQLITE_CONFIG_PAGECACHE]. +** The amount of extra space required can change depending on the compiler, +** target platform, and SQLite version. +** +** [[SQLITE_CONFIG_PMASZ]] +**
    SQLITE_CONFIG_PMASZ +**
    ^The SQLITE_CONFIG_PMASZ option takes a single parameter which +** is an unsigned integer and sets the "Minimum PMA Size" for the multithreaded +** sorter to that integer. The default minimum PMA Size is set by the +** [SQLITE_SORTER_PMASZ] compile-time option. New threads are launched +** to help with sort operations when multithreaded sorting +** is enabled (using the [PRAGMA threads] command) and the amount of content +** to be sorted exceeds the page size times the minimum of the +** [PRAGMA cache_size] setting and this value. +** +** [[SQLITE_CONFIG_STMTJRNL_SPILL]] +**
    SQLITE_CONFIG_STMTJRNL_SPILL +**
    ^The SQLITE_CONFIG_STMTJRNL_SPILL option takes a single parameter which +** becomes the [statement journal] spill-to-disk threshold. +** [Statement journals] are held in memory until their size (in bytes) +** exceeds this threshold, at which point they are written to disk. +** Or if the threshold is -1, statement journals are always held +** exclusively in memory. +** Since many statement journals never become large, setting the spill +** threshold to a value such as 64KiB can greatly reduce the amount of +** I/O required to support statement rollback. +** The default value for this setting is controlled by the +** [SQLITE_STMTJRNL_SPILL] compile-time option. +** +** [[SQLITE_CONFIG_SORTERREF_SIZE]] +**
    SQLITE_CONFIG_SORTERREF_SIZE +**
    The SQLITE_CONFIG_SORTERREF_SIZE option accepts a single parameter +** of type (int) - the new value of the sorter-reference size threshold. +** Usually, when SQLite uses an external sort to order records according +** to an ORDER BY clause, all fields required by the caller are present in the +** sorted records. However, if SQLite determines based on the declared type +** of a table column that its values are likely to be very large - larger +** than the configured sorter-reference size threshold - then a reference +** is stored in each sorted record and the required column values loaded +** from the database as records are returned in sorted order. The default +** value for this option is to never use this optimization. Specifying a +** negative value for this option restores the default behaviour. +** This option is only available if SQLite is compiled with the +** [SQLITE_ENABLE_SORTER_REFERENCES] compile-time option. +** +** [[SQLITE_CONFIG_MEMDB_MAXSIZE]] +**
    SQLITE_CONFIG_MEMDB_MAXSIZE +**
    The SQLITE_CONFIG_MEMDB_MAXSIZE option accepts a single parameter +** [sqlite3_int64] parameter which is the default maximum size for an in-memory +** database created using [sqlite3_deserialize()]. This default maximum +** size can be adjusted up or down for individual databases using the +** [SQLITE_FCNTL_SIZE_LIMIT] [sqlite3_file_control|file-control]. If this +** configuration setting is never used, then the default maximum is determined +** by the [SQLITE_MEMDB_DEFAULT_MAXSIZE] compile-time option. If that +** compile-time option is not set, then the default maximum is 1073741824. +**
    +*/ +#define SQLITE_CONFIG_SINGLETHREAD 1 /* nil */ +#define SQLITE_CONFIG_MULTITHREAD 2 /* nil */ +#define SQLITE_CONFIG_SERIALIZED 3 /* nil */ +#define SQLITE_CONFIG_MALLOC 4 /* sqlite3_mem_methods* */ +#define SQLITE_CONFIG_GETMALLOC 5 /* sqlite3_mem_methods* */ +#define SQLITE_CONFIG_SCRATCH 6 /* No longer used */ +#define SQLITE_CONFIG_PAGECACHE 7 /* void*, int sz, int N */ +#define SQLITE_CONFIG_HEAP 8 /* void*, int nByte, int min */ +#define SQLITE_CONFIG_MEMSTATUS 9 /* boolean */ +#define SQLITE_CONFIG_MUTEX 10 /* sqlite3_mutex_methods* */ +#define SQLITE_CONFIG_GETMUTEX 11 /* sqlite3_mutex_methods* */ +/* previously SQLITE_CONFIG_CHUNKALLOC 12 which is now unused. */ +#define SQLITE_CONFIG_LOOKASIDE 13 /* int int */ +#define SQLITE_CONFIG_PCACHE 14 /* no-op */ +#define SQLITE_CONFIG_GETPCACHE 15 /* no-op */ +#define SQLITE_CONFIG_LOG 16 /* xFunc, void* */ +#define SQLITE_CONFIG_URI 17 /* int */ +#define SQLITE_CONFIG_PCACHE2 18 /* sqlite3_pcache_methods2* */ +#define SQLITE_CONFIG_GETPCACHE2 19 /* sqlite3_pcache_methods2* */ +#define SQLITE_CONFIG_COVERING_INDEX_SCAN 20 /* int */ +#define SQLITE_CONFIG_SQLLOG 21 /* xSqllog, void* */ +#define SQLITE_CONFIG_MMAP_SIZE 22 /* sqlite3_int64, sqlite3_int64 */ +#define SQLITE_CONFIG_WIN32_HEAPSIZE 23 /* int nByte */ +#define SQLITE_CONFIG_PCACHE_HDRSZ 24 /* int *psz */ +#define SQLITE_CONFIG_PMASZ 25 /* unsigned int szPma */ +#define SQLITE_CONFIG_STMTJRNL_SPILL 26 /* int nByte */ +#define SQLITE_CONFIG_SMALL_MALLOC 27 /* boolean */ +#define SQLITE_CONFIG_SORTERREF_SIZE 28 /* int nByte */ +#define SQLITE_CONFIG_MEMDB_MAXSIZE 29 /* sqlite3_int64 */ + +/* +** CAPI3REF: Database Connection Configuration Options +** +** These constants are the available integer configuration options that +** can be passed as the second argument to the [sqlite3_db_config()] interface. +** +** New configuration options may be added in future releases of SQLite. +** Existing configuration options might be discontinued. Applications +** should check the return code from [sqlite3_db_config()] to make sure that +** the call worked. ^The [sqlite3_db_config()] interface will return a +** non-zero [error code] if a discontinued or unsupported configuration option +** is invoked. +** +**
    +** [[SQLITE_DBCONFIG_LOOKASIDE]] +**
    SQLITE_DBCONFIG_LOOKASIDE
    +**
    ^This option takes three additional arguments that determine the +** [lookaside memory allocator] configuration for the [database connection]. +** ^The first argument (the third parameter to [sqlite3_db_config()] is a +** pointer to a memory buffer to use for lookaside memory. +** ^The first argument after the SQLITE_DBCONFIG_LOOKASIDE verb +** may be NULL in which case SQLite will allocate the +** lookaside buffer itself using [sqlite3_malloc()]. ^The second argument is the +** size of each lookaside buffer slot. ^The third argument is the number of +** slots. The size of the buffer in the first argument must be greater than +** or equal to the product of the second and third arguments. The buffer +** must be aligned to an 8-byte boundary. ^If the second argument to +** SQLITE_DBCONFIG_LOOKASIDE is not a multiple of 8, it is internally +** rounded down to the next smaller multiple of 8. ^(The lookaside memory +** configuration for a database connection can only be changed when that +** connection is not currently using lookaside memory, or in other words +** when the "current value" returned by +** [sqlite3_db_status](D,[SQLITE_CONFIG_LOOKASIDE],...) is zero. +** Any attempt to change the lookaside memory configuration when lookaside +** memory is in use leaves the configuration unchanged and returns +** [SQLITE_BUSY].)^
    +** +** [[SQLITE_DBCONFIG_ENABLE_FKEY]] +**
    SQLITE_DBCONFIG_ENABLE_FKEY
    +**
    ^This option is used to enable or disable the enforcement of +** [foreign key constraints]. There should be two additional arguments. +** The first argument is an integer which is 0 to disable FK enforcement, +** positive to enable FK enforcement or negative to leave FK enforcement +** unchanged. The second parameter is a pointer to an integer into which +** is written 0 or 1 to indicate whether FK enforcement is off or on +** following this call. The second parameter may be a NULL pointer, in +** which case the FK enforcement setting is not reported back.
    +** +** [[SQLITE_DBCONFIG_ENABLE_TRIGGER]] +**
    SQLITE_DBCONFIG_ENABLE_TRIGGER
    +**
    ^This option is used to enable or disable [CREATE TRIGGER | triggers]. +** There should be two additional arguments. +** The first argument is an integer which is 0 to disable triggers, +** positive to enable triggers or negative to leave the setting unchanged. +** The second parameter is a pointer to an integer into which +** is written 0 or 1 to indicate whether triggers are disabled or enabled +** following this call. The second parameter may be a NULL pointer, in +** which case the trigger setting is not reported back. +** +**

    Originally this option disabled all triggers. ^(However, since +** SQLite version 3.35.0, TEMP triggers are still allowed even if +** this option is off. So, in other words, this option now only disables +** triggers in the main database schema or in the schemas of ATTACH-ed +** databases.)^

    +** +** [[SQLITE_DBCONFIG_ENABLE_VIEW]] +**
    SQLITE_DBCONFIG_ENABLE_VIEW
    +**
    ^This option is used to enable or disable [CREATE VIEW | views]. +** There should be two additional arguments. +** The first argument is an integer which is 0 to disable views, +** positive to enable views or negative to leave the setting unchanged. +** The second parameter is a pointer to an integer into which +** is written 0 or 1 to indicate whether views are disabled or enabled +** following this call. The second parameter may be a NULL pointer, in +** which case the view setting is not reported back. +** +**

    Originally this option disabled all views. ^(However, since +** SQLite version 3.35.0, TEMP views are still allowed even if +** this option is off. So, in other words, this option now only disables +** views in the main database schema or in the schemas of ATTACH-ed +** databases.)^

    +** +** [[SQLITE_DBCONFIG_ENABLE_FTS3_TOKENIZER]] +**
    SQLITE_DBCONFIG_ENABLE_FTS3_TOKENIZER
    +**
    ^This option is used to enable or disable the +** [fts3_tokenizer()] function which is part of the +** [FTS3] full-text search engine extension. +** There should be two additional arguments. +** The first argument is an integer which is 0 to disable fts3_tokenizer() or +** positive to enable fts3_tokenizer() or negative to leave the setting +** unchanged. +** The second parameter is a pointer to an integer into which +** is written 0 or 1 to indicate whether fts3_tokenizer is disabled or enabled +** following this call. The second parameter may be a NULL pointer, in +** which case the new setting is not reported back.
    +** +** [[SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION]] +**
    SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION
    +**
    ^This option is used to enable or disable the [sqlite3_load_extension()] +** interface independently of the [load_extension()] SQL function. +** The [sqlite3_enable_load_extension()] API enables or disables both the +** C-API [sqlite3_load_extension()] and the SQL function [load_extension()]. +** There should be two additional arguments. +** When the first argument to this interface is 1, then only the C-API is +** enabled and the SQL function remains disabled. If the first argument to +** this interface is 0, then both the C-API and the SQL function are disabled. +** If the first argument is -1, then no changes are made to state of either the +** C-API or the SQL function. +** The second parameter is a pointer to an integer into which +** is written 0 or 1 to indicate whether [sqlite3_load_extension()] interface +** is disabled or enabled following this call. The second parameter may +** be a NULL pointer, in which case the new setting is not reported back. +**
    +** +** [[SQLITE_DBCONFIG_MAINDBNAME]]
    SQLITE_DBCONFIG_MAINDBNAME
    +**
    ^This option is used to change the name of the "main" database +** schema. ^The sole argument is a pointer to a constant UTF8 string +** which will become the new schema name in place of "main". ^SQLite +** does not make a copy of the new main schema name string, so the application +** must ensure that the argument passed into this DBCONFIG option is unchanged +** until after the database connection closes. +**
    +** +** [[SQLITE_DBCONFIG_NO_CKPT_ON_CLOSE]] +**
    SQLITE_DBCONFIG_NO_CKPT_ON_CLOSE
    +**
    Usually, when a database in wal mode is closed or detached from a +** database handle, SQLite checks if this will mean that there are now no +** connections at all to the database. If so, it performs a checkpoint +** operation before closing the connection. This option may be used to +** override this behaviour. The first parameter passed to this operation +** is an integer - positive to disable checkpoints-on-close, or zero (the +** default) to enable them, and negative to leave the setting unchanged. +** The second parameter is a pointer to an integer +** into which is written 0 or 1 to indicate whether checkpoints-on-close +** have been disabled - 0 if they are not disabled, 1 if they are. +**
    +** +** [[SQLITE_DBCONFIG_ENABLE_QPSG]]
    SQLITE_DBCONFIG_ENABLE_QPSG
    +**
    ^(The SQLITE_DBCONFIG_ENABLE_QPSG option activates or deactivates +** the [query planner stability guarantee] (QPSG). When the QPSG is active, +** a single SQL query statement will always use the same algorithm regardless +** of values of [bound parameters].)^ The QPSG disables some query optimizations +** that look at the values of bound parameters, which can make some queries +** slower. But the QPSG has the advantage of more predictable behavior. With +** the QPSG active, SQLite will always use the same query plan in the field as +** was used during testing in the lab. +** The first argument to this setting is an integer which is 0 to disable +** the QPSG, positive to enable QPSG, or negative to leave the setting +** unchanged. The second parameter is a pointer to an integer into which +** is written 0 or 1 to indicate whether the QPSG is disabled or enabled +** following this call. +**
    +** +** [[SQLITE_DBCONFIG_TRIGGER_EQP]]
    SQLITE_DBCONFIG_TRIGGER_EQP
    +**
    By default, the output of EXPLAIN QUERY PLAN commands does not +** include output for any operations performed by trigger programs. This +** option is used to set or clear (the default) a flag that governs this +** behavior. The first parameter passed to this operation is an integer - +** positive to enable output for trigger programs, or zero to disable it, +** or negative to leave the setting unchanged. +** The second parameter is a pointer to an integer into which is written +** 0 or 1 to indicate whether output-for-triggers has been disabled - 0 if +** it is not disabled, 1 if it is. +**
    +** +** [[SQLITE_DBCONFIG_RESET_DATABASE]]
    SQLITE_DBCONFIG_RESET_DATABASE
    +**
    Set the SQLITE_DBCONFIG_RESET_DATABASE flag and then run +** [VACUUM] in order to reset a database back to an empty database +** with no schema and no content. The following process works even for +** a badly corrupted database file: +**
      +**
    1. If the database connection is newly opened, make sure it has read the +** database schema by preparing then discarding some query against the +** database, or calling sqlite3_table_column_metadata(), ignoring any +** errors. This step is only necessary if the application desires to keep +** the database in WAL mode after the reset if it was in WAL mode before +** the reset. +**
    2. sqlite3_db_config(db, SQLITE_DBCONFIG_RESET_DATABASE, 1, 0); +**
    3. [sqlite3_exec](db, "[VACUUM]", 0, 0, 0); +**
    4. sqlite3_db_config(db, SQLITE_DBCONFIG_RESET_DATABASE, 0, 0); +**
    +** Because resetting a database is destructive and irreversible, the +** process requires the use of this obscure API and multiple steps to help +** ensure that it does not happen by accident. +** +** [[SQLITE_DBCONFIG_DEFENSIVE]]
    SQLITE_DBCONFIG_DEFENSIVE
    +**
    The SQLITE_DBCONFIG_DEFENSIVE option activates or deactivates the +** "defensive" flag for a database connection. When the defensive +** flag is enabled, language features that allow ordinary SQL to +** deliberately corrupt the database file are disabled. The disabled +** features include but are not limited to the following: +**
      +**
    • The [PRAGMA writable_schema=ON] statement. +**
    • The [PRAGMA journal_mode=OFF] statement. +**
    • Writes to the [sqlite_dbpage] virtual table. +**
    • Direct writes to [shadow tables]. +**
    +**
    +** +** [[SQLITE_DBCONFIG_WRITABLE_SCHEMA]]
    SQLITE_DBCONFIG_WRITABLE_SCHEMA
    +**
    The SQLITE_DBCONFIG_WRITABLE_SCHEMA option activates or deactivates the +** "writable_schema" flag. This has the same effect and is logically equivalent +** to setting [PRAGMA writable_schema=ON] or [PRAGMA writable_schema=OFF]. +** The first argument to this setting is an integer which is 0 to disable +** the writable_schema, positive to enable writable_schema, or negative to +** leave the setting unchanged. The second parameter is a pointer to an +** integer into which is written 0 or 1 to indicate whether the writable_schema +** is enabled or disabled following this call. +**
    +** +** [[SQLITE_DBCONFIG_LEGACY_ALTER_TABLE]] +**
    SQLITE_DBCONFIG_LEGACY_ALTER_TABLE
    +**
    The SQLITE_DBCONFIG_LEGACY_ALTER_TABLE option activates or deactivates +** the legacy behavior of the [ALTER TABLE RENAME] command such it +** behaves as it did prior to [version 3.24.0] (2018-06-04). See the +** "Compatibility Notice" on the [ALTER TABLE RENAME documentation] for +** additional information. This feature can also be turned on and off +** using the [PRAGMA legacy_alter_table] statement. +**
    +** +** [[SQLITE_DBCONFIG_DQS_DML]] +**
    SQLITE_DBCONFIG_DQS_DML +**
    The SQLITE_DBCONFIG_DQS_DML option activates or deactivates +** the legacy [double-quoted string literal] misfeature for DML statements +** only, that is DELETE, INSERT, SELECT, and UPDATE statements. The +** default value of this setting is determined by the [-DSQLITE_DQS] +** compile-time option. +**
    +** +** [[SQLITE_DBCONFIG_DQS_DDL]] +**
    SQLITE_DBCONFIG_DQS_DDL +**
    The SQLITE_DBCONFIG_DQS option activates or deactivates +** the legacy [double-quoted string literal] misfeature for DDL statements, +** such as CREATE TABLE and CREATE INDEX. The +** default value of this setting is determined by the [-DSQLITE_DQS] +** compile-time option. +**
    +** +** [[SQLITE_DBCONFIG_TRUSTED_SCHEMA]] +**
    SQLITE_DBCONFIG_TRUSTED_SCHEMA +**
    The SQLITE_DBCONFIG_TRUSTED_SCHEMA option tells SQLite to +** assume that database schemas are untainted by malicious content. +** When the SQLITE_DBCONFIG_TRUSTED_SCHEMA option is disabled, SQLite +** takes additional defensive steps to protect the application from harm +** including: +**
      +**
    • Prohibit the use of SQL functions inside triggers, views, +** CHECK constraints, DEFAULT clauses, expression indexes, +** partial indexes, or generated columns +** unless those functions are tagged with [SQLITE_INNOCUOUS]. +**
    • Prohibit the use of virtual tables inside of triggers or views +** unless those virtual tables are tagged with [SQLITE_VTAB_INNOCUOUS]. +**
    +** This setting defaults to "on" for legacy compatibility, however +** all applications are advised to turn it off if possible. This setting +** can also be controlled using the [PRAGMA trusted_schema] statement. +**
    +** +** [[SQLITE_DBCONFIG_LEGACY_FILE_FORMAT]] +**
    SQLITE_DBCONFIG_LEGACY_FILE_FORMAT +**
    The SQLITE_DBCONFIG_LEGACY_FILE_FORMAT option activates or deactivates +** the legacy file format flag. When activated, this flag causes all newly +** created database file to have a schema format version number (the 4-byte +** integer found at offset 44 into the database header) of 1. This in turn +** means that the resulting database file will be readable and writable by +** any SQLite version back to 3.0.0 ([dateof:3.0.0]). Without this setting, +** newly created databases are generally not understandable by SQLite versions +** prior to 3.3.0 ([dateof:3.3.0]). As these words are written, there +** is now scarcely any need to generated database files that are compatible +** all the way back to version 3.0.0, and so this setting is of little +** practical use, but is provided so that SQLite can continue to claim the +** ability to generate new database files that are compatible with version +** 3.0.0. +**

    Note that when the SQLITE_DBCONFIG_LEGACY_FILE_FORMAT setting is on, +** the [VACUUM] command will fail with an obscure error when attempting to +** process a table with generated columns and a descending index. This is +** not considered a bug since SQLite versions 3.3.0 and earlier do not support +** either generated columns or decending indexes. +**

    +**
    +*/ +#define SQLITE_DBCONFIG_MAINDBNAME 1000 /* const char* */ +#define SQLITE_DBCONFIG_LOOKASIDE 1001 /* void* int int */ +#define SQLITE_DBCONFIG_ENABLE_FKEY 1002 /* int int* */ +#define SQLITE_DBCONFIG_ENABLE_TRIGGER 1003 /* int int* */ +#define SQLITE_DBCONFIG_ENABLE_FTS3_TOKENIZER 1004 /* int int* */ +#define SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION 1005 /* int int* */ +#define SQLITE_DBCONFIG_NO_CKPT_ON_CLOSE 1006 /* int int* */ +#define SQLITE_DBCONFIG_ENABLE_QPSG 1007 /* int int* */ +#define SQLITE_DBCONFIG_TRIGGER_EQP 1008 /* int int* */ +#define SQLITE_DBCONFIG_RESET_DATABASE 1009 /* int int* */ +#define SQLITE_DBCONFIG_DEFENSIVE 1010 /* int int* */ +#define SQLITE_DBCONFIG_WRITABLE_SCHEMA 1011 /* int int* */ +#define SQLITE_DBCONFIG_LEGACY_ALTER_TABLE 1012 /* int int* */ +#define SQLITE_DBCONFIG_DQS_DML 1013 /* int int* */ +#define SQLITE_DBCONFIG_DQS_DDL 1014 /* int int* */ +#define SQLITE_DBCONFIG_ENABLE_VIEW 1015 /* int int* */ +#define SQLITE_DBCONFIG_LEGACY_FILE_FORMAT 1016 /* int int* */ +#define SQLITE_DBCONFIG_TRUSTED_SCHEMA 1017 /* int int* */ +#define SQLITE_DBCONFIG_MAX 1017 /* Largest DBCONFIG */ + +/* +** CAPI3REF: Enable Or Disable Extended Result Codes +** METHOD: sqlite3 +** +** ^The sqlite3_extended_result_codes() routine enables or disables the +** [extended result codes] feature of SQLite. ^The extended result +** codes are disabled by default for historical compatibility. +*/ +SQLITE_API int sqlite3_extended_result_codes(sqlite3*, int onoff); + +/* +** CAPI3REF: Last Insert Rowid +** METHOD: sqlite3 +** +** ^Each entry in most SQLite tables (except for [WITHOUT ROWID] tables) +** has a unique 64-bit signed +** integer key called the [ROWID | "rowid"]. ^The rowid is always available +** as an undeclared column named ROWID, OID, or _ROWID_ as long as those +** names are not also used by explicitly declared columns. ^If +** the table has a column of type [INTEGER PRIMARY KEY] then that column +** is another alias for the rowid. +** +** ^The sqlite3_last_insert_rowid(D) interface usually returns the [rowid] of +** the most recent successful [INSERT] into a rowid table or [virtual table] +** on database connection D. ^Inserts into [WITHOUT ROWID] tables are not +** recorded. ^If no successful [INSERT]s into rowid tables have ever occurred +** on the database connection D, then sqlite3_last_insert_rowid(D) returns +** zero. +** +** As well as being set automatically as rows are inserted into database +** tables, the value returned by this function may be set explicitly by +** [sqlite3_set_last_insert_rowid()] +** +** Some virtual table implementations may INSERT rows into rowid tables as +** part of committing a transaction (e.g. to flush data accumulated in memory +** to disk). In this case subsequent calls to this function return the rowid +** associated with these internal INSERT operations, which leads to +** unintuitive results. Virtual table implementations that do write to rowid +** tables in this way can avoid this problem by restoring the original +** rowid value using [sqlite3_set_last_insert_rowid()] before returning +** control to the user. +** +** ^(If an [INSERT] occurs within a trigger then this routine will +** return the [rowid] of the inserted row as long as the trigger is +** running. Once the trigger program ends, the value returned +** by this routine reverts to what it was before the trigger was fired.)^ +** +** ^An [INSERT] that fails due to a constraint violation is not a +** successful [INSERT] and does not change the value returned by this +** routine. ^Thus INSERT OR FAIL, INSERT OR IGNORE, INSERT OR ROLLBACK, +** and INSERT OR ABORT make no changes to the return value of this +** routine when their insertion fails. ^(When INSERT OR REPLACE +** encounters a constraint violation, it does not fail. The +** INSERT continues to completion after deleting rows that caused +** the constraint problem so INSERT OR REPLACE will always change +** the return value of this interface.)^ +** +** ^For the purposes of this routine, an [INSERT] is considered to +** be successful even if it is subsequently rolled back. +** +** This function is accessible to SQL statements via the +** [last_insert_rowid() SQL function]. +** +** If a separate thread performs a new [INSERT] on the same +** database connection while the [sqlite3_last_insert_rowid()] +** function is running and thus changes the last insert [rowid], +** then the value returned by [sqlite3_last_insert_rowid()] is +** unpredictable and might not equal either the old or the new +** last insert [rowid]. +*/ +SQLITE_API sqlite3_int64 sqlite3_last_insert_rowid(sqlite3*); + +/* +** CAPI3REF: Set the Last Insert Rowid value. +** METHOD: sqlite3 +** +** The sqlite3_set_last_insert_rowid(D, R) method allows the application to +** set the value returned by calling sqlite3_last_insert_rowid(D) to R +** without inserting a row into the database. +*/ +SQLITE_API void sqlite3_set_last_insert_rowid(sqlite3*,sqlite3_int64); + +/* +** CAPI3REF: Count The Number Of Rows Modified +** METHOD: sqlite3 +** +** ^These functions return the number of rows modified, inserted or +** deleted by the most recently completed INSERT, UPDATE or DELETE +** statement on the database connection specified by the only parameter. +** The two functions are identical except for the type of the return value +** and that if the number of rows modified by the most recent INSERT, UPDATE +** or DELETE is greater than the maximum value supported by type "int", then +** the return value of sqlite3_changes() is undefined. ^Executing any other +** type of SQL statement does not modify the value returned by these functions. +** +** ^Only changes made directly by the INSERT, UPDATE or DELETE statement are +** considered - auxiliary changes caused by [CREATE TRIGGER | triggers], +** [foreign key actions] or [REPLACE] constraint resolution are not counted. +** +** Changes to a view that are intercepted by +** [INSTEAD OF trigger | INSTEAD OF triggers] are not counted. ^The value +** returned by sqlite3_changes() immediately after an INSERT, UPDATE or +** DELETE statement run on a view is always zero. Only changes made to real +** tables are counted. +** +** Things are more complicated if the sqlite3_changes() function is +** executed while a trigger program is running. This may happen if the +** program uses the [changes() SQL function], or if some other callback +** function invokes sqlite3_changes() directly. Essentially: +** +**
      +**
    • ^(Before entering a trigger program the value returned by +** sqlite3_changes() function is saved. After the trigger program +** has finished, the original value is restored.)^ +** +**
    • ^(Within a trigger program each INSERT, UPDATE and DELETE +** statement sets the value returned by sqlite3_changes() +** upon completion as normal. Of course, this value will not include +** any changes performed by sub-triggers, as the sqlite3_changes() +** value will be saved and restored after each sub-trigger has run.)^ +**
    +** +** ^This means that if the changes() SQL function (or similar) is used +** by the first INSERT, UPDATE or DELETE statement within a trigger, it +** returns the value as set when the calling statement began executing. +** ^If it is used by the second or subsequent such statement within a trigger +** program, the value returned reflects the number of rows modified by the +** previous INSERT, UPDATE or DELETE statement within the same trigger. +** +** If a separate thread makes changes on the same database connection +** while [sqlite3_changes()] is running then the value returned +** is unpredictable and not meaningful. +** +** See also: +**
      +**
    • the [sqlite3_total_changes()] interface +**
    • the [count_changes pragma] +**
    • the [changes() SQL function] +**
    • the [data_version pragma] +**
    +*/ +SQLITE_API int sqlite3_changes(sqlite3*); +SQLITE_API sqlite3_int64 sqlite3_changes64(sqlite3*); + +/* +** CAPI3REF: Total Number Of Rows Modified +** METHOD: sqlite3 +** +** ^These functions return the total number of rows inserted, modified or +** deleted by all [INSERT], [UPDATE] or [DELETE] statements completed +** since the database connection was opened, including those executed as +** part of trigger programs. The two functions are identical except for the +** type of the return value and that if the number of rows modified by the +** connection exceeds the maximum value supported by type "int", then +** the return value of sqlite3_total_changes() is undefined. ^Executing +** any other type of SQL statement does not affect the value returned by +** sqlite3_total_changes(). +** +** ^Changes made as part of [foreign key actions] are included in the +** count, but those made as part of REPLACE constraint resolution are +** not. ^Changes to a view that are intercepted by INSTEAD OF triggers +** are not counted. +** +** The [sqlite3_total_changes(D)] interface only reports the number +** of rows that changed due to SQL statement run against database +** connection D. Any changes by other database connections are ignored. +** To detect changes against a database file from other database +** connections use the [PRAGMA data_version] command or the +** [SQLITE_FCNTL_DATA_VERSION] [file control]. +** +** If a separate thread makes changes on the same database connection +** while [sqlite3_total_changes()] is running then the value +** returned is unpredictable and not meaningful. +** +** See also: +**
      +**
    • the [sqlite3_changes()] interface +**
    • the [count_changes pragma] +**
    • the [changes() SQL function] +**
    • the [data_version pragma] +**
    • the [SQLITE_FCNTL_DATA_VERSION] [file control] +**
    +*/ +SQLITE_API int sqlite3_total_changes(sqlite3*); +SQLITE_API sqlite3_int64 sqlite3_total_changes64(sqlite3*); + +/* +** CAPI3REF: Interrupt A Long-Running Query +** METHOD: sqlite3 +** +** ^This function causes any pending database operation to abort and +** return at its earliest opportunity. This routine is typically +** called in response to a user action such as pressing "Cancel" +** or Ctrl-C where the user wants a long query operation to halt +** immediately. +** +** ^It is safe to call this routine from a thread different from the +** thread that is currently running the database operation. But it +** is not safe to call this routine with a [database connection] that +** is closed or might close before sqlite3_interrupt() returns. +** +** ^If an SQL operation is very nearly finished at the time when +** sqlite3_interrupt() is called, then it might not have an opportunity +** to be interrupted and might continue to completion. +** +** ^An SQL operation that is interrupted will return [SQLITE_INTERRUPT]. +** ^If the interrupted SQL operation is an INSERT, UPDATE, or DELETE +** that is inside an explicit transaction, then the entire transaction +** will be rolled back automatically. +** +** ^The sqlite3_interrupt(D) call is in effect until all currently running +** SQL statements on [database connection] D complete. ^Any new SQL statements +** that are started after the sqlite3_interrupt() call and before the +** running statement count reaches zero are interrupted as if they had been +** running prior to the sqlite3_interrupt() call. ^New SQL statements +** that are started after the running statement count reaches zero are +** not effected by the sqlite3_interrupt(). +** ^A call to sqlite3_interrupt(D) that occurs when there are no running +** SQL statements is a no-op and has no effect on SQL statements +** that are started after the sqlite3_interrupt() call returns. +*/ +SQLITE_API void sqlite3_interrupt(sqlite3*); + +/* +** CAPI3REF: Determine If An SQL Statement Is Complete +** +** These routines are useful during command-line input to determine if the +** currently entered text seems to form a complete SQL statement or +** if additional input is needed before sending the text into +** SQLite for parsing. ^These routines return 1 if the input string +** appears to be a complete SQL statement. ^A statement is judged to be +** complete if it ends with a semicolon token and is not a prefix of a +** well-formed CREATE TRIGGER statement. ^Semicolons that are embedded within +** string literals or quoted identifier names or comments are not +** independent tokens (they are part of the token in which they are +** embedded) and thus do not count as a statement terminator. ^Whitespace +** and comments that follow the final semicolon are ignored. +** +** ^These routines return 0 if the statement is incomplete. ^If a +** memory allocation fails, then SQLITE_NOMEM is returned. +** +** ^These routines do not parse the SQL statements thus +** will not detect syntactically incorrect SQL. +** +** ^(If SQLite has not been initialized using [sqlite3_initialize()] prior +** to invoking sqlite3_complete16() then sqlite3_initialize() is invoked +** automatically by sqlite3_complete16(). If that initialization fails, +** then the return value from sqlite3_complete16() will be non-zero +** regardless of whether or not the input SQL is complete.)^ +** +** The input to [sqlite3_complete()] must be a zero-terminated +** UTF-8 string. +** +** The input to [sqlite3_complete16()] must be a zero-terminated +** UTF-16 string in native byte order. +*/ +SQLITE_API int sqlite3_complete(const char *sql); +SQLITE_API int sqlite3_complete16(const void *sql); + +/* +** CAPI3REF: Register A Callback To Handle SQLITE_BUSY Errors +** KEYWORDS: {busy-handler callback} {busy handler} +** METHOD: sqlite3 +** +** ^The sqlite3_busy_handler(D,X,P) routine sets a callback function X +** that might be invoked with argument P whenever +** an attempt is made to access a database table associated with +** [database connection] D when another thread +** or process has the table locked. +** The sqlite3_busy_handler() interface is used to implement +** [sqlite3_busy_timeout()] and [PRAGMA busy_timeout]. +** +** ^If the busy callback is NULL, then [SQLITE_BUSY] +** is returned immediately upon encountering the lock. ^If the busy callback +** is not NULL, then the callback might be invoked with two arguments. +** +** ^The first argument to the busy handler is a copy of the void* pointer which +** is the third argument to sqlite3_busy_handler(). ^The second argument to +** the busy handler callback is the number of times that the busy handler has +** been invoked previously for the same locking event. ^If the +** busy callback returns 0, then no additional attempts are made to +** access the database and [SQLITE_BUSY] is returned +** to the application. +** ^If the callback returns non-zero, then another attempt +** is made to access the database and the cycle repeats. +** +** The presence of a busy handler does not guarantee that it will be invoked +** when there is lock contention. ^If SQLite determines that invoking the busy +** handler could result in a deadlock, it will go ahead and return [SQLITE_BUSY] +** to the application instead of invoking the +** busy handler. +** Consider a scenario where one process is holding a read lock that +** it is trying to promote to a reserved lock and +** a second process is holding a reserved lock that it is trying +** to promote to an exclusive lock. The first process cannot proceed +** because it is blocked by the second and the second process cannot +** proceed because it is blocked by the first. If both processes +** invoke the busy handlers, neither will make any progress. Therefore, +** SQLite returns [SQLITE_BUSY] for the first process, hoping that this +** will induce the first process to release its read lock and allow +** the second process to proceed. +** +** ^The default busy callback is NULL. +** +** ^(There can only be a single busy handler defined for each +** [database connection]. Setting a new busy handler clears any +** previously set handler.)^ ^Note that calling [sqlite3_busy_timeout()] +** or evaluating [PRAGMA busy_timeout=N] will change the +** busy handler and thus clear any previously set busy handler. +** +** The busy callback should not take any actions which modify the +** database connection that invoked the busy handler. In other words, +** the busy handler is not reentrant. Any such actions +** result in undefined behavior. +** +** A busy handler must not close the database connection +** or [prepared statement] that invoked the busy handler. +*/ +SQLITE_API int sqlite3_busy_handler(sqlite3*,int(*)(void*,int),void*); + +/* +** CAPI3REF: Set A Busy Timeout +** METHOD: sqlite3 +** +** ^This routine sets a [sqlite3_busy_handler | busy handler] that sleeps +** for a specified amount of time when a table is locked. ^The handler +** will sleep multiple times until at least "ms" milliseconds of sleeping +** have accumulated. ^After at least "ms" milliseconds of sleeping, +** the handler returns 0 which causes [sqlite3_step()] to return +** [SQLITE_BUSY]. +** +** ^Calling this routine with an argument less than or equal to zero +** turns off all busy handlers. +** +** ^(There can only be a single busy handler for a particular +** [database connection] at any given moment. If another busy handler +** was defined (using [sqlite3_busy_handler()]) prior to calling +** this routine, that other busy handler is cleared.)^ +** +** See also: [PRAGMA busy_timeout] +*/ +SQLITE_API int sqlite3_busy_timeout(sqlite3*, int ms); + +/* +** CAPI3REF: Convenience Routines For Running Queries +** METHOD: sqlite3 +** +** This is a legacy interface that is preserved for backwards compatibility. +** Use of this interface is not recommended. +** +** Definition: A result table is memory data structure created by the +** [sqlite3_get_table()] interface. A result table records the +** complete query results from one or more queries. +** +** The table conceptually has a number of rows and columns. But +** these numbers are not part of the result table itself. These +** numbers are obtained separately. Let N be the number of rows +** and M be the number of columns. +** +** A result table is an array of pointers to zero-terminated UTF-8 strings. +** There are (N+1)*M elements in the array. The first M pointers point +** to zero-terminated strings that contain the names of the columns. +** The remaining entries all point to query results. NULL values result +** in NULL pointers. All other values are in their UTF-8 zero-terminated +** string representation as returned by [sqlite3_column_text()]. +** +** A result table might consist of one or more memory allocations. +** It is not safe to pass a result table directly to [sqlite3_free()]. +** A result table should be deallocated using [sqlite3_free_table()]. +** +** ^(As an example of the result table format, suppose a query result +** is as follows: +** +**
    +**        Name        | Age
    +**        -----------------------
    +**        Alice       | 43
    +**        Bob         | 28
    +**        Cindy       | 21
    +** 
    +** +** There are two columns (M==2) and three rows (N==3). Thus the +** result table has 8 entries. Suppose the result table is stored +** in an array named azResult. Then azResult holds this content: +** +**
    +**        azResult[0] = "Name";
    +**        azResult[1] = "Age";
    +**        azResult[2] = "Alice";
    +**        azResult[3] = "43";
    +**        azResult[4] = "Bob";
    +**        azResult[5] = "28";
    +**        azResult[6] = "Cindy";
    +**        azResult[7] = "21";
    +** 
    )^ +** +** ^The sqlite3_get_table() function evaluates one or more +** semicolon-separated SQL statements in the zero-terminated UTF-8 +** string of its 2nd parameter and returns a result table to the +** pointer given in its 3rd parameter. +** +** After the application has finished with the result from sqlite3_get_table(), +** it must pass the result table pointer to sqlite3_free_table() in order to +** release the memory that was malloced. Because of the way the +** [sqlite3_malloc()] happens within sqlite3_get_table(), the calling +** function must not try to call [sqlite3_free()] directly. Only +** [sqlite3_free_table()] is able to release the memory properly and safely. +** +** The sqlite3_get_table() interface is implemented as a wrapper around +** [sqlite3_exec()]. The sqlite3_get_table() routine does not have access +** to any internal data structures of SQLite. It uses only the public +** interface defined here. As a consequence, errors that occur in the +** wrapper layer outside of the internal [sqlite3_exec()] call are not +** reflected in subsequent calls to [sqlite3_errcode()] or +** [sqlite3_errmsg()]. +*/ +SQLITE_API int sqlite3_get_table( + sqlite3 *db, /* An open database */ + const char *zSql, /* SQL to be evaluated */ + char ***pazResult, /* Results of the query */ + int *pnRow, /* Number of result rows written here */ + int *pnColumn, /* Number of result columns written here */ + char **pzErrmsg /* Error msg written here */ +); +SQLITE_API void sqlite3_free_table(char **result); + +/* +** CAPI3REF: Formatted String Printing Functions +** +** These routines are work-alikes of the "printf()" family of functions +** from the standard C library. +** These routines understand most of the common formatting options from +** the standard library printf() +** plus some additional non-standard formats ([%q], [%Q], [%w], and [%z]). +** See the [built-in printf()] documentation for details. +** +** ^The sqlite3_mprintf() and sqlite3_vmprintf() routines write their +** results into memory obtained from [sqlite3_malloc64()]. +** The strings returned by these two routines should be +** released by [sqlite3_free()]. ^Both routines return a +** NULL pointer if [sqlite3_malloc64()] is unable to allocate enough +** memory to hold the resulting string. +** +** ^(The sqlite3_snprintf() routine is similar to "snprintf()" from +** the standard C library. The result is written into the +** buffer supplied as the second parameter whose size is given by +** the first parameter. Note that the order of the +** first two parameters is reversed from snprintf().)^ This is an +** historical accident that cannot be fixed without breaking +** backwards compatibility. ^(Note also that sqlite3_snprintf() +** returns a pointer to its buffer instead of the number of +** characters actually written into the buffer.)^ We admit that +** the number of characters written would be a more useful return +** value but we cannot change the implementation of sqlite3_snprintf() +** now without breaking compatibility. +** +** ^As long as the buffer size is greater than zero, sqlite3_snprintf() +** guarantees that the buffer is always zero-terminated. ^The first +** parameter "n" is the total size of the buffer, including space for +** the zero terminator. So the longest string that can be completely +** written will be n-1 characters. +** +** ^The sqlite3_vsnprintf() routine is a varargs version of sqlite3_snprintf(). +** +** See also: [built-in printf()], [printf() SQL function] +*/ +SQLITE_API char *sqlite3_mprintf(const char*,...); +SQLITE_API char *sqlite3_vmprintf(const char*, va_list); +SQLITE_API char *sqlite3_snprintf(int,char*,const char*, ...); +SQLITE_API char *sqlite3_vsnprintf(int,char*,const char*, va_list); + +/* +** CAPI3REF: Memory Allocation Subsystem +** +** The SQLite core uses these three routines for all of its own +** internal memory allocation needs. "Core" in the previous sentence +** does not include operating-system specific [VFS] implementation. The +** Windows VFS uses native malloc() and free() for some operations. +** +** ^The sqlite3_malloc() routine returns a pointer to a block +** of memory at least N bytes in length, where N is the parameter. +** ^If sqlite3_malloc() is unable to obtain sufficient free +** memory, it returns a NULL pointer. ^If the parameter N to +** sqlite3_malloc() is zero or negative then sqlite3_malloc() returns +** a NULL pointer. +** +** ^The sqlite3_malloc64(N) routine works just like +** sqlite3_malloc(N) except that N is an unsigned 64-bit integer instead +** of a signed 32-bit integer. +** +** ^Calling sqlite3_free() with a pointer previously returned +** by sqlite3_malloc() or sqlite3_realloc() releases that memory so +** that it might be reused. ^The sqlite3_free() routine is +** a no-op if is called with a NULL pointer. Passing a NULL pointer +** to sqlite3_free() is harmless. After being freed, memory +** should neither be read nor written. Even reading previously freed +** memory might result in a segmentation fault or other severe error. +** Memory corruption, a segmentation fault, or other severe error +** might result if sqlite3_free() is called with a non-NULL pointer that +** was not obtained from sqlite3_malloc() or sqlite3_realloc(). +** +** ^The sqlite3_realloc(X,N) interface attempts to resize a +** prior memory allocation X to be at least N bytes. +** ^If the X parameter to sqlite3_realloc(X,N) +** is a NULL pointer then its behavior is identical to calling +** sqlite3_malloc(N). +** ^If the N parameter to sqlite3_realloc(X,N) is zero or +** negative then the behavior is exactly the same as calling +** sqlite3_free(X). +** ^sqlite3_realloc(X,N) returns a pointer to a memory allocation +** of at least N bytes in size or NULL if insufficient memory is available. +** ^If M is the size of the prior allocation, then min(N,M) bytes +** of the prior allocation are copied into the beginning of buffer returned +** by sqlite3_realloc(X,N) and the prior allocation is freed. +** ^If sqlite3_realloc(X,N) returns NULL and N is positive, then the +** prior allocation is not freed. +** +** ^The sqlite3_realloc64(X,N) interfaces works the same as +** sqlite3_realloc(X,N) except that N is a 64-bit unsigned integer instead +** of a 32-bit signed integer. +** +** ^If X is a memory allocation previously obtained from sqlite3_malloc(), +** sqlite3_malloc64(), sqlite3_realloc(), or sqlite3_realloc64(), then +** sqlite3_msize(X) returns the size of that memory allocation in bytes. +** ^The value returned by sqlite3_msize(X) might be larger than the number +** of bytes requested when X was allocated. ^If X is a NULL pointer then +** sqlite3_msize(X) returns zero. If X points to something that is not +** the beginning of memory allocation, or if it points to a formerly +** valid memory allocation that has now been freed, then the behavior +** of sqlite3_msize(X) is undefined and possibly harmful. +** +** ^The memory returned by sqlite3_malloc(), sqlite3_realloc(), +** sqlite3_malloc64(), and sqlite3_realloc64() +** is always aligned to at least an 8 byte boundary, or to a +** 4 byte boundary if the [SQLITE_4_BYTE_ALIGNED_MALLOC] compile-time +** option is used. +** +** The pointer arguments to [sqlite3_free()] and [sqlite3_realloc()] +** must be either NULL or else pointers obtained from a prior +** invocation of [sqlite3_malloc()] or [sqlite3_realloc()] that have +** not yet been released. +** +** The application must not read or write any part of +** a block of memory after it has been released using +** [sqlite3_free()] or [sqlite3_realloc()]. +*/ +SQLITE_API void *sqlite3_malloc(int); +SQLITE_API void *sqlite3_malloc64(sqlite3_uint64); +SQLITE_API void *sqlite3_realloc(void*, int); +SQLITE_API void *sqlite3_realloc64(void*, sqlite3_uint64); +SQLITE_API void sqlite3_free(void*); +SQLITE_API sqlite3_uint64 sqlite3_msize(void*); + +/* +** CAPI3REF: Memory Allocator Statistics +** +** SQLite provides these two interfaces for reporting on the status +** of the [sqlite3_malloc()], [sqlite3_free()], and [sqlite3_realloc()] +** routines, which form the built-in memory allocation subsystem. +** +** ^The [sqlite3_memory_used()] routine returns the number of bytes +** of memory currently outstanding (malloced but not freed). +** ^The [sqlite3_memory_highwater()] routine returns the maximum +** value of [sqlite3_memory_used()] since the high-water mark +** was last reset. ^The values returned by [sqlite3_memory_used()] and +** [sqlite3_memory_highwater()] include any overhead +** added by SQLite in its implementation of [sqlite3_malloc()], +** but not overhead added by the any underlying system library +** routines that [sqlite3_malloc()] may call. +** +** ^The memory high-water mark is reset to the current value of +** [sqlite3_memory_used()] if and only if the parameter to +** [sqlite3_memory_highwater()] is true. ^The value returned +** by [sqlite3_memory_highwater(1)] is the high-water mark +** prior to the reset. +*/ +SQLITE_API sqlite3_int64 sqlite3_memory_used(void); +SQLITE_API sqlite3_int64 sqlite3_memory_highwater(int resetFlag); + +/* +** CAPI3REF: Pseudo-Random Number Generator +** +** SQLite contains a high-quality pseudo-random number generator (PRNG) used to +** select random [ROWID | ROWIDs] when inserting new records into a table that +** already uses the largest possible [ROWID]. The PRNG is also used for +** the built-in random() and randomblob() SQL functions. This interface allows +** applications to access the same PRNG for other purposes. +** +** ^A call to this routine stores N bytes of randomness into buffer P. +** ^The P parameter can be a NULL pointer. +** +** ^If this routine has not been previously called or if the previous +** call had N less than one or a NULL pointer for P, then the PRNG is +** seeded using randomness obtained from the xRandomness method of +** the default [sqlite3_vfs] object. +** ^If the previous call to this routine had an N of 1 or more and a +** non-NULL P then the pseudo-randomness is generated +** internally and without recourse to the [sqlite3_vfs] xRandomness +** method. +*/ +SQLITE_API void sqlite3_randomness(int N, void *P); + +/* +** CAPI3REF: Compile-Time Authorization Callbacks +** METHOD: sqlite3 +** KEYWORDS: {authorizer callback} +** +** ^This routine registers an authorizer callback with a particular +** [database connection], supplied in the first argument. +** ^The authorizer callback is invoked as SQL statements are being compiled +** by [sqlite3_prepare()] or its variants [sqlite3_prepare_v2()], +** [sqlite3_prepare_v3()], [sqlite3_prepare16()], [sqlite3_prepare16_v2()], +** and [sqlite3_prepare16_v3()]. ^At various +** points during the compilation process, as logic is being created +** to perform various actions, the authorizer callback is invoked to +** see if those actions are allowed. ^The authorizer callback should +** return [SQLITE_OK] to allow the action, [SQLITE_IGNORE] to disallow the +** specific action but allow the SQL statement to continue to be +** compiled, or [SQLITE_DENY] to cause the entire SQL statement to be +** rejected with an error. ^If the authorizer callback returns +** any value other than [SQLITE_IGNORE], [SQLITE_OK], or [SQLITE_DENY] +** then the [sqlite3_prepare_v2()] or equivalent call that triggered +** the authorizer will fail with an error message. +** +** When the callback returns [SQLITE_OK], that means the operation +** requested is ok. ^When the callback returns [SQLITE_DENY], the +** [sqlite3_prepare_v2()] or equivalent call that triggered the +** authorizer will fail with an error message explaining that +** access is denied. +** +** ^The first parameter to the authorizer callback is a copy of the third +** parameter to the sqlite3_set_authorizer() interface. ^The second parameter +** to the callback is an integer [SQLITE_COPY | action code] that specifies +** the particular action to be authorized. ^The third through sixth parameters +** to the callback are either NULL pointers or zero-terminated strings +** that contain additional details about the action to be authorized. +** Applications must always be prepared to encounter a NULL pointer in any +** of the third through the sixth parameters of the authorization callback. +** +** ^If the action code is [SQLITE_READ] +** and the callback returns [SQLITE_IGNORE] then the +** [prepared statement] statement is constructed to substitute +** a NULL value in place of the table column that would have +** been read if [SQLITE_OK] had been returned. The [SQLITE_IGNORE] +** return can be used to deny an untrusted user access to individual +** columns of a table. +** ^When a table is referenced by a [SELECT] but no column values are +** extracted from that table (for example in a query like +** "SELECT count(*) FROM tab") then the [SQLITE_READ] authorizer callback +** is invoked once for that table with a column name that is an empty string. +** ^If the action code is [SQLITE_DELETE] and the callback returns +** [SQLITE_IGNORE] then the [DELETE] operation proceeds but the +** [truncate optimization] is disabled and all rows are deleted individually. +** +** An authorizer is used when [sqlite3_prepare | preparing] +** SQL statements from an untrusted source, to ensure that the SQL statements +** do not try to access data they are not allowed to see, or that they do not +** try to execute malicious statements that damage the database. For +** example, an application may allow a user to enter arbitrary +** SQL queries for evaluation by a database. But the application does +** not want the user to be able to make arbitrary changes to the +** database. An authorizer could then be put in place while the +** user-entered SQL is being [sqlite3_prepare | prepared] that +** disallows everything except [SELECT] statements. +** +** Applications that need to process SQL from untrusted sources +** might also consider lowering resource limits using [sqlite3_limit()] +** and limiting database size using the [max_page_count] [PRAGMA] +** in addition to using an authorizer. +** +** ^(Only a single authorizer can be in place on a database connection +** at a time. Each call to sqlite3_set_authorizer overrides the +** previous call.)^ ^Disable the authorizer by installing a NULL callback. +** The authorizer is disabled by default. +** +** The authorizer callback must not do anything that will modify +** the database connection that invoked the authorizer callback. +** Note that [sqlite3_prepare_v2()] and [sqlite3_step()] both modify their +** database connections for the meaning of "modify" in this paragraph. +** +** ^When [sqlite3_prepare_v2()] is used to prepare a statement, the +** statement might be re-prepared during [sqlite3_step()] due to a +** schema change. Hence, the application should ensure that the +** correct authorizer callback remains in place during the [sqlite3_step()]. +** +** ^Note that the authorizer callback is invoked only during +** [sqlite3_prepare()] or its variants. Authorization is not +** performed during statement evaluation in [sqlite3_step()], unless +** as stated in the previous paragraph, sqlite3_step() invokes +** sqlite3_prepare_v2() to reprepare a statement after a schema change. +*/ +SQLITE_API int sqlite3_set_authorizer( + sqlite3*, + int (*xAuth)(void*,int,const char*,const char*,const char*,const char*), + void *pUserData +); + +/* +** CAPI3REF: Authorizer Return Codes +** +** The [sqlite3_set_authorizer | authorizer callback function] must +** return either [SQLITE_OK] or one of these two constants in order +** to signal SQLite whether or not the action is permitted. See the +** [sqlite3_set_authorizer | authorizer documentation] for additional +** information. +** +** Note that SQLITE_IGNORE is also used as a [conflict resolution mode] +** returned from the [sqlite3_vtab_on_conflict()] interface. +*/ +#define SQLITE_DENY 1 /* Abort the SQL statement with an error */ +#define SQLITE_IGNORE 2 /* Don't allow access, but don't generate an error */ + +/* +** CAPI3REF: Authorizer Action Codes +** +** The [sqlite3_set_authorizer()] interface registers a callback function +** that is invoked to authorize certain SQL statement actions. The +** second parameter to the callback is an integer code that specifies +** what action is being authorized. These are the integer action codes that +** the authorizer callback may be passed. +** +** These action code values signify what kind of operation is to be +** authorized. The 3rd and 4th parameters to the authorization +** callback function will be parameters or NULL depending on which of these +** codes is used as the second parameter. ^(The 5th parameter to the +** authorizer callback is the name of the database ("main", "temp", +** etc.) if applicable.)^ ^The 6th parameter to the authorizer callback +** is the name of the inner-most trigger or view that is responsible for +** the access attempt or NULL if this access attempt is directly from +** top-level SQL code. +*/ +/******************************************* 3rd ************ 4th ***********/ +#define SQLITE_CREATE_INDEX 1 /* Index Name Table Name */ +#define SQLITE_CREATE_TABLE 2 /* Table Name NULL */ +#define SQLITE_CREATE_TEMP_INDEX 3 /* Index Name Table Name */ +#define SQLITE_CREATE_TEMP_TABLE 4 /* Table Name NULL */ +#define SQLITE_CREATE_TEMP_TRIGGER 5 /* Trigger Name Table Name */ +#define SQLITE_CREATE_TEMP_VIEW 6 /* View Name NULL */ +#define SQLITE_CREATE_TRIGGER 7 /* Trigger Name Table Name */ +#define SQLITE_CREATE_VIEW 8 /* View Name NULL */ +#define SQLITE_DELETE 9 /* Table Name NULL */ +#define SQLITE_DROP_INDEX 10 /* Index Name Table Name */ +#define SQLITE_DROP_TABLE 11 /* Table Name NULL */ +#define SQLITE_DROP_TEMP_INDEX 12 /* Index Name Table Name */ +#define SQLITE_DROP_TEMP_TABLE 13 /* Table Name NULL */ +#define SQLITE_DROP_TEMP_TRIGGER 14 /* Trigger Name Table Name */ +#define SQLITE_DROP_TEMP_VIEW 15 /* View Name NULL */ +#define SQLITE_DROP_TRIGGER 16 /* Trigger Name Table Name */ +#define SQLITE_DROP_VIEW 17 /* View Name NULL */ +#define SQLITE_INSERT 18 /* Table Name NULL */ +#define SQLITE_PRAGMA 19 /* Pragma Name 1st arg or NULL */ +#define SQLITE_READ 20 /* Table Name Column Name */ +#define SQLITE_SELECT 21 /* NULL NULL */ +#define SQLITE_TRANSACTION 22 /* Operation NULL */ +#define SQLITE_UPDATE 23 /* Table Name Column Name */ +#define SQLITE_ATTACH 24 /* Filename NULL */ +#define SQLITE_DETACH 25 /* Database Name NULL */ +#define SQLITE_ALTER_TABLE 26 /* Database Name Table Name */ +#define SQLITE_REINDEX 27 /* Index Name NULL */ +#define SQLITE_ANALYZE 28 /* Table Name NULL */ +#define SQLITE_CREATE_VTABLE 29 /* Table Name Module Name */ +#define SQLITE_DROP_VTABLE 30 /* Table Name Module Name */ +#define SQLITE_FUNCTION 31 /* NULL Function Name */ +#define SQLITE_SAVEPOINT 32 /* Operation Savepoint Name */ +#define SQLITE_COPY 0 /* No longer used */ +#define SQLITE_RECURSIVE 33 /* NULL NULL */ + +/* +** CAPI3REF: Tracing And Profiling Functions +** METHOD: sqlite3 +** +** These routines are deprecated. Use the [sqlite3_trace_v2()] interface +** instead of the routines described here. +** +** These routines register callback functions that can be used for +** tracing and profiling the execution of SQL statements. +** +** ^The callback function registered by sqlite3_trace() is invoked at +** various times when an SQL statement is being run by [sqlite3_step()]. +** ^The sqlite3_trace() callback is invoked with a UTF-8 rendering of the +** SQL statement text as the statement first begins executing. +** ^(Additional sqlite3_trace() callbacks might occur +** as each triggered subprogram is entered. The callbacks for triggers +** contain a UTF-8 SQL comment that identifies the trigger.)^ +** +** The [SQLITE_TRACE_SIZE_LIMIT] compile-time option can be used to limit +** the length of [bound parameter] expansion in the output of sqlite3_trace(). +** +** ^The callback function registered by sqlite3_profile() is invoked +** as each SQL statement finishes. ^The profile callback contains +** the original statement text and an estimate of wall-clock time +** of how long that statement took to run. ^The profile callback +** time is in units of nanoseconds, however the current implementation +** is only capable of millisecond resolution so the six least significant +** digits in the time are meaningless. Future versions of SQLite +** might provide greater resolution on the profiler callback. Invoking +** either [sqlite3_trace()] or [sqlite3_trace_v2()] will cancel the +** profile callback. +*/ +SQLITE_API SQLITE_DEPRECATED void *sqlite3_trace(sqlite3*, + void(*xTrace)(void*,const char*), void*); +SQLITE_API SQLITE_DEPRECATED void *sqlite3_profile(sqlite3*, + void(*xProfile)(void*,const char*,sqlite3_uint64), void*); + +/* +** CAPI3REF: SQL Trace Event Codes +** KEYWORDS: SQLITE_TRACE +** +** These constants identify classes of events that can be monitored +** using the [sqlite3_trace_v2()] tracing logic. The M argument +** to [sqlite3_trace_v2(D,M,X,P)] is an OR-ed combination of one or more of +** the following constants. ^The first argument to the trace callback +** is one of the following constants. +** +** New tracing constants may be added in future releases. +** +** ^A trace callback has four arguments: xCallback(T,C,P,X). +** ^The T argument is one of the integer type codes above. +** ^The C argument is a copy of the context pointer passed in as the +** fourth argument to [sqlite3_trace_v2()]. +** The P and X arguments are pointers whose meanings depend on T. +** +**
    +** [[SQLITE_TRACE_STMT]]
    SQLITE_TRACE_STMT
    +**
    ^An SQLITE_TRACE_STMT callback is invoked when a prepared statement +** first begins running and possibly at other times during the +** execution of the prepared statement, such as at the start of each +** trigger subprogram. ^The P argument is a pointer to the +** [prepared statement]. ^The X argument is a pointer to a string which +** is the unexpanded SQL text of the prepared statement or an SQL comment +** that indicates the invocation of a trigger. ^The callback can compute +** the same text that would have been returned by the legacy [sqlite3_trace()] +** interface by using the X argument when X begins with "--" and invoking +** [sqlite3_expanded_sql(P)] otherwise. +** +** [[SQLITE_TRACE_PROFILE]]
    SQLITE_TRACE_PROFILE
    +**
    ^An SQLITE_TRACE_PROFILE callback provides approximately the same +** information as is provided by the [sqlite3_profile()] callback. +** ^The P argument is a pointer to the [prepared statement] and the +** X argument points to a 64-bit integer which is the estimated of +** the number of nanosecond that the prepared statement took to run. +** ^The SQLITE_TRACE_PROFILE callback is invoked when the statement finishes. +** +** [[SQLITE_TRACE_ROW]]
    SQLITE_TRACE_ROW
    +**
    ^An SQLITE_TRACE_ROW callback is invoked whenever a prepared +** statement generates a single row of result. +** ^The P argument is a pointer to the [prepared statement] and the +** X argument is unused. +** +** [[SQLITE_TRACE_CLOSE]]
    SQLITE_TRACE_CLOSE
    +**
    ^An SQLITE_TRACE_CLOSE callback is invoked when a database +** connection closes. +** ^The P argument is a pointer to the [database connection] object +** and the X argument is unused. +**
    +*/ +#define SQLITE_TRACE_STMT 0x01 +#define SQLITE_TRACE_PROFILE 0x02 +#define SQLITE_TRACE_ROW 0x04 +#define SQLITE_TRACE_CLOSE 0x08 + +/* +** CAPI3REF: SQL Trace Hook +** METHOD: sqlite3 +** +** ^The sqlite3_trace_v2(D,M,X,P) interface registers a trace callback +** function X against [database connection] D, using property mask M +** and context pointer P. ^If the X callback is +** NULL or if the M mask is zero, then tracing is disabled. The +** M argument should be the bitwise OR-ed combination of +** zero or more [SQLITE_TRACE] constants. +** +** ^Each call to either sqlite3_trace() or sqlite3_trace_v2() overrides +** (cancels) any prior calls to sqlite3_trace() or sqlite3_trace_v2(). +** +** ^The X callback is invoked whenever any of the events identified by +** mask M occur. ^The integer return value from the callback is currently +** ignored, though this may change in future releases. Callback +** implementations should return zero to ensure future compatibility. +** +** ^A trace callback is invoked with four arguments: callback(T,C,P,X). +** ^The T argument is one of the [SQLITE_TRACE] +** constants to indicate why the callback was invoked. +** ^The C argument is a copy of the context pointer. +** The P and X arguments are pointers whose meanings depend on T. +** +** The sqlite3_trace_v2() interface is intended to replace the legacy +** interfaces [sqlite3_trace()] and [sqlite3_profile()], both of which +** are deprecated. +*/ +SQLITE_API int sqlite3_trace_v2( + sqlite3*, + unsigned uMask, + int(*xCallback)(unsigned,void*,void*,void*), + void *pCtx +); + +/* +** CAPI3REF: Query Progress Callbacks +** METHOD: sqlite3 +** +** ^The sqlite3_progress_handler(D,N,X,P) interface causes the callback +** function X to be invoked periodically during long running calls to +** [sqlite3_exec()], [sqlite3_step()] and [sqlite3_get_table()] for +** database connection D. An example use for this +** interface is to keep a GUI updated during a large query. +** +** ^The parameter P is passed through as the only parameter to the +** callback function X. ^The parameter N is the approximate number of +** [virtual machine instructions] that are evaluated between successive +** invocations of the callback X. ^If N is less than one then the progress +** handler is disabled. +** +** ^Only a single progress handler may be defined at one time per +** [database connection]; setting a new progress handler cancels the +** old one. ^Setting parameter X to NULL disables the progress handler. +** ^The progress handler is also disabled by setting N to a value less +** than 1. +** +** ^If the progress callback returns non-zero, the operation is +** interrupted. This feature can be used to implement a +** "Cancel" button on a GUI progress dialog box. +** +** The progress handler callback must not do anything that will modify +** the database connection that invoked the progress handler. +** Note that [sqlite3_prepare_v2()] and [sqlite3_step()] both modify their +** database connections for the meaning of "modify" in this paragraph. +** +*/ +SQLITE_API void sqlite3_progress_handler(sqlite3*, int, int(*)(void*), void*); + +/* +** CAPI3REF: Opening A New Database Connection +** CONSTRUCTOR: sqlite3 +** +** ^These routines open an SQLite database file as specified by the +** filename argument. ^The filename argument is interpreted as UTF-8 for +** sqlite3_open() and sqlite3_open_v2() and as UTF-16 in the native byte +** order for sqlite3_open16(). ^(A [database connection] handle is usually +** returned in *ppDb, even if an error occurs. The only exception is that +** if SQLite is unable to allocate memory to hold the [sqlite3] object, +** a NULL will be written into *ppDb instead of a pointer to the [sqlite3] +** object.)^ ^(If the database is opened (and/or created) successfully, then +** [SQLITE_OK] is returned. Otherwise an [error code] is returned.)^ ^The +** [sqlite3_errmsg()] or [sqlite3_errmsg16()] routines can be used to obtain +** an English language description of the error following a failure of any +** of the sqlite3_open() routines. +** +** ^The default encoding will be UTF-8 for databases created using +** sqlite3_open() or sqlite3_open_v2(). ^The default encoding for databases +** created using sqlite3_open16() will be UTF-16 in the native byte order. +** +** Whether or not an error occurs when it is opened, resources +** associated with the [database connection] handle should be released by +** passing it to [sqlite3_close()] when it is no longer required. +** +** The sqlite3_open_v2() interface works like sqlite3_open() +** except that it accepts two additional parameters for additional control +** over the new database connection. ^(The flags parameter to +** sqlite3_open_v2() must include, at a minimum, one of the following +** three flag combinations:)^ +** +**
    +** ^(
    [SQLITE_OPEN_READONLY]
    +**
    The database is opened in read-only mode. If the database does not +** already exist, an error is returned.
    )^ +** +** ^(
    [SQLITE_OPEN_READWRITE]
    +**
    The database is opened for reading and writing if possible, or reading +** only if the file is write protected by the operating system. In either +** case the database must already exist, otherwise an error is returned.
    )^ +** +** ^(
    [SQLITE_OPEN_READWRITE] | [SQLITE_OPEN_CREATE]
    +**
    The database is opened for reading and writing, and is created if +** it does not already exist. This is the behavior that is always used for +** sqlite3_open() and sqlite3_open16().
    )^ +**
    +** +** In addition to the required flags, the following optional flags are +** also supported: +** +**
    +** ^(
    [SQLITE_OPEN_URI]
    +**
    The filename can be interpreted as a URI if this flag is set.
    )^ +** +** ^(
    [SQLITE_OPEN_MEMORY]
    +**
    The database will be opened as an in-memory database. The database +** is named by the "filename" argument for the purposes of cache-sharing, +** if shared cache mode is enabled, but the "filename" is otherwise ignored. +**
    )^ +** +** ^(
    [SQLITE_OPEN_NOMUTEX]
    +**
    The new database connection will use the "multi-thread" +** [threading mode].)^ This means that separate threads are allowed +** to use SQLite at the same time, as long as each thread is using +** a different [database connection]. +** +** ^(
    [SQLITE_OPEN_FULLMUTEX]
    +**
    The new database connection will use the "serialized" +** [threading mode].)^ This means the multiple threads can safely +** attempt to use the same database connection at the same time. +** (Mutexes will block any actual concurrency, but in this mode +** there is no harm in trying.) +** +** ^(
    [SQLITE_OPEN_SHAREDCACHE]
    +**
    The database is opened [shared cache] enabled, overriding +** the default shared cache setting provided by +** [sqlite3_enable_shared_cache()].)^ +** +** ^(
    [SQLITE_OPEN_PRIVATECACHE]
    +**
    The database is opened [shared cache] disabled, overriding +** the default shared cache setting provided by +** [sqlite3_enable_shared_cache()].)^ +** +** [[OPEN_EXRESCODE]] ^(
    [SQLITE_OPEN_EXRESCODE]
    +**
    The database connection comes up in "extended result code mode". +** In other words, the database behaves has if +** [sqlite3_extended_result_codes(db,1)] where called on the database +** connection as soon as the connection is created. In addition to setting +** the extended result code mode, this flag also causes [sqlite3_open_v2()] +** to return an extended result code.
    +** +** [[OPEN_NOFOLLOW]] ^(
    [SQLITE_OPEN_NOFOLLOW]
    +**
    The database filename is not allowed to be a symbolic link
    +**
    )^ +** +** If the 3rd parameter to sqlite3_open_v2() is not one of the +** required combinations shown above optionally combined with other +** [SQLITE_OPEN_READONLY | SQLITE_OPEN_* bits] +** then the behavior is undefined. Historic versions of SQLite +** have silently ignored surplus bits in the flags parameter to +** sqlite3_open_v2(), however that behavior might not be carried through +** into future versions of SQLite and so applications should not rely +** upon it. Note in particular that the SQLITE_OPEN_EXCLUSIVE flag is a no-op +** for sqlite3_open_v2(). The SQLITE_OPEN_EXCLUSIVE does *not* cause +** the open to fail if the database already exists. The SQLITE_OPEN_EXCLUSIVE +** flag is intended for use by the [sqlite3_vfs|VFS interface] only, and not +** by sqlite3_open_v2(). +** +** ^The fourth parameter to sqlite3_open_v2() is the name of the +** [sqlite3_vfs] object that defines the operating system interface that +** the new database connection should use. ^If the fourth parameter is +** a NULL pointer then the default [sqlite3_vfs] object is used. +** +** ^If the filename is ":memory:", then a private, temporary in-memory database +** is created for the connection. ^This in-memory database will vanish when +** the database connection is closed. Future versions of SQLite might +** make use of additional special filenames that begin with the ":" character. +** It is recommended that when a database filename actually does begin with +** a ":" character you should prefix the filename with a pathname such as +** "./" to avoid ambiguity. +** +** ^If the filename is an empty string, then a private, temporary +** on-disk database will be created. ^This private database will be +** automatically deleted as soon as the database connection is closed. +** +** [[URI filenames in sqlite3_open()]]

    URI Filenames

    +** +** ^If [URI filename] interpretation is enabled, and the filename argument +** begins with "file:", then the filename is interpreted as a URI. ^URI +** filename interpretation is enabled if the [SQLITE_OPEN_URI] flag is +** set in the third argument to sqlite3_open_v2(), or if it has +** been enabled globally using the [SQLITE_CONFIG_URI] option with the +** [sqlite3_config()] method or by the [SQLITE_USE_URI] compile-time option. +** URI filename interpretation is turned off +** by default, but future releases of SQLite might enable URI filename +** interpretation by default. See "[URI filenames]" for additional +** information. +** +** URI filenames are parsed according to RFC 3986. ^If the URI contains an +** authority, then it must be either an empty string or the string +** "localhost". ^If the authority is not an empty string or "localhost", an +** error is returned to the caller. ^The fragment component of a URI, if +** present, is ignored. +** +** ^SQLite uses the path component of the URI as the name of the disk file +** which contains the database. ^If the path begins with a '/' character, +** then it is interpreted as an absolute path. ^If the path does not begin +** with a '/' (meaning that the authority section is omitted from the URI) +** then the path is interpreted as a relative path. +** ^(On windows, the first component of an absolute path +** is a drive specification (e.g. "C:").)^ +** +** [[core URI query parameters]] +** The query component of a URI may contain parameters that are interpreted +** either by SQLite itself, or by a [VFS | custom VFS implementation]. +** SQLite and its built-in [VFSes] interpret the +** following query parameters: +** +**
      +**
    • vfs: ^The "vfs" parameter may be used to specify the name of +** a VFS object that provides the operating system interface that should +** be used to access the database file on disk. ^If this option is set to +** an empty string the default VFS object is used. ^Specifying an unknown +** VFS is an error. ^If sqlite3_open_v2() is used and the vfs option is +** present, then the VFS specified by the option takes precedence over +** the value passed as the fourth parameter to sqlite3_open_v2(). +** +**
    • mode: ^(The mode parameter may be set to either "ro", "rw", +** "rwc", or "memory". Attempting to set it to any other value is +** an error)^. +** ^If "ro" is specified, then the database is opened for read-only +** access, just as if the [SQLITE_OPEN_READONLY] flag had been set in the +** third argument to sqlite3_open_v2(). ^If the mode option is set to +** "rw", then the database is opened for read-write (but not create) +** access, as if SQLITE_OPEN_READWRITE (but not SQLITE_OPEN_CREATE) had +** been set. ^Value "rwc" is equivalent to setting both +** SQLITE_OPEN_READWRITE and SQLITE_OPEN_CREATE. ^If the mode option is +** set to "memory" then a pure [in-memory database] that never reads +** or writes from disk is used. ^It is an error to specify a value for +** the mode parameter that is less restrictive than that specified by +** the flags passed in the third parameter to sqlite3_open_v2(). +** +**
    • cache: ^The cache parameter may be set to either "shared" or +** "private". ^Setting it to "shared" is equivalent to setting the +** SQLITE_OPEN_SHAREDCACHE bit in the flags argument passed to +** sqlite3_open_v2(). ^Setting the cache parameter to "private" is +** equivalent to setting the SQLITE_OPEN_PRIVATECACHE bit. +** ^If sqlite3_open_v2() is used and the "cache" parameter is present in +** a URI filename, its value overrides any behavior requested by setting +** SQLITE_OPEN_PRIVATECACHE or SQLITE_OPEN_SHAREDCACHE flag. +** +**
    • psow: ^The psow parameter indicates whether or not the +** [powersafe overwrite] property does or does not apply to the +** storage media on which the database file resides. +** +**
    • nolock: ^The nolock parameter is a boolean query parameter +** which if set disables file locking in rollback journal modes. This +** is useful for accessing a database on a filesystem that does not +** support locking. Caution: Database corruption might result if two +** or more processes write to the same database and any one of those +** processes uses nolock=1. +** +**
    • immutable: ^The immutable parameter is a boolean query +** parameter that indicates that the database file is stored on +** read-only media. ^When immutable is set, SQLite assumes that the +** database file cannot be changed, even by a process with higher +** privilege, and so the database is opened read-only and all locking +** and change detection is disabled. Caution: Setting the immutable +** property on a database file that does in fact change can result +** in incorrect query results and/or [SQLITE_CORRUPT] errors. +** See also: [SQLITE_IOCAP_IMMUTABLE]. +** +**
    +** +** ^Specifying an unknown parameter in the query component of a URI is not an +** error. Future versions of SQLite might understand additional query +** parameters. See "[query parameters with special meaning to SQLite]" for +** additional information. +** +** [[URI filename examples]]

    URI filename examples

    +** +** +**
    URI filenames Results +**
    file:data.db +** Open the file "data.db" in the current directory. +**
    file:/home/fred/data.db
    +** file:///home/fred/data.db
    +** file://localhost/home/fred/data.db
    +** Open the database file "/home/fred/data.db". +**
    file://darkstar/home/fred/data.db +** An error. "darkstar" is not a recognized authority. +**
    +** file:///C:/Documents%20and%20Settings/fred/Desktop/data.db +** Windows only: Open the file "data.db" on fred's desktop on drive +** C:. Note that the %20 escaping in this example is not strictly +** necessary - space characters can be used literally +** in URI filenames. +**
    file:data.db?mode=ro&cache=private +** Open file "data.db" in the current directory for read-only access. +** Regardless of whether or not shared-cache mode is enabled by +** default, use a private cache. +**
    file:/home/fred/data.db?vfs=unix-dotfile +** Open file "/home/fred/data.db". Use the special VFS "unix-dotfile" +** that uses dot-files in place of posix advisory locking. +**
    file:data.db?mode=readonly +** An error. "readonly" is not a valid option for the "mode" parameter. +** Use "ro" instead: "file:data.db?mode=ro". +**
    +** +** ^URI hexadecimal escape sequences (%HH) are supported within the path and +** query components of a URI. A hexadecimal escape sequence consists of a +** percent sign - "%" - followed by exactly two hexadecimal digits +** specifying an octet value. ^Before the path or query components of a +** URI filename are interpreted, they are encoded using UTF-8 and all +** hexadecimal escape sequences replaced by a single byte containing the +** corresponding octet. If this process generates an invalid UTF-8 encoding, +** the results are undefined. +** +** Note to Windows users: The encoding used for the filename argument +** of sqlite3_open() and sqlite3_open_v2() must be UTF-8, not whatever +** codepage is currently defined. Filenames containing international +** characters must be converted to UTF-8 prior to passing them into +** sqlite3_open() or sqlite3_open_v2(). +** +** Note to Windows Runtime users: The temporary directory must be set +** prior to calling sqlite3_open() or sqlite3_open_v2(). Otherwise, various +** features that require the use of temporary files may fail. +** +** See also: [sqlite3_temp_directory] +*/ +SQLITE_API int sqlite3_open( + const char *filename, /* Database filename (UTF-8) */ + sqlite3 **ppDb /* OUT: SQLite db handle */ +); +SQLITE_API int sqlite3_open16( + const void *filename, /* Database filename (UTF-16) */ + sqlite3 **ppDb /* OUT: SQLite db handle */ +); +SQLITE_API int sqlite3_open_v2( + const char *filename, /* Database filename (UTF-8) */ + sqlite3 **ppDb, /* OUT: SQLite db handle */ + int flags, /* Flags */ + const char *zVfs /* Name of VFS module to use */ +); + +/* +** CAPI3REF: Obtain Values For URI Parameters +** +** These are utility routines, useful to [VFS|custom VFS implementations], +** that check if a database file was a URI that contained a specific query +** parameter, and if so obtains the value of that query parameter. +** +** The first parameter to these interfaces (hereafter referred to +** as F) must be one of: +**
      +**
    • A database filename pointer created by the SQLite core and +** passed into the xOpen() method of a VFS implemention, or +**
    • A filename obtained from [sqlite3_db_filename()], or +**
    • A new filename constructed using [sqlite3_create_filename()]. +**
    +** If the F parameter is not one of the above, then the behavior is +** undefined and probably undesirable. Older versions of SQLite were +** more tolerant of invalid F parameters than newer versions. +** +** If F is a suitable filename (as described in the previous paragraph) +** and if P is the name of the query parameter, then +** sqlite3_uri_parameter(F,P) returns the value of the P +** parameter if it exists or a NULL pointer if P does not appear as a +** query parameter on F. If P is a query parameter of F and it +** has no explicit value, then sqlite3_uri_parameter(F,P) returns +** a pointer to an empty string. +** +** The sqlite3_uri_boolean(F,P,B) routine assumes that P is a boolean +** parameter and returns true (1) or false (0) according to the value +** of P. The sqlite3_uri_boolean(F,P,B) routine returns true (1) if the +** value of query parameter P is one of "yes", "true", or "on" in any +** case or if the value begins with a non-zero number. The +** sqlite3_uri_boolean(F,P,B) routines returns false (0) if the value of +** query parameter P is one of "no", "false", or "off" in any case or +** if the value begins with a numeric zero. If P is not a query +** parameter on F or if the value of P does not match any of the +** above, then sqlite3_uri_boolean(F,P,B) returns (B!=0). +** +** The sqlite3_uri_int64(F,P,D) routine converts the value of P into a +** 64-bit signed integer and returns that integer, or D if P does not +** exist. If the value of P is something other than an integer, then +** zero is returned. +** +** The sqlite3_uri_key(F,N) returns a pointer to the name (not +** the value) of the N-th query parameter for filename F, or a NULL +** pointer if N is less than zero or greater than the number of query +** parameters minus 1. The N value is zero-based so N should be 0 to obtain +** the name of the first query parameter, 1 for the second parameter, and +** so forth. +** +** If F is a NULL pointer, then sqlite3_uri_parameter(F,P) returns NULL and +** sqlite3_uri_boolean(F,P,B) returns B. If F is not a NULL pointer and +** is not a database file pathname pointer that the SQLite core passed +** into the xOpen VFS method, then the behavior of this routine is undefined +** and probably undesirable. +** +** Beginning with SQLite [version 3.31.0] ([dateof:3.31.0]) the input F +** parameter can also be the name of a rollback journal file or WAL file +** in addition to the main database file. Prior to version 3.31.0, these +** routines would only work if F was the name of the main database file. +** When the F parameter is the name of the rollback journal or WAL file, +** it has access to all the same query parameters as were found on the +** main database file. +** +** See the [URI filename] documentation for additional information. +*/ +SQLITE_API const char *sqlite3_uri_parameter(const char *zFilename, const char *zParam); +SQLITE_API int sqlite3_uri_boolean(const char *zFile, const char *zParam, int bDefault); +SQLITE_API sqlite3_int64 sqlite3_uri_int64(const char*, const char*, sqlite3_int64); +SQLITE_API const char *sqlite3_uri_key(const char *zFilename, int N); + +/* +** CAPI3REF: Translate filenames +** +** These routines are available to [VFS|custom VFS implementations] for +** translating filenames between the main database file, the journal file, +** and the WAL file. +** +** If F is the name of an sqlite database file, journal file, or WAL file +** passed by the SQLite core into the VFS, then sqlite3_filename_database(F) +** returns the name of the corresponding database file. +** +** If F is the name of an sqlite database file, journal file, or WAL file +** passed by the SQLite core into the VFS, or if F is a database filename +** obtained from [sqlite3_db_filename()], then sqlite3_filename_journal(F) +** returns the name of the corresponding rollback journal file. +** +** If F is the name of an sqlite database file, journal file, or WAL file +** that was passed by the SQLite core into the VFS, or if F is a database +** filename obtained from [sqlite3_db_filename()], then +** sqlite3_filename_wal(F) returns the name of the corresponding +** WAL file. +** +** In all of the above, if F is not the name of a database, journal or WAL +** filename passed into the VFS from the SQLite core and F is not the +** return value from [sqlite3_db_filename()], then the result is +** undefined and is likely a memory access violation. +*/ +SQLITE_API const char *sqlite3_filename_database(const char*); +SQLITE_API const char *sqlite3_filename_journal(const char*); +SQLITE_API const char *sqlite3_filename_wal(const char*); + +/* +** CAPI3REF: Database File Corresponding To A Journal +** +** ^If X is the name of a rollback or WAL-mode journal file that is +** passed into the xOpen method of [sqlite3_vfs], then +** sqlite3_database_file_object(X) returns a pointer to the [sqlite3_file] +** object that represents the main database file. +** +** This routine is intended for use in custom [VFS] implementations +** only. It is not a general-purpose interface. +** The argument sqlite3_file_object(X) must be a filename pointer that +** has been passed into [sqlite3_vfs].xOpen method where the +** flags parameter to xOpen contains one of the bits +** [SQLITE_OPEN_MAIN_JOURNAL] or [SQLITE_OPEN_WAL]. Any other use +** of this routine results in undefined and probably undesirable +** behavior. +*/ +SQLITE_API sqlite3_file *sqlite3_database_file_object(const char*); + +/* +** CAPI3REF: Create and Destroy VFS Filenames +** +** These interfces are provided for use by [VFS shim] implementations and +** are not useful outside of that context. +** +** The sqlite3_create_filename(D,J,W,N,P) allocates memory to hold a version of +** database filename D with corresponding journal file J and WAL file W and +** with N URI parameters key/values pairs in the array P. The result from +** sqlite3_create_filename(D,J,W,N,P) is a pointer to a database filename that +** is safe to pass to routines like: +**
      +**
    • [sqlite3_uri_parameter()], +**
    • [sqlite3_uri_boolean()], +**
    • [sqlite3_uri_int64()], +**
    • [sqlite3_uri_key()], +**
    • [sqlite3_filename_database()], +**
    • [sqlite3_filename_journal()], or +**
    • [sqlite3_filename_wal()]. +**
    +** If a memory allocation error occurs, sqlite3_create_filename() might +** return a NULL pointer. The memory obtained from sqlite3_create_filename(X) +** must be released by a corresponding call to sqlite3_free_filename(Y). +** +** The P parameter in sqlite3_create_filename(D,J,W,N,P) should be an array +** of 2*N pointers to strings. Each pair of pointers in this array corresponds +** to a key and value for a query parameter. The P parameter may be a NULL +** pointer if N is zero. None of the 2*N pointers in the P array may be +** NULL pointers and key pointers should not be empty strings. +** None of the D, J, or W parameters to sqlite3_create_filename(D,J,W,N,P) may +** be NULL pointers, though they can be empty strings. +** +** The sqlite3_free_filename(Y) routine releases a memory allocation +** previously obtained from sqlite3_create_filename(). Invoking +** sqlite3_free_filename(Y) where Y is a NULL pointer is a harmless no-op. +** +** If the Y parameter to sqlite3_free_filename(Y) is anything other +** than a NULL pointer or a pointer previously acquired from +** sqlite3_create_filename(), then bad things such as heap +** corruption or segfaults may occur. The value Y should not be +** used again after sqlite3_free_filename(Y) has been called. This means +** that if the [sqlite3_vfs.xOpen()] method of a VFS has been called using Y, +** then the corresponding [sqlite3_module.xClose() method should also be +** invoked prior to calling sqlite3_free_filename(Y). +*/ +SQLITE_API char *sqlite3_create_filename( + const char *zDatabase, + const char *zJournal, + const char *zWal, + int nParam, + const char **azParam +); +SQLITE_API void sqlite3_free_filename(char*); + +/* +** CAPI3REF: Error Codes And Messages +** METHOD: sqlite3 +** +** ^If the most recent sqlite3_* API call associated with +** [database connection] D failed, then the sqlite3_errcode(D) interface +** returns the numeric [result code] or [extended result code] for that +** API call. +** ^The sqlite3_extended_errcode() +** interface is the same except that it always returns the +** [extended result code] even when extended result codes are +** disabled. +** +** The values returned by sqlite3_errcode() and/or +** sqlite3_extended_errcode() might change with each API call. +** Except, there are some interfaces that are guaranteed to never +** change the value of the error code. The error-code preserving +** interfaces include the following: +** +**
      +**
    • sqlite3_errcode() +**
    • sqlite3_extended_errcode() +**
    • sqlite3_errmsg() +**
    • sqlite3_errmsg16() +**
    • sqlite3_error_offset() +**
    +** +** ^The sqlite3_errmsg() and sqlite3_errmsg16() return English-language +** text that describes the error, as either UTF-8 or UTF-16 respectively. +** ^(Memory to hold the error message string is managed internally. +** The application does not need to worry about freeing the result. +** However, the error string might be overwritten or deallocated by +** subsequent calls to other SQLite interface functions.)^ +** +** ^The sqlite3_errstr() interface returns the English-language text +** that describes the [result code], as UTF-8. +** ^(Memory to hold the error message string is managed internally +** and must not be freed by the application)^. +** +** ^If the most recent error references a specific token in the input +** SQL, the sqlite3_error_offset() interface returns the byte offset +** of the start of that token. ^The byte offset returned by +** sqlite3_error_offset() assumes that the input SQL is UTF8. +** ^If the most recent error does not reference a specific token in the input +** SQL, then the sqlite3_error_offset() function returns -1. +** +** When the serialized [threading mode] is in use, it might be the +** case that a second error occurs on a separate thread in between +** the time of the first error and the call to these interfaces. +** When that happens, the second error will be reported since these +** interfaces always report the most recent result. To avoid +** this, each thread can obtain exclusive use of the [database connection] D +** by invoking [sqlite3_mutex_enter]([sqlite3_db_mutex](D)) before beginning +** to use D and invoking [sqlite3_mutex_leave]([sqlite3_db_mutex](D)) after +** all calls to the interfaces listed here are completed. +** +** If an interface fails with SQLITE_MISUSE, that means the interface +** was invoked incorrectly by the application. In that case, the +** error code and message may or may not be set. +*/ +SQLITE_API int sqlite3_errcode(sqlite3 *db); +SQLITE_API int sqlite3_extended_errcode(sqlite3 *db); +SQLITE_API const char *sqlite3_errmsg(sqlite3*); +SQLITE_API const void *sqlite3_errmsg16(sqlite3*); +SQLITE_API const char *sqlite3_errstr(int); +SQLITE_API int sqlite3_error_offset(sqlite3 *db); + +/* +** CAPI3REF: Prepared Statement Object +** KEYWORDS: {prepared statement} {prepared statements} +** +** An instance of this object represents a single SQL statement that +** has been compiled into binary form and is ready to be evaluated. +** +** Think of each SQL statement as a separate computer program. The +** original SQL text is source code. A prepared statement object +** is the compiled object code. All SQL must be converted into a +** prepared statement before it can be run. +** +** The life-cycle of a prepared statement object usually goes like this: +** +**
      +**
    1. Create the prepared statement object using [sqlite3_prepare_v2()]. +**
    2. Bind values to [parameters] using the sqlite3_bind_*() +** interfaces. +**
    3. Run the SQL by calling [sqlite3_step()] one or more times. +**
    4. Reset the prepared statement using [sqlite3_reset()] then go back +** to step 2. Do this zero or more times. +**
    5. Destroy the object using [sqlite3_finalize()]. +**
    +*/ +typedef struct sqlite3_stmt sqlite3_stmt; + +/* +** CAPI3REF: Run-time Limits +** METHOD: sqlite3 +** +** ^(This interface allows the size of various constructs to be limited +** on a connection by connection basis. The first parameter is the +** [database connection] whose limit is to be set or queried. The +** second parameter is one of the [limit categories] that define a +** class of constructs to be size limited. The third parameter is the +** new limit for that construct.)^ +** +** ^If the new limit is a negative number, the limit is unchanged. +** ^(For each limit category SQLITE_LIMIT_NAME there is a +** [limits | hard upper bound] +** set at compile-time by a C preprocessor macro called +** [limits | SQLITE_MAX_NAME]. +** (The "_LIMIT_" in the name is changed to "_MAX_".))^ +** ^Attempts to increase a limit above its hard upper bound are +** silently truncated to the hard upper bound. +** +** ^Regardless of whether or not the limit was changed, the +** [sqlite3_limit()] interface returns the prior value of the limit. +** ^Hence, to find the current value of a limit without changing it, +** simply invoke this interface with the third parameter set to -1. +** +** Run-time limits are intended for use in applications that manage +** both their own internal database and also databases that are controlled +** by untrusted external sources. An example application might be a +** web browser that has its own databases for storing history and +** separate databases controlled by JavaScript applications downloaded +** off the Internet. The internal databases can be given the +** large, default limits. Databases managed by external sources can +** be given much smaller limits designed to prevent a denial of service +** attack. Developers might also want to use the [sqlite3_set_authorizer()] +** interface to further control untrusted SQL. The size of the database +** created by an untrusted script can be contained using the +** [max_page_count] [PRAGMA]. +** +** New run-time limit categories may be added in future releases. +*/ +SQLITE_API int sqlite3_limit(sqlite3*, int id, int newVal); + +/* +** CAPI3REF: Run-Time Limit Categories +** KEYWORDS: {limit category} {*limit categories} +** +** These constants define various performance limits +** that can be lowered at run-time using [sqlite3_limit()]. +** The synopsis of the meanings of the various limits is shown below. +** Additional information is available at [limits | Limits in SQLite]. +** +**
    +** [[SQLITE_LIMIT_LENGTH]] ^(
    SQLITE_LIMIT_LENGTH
    +**
    The maximum size of any string or BLOB or table row, in bytes.
    )^ +** +** [[SQLITE_LIMIT_SQL_LENGTH]] ^(
    SQLITE_LIMIT_SQL_LENGTH
    +**
    The maximum length of an SQL statement, in bytes.
    )^ +** +** [[SQLITE_LIMIT_COLUMN]] ^(
    SQLITE_LIMIT_COLUMN
    +**
    The maximum number of columns in a table definition or in the +** result set of a [SELECT] or the maximum number of columns in an index +** or in an ORDER BY or GROUP BY clause.
    )^ +** +** [[SQLITE_LIMIT_EXPR_DEPTH]] ^(
    SQLITE_LIMIT_EXPR_DEPTH
    +**
    The maximum depth of the parse tree on any expression.
    )^ +** +** [[SQLITE_LIMIT_COMPOUND_SELECT]] ^(
    SQLITE_LIMIT_COMPOUND_SELECT
    +**
    The maximum number of terms in a compound SELECT statement.
    )^ +** +** [[SQLITE_LIMIT_VDBE_OP]] ^(
    SQLITE_LIMIT_VDBE_OP
    +**
    The maximum number of instructions in a virtual machine program +** used to implement an SQL statement. If [sqlite3_prepare_v2()] or +** the equivalent tries to allocate space for more than this many opcodes +** in a single prepared statement, an SQLITE_NOMEM error is returned.
    )^ +** +** [[SQLITE_LIMIT_FUNCTION_ARG]] ^(
    SQLITE_LIMIT_FUNCTION_ARG
    +**
    The maximum number of arguments on a function.
    )^ +** +** [[SQLITE_LIMIT_ATTACHED]] ^(
    SQLITE_LIMIT_ATTACHED
    +**
    The maximum number of [ATTACH | attached databases].)^
    +** +** [[SQLITE_LIMIT_LIKE_PATTERN_LENGTH]] +** ^(
    SQLITE_LIMIT_LIKE_PATTERN_LENGTH
    +**
    The maximum length of the pattern argument to the [LIKE] or +** [GLOB] operators.
    )^ +** +** [[SQLITE_LIMIT_VARIABLE_NUMBER]] +** ^(
    SQLITE_LIMIT_VARIABLE_NUMBER
    +**
    The maximum index number of any [parameter] in an SQL statement.)^ +** +** [[SQLITE_LIMIT_TRIGGER_DEPTH]] ^(
    SQLITE_LIMIT_TRIGGER_DEPTH
    +**
    The maximum depth of recursion for triggers.
    )^ +** +** [[SQLITE_LIMIT_WORKER_THREADS]] ^(
    SQLITE_LIMIT_WORKER_THREADS
    +**
    The maximum number of auxiliary worker threads that a single +** [prepared statement] may start.
    )^ +**
    +*/ +#define SQLITE_LIMIT_LENGTH 0 +#define SQLITE_LIMIT_SQL_LENGTH 1 +#define SQLITE_LIMIT_COLUMN 2 +#define SQLITE_LIMIT_EXPR_DEPTH 3 +#define SQLITE_LIMIT_COMPOUND_SELECT 4 +#define SQLITE_LIMIT_VDBE_OP 5 +#define SQLITE_LIMIT_FUNCTION_ARG 6 +#define SQLITE_LIMIT_ATTACHED 7 +#define SQLITE_LIMIT_LIKE_PATTERN_LENGTH 8 +#define SQLITE_LIMIT_VARIABLE_NUMBER 9 +#define SQLITE_LIMIT_TRIGGER_DEPTH 10 +#define SQLITE_LIMIT_WORKER_THREADS 11 + +/* +** CAPI3REF: Prepare Flags +** +** These constants define various flags that can be passed into +** "prepFlags" parameter of the [sqlite3_prepare_v3()] and +** [sqlite3_prepare16_v3()] interfaces. +** +** New flags may be added in future releases of SQLite. +** +**
    +** [[SQLITE_PREPARE_PERSISTENT]] ^(
    SQLITE_PREPARE_PERSISTENT
    +**
    The SQLITE_PREPARE_PERSISTENT flag is a hint to the query planner +** that the prepared statement will be retained for a long time and +** probably reused many times.)^ ^Without this flag, [sqlite3_prepare_v3()] +** and [sqlite3_prepare16_v3()] assume that the prepared statement will +** be used just once or at most a few times and then destroyed using +** [sqlite3_finalize()] relatively soon. The current implementation acts +** on this hint by avoiding the use of [lookaside memory] so as not to +** deplete the limited store of lookaside memory. Future versions of +** SQLite may act on this hint differently. +** +** [[SQLITE_PREPARE_NORMALIZE]]
    SQLITE_PREPARE_NORMALIZE
    +**
    The SQLITE_PREPARE_NORMALIZE flag is a no-op. This flag used +** to be required for any prepared statement that wanted to use the +** [sqlite3_normalized_sql()] interface. However, the +** [sqlite3_normalized_sql()] interface is now available to all +** prepared statements, regardless of whether or not they use this +** flag. +** +** [[SQLITE_PREPARE_NO_VTAB]]
    SQLITE_PREPARE_NO_VTAB
    +**
    The SQLITE_PREPARE_NO_VTAB flag causes the SQL compiler +** to return an error (error code SQLITE_ERROR) if the statement uses +** any virtual tables. +**
    +*/ +#define SQLITE_PREPARE_PERSISTENT 0x01 +#define SQLITE_PREPARE_NORMALIZE 0x02 +#define SQLITE_PREPARE_NO_VTAB 0x04 + +/* +** CAPI3REF: Compiling An SQL Statement +** KEYWORDS: {SQL statement compiler} +** METHOD: sqlite3 +** CONSTRUCTOR: sqlite3_stmt +** +** To execute an SQL statement, it must first be compiled into a byte-code +** program using one of these routines. Or, in other words, these routines +** are constructors for the [prepared statement] object. +** +** The preferred routine to use is [sqlite3_prepare_v2()]. The +** [sqlite3_prepare()] interface is legacy and should be avoided. +** [sqlite3_prepare_v3()] has an extra "prepFlags" option that is used +** for special purposes. +** +** The use of the UTF-8 interfaces is preferred, as SQLite currently +** does all parsing using UTF-8. The UTF-16 interfaces are provided +** as a convenience. The UTF-16 interfaces work by converting the +** input text into UTF-8, then invoking the corresponding UTF-8 interface. +** +** The first argument, "db", is a [database connection] obtained from a +** prior successful call to [sqlite3_open()], [sqlite3_open_v2()] or +** [sqlite3_open16()]. The database connection must not have been closed. +** +** The second argument, "zSql", is the statement to be compiled, encoded +** as either UTF-8 or UTF-16. The sqlite3_prepare(), sqlite3_prepare_v2(), +** and sqlite3_prepare_v3() +** interfaces use UTF-8, and sqlite3_prepare16(), sqlite3_prepare16_v2(), +** and sqlite3_prepare16_v3() use UTF-16. +** +** ^If the nByte argument is negative, then zSql is read up to the +** first zero terminator. ^If nByte is positive, then it is the +** number of bytes read from zSql. ^If nByte is zero, then no prepared +** statement is generated. +** If the caller knows that the supplied string is nul-terminated, then +** there is a small performance advantage to passing an nByte parameter that +** is the number of bytes in the input string including +** the nul-terminator. +** +** ^If pzTail is not NULL then *pzTail is made to point to the first byte +** past the end of the first SQL statement in zSql. These routines only +** compile the first statement in zSql, so *pzTail is left pointing to +** what remains uncompiled. +** +** ^*ppStmt is left pointing to a compiled [prepared statement] that can be +** executed using [sqlite3_step()]. ^If there is an error, *ppStmt is set +** to NULL. ^If the input text contains no SQL (if the input is an empty +** string or a comment) then *ppStmt is set to NULL. +** The calling procedure is responsible for deleting the compiled +** SQL statement using [sqlite3_finalize()] after it has finished with it. +** ppStmt may not be NULL. +** +** ^On success, the sqlite3_prepare() family of routines return [SQLITE_OK]; +** otherwise an [error code] is returned. +** +** The sqlite3_prepare_v2(), sqlite3_prepare_v3(), sqlite3_prepare16_v2(), +** and sqlite3_prepare16_v3() interfaces are recommended for all new programs. +** The older interfaces (sqlite3_prepare() and sqlite3_prepare16()) +** are retained for backwards compatibility, but their use is discouraged. +** ^In the "vX" interfaces, the prepared statement +** that is returned (the [sqlite3_stmt] object) contains a copy of the +** original SQL text. This causes the [sqlite3_step()] interface to +** behave differently in three ways: +** +**
      +**
    1. +** ^If the database schema changes, instead of returning [SQLITE_SCHEMA] as it +** always used to do, [sqlite3_step()] will automatically recompile the SQL +** statement and try to run it again. As many as [SQLITE_MAX_SCHEMA_RETRY] +** retries will occur before sqlite3_step() gives up and returns an error. +**
    2. +** +**
    3. +** ^When an error occurs, [sqlite3_step()] will return one of the detailed +** [error codes] or [extended error codes]. ^The legacy behavior was that +** [sqlite3_step()] would only return a generic [SQLITE_ERROR] result code +** and the application would have to make a second call to [sqlite3_reset()] +** in order to find the underlying cause of the problem. With the "v2" prepare +** interfaces, the underlying reason for the error is returned immediately. +**
    4. +** +**
    5. +** ^If the specific value bound to a [parameter | host parameter] in the +** WHERE clause might influence the choice of query plan for a statement, +** then the statement will be automatically recompiled, as if there had been +** a schema change, on the first [sqlite3_step()] call following any change +** to the [sqlite3_bind_text | bindings] of that [parameter]. +** ^The specific value of a WHERE-clause [parameter] might influence the +** choice of query plan if the parameter is the left-hand side of a [LIKE] +** or [GLOB] operator or if the parameter is compared to an indexed column +** and the [SQLITE_ENABLE_STAT4] compile-time option is enabled. +**
    6. +**
    +** +**

    ^sqlite3_prepare_v3() differs from sqlite3_prepare_v2() only in having +** the extra prepFlags parameter, which is a bit array consisting of zero or +** more of the [SQLITE_PREPARE_PERSISTENT|SQLITE_PREPARE_*] flags. ^The +** sqlite3_prepare_v2() interface works exactly the same as +** sqlite3_prepare_v3() with a zero prepFlags parameter. +*/ +SQLITE_API int sqlite3_prepare( + sqlite3 *db, /* Database handle */ + const char *zSql, /* SQL statement, UTF-8 encoded */ + int nByte, /* Maximum length of zSql in bytes. */ + sqlite3_stmt **ppStmt, /* OUT: Statement handle */ + const char **pzTail /* OUT: Pointer to unused portion of zSql */ +); +SQLITE_API int sqlite3_prepare_v2( + sqlite3 *db, /* Database handle */ + const char *zSql, /* SQL statement, UTF-8 encoded */ + int nByte, /* Maximum length of zSql in bytes. */ + sqlite3_stmt **ppStmt, /* OUT: Statement handle */ + const char **pzTail /* OUT: Pointer to unused portion of zSql */ +); +SQLITE_API int sqlite3_prepare_v3( + sqlite3 *db, /* Database handle */ + const char *zSql, /* SQL statement, UTF-8 encoded */ + int nByte, /* Maximum length of zSql in bytes. */ + unsigned int prepFlags, /* Zero or more SQLITE_PREPARE_ flags */ + sqlite3_stmt **ppStmt, /* OUT: Statement handle */ + const char **pzTail /* OUT: Pointer to unused portion of zSql */ +); +SQLITE_API int sqlite3_prepare16( + sqlite3 *db, /* Database handle */ + const void *zSql, /* SQL statement, UTF-16 encoded */ + int nByte, /* Maximum length of zSql in bytes. */ + sqlite3_stmt **ppStmt, /* OUT: Statement handle */ + const void **pzTail /* OUT: Pointer to unused portion of zSql */ +); +SQLITE_API int sqlite3_prepare16_v2( + sqlite3 *db, /* Database handle */ + const void *zSql, /* SQL statement, UTF-16 encoded */ + int nByte, /* Maximum length of zSql in bytes. */ + sqlite3_stmt **ppStmt, /* OUT: Statement handle */ + const void **pzTail /* OUT: Pointer to unused portion of zSql */ +); +SQLITE_API int sqlite3_prepare16_v3( + sqlite3 *db, /* Database handle */ + const void *zSql, /* SQL statement, UTF-16 encoded */ + int nByte, /* Maximum length of zSql in bytes. */ + unsigned int prepFlags, /* Zero or more SQLITE_PREPARE_ flags */ + sqlite3_stmt **ppStmt, /* OUT: Statement handle */ + const void **pzTail /* OUT: Pointer to unused portion of zSql */ +); + +/* +** CAPI3REF: Retrieving Statement SQL +** METHOD: sqlite3_stmt +** +** ^The sqlite3_sql(P) interface returns a pointer to a copy of the UTF-8 +** SQL text used to create [prepared statement] P if P was +** created by [sqlite3_prepare_v2()], [sqlite3_prepare_v3()], +** [sqlite3_prepare16_v2()], or [sqlite3_prepare16_v3()]. +** ^The sqlite3_expanded_sql(P) interface returns a pointer to a UTF-8 +** string containing the SQL text of prepared statement P with +** [bound parameters] expanded. +** ^The sqlite3_normalized_sql(P) interface returns a pointer to a UTF-8 +** string containing the normalized SQL text of prepared statement P. The +** semantics used to normalize a SQL statement are unspecified and subject +** to change. At a minimum, literal values will be replaced with suitable +** placeholders. +** +** ^(For example, if a prepared statement is created using the SQL +** text "SELECT $abc,:xyz" and if parameter $abc is bound to integer 2345 +** and parameter :xyz is unbound, then sqlite3_sql() will return +** the original string, "SELECT $abc,:xyz" but sqlite3_expanded_sql() +** will return "SELECT 2345,NULL".)^ +** +** ^The sqlite3_expanded_sql() interface returns NULL if insufficient memory +** is available to hold the result, or if the result would exceed the +** the maximum string length determined by the [SQLITE_LIMIT_LENGTH]. +** +** ^The [SQLITE_TRACE_SIZE_LIMIT] compile-time option limits the size of +** bound parameter expansions. ^The [SQLITE_OMIT_TRACE] compile-time +** option causes sqlite3_expanded_sql() to always return NULL. +** +** ^The strings returned by sqlite3_sql(P) and sqlite3_normalized_sql(P) +** are managed by SQLite and are automatically freed when the prepared +** statement is finalized. +** ^The string returned by sqlite3_expanded_sql(P), on the other hand, +** is obtained from [sqlite3_malloc()] and must be freed by the application +** by passing it to [sqlite3_free()]. +** +** ^The sqlite3_normalized_sql() interface is only available if +** the [SQLITE_ENABLE_NORMALIZE] compile-time option is defined. +*/ +SQLITE_API const char *sqlite3_sql(sqlite3_stmt *pStmt); +SQLITE_API char *sqlite3_expanded_sql(sqlite3_stmt *pStmt); +#ifdef SQLITE_ENABLE_NORMALIZE +SQLITE_API const char *sqlite3_normalized_sql(sqlite3_stmt *pStmt); +#endif + +/* +** CAPI3REF: Determine If An SQL Statement Writes The Database +** METHOD: sqlite3_stmt +** +** ^The sqlite3_stmt_readonly(X) interface returns true (non-zero) if +** and only if the [prepared statement] X makes no direct changes to +** the content of the database file. +** +** Note that [application-defined SQL functions] or +** [virtual tables] might change the database indirectly as a side effect. +** ^(For example, if an application defines a function "eval()" that +** calls [sqlite3_exec()], then the following SQL statement would +** change the database file through side-effects: +** +**

    +**    SELECT eval('DELETE FROM t1') FROM t2;
    +** 
    +** +** But because the [SELECT] statement does not change the database file +** directly, sqlite3_stmt_readonly() would still return true.)^ +** +** ^Transaction control statements such as [BEGIN], [COMMIT], [ROLLBACK], +** [SAVEPOINT], and [RELEASE] cause sqlite3_stmt_readonly() to return true, +** since the statements themselves do not actually modify the database but +** rather they control the timing of when other statements modify the +** database. ^The [ATTACH] and [DETACH] statements also cause +** sqlite3_stmt_readonly() to return true since, while those statements +** change the configuration of a database connection, they do not make +** changes to the content of the database files on disk. +** ^The sqlite3_stmt_readonly() interface returns true for [BEGIN] since +** [BEGIN] merely sets internal flags, but the [BEGIN|BEGIN IMMEDIATE] and +** [BEGIN|BEGIN EXCLUSIVE] commands do touch the database and so +** sqlite3_stmt_readonly() returns false for those commands. +** +** ^This routine returns false if there is any possibility that the +** statement might change the database file. ^A false return does +** not guarantee that the statement will change the database file. +** ^For example, an UPDATE statement might have a WHERE clause that +** makes it a no-op, but the sqlite3_stmt_readonly() result would still +** be false. ^Similarly, a CREATE TABLE IF NOT EXISTS statement is a +** read-only no-op if the table already exists, but +** sqlite3_stmt_readonly() still returns false for such a statement. +** +** ^If prepared statement X is an [EXPLAIN] or [EXPLAIN QUERY PLAN] +** statement, then sqlite3_stmt_readonly(X) returns the same value as +** if the EXPLAIN or EXPLAIN QUERY PLAN prefix were omitted. +*/ +SQLITE_API int sqlite3_stmt_readonly(sqlite3_stmt *pStmt); + +/* +** CAPI3REF: Query The EXPLAIN Setting For A Prepared Statement +** METHOD: sqlite3_stmt +** +** ^The sqlite3_stmt_isexplain(S) interface returns 1 if the +** prepared statement S is an EXPLAIN statement, or 2 if the +** statement S is an EXPLAIN QUERY PLAN. +** ^The sqlite3_stmt_isexplain(S) interface returns 0 if S is +** an ordinary statement or a NULL pointer. +*/ +SQLITE_API int sqlite3_stmt_isexplain(sqlite3_stmt *pStmt); + +/* +** CAPI3REF: Determine If A Prepared Statement Has Been Reset +** METHOD: sqlite3_stmt +** +** ^The sqlite3_stmt_busy(S) interface returns true (non-zero) if the +** [prepared statement] S has been stepped at least once using +** [sqlite3_step(S)] but has neither run to completion (returned +** [SQLITE_DONE] from [sqlite3_step(S)]) nor +** been reset using [sqlite3_reset(S)]. ^The sqlite3_stmt_busy(S) +** interface returns false if S is a NULL pointer. If S is not a +** NULL pointer and is not a pointer to a valid [prepared statement] +** object, then the behavior is undefined and probably undesirable. +** +** This interface can be used in combination [sqlite3_next_stmt()] +** to locate all prepared statements associated with a database +** connection that are in need of being reset. This can be used, +** for example, in diagnostic routines to search for prepared +** statements that are holding a transaction open. +*/ +SQLITE_API int sqlite3_stmt_busy(sqlite3_stmt*); + +/* +** CAPI3REF: Dynamically Typed Value Object +** KEYWORDS: {protected sqlite3_value} {unprotected sqlite3_value} +** +** SQLite uses the sqlite3_value object to represent all values +** that can be stored in a database table. SQLite uses dynamic typing +** for the values it stores. ^Values stored in sqlite3_value objects +** can be integers, floating point values, strings, BLOBs, or NULL. +** +** An sqlite3_value object may be either "protected" or "unprotected". +** Some interfaces require a protected sqlite3_value. Other interfaces +** will accept either a protected or an unprotected sqlite3_value. +** Every interface that accepts sqlite3_value arguments specifies +** whether or not it requires a protected sqlite3_value. The +** [sqlite3_value_dup()] interface can be used to construct a new +** protected sqlite3_value from an unprotected sqlite3_value. +** +** The terms "protected" and "unprotected" refer to whether or not +** a mutex is held. An internal mutex is held for a protected +** sqlite3_value object but no mutex is held for an unprotected +** sqlite3_value object. If SQLite is compiled to be single-threaded +** (with [SQLITE_THREADSAFE=0] and with [sqlite3_threadsafe()] returning 0) +** or if SQLite is run in one of reduced mutex modes +** [SQLITE_CONFIG_SINGLETHREAD] or [SQLITE_CONFIG_MULTITHREAD] +** then there is no distinction between protected and unprotected +** sqlite3_value objects and they can be used interchangeably. However, +** for maximum code portability it is recommended that applications +** still make the distinction between protected and unprotected +** sqlite3_value objects even when not strictly required. +** +** ^The sqlite3_value objects that are passed as parameters into the +** implementation of [application-defined SQL functions] are protected. +** ^The sqlite3_value objects returned by [sqlite3_vtab_rhs_value()] +** are protected. +** ^The sqlite3_value object returned by +** [sqlite3_column_value()] is unprotected. +** Unprotected sqlite3_value objects may only be used as arguments +** to [sqlite3_result_value()], [sqlite3_bind_value()], and +** [sqlite3_value_dup()]. +** The [sqlite3_value_blob | sqlite3_value_type()] family of +** interfaces require protected sqlite3_value objects. +*/ +typedef struct sqlite3_value sqlite3_value; + +/* +** CAPI3REF: SQL Function Context Object +** +** The context in which an SQL function executes is stored in an +** sqlite3_context object. ^A pointer to an sqlite3_context object +** is always first parameter to [application-defined SQL functions]. +** The application-defined SQL function implementation will pass this +** pointer through into calls to [sqlite3_result_int | sqlite3_result()], +** [sqlite3_aggregate_context()], [sqlite3_user_data()], +** [sqlite3_context_db_handle()], [sqlite3_get_auxdata()], +** and/or [sqlite3_set_auxdata()]. +*/ +typedef struct sqlite3_context sqlite3_context; + +/* +** CAPI3REF: Binding Values To Prepared Statements +** KEYWORDS: {host parameter} {host parameters} {host parameter name} +** KEYWORDS: {SQL parameter} {SQL parameters} {parameter binding} +** METHOD: sqlite3_stmt +** +** ^(In the SQL statement text input to [sqlite3_prepare_v2()] and its variants, +** literals may be replaced by a [parameter] that matches one of following +** templates: +** +**
      +**
    • ? +**
    • ?NNN +**
    • :VVV +**
    • @VVV +**
    • $VVV +**
    +** +** In the templates above, NNN represents an integer literal, +** and VVV represents an alphanumeric identifier.)^ ^The values of these +** parameters (also called "host parameter names" or "SQL parameters") +** can be set using the sqlite3_bind_*() routines defined here. +** +** ^The first argument to the sqlite3_bind_*() routines is always +** a pointer to the [sqlite3_stmt] object returned from +** [sqlite3_prepare_v2()] or its variants. +** +** ^The second argument is the index of the SQL parameter to be set. +** ^The leftmost SQL parameter has an index of 1. ^When the same named +** SQL parameter is used more than once, second and subsequent +** occurrences have the same index as the first occurrence. +** ^The index for named parameters can be looked up using the +** [sqlite3_bind_parameter_index()] API if desired. ^The index +** for "?NNN" parameters is the value of NNN. +** ^The NNN value must be between 1 and the [sqlite3_limit()] +** parameter [SQLITE_LIMIT_VARIABLE_NUMBER] (default value: 32766). +** +** ^The third argument is the value to bind to the parameter. +** ^If the third parameter to sqlite3_bind_text() or sqlite3_bind_text16() +** or sqlite3_bind_blob() is a NULL pointer then the fourth parameter +** is ignored and the end result is the same as sqlite3_bind_null(). +** ^If the third parameter to sqlite3_bind_text() is not NULL, then +** it should be a pointer to well-formed UTF8 text. +** ^If the third parameter to sqlite3_bind_text16() is not NULL, then +** it should be a pointer to well-formed UTF16 text. +** ^If the third parameter to sqlite3_bind_text64() is not NULL, then +** it should be a pointer to a well-formed unicode string that is +** either UTF8 if the sixth parameter is SQLITE_UTF8, or UTF16 +** otherwise. +** +** [[byte-order determination rules]] ^The byte-order of +** UTF16 input text is determined by the byte-order mark (BOM, U+FEFF) +** found in first character, which is removed, or in the absence of a BOM +** the byte order is the native byte order of the host +** machine for sqlite3_bind_text16() or the byte order specified in +** the 6th parameter for sqlite3_bind_text64().)^ +** ^If UTF16 input text contains invalid unicode +** characters, then SQLite might change those invalid characters +** into the unicode replacement character: U+FFFD. +** +** ^(In those routines that have a fourth argument, its value is the +** number of bytes in the parameter. To be clear: the value is the +** number of bytes in the value, not the number of characters.)^ +** ^If the fourth parameter to sqlite3_bind_text() or sqlite3_bind_text16() +** is negative, then the length of the string is +** the number of bytes up to the first zero terminator. +** If the fourth parameter to sqlite3_bind_blob() is negative, then +** the behavior is undefined. +** If a non-negative fourth parameter is provided to sqlite3_bind_text() +** or sqlite3_bind_text16() or sqlite3_bind_text64() then +** that parameter must be the byte offset +** where the NUL terminator would occur assuming the string were NUL +** terminated. If any NUL characters occurs at byte offsets less than +** the value of the fourth parameter then the resulting string value will +** contain embedded NULs. The result of expressions involving strings +** with embedded NULs is undefined. +** +** ^The fifth argument to the BLOB and string binding interfaces controls +** or indicates the lifetime of the object referenced by the third parameter. +** These three options exist: +** ^ (1) A destructor to dispose of the BLOB or string after SQLite has finished +** with it may be passed. ^It is called to dispose of the BLOB or string even +** if the call to the bind API fails, except the destructor is not called if +** the third parameter is a NULL pointer or the fourth parameter is negative. +** ^ (2) The special constant, [SQLITE_STATIC], may be passsed to indicate that +** the application remains responsible for disposing of the object. ^In this +** case, the object and the provided pointer to it must remain valid until +** either the prepared statement is finalized or the same SQL parameter is +** bound to something else, whichever occurs sooner. +** ^ (3) The constant, [SQLITE_TRANSIENT], may be passed to indicate that the +** object is to be copied prior to the return from sqlite3_bind_*(). ^The +** object and pointer to it must remain valid until then. ^SQLite will then +** manage the lifetime of its private copy. +** +** ^The sixth argument to sqlite3_bind_text64() must be one of +** [SQLITE_UTF8], [SQLITE_UTF16], [SQLITE_UTF16BE], or [SQLITE_UTF16LE] +** to specify the encoding of the text in the third parameter. If +** the sixth argument to sqlite3_bind_text64() is not one of the +** allowed values shown above, or if the text encoding is different +** from the encoding specified by the sixth parameter, then the behavior +** is undefined. +** +** ^The sqlite3_bind_zeroblob() routine binds a BLOB of length N that +** is filled with zeroes. ^A zeroblob uses a fixed amount of memory +** (just an integer to hold its size) while it is being processed. +** Zeroblobs are intended to serve as placeholders for BLOBs whose +** content is later written using +** [sqlite3_blob_open | incremental BLOB I/O] routines. +** ^A negative value for the zeroblob results in a zero-length BLOB. +** +** ^The sqlite3_bind_pointer(S,I,P,T,D) routine causes the I-th parameter in +** [prepared statement] S to have an SQL value of NULL, but to also be +** associated with the pointer P of type T. ^D is either a NULL pointer or +** a pointer to a destructor function for P. ^SQLite will invoke the +** destructor D with a single argument of P when it is finished using +** P. The T parameter should be a static string, preferably a string +** literal. The sqlite3_bind_pointer() routine is part of the +** [pointer passing interface] added for SQLite 3.20.0. +** +** ^If any of the sqlite3_bind_*() routines are called with a NULL pointer +** for the [prepared statement] or with a prepared statement for which +** [sqlite3_step()] has been called more recently than [sqlite3_reset()], +** then the call will return [SQLITE_MISUSE]. If any sqlite3_bind_() +** routine is passed a [prepared statement] that has been finalized, the +** result is undefined and probably harmful. +** +** ^Bindings are not cleared by the [sqlite3_reset()] routine. +** ^Unbound parameters are interpreted as NULL. +** +** ^The sqlite3_bind_* routines return [SQLITE_OK] on success or an +** [error code] if anything goes wrong. +** ^[SQLITE_TOOBIG] might be returned if the size of a string or BLOB +** exceeds limits imposed by [sqlite3_limit]([SQLITE_LIMIT_LENGTH]) or +** [SQLITE_MAX_LENGTH]. +** ^[SQLITE_RANGE] is returned if the parameter +** index is out of range. ^[SQLITE_NOMEM] is returned if malloc() fails. +** +** See also: [sqlite3_bind_parameter_count()], +** [sqlite3_bind_parameter_name()], and [sqlite3_bind_parameter_index()]. +*/ +SQLITE_API int sqlite3_bind_blob(sqlite3_stmt*, int, const void*, int n, void(*)(void*)); +SQLITE_API int sqlite3_bind_blob64(sqlite3_stmt*, int, const void*, sqlite3_uint64, + void(*)(void*)); +SQLITE_API int sqlite3_bind_double(sqlite3_stmt*, int, double); +SQLITE_API int sqlite3_bind_int(sqlite3_stmt*, int, int); +SQLITE_API int sqlite3_bind_int64(sqlite3_stmt*, int, sqlite3_int64); +SQLITE_API int sqlite3_bind_null(sqlite3_stmt*, int); +SQLITE_API int sqlite3_bind_text(sqlite3_stmt*,int,const char*,int,void(*)(void*)); +SQLITE_API int sqlite3_bind_text16(sqlite3_stmt*, int, const void*, int, void(*)(void*)); +SQLITE_API int sqlite3_bind_text64(sqlite3_stmt*, int, const char*, sqlite3_uint64, + void(*)(void*), unsigned char encoding); +SQLITE_API int sqlite3_bind_value(sqlite3_stmt*, int, const sqlite3_value*); +SQLITE_API int sqlite3_bind_pointer(sqlite3_stmt*, int, void*, const char*,void(*)(void*)); +SQLITE_API int sqlite3_bind_zeroblob(sqlite3_stmt*, int, int n); +SQLITE_API int sqlite3_bind_zeroblob64(sqlite3_stmt*, int, sqlite3_uint64); + +/* +** CAPI3REF: Number Of SQL Parameters +** METHOD: sqlite3_stmt +** +** ^This routine can be used to find the number of [SQL parameters] +** in a [prepared statement]. SQL parameters are tokens of the +** form "?", "?NNN", ":AAA", "$AAA", or "@AAA" that serve as +** placeholders for values that are [sqlite3_bind_blob | bound] +** to the parameters at a later time. +** +** ^(This routine actually returns the index of the largest (rightmost) +** parameter. For all forms except ?NNN, this will correspond to the +** number of unique parameters. If parameters of the ?NNN form are used, +** there may be gaps in the list.)^ +** +** See also: [sqlite3_bind_blob|sqlite3_bind()], +** [sqlite3_bind_parameter_name()], and +** [sqlite3_bind_parameter_index()]. +*/ +SQLITE_API int sqlite3_bind_parameter_count(sqlite3_stmt*); + +/* +** CAPI3REF: Name Of A Host Parameter +** METHOD: sqlite3_stmt +** +** ^The sqlite3_bind_parameter_name(P,N) interface returns +** the name of the N-th [SQL parameter] in the [prepared statement] P. +** ^(SQL parameters of the form "?NNN" or ":AAA" or "@AAA" or "$AAA" +** have a name which is the string "?NNN" or ":AAA" or "@AAA" or "$AAA" +** respectively. +** In other words, the initial ":" or "$" or "@" or "?" +** is included as part of the name.)^ +** ^Parameters of the form "?" without a following integer have no name +** and are referred to as "nameless" or "anonymous parameters". +** +** ^The first host parameter has an index of 1, not 0. +** +** ^If the value N is out of range or if the N-th parameter is +** nameless, then NULL is returned. ^The returned string is +** always in UTF-8 encoding even if the named parameter was +** originally specified as UTF-16 in [sqlite3_prepare16()], +** [sqlite3_prepare16_v2()], or [sqlite3_prepare16_v3()]. +** +** See also: [sqlite3_bind_blob|sqlite3_bind()], +** [sqlite3_bind_parameter_count()], and +** [sqlite3_bind_parameter_index()]. +*/ +SQLITE_API const char *sqlite3_bind_parameter_name(sqlite3_stmt*, int); + +/* +** CAPI3REF: Index Of A Parameter With A Given Name +** METHOD: sqlite3_stmt +** +** ^Return the index of an SQL parameter given its name. ^The +** index value returned is suitable for use as the second +** parameter to [sqlite3_bind_blob|sqlite3_bind()]. ^A zero +** is returned if no matching parameter is found. ^The parameter +** name must be given in UTF-8 even if the original statement +** was prepared from UTF-16 text using [sqlite3_prepare16_v2()] or +** [sqlite3_prepare16_v3()]. +** +** See also: [sqlite3_bind_blob|sqlite3_bind()], +** [sqlite3_bind_parameter_count()], and +** [sqlite3_bind_parameter_name()]. +*/ +SQLITE_API int sqlite3_bind_parameter_index(sqlite3_stmt*, const char *zName); + +/* +** CAPI3REF: Reset All Bindings On A Prepared Statement +** METHOD: sqlite3_stmt +** +** ^Contrary to the intuition of many, [sqlite3_reset()] does not reset +** the [sqlite3_bind_blob | bindings] on a [prepared statement]. +** ^Use this routine to reset all host parameters to NULL. +*/ +SQLITE_API int sqlite3_clear_bindings(sqlite3_stmt*); + +/* +** CAPI3REF: Number Of Columns In A Result Set +** METHOD: sqlite3_stmt +** +** ^Return the number of columns in the result set returned by the +** [prepared statement]. ^If this routine returns 0, that means the +** [prepared statement] returns no data (for example an [UPDATE]). +** ^However, just because this routine returns a positive number does not +** mean that one or more rows of data will be returned. ^A SELECT statement +** will always have a positive sqlite3_column_count() but depending on the +** WHERE clause constraints and the table content, it might return no rows. +** +** See also: [sqlite3_data_count()] +*/ +SQLITE_API int sqlite3_column_count(sqlite3_stmt *pStmt); + +/* +** CAPI3REF: Column Names In A Result Set +** METHOD: sqlite3_stmt +** +** ^These routines return the name assigned to a particular column +** in the result set of a [SELECT] statement. ^The sqlite3_column_name() +** interface returns a pointer to a zero-terminated UTF-8 string +** and sqlite3_column_name16() returns a pointer to a zero-terminated +** UTF-16 string. ^The first parameter is the [prepared statement] +** that implements the [SELECT] statement. ^The second parameter is the +** column number. ^The leftmost column is number 0. +** +** ^The returned string pointer is valid until either the [prepared statement] +** is destroyed by [sqlite3_finalize()] or until the statement is automatically +** reprepared by the first call to [sqlite3_step()] for a particular run +** or until the next call to +** sqlite3_column_name() or sqlite3_column_name16() on the same column. +** +** ^If sqlite3_malloc() fails during the processing of either routine +** (for example during a conversion from UTF-8 to UTF-16) then a +** NULL pointer is returned. +** +** ^The name of a result column is the value of the "AS" clause for +** that column, if there is an AS clause. If there is no AS clause +** then the name of the column is unspecified and may change from +** one release of SQLite to the next. +*/ +SQLITE_API const char *sqlite3_column_name(sqlite3_stmt*, int N); +SQLITE_API const void *sqlite3_column_name16(sqlite3_stmt*, int N); + +/* +** CAPI3REF: Source Of Data In A Query Result +** METHOD: sqlite3_stmt +** +** ^These routines provide a means to determine the database, table, and +** table column that is the origin of a particular result column in +** [SELECT] statement. +** ^The name of the database or table or column can be returned as +** either a UTF-8 or UTF-16 string. ^The _database_ routines return +** the database name, the _table_ routines return the table name, and +** the origin_ routines return the column name. +** ^The returned string is valid until the [prepared statement] is destroyed +** using [sqlite3_finalize()] or until the statement is automatically +** reprepared by the first call to [sqlite3_step()] for a particular run +** or until the same information is requested +** again in a different encoding. +** +** ^The names returned are the original un-aliased names of the +** database, table, and column. +** +** ^The first argument to these interfaces is a [prepared statement]. +** ^These functions return information about the Nth result column returned by +** the statement, where N is the second function argument. +** ^The left-most column is column 0 for these routines. +** +** ^If the Nth column returned by the statement is an expression or +** subquery and is not a column value, then all of these functions return +** NULL. ^These routines might also return NULL if a memory allocation error +** occurs. ^Otherwise, they return the name of the attached database, table, +** or column that query result column was extracted from. +** +** ^As with all other SQLite APIs, those whose names end with "16" return +** UTF-16 encoded strings and the other functions return UTF-8. +** +** ^These APIs are only available if the library was compiled with the +** [SQLITE_ENABLE_COLUMN_METADATA] C-preprocessor symbol. +** +** If two or more threads call one or more +** [sqlite3_column_database_name | column metadata interfaces] +** for the same [prepared statement] and result column +** at the same time then the results are undefined. +*/ +SQLITE_API const char *sqlite3_column_database_name(sqlite3_stmt*,int); +SQLITE_API const void *sqlite3_column_database_name16(sqlite3_stmt*,int); +SQLITE_API const char *sqlite3_column_table_name(sqlite3_stmt*,int); +SQLITE_API const void *sqlite3_column_table_name16(sqlite3_stmt*,int); +SQLITE_API const char *sqlite3_column_origin_name(sqlite3_stmt*,int); +SQLITE_API const void *sqlite3_column_origin_name16(sqlite3_stmt*,int); + +/* +** CAPI3REF: Declared Datatype Of A Query Result +** METHOD: sqlite3_stmt +** +** ^(The first parameter is a [prepared statement]. +** If this statement is a [SELECT] statement and the Nth column of the +** returned result set of that [SELECT] is a table column (not an +** expression or subquery) then the declared type of the table +** column is returned.)^ ^If the Nth column of the result set is an +** expression or subquery, then a NULL pointer is returned. +** ^The returned string is always UTF-8 encoded. +** +** ^(For example, given the database schema: +** +** CREATE TABLE t1(c1 VARIANT); +** +** and the following statement to be compiled: +** +** SELECT c1 + 1, c1 FROM t1; +** +** this routine would return the string "VARIANT" for the second result +** column (i==1), and a NULL pointer for the first result column (i==0).)^ +** +** ^SQLite uses dynamic run-time typing. ^So just because a column +** is declared to contain a particular type does not mean that the +** data stored in that column is of the declared type. SQLite is +** strongly typed, but the typing is dynamic not static. ^Type +** is associated with individual values, not with the containers +** used to hold those values. +*/ +SQLITE_API const char *sqlite3_column_decltype(sqlite3_stmt*,int); +SQLITE_API const void *sqlite3_column_decltype16(sqlite3_stmt*,int); + +/* +** CAPI3REF: Evaluate An SQL Statement +** METHOD: sqlite3_stmt +** +** After a [prepared statement] has been prepared using any of +** [sqlite3_prepare_v2()], [sqlite3_prepare_v3()], [sqlite3_prepare16_v2()], +** or [sqlite3_prepare16_v3()] or one of the legacy +** interfaces [sqlite3_prepare()] or [sqlite3_prepare16()], this function +** must be called one or more times to evaluate the statement. +** +** The details of the behavior of the sqlite3_step() interface depend +** on whether the statement was prepared using the newer "vX" interfaces +** [sqlite3_prepare_v3()], [sqlite3_prepare_v2()], [sqlite3_prepare16_v3()], +** [sqlite3_prepare16_v2()] or the older legacy +** interfaces [sqlite3_prepare()] and [sqlite3_prepare16()]. The use of the +** new "vX" interface is recommended for new applications but the legacy +** interface will continue to be supported. +** +** ^In the legacy interface, the return value will be either [SQLITE_BUSY], +** [SQLITE_DONE], [SQLITE_ROW], [SQLITE_ERROR], or [SQLITE_MISUSE]. +** ^With the "v2" interface, any of the other [result codes] or +** [extended result codes] might be returned as well. +** +** ^[SQLITE_BUSY] means that the database engine was unable to acquire the +** database locks it needs to do its job. ^If the statement is a [COMMIT] +** or occurs outside of an explicit transaction, then you can retry the +** statement. If the statement is not a [COMMIT] and occurs within an +** explicit transaction then you should rollback the transaction before +** continuing. +** +** ^[SQLITE_DONE] means that the statement has finished executing +** successfully. sqlite3_step() should not be called again on this virtual +** machine without first calling [sqlite3_reset()] to reset the virtual +** machine back to its initial state. +** +** ^If the SQL statement being executed returns any data, then [SQLITE_ROW] +** is returned each time a new row of data is ready for processing by the +** caller. The values may be accessed using the [column access functions]. +** sqlite3_step() is called again to retrieve the next row of data. +** +** ^[SQLITE_ERROR] means that a run-time error (such as a constraint +** violation) has occurred. sqlite3_step() should not be called again on +** the VM. More information may be found by calling [sqlite3_errmsg()]. +** ^With the legacy interface, a more specific error code (for example, +** [SQLITE_INTERRUPT], [SQLITE_SCHEMA], [SQLITE_CORRUPT], and so forth) +** can be obtained by calling [sqlite3_reset()] on the +** [prepared statement]. ^In the "v2" interface, +** the more specific error code is returned directly by sqlite3_step(). +** +** [SQLITE_MISUSE] means that the this routine was called inappropriately. +** Perhaps it was called on a [prepared statement] that has +** already been [sqlite3_finalize | finalized] or on one that had +** previously returned [SQLITE_ERROR] or [SQLITE_DONE]. Or it could +** be the case that the same database connection is being used by two or +** more threads at the same moment in time. +** +** For all versions of SQLite up to and including 3.6.23.1, a call to +** [sqlite3_reset()] was required after sqlite3_step() returned anything +** other than [SQLITE_ROW] before any subsequent invocation of +** sqlite3_step(). Failure to reset the prepared statement using +** [sqlite3_reset()] would result in an [SQLITE_MISUSE] return from +** sqlite3_step(). But after [version 3.6.23.1] ([dateof:3.6.23.1], +** sqlite3_step() began +** calling [sqlite3_reset()] automatically in this circumstance rather +** than returning [SQLITE_MISUSE]. This is not considered a compatibility +** break because any application that ever receives an SQLITE_MISUSE error +** is broken by definition. The [SQLITE_OMIT_AUTORESET] compile-time option +** can be used to restore the legacy behavior. +** +** Goofy Interface Alert: In the legacy interface, the sqlite3_step() +** API always returns a generic error code, [SQLITE_ERROR], following any +** error other than [SQLITE_BUSY] and [SQLITE_MISUSE]. You must call +** [sqlite3_reset()] or [sqlite3_finalize()] in order to find one of the +** specific [error codes] that better describes the error. +** We admit that this is a goofy design. The problem has been fixed +** with the "v2" interface. If you prepare all of your SQL statements +** using [sqlite3_prepare_v3()] or [sqlite3_prepare_v2()] +** or [sqlite3_prepare16_v2()] or [sqlite3_prepare16_v3()] instead +** of the legacy [sqlite3_prepare()] and [sqlite3_prepare16()] interfaces, +** then the more specific [error codes] are returned directly +** by sqlite3_step(). The use of the "vX" interfaces is recommended. +*/ +SQLITE_API int sqlite3_step(sqlite3_stmt*); + +/* +** CAPI3REF: Number of columns in a result set +** METHOD: sqlite3_stmt +** +** ^The sqlite3_data_count(P) interface returns the number of columns in the +** current row of the result set of [prepared statement] P. +** ^If prepared statement P does not have results ready to return +** (via calls to the [sqlite3_column_int | sqlite3_column()] family of +** interfaces) then sqlite3_data_count(P) returns 0. +** ^The sqlite3_data_count(P) routine also returns 0 if P is a NULL pointer. +** ^The sqlite3_data_count(P) routine returns 0 if the previous call to +** [sqlite3_step](P) returned [SQLITE_DONE]. ^The sqlite3_data_count(P) +** will return non-zero if previous call to [sqlite3_step](P) returned +** [SQLITE_ROW], except in the case of the [PRAGMA incremental_vacuum] +** where it always returns zero since each step of that multi-step +** pragma returns 0 columns of data. +** +** See also: [sqlite3_column_count()] +*/ +SQLITE_API int sqlite3_data_count(sqlite3_stmt *pStmt); + +/* +** CAPI3REF: Fundamental Datatypes +** KEYWORDS: SQLITE_TEXT +** +** ^(Every value in SQLite has one of five fundamental datatypes: +** +**
      +**
    • 64-bit signed integer +**
    • 64-bit IEEE floating point number +**
    • string +**
    • BLOB +**
    • NULL +**
    )^ +** +** These constants are codes for each of those types. +** +** Note that the SQLITE_TEXT constant was also used in SQLite version 2 +** for a completely different meaning. Software that links against both +** SQLite version 2 and SQLite version 3 should use SQLITE3_TEXT, not +** SQLITE_TEXT. +*/ +#define SQLITE_INTEGER 1 +#define SQLITE_FLOAT 2 +#define SQLITE_BLOB 4 +#define SQLITE_NULL 5 +#ifdef SQLITE_TEXT +# undef SQLITE_TEXT +#else +# define SQLITE_TEXT 3 +#endif +#define SQLITE3_TEXT 3 + +/* +** CAPI3REF: Result Values From A Query +** KEYWORDS: {column access functions} +** METHOD: sqlite3_stmt +** +** Summary: +**
    +**
    sqlite3_column_blobBLOB result +**
    sqlite3_column_doubleREAL result +**
    sqlite3_column_int32-bit INTEGER result +**
    sqlite3_column_int6464-bit INTEGER result +**
    sqlite3_column_textUTF-8 TEXT result +**
    sqlite3_column_text16UTF-16 TEXT result +**
    sqlite3_column_valueThe result as an +** [sqlite3_value|unprotected sqlite3_value] object. +**
        +**
    sqlite3_column_bytesSize of a BLOB +** or a UTF-8 TEXT result in bytes +**
    sqlite3_column_bytes16   +** →  Size of UTF-16 +** TEXT in bytes +**
    sqlite3_column_typeDefault +** datatype of the result +**
    +** +** Details: +** +** ^These routines return information about a single column of the current +** result row of a query. ^In every case the first argument is a pointer +** to the [prepared statement] that is being evaluated (the [sqlite3_stmt*] +** that was returned from [sqlite3_prepare_v2()] or one of its variants) +** and the second argument is the index of the column for which information +** should be returned. ^The leftmost column of the result set has the index 0. +** ^The number of columns in the result can be determined using +** [sqlite3_column_count()]. +** +** If the SQL statement does not currently point to a valid row, or if the +** column index is out of range, the result is undefined. +** These routines may only be called when the most recent call to +** [sqlite3_step()] has returned [SQLITE_ROW] and neither +** [sqlite3_reset()] nor [sqlite3_finalize()] have been called subsequently. +** If any of these routines are called after [sqlite3_reset()] or +** [sqlite3_finalize()] or after [sqlite3_step()] has returned +** something other than [SQLITE_ROW], the results are undefined. +** If [sqlite3_step()] or [sqlite3_reset()] or [sqlite3_finalize()] +** are called from a different thread while any of these routines +** are pending, then the results are undefined. +** +** The first six interfaces (_blob, _double, _int, _int64, _text, and _text16) +** each return the value of a result column in a specific data format. If +** the result column is not initially in the requested format (for example, +** if the query returns an integer but the sqlite3_column_text() interface +** is used to extract the value) then an automatic type conversion is performed. +** +** ^The sqlite3_column_type() routine returns the +** [SQLITE_INTEGER | datatype code] for the initial data type +** of the result column. ^The returned value is one of [SQLITE_INTEGER], +** [SQLITE_FLOAT], [SQLITE_TEXT], [SQLITE_BLOB], or [SQLITE_NULL]. +** The return value of sqlite3_column_type() can be used to decide which +** of the first six interface should be used to extract the column value. +** The value returned by sqlite3_column_type() is only meaningful if no +** automatic type conversions have occurred for the value in question. +** After a type conversion, the result of calling sqlite3_column_type() +** is undefined, though harmless. Future +** versions of SQLite may change the behavior of sqlite3_column_type() +** following a type conversion. +** +** If the result is a BLOB or a TEXT string, then the sqlite3_column_bytes() +** or sqlite3_column_bytes16() interfaces can be used to determine the size +** of that BLOB or string. +** +** ^If the result is a BLOB or UTF-8 string then the sqlite3_column_bytes() +** routine returns the number of bytes in that BLOB or string. +** ^If the result is a UTF-16 string, then sqlite3_column_bytes() converts +** the string to UTF-8 and then returns the number of bytes. +** ^If the result is a numeric value then sqlite3_column_bytes() uses +** [sqlite3_snprintf()] to convert that value to a UTF-8 string and returns +** the number of bytes in that string. +** ^If the result is NULL, then sqlite3_column_bytes() returns zero. +** +** ^If the result is a BLOB or UTF-16 string then the sqlite3_column_bytes16() +** routine returns the number of bytes in that BLOB or string. +** ^If the result is a UTF-8 string, then sqlite3_column_bytes16() converts +** the string to UTF-16 and then returns the number of bytes. +** ^If the result is a numeric value then sqlite3_column_bytes16() uses +** [sqlite3_snprintf()] to convert that value to a UTF-16 string and returns +** the number of bytes in that string. +** ^If the result is NULL, then sqlite3_column_bytes16() returns zero. +** +** ^The values returned by [sqlite3_column_bytes()] and +** [sqlite3_column_bytes16()] do not include the zero terminators at the end +** of the string. ^For clarity: the values returned by +** [sqlite3_column_bytes()] and [sqlite3_column_bytes16()] are the number of +** bytes in the string, not the number of characters. +** +** ^Strings returned by sqlite3_column_text() and sqlite3_column_text16(), +** even empty strings, are always zero-terminated. ^The return +** value from sqlite3_column_blob() for a zero-length BLOB is a NULL pointer. +** +** ^Strings returned by sqlite3_column_text16() always have the endianness +** which is native to the platform, regardless of the text encoding set +** for the database. +** +** Warning: ^The object returned by [sqlite3_column_value()] is an +** [unprotected sqlite3_value] object. In a multithreaded environment, +** an unprotected sqlite3_value object may only be used safely with +** [sqlite3_bind_value()] and [sqlite3_result_value()]. +** If the [unprotected sqlite3_value] object returned by +** [sqlite3_column_value()] is used in any other way, including calls +** to routines like [sqlite3_value_int()], [sqlite3_value_text()], +** or [sqlite3_value_bytes()], the behavior is not threadsafe. +** Hence, the sqlite3_column_value() interface +** is normally only useful within the implementation of +** [application-defined SQL functions] or [virtual tables], not within +** top-level application code. +** +** These routines may attempt to convert the datatype of the result. +** ^For example, if the internal representation is FLOAT and a text result +** is requested, [sqlite3_snprintf()] is used internally to perform the +** conversion automatically. ^(The following table details the conversions +** that are applied: +** +**
    +** +**
    Internal
    Type
    Requested
    Type
    Conversion +** +**
    NULL INTEGER Result is 0 +**
    NULL FLOAT Result is 0.0 +**
    NULL TEXT Result is a NULL pointer +**
    NULL BLOB Result is a NULL pointer +**
    INTEGER FLOAT Convert from integer to float +**
    INTEGER TEXT ASCII rendering of the integer +**
    INTEGER BLOB Same as INTEGER->TEXT +**
    FLOAT INTEGER [CAST] to INTEGER +**
    FLOAT TEXT ASCII rendering of the float +**
    FLOAT BLOB [CAST] to BLOB +**
    TEXT INTEGER [CAST] to INTEGER +**
    TEXT FLOAT [CAST] to REAL +**
    TEXT BLOB No change +**
    BLOB INTEGER [CAST] to INTEGER +**
    BLOB FLOAT [CAST] to REAL +**
    BLOB TEXT [CAST] to TEXT, ensure zero terminator +**
    +**
    )^ +** +** Note that when type conversions occur, pointers returned by prior +** calls to sqlite3_column_blob(), sqlite3_column_text(), and/or +** sqlite3_column_text16() may be invalidated. +** Type conversions and pointer invalidations might occur +** in the following cases: +** +**
      +**
    • The initial content is a BLOB and sqlite3_column_text() or +** sqlite3_column_text16() is called. A zero-terminator might +** need to be added to the string.
    • +**
    • The initial content is UTF-8 text and sqlite3_column_bytes16() or +** sqlite3_column_text16() is called. The content must be converted +** to UTF-16.
    • +**
    • The initial content is UTF-16 text and sqlite3_column_bytes() or +** sqlite3_column_text() is called. The content must be converted +** to UTF-8.
    • +**
    +** +** ^Conversions between UTF-16be and UTF-16le are always done in place and do +** not invalidate a prior pointer, though of course the content of the buffer +** that the prior pointer references will have been modified. Other kinds +** of conversion are done in place when it is possible, but sometimes they +** are not possible and in those cases prior pointers are invalidated. +** +** The safest policy is to invoke these routines +** in one of the following ways: +** +**
      +**
    • sqlite3_column_text() followed by sqlite3_column_bytes()
    • +**
    • sqlite3_column_blob() followed by sqlite3_column_bytes()
    • +**
    • sqlite3_column_text16() followed by sqlite3_column_bytes16()
    • +**
    +** +** In other words, you should call sqlite3_column_text(), +** sqlite3_column_blob(), or sqlite3_column_text16() first to force the result +** into the desired format, then invoke sqlite3_column_bytes() or +** sqlite3_column_bytes16() to find the size of the result. Do not mix calls +** to sqlite3_column_text() or sqlite3_column_blob() with calls to +** sqlite3_column_bytes16(), and do not mix calls to sqlite3_column_text16() +** with calls to sqlite3_column_bytes(). +** +** ^The pointers returned are valid until a type conversion occurs as +** described above, or until [sqlite3_step()] or [sqlite3_reset()] or +** [sqlite3_finalize()] is called. ^The memory space used to hold strings +** and BLOBs is freed automatically. Do not pass the pointers returned +** from [sqlite3_column_blob()], [sqlite3_column_text()], etc. into +** [sqlite3_free()]. +** +** As long as the input parameters are correct, these routines will only +** fail if an out-of-memory error occurs during a format conversion. +** Only the following subset of interfaces are subject to out-of-memory +** errors: +** +**
      +**
    • sqlite3_column_blob() +**
    • sqlite3_column_text() +**
    • sqlite3_column_text16() +**
    • sqlite3_column_bytes() +**
    • sqlite3_column_bytes16() +**
    +** +** If an out-of-memory error occurs, then the return value from these +** routines is the same as if the column had contained an SQL NULL value. +** Valid SQL NULL returns can be distinguished from out-of-memory errors +** by invoking the [sqlite3_errcode()] immediately after the suspect +** return value is obtained and before any +** other SQLite interface is called on the same [database connection]. +*/ +SQLITE_API const void *sqlite3_column_blob(sqlite3_stmt*, int iCol); +SQLITE_API double sqlite3_column_double(sqlite3_stmt*, int iCol); +SQLITE_API int sqlite3_column_int(sqlite3_stmt*, int iCol); +SQLITE_API sqlite3_int64 sqlite3_column_int64(sqlite3_stmt*, int iCol); +SQLITE_API const unsigned char *sqlite3_column_text(sqlite3_stmt*, int iCol); +SQLITE_API const void *sqlite3_column_text16(sqlite3_stmt*, int iCol); +SQLITE_API sqlite3_value *sqlite3_column_value(sqlite3_stmt*, int iCol); +SQLITE_API int sqlite3_column_bytes(sqlite3_stmt*, int iCol); +SQLITE_API int sqlite3_column_bytes16(sqlite3_stmt*, int iCol); +SQLITE_API int sqlite3_column_type(sqlite3_stmt*, int iCol); + +/* +** CAPI3REF: Destroy A Prepared Statement Object +** DESTRUCTOR: sqlite3_stmt +** +** ^The sqlite3_finalize() function is called to delete a [prepared statement]. +** ^If the most recent evaluation of the statement encountered no errors +** or if the statement is never been evaluated, then sqlite3_finalize() returns +** SQLITE_OK. ^If the most recent evaluation of statement S failed, then +** sqlite3_finalize(S) returns the appropriate [error code] or +** [extended error code]. +** +** ^The sqlite3_finalize(S) routine can be called at any point during +** the life cycle of [prepared statement] S: +** before statement S is ever evaluated, after +** one or more calls to [sqlite3_reset()], or after any call +** to [sqlite3_step()] regardless of whether or not the statement has +** completed execution. +** +** ^Invoking sqlite3_finalize() on a NULL pointer is a harmless no-op. +** +** The application must finalize every [prepared statement] in order to avoid +** resource leaks. It is a grievous error for the application to try to use +** a prepared statement after it has been finalized. Any use of a prepared +** statement after it has been finalized can result in undefined and +** undesirable behavior such as segfaults and heap corruption. +*/ +SQLITE_API int sqlite3_finalize(sqlite3_stmt *pStmt); + +/* +** CAPI3REF: Reset A Prepared Statement Object +** METHOD: sqlite3_stmt +** +** The sqlite3_reset() function is called to reset a [prepared statement] +** object back to its initial state, ready to be re-executed. +** ^Any SQL statement variables that had values bound to them using +** the [sqlite3_bind_blob | sqlite3_bind_*() API] retain their values. +** Use [sqlite3_clear_bindings()] to reset the bindings. +** +** ^The [sqlite3_reset(S)] interface resets the [prepared statement] S +** back to the beginning of its program. +** +** ^If the most recent call to [sqlite3_step(S)] for the +** [prepared statement] S returned [SQLITE_ROW] or [SQLITE_DONE], +** or if [sqlite3_step(S)] has never before been called on S, +** then [sqlite3_reset(S)] returns [SQLITE_OK]. +** +** ^If the most recent call to [sqlite3_step(S)] for the +** [prepared statement] S indicated an error, then +** [sqlite3_reset(S)] returns an appropriate [error code]. +** +** ^The [sqlite3_reset(S)] interface does not change the values +** of any [sqlite3_bind_blob|bindings] on the [prepared statement] S. +*/ +SQLITE_API int sqlite3_reset(sqlite3_stmt *pStmt); + +/* +** CAPI3REF: Create Or Redefine SQL Functions +** KEYWORDS: {function creation routines} +** METHOD: sqlite3 +** +** ^These functions (collectively known as "function creation routines") +** are used to add SQL functions or aggregates or to redefine the behavior +** of existing SQL functions or aggregates. The only differences between +** the three "sqlite3_create_function*" routines are the text encoding +** expected for the second parameter (the name of the function being +** created) and the presence or absence of a destructor callback for +** the application data pointer. Function sqlite3_create_window_function() +** is similar, but allows the user to supply the extra callback functions +** needed by [aggregate window functions]. +** +** ^The first parameter is the [database connection] to which the SQL +** function is to be added. ^If an application uses more than one database +** connection then application-defined SQL functions must be added +** to each database connection separately. +** +** ^The second parameter is the name of the SQL function to be created or +** redefined. ^The length of the name is limited to 255 bytes in a UTF-8 +** representation, exclusive of the zero-terminator. ^Note that the name +** length limit is in UTF-8 bytes, not characters nor UTF-16 bytes. +** ^Any attempt to create a function with a longer name +** will result in [SQLITE_MISUSE] being returned. +** +** ^The third parameter (nArg) +** is the number of arguments that the SQL function or +** aggregate takes. ^If this parameter is -1, then the SQL function or +** aggregate may take any number of arguments between 0 and the limit +** set by [sqlite3_limit]([SQLITE_LIMIT_FUNCTION_ARG]). If the third +** parameter is less than -1 or greater than 127 then the behavior is +** undefined. +** +** ^The fourth parameter, eTextRep, specifies what +** [SQLITE_UTF8 | text encoding] this SQL function prefers for +** its parameters. The application should set this parameter to +** [SQLITE_UTF16LE] if the function implementation invokes +** [sqlite3_value_text16le()] on an input, or [SQLITE_UTF16BE] if the +** implementation invokes [sqlite3_value_text16be()] on an input, or +** [SQLITE_UTF16] if [sqlite3_value_text16()] is used, or [SQLITE_UTF8] +** otherwise. ^The same SQL function may be registered multiple times using +** different preferred text encodings, with different implementations for +** each encoding. +** ^When multiple implementations of the same function are available, SQLite +** will pick the one that involves the least amount of data conversion. +** +** ^The fourth parameter may optionally be ORed with [SQLITE_DETERMINISTIC] +** to signal that the function will always return the same result given +** the same inputs within a single SQL statement. Most SQL functions are +** deterministic. The built-in [random()] SQL function is an example of a +** function that is not deterministic. The SQLite query planner is able to +** perform additional optimizations on deterministic functions, so use +** of the [SQLITE_DETERMINISTIC] flag is recommended where possible. +** +** ^The fourth parameter may also optionally include the [SQLITE_DIRECTONLY] +** flag, which if present prevents the function from being invoked from +** within VIEWs, TRIGGERs, CHECK constraints, generated column expressions, +** index expressions, or the WHERE clause of partial indexes. +** +** For best security, the [SQLITE_DIRECTONLY] flag is recommended for +** all application-defined SQL functions that do not need to be +** used inside of triggers, view, CHECK constraints, or other elements of +** the database schema. This flags is especially recommended for SQL +** functions that have side effects or reveal internal application state. +** Without this flag, an attacker might be able to modify the schema of +** a database file to include invocations of the function with parameters +** chosen by the attacker, which the application will then execute when +** the database file is opened and read. +** +** ^(The fifth parameter is an arbitrary pointer. The implementation of the +** function can gain access to this pointer using [sqlite3_user_data()].)^ +** +** ^The sixth, seventh and eighth parameters passed to the three +** "sqlite3_create_function*" functions, xFunc, xStep and xFinal, are +** pointers to C-language functions that implement the SQL function or +** aggregate. ^A scalar SQL function requires an implementation of the xFunc +** callback only; NULL pointers must be passed as the xStep and xFinal +** parameters. ^An aggregate SQL function requires an implementation of xStep +** and xFinal and NULL pointer must be passed for xFunc. ^To delete an existing +** SQL function or aggregate, pass NULL pointers for all three function +** callbacks. +** +** ^The sixth, seventh, eighth and ninth parameters (xStep, xFinal, xValue +** and xInverse) passed to sqlite3_create_window_function are pointers to +** C-language callbacks that implement the new function. xStep and xFinal +** must both be non-NULL. xValue and xInverse may either both be NULL, in +** which case a regular aggregate function is created, or must both be +** non-NULL, in which case the new function may be used as either an aggregate +** or aggregate window function. More details regarding the implementation +** of aggregate window functions are +** [user-defined window functions|available here]. +** +** ^(If the final parameter to sqlite3_create_function_v2() or +** sqlite3_create_window_function() is not NULL, then it is destructor for +** the application data pointer. The destructor is invoked when the function +** is deleted, either by being overloaded or when the database connection +** closes.)^ ^The destructor is also invoked if the call to +** sqlite3_create_function_v2() fails. ^When the destructor callback is +** invoked, it is passed a single argument which is a copy of the application +** data pointer which was the fifth parameter to sqlite3_create_function_v2(). +** +** ^It is permitted to register multiple implementations of the same +** functions with the same name but with either differing numbers of +** arguments or differing preferred text encodings. ^SQLite will use +** the implementation that most closely matches the way in which the +** SQL function is used. ^A function implementation with a non-negative +** nArg parameter is a better match than a function implementation with +** a negative nArg. ^A function where the preferred text encoding +** matches the database encoding is a better +** match than a function where the encoding is different. +** ^A function where the encoding difference is between UTF16le and UTF16be +** is a closer match than a function where the encoding difference is +** between UTF8 and UTF16. +** +** ^Built-in functions may be overloaded by new application-defined functions. +** +** ^An application-defined function is permitted to call other +** SQLite interfaces. However, such calls must not +** close the database connection nor finalize or reset the prepared +** statement in which the function is running. +*/ +SQLITE_API int sqlite3_create_function( + sqlite3 *db, + const char *zFunctionName, + int nArg, + int eTextRep, + void *pApp, + void (*xFunc)(sqlite3_context*,int,sqlite3_value**), + void (*xStep)(sqlite3_context*,int,sqlite3_value**), + void (*xFinal)(sqlite3_context*) +); +SQLITE_API int sqlite3_create_function16( + sqlite3 *db, + const void *zFunctionName, + int nArg, + int eTextRep, + void *pApp, + void (*xFunc)(sqlite3_context*,int,sqlite3_value**), + void (*xStep)(sqlite3_context*,int,sqlite3_value**), + void (*xFinal)(sqlite3_context*) +); +SQLITE_API int sqlite3_create_function_v2( + sqlite3 *db, + const char *zFunctionName, + int nArg, + int eTextRep, + void *pApp, + void (*xFunc)(sqlite3_context*,int,sqlite3_value**), + void (*xStep)(sqlite3_context*,int,sqlite3_value**), + void (*xFinal)(sqlite3_context*), + void(*xDestroy)(void*) +); +SQLITE_API int sqlite3_create_window_function( + sqlite3 *db, + const char *zFunctionName, + int nArg, + int eTextRep, + void *pApp, + void (*xStep)(sqlite3_context*,int,sqlite3_value**), + void (*xFinal)(sqlite3_context*), + void (*xValue)(sqlite3_context*), + void (*xInverse)(sqlite3_context*,int,sqlite3_value**), + void(*xDestroy)(void*) +); + +/* +** CAPI3REF: Text Encodings +** +** These constant define integer codes that represent the various +** text encodings supported by SQLite. +*/ +#define SQLITE_UTF8 1 /* IMP: R-37514-35566 */ +#define SQLITE_UTF16LE 2 /* IMP: R-03371-37637 */ +#define SQLITE_UTF16BE 3 /* IMP: R-51971-34154 */ +#define SQLITE_UTF16 4 /* Use native byte order */ +#define SQLITE_ANY 5 /* Deprecated */ +#define SQLITE_UTF16_ALIGNED 8 /* sqlite3_create_collation only */ + +/* +** CAPI3REF: Function Flags +** +** These constants may be ORed together with the +** [SQLITE_UTF8 | preferred text encoding] as the fourth argument +** to [sqlite3_create_function()], [sqlite3_create_function16()], or +** [sqlite3_create_function_v2()]. +** +**
    +** [[SQLITE_DETERMINISTIC]]
    SQLITE_DETERMINISTIC
    +** The SQLITE_DETERMINISTIC flag means that the new function always gives +** the same output when the input parameters are the same. +** The [abs|abs() function] is deterministic, for example, but +** [randomblob|randomblob()] is not. Functions must +** be deterministic in order to be used in certain contexts such as +** with the WHERE clause of [partial indexes] or in [generated columns]. +** SQLite might also optimize deterministic functions by factoring them +** out of inner loops. +**
    +** +** [[SQLITE_DIRECTONLY]]
    SQLITE_DIRECTONLY
    +** The SQLITE_DIRECTONLY flag means that the function may only be invoked +** from top-level SQL, and cannot be used in VIEWs or TRIGGERs nor in +** schema structures such as [CHECK constraints], [DEFAULT clauses], +** [expression indexes], [partial indexes], or [generated columns]. +** The SQLITE_DIRECTONLY flags is a security feature which is recommended +** for all [application-defined SQL functions], and especially for functions +** that have side-effects or that could potentially leak sensitive +** information. +**
    +** +** [[SQLITE_INNOCUOUS]]
    SQLITE_INNOCUOUS
    +** The SQLITE_INNOCUOUS flag means that the function is unlikely +** to cause problems even if misused. An innocuous function should have +** no side effects and should not depend on any values other than its +** input parameters. The [abs|abs() function] is an example of an +** innocuous function. +** The [load_extension() SQL function] is not innocuous because of its +** side effects. +**

    SQLITE_INNOCUOUS is similar to SQLITE_DETERMINISTIC, but is not +** exactly the same. The [random|random() function] is an example of a +** function that is innocuous but not deterministic. +**

    Some heightened security settings +** ([SQLITE_DBCONFIG_TRUSTED_SCHEMA] and [PRAGMA trusted_schema=OFF]) +** disable the use of SQL functions inside views and triggers and in +** schema structures such as [CHECK constraints], [DEFAULT clauses], +** [expression indexes], [partial indexes], and [generated columns] unless +** the function is tagged with SQLITE_INNOCUOUS. Most built-in functions +** are innocuous. Developers are advised to avoid using the +** SQLITE_INNOCUOUS flag for application-defined functions unless the +** function has been carefully audited and found to be free of potentially +** security-adverse side-effects and information-leaks. +**

    +** +** [[SQLITE_SUBTYPE]]
    SQLITE_SUBTYPE
    +** The SQLITE_SUBTYPE flag indicates to SQLite that a function may call +** [sqlite3_value_subtype()] to inspect the sub-types of its arguments. +** Specifying this flag makes no difference for scalar or aggregate user +** functions. However, if it is not specified for a user-defined window +** function, then any sub-types belonging to arguments passed to the window +** function may be discarded before the window function is called (i.e. +** sqlite3_value_subtype() will always return 0). +**
    +**
    +*/ +#define SQLITE_DETERMINISTIC 0x000000800 +#define SQLITE_DIRECTONLY 0x000080000 +#define SQLITE_SUBTYPE 0x000100000 +#define SQLITE_INNOCUOUS 0x000200000 + +/* +** CAPI3REF: Deprecated Functions +** DEPRECATED +** +** These functions are [deprecated]. In order to maintain +** backwards compatibility with older code, these functions continue +** to be supported. However, new applications should avoid +** the use of these functions. To encourage programmers to avoid +** these functions, we will not explain what they do. +*/ +#ifndef SQLITE_OMIT_DEPRECATED +SQLITE_API SQLITE_DEPRECATED int sqlite3_aggregate_count(sqlite3_context*); +SQLITE_API SQLITE_DEPRECATED int sqlite3_expired(sqlite3_stmt*); +SQLITE_API SQLITE_DEPRECATED int sqlite3_transfer_bindings(sqlite3_stmt*, sqlite3_stmt*); +SQLITE_API SQLITE_DEPRECATED int sqlite3_global_recover(void); +SQLITE_API SQLITE_DEPRECATED void sqlite3_thread_cleanup(void); +SQLITE_API SQLITE_DEPRECATED int sqlite3_memory_alarm(void(*)(void*,sqlite3_int64,int), + void*,sqlite3_int64); +#endif + +/* +** CAPI3REF: Obtaining SQL Values +** METHOD: sqlite3_value +** +** Summary: +**
    +**
    sqlite3_value_blobBLOB value +**
    sqlite3_value_doubleREAL value +**
    sqlite3_value_int32-bit INTEGER value +**
    sqlite3_value_int6464-bit INTEGER value +**
    sqlite3_value_pointerPointer value +**
    sqlite3_value_textUTF-8 TEXT value +**
    sqlite3_value_text16UTF-16 TEXT value in +** the native byteorder +**
    sqlite3_value_text16beUTF-16be TEXT value +**
    sqlite3_value_text16leUTF-16le TEXT value +**
        +**
    sqlite3_value_bytesSize of a BLOB +** or a UTF-8 TEXT in bytes +**
    sqlite3_value_bytes16   +** →  Size of UTF-16 +** TEXT in bytes +**
    sqlite3_value_typeDefault +** datatype of the value +**
    sqlite3_value_numeric_type   +** →  Best numeric datatype of the value +**
    sqlite3_value_nochange   +** →  True if the column is unchanged in an UPDATE +** against a virtual table. +**
    sqlite3_value_frombind   +** →  True if value originated from a [bound parameter] +**
    +** +** Details: +** +** These routines extract type, size, and content information from +** [protected sqlite3_value] objects. Protected sqlite3_value objects +** are used to pass parameter information into the functions that +** implement [application-defined SQL functions] and [virtual tables]. +** +** These routines work only with [protected sqlite3_value] objects. +** Any attempt to use these routines on an [unprotected sqlite3_value] +** is not threadsafe. +** +** ^These routines work just like the corresponding [column access functions] +** except that these routines take a single [protected sqlite3_value] object +** pointer instead of a [sqlite3_stmt*] pointer and an integer column number. +** +** ^The sqlite3_value_text16() interface extracts a UTF-16 string +** in the native byte-order of the host machine. ^The +** sqlite3_value_text16be() and sqlite3_value_text16le() interfaces +** extract UTF-16 strings as big-endian and little-endian respectively. +** +** ^If [sqlite3_value] object V was initialized +** using [sqlite3_bind_pointer(S,I,P,X,D)] or [sqlite3_result_pointer(C,P,X,D)] +** and if X and Y are strings that compare equal according to strcmp(X,Y), +** then sqlite3_value_pointer(V,Y) will return the pointer P. ^Otherwise, +** sqlite3_value_pointer(V,Y) returns a NULL. The sqlite3_bind_pointer() +** routine is part of the [pointer passing interface] added for SQLite 3.20.0. +** +** ^(The sqlite3_value_type(V) interface returns the +** [SQLITE_INTEGER | datatype code] for the initial datatype of the +** [sqlite3_value] object V. The returned value is one of [SQLITE_INTEGER], +** [SQLITE_FLOAT], [SQLITE_TEXT], [SQLITE_BLOB], or [SQLITE_NULL].)^ +** Other interfaces might change the datatype for an sqlite3_value object. +** For example, if the datatype is initially SQLITE_INTEGER and +** sqlite3_value_text(V) is called to extract a text value for that +** integer, then subsequent calls to sqlite3_value_type(V) might return +** SQLITE_TEXT. Whether or not a persistent internal datatype conversion +** occurs is undefined and may change from one release of SQLite to the next. +** +** ^(The sqlite3_value_numeric_type() interface attempts to apply +** numeric affinity to the value. This means that an attempt is +** made to convert the value to an integer or floating point. If +** such a conversion is possible without loss of information (in other +** words, if the value is a string that looks like a number) +** then the conversion is performed. Otherwise no conversion occurs. +** The [SQLITE_INTEGER | datatype] after conversion is returned.)^ +** +** ^Within the [xUpdate] method of a [virtual table], the +** sqlite3_value_nochange(X) interface returns true if and only if +** the column corresponding to X is unchanged by the UPDATE operation +** that the xUpdate method call was invoked to implement and if +** and the prior [xColumn] method call that was invoked to extracted +** the value for that column returned without setting a result (probably +** because it queried [sqlite3_vtab_nochange()] and found that the column +** was unchanging). ^Within an [xUpdate] method, any value for which +** sqlite3_value_nochange(X) is true will in all other respects appear +** to be a NULL value. If sqlite3_value_nochange(X) is invoked anywhere other +** than within an [xUpdate] method call for an UPDATE statement, then +** the return value is arbitrary and meaningless. +** +** ^The sqlite3_value_frombind(X) interface returns non-zero if the +** value X originated from one of the [sqlite3_bind_int|sqlite3_bind()] +** interfaces. ^If X comes from an SQL literal value, or a table column, +** or an expression, then sqlite3_value_frombind(X) returns zero. +** +** Please pay particular attention to the fact that the pointer returned +** from [sqlite3_value_blob()], [sqlite3_value_text()], or +** [sqlite3_value_text16()] can be invalidated by a subsequent call to +** [sqlite3_value_bytes()], [sqlite3_value_bytes16()], [sqlite3_value_text()], +** or [sqlite3_value_text16()]. +** +** These routines must be called from the same thread as +** the SQL function that supplied the [sqlite3_value*] parameters. +** +** As long as the input parameter is correct, these routines can only +** fail if an out-of-memory error occurs during a format conversion. +** Only the following subset of interfaces are subject to out-of-memory +** errors: +** +**
      +**
    • sqlite3_value_blob() +**
    • sqlite3_value_text() +**
    • sqlite3_value_text16() +**
    • sqlite3_value_text16le() +**
    • sqlite3_value_text16be() +**
    • sqlite3_value_bytes() +**
    • sqlite3_value_bytes16() +**
    +** +** If an out-of-memory error occurs, then the return value from these +** routines is the same as if the column had contained an SQL NULL value. +** Valid SQL NULL returns can be distinguished from out-of-memory errors +** by invoking the [sqlite3_errcode()] immediately after the suspect +** return value is obtained and before any +** other SQLite interface is called on the same [database connection]. +*/ +SQLITE_API const void *sqlite3_value_blob(sqlite3_value*); +SQLITE_API double sqlite3_value_double(sqlite3_value*); +SQLITE_API int sqlite3_value_int(sqlite3_value*); +SQLITE_API sqlite3_int64 sqlite3_value_int64(sqlite3_value*); +SQLITE_API void *sqlite3_value_pointer(sqlite3_value*, const char*); +SQLITE_API const unsigned char *sqlite3_value_text(sqlite3_value*); +SQLITE_API const void *sqlite3_value_text16(sqlite3_value*); +SQLITE_API const void *sqlite3_value_text16le(sqlite3_value*); +SQLITE_API const void *sqlite3_value_text16be(sqlite3_value*); +SQLITE_API int sqlite3_value_bytes(sqlite3_value*); +SQLITE_API int sqlite3_value_bytes16(sqlite3_value*); +SQLITE_API int sqlite3_value_type(sqlite3_value*); +SQLITE_API int sqlite3_value_numeric_type(sqlite3_value*); +SQLITE_API int sqlite3_value_nochange(sqlite3_value*); +SQLITE_API int sqlite3_value_frombind(sqlite3_value*); + +/* +** CAPI3REF: Finding The Subtype Of SQL Values +** METHOD: sqlite3_value +** +** The sqlite3_value_subtype(V) function returns the subtype for +** an [application-defined SQL function] argument V. The subtype +** information can be used to pass a limited amount of context from +** one SQL function to another. Use the [sqlite3_result_subtype()] +** routine to set the subtype for the return value of an SQL function. +*/ +SQLITE_API unsigned int sqlite3_value_subtype(sqlite3_value*); + +/* +** CAPI3REF: Copy And Free SQL Values +** METHOD: sqlite3_value +** +** ^The sqlite3_value_dup(V) interface makes a copy of the [sqlite3_value] +** object D and returns a pointer to that copy. ^The [sqlite3_value] returned +** is a [protected sqlite3_value] object even if the input is not. +** ^The sqlite3_value_dup(V) interface returns NULL if V is NULL or if a +** memory allocation fails. +** +** ^The sqlite3_value_free(V) interface frees an [sqlite3_value] object +** previously obtained from [sqlite3_value_dup()]. ^If V is a NULL pointer +** then sqlite3_value_free(V) is a harmless no-op. +*/ +SQLITE_API sqlite3_value *sqlite3_value_dup(const sqlite3_value*); +SQLITE_API void sqlite3_value_free(sqlite3_value*); + +/* +** CAPI3REF: Obtain Aggregate Function Context +** METHOD: sqlite3_context +** +** Implementations of aggregate SQL functions use this +** routine to allocate memory for storing their state. +** +** ^The first time the sqlite3_aggregate_context(C,N) routine is called +** for a particular aggregate function, SQLite allocates +** N bytes of memory, zeroes out that memory, and returns a pointer +** to the new memory. ^On second and subsequent calls to +** sqlite3_aggregate_context() for the same aggregate function instance, +** the same buffer is returned. Sqlite3_aggregate_context() is normally +** called once for each invocation of the xStep callback and then one +** last time when the xFinal callback is invoked. ^(When no rows match +** an aggregate query, the xStep() callback of the aggregate function +** implementation is never called and xFinal() is called exactly once. +** In those cases, sqlite3_aggregate_context() might be called for the +** first time from within xFinal().)^ +** +** ^The sqlite3_aggregate_context(C,N) routine returns a NULL pointer +** when first called if N is less than or equal to zero or if a memory +** allocate error occurs. +** +** ^(The amount of space allocated by sqlite3_aggregate_context(C,N) is +** determined by the N parameter on first successful call. Changing the +** value of N in any subsequent call to sqlite3_aggregate_context() within +** the same aggregate function instance will not resize the memory +** allocation.)^ Within the xFinal callback, it is customary to set +** N=0 in calls to sqlite3_aggregate_context(C,N) so that no +** pointless memory allocations occur. +** +** ^SQLite automatically frees the memory allocated by +** sqlite3_aggregate_context() when the aggregate query concludes. +** +** The first parameter must be a copy of the +** [sqlite3_context | SQL function context] that is the first parameter +** to the xStep or xFinal callback routine that implements the aggregate +** function. +** +** This routine must be called from the same thread in which +** the aggregate SQL function is running. +*/ +SQLITE_API void *sqlite3_aggregate_context(sqlite3_context*, int nBytes); + +/* +** CAPI3REF: User Data For Functions +** METHOD: sqlite3_context +** +** ^The sqlite3_user_data() interface returns a copy of +** the pointer that was the pUserData parameter (the 5th parameter) +** of the [sqlite3_create_function()] +** and [sqlite3_create_function16()] routines that originally +** registered the application defined function. +** +** This routine must be called from the same thread in which +** the application-defined function is running. +*/ +SQLITE_API void *sqlite3_user_data(sqlite3_context*); + +/* +** CAPI3REF: Database Connection For Functions +** METHOD: sqlite3_context +** +** ^The sqlite3_context_db_handle() interface returns a copy of +** the pointer to the [database connection] (the 1st parameter) +** of the [sqlite3_create_function()] +** and [sqlite3_create_function16()] routines that originally +** registered the application defined function. +*/ +SQLITE_API sqlite3 *sqlite3_context_db_handle(sqlite3_context*); + +/* +** CAPI3REF: Function Auxiliary Data +** METHOD: sqlite3_context +** +** These functions may be used by (non-aggregate) SQL functions to +** associate metadata with argument values. If the same value is passed to +** multiple invocations of the same SQL function during query execution, under +** some circumstances the associated metadata may be preserved. An example +** of where this might be useful is in a regular-expression matching +** function. The compiled version of the regular expression can be stored as +** metadata associated with the pattern string. +** Then as long as the pattern string remains the same, +** the compiled regular expression can be reused on multiple +** invocations of the same function. +** +** ^The sqlite3_get_auxdata(C,N) interface returns a pointer to the metadata +** associated by the sqlite3_set_auxdata(C,N,P,X) function with the Nth argument +** value to the application-defined function. ^N is zero for the left-most +** function argument. ^If there is no metadata +** associated with the function argument, the sqlite3_get_auxdata(C,N) interface +** returns a NULL pointer. +** +** ^The sqlite3_set_auxdata(C,N,P,X) interface saves P as metadata for the N-th +** argument of the application-defined function. ^Subsequent +** calls to sqlite3_get_auxdata(C,N) return P from the most recent +** sqlite3_set_auxdata(C,N,P,X) call if the metadata is still valid or +** NULL if the metadata has been discarded. +** ^After each call to sqlite3_set_auxdata(C,N,P,X) where X is not NULL, +** SQLite will invoke the destructor function X with parameter P exactly +** once, when the metadata is discarded. +** SQLite is free to discard the metadata at any time, including:
      +**
    • ^(when the corresponding function parameter changes)^, or +**
    • ^(when [sqlite3_reset()] or [sqlite3_finalize()] is called for the +** SQL statement)^, or +**
    • ^(when sqlite3_set_auxdata() is invoked again on the same +** parameter)^, or +**
    • ^(during the original sqlite3_set_auxdata() call when a memory +** allocation error occurs.)^
    +** +** Note the last bullet in particular. The destructor X in +** sqlite3_set_auxdata(C,N,P,X) might be called immediately, before the +** sqlite3_set_auxdata() interface even returns. Hence sqlite3_set_auxdata() +** should be called near the end of the function implementation and the +** function implementation should not make any use of P after +** sqlite3_set_auxdata() has been called. +** +** ^(In practice, metadata is preserved between function calls for +** function parameters that are compile-time constants, including literal +** values and [parameters] and expressions composed from the same.)^ +** +** The value of the N parameter to these interfaces should be non-negative. +** Future enhancements may make use of negative N values to define new +** kinds of function caching behavior. +** +** These routines must be called from the same thread in which +** the SQL function is running. +*/ +SQLITE_API void *sqlite3_get_auxdata(sqlite3_context*, int N); +SQLITE_API void sqlite3_set_auxdata(sqlite3_context*, int N, void*, void (*)(void*)); + + +/* +** CAPI3REF: Constants Defining Special Destructor Behavior +** +** These are special values for the destructor that is passed in as the +** final argument to routines like [sqlite3_result_blob()]. ^If the destructor +** argument is SQLITE_STATIC, it means that the content pointer is constant +** and will never change. It does not need to be destroyed. ^The +** SQLITE_TRANSIENT value means that the content will likely change in +** the near future and that SQLite should make its own private copy of +** the content before returning. +** +** The typedef is necessary to work around problems in certain +** C++ compilers. +*/ +typedef void (*sqlite3_destructor_type)(void*); +#define SQLITE_STATIC ((sqlite3_destructor_type)0) +#define SQLITE_TRANSIENT ((sqlite3_destructor_type)-1) + +/* +** CAPI3REF: Setting The Result Of An SQL Function +** METHOD: sqlite3_context +** +** These routines are used by the xFunc or xFinal callbacks that +** implement SQL functions and aggregates. See +** [sqlite3_create_function()] and [sqlite3_create_function16()] +** for additional information. +** +** These functions work very much like the [parameter binding] family of +** functions used to bind values to host parameters in prepared statements. +** Refer to the [SQL parameter] documentation for additional information. +** +** ^The sqlite3_result_blob() interface sets the result from +** an application-defined function to be the BLOB whose content is pointed +** to by the second parameter and which is N bytes long where N is the +** third parameter. +** +** ^The sqlite3_result_zeroblob(C,N) and sqlite3_result_zeroblob64(C,N) +** interfaces set the result of the application-defined function to be +** a BLOB containing all zero bytes and N bytes in size. +** +** ^The sqlite3_result_double() interface sets the result from +** an application-defined function to be a floating point value specified +** by its 2nd argument. +** +** ^The sqlite3_result_error() and sqlite3_result_error16() functions +** cause the implemented SQL function to throw an exception. +** ^SQLite uses the string pointed to by the +** 2nd parameter of sqlite3_result_error() or sqlite3_result_error16() +** as the text of an error message. ^SQLite interprets the error +** message string from sqlite3_result_error() as UTF-8. ^SQLite +** interprets the string from sqlite3_result_error16() as UTF-16 using +** the same [byte-order determination rules] as [sqlite3_bind_text16()]. +** ^If the third parameter to sqlite3_result_error() +** or sqlite3_result_error16() is negative then SQLite takes as the error +** message all text up through the first zero character. +** ^If the third parameter to sqlite3_result_error() or +** sqlite3_result_error16() is non-negative then SQLite takes that many +** bytes (not characters) from the 2nd parameter as the error message. +** ^The sqlite3_result_error() and sqlite3_result_error16() +** routines make a private copy of the error message text before +** they return. Hence, the calling function can deallocate or +** modify the text after they return without harm. +** ^The sqlite3_result_error_code() function changes the error code +** returned by SQLite as a result of an error in a function. ^By default, +** the error code is SQLITE_ERROR. ^A subsequent call to sqlite3_result_error() +** or sqlite3_result_error16() resets the error code to SQLITE_ERROR. +** +** ^The sqlite3_result_error_toobig() interface causes SQLite to throw an +** error indicating that a string or BLOB is too long to represent. +** +** ^The sqlite3_result_error_nomem() interface causes SQLite to throw an +** error indicating that a memory allocation failed. +** +** ^The sqlite3_result_int() interface sets the return value +** of the application-defined function to be the 32-bit signed integer +** value given in the 2nd argument. +** ^The sqlite3_result_int64() interface sets the return value +** of the application-defined function to be the 64-bit signed integer +** value given in the 2nd argument. +** +** ^The sqlite3_result_null() interface sets the return value +** of the application-defined function to be NULL. +** +** ^The sqlite3_result_text(), sqlite3_result_text16(), +** sqlite3_result_text16le(), and sqlite3_result_text16be() interfaces +** set the return value of the application-defined function to be +** a text string which is represented as UTF-8, UTF-16 native byte order, +** UTF-16 little endian, or UTF-16 big endian, respectively. +** ^The sqlite3_result_text64() interface sets the return value of an +** application-defined function to be a text string in an encoding +** specified by the fifth (and last) parameter, which must be one +** of [SQLITE_UTF8], [SQLITE_UTF16], [SQLITE_UTF16BE], or [SQLITE_UTF16LE]. +** ^SQLite takes the text result from the application from +** the 2nd parameter of the sqlite3_result_text* interfaces. +** ^If the 3rd parameter to the sqlite3_result_text* interfaces +** is negative, then SQLite takes result text from the 2nd parameter +** through the first zero character. +** ^If the 3rd parameter to the sqlite3_result_text* interfaces +** is non-negative, then as many bytes (not characters) of the text +** pointed to by the 2nd parameter are taken as the application-defined +** function result. If the 3rd parameter is non-negative, then it +** must be the byte offset into the string where the NUL terminator would +** appear if the string where NUL terminated. If any NUL characters occur +** in the string at a byte offset that is less than the value of the 3rd +** parameter, then the resulting string will contain embedded NULs and the +** result of expressions operating on strings with embedded NULs is undefined. +** ^If the 4th parameter to the sqlite3_result_text* interfaces +** or sqlite3_result_blob is a non-NULL pointer, then SQLite calls that +** function as the destructor on the text or BLOB result when it has +** finished using that result. +** ^If the 4th parameter to the sqlite3_result_text* interfaces or to +** sqlite3_result_blob is the special constant SQLITE_STATIC, then SQLite +** assumes that the text or BLOB result is in constant space and does not +** copy the content of the parameter nor call a destructor on the content +** when it has finished using that result. +** ^If the 4th parameter to the sqlite3_result_text* interfaces +** or sqlite3_result_blob is the special constant SQLITE_TRANSIENT +** then SQLite makes a copy of the result into space obtained +** from [sqlite3_malloc()] before it returns. +** +** ^For the sqlite3_result_text16(), sqlite3_result_text16le(), and +** sqlite3_result_text16be() routines, and for sqlite3_result_text64() +** when the encoding is not UTF8, if the input UTF16 begins with a +** byte-order mark (BOM, U+FEFF) then the BOM is removed from the +** string and the rest of the string is interpreted according to the +** byte-order specified by the BOM. ^The byte-order specified by +** the BOM at the beginning of the text overrides the byte-order +** specified by the interface procedure. ^So, for example, if +** sqlite3_result_text16le() is invoked with text that begins +** with bytes 0xfe, 0xff (a big-endian byte-order mark) then the +** first two bytes of input are skipped and the remaining input +** is interpreted as UTF16BE text. +** +** ^For UTF16 input text to the sqlite3_result_text16(), +** sqlite3_result_text16be(), sqlite3_result_text16le(), and +** sqlite3_result_text64() routines, if the text contains invalid +** UTF16 characters, the invalid characters might be converted +** into the unicode replacement character, U+FFFD. +** +** ^The sqlite3_result_value() interface sets the result of +** the application-defined function to be a copy of the +** [unprotected sqlite3_value] object specified by the 2nd parameter. ^The +** sqlite3_result_value() interface makes a copy of the [sqlite3_value] +** so that the [sqlite3_value] specified in the parameter may change or +** be deallocated after sqlite3_result_value() returns without harm. +** ^A [protected sqlite3_value] object may always be used where an +** [unprotected sqlite3_value] object is required, so either +** kind of [sqlite3_value] object can be used with this interface. +** +** ^The sqlite3_result_pointer(C,P,T,D) interface sets the result to an +** SQL NULL value, just like [sqlite3_result_null(C)], except that it +** also associates the host-language pointer P or type T with that +** NULL value such that the pointer can be retrieved within an +** [application-defined SQL function] using [sqlite3_value_pointer()]. +** ^If the D parameter is not NULL, then it is a pointer to a destructor +** for the P parameter. ^SQLite invokes D with P as its only argument +** when SQLite is finished with P. The T parameter should be a static +** string and preferably a string literal. The sqlite3_result_pointer() +** routine is part of the [pointer passing interface] added for SQLite 3.20.0. +** +** If these routines are called from within the different thread +** than the one containing the application-defined function that received +** the [sqlite3_context] pointer, the results are undefined. +*/ +SQLITE_API void sqlite3_result_blob(sqlite3_context*, const void*, int, void(*)(void*)); +SQLITE_API void sqlite3_result_blob64(sqlite3_context*,const void*, + sqlite3_uint64,void(*)(void*)); +SQLITE_API void sqlite3_result_double(sqlite3_context*, double); +SQLITE_API void sqlite3_result_error(sqlite3_context*, const char*, int); +SQLITE_API void sqlite3_result_error16(sqlite3_context*, const void*, int); +SQLITE_API void sqlite3_result_error_toobig(sqlite3_context*); +SQLITE_API void sqlite3_result_error_nomem(sqlite3_context*); +SQLITE_API void sqlite3_result_error_code(sqlite3_context*, int); +SQLITE_API void sqlite3_result_int(sqlite3_context*, int); +SQLITE_API void sqlite3_result_int64(sqlite3_context*, sqlite3_int64); +SQLITE_API void sqlite3_result_null(sqlite3_context*); +SQLITE_API void sqlite3_result_text(sqlite3_context*, const char*, int, void(*)(void*)); +SQLITE_API void sqlite3_result_text64(sqlite3_context*, const char*,sqlite3_uint64, + void(*)(void*), unsigned char encoding); +SQLITE_API void sqlite3_result_text16(sqlite3_context*, const void*, int, void(*)(void*)); +SQLITE_API void sqlite3_result_text16le(sqlite3_context*, const void*, int,void(*)(void*)); +SQLITE_API void sqlite3_result_text16be(sqlite3_context*, const void*, int,void(*)(void*)); +SQLITE_API void sqlite3_result_value(sqlite3_context*, sqlite3_value*); +SQLITE_API void sqlite3_result_pointer(sqlite3_context*, void*,const char*,void(*)(void*)); +SQLITE_API void sqlite3_result_zeroblob(sqlite3_context*, int n); +SQLITE_API int sqlite3_result_zeroblob64(sqlite3_context*, sqlite3_uint64 n); + + +/* +** CAPI3REF: Setting The Subtype Of An SQL Function +** METHOD: sqlite3_context +** +** The sqlite3_result_subtype(C,T) function causes the subtype of +** the result from the [application-defined SQL function] with +** [sqlite3_context] C to be the value T. Only the lower 8 bits +** of the subtype T are preserved in current versions of SQLite; +** higher order bits are discarded. +** The number of subtype bytes preserved by SQLite might increase +** in future releases of SQLite. +*/ +SQLITE_API void sqlite3_result_subtype(sqlite3_context*,unsigned int); + +/* +** CAPI3REF: Define New Collating Sequences +** METHOD: sqlite3 +** +** ^These functions add, remove, or modify a [collation] associated +** with the [database connection] specified as the first argument. +** +** ^The name of the collation is a UTF-8 string +** for sqlite3_create_collation() and sqlite3_create_collation_v2() +** and a UTF-16 string in native byte order for sqlite3_create_collation16(). +** ^Collation names that compare equal according to [sqlite3_strnicmp()] are +** considered to be the same name. +** +** ^(The third argument (eTextRep) must be one of the constants: +**
      +**
    • [SQLITE_UTF8], +**
    • [SQLITE_UTF16LE], +**
    • [SQLITE_UTF16BE], +**
    • [SQLITE_UTF16], or +**
    • [SQLITE_UTF16_ALIGNED]. +**
    )^ +** ^The eTextRep argument determines the encoding of strings passed +** to the collating function callback, xCompare. +** ^The [SQLITE_UTF16] and [SQLITE_UTF16_ALIGNED] values for eTextRep +** force strings to be UTF16 with native byte order. +** ^The [SQLITE_UTF16_ALIGNED] value for eTextRep forces strings to begin +** on an even byte address. +** +** ^The fourth argument, pArg, is an application data pointer that is passed +** through as the first argument to the collating function callback. +** +** ^The fifth argument, xCompare, is a pointer to the collating function. +** ^Multiple collating functions can be registered using the same name but +** with different eTextRep parameters and SQLite will use whichever +** function requires the least amount of data transformation. +** ^If the xCompare argument is NULL then the collating function is +** deleted. ^When all collating functions having the same name are deleted, +** that collation is no longer usable. +** +** ^The collating function callback is invoked with a copy of the pArg +** application data pointer and with two strings in the encoding specified +** by the eTextRep argument. The two integer parameters to the collating +** function callback are the length of the two strings, in bytes. The collating +** function must return an integer that is negative, zero, or positive +** if the first string is less than, equal to, or greater than the second, +** respectively. A collating function must always return the same answer +** given the same inputs. If two or more collating functions are registered +** to the same collation name (using different eTextRep values) then all +** must give an equivalent answer when invoked with equivalent strings. +** The collating function must obey the following properties for all +** strings A, B, and C: +** +**
      +**
    1. If A==B then B==A. +**
    2. If A==B and B==C then A==C. +**
    3. If A<B THEN B>A. +**
    4. If A<B and B<C then A<C. +**
    +** +** If a collating function fails any of the above constraints and that +** collating function is registered and used, then the behavior of SQLite +** is undefined. +** +** ^The sqlite3_create_collation_v2() works like sqlite3_create_collation() +** with the addition that the xDestroy callback is invoked on pArg when +** the collating function is deleted. +** ^Collating functions are deleted when they are overridden by later +** calls to the collation creation functions or when the +** [database connection] is closed using [sqlite3_close()]. +** +** ^The xDestroy callback is not called if the +** sqlite3_create_collation_v2() function fails. Applications that invoke +** sqlite3_create_collation_v2() with a non-NULL xDestroy argument should +** check the return code and dispose of the application data pointer +** themselves rather than expecting SQLite to deal with it for them. +** This is different from every other SQLite interface. The inconsistency +** is unfortunate but cannot be changed without breaking backwards +** compatibility. +** +** See also: [sqlite3_collation_needed()] and [sqlite3_collation_needed16()]. +*/ +SQLITE_API int sqlite3_create_collation( + sqlite3*, + const char *zName, + int eTextRep, + void *pArg, + int(*xCompare)(void*,int,const void*,int,const void*) +); +SQLITE_API int sqlite3_create_collation_v2( + sqlite3*, + const char *zName, + int eTextRep, + void *pArg, + int(*xCompare)(void*,int,const void*,int,const void*), + void(*xDestroy)(void*) +); +SQLITE_API int sqlite3_create_collation16( + sqlite3*, + const void *zName, + int eTextRep, + void *pArg, + int(*xCompare)(void*,int,const void*,int,const void*) +); + +/* +** CAPI3REF: Collation Needed Callbacks +** METHOD: sqlite3 +** +** ^To avoid having to register all collation sequences before a database +** can be used, a single callback function may be registered with the +** [database connection] to be invoked whenever an undefined collation +** sequence is required. +** +** ^If the function is registered using the sqlite3_collation_needed() API, +** then it is passed the names of undefined collation sequences as strings +** encoded in UTF-8. ^If sqlite3_collation_needed16() is used, +** the names are passed as UTF-16 in machine native byte order. +** ^A call to either function replaces the existing collation-needed callback. +** +** ^(When the callback is invoked, the first argument passed is a copy +** of the second argument to sqlite3_collation_needed() or +** sqlite3_collation_needed16(). The second argument is the database +** connection. The third argument is one of [SQLITE_UTF8], [SQLITE_UTF16BE], +** or [SQLITE_UTF16LE], indicating the most desirable form of the collation +** sequence function required. The fourth parameter is the name of the +** required collation sequence.)^ +** +** The callback function should register the desired collation using +** [sqlite3_create_collation()], [sqlite3_create_collation16()], or +** [sqlite3_create_collation_v2()]. +*/ +SQLITE_API int sqlite3_collation_needed( + sqlite3*, + void*, + void(*)(void*,sqlite3*,int eTextRep,const char*) +); +SQLITE_API int sqlite3_collation_needed16( + sqlite3*, + void*, + void(*)(void*,sqlite3*,int eTextRep,const void*) +); + +#ifdef SQLITE_ENABLE_CEROD +/* +** Specify the activation key for a CEROD database. Unless +** activated, none of the CEROD routines will work. +*/ +SQLITE_API void sqlite3_activate_cerod( + const char *zPassPhrase /* Activation phrase */ +); +#endif + +/* +** CAPI3REF: Suspend Execution For A Short Time +** +** The sqlite3_sleep() function causes the current thread to suspend execution +** for at least a number of milliseconds specified in its parameter. +** +** If the operating system does not support sleep requests with +** millisecond time resolution, then the time will be rounded up to +** the nearest second. The number of milliseconds of sleep actually +** requested from the operating system is returned. +** +** ^SQLite implements this interface by calling the xSleep() +** method of the default [sqlite3_vfs] object. If the xSleep() method +** of the default VFS is not implemented correctly, or not implemented at +** all, then the behavior of sqlite3_sleep() may deviate from the description +** in the previous paragraphs. +*/ +SQLITE_API int sqlite3_sleep(int); + +/* +** CAPI3REF: Name Of The Folder Holding Temporary Files +** +** ^(If this global variable is made to point to a string which is +** the name of a folder (a.k.a. directory), then all temporary files +** created by SQLite when using a built-in [sqlite3_vfs | VFS] +** will be placed in that directory.)^ ^If this variable +** is a NULL pointer, then SQLite performs a search for an appropriate +** temporary file directory. +** +** Applications are strongly discouraged from using this global variable. +** It is required to set a temporary folder on Windows Runtime (WinRT). +** But for all other platforms, it is highly recommended that applications +** neither read nor write this variable. This global variable is a relic +** that exists for backwards compatibility of legacy applications and should +** be avoided in new projects. +** +** It is not safe to read or modify this variable in more than one +** thread at a time. It is not safe to read or modify this variable +** if a [database connection] is being used at the same time in a separate +** thread. +** It is intended that this variable be set once +** as part of process initialization and before any SQLite interface +** routines have been called and that this variable remain unchanged +** thereafter. +** +** ^The [temp_store_directory pragma] may modify this variable and cause +** it to point to memory obtained from [sqlite3_malloc]. ^Furthermore, +** the [temp_store_directory pragma] always assumes that any string +** that this variable points to is held in memory obtained from +** [sqlite3_malloc] and the pragma may attempt to free that memory +** using [sqlite3_free]. +** Hence, if this variable is modified directly, either it should be +** made NULL or made to point to memory obtained from [sqlite3_malloc] +** or else the use of the [temp_store_directory pragma] should be avoided. +** Except when requested by the [temp_store_directory pragma], SQLite +** does not free the memory that sqlite3_temp_directory points to. If +** the application wants that memory to be freed, it must do +** so itself, taking care to only do so after all [database connection] +** objects have been destroyed. +** +** Note to Windows Runtime users: The temporary directory must be set +** prior to calling [sqlite3_open] or [sqlite3_open_v2]. Otherwise, various +** features that require the use of temporary files may fail. Here is an +** example of how to do this using C++ with the Windows Runtime: +** +**
    +** LPCWSTR zPath = Windows::Storage::ApplicationData::Current->
    +**       TemporaryFolder->Path->Data();
    +** char zPathBuf[MAX_PATH + 1];
    +** memset(zPathBuf, 0, sizeof(zPathBuf));
    +** WideCharToMultiByte(CP_UTF8, 0, zPath, -1, zPathBuf, sizeof(zPathBuf),
    +**       NULL, NULL);
    +** sqlite3_temp_directory = sqlite3_mprintf("%s", zPathBuf);
    +** 
    +*/ +SQLITE_API SQLITE_EXTERN char *sqlite3_temp_directory; + +/* +** CAPI3REF: Name Of The Folder Holding Database Files +** +** ^(If this global variable is made to point to a string which is +** the name of a folder (a.k.a. directory), then all database files +** specified with a relative pathname and created or accessed by +** SQLite when using a built-in windows [sqlite3_vfs | VFS] will be assumed +** to be relative to that directory.)^ ^If this variable is a NULL +** pointer, then SQLite assumes that all database files specified +** with a relative pathname are relative to the current directory +** for the process. Only the windows VFS makes use of this global +** variable; it is ignored by the unix VFS. +** +** Changing the value of this variable while a database connection is +** open can result in a corrupt database. +** +** It is not safe to read or modify this variable in more than one +** thread at a time. It is not safe to read or modify this variable +** if a [database connection] is being used at the same time in a separate +** thread. +** It is intended that this variable be set once +** as part of process initialization and before any SQLite interface +** routines have been called and that this variable remain unchanged +** thereafter. +** +** ^The [data_store_directory pragma] may modify this variable and cause +** it to point to memory obtained from [sqlite3_malloc]. ^Furthermore, +** the [data_store_directory pragma] always assumes that any string +** that this variable points to is held in memory obtained from +** [sqlite3_malloc] and the pragma may attempt to free that memory +** using [sqlite3_free]. +** Hence, if this variable is modified directly, either it should be +** made NULL or made to point to memory obtained from [sqlite3_malloc] +** or else the use of the [data_store_directory pragma] should be avoided. +*/ +SQLITE_API SQLITE_EXTERN char *sqlite3_data_directory; + +/* +** CAPI3REF: Win32 Specific Interface +** +** These interfaces are available only on Windows. The +** [sqlite3_win32_set_directory] interface is used to set the value associated +** with the [sqlite3_temp_directory] or [sqlite3_data_directory] variable, to +** zValue, depending on the value of the type parameter. The zValue parameter +** should be NULL to cause the previous value to be freed via [sqlite3_free]; +** a non-NULL value will be copied into memory obtained from [sqlite3_malloc] +** prior to being used. The [sqlite3_win32_set_directory] interface returns +** [SQLITE_OK] to indicate success, [SQLITE_ERROR] if the type is unsupported, +** or [SQLITE_NOMEM] if memory could not be allocated. The value of the +** [sqlite3_data_directory] variable is intended to act as a replacement for +** the current directory on the sub-platforms of Win32 where that concept is +** not present, e.g. WinRT and UWP. The [sqlite3_win32_set_directory8] and +** [sqlite3_win32_set_directory16] interfaces behave exactly the same as the +** sqlite3_win32_set_directory interface except the string parameter must be +** UTF-8 or UTF-16, respectively. +*/ +SQLITE_API int sqlite3_win32_set_directory( + unsigned long type, /* Identifier for directory being set or reset */ + void *zValue /* New value for directory being set or reset */ +); +SQLITE_API int sqlite3_win32_set_directory8(unsigned long type, const char *zValue); +SQLITE_API int sqlite3_win32_set_directory16(unsigned long type, const void *zValue); + +/* +** CAPI3REF: Win32 Directory Types +** +** These macros are only available on Windows. They define the allowed values +** for the type argument to the [sqlite3_win32_set_directory] interface. +*/ +#define SQLITE_WIN32_DATA_DIRECTORY_TYPE 1 +#define SQLITE_WIN32_TEMP_DIRECTORY_TYPE 2 + +/* +** CAPI3REF: Test For Auto-Commit Mode +** KEYWORDS: {autocommit mode} +** METHOD: sqlite3 +** +** ^The sqlite3_get_autocommit() interface returns non-zero or +** zero if the given database connection is or is not in autocommit mode, +** respectively. ^Autocommit mode is on by default. +** ^Autocommit mode is disabled by a [BEGIN] statement. +** ^Autocommit mode is re-enabled by a [COMMIT] or [ROLLBACK]. +** +** If certain kinds of errors occur on a statement within a multi-statement +** transaction (errors including [SQLITE_FULL], [SQLITE_IOERR], +** [SQLITE_NOMEM], [SQLITE_BUSY], and [SQLITE_INTERRUPT]) then the +** transaction might be rolled back automatically. The only way to +** find out whether SQLite automatically rolled back the transaction after +** an error is to use this function. +** +** If another thread changes the autocommit status of the database +** connection while this routine is running, then the return value +** is undefined. +*/ +SQLITE_API int sqlite3_get_autocommit(sqlite3*); + +/* +** CAPI3REF: Find The Database Handle Of A Prepared Statement +** METHOD: sqlite3_stmt +** +** ^The sqlite3_db_handle interface returns the [database connection] handle +** to which a [prepared statement] belongs. ^The [database connection] +** returned by sqlite3_db_handle is the same [database connection] +** that was the first argument +** to the [sqlite3_prepare_v2()] call (or its variants) that was used to +** create the statement in the first place. +*/ +SQLITE_API sqlite3 *sqlite3_db_handle(sqlite3_stmt*); + +/* +** CAPI3REF: Return The Filename For A Database Connection +** METHOD: sqlite3 +** +** ^The sqlite3_db_filename(D,N) interface returns a pointer to the filename +** associated with database N of connection D. +** ^If there is no attached database N on the database +** connection D, or if database N is a temporary or in-memory database, then +** this function will return either a NULL pointer or an empty string. +** +** ^The string value returned by this routine is owned and managed by +** the database connection. ^The value will be valid until the database N +** is [DETACH]-ed or until the database connection closes. +** +** ^The filename returned by this function is the output of the +** xFullPathname method of the [VFS]. ^In other words, the filename +** will be an absolute pathname, even if the filename used +** to open the database originally was a URI or relative pathname. +** +** If the filename pointer returned by this routine is not NULL, then it +** can be used as the filename input parameter to these routines: +**
      +**
    • [sqlite3_uri_parameter()] +**
    • [sqlite3_uri_boolean()] +**
    • [sqlite3_uri_int64()] +**
    • [sqlite3_filename_database()] +**
    • [sqlite3_filename_journal()] +**
    • [sqlite3_filename_wal()] +**
    +*/ +SQLITE_API const char *sqlite3_db_filename(sqlite3 *db, const char *zDbName); + +/* +** CAPI3REF: Determine if a database is read-only +** METHOD: sqlite3 +** +** ^The sqlite3_db_readonly(D,N) interface returns 1 if the database N +** of connection D is read-only, 0 if it is read/write, or -1 if N is not +** the name of a database on connection D. +*/ +SQLITE_API int sqlite3_db_readonly(sqlite3 *db, const char *zDbName); + +/* +** CAPI3REF: Determine the transaction state of a database +** METHOD: sqlite3 +** +** ^The sqlite3_txn_state(D,S) interface returns the current +** [transaction state] of schema S in database connection D. ^If S is NULL, +** then the highest transaction state of any schema on database connection D +** is returned. Transaction states are (in order of lowest to highest): +**
      +**
    1. SQLITE_TXN_NONE +**
    2. SQLITE_TXN_READ +**
    3. SQLITE_TXN_WRITE +**
    +** ^If the S argument to sqlite3_txn_state(D,S) is not the name of +** a valid schema, then -1 is returned. +*/ +SQLITE_API int sqlite3_txn_state(sqlite3*,const char *zSchema); + +/* +** CAPI3REF: Allowed return values from [sqlite3_txn_state()] +** KEYWORDS: {transaction state} +** +** These constants define the current transaction state of a database file. +** ^The [sqlite3_txn_state(D,S)] interface returns one of these +** constants in order to describe the transaction state of schema S +** in [database connection] D. +** +**
    +** [[SQLITE_TXN_NONE]]
    SQLITE_TXN_NONE
    +**
    The SQLITE_TXN_NONE state means that no transaction is currently +** pending.
    +** +** [[SQLITE_TXN_READ]]
    SQLITE_TXN_READ
    +**
    The SQLITE_TXN_READ state means that the database is currently +** in a read transaction. Content has been read from the database file +** but nothing in the database file has changed. The transaction state +** will advanced to SQLITE_TXN_WRITE if any changes occur and there are +** no other conflicting concurrent write transactions. The transaction +** state will revert to SQLITE_TXN_NONE following a [ROLLBACK] or +** [COMMIT].
    +** +** [[SQLITE_TXN_WRITE]]
    SQLITE_TXN_WRITE
    +**
    The SQLITE_TXN_WRITE state means that the database is currently +** in a write transaction. Content has been written to the database file +** but has not yet committed. The transaction state will change to +** to SQLITE_TXN_NONE at the next [ROLLBACK] or [COMMIT].
    +*/ +#define SQLITE_TXN_NONE 0 +#define SQLITE_TXN_READ 1 +#define SQLITE_TXN_WRITE 2 + +/* +** CAPI3REF: Find the next prepared statement +** METHOD: sqlite3 +** +** ^This interface returns a pointer to the next [prepared statement] after +** pStmt associated with the [database connection] pDb. ^If pStmt is NULL +** then this interface returns a pointer to the first prepared statement +** associated with the database connection pDb. ^If no prepared statement +** satisfies the conditions of this routine, it returns NULL. +** +** The [database connection] pointer D in a call to +** [sqlite3_next_stmt(D,S)] must refer to an open database +** connection and in particular must not be a NULL pointer. +*/ +SQLITE_API sqlite3_stmt *sqlite3_next_stmt(sqlite3 *pDb, sqlite3_stmt *pStmt); + +/* +** CAPI3REF: Commit And Rollback Notification Callbacks +** METHOD: sqlite3 +** +** ^The sqlite3_commit_hook() interface registers a callback +** function to be invoked whenever a transaction is [COMMIT | committed]. +** ^Any callback set by a previous call to sqlite3_commit_hook() +** for the same database connection is overridden. +** ^The sqlite3_rollback_hook() interface registers a callback +** function to be invoked whenever a transaction is [ROLLBACK | rolled back]. +** ^Any callback set by a previous call to sqlite3_rollback_hook() +** for the same database connection is overridden. +** ^The pArg argument is passed through to the callback. +** ^If the callback on a commit hook function returns non-zero, +** then the commit is converted into a rollback. +** +** ^The sqlite3_commit_hook(D,C,P) and sqlite3_rollback_hook(D,C,P) functions +** return the P argument from the previous call of the same function +** on the same [database connection] D, or NULL for +** the first call for each function on D. +** +** The commit and rollback hook callbacks are not reentrant. +** The callback implementation must not do anything that will modify +** the database connection that invoked the callback. Any actions +** to modify the database connection must be deferred until after the +** completion of the [sqlite3_step()] call that triggered the commit +** or rollback hook in the first place. +** Note that running any other SQL statements, including SELECT statements, +** or merely calling [sqlite3_prepare_v2()] and [sqlite3_step()] will modify +** the database connections for the meaning of "modify" in this paragraph. +** +** ^Registering a NULL function disables the callback. +** +** ^When the commit hook callback routine returns zero, the [COMMIT] +** operation is allowed to continue normally. ^If the commit hook +** returns non-zero, then the [COMMIT] is converted into a [ROLLBACK]. +** ^The rollback hook is invoked on a rollback that results from a commit +** hook returning non-zero, just as it would be with any other rollback. +** +** ^For the purposes of this API, a transaction is said to have been +** rolled back if an explicit "ROLLBACK" statement is executed, or +** an error or constraint causes an implicit rollback to occur. +** ^The rollback callback is not invoked if a transaction is +** automatically rolled back because the database connection is closed. +** +** See also the [sqlite3_update_hook()] interface. +*/ +SQLITE_API void *sqlite3_commit_hook(sqlite3*, int(*)(void*), void*); +SQLITE_API void *sqlite3_rollback_hook(sqlite3*, void(*)(void *), void*); + +/* +** CAPI3REF: Autovacuum Compaction Amount Callback +** METHOD: sqlite3 +** +** ^The sqlite3_autovacuum_pages(D,C,P,X) interface registers a callback +** function C that is invoked prior to each autovacuum of the database +** file. ^The callback is passed a copy of the generic data pointer (P), +** the schema-name of the attached database that is being autovacuumed, +** the the size of the database file in pages, the number of free pages, +** and the number of bytes per page, respectively. The callback should +** return the number of free pages that should be removed by the +** autovacuum. ^If the callback returns zero, then no autovacuum happens. +** ^If the value returned is greater than or equal to the number of +** free pages, then a complete autovacuum happens. +** +**

    ^If there are multiple ATTACH-ed database files that are being +** modified as part of a transaction commit, then the autovacuum pages +** callback is invoked separately for each file. +** +**

    The callback is not reentrant. The callback function should +** not attempt to invoke any other SQLite interface. If it does, bad +** things may happen, including segmentation faults and corrupt database +** files. The callback function should be a simple function that +** does some arithmetic on its input parameters and returns a result. +** +** ^The X parameter to sqlite3_autovacuum_pages(D,C,P,X) is an optional +** destructor for the P parameter. ^If X is not NULL, then X(P) is +** invoked whenever the database connection closes or when the callback +** is overwritten by another invocation of sqlite3_autovacuum_pages(). +** +**

    ^There is only one autovacuum pages callback per database connection. +** ^Each call to the sqlite3_autovacuum_pages() interface overrides all +** previous invocations for that database connection. ^If the callback +** argument (C) to sqlite3_autovacuum_pages(D,C,P,X) is a NULL pointer, +** then the autovacuum steps callback is cancelled. The return value +** from sqlite3_autovacuum_pages() is normally SQLITE_OK, but might +** be some other error code if something goes wrong. The current +** implementation will only return SQLITE_OK or SQLITE_MISUSE, but other +** return codes might be added in future releases. +** +**

    If no autovacuum pages callback is specified (the usual case) or +** a NULL pointer is provided for the callback, +** then the default behavior is to vacuum all free pages. So, in other +** words, the default behavior is the same as if the callback function +** were something like this: +** +**

    +**     unsigned int demonstration_autovac_pages_callback(
    +**       void *pClientData,
    +**       const char *zSchema,
    +**       unsigned int nDbPage,
    +**       unsigned int nFreePage,
    +**       unsigned int nBytePerPage
    +**     ){
    +**       return nFreePage;
    +**     }
    +** 
    +*/ +SQLITE_API int sqlite3_autovacuum_pages( + sqlite3 *db, + unsigned int(*)(void*,const char*,unsigned int,unsigned int,unsigned int), + void*, + void(*)(void*) +); + + +/* +** CAPI3REF: Data Change Notification Callbacks +** METHOD: sqlite3 +** +** ^The sqlite3_update_hook() interface registers a callback function +** with the [database connection] identified by the first argument +** to be invoked whenever a row is updated, inserted or deleted in +** a [rowid table]. +** ^Any callback set by a previous call to this function +** for the same database connection is overridden. +** +** ^The second argument is a pointer to the function to invoke when a +** row is updated, inserted or deleted in a rowid table. +** ^The first argument to the callback is a copy of the third argument +** to sqlite3_update_hook(). +** ^The second callback argument is one of [SQLITE_INSERT], [SQLITE_DELETE], +** or [SQLITE_UPDATE], depending on the operation that caused the callback +** to be invoked. +** ^The third and fourth arguments to the callback contain pointers to the +** database and table name containing the affected row. +** ^The final callback parameter is the [rowid] of the row. +** ^In the case of an update, this is the [rowid] after the update takes place. +** +** ^(The update hook is not invoked when internal system tables are +** modified (i.e. sqlite_sequence).)^ +** ^The update hook is not invoked when [WITHOUT ROWID] tables are modified. +** +** ^In the current implementation, the update hook +** is not invoked when conflicting rows are deleted because of an +** [ON CONFLICT | ON CONFLICT REPLACE] clause. ^Nor is the update hook +** invoked when rows are deleted using the [truncate optimization]. +** The exceptions defined in this paragraph might change in a future +** release of SQLite. +** +** The update hook implementation must not do anything that will modify +** the database connection that invoked the update hook. Any actions +** to modify the database connection must be deferred until after the +** completion of the [sqlite3_step()] call that triggered the update hook. +** Note that [sqlite3_prepare_v2()] and [sqlite3_step()] both modify their +** database connections for the meaning of "modify" in this paragraph. +** +** ^The sqlite3_update_hook(D,C,P) function +** returns the P argument from the previous call +** on the same [database connection] D, or NULL for +** the first call on D. +** +** See also the [sqlite3_commit_hook()], [sqlite3_rollback_hook()], +** and [sqlite3_preupdate_hook()] interfaces. +*/ +SQLITE_API void *sqlite3_update_hook( + sqlite3*, + void(*)(void *,int ,char const *,char const *,sqlite3_int64), + void* +); + +/* +** CAPI3REF: Enable Or Disable Shared Pager Cache +** +** ^(This routine enables or disables the sharing of the database cache +** and schema data structures between [database connection | connections] +** to the same database. Sharing is enabled if the argument is true +** and disabled if the argument is false.)^ +** +** ^Cache sharing is enabled and disabled for an entire process. +** This is a change as of SQLite [version 3.5.0] ([dateof:3.5.0]). +** In prior versions of SQLite, +** sharing was enabled or disabled for each thread separately. +** +** ^(The cache sharing mode set by this interface effects all subsequent +** calls to [sqlite3_open()], [sqlite3_open_v2()], and [sqlite3_open16()]. +** Existing database connections continue to use the sharing mode +** that was in effect at the time they were opened.)^ +** +** ^(This routine returns [SQLITE_OK] if shared cache was enabled or disabled +** successfully. An [error code] is returned otherwise.)^ +** +** ^Shared cache is disabled by default. It is recommended that it stay +** that way. In other words, do not use this routine. This interface +** continues to be provided for historical compatibility, but its use is +** discouraged. Any use of shared cache is discouraged. If shared cache +** must be used, it is recommended that shared cache only be enabled for +** individual database connections using the [sqlite3_open_v2()] interface +** with the [SQLITE_OPEN_SHAREDCACHE] flag. +** +** Note: This method is disabled on MacOS X 10.7 and iOS version 5.0 +** and will always return SQLITE_MISUSE. On those systems, +** shared cache mode should be enabled per-database connection via +** [sqlite3_open_v2()] with [SQLITE_OPEN_SHAREDCACHE]. +** +** This interface is threadsafe on processors where writing a +** 32-bit integer is atomic. +** +** See Also: [SQLite Shared-Cache Mode] +*/ +SQLITE_API int sqlite3_enable_shared_cache(int); + +/* +** CAPI3REF: Attempt To Free Heap Memory +** +** ^The sqlite3_release_memory() interface attempts to free N bytes +** of heap memory by deallocating non-essential memory allocations +** held by the database library. Memory used to cache database +** pages to improve performance is an example of non-essential memory. +** ^sqlite3_release_memory() returns the number of bytes actually freed, +** which might be more or less than the amount requested. +** ^The sqlite3_release_memory() routine is a no-op returning zero +** if SQLite is not compiled with [SQLITE_ENABLE_MEMORY_MANAGEMENT]. +** +** See also: [sqlite3_db_release_memory()] +*/ +SQLITE_API int sqlite3_release_memory(int); + +/* +** CAPI3REF: Free Memory Used By A Database Connection +** METHOD: sqlite3 +** +** ^The sqlite3_db_release_memory(D) interface attempts to free as much heap +** memory as possible from database connection D. Unlike the +** [sqlite3_release_memory()] interface, this interface is in effect even +** when the [SQLITE_ENABLE_MEMORY_MANAGEMENT] compile-time option is +** omitted. +** +** See also: [sqlite3_release_memory()] +*/ +SQLITE_API int sqlite3_db_release_memory(sqlite3*); + +/* +** CAPI3REF: Impose A Limit On Heap Size +** +** These interfaces impose limits on the amount of heap memory that will be +** by all database connections within a single process. +** +** ^The sqlite3_soft_heap_limit64() interface sets and/or queries the +** soft limit on the amount of heap memory that may be allocated by SQLite. +** ^SQLite strives to keep heap memory utilization below the soft heap +** limit by reducing the number of pages held in the page cache +** as heap memory usages approaches the limit. +** ^The soft heap limit is "soft" because even though SQLite strives to stay +** below the limit, it will exceed the limit rather than generate +** an [SQLITE_NOMEM] error. In other words, the soft heap limit +** is advisory only. +** +** ^The sqlite3_hard_heap_limit64(N) interface sets a hard upper bound of +** N bytes on the amount of memory that will be allocated. ^The +** sqlite3_hard_heap_limit64(N) interface is similar to +** sqlite3_soft_heap_limit64(N) except that memory allocations will fail +** when the hard heap limit is reached. +** +** ^The return value from both sqlite3_soft_heap_limit64() and +** sqlite3_hard_heap_limit64() is the size of +** the heap limit prior to the call, or negative in the case of an +** error. ^If the argument N is negative +** then no change is made to the heap limit. Hence, the current +** size of heap limits can be determined by invoking +** sqlite3_soft_heap_limit64(-1) or sqlite3_hard_heap_limit(-1). +** +** ^Setting the heap limits to zero disables the heap limiter mechanism. +** +** ^The soft heap limit may not be greater than the hard heap limit. +** ^If the hard heap limit is enabled and if sqlite3_soft_heap_limit(N) +** is invoked with a value of N that is greater than the hard heap limit, +** the the soft heap limit is set to the value of the hard heap limit. +** ^The soft heap limit is automatically enabled whenever the hard heap +** limit is enabled. ^When sqlite3_hard_heap_limit64(N) is invoked and +** the soft heap limit is outside the range of 1..N, then the soft heap +** limit is set to N. ^Invoking sqlite3_soft_heap_limit64(0) when the +** hard heap limit is enabled makes the soft heap limit equal to the +** hard heap limit. +** +** The memory allocation limits can also be adjusted using +** [PRAGMA soft_heap_limit] and [PRAGMA hard_heap_limit]. +** +** ^(The heap limits are not enforced in the current implementation +** if one or more of following conditions are true: +** +**
      +**
    • The limit value is set to zero. +**
    • Memory accounting is disabled using a combination of the +** [sqlite3_config]([SQLITE_CONFIG_MEMSTATUS],...) start-time option and +** the [SQLITE_DEFAULT_MEMSTATUS] compile-time option. +**
    • An alternative page cache implementation is specified using +** [sqlite3_config]([SQLITE_CONFIG_PCACHE2],...). +**
    • The page cache allocates from its own memory pool supplied +** by [sqlite3_config]([SQLITE_CONFIG_PAGECACHE],...) rather than +** from the heap. +**
    )^ +** +** The circumstances under which SQLite will enforce the heap limits may +** changes in future releases of SQLite. +*/ +SQLITE_API sqlite3_int64 sqlite3_soft_heap_limit64(sqlite3_int64 N); +SQLITE_API sqlite3_int64 sqlite3_hard_heap_limit64(sqlite3_int64 N); + +/* +** CAPI3REF: Deprecated Soft Heap Limit Interface +** DEPRECATED +** +** This is a deprecated version of the [sqlite3_soft_heap_limit64()] +** interface. This routine is provided for historical compatibility +** only. All new applications should use the +** [sqlite3_soft_heap_limit64()] interface rather than this one. +*/ +SQLITE_API SQLITE_DEPRECATED void sqlite3_soft_heap_limit(int N); + + +/* +** CAPI3REF: Extract Metadata About A Column Of A Table +** METHOD: sqlite3 +** +** ^(The sqlite3_table_column_metadata(X,D,T,C,....) routine returns +** information about column C of table T in database D +** on [database connection] X.)^ ^The sqlite3_table_column_metadata() +** interface returns SQLITE_OK and fills in the non-NULL pointers in +** the final five arguments with appropriate values if the specified +** column exists. ^The sqlite3_table_column_metadata() interface returns +** SQLITE_ERROR if the specified column does not exist. +** ^If the column-name parameter to sqlite3_table_column_metadata() is a +** NULL pointer, then this routine simply checks for the existence of the +** table and returns SQLITE_OK if the table exists and SQLITE_ERROR if it +** does not. If the table name parameter T in a call to +** sqlite3_table_column_metadata(X,D,T,C,...) is NULL then the result is +** undefined behavior. +** +** ^The column is identified by the second, third and fourth parameters to +** this function. ^(The second parameter is either the name of the database +** (i.e. "main", "temp", or an attached database) containing the specified +** table or NULL.)^ ^If it is NULL, then all attached databases are searched +** for the table using the same algorithm used by the database engine to +** resolve unqualified table references. +** +** ^The third and fourth parameters to this function are the table and column +** name of the desired column, respectively. +** +** ^Metadata is returned by writing to the memory locations passed as the 5th +** and subsequent parameters to this function. ^Any of these arguments may be +** NULL, in which case the corresponding element of metadata is omitted. +** +** ^(
    +** +**
    Parameter Output
    Type
    Description +** +**
    5th const char* Data type +**
    6th const char* Name of default collation sequence +**
    7th int True if column has a NOT NULL constraint +**
    8th int True if column is part of the PRIMARY KEY +**
    9th int True if column is [AUTOINCREMENT] +**
    +**
    )^ +** +** ^The memory pointed to by the character pointers returned for the +** declaration type and collation sequence is valid until the next +** call to any SQLite API function. +** +** ^If the specified table is actually a view, an [error code] is returned. +** +** ^If the specified column is "rowid", "oid" or "_rowid_" and the table +** is not a [WITHOUT ROWID] table and an +** [INTEGER PRIMARY KEY] column has been explicitly declared, then the output +** parameters are set for the explicitly declared column. ^(If there is no +** [INTEGER PRIMARY KEY] column, then the outputs +** for the [rowid] are set as follows: +** +**
    +**     data type: "INTEGER"
    +**     collation sequence: "BINARY"
    +**     not null: 0
    +**     primary key: 1
    +**     auto increment: 0
    +** 
    )^ +** +** ^This function causes all database schemas to be read from disk and +** parsed, if that has not already been done, and returns an error if +** any errors are encountered while loading the schema. +*/ +SQLITE_API int sqlite3_table_column_metadata( + sqlite3 *db, /* Connection handle */ + const char *zDbName, /* Database name or NULL */ + const char *zTableName, /* Table name */ + const char *zColumnName, /* Column name */ + char const **pzDataType, /* OUTPUT: Declared data type */ + char const **pzCollSeq, /* OUTPUT: Collation sequence name */ + int *pNotNull, /* OUTPUT: True if NOT NULL constraint exists */ + int *pPrimaryKey, /* OUTPUT: True if column part of PK */ + int *pAutoinc /* OUTPUT: True if column is auto-increment */ +); + +/* +** CAPI3REF: Load An Extension +** METHOD: sqlite3 +** +** ^This interface loads an SQLite extension library from the named file. +** +** ^The sqlite3_load_extension() interface attempts to load an +** [SQLite extension] library contained in the file zFile. If +** the file cannot be loaded directly, attempts are made to load +** with various operating-system specific extensions added. +** So for example, if "samplelib" cannot be loaded, then names like +** "samplelib.so" or "samplelib.dylib" or "samplelib.dll" might +** be tried also. +** +** ^The entry point is zProc. +** ^(zProc may be 0, in which case SQLite will try to come up with an +** entry point name on its own. It first tries "sqlite3_extension_init". +** If that does not work, it constructs a name "sqlite3_X_init" where the +** X is consists of the lower-case equivalent of all ASCII alphabetic +** characters in the filename from the last "/" to the first following +** "." and omitting any initial "lib".)^ +** ^The sqlite3_load_extension() interface returns +** [SQLITE_OK] on success and [SQLITE_ERROR] if something goes wrong. +** ^If an error occurs and pzErrMsg is not 0, then the +** [sqlite3_load_extension()] interface shall attempt to +** fill *pzErrMsg with error message text stored in memory +** obtained from [sqlite3_malloc()]. The calling function +** should free this memory by calling [sqlite3_free()]. +** +** ^Extension loading must be enabled using +** [sqlite3_enable_load_extension()] or +** [sqlite3_db_config](db,[SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION],1,NULL) +** prior to calling this API, +** otherwise an error will be returned. +** +** Security warning: It is recommended that the +** [SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION] method be used to enable only this +** interface. The use of the [sqlite3_enable_load_extension()] interface +** should be avoided. This will keep the SQL function [load_extension()] +** disabled and prevent SQL injections from giving attackers +** access to extension loading capabilities. +** +** See also the [load_extension() SQL function]. +*/ +SQLITE_API int sqlite3_load_extension( + sqlite3 *db, /* Load the extension into this database connection */ + const char *zFile, /* Name of the shared library containing extension */ + const char *zProc, /* Entry point. Derived from zFile if 0 */ + char **pzErrMsg /* Put error message here if not 0 */ +); + +/* +** CAPI3REF: Enable Or Disable Extension Loading +** METHOD: sqlite3 +** +** ^So as not to open security holes in older applications that are +** unprepared to deal with [extension loading], and as a means of disabling +** [extension loading] while evaluating user-entered SQL, the following API +** is provided to turn the [sqlite3_load_extension()] mechanism on and off. +** +** ^Extension loading is off by default. +** ^Call the sqlite3_enable_load_extension() routine with onoff==1 +** to turn extension loading on and call it with onoff==0 to turn +** it back off again. +** +** ^This interface enables or disables both the C-API +** [sqlite3_load_extension()] and the SQL function [load_extension()]. +** ^(Use [sqlite3_db_config](db,[SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION],..) +** to enable or disable only the C-API.)^ +** +** Security warning: It is recommended that extension loading +** be enabled using the [SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION] method +** rather than this interface, so the [load_extension()] SQL function +** remains disabled. This will prevent SQL injections from giving attackers +** access to extension loading capabilities. +*/ +SQLITE_API int sqlite3_enable_load_extension(sqlite3 *db, int onoff); + +/* +** CAPI3REF: Automatically Load Statically Linked Extensions +** +** ^This interface causes the xEntryPoint() function to be invoked for +** each new [database connection] that is created. The idea here is that +** xEntryPoint() is the entry point for a statically linked [SQLite extension] +** that is to be automatically loaded into all new database connections. +** +** ^(Even though the function prototype shows that xEntryPoint() takes +** no arguments and returns void, SQLite invokes xEntryPoint() with three +** arguments and expects an integer result as if the signature of the +** entry point where as follows: +** +**
    +**    int xEntryPoint(
    +**      sqlite3 *db,
    +**      const char **pzErrMsg,
    +**      const struct sqlite3_api_routines *pThunk
    +**    );
    +** 
    )^ +** +** If the xEntryPoint routine encounters an error, it should make *pzErrMsg +** point to an appropriate error message (obtained from [sqlite3_mprintf()]) +** and return an appropriate [error code]. ^SQLite ensures that *pzErrMsg +** is NULL before calling the xEntryPoint(). ^SQLite will invoke +** [sqlite3_free()] on *pzErrMsg after xEntryPoint() returns. ^If any +** xEntryPoint() returns an error, the [sqlite3_open()], [sqlite3_open16()], +** or [sqlite3_open_v2()] call that provoked the xEntryPoint() will fail. +** +** ^Calling sqlite3_auto_extension(X) with an entry point X that is already +** on the list of automatic extensions is a harmless no-op. ^No entry point +** will be called more than once for each database connection that is opened. +** +** See also: [sqlite3_reset_auto_extension()] +** and [sqlite3_cancel_auto_extension()] +*/ +SQLITE_API int sqlite3_auto_extension(void(*xEntryPoint)(void)); + +/* +** CAPI3REF: Cancel Automatic Extension Loading +** +** ^The [sqlite3_cancel_auto_extension(X)] interface unregisters the +** initialization routine X that was registered using a prior call to +** [sqlite3_auto_extension(X)]. ^The [sqlite3_cancel_auto_extension(X)] +** routine returns 1 if initialization routine X was successfully +** unregistered and it returns 0 if X was not on the list of initialization +** routines. +*/ +SQLITE_API int sqlite3_cancel_auto_extension(void(*xEntryPoint)(void)); + +/* +** CAPI3REF: Reset Automatic Extension Loading +** +** ^This interface disables all automatic extensions previously +** registered using [sqlite3_auto_extension()]. +*/ +SQLITE_API void sqlite3_reset_auto_extension(void); + +/* +** The interface to the virtual-table mechanism is currently considered +** to be experimental. The interface might change in incompatible ways. +** If this is a problem for you, do not use the interface at this time. +** +** When the virtual-table mechanism stabilizes, we will declare the +** interface fixed, support it indefinitely, and remove this comment. +*/ + +/* +** Structures used by the virtual table interface +*/ +typedef struct sqlite3_vtab sqlite3_vtab; +typedef struct sqlite3_index_info sqlite3_index_info; +typedef struct sqlite3_vtab_cursor sqlite3_vtab_cursor; +typedef struct sqlite3_module sqlite3_module; + +/* +** CAPI3REF: Virtual Table Object +** KEYWORDS: sqlite3_module {virtual table module} +** +** This structure, sometimes called a "virtual table module", +** defines the implementation of a [virtual table]. +** This structure consists mostly of methods for the module. +** +** ^A virtual table module is created by filling in a persistent +** instance of this structure and passing a pointer to that instance +** to [sqlite3_create_module()] or [sqlite3_create_module_v2()]. +** ^The registration remains valid until it is replaced by a different +** module or until the [database connection] closes. The content +** of this structure must not change while it is registered with +** any database connection. +*/ +struct sqlite3_module { + int iVersion; + int (*xCreate)(sqlite3*, void *pAux, + int argc, const char *const*argv, + sqlite3_vtab **ppVTab, char**); + int (*xConnect)(sqlite3*, void *pAux, + int argc, const char *const*argv, + sqlite3_vtab **ppVTab, char**); + int (*xBestIndex)(sqlite3_vtab *pVTab, sqlite3_index_info*); + int (*xDisconnect)(sqlite3_vtab *pVTab); + int (*xDestroy)(sqlite3_vtab *pVTab); + int (*xOpen)(sqlite3_vtab *pVTab, sqlite3_vtab_cursor **ppCursor); + int (*xClose)(sqlite3_vtab_cursor*); + int (*xFilter)(sqlite3_vtab_cursor*, int idxNum, const char *idxStr, + int argc, sqlite3_value **argv); + int (*xNext)(sqlite3_vtab_cursor*); + int (*xEof)(sqlite3_vtab_cursor*); + int (*xColumn)(sqlite3_vtab_cursor*, sqlite3_context*, int); + int (*xRowid)(sqlite3_vtab_cursor*, sqlite3_int64 *pRowid); + int (*xUpdate)(sqlite3_vtab *, int, sqlite3_value **, sqlite3_int64 *); + int (*xBegin)(sqlite3_vtab *pVTab); + int (*xSync)(sqlite3_vtab *pVTab); + int (*xCommit)(sqlite3_vtab *pVTab); + int (*xRollback)(sqlite3_vtab *pVTab); + int (*xFindFunction)(sqlite3_vtab *pVtab, int nArg, const char *zName, + void (**pxFunc)(sqlite3_context*,int,sqlite3_value**), + void **ppArg); + int (*xRename)(sqlite3_vtab *pVtab, const char *zNew); + /* The methods above are in version 1 of the sqlite_module object. Those + ** below are for version 2 and greater. */ + int (*xSavepoint)(sqlite3_vtab *pVTab, int); + int (*xRelease)(sqlite3_vtab *pVTab, int); + int (*xRollbackTo)(sqlite3_vtab *pVTab, int); + /* The methods above are in versions 1 and 2 of the sqlite_module object. + ** Those below are for version 3 and greater. */ + int (*xShadowName)(const char*); +}; + +/* +** CAPI3REF: Virtual Table Indexing Information +** KEYWORDS: sqlite3_index_info +** +** The sqlite3_index_info structure and its substructures is used as part +** of the [virtual table] interface to +** pass information into and receive the reply from the [xBestIndex] +** method of a [virtual table module]. The fields under **Inputs** are the +** inputs to xBestIndex and are read-only. xBestIndex inserts its +** results into the **Outputs** fields. +** +** ^(The aConstraint[] array records WHERE clause constraints of the form: +** +**
    column OP expr
    +** +** where OP is =, <, <=, >, or >=.)^ ^(The particular operator is +** stored in aConstraint[].op using one of the +** [SQLITE_INDEX_CONSTRAINT_EQ | SQLITE_INDEX_CONSTRAINT_ values].)^ +** ^(The index of the column is stored in +** aConstraint[].iColumn.)^ ^(aConstraint[].usable is TRUE if the +** expr on the right-hand side can be evaluated (and thus the constraint +** is usable) and false if it cannot.)^ +** +** ^The optimizer automatically inverts terms of the form "expr OP column" +** and makes other simplifications to the WHERE clause in an attempt to +** get as many WHERE clause terms into the form shown above as possible. +** ^The aConstraint[] array only reports WHERE clause terms that are +** relevant to the particular virtual table being queried. +** +** ^Information about the ORDER BY clause is stored in aOrderBy[]. +** ^Each term of aOrderBy records a column of the ORDER BY clause. +** +** The colUsed field indicates which columns of the virtual table may be +** required by the current scan. Virtual table columns are numbered from +** zero in the order in which they appear within the CREATE TABLE statement +** passed to sqlite3_declare_vtab(). For the first 63 columns (columns 0-62), +** the corresponding bit is set within the colUsed mask if the column may be +** required by SQLite. If the table has at least 64 columns and any column +** to the right of the first 63 is required, then bit 63 of colUsed is also +** set. In other words, column iCol may be required if the expression +** (colUsed & ((sqlite3_uint64)1 << (iCol>=63 ? 63 : iCol))) evaluates to +** non-zero. +** +** The [xBestIndex] method must fill aConstraintUsage[] with information +** about what parameters to pass to xFilter. ^If argvIndex>0 then +** the right-hand side of the corresponding aConstraint[] is evaluated +** and becomes the argvIndex-th entry in argv. ^(If aConstraintUsage[].omit +** is true, then the constraint is assumed to be fully handled by the +** virtual table and might not be checked again by the byte code.)^ ^(The +** aConstraintUsage[].omit flag is an optimization hint. When the omit flag +** is left in its default setting of false, the constraint will always be +** checked separately in byte code. If the omit flag is change to true, then +** the constraint may or may not be checked in byte code. In other words, +** when the omit flag is true there is no guarantee that the constraint will +** not be checked again using byte code.)^ +** +** ^The idxNum and idxPtr values are recorded and passed into the +** [xFilter] method. +** ^[sqlite3_free()] is used to free idxPtr if and only if +** needToFreeIdxPtr is true. +** +** ^The orderByConsumed means that output from [xFilter]/[xNext] will occur in +** the correct order to satisfy the ORDER BY clause so that no separate +** sorting step is required. +** +** ^The estimatedCost value is an estimate of the cost of a particular +** strategy. A cost of N indicates that the cost of the strategy is similar +** to a linear scan of an SQLite table with N rows. A cost of log(N) +** indicates that the expense of the operation is similar to that of a +** binary search on a unique indexed field of an SQLite table with N rows. +** +** ^The estimatedRows value is an estimate of the number of rows that +** will be returned by the strategy. +** +** The xBestIndex method may optionally populate the idxFlags field with a +** mask of SQLITE_INDEX_SCAN_* flags. Currently there is only one such flag - +** SQLITE_INDEX_SCAN_UNIQUE. If the xBestIndex method sets this flag, SQLite +** assumes that the strategy may visit at most one row. +** +** Additionally, if xBestIndex sets the SQLITE_INDEX_SCAN_UNIQUE flag, then +** SQLite also assumes that if a call to the xUpdate() method is made as +** part of the same statement to delete or update a virtual table row and the +** implementation returns SQLITE_CONSTRAINT, then there is no need to rollback +** any database changes. In other words, if the xUpdate() returns +** SQLITE_CONSTRAINT, the database contents must be exactly as they were +** before xUpdate was called. By contrast, if SQLITE_INDEX_SCAN_UNIQUE is not +** set and xUpdate returns SQLITE_CONSTRAINT, any database changes made by +** the xUpdate method are automatically rolled back by SQLite. +** +** IMPORTANT: The estimatedRows field was added to the sqlite3_index_info +** structure for SQLite [version 3.8.2] ([dateof:3.8.2]). +** If a virtual table extension is +** used with an SQLite version earlier than 3.8.2, the results of attempting +** to read or write the estimatedRows field are undefined (but are likely +** to include crashing the application). The estimatedRows field should +** therefore only be used if [sqlite3_libversion_number()] returns a +** value greater than or equal to 3008002. Similarly, the idxFlags field +** was added for [version 3.9.0] ([dateof:3.9.0]). +** It may therefore only be used if +** sqlite3_libversion_number() returns a value greater than or equal to +** 3009000. +*/ +struct sqlite3_index_info { + /* Inputs */ + int nConstraint; /* Number of entries in aConstraint */ + struct sqlite3_index_constraint { + int iColumn; /* Column constrained. -1 for ROWID */ + unsigned char op; /* Constraint operator */ + unsigned char usable; /* True if this constraint is usable */ + int iTermOffset; /* Used internally - xBestIndex should ignore */ + } *aConstraint; /* Table of WHERE clause constraints */ + int nOrderBy; /* Number of terms in the ORDER BY clause */ + struct sqlite3_index_orderby { + int iColumn; /* Column number */ + unsigned char desc; /* True for DESC. False for ASC. */ + } *aOrderBy; /* The ORDER BY clause */ + /* Outputs */ + struct sqlite3_index_constraint_usage { + int argvIndex; /* if >0, constraint is part of argv to xFilter */ + unsigned char omit; /* Do not code a test for this constraint */ + } *aConstraintUsage; + int idxNum; /* Number used to identify the index */ + char *idxStr; /* String, possibly obtained from sqlite3_malloc */ + int needToFreeIdxStr; /* Free idxStr using sqlite3_free() if true */ + int orderByConsumed; /* True if output is already ordered */ + double estimatedCost; /* Estimated cost of using this index */ + /* Fields below are only available in SQLite 3.8.2 and later */ + sqlite3_int64 estimatedRows; /* Estimated number of rows returned */ + /* Fields below are only available in SQLite 3.9.0 and later */ + int idxFlags; /* Mask of SQLITE_INDEX_SCAN_* flags */ + /* Fields below are only available in SQLite 3.10.0 and later */ + sqlite3_uint64 colUsed; /* Input: Mask of columns used by statement */ +}; + +/* +** CAPI3REF: Virtual Table Scan Flags +** +** Virtual table implementations are allowed to set the +** [sqlite3_index_info].idxFlags field to some combination of +** these bits. +*/ +#define SQLITE_INDEX_SCAN_UNIQUE 1 /* Scan visits at most 1 row */ + +/* +** CAPI3REF: Virtual Table Constraint Operator Codes +** +** These macros define the allowed values for the +** [sqlite3_index_info].aConstraint[].op field. Each value represents +** an operator that is part of a constraint term in the WHERE clause of +** a query that uses a [virtual table]. +** +** ^The left-hand operand of the operator is given by the corresponding +** aConstraint[].iColumn field. ^An iColumn of -1 indicates the left-hand +** operand is the rowid. +** The SQLITE_INDEX_CONSTRAINT_LIMIT and SQLITE_INDEX_CONSTRAINT_OFFSET +** operators have no left-hand operand, and so for those operators the +** corresponding aConstraint[].iColumn is meaningless and should not be +** used. +** +** All operator values from SQLITE_INDEX_CONSTRAINT_FUNCTION through +** value 255 are reserved to represent functions that are overloaded +** by the [xFindFunction|xFindFunction method] of the virtual table +** implementation. +** +** The right-hand operands for each constraint might be accessible using +** the [sqlite3_vtab_rhs_value()] interface. Usually the right-hand +** operand is only available if it appears as a single constant literal +** in the input SQL. If the right-hand operand is another column or an +** expression (even a constant expression) or a parameter, then the +** sqlite3_vtab_rhs_value() probably will not be able to extract it. +** ^The SQLITE_INDEX_CONSTRAINT_ISNULL and +** SQLITE_INDEX_CONSTRAINT_ISNOTNULL operators have no right-hand operand +** and hence calls to sqlite3_vtab_rhs_value() for those operators will +** always return SQLITE_NOTFOUND. +** +** The collating sequence to be used for comparison can be found using +** the [sqlite3_vtab_collation()] interface. For most real-world virtual +** tables, the collating sequence of constraints does not matter (for example +** because the constraints are numeric) and so the sqlite3_vtab_collation() +** interface is no commonly needed. +*/ +#define SQLITE_INDEX_CONSTRAINT_EQ 2 +#define SQLITE_INDEX_CONSTRAINT_GT 4 +#define SQLITE_INDEX_CONSTRAINT_LE 8 +#define SQLITE_INDEX_CONSTRAINT_LT 16 +#define SQLITE_INDEX_CONSTRAINT_GE 32 +#define SQLITE_INDEX_CONSTRAINT_MATCH 64 +#define SQLITE_INDEX_CONSTRAINT_LIKE 65 +#define SQLITE_INDEX_CONSTRAINT_GLOB 66 +#define SQLITE_INDEX_CONSTRAINT_REGEXP 67 +#define SQLITE_INDEX_CONSTRAINT_NE 68 +#define SQLITE_INDEX_CONSTRAINT_ISNOT 69 +#define SQLITE_INDEX_CONSTRAINT_ISNOTNULL 70 +#define SQLITE_INDEX_CONSTRAINT_ISNULL 71 +#define SQLITE_INDEX_CONSTRAINT_IS 72 +#define SQLITE_INDEX_CONSTRAINT_LIMIT 73 +#define SQLITE_INDEX_CONSTRAINT_OFFSET 74 +#define SQLITE_INDEX_CONSTRAINT_FUNCTION 150 + +/* +** CAPI3REF: Register A Virtual Table Implementation +** METHOD: sqlite3 +** +** ^These routines are used to register a new [virtual table module] name. +** ^Module names must be registered before +** creating a new [virtual table] using the module and before using a +** preexisting [virtual table] for the module. +** +** ^The module name is registered on the [database connection] specified +** by the first parameter. ^The name of the module is given by the +** second parameter. ^The third parameter is a pointer to +** the implementation of the [virtual table module]. ^The fourth +** parameter is an arbitrary client data pointer that is passed through +** into the [xCreate] and [xConnect] methods of the virtual table module +** when a new virtual table is be being created or reinitialized. +** +** ^The sqlite3_create_module_v2() interface has a fifth parameter which +** is a pointer to a destructor for the pClientData. ^SQLite will +** invoke the destructor function (if it is not NULL) when SQLite +** no longer needs the pClientData pointer. ^The destructor will also +** be invoked if the call to sqlite3_create_module_v2() fails. +** ^The sqlite3_create_module() +** interface is equivalent to sqlite3_create_module_v2() with a NULL +** destructor. +** +** ^If the third parameter (the pointer to the sqlite3_module object) is +** NULL then no new module is created and any existing modules with the +** same name are dropped. +** +** See also: [sqlite3_drop_modules()] +*/ +SQLITE_API int sqlite3_create_module( + sqlite3 *db, /* SQLite connection to register module with */ + const char *zName, /* Name of the module */ + const sqlite3_module *p, /* Methods for the module */ + void *pClientData /* Client data for xCreate/xConnect */ +); +SQLITE_API int sqlite3_create_module_v2( + sqlite3 *db, /* SQLite connection to register module with */ + const char *zName, /* Name of the module */ + const sqlite3_module *p, /* Methods for the module */ + void *pClientData, /* Client data for xCreate/xConnect */ + void(*xDestroy)(void*) /* Module destructor function */ +); + +/* +** CAPI3REF: Remove Unnecessary Virtual Table Implementations +** METHOD: sqlite3 +** +** ^The sqlite3_drop_modules(D,L) interface removes all virtual +** table modules from database connection D except those named on list L. +** The L parameter must be either NULL or a pointer to an array of pointers +** to strings where the array is terminated by a single NULL pointer. +** ^If the L parameter is NULL, then all virtual table modules are removed. +** +** See also: [sqlite3_create_module()] +*/ +SQLITE_API int sqlite3_drop_modules( + sqlite3 *db, /* Remove modules from this connection */ + const char **azKeep /* Except, do not remove the ones named here */ +); + +/* +** CAPI3REF: Virtual Table Instance Object +** KEYWORDS: sqlite3_vtab +** +** Every [virtual table module] implementation uses a subclass +** of this object to describe a particular instance +** of the [virtual table]. Each subclass will +** be tailored to the specific needs of the module implementation. +** The purpose of this superclass is to define certain fields that are +** common to all module implementations. +** +** ^Virtual tables methods can set an error message by assigning a +** string obtained from [sqlite3_mprintf()] to zErrMsg. The method should +** take care that any prior string is freed by a call to [sqlite3_free()] +** prior to assigning a new string to zErrMsg. ^After the error message +** is delivered up to the client application, the string will be automatically +** freed by sqlite3_free() and the zErrMsg field will be zeroed. +*/ +struct sqlite3_vtab { + const sqlite3_module *pModule; /* The module for this virtual table */ + int nRef; /* Number of open cursors */ + char *zErrMsg; /* Error message from sqlite3_mprintf() */ + /* Virtual table implementations will typically add additional fields */ +}; + +/* +** CAPI3REF: Virtual Table Cursor Object +** KEYWORDS: sqlite3_vtab_cursor {virtual table cursor} +** +** Every [virtual table module] implementation uses a subclass of the +** following structure to describe cursors that point into the +** [virtual table] and are used +** to loop through the virtual table. Cursors are created using the +** [sqlite3_module.xOpen | xOpen] method of the module and are destroyed +** by the [sqlite3_module.xClose | xClose] method. Cursors are used +** by the [xFilter], [xNext], [xEof], [xColumn], and [xRowid] methods +** of the module. Each module implementation will define +** the content of a cursor structure to suit its own needs. +** +** This superclass exists in order to define fields of the cursor that +** are common to all implementations. +*/ +struct sqlite3_vtab_cursor { + sqlite3_vtab *pVtab; /* Virtual table of this cursor */ + /* Virtual table implementations will typically add additional fields */ +}; + +/* +** CAPI3REF: Declare The Schema Of A Virtual Table +** +** ^The [xCreate] and [xConnect] methods of a +** [virtual table module] call this interface +** to declare the format (the names and datatypes of the columns) of +** the virtual tables they implement. +*/ +SQLITE_API int sqlite3_declare_vtab(sqlite3*, const char *zSQL); + +/* +** CAPI3REF: Overload A Function For A Virtual Table +** METHOD: sqlite3 +** +** ^(Virtual tables can provide alternative implementations of functions +** using the [xFindFunction] method of the [virtual table module]. +** But global versions of those functions +** must exist in order to be overloaded.)^ +** +** ^(This API makes sure a global version of a function with a particular +** name and number of parameters exists. If no such function exists +** before this API is called, a new function is created.)^ ^The implementation +** of the new function always causes an exception to be thrown. So +** the new function is not good for anything by itself. Its only +** purpose is to be a placeholder function that can be overloaded +** by a [virtual table]. +*/ +SQLITE_API int sqlite3_overload_function(sqlite3*, const char *zFuncName, int nArg); + +/* +** The interface to the virtual-table mechanism defined above (back up +** to a comment remarkably similar to this one) is currently considered +** to be experimental. The interface might change in incompatible ways. +** If this is a problem for you, do not use the interface at this time. +** +** When the virtual-table mechanism stabilizes, we will declare the +** interface fixed, support it indefinitely, and remove this comment. +*/ + +/* +** CAPI3REF: A Handle To An Open BLOB +** KEYWORDS: {BLOB handle} {BLOB handles} +** +** An instance of this object represents an open BLOB on which +** [sqlite3_blob_open | incremental BLOB I/O] can be performed. +** ^Objects of this type are created by [sqlite3_blob_open()] +** and destroyed by [sqlite3_blob_close()]. +** ^The [sqlite3_blob_read()] and [sqlite3_blob_write()] interfaces +** can be used to read or write small subsections of the BLOB. +** ^The [sqlite3_blob_bytes()] interface returns the size of the BLOB in bytes. +*/ +typedef struct sqlite3_blob sqlite3_blob; + +/* +** CAPI3REF: Open A BLOB For Incremental I/O +** METHOD: sqlite3 +** CONSTRUCTOR: sqlite3_blob +** +** ^(This interfaces opens a [BLOB handle | handle] to the BLOB located +** in row iRow, column zColumn, table zTable in database zDb; +** in other words, the same BLOB that would be selected by: +** +**
    +**     SELECT zColumn FROM zDb.zTable WHERE [rowid] = iRow;
    +** 
    )^ +** +** ^(Parameter zDb is not the filename that contains the database, but +** rather the symbolic name of the database. For attached databases, this is +** the name that appears after the AS keyword in the [ATTACH] statement. +** For the main database file, the database name is "main". For TEMP +** tables, the database name is "temp".)^ +** +** ^If the flags parameter is non-zero, then the BLOB is opened for read +** and write access. ^If the flags parameter is zero, the BLOB is opened for +** read-only access. +** +** ^(On success, [SQLITE_OK] is returned and the new [BLOB handle] is stored +** in *ppBlob. Otherwise an [error code] is returned and, unless the error +** code is SQLITE_MISUSE, *ppBlob is set to NULL.)^ ^This means that, provided +** the API is not misused, it is always safe to call [sqlite3_blob_close()] +** on *ppBlob after this function it returns. +** +** This function fails with SQLITE_ERROR if any of the following are true: +**
      +**
    • ^(Database zDb does not exist)^, +**
    • ^(Table zTable does not exist within database zDb)^, +**
    • ^(Table zTable is a WITHOUT ROWID table)^, +**
    • ^(Column zColumn does not exist)^, +**
    • ^(Row iRow is not present in the table)^, +**
    • ^(The specified column of row iRow contains a value that is not +** a TEXT or BLOB value)^, +**
    • ^(Column zColumn is part of an index, PRIMARY KEY or UNIQUE +** constraint and the blob is being opened for read/write access)^, +**
    • ^([foreign key constraints | Foreign key constraints] are enabled, +** column zColumn is part of a [child key] definition and the blob is +** being opened for read/write access)^. +**
    +** +** ^Unless it returns SQLITE_MISUSE, this function sets the +** [database connection] error code and message accessible via +** [sqlite3_errcode()] and [sqlite3_errmsg()] and related functions. +** +** A BLOB referenced by sqlite3_blob_open() may be read using the +** [sqlite3_blob_read()] interface and modified by using +** [sqlite3_blob_write()]. The [BLOB handle] can be moved to a +** different row of the same table using the [sqlite3_blob_reopen()] +** interface. However, the column, table, or database of a [BLOB handle] +** cannot be changed after the [BLOB handle] is opened. +** +** ^(If the row that a BLOB handle points to is modified by an +** [UPDATE], [DELETE], or by [ON CONFLICT] side-effects +** then the BLOB handle is marked as "expired". +** This is true if any column of the row is changed, even a column +** other than the one the BLOB handle is open on.)^ +** ^Calls to [sqlite3_blob_read()] and [sqlite3_blob_write()] for +** an expired BLOB handle fail with a return code of [SQLITE_ABORT]. +** ^(Changes written into a BLOB prior to the BLOB expiring are not +** rolled back by the expiration of the BLOB. Such changes will eventually +** commit if the transaction continues to completion.)^ +** +** ^Use the [sqlite3_blob_bytes()] interface to determine the size of +** the opened blob. ^The size of a blob may not be changed by this +** interface. Use the [UPDATE] SQL command to change the size of a +** blob. +** +** ^The [sqlite3_bind_zeroblob()] and [sqlite3_result_zeroblob()] interfaces +** and the built-in [zeroblob] SQL function may be used to create a +** zero-filled blob to read or write using the incremental-blob interface. +** +** To avoid a resource leak, every open [BLOB handle] should eventually +** be released by a call to [sqlite3_blob_close()]. +** +** See also: [sqlite3_blob_close()], +** [sqlite3_blob_reopen()], [sqlite3_blob_read()], +** [sqlite3_blob_bytes()], [sqlite3_blob_write()]. +*/ +SQLITE_API int sqlite3_blob_open( + sqlite3*, + const char *zDb, + const char *zTable, + const char *zColumn, + sqlite3_int64 iRow, + int flags, + sqlite3_blob **ppBlob +); + +/* +** CAPI3REF: Move a BLOB Handle to a New Row +** METHOD: sqlite3_blob +** +** ^This function is used to move an existing [BLOB handle] so that it points +** to a different row of the same database table. ^The new row is identified +** by the rowid value passed as the second argument. Only the row can be +** changed. ^The database, table and column on which the blob handle is open +** remain the same. Moving an existing [BLOB handle] to a new row is +** faster than closing the existing handle and opening a new one. +** +** ^(The new row must meet the same criteria as for [sqlite3_blob_open()] - +** it must exist and there must be either a blob or text value stored in +** the nominated column.)^ ^If the new row is not present in the table, or if +** it does not contain a blob or text value, or if another error occurs, an +** SQLite error code is returned and the blob handle is considered aborted. +** ^All subsequent calls to [sqlite3_blob_read()], [sqlite3_blob_write()] or +** [sqlite3_blob_reopen()] on an aborted blob handle immediately return +** SQLITE_ABORT. ^Calling [sqlite3_blob_bytes()] on an aborted blob handle +** always returns zero. +** +** ^This function sets the database handle error code and message. +*/ +SQLITE_API int sqlite3_blob_reopen(sqlite3_blob *, sqlite3_int64); + +/* +** CAPI3REF: Close A BLOB Handle +** DESTRUCTOR: sqlite3_blob +** +** ^This function closes an open [BLOB handle]. ^(The BLOB handle is closed +** unconditionally. Even if this routine returns an error code, the +** handle is still closed.)^ +** +** ^If the blob handle being closed was opened for read-write access, and if +** the database is in auto-commit mode and there are no other open read-write +** blob handles or active write statements, the current transaction is +** committed. ^If an error occurs while committing the transaction, an error +** code is returned and the transaction rolled back. +** +** Calling this function with an argument that is not a NULL pointer or an +** open blob handle results in undefined behaviour. ^Calling this routine +** with a null pointer (such as would be returned by a failed call to +** [sqlite3_blob_open()]) is a harmless no-op. ^Otherwise, if this function +** is passed a valid open blob handle, the values returned by the +** sqlite3_errcode() and sqlite3_errmsg() functions are set before returning. +*/ +SQLITE_API int sqlite3_blob_close(sqlite3_blob *); + +/* +** CAPI3REF: Return The Size Of An Open BLOB +** METHOD: sqlite3_blob +** +** ^Returns the size in bytes of the BLOB accessible via the +** successfully opened [BLOB handle] in its only argument. ^The +** incremental blob I/O routines can only read or overwriting existing +** blob content; they cannot change the size of a blob. +** +** This routine only works on a [BLOB handle] which has been created +** by a prior successful call to [sqlite3_blob_open()] and which has not +** been closed by [sqlite3_blob_close()]. Passing any other pointer in +** to this routine results in undefined and probably undesirable behavior. +*/ +SQLITE_API int sqlite3_blob_bytes(sqlite3_blob *); + +/* +** CAPI3REF: Read Data From A BLOB Incrementally +** METHOD: sqlite3_blob +** +** ^(This function is used to read data from an open [BLOB handle] into a +** caller-supplied buffer. N bytes of data are copied into buffer Z +** from the open BLOB, starting at offset iOffset.)^ +** +** ^If offset iOffset is less than N bytes from the end of the BLOB, +** [SQLITE_ERROR] is returned and no data is read. ^If N or iOffset is +** less than zero, [SQLITE_ERROR] is returned and no data is read. +** ^The size of the blob (and hence the maximum value of N+iOffset) +** can be determined using the [sqlite3_blob_bytes()] interface. +** +** ^An attempt to read from an expired [BLOB handle] fails with an +** error code of [SQLITE_ABORT]. +** +** ^(On success, sqlite3_blob_read() returns SQLITE_OK. +** Otherwise, an [error code] or an [extended error code] is returned.)^ +** +** This routine only works on a [BLOB handle] which has been created +** by a prior successful call to [sqlite3_blob_open()] and which has not +** been closed by [sqlite3_blob_close()]. Passing any other pointer in +** to this routine results in undefined and probably undesirable behavior. +** +** See also: [sqlite3_blob_write()]. +*/ +SQLITE_API int sqlite3_blob_read(sqlite3_blob *, void *Z, int N, int iOffset); + +/* +** CAPI3REF: Write Data Into A BLOB Incrementally +** METHOD: sqlite3_blob +** +** ^(This function is used to write data into an open [BLOB handle] from a +** caller-supplied buffer. N bytes of data are copied from the buffer Z +** into the open BLOB, starting at offset iOffset.)^ +** +** ^(On success, sqlite3_blob_write() returns SQLITE_OK. +** Otherwise, an [error code] or an [extended error code] is returned.)^ +** ^Unless SQLITE_MISUSE is returned, this function sets the +** [database connection] error code and message accessible via +** [sqlite3_errcode()] and [sqlite3_errmsg()] and related functions. +** +** ^If the [BLOB handle] passed as the first argument was not opened for +** writing (the flags parameter to [sqlite3_blob_open()] was zero), +** this function returns [SQLITE_READONLY]. +** +** This function may only modify the contents of the BLOB; it is +** not possible to increase the size of a BLOB using this API. +** ^If offset iOffset is less than N bytes from the end of the BLOB, +** [SQLITE_ERROR] is returned and no data is written. The size of the +** BLOB (and hence the maximum value of N+iOffset) can be determined +** using the [sqlite3_blob_bytes()] interface. ^If N or iOffset are less +** than zero [SQLITE_ERROR] is returned and no data is written. +** +** ^An attempt to write to an expired [BLOB handle] fails with an +** error code of [SQLITE_ABORT]. ^Writes to the BLOB that occurred +** before the [BLOB handle] expired are not rolled back by the +** expiration of the handle, though of course those changes might +** have been overwritten by the statement that expired the BLOB handle +** or by other independent statements. +** +** This routine only works on a [BLOB handle] which has been created +** by a prior successful call to [sqlite3_blob_open()] and which has not +** been closed by [sqlite3_blob_close()]. Passing any other pointer in +** to this routine results in undefined and probably undesirable behavior. +** +** See also: [sqlite3_blob_read()]. +*/ +SQLITE_API int sqlite3_blob_write(sqlite3_blob *, const void *z, int n, int iOffset); + +/* +** CAPI3REF: Virtual File System Objects +** +** A virtual filesystem (VFS) is an [sqlite3_vfs] object +** that SQLite uses to interact +** with the underlying operating system. Most SQLite builds come with a +** single default VFS that is appropriate for the host computer. +** New VFSes can be registered and existing VFSes can be unregistered. +** The following interfaces are provided. +** +** ^The sqlite3_vfs_find() interface returns a pointer to a VFS given its name. +** ^Names are case sensitive. +** ^Names are zero-terminated UTF-8 strings. +** ^If there is no match, a NULL pointer is returned. +** ^If zVfsName is NULL then the default VFS is returned. +** +** ^New VFSes are registered with sqlite3_vfs_register(). +** ^Each new VFS becomes the default VFS if the makeDflt flag is set. +** ^The same VFS can be registered multiple times without injury. +** ^To make an existing VFS into the default VFS, register it again +** with the makeDflt flag set. If two different VFSes with the +** same name are registered, the behavior is undefined. If a +** VFS is registered with a name that is NULL or an empty string, +** then the behavior is undefined. +** +** ^Unregister a VFS with the sqlite3_vfs_unregister() interface. +** ^(If the default VFS is unregistered, another VFS is chosen as +** the default. The choice for the new VFS is arbitrary.)^ +*/ +SQLITE_API sqlite3_vfs *sqlite3_vfs_find(const char *zVfsName); +SQLITE_API int sqlite3_vfs_register(sqlite3_vfs*, int makeDflt); +SQLITE_API int sqlite3_vfs_unregister(sqlite3_vfs*); + +/* +** CAPI3REF: Mutexes +** +** The SQLite core uses these routines for thread +** synchronization. Though they are intended for internal +** use by SQLite, code that links against SQLite is +** permitted to use any of these routines. +** +** The SQLite source code contains multiple implementations +** of these mutex routines. An appropriate implementation +** is selected automatically at compile-time. The following +** implementations are available in the SQLite core: +** +**
      +**
    • SQLITE_MUTEX_PTHREADS +**
    • SQLITE_MUTEX_W32 +**
    • SQLITE_MUTEX_NOOP +**
    +** +** The SQLITE_MUTEX_NOOP implementation is a set of routines +** that does no real locking and is appropriate for use in +** a single-threaded application. The SQLITE_MUTEX_PTHREADS and +** SQLITE_MUTEX_W32 implementations are appropriate for use on Unix +** and Windows. +** +** If SQLite is compiled with the SQLITE_MUTEX_APPDEF preprocessor +** macro defined (with "-DSQLITE_MUTEX_APPDEF=1"), then no mutex +** implementation is included with the library. In this case the +** application must supply a custom mutex implementation using the +** [SQLITE_CONFIG_MUTEX] option of the sqlite3_config() function +** before calling sqlite3_initialize() or any other public sqlite3_ +** function that calls sqlite3_initialize(). +** +** ^The sqlite3_mutex_alloc() routine allocates a new +** mutex and returns a pointer to it. ^The sqlite3_mutex_alloc() +** routine returns NULL if it is unable to allocate the requested +** mutex. The argument to sqlite3_mutex_alloc() must one of these +** integer constants: +** +**
      +**
    • SQLITE_MUTEX_FAST +**
    • SQLITE_MUTEX_RECURSIVE +**
    • SQLITE_MUTEX_STATIC_MAIN +**
    • SQLITE_MUTEX_STATIC_MEM +**
    • SQLITE_MUTEX_STATIC_OPEN +**
    • SQLITE_MUTEX_STATIC_PRNG +**
    • SQLITE_MUTEX_STATIC_LRU +**
    • SQLITE_MUTEX_STATIC_PMEM +**
    • SQLITE_MUTEX_STATIC_APP1 +**
    • SQLITE_MUTEX_STATIC_APP2 +**
    • SQLITE_MUTEX_STATIC_APP3 +**
    • SQLITE_MUTEX_STATIC_VFS1 +**
    • SQLITE_MUTEX_STATIC_VFS2 +**
    • SQLITE_MUTEX_STATIC_VFS3 +**
    +** +** ^The first two constants (SQLITE_MUTEX_FAST and SQLITE_MUTEX_RECURSIVE) +** cause sqlite3_mutex_alloc() to create +** a new mutex. ^The new mutex is recursive when SQLITE_MUTEX_RECURSIVE +** is used but not necessarily so when SQLITE_MUTEX_FAST is used. +** The mutex implementation does not need to make a distinction +** between SQLITE_MUTEX_RECURSIVE and SQLITE_MUTEX_FAST if it does +** not want to. SQLite will only request a recursive mutex in +** cases where it really needs one. If a faster non-recursive mutex +** implementation is available on the host platform, the mutex subsystem +** might return such a mutex in response to SQLITE_MUTEX_FAST. +** +** ^The other allowed parameters to sqlite3_mutex_alloc() (anything other +** than SQLITE_MUTEX_FAST and SQLITE_MUTEX_RECURSIVE) each return +** a pointer to a static preexisting mutex. ^Nine static mutexes are +** used by the current version of SQLite. Future versions of SQLite +** may add additional static mutexes. Static mutexes are for internal +** use by SQLite only. Applications that use SQLite mutexes should +** use only the dynamic mutexes returned by SQLITE_MUTEX_FAST or +** SQLITE_MUTEX_RECURSIVE. +** +** ^Note that if one of the dynamic mutex parameters (SQLITE_MUTEX_FAST +** or SQLITE_MUTEX_RECURSIVE) is used then sqlite3_mutex_alloc() +** returns a different mutex on every call. ^For the static +** mutex types, the same mutex is returned on every call that has +** the same type number. +** +** ^The sqlite3_mutex_free() routine deallocates a previously +** allocated dynamic mutex. Attempting to deallocate a static +** mutex results in undefined behavior. +** +** ^The sqlite3_mutex_enter() and sqlite3_mutex_try() routines attempt +** to enter a mutex. ^If another thread is already within the mutex, +** sqlite3_mutex_enter() will block and sqlite3_mutex_try() will return +** SQLITE_BUSY. ^The sqlite3_mutex_try() interface returns [SQLITE_OK] +** upon successful entry. ^(Mutexes created using +** SQLITE_MUTEX_RECURSIVE can be entered multiple times by the same thread. +** In such cases, the +** mutex must be exited an equal number of times before another thread +** can enter.)^ If the same thread tries to enter any mutex other +** than an SQLITE_MUTEX_RECURSIVE more than once, the behavior is undefined. +** +** ^(Some systems (for example, Windows 95) do not support the operation +** implemented by sqlite3_mutex_try(). On those systems, sqlite3_mutex_try() +** will always return SQLITE_BUSY. The SQLite core only ever uses +** sqlite3_mutex_try() as an optimization so this is acceptable +** behavior.)^ +** +** ^The sqlite3_mutex_leave() routine exits a mutex that was +** previously entered by the same thread. The behavior +** is undefined if the mutex is not currently entered by the +** calling thread or is not currently allocated. +** +** ^If the argument to sqlite3_mutex_enter(), sqlite3_mutex_try(), or +** sqlite3_mutex_leave() is a NULL pointer, then all three routines +** behave as no-ops. +** +** See also: [sqlite3_mutex_held()] and [sqlite3_mutex_notheld()]. +*/ +SQLITE_API sqlite3_mutex *sqlite3_mutex_alloc(int); +SQLITE_API void sqlite3_mutex_free(sqlite3_mutex*); +SQLITE_API void sqlite3_mutex_enter(sqlite3_mutex*); +SQLITE_API int sqlite3_mutex_try(sqlite3_mutex*); +SQLITE_API void sqlite3_mutex_leave(sqlite3_mutex*); + +/* +** CAPI3REF: Mutex Methods Object +** +** An instance of this structure defines the low-level routines +** used to allocate and use mutexes. +** +** Usually, the default mutex implementations provided by SQLite are +** sufficient, however the application has the option of substituting a custom +** implementation for specialized deployments or systems for which SQLite +** does not provide a suitable implementation. In this case, the application +** creates and populates an instance of this structure to pass +** to sqlite3_config() along with the [SQLITE_CONFIG_MUTEX] option. +** Additionally, an instance of this structure can be used as an +** output variable when querying the system for the current mutex +** implementation, using the [SQLITE_CONFIG_GETMUTEX] option. +** +** ^The xMutexInit method defined by this structure is invoked as +** part of system initialization by the sqlite3_initialize() function. +** ^The xMutexInit routine is called by SQLite exactly once for each +** effective call to [sqlite3_initialize()]. +** +** ^The xMutexEnd method defined by this structure is invoked as +** part of system shutdown by the sqlite3_shutdown() function. The +** implementation of this method is expected to release all outstanding +** resources obtained by the mutex methods implementation, especially +** those obtained by the xMutexInit method. ^The xMutexEnd() +** interface is invoked exactly once for each call to [sqlite3_shutdown()]. +** +** ^(The remaining seven methods defined by this structure (xMutexAlloc, +** xMutexFree, xMutexEnter, xMutexTry, xMutexLeave, xMutexHeld and +** xMutexNotheld) implement the following interfaces (respectively): +** +**
      +**
    • [sqlite3_mutex_alloc()]
    • +**
    • [sqlite3_mutex_free()]
    • +**
    • [sqlite3_mutex_enter()]
    • +**
    • [sqlite3_mutex_try()]
    • +**
    • [sqlite3_mutex_leave()]
    • +**
    • [sqlite3_mutex_held()]
    • +**
    • [sqlite3_mutex_notheld()]
    • +**
    )^ +** +** The only difference is that the public sqlite3_XXX functions enumerated +** above silently ignore any invocations that pass a NULL pointer instead +** of a valid mutex handle. The implementations of the methods defined +** by this structure are not required to handle this case. The results +** of passing a NULL pointer instead of a valid mutex handle are undefined +** (i.e. it is acceptable to provide an implementation that segfaults if +** it is passed a NULL pointer). +** +** The xMutexInit() method must be threadsafe. It must be harmless to +** invoke xMutexInit() multiple times within the same process and without +** intervening calls to xMutexEnd(). Second and subsequent calls to +** xMutexInit() must be no-ops. +** +** xMutexInit() must not use SQLite memory allocation ([sqlite3_malloc()] +** and its associates). Similarly, xMutexAlloc() must not use SQLite memory +** allocation for a static mutex. ^However xMutexAlloc() may use SQLite +** memory allocation for a fast or recursive mutex. +** +** ^SQLite will invoke the xMutexEnd() method when [sqlite3_shutdown()] is +** called, but only if the prior call to xMutexInit returned SQLITE_OK. +** If xMutexInit fails in any way, it is expected to clean up after itself +** prior to returning. +*/ +typedef struct sqlite3_mutex_methods sqlite3_mutex_methods; +struct sqlite3_mutex_methods { + int (*xMutexInit)(void); + int (*xMutexEnd)(void); + sqlite3_mutex *(*xMutexAlloc)(int); + void (*xMutexFree)(sqlite3_mutex *); + void (*xMutexEnter)(sqlite3_mutex *); + int (*xMutexTry)(sqlite3_mutex *); + void (*xMutexLeave)(sqlite3_mutex *); + int (*xMutexHeld)(sqlite3_mutex *); + int (*xMutexNotheld)(sqlite3_mutex *); +}; + +/* +** CAPI3REF: Mutex Verification Routines +** +** The sqlite3_mutex_held() and sqlite3_mutex_notheld() routines +** are intended for use inside assert() statements. The SQLite core +** never uses these routines except inside an assert() and applications +** are advised to follow the lead of the core. The SQLite core only +** provides implementations for these routines when it is compiled +** with the SQLITE_DEBUG flag. External mutex implementations +** are only required to provide these routines if SQLITE_DEBUG is +** defined and if NDEBUG is not defined. +** +** These routines should return true if the mutex in their argument +** is held or not held, respectively, by the calling thread. +** +** The implementation is not required to provide versions of these +** routines that actually work. If the implementation does not provide working +** versions of these routines, it should at least provide stubs that always +** return true so that one does not get spurious assertion failures. +** +** If the argument to sqlite3_mutex_held() is a NULL pointer then +** the routine should return 1. This seems counter-intuitive since +** clearly the mutex cannot be held if it does not exist. But +** the reason the mutex does not exist is because the build is not +** using mutexes. And we do not want the assert() containing the +** call to sqlite3_mutex_held() to fail, so a non-zero return is +** the appropriate thing to do. The sqlite3_mutex_notheld() +** interface should also return 1 when given a NULL pointer. +*/ +#ifndef NDEBUG +SQLITE_API int sqlite3_mutex_held(sqlite3_mutex*); +SQLITE_API int sqlite3_mutex_notheld(sqlite3_mutex*); +#endif + +/* +** CAPI3REF: Mutex Types +** +** The [sqlite3_mutex_alloc()] interface takes a single argument +** which is one of these integer constants. +** +** The set of static mutexes may change from one SQLite release to the +** next. Applications that override the built-in mutex logic must be +** prepared to accommodate additional static mutexes. +*/ +#define SQLITE_MUTEX_FAST 0 +#define SQLITE_MUTEX_RECURSIVE 1 +#define SQLITE_MUTEX_STATIC_MAIN 2 +#define SQLITE_MUTEX_STATIC_MEM 3 /* sqlite3_malloc() */ +#define SQLITE_MUTEX_STATIC_MEM2 4 /* NOT USED */ +#define SQLITE_MUTEX_STATIC_OPEN 4 /* sqlite3BtreeOpen() */ +#define SQLITE_MUTEX_STATIC_PRNG 5 /* sqlite3_randomness() */ +#define SQLITE_MUTEX_STATIC_LRU 6 /* lru page list */ +#define SQLITE_MUTEX_STATIC_LRU2 7 /* NOT USED */ +#define SQLITE_MUTEX_STATIC_PMEM 7 /* sqlite3PageMalloc() */ +#define SQLITE_MUTEX_STATIC_APP1 8 /* For use by application */ +#define SQLITE_MUTEX_STATIC_APP2 9 /* For use by application */ +#define SQLITE_MUTEX_STATIC_APP3 10 /* For use by application */ +#define SQLITE_MUTEX_STATIC_VFS1 11 /* For use by built-in VFS */ +#define SQLITE_MUTEX_STATIC_VFS2 12 /* For use by extension VFS */ +#define SQLITE_MUTEX_STATIC_VFS3 13 /* For use by application VFS */ + +/* Legacy compatibility: */ +#define SQLITE_MUTEX_STATIC_MASTER 2 + + +/* +** CAPI3REF: Retrieve the mutex for a database connection +** METHOD: sqlite3 +** +** ^This interface returns a pointer the [sqlite3_mutex] object that +** serializes access to the [database connection] given in the argument +** when the [threading mode] is Serialized. +** ^If the [threading mode] is Single-thread or Multi-thread then this +** routine returns a NULL pointer. +*/ +SQLITE_API sqlite3_mutex *sqlite3_db_mutex(sqlite3*); + +/* +** CAPI3REF: Low-Level Control Of Database Files +** METHOD: sqlite3 +** KEYWORDS: {file control} +** +** ^The [sqlite3_file_control()] interface makes a direct call to the +** xFileControl method for the [sqlite3_io_methods] object associated +** with a particular database identified by the second argument. ^The +** name of the database is "main" for the main database or "temp" for the +** TEMP database, or the name that appears after the AS keyword for +** databases that are added using the [ATTACH] SQL command. +** ^A NULL pointer can be used in place of "main" to refer to the +** main database file. +** ^The third and fourth parameters to this routine +** are passed directly through to the second and third parameters of +** the xFileControl method. ^The return value of the xFileControl +** method becomes the return value of this routine. +** +** A few opcodes for [sqlite3_file_control()] are handled directly +** by the SQLite core and never invoke the +** sqlite3_io_methods.xFileControl method. +** ^The [SQLITE_FCNTL_FILE_POINTER] value for the op parameter causes +** a pointer to the underlying [sqlite3_file] object to be written into +** the space pointed to by the 4th parameter. The +** [SQLITE_FCNTL_JOURNAL_POINTER] works similarly except that it returns +** the [sqlite3_file] object associated with the journal file instead of +** the main database. The [SQLITE_FCNTL_VFS_POINTER] opcode returns +** a pointer to the underlying [sqlite3_vfs] object for the file. +** The [SQLITE_FCNTL_DATA_VERSION] returns the data version counter +** from the pager. +** +** ^If the second parameter (zDbName) does not match the name of any +** open database file, then SQLITE_ERROR is returned. ^This error +** code is not remembered and will not be recalled by [sqlite3_errcode()] +** or [sqlite3_errmsg()]. The underlying xFileControl method might +** also return SQLITE_ERROR. There is no way to distinguish between +** an incorrect zDbName and an SQLITE_ERROR return from the underlying +** xFileControl method. +** +** See also: [file control opcodes] +*/ +SQLITE_API int sqlite3_file_control(sqlite3*, const char *zDbName, int op, void*); + +/* +** CAPI3REF: Testing Interface +** +** ^The sqlite3_test_control() interface is used to read out internal +** state of SQLite and to inject faults into SQLite for testing +** purposes. ^The first parameter is an operation code that determines +** the number, meaning, and operation of all subsequent parameters. +** +** This interface is not for use by applications. It exists solely +** for verifying the correct operation of the SQLite library. Depending +** on how the SQLite library is compiled, this interface might not exist. +** +** The details of the operation codes, their meanings, the parameters +** they take, and what they do are all subject to change without notice. +** Unlike most of the SQLite API, this function is not guaranteed to +** operate consistently from one release to the next. +*/ +SQLITE_API int sqlite3_test_control(int op, ...); + +/* +** CAPI3REF: Testing Interface Operation Codes +** +** These constants are the valid operation code parameters used +** as the first argument to [sqlite3_test_control()]. +** +** These parameters and their meanings are subject to change +** without notice. These values are for testing purposes only. +** Applications should not use any of these parameters or the +** [sqlite3_test_control()] interface. +*/ +#define SQLITE_TESTCTRL_FIRST 5 +#define SQLITE_TESTCTRL_PRNG_SAVE 5 +#define SQLITE_TESTCTRL_PRNG_RESTORE 6 +#define SQLITE_TESTCTRL_PRNG_RESET 7 /* NOT USED */ +#define SQLITE_TESTCTRL_BITVEC_TEST 8 +#define SQLITE_TESTCTRL_FAULT_INSTALL 9 +#define SQLITE_TESTCTRL_BENIGN_MALLOC_HOOKS 10 +#define SQLITE_TESTCTRL_PENDING_BYTE 11 +#define SQLITE_TESTCTRL_ASSERT 12 +#define SQLITE_TESTCTRL_ALWAYS 13 +#define SQLITE_TESTCTRL_RESERVE 14 /* NOT USED */ +#define SQLITE_TESTCTRL_OPTIMIZATIONS 15 +#define SQLITE_TESTCTRL_ISKEYWORD 16 /* NOT USED */ +#define SQLITE_TESTCTRL_SCRATCHMALLOC 17 /* NOT USED */ +#define SQLITE_TESTCTRL_INTERNAL_FUNCTIONS 17 +#define SQLITE_TESTCTRL_LOCALTIME_FAULT 18 +#define SQLITE_TESTCTRL_EXPLAIN_STMT 19 /* NOT USED */ +#define SQLITE_TESTCTRL_ONCE_RESET_THRESHOLD 19 +#define SQLITE_TESTCTRL_NEVER_CORRUPT 20 +#define SQLITE_TESTCTRL_VDBE_COVERAGE 21 +#define SQLITE_TESTCTRL_BYTEORDER 22 +#define SQLITE_TESTCTRL_ISINIT 23 +#define SQLITE_TESTCTRL_SORTER_MMAP 24 +#define SQLITE_TESTCTRL_IMPOSTER 25 +#define SQLITE_TESTCTRL_PARSER_COVERAGE 26 +#define SQLITE_TESTCTRL_RESULT_INTREAL 27 +#define SQLITE_TESTCTRL_PRNG_SEED 28 +#define SQLITE_TESTCTRL_EXTRA_SCHEMA_CHECKS 29 +#define SQLITE_TESTCTRL_SEEK_COUNT 30 +#define SQLITE_TESTCTRL_TRACEFLAGS 31 +#define SQLITE_TESTCTRL_TUNE 32 +#define SQLITE_TESTCTRL_LOGEST 33 +#define SQLITE_TESTCTRL_LAST 33 /* Largest TESTCTRL */ + +/* +** CAPI3REF: SQL Keyword Checking +** +** These routines provide access to the set of SQL language keywords +** recognized by SQLite. Applications can uses these routines to determine +** whether or not a specific identifier needs to be escaped (for example, +** by enclosing in double-quotes) so as not to confuse the parser. +** +** The sqlite3_keyword_count() interface returns the number of distinct +** keywords understood by SQLite. +** +** The sqlite3_keyword_name(N,Z,L) interface finds the N-th keyword and +** makes *Z point to that keyword expressed as UTF8 and writes the number +** of bytes in the keyword into *L. The string that *Z points to is not +** zero-terminated. The sqlite3_keyword_name(N,Z,L) routine returns +** SQLITE_OK if N is within bounds and SQLITE_ERROR if not. If either Z +** or L are NULL or invalid pointers then calls to +** sqlite3_keyword_name(N,Z,L) result in undefined behavior. +** +** The sqlite3_keyword_check(Z,L) interface checks to see whether or not +** the L-byte UTF8 identifier that Z points to is a keyword, returning non-zero +** if it is and zero if not. +** +** The parser used by SQLite is forgiving. It is often possible to use +** a keyword as an identifier as long as such use does not result in a +** parsing ambiguity. For example, the statement +** "CREATE TABLE BEGIN(REPLACE,PRAGMA,END);" is accepted by SQLite, and +** creates a new table named "BEGIN" with three columns named +** "REPLACE", "PRAGMA", and "END". Nevertheless, best practice is to avoid +** using keywords as identifiers. Common techniques used to avoid keyword +** name collisions include: +**
      +**
    • Put all identifier names inside double-quotes. This is the official +** SQL way to escape identifier names. +**
    • Put identifier names inside [...]. This is not standard SQL, +** but it is what SQL Server does and so lots of programmers use this +** technique. +**
    • Begin every identifier with the letter "Z" as no SQL keywords start +** with "Z". +**
    • Include a digit somewhere in every identifier name. +**
    +** +** Note that the number of keywords understood by SQLite can depend on +** compile-time options. For example, "VACUUM" is not a keyword if +** SQLite is compiled with the [-DSQLITE_OMIT_VACUUM] option. Also, +** new keywords may be added to future releases of SQLite. +*/ +SQLITE_API int sqlite3_keyword_count(void); +SQLITE_API int sqlite3_keyword_name(int,const char**,int*); +SQLITE_API int sqlite3_keyword_check(const char*,int); + +/* +** CAPI3REF: Dynamic String Object +** KEYWORDS: {dynamic string} +** +** An instance of the sqlite3_str object contains a dynamically-sized +** string under construction. +** +** The lifecycle of an sqlite3_str object is as follows: +**
      +**
    1. ^The sqlite3_str object is created using [sqlite3_str_new()]. +**
    2. ^Text is appended to the sqlite3_str object using various +** methods, such as [sqlite3_str_appendf()]. +**
    3. ^The sqlite3_str object is destroyed and the string it created +** is returned using the [sqlite3_str_finish()] interface. +**
    +*/ +typedef struct sqlite3_str sqlite3_str; + +/* +** CAPI3REF: Create A New Dynamic String Object +** CONSTRUCTOR: sqlite3_str +** +** ^The [sqlite3_str_new(D)] interface allocates and initializes +** a new [sqlite3_str] object. To avoid memory leaks, the object returned by +** [sqlite3_str_new()] must be freed by a subsequent call to +** [sqlite3_str_finish(X)]. +** +** ^The [sqlite3_str_new(D)] interface always returns a pointer to a +** valid [sqlite3_str] object, though in the event of an out-of-memory +** error the returned object might be a special singleton that will +** silently reject new text, always return SQLITE_NOMEM from +** [sqlite3_str_errcode()], always return 0 for +** [sqlite3_str_length()], and always return NULL from +** [sqlite3_str_finish(X)]. It is always safe to use the value +** returned by [sqlite3_str_new(D)] as the sqlite3_str parameter +** to any of the other [sqlite3_str] methods. +** +** The D parameter to [sqlite3_str_new(D)] may be NULL. If the +** D parameter in [sqlite3_str_new(D)] is not NULL, then the maximum +** length of the string contained in the [sqlite3_str] object will be +** the value set for [sqlite3_limit](D,[SQLITE_LIMIT_LENGTH]) instead +** of [SQLITE_MAX_LENGTH]. +*/ +SQLITE_API sqlite3_str *sqlite3_str_new(sqlite3*); + +/* +** CAPI3REF: Finalize A Dynamic String +** DESTRUCTOR: sqlite3_str +** +** ^The [sqlite3_str_finish(X)] interface destroys the sqlite3_str object X +** and returns a pointer to a memory buffer obtained from [sqlite3_malloc64()] +** that contains the constructed string. The calling application should +** pass the returned value to [sqlite3_free()] to avoid a memory leak. +** ^The [sqlite3_str_finish(X)] interface may return a NULL pointer if any +** errors were encountered during construction of the string. ^The +** [sqlite3_str_finish(X)] interface will also return a NULL pointer if the +** string in [sqlite3_str] object X is zero bytes long. +*/ +SQLITE_API char *sqlite3_str_finish(sqlite3_str*); + +/* +** CAPI3REF: Add Content To A Dynamic String +** METHOD: sqlite3_str +** +** These interfaces add content to an sqlite3_str object previously obtained +** from [sqlite3_str_new()]. +** +** ^The [sqlite3_str_appendf(X,F,...)] and +** [sqlite3_str_vappendf(X,F,V)] interfaces uses the [built-in printf] +** functionality of SQLite to append formatted text onto the end of +** [sqlite3_str] object X. +** +** ^The [sqlite3_str_append(X,S,N)] method appends exactly N bytes from string S +** onto the end of the [sqlite3_str] object X. N must be non-negative. +** S must contain at least N non-zero bytes of content. To append a +** zero-terminated string in its entirety, use the [sqlite3_str_appendall()] +** method instead. +** +** ^The [sqlite3_str_appendall(X,S)] method appends the complete content of +** zero-terminated string S onto the end of [sqlite3_str] object X. +** +** ^The [sqlite3_str_appendchar(X,N,C)] method appends N copies of the +** single-byte character C onto the end of [sqlite3_str] object X. +** ^This method can be used, for example, to add whitespace indentation. +** +** ^The [sqlite3_str_reset(X)] method resets the string under construction +** inside [sqlite3_str] object X back to zero bytes in length. +** +** These methods do not return a result code. ^If an error occurs, that fact +** is recorded in the [sqlite3_str] object and can be recovered by a +** subsequent call to [sqlite3_str_errcode(X)]. +*/ +SQLITE_API void sqlite3_str_appendf(sqlite3_str*, const char *zFormat, ...); +SQLITE_API void sqlite3_str_vappendf(sqlite3_str*, const char *zFormat, va_list); +SQLITE_API void sqlite3_str_append(sqlite3_str*, const char *zIn, int N); +SQLITE_API void sqlite3_str_appendall(sqlite3_str*, const char *zIn); +SQLITE_API void sqlite3_str_appendchar(sqlite3_str*, int N, char C); +SQLITE_API void sqlite3_str_reset(sqlite3_str*); + +/* +** CAPI3REF: Status Of A Dynamic String +** METHOD: sqlite3_str +** +** These interfaces return the current status of an [sqlite3_str] object. +** +** ^If any prior errors have occurred while constructing the dynamic string +** in sqlite3_str X, then the [sqlite3_str_errcode(X)] method will return +** an appropriate error code. ^The [sqlite3_str_errcode(X)] method returns +** [SQLITE_NOMEM] following any out-of-memory error, or +** [SQLITE_TOOBIG] if the size of the dynamic string exceeds +** [SQLITE_MAX_LENGTH], or [SQLITE_OK] if there have been no errors. +** +** ^The [sqlite3_str_length(X)] method returns the current length, in bytes, +** of the dynamic string under construction in [sqlite3_str] object X. +** ^The length returned by [sqlite3_str_length(X)] does not include the +** zero-termination byte. +** +** ^The [sqlite3_str_value(X)] method returns a pointer to the current +** content of the dynamic string under construction in X. The value +** returned by [sqlite3_str_value(X)] is managed by the sqlite3_str object X +** and might be freed or altered by any subsequent method on the same +** [sqlite3_str] object. Applications must not used the pointer returned +** [sqlite3_str_value(X)] after any subsequent method call on the same +** object. ^Applications may change the content of the string returned +** by [sqlite3_str_value(X)] as long as they do not write into any bytes +** outside the range of 0 to [sqlite3_str_length(X)] and do not read or +** write any byte after any subsequent sqlite3_str method call. +*/ +SQLITE_API int sqlite3_str_errcode(sqlite3_str*); +SQLITE_API int sqlite3_str_length(sqlite3_str*); +SQLITE_API char *sqlite3_str_value(sqlite3_str*); + +/* +** CAPI3REF: SQLite Runtime Status +** +** ^These interfaces are used to retrieve runtime status information +** about the performance of SQLite, and optionally to reset various +** highwater marks. ^The first argument is an integer code for +** the specific parameter to measure. ^(Recognized integer codes +** are of the form [status parameters | SQLITE_STATUS_...].)^ +** ^The current value of the parameter is returned into *pCurrent. +** ^The highest recorded value is returned in *pHighwater. ^If the +** resetFlag is true, then the highest record value is reset after +** *pHighwater is written. ^(Some parameters do not record the highest +** value. For those parameters +** nothing is written into *pHighwater and the resetFlag is ignored.)^ +** ^(Other parameters record only the highwater mark and not the current +** value. For these latter parameters nothing is written into *pCurrent.)^ +** +** ^The sqlite3_status() and sqlite3_status64() routines return +** SQLITE_OK on success and a non-zero [error code] on failure. +** +** If either the current value or the highwater mark is too large to +** be represented by a 32-bit integer, then the values returned by +** sqlite3_status() are undefined. +** +** See also: [sqlite3_db_status()] +*/ +SQLITE_API int sqlite3_status(int op, int *pCurrent, int *pHighwater, int resetFlag); +SQLITE_API int sqlite3_status64( + int op, + sqlite3_int64 *pCurrent, + sqlite3_int64 *pHighwater, + int resetFlag +); + + +/* +** CAPI3REF: Status Parameters +** KEYWORDS: {status parameters} +** +** These integer constants designate various run-time status parameters +** that can be returned by [sqlite3_status()]. +** +**
    +** [[SQLITE_STATUS_MEMORY_USED]] ^(
    SQLITE_STATUS_MEMORY_USED
    +**
    This parameter is the current amount of memory checked out +** using [sqlite3_malloc()], either directly or indirectly. The +** figure includes calls made to [sqlite3_malloc()] by the application +** and internal memory usage by the SQLite library. Auxiliary page-cache +** memory controlled by [SQLITE_CONFIG_PAGECACHE] is not included in +** this parameter. The amount returned is the sum of the allocation +** sizes as reported by the xSize method in [sqlite3_mem_methods].
    )^ +** +** [[SQLITE_STATUS_MALLOC_SIZE]] ^(
    SQLITE_STATUS_MALLOC_SIZE
    +**
    This parameter records the largest memory allocation request +** handed to [sqlite3_malloc()] or [sqlite3_realloc()] (or their +** internal equivalents). Only the value returned in the +** *pHighwater parameter to [sqlite3_status()] is of interest. +** The value written into the *pCurrent parameter is undefined.
    )^ +** +** [[SQLITE_STATUS_MALLOC_COUNT]] ^(
    SQLITE_STATUS_MALLOC_COUNT
    +**
    This parameter records the number of separate memory allocations +** currently checked out.
    )^ +** +** [[SQLITE_STATUS_PAGECACHE_USED]] ^(
    SQLITE_STATUS_PAGECACHE_USED
    +**
    This parameter returns the number of pages used out of the +** [pagecache memory allocator] that was configured using +** [SQLITE_CONFIG_PAGECACHE]. The +** value returned is in pages, not in bytes.
    )^ +** +** [[SQLITE_STATUS_PAGECACHE_OVERFLOW]] +** ^(
    SQLITE_STATUS_PAGECACHE_OVERFLOW
    +**
    This parameter returns the number of bytes of page cache +** allocation which could not be satisfied by the [SQLITE_CONFIG_PAGECACHE] +** buffer and where forced to overflow to [sqlite3_malloc()]. The +** returned value includes allocations that overflowed because they +** where too large (they were larger than the "sz" parameter to +** [SQLITE_CONFIG_PAGECACHE]) and allocations that overflowed because +** no space was left in the page cache.
    )^ +** +** [[SQLITE_STATUS_PAGECACHE_SIZE]] ^(
    SQLITE_STATUS_PAGECACHE_SIZE
    +**
    This parameter records the largest memory allocation request +** handed to the [pagecache memory allocator]. Only the value returned in the +** *pHighwater parameter to [sqlite3_status()] is of interest. +** The value written into the *pCurrent parameter is undefined.
    )^ +** +** [[SQLITE_STATUS_SCRATCH_USED]]
    SQLITE_STATUS_SCRATCH_USED
    +**
    No longer used.
    +** +** [[SQLITE_STATUS_SCRATCH_OVERFLOW]] ^(
    SQLITE_STATUS_SCRATCH_OVERFLOW
    +**
    No longer used.
    +** +** [[SQLITE_STATUS_SCRATCH_SIZE]]
    SQLITE_STATUS_SCRATCH_SIZE
    +**
    No longer used.
    +** +** [[SQLITE_STATUS_PARSER_STACK]] ^(
    SQLITE_STATUS_PARSER_STACK
    +**
    The *pHighwater parameter records the deepest parser stack. +** The *pCurrent value is undefined. The *pHighwater value is only +** meaningful if SQLite is compiled with [YYTRACKMAXSTACKDEPTH].
    )^ +**
    +** +** New status parameters may be added from time to time. +*/ +#define SQLITE_STATUS_MEMORY_USED 0 +#define SQLITE_STATUS_PAGECACHE_USED 1 +#define SQLITE_STATUS_PAGECACHE_OVERFLOW 2 +#define SQLITE_STATUS_SCRATCH_USED 3 /* NOT USED */ +#define SQLITE_STATUS_SCRATCH_OVERFLOW 4 /* NOT USED */ +#define SQLITE_STATUS_MALLOC_SIZE 5 +#define SQLITE_STATUS_PARSER_STACK 6 +#define SQLITE_STATUS_PAGECACHE_SIZE 7 +#define SQLITE_STATUS_SCRATCH_SIZE 8 /* NOT USED */ +#define SQLITE_STATUS_MALLOC_COUNT 9 + +/* +** CAPI3REF: Database Connection Status +** METHOD: sqlite3 +** +** ^This interface is used to retrieve runtime status information +** about a single [database connection]. ^The first argument is the +** database connection object to be interrogated. ^The second argument +** is an integer constant, taken from the set of +** [SQLITE_DBSTATUS options], that +** determines the parameter to interrogate. The set of +** [SQLITE_DBSTATUS options] is likely +** to grow in future releases of SQLite. +** +** ^The current value of the requested parameter is written into *pCur +** and the highest instantaneous value is written into *pHiwtr. ^If +** the resetFlg is true, then the highest instantaneous value is +** reset back down to the current value. +** +** ^The sqlite3_db_status() routine returns SQLITE_OK on success and a +** non-zero [error code] on failure. +** +** See also: [sqlite3_status()] and [sqlite3_stmt_status()]. +*/ +SQLITE_API int sqlite3_db_status(sqlite3*, int op, int *pCur, int *pHiwtr, int resetFlg); + +/* +** CAPI3REF: Status Parameters for database connections +** KEYWORDS: {SQLITE_DBSTATUS options} +** +** These constants are the available integer "verbs" that can be passed as +** the second argument to the [sqlite3_db_status()] interface. +** +** New verbs may be added in future releases of SQLite. Existing verbs +** might be discontinued. Applications should check the return code from +** [sqlite3_db_status()] to make sure that the call worked. +** The [sqlite3_db_status()] interface will return a non-zero error code +** if a discontinued or unsupported verb is invoked. +** +**
    +** [[SQLITE_DBSTATUS_LOOKASIDE_USED]] ^(
    SQLITE_DBSTATUS_LOOKASIDE_USED
    +**
    This parameter returns the number of lookaside memory slots currently +** checked out.
    )^ +** +** [[SQLITE_DBSTATUS_LOOKASIDE_HIT]] ^(
    SQLITE_DBSTATUS_LOOKASIDE_HIT
    +**
    This parameter returns the number of malloc attempts that were +** satisfied using lookaside memory. Only the high-water value is meaningful; +** the current value is always zero.)^ +** +** [[SQLITE_DBSTATUS_LOOKASIDE_MISS_SIZE]] +** ^(
    SQLITE_DBSTATUS_LOOKASIDE_MISS_SIZE
    +**
    This parameter returns the number malloc attempts that might have +** been satisfied using lookaside memory but failed due to the amount of +** memory requested being larger than the lookaside slot size. +** Only the high-water value is meaningful; +** the current value is always zero.)^ +** +** [[SQLITE_DBSTATUS_LOOKASIDE_MISS_FULL]] +** ^(
    SQLITE_DBSTATUS_LOOKASIDE_MISS_FULL
    +**
    This parameter returns the number malloc attempts that might have +** been satisfied using lookaside memory but failed due to all lookaside +** memory already being in use. +** Only the high-water value is meaningful; +** the current value is always zero.)^ +** +** [[SQLITE_DBSTATUS_CACHE_USED]] ^(
    SQLITE_DBSTATUS_CACHE_USED
    +**
    This parameter returns the approximate number of bytes of heap +** memory used by all pager caches associated with the database connection.)^ +** ^The highwater mark associated with SQLITE_DBSTATUS_CACHE_USED is always 0. +** +** [[SQLITE_DBSTATUS_CACHE_USED_SHARED]] +** ^(
    SQLITE_DBSTATUS_CACHE_USED_SHARED
    +**
    This parameter is similar to DBSTATUS_CACHE_USED, except that if a +** pager cache is shared between two or more connections the bytes of heap +** memory used by that pager cache is divided evenly between the attached +** connections.)^ In other words, if none of the pager caches associated +** with the database connection are shared, this request returns the same +** value as DBSTATUS_CACHE_USED. Or, if one or more or the pager caches are +** shared, the value returned by this call will be smaller than that returned +** by DBSTATUS_CACHE_USED. ^The highwater mark associated with +** SQLITE_DBSTATUS_CACHE_USED_SHARED is always 0. +** +** [[SQLITE_DBSTATUS_SCHEMA_USED]] ^(
    SQLITE_DBSTATUS_SCHEMA_USED
    +**
    This parameter returns the approximate number of bytes of heap +** memory used to store the schema for all databases associated +** with the connection - main, temp, and any [ATTACH]-ed databases.)^ +** ^The full amount of memory used by the schemas is reported, even if the +** schema memory is shared with other database connections due to +** [shared cache mode] being enabled. +** ^The highwater mark associated with SQLITE_DBSTATUS_SCHEMA_USED is always 0. +** +** [[SQLITE_DBSTATUS_STMT_USED]] ^(
    SQLITE_DBSTATUS_STMT_USED
    +**
    This parameter returns the approximate number of bytes of heap +** and lookaside memory used by all prepared statements associated with +** the database connection.)^ +** ^The highwater mark associated with SQLITE_DBSTATUS_STMT_USED is always 0. +**
    +** +** [[SQLITE_DBSTATUS_CACHE_HIT]] ^(
    SQLITE_DBSTATUS_CACHE_HIT
    +**
    This parameter returns the number of pager cache hits that have +** occurred.)^ ^The highwater mark associated with SQLITE_DBSTATUS_CACHE_HIT +** is always 0. +**
    +** +** [[SQLITE_DBSTATUS_CACHE_MISS]] ^(
    SQLITE_DBSTATUS_CACHE_MISS
    +**
    This parameter returns the number of pager cache misses that have +** occurred.)^ ^The highwater mark associated with SQLITE_DBSTATUS_CACHE_MISS +** is always 0. +**
    +** +** [[SQLITE_DBSTATUS_CACHE_WRITE]] ^(
    SQLITE_DBSTATUS_CACHE_WRITE
    +**
    This parameter returns the number of dirty cache entries that have +** been written to disk. Specifically, the number of pages written to the +** wal file in wal mode databases, or the number of pages written to the +** database file in rollback mode databases. Any pages written as part of +** transaction rollback or database recovery operations are not included. +** If an IO or other error occurs while writing a page to disk, the effect +** on subsequent SQLITE_DBSTATUS_CACHE_WRITE requests is undefined.)^ ^The +** highwater mark associated with SQLITE_DBSTATUS_CACHE_WRITE is always 0. +**
    +** +** [[SQLITE_DBSTATUS_CACHE_SPILL]] ^(
    SQLITE_DBSTATUS_CACHE_SPILL
    +**
    This parameter returns the number of dirty cache entries that have +** been written to disk in the middle of a transaction due to the page +** cache overflowing. Transactions are more efficient if they are written +** to disk all at once. When pages spill mid-transaction, that introduces +** additional overhead. This parameter can be used help identify +** inefficiencies that can be resolved by increasing the cache size. +**
    +** +** [[SQLITE_DBSTATUS_DEFERRED_FKS]] ^(
    SQLITE_DBSTATUS_DEFERRED_FKS
    +**
    This parameter returns zero for the current value if and only if +** all foreign key constraints (deferred or immediate) have been +** resolved.)^ ^The highwater mark is always 0. +**
    +**
    +*/ +#define SQLITE_DBSTATUS_LOOKASIDE_USED 0 +#define SQLITE_DBSTATUS_CACHE_USED 1 +#define SQLITE_DBSTATUS_SCHEMA_USED 2 +#define SQLITE_DBSTATUS_STMT_USED 3 +#define SQLITE_DBSTATUS_LOOKASIDE_HIT 4 +#define SQLITE_DBSTATUS_LOOKASIDE_MISS_SIZE 5 +#define SQLITE_DBSTATUS_LOOKASIDE_MISS_FULL 6 +#define SQLITE_DBSTATUS_CACHE_HIT 7 +#define SQLITE_DBSTATUS_CACHE_MISS 8 +#define SQLITE_DBSTATUS_CACHE_WRITE 9 +#define SQLITE_DBSTATUS_DEFERRED_FKS 10 +#define SQLITE_DBSTATUS_CACHE_USED_SHARED 11 +#define SQLITE_DBSTATUS_CACHE_SPILL 12 +#define SQLITE_DBSTATUS_MAX 12 /* Largest defined DBSTATUS */ + + +/* +** CAPI3REF: Prepared Statement Status +** METHOD: sqlite3_stmt +** +** ^(Each prepared statement maintains various +** [SQLITE_STMTSTATUS counters] that measure the number +** of times it has performed specific operations.)^ These counters can +** be used to monitor the performance characteristics of the prepared +** statements. For example, if the number of table steps greatly exceeds +** the number of table searches or result rows, that would tend to indicate +** that the prepared statement is using a full table scan rather than +** an index. +** +** ^(This interface is used to retrieve and reset counter values from +** a [prepared statement]. The first argument is the prepared statement +** object to be interrogated. The second argument +** is an integer code for a specific [SQLITE_STMTSTATUS counter] +** to be interrogated.)^ +** ^The current value of the requested counter is returned. +** ^If the resetFlg is true, then the counter is reset to zero after this +** interface call returns. +** +** See also: [sqlite3_status()] and [sqlite3_db_status()]. +*/ +SQLITE_API int sqlite3_stmt_status(sqlite3_stmt*, int op,int resetFlg); + +/* +** CAPI3REF: Status Parameters for prepared statements +** KEYWORDS: {SQLITE_STMTSTATUS counter} {SQLITE_STMTSTATUS counters} +** +** These preprocessor macros define integer codes that name counter +** values associated with the [sqlite3_stmt_status()] interface. +** The meanings of the various counters are as follows: +** +**
    +** [[SQLITE_STMTSTATUS_FULLSCAN_STEP]]
    SQLITE_STMTSTATUS_FULLSCAN_STEP
    +**
    ^This is the number of times that SQLite has stepped forward in +** a table as part of a full table scan. Large numbers for this counter +** may indicate opportunities for performance improvement through +** careful use of indices.
    +** +** [[SQLITE_STMTSTATUS_SORT]]
    SQLITE_STMTSTATUS_SORT
    +**
    ^This is the number of sort operations that have occurred. +** A non-zero value in this counter may indicate an opportunity to +** improvement performance through careful use of indices.
    +** +** [[SQLITE_STMTSTATUS_AUTOINDEX]]
    SQLITE_STMTSTATUS_AUTOINDEX
    +**
    ^This is the number of rows inserted into transient indices that +** were created automatically in order to help joins run faster. +** A non-zero value in this counter may indicate an opportunity to +** improvement performance by adding permanent indices that do not +** need to be reinitialized each time the statement is run.
    +** +** [[SQLITE_STMTSTATUS_VM_STEP]]
    SQLITE_STMTSTATUS_VM_STEP
    +**
    ^This is the number of virtual machine operations executed +** by the prepared statement if that number is less than or equal +** to 2147483647. The number of virtual machine operations can be +** used as a proxy for the total work done by the prepared statement. +** If the number of virtual machine operations exceeds 2147483647 +** then the value returned by this statement status code is undefined. +** +** [[SQLITE_STMTSTATUS_REPREPARE]]
    SQLITE_STMTSTATUS_REPREPARE
    +**
    ^This is the number of times that the prepare statement has been +** automatically regenerated due to schema changes or changes to +** [bound parameters] that might affect the query plan. +** +** [[SQLITE_STMTSTATUS_RUN]]
    SQLITE_STMTSTATUS_RUN
    +**
    ^This is the number of times that the prepared statement has +** been run. A single "run" for the purposes of this counter is one +** or more calls to [sqlite3_step()] followed by a call to [sqlite3_reset()]. +** The counter is incremented on the first [sqlite3_step()] call of each +** cycle. +** +** [[SQLITE_STMTSTATUS_FILTER_MISS]] +** [[SQLITE_STMTSTATUS_FILTER HIT]] +**
    SQLITE_STMTSTATUS_FILTER_HIT
    +** SQLITE_STMTSTATUS_FILTER_MISS
    +**
    ^SQLITE_STMTSTATUS_FILTER_HIT is the number of times that a join +** step was bypassed because a Bloom filter returned not-found. The +** corresponding SQLITE_STMTSTATUS_FILTER_MISS value is the number of +** times that the Bloom filter returned a find, and thus the join step +** had to be processed as normal. +** +** [[SQLITE_STMTSTATUS_MEMUSED]]
    SQLITE_STMTSTATUS_MEMUSED
    +**
    ^This is the approximate number of bytes of heap memory +** used to store the prepared statement. ^This value is not actually +** a counter, and so the resetFlg parameter to sqlite3_stmt_status() +** is ignored when the opcode is SQLITE_STMTSTATUS_MEMUSED. +**
    +**
    +*/ +#define SQLITE_STMTSTATUS_FULLSCAN_STEP 1 +#define SQLITE_STMTSTATUS_SORT 2 +#define SQLITE_STMTSTATUS_AUTOINDEX 3 +#define SQLITE_STMTSTATUS_VM_STEP 4 +#define SQLITE_STMTSTATUS_REPREPARE 5 +#define SQLITE_STMTSTATUS_RUN 6 +#define SQLITE_STMTSTATUS_FILTER_MISS 7 +#define SQLITE_STMTSTATUS_FILTER_HIT 8 +#define SQLITE_STMTSTATUS_MEMUSED 99 + +/* +** CAPI3REF: Custom Page Cache Object +** +** The sqlite3_pcache type is opaque. It is implemented by +** the pluggable module. The SQLite core has no knowledge of +** its size or internal structure and never deals with the +** sqlite3_pcache object except by holding and passing pointers +** to the object. +** +** See [sqlite3_pcache_methods2] for additional information. +*/ +typedef struct sqlite3_pcache sqlite3_pcache; + +/* +** CAPI3REF: Custom Page Cache Object +** +** The sqlite3_pcache_page object represents a single page in the +** page cache. The page cache will allocate instances of this +** object. Various methods of the page cache use pointers to instances +** of this object as parameters or as their return value. +** +** See [sqlite3_pcache_methods2] for additional information. +*/ +typedef struct sqlite3_pcache_page sqlite3_pcache_page; +struct sqlite3_pcache_page { + void *pBuf; /* The content of the page */ + void *pExtra; /* Extra information associated with the page */ +}; + +/* +** CAPI3REF: Application Defined Page Cache. +** KEYWORDS: {page cache} +** +** ^(The [sqlite3_config]([SQLITE_CONFIG_PCACHE2], ...) interface can +** register an alternative page cache implementation by passing in an +** instance of the sqlite3_pcache_methods2 structure.)^ +** In many applications, most of the heap memory allocated by +** SQLite is used for the page cache. +** By implementing a +** custom page cache using this API, an application can better control +** the amount of memory consumed by SQLite, the way in which +** that memory is allocated and released, and the policies used to +** determine exactly which parts of a database file are cached and for +** how long. +** +** The alternative page cache mechanism is an +** extreme measure that is only needed by the most demanding applications. +** The built-in page cache is recommended for most uses. +** +** ^(The contents of the sqlite3_pcache_methods2 structure are copied to an +** internal buffer by SQLite within the call to [sqlite3_config]. Hence +** the application may discard the parameter after the call to +** [sqlite3_config()] returns.)^ +** +** [[the xInit() page cache method]] +** ^(The xInit() method is called once for each effective +** call to [sqlite3_initialize()])^ +** (usually only once during the lifetime of the process). ^(The xInit() +** method is passed a copy of the sqlite3_pcache_methods2.pArg value.)^ +** The intent of the xInit() method is to set up global data structures +** required by the custom page cache implementation. +** ^(If the xInit() method is NULL, then the +** built-in default page cache is used instead of the application defined +** page cache.)^ +** +** [[the xShutdown() page cache method]] +** ^The xShutdown() method is called by [sqlite3_shutdown()]. +** It can be used to clean up +** any outstanding resources before process shutdown, if required. +** ^The xShutdown() method may be NULL. +** +** ^SQLite automatically serializes calls to the xInit method, +** so the xInit method need not be threadsafe. ^The +** xShutdown method is only called from [sqlite3_shutdown()] so it does +** not need to be threadsafe either. All other methods must be threadsafe +** in multithreaded applications. +** +** ^SQLite will never invoke xInit() more than once without an intervening +** call to xShutdown(). +** +** [[the xCreate() page cache methods]] +** ^SQLite invokes the xCreate() method to construct a new cache instance. +** SQLite will typically create one cache instance for each open database file, +** though this is not guaranteed. ^The +** first parameter, szPage, is the size in bytes of the pages that must +** be allocated by the cache. ^szPage will always a power of two. ^The +** second parameter szExtra is a number of bytes of extra storage +** associated with each page cache entry. ^The szExtra parameter will +** a number less than 250. SQLite will use the +** extra szExtra bytes on each page to store metadata about the underlying +** database page on disk. The value passed into szExtra depends +** on the SQLite version, the target platform, and how SQLite was compiled. +** ^The third argument to xCreate(), bPurgeable, is true if the cache being +** created will be used to cache database pages of a file stored on disk, or +** false if it is used for an in-memory database. The cache implementation +** does not have to do anything special based with the value of bPurgeable; +** it is purely advisory. ^On a cache where bPurgeable is false, SQLite will +** never invoke xUnpin() except to deliberately delete a page. +** ^In other words, calls to xUnpin() on a cache with bPurgeable set to +** false will always have the "discard" flag set to true. +** ^Hence, a cache created with bPurgeable false will +** never contain any unpinned pages. +** +** [[the xCachesize() page cache method]] +** ^(The xCachesize() method may be called at any time by SQLite to set the +** suggested maximum cache-size (number of pages stored by) the cache +** instance passed as the first argument. This is the value configured using +** the SQLite "[PRAGMA cache_size]" command.)^ As with the bPurgeable +** parameter, the implementation is not required to do anything with this +** value; it is advisory only. +** +** [[the xPagecount() page cache methods]] +** The xPagecount() method must return the number of pages currently +** stored in the cache, both pinned and unpinned. +** +** [[the xFetch() page cache methods]] +** The xFetch() method locates a page in the cache and returns a pointer to +** an sqlite3_pcache_page object associated with that page, or a NULL pointer. +** The pBuf element of the returned sqlite3_pcache_page object will be a +** pointer to a buffer of szPage bytes used to store the content of a +** single database page. The pExtra element of sqlite3_pcache_page will be +** a pointer to the szExtra bytes of extra storage that SQLite has requested +** for each entry in the page cache. +** +** The page to be fetched is determined by the key. ^The minimum key value +** is 1. After it has been retrieved using xFetch, the page is considered +** to be "pinned". +** +** If the requested page is already in the page cache, then the page cache +** implementation must return a pointer to the page buffer with its content +** intact. If the requested page is not already in the cache, then the +** cache implementation should use the value of the createFlag +** parameter to help it determined what action to take: +** +** +**
    createFlag Behavior when page is not already in cache +**
    0 Do not allocate a new page. Return NULL. +**
    1 Allocate a new page if it easy and convenient to do so. +** Otherwise return NULL. +**
    2 Make every effort to allocate a new page. Only return +** NULL if allocating a new page is effectively impossible. +**
    +** +** ^(SQLite will normally invoke xFetch() with a createFlag of 0 or 1. SQLite +** will only use a createFlag of 2 after a prior call with a createFlag of 1 +** failed.)^ In between the xFetch() calls, SQLite may +** attempt to unpin one or more cache pages by spilling the content of +** pinned pages to disk and synching the operating system disk cache. +** +** [[the xUnpin() page cache method]] +** ^xUnpin() is called by SQLite with a pointer to a currently pinned page +** as its second argument. If the third parameter, discard, is non-zero, +** then the page must be evicted from the cache. +** ^If the discard parameter is +** zero, then the page may be discarded or retained at the discretion of +** page cache implementation. ^The page cache implementation +** may choose to evict unpinned pages at any time. +** +** The cache must not perform any reference counting. A single +** call to xUnpin() unpins the page regardless of the number of prior calls +** to xFetch(). +** +** [[the xRekey() page cache methods]] +** The xRekey() method is used to change the key value associated with the +** page passed as the second argument. If the cache +** previously contains an entry associated with newKey, it must be +** discarded. ^Any prior cache entry associated with newKey is guaranteed not +** to be pinned. +** +** When SQLite calls the xTruncate() method, the cache must discard all +** existing cache entries with page numbers (keys) greater than or equal +** to the value of the iLimit parameter passed to xTruncate(). If any +** of these pages are pinned, they are implicitly unpinned, meaning that +** they can be safely discarded. +** +** [[the xDestroy() page cache method]] +** ^The xDestroy() method is used to delete a cache allocated by xCreate(). +** All resources associated with the specified cache should be freed. ^After +** calling the xDestroy() method, SQLite considers the [sqlite3_pcache*] +** handle invalid, and will not use it with any other sqlite3_pcache_methods2 +** functions. +** +** [[the xShrink() page cache method]] +** ^SQLite invokes the xShrink() method when it wants the page cache to +** free up as much of heap memory as possible. The page cache implementation +** is not obligated to free any memory, but well-behaved implementations should +** do their best. +*/ +typedef struct sqlite3_pcache_methods2 sqlite3_pcache_methods2; +struct sqlite3_pcache_methods2 { + int iVersion; + void *pArg; + int (*xInit)(void*); + void (*xShutdown)(void*); + sqlite3_pcache *(*xCreate)(int szPage, int szExtra, int bPurgeable); + void (*xCachesize)(sqlite3_pcache*, int nCachesize); + int (*xPagecount)(sqlite3_pcache*); + sqlite3_pcache_page *(*xFetch)(sqlite3_pcache*, unsigned key, int createFlag); + void (*xUnpin)(sqlite3_pcache*, sqlite3_pcache_page*, int discard); + void (*xRekey)(sqlite3_pcache*, sqlite3_pcache_page*, + unsigned oldKey, unsigned newKey); + void (*xTruncate)(sqlite3_pcache*, unsigned iLimit); + void (*xDestroy)(sqlite3_pcache*); + void (*xShrink)(sqlite3_pcache*); +}; + +/* +** This is the obsolete pcache_methods object that has now been replaced +** by sqlite3_pcache_methods2. This object is not used by SQLite. It is +** retained in the header file for backwards compatibility only. +*/ +typedef struct sqlite3_pcache_methods sqlite3_pcache_methods; +struct sqlite3_pcache_methods { + void *pArg; + int (*xInit)(void*); + void (*xShutdown)(void*); + sqlite3_pcache *(*xCreate)(int szPage, int bPurgeable); + void (*xCachesize)(sqlite3_pcache*, int nCachesize); + int (*xPagecount)(sqlite3_pcache*); + void *(*xFetch)(sqlite3_pcache*, unsigned key, int createFlag); + void (*xUnpin)(sqlite3_pcache*, void*, int discard); + void (*xRekey)(sqlite3_pcache*, void*, unsigned oldKey, unsigned newKey); + void (*xTruncate)(sqlite3_pcache*, unsigned iLimit); + void (*xDestroy)(sqlite3_pcache*); +}; + + +/* +** CAPI3REF: Online Backup Object +** +** The sqlite3_backup object records state information about an ongoing +** online backup operation. ^The sqlite3_backup object is created by +** a call to [sqlite3_backup_init()] and is destroyed by a call to +** [sqlite3_backup_finish()]. +** +** See Also: [Using the SQLite Online Backup API] +*/ +typedef struct sqlite3_backup sqlite3_backup; + +/* +** CAPI3REF: Online Backup API. +** +** The backup API copies the content of one database into another. +** It is useful either for creating backups of databases or +** for copying in-memory databases to or from persistent files. +** +** See Also: [Using the SQLite Online Backup API] +** +** ^SQLite holds a write transaction open on the destination database file +** for the duration of the backup operation. +** ^The source database is read-locked only while it is being read; +** it is not locked continuously for the entire backup operation. +** ^Thus, the backup may be performed on a live source database without +** preventing other database connections from +** reading or writing to the source database while the backup is underway. +** +** ^(To perform a backup operation: +**
      +**
    1. sqlite3_backup_init() is called once to initialize the +** backup, +**
    2. sqlite3_backup_step() is called one or more times to transfer +** the data between the two databases, and finally +**
    3. sqlite3_backup_finish() is called to release all resources +** associated with the backup operation. +**
    )^ +** There should be exactly one call to sqlite3_backup_finish() for each +** successful call to sqlite3_backup_init(). +** +** [[sqlite3_backup_init()]] sqlite3_backup_init() +** +** ^The D and N arguments to sqlite3_backup_init(D,N,S,M) are the +** [database connection] associated with the destination database +** and the database name, respectively. +** ^The database name is "main" for the main database, "temp" for the +** temporary database, or the name specified after the AS keyword in +** an [ATTACH] statement for an attached database. +** ^The S and M arguments passed to +** sqlite3_backup_init(D,N,S,M) identify the [database connection] +** and database name of the source database, respectively. +** ^The source and destination [database connections] (parameters S and D) +** must be different or else sqlite3_backup_init(D,N,S,M) will fail with +** an error. +** +** ^A call to sqlite3_backup_init() will fail, returning NULL, if +** there is already a read or read-write transaction open on the +** destination database. +** +** ^If an error occurs within sqlite3_backup_init(D,N,S,M), then NULL is +** returned and an error code and error message are stored in the +** destination [database connection] D. +** ^The error code and message for the failed call to sqlite3_backup_init() +** can be retrieved using the [sqlite3_errcode()], [sqlite3_errmsg()], and/or +** [sqlite3_errmsg16()] functions. +** ^A successful call to sqlite3_backup_init() returns a pointer to an +** [sqlite3_backup] object. +** ^The [sqlite3_backup] object may be used with the sqlite3_backup_step() and +** sqlite3_backup_finish() functions to perform the specified backup +** operation. +** +** [[sqlite3_backup_step()]] sqlite3_backup_step() +** +** ^Function sqlite3_backup_step(B,N) will copy up to N pages between +** the source and destination databases specified by [sqlite3_backup] object B. +** ^If N is negative, all remaining source pages are copied. +** ^If sqlite3_backup_step(B,N) successfully copies N pages and there +** are still more pages to be copied, then the function returns [SQLITE_OK]. +** ^If sqlite3_backup_step(B,N) successfully finishes copying all pages +** from source to destination, then it returns [SQLITE_DONE]. +** ^If an error occurs while running sqlite3_backup_step(B,N), +** then an [error code] is returned. ^As well as [SQLITE_OK] and +** [SQLITE_DONE], a call to sqlite3_backup_step() may return [SQLITE_READONLY], +** [SQLITE_NOMEM], [SQLITE_BUSY], [SQLITE_LOCKED], or an +** [SQLITE_IOERR_ACCESS | SQLITE_IOERR_XXX] extended error code. +** +** ^(The sqlite3_backup_step() might return [SQLITE_READONLY] if +**
      +**
    1. the destination database was opened read-only, or +**
    2. the destination database is using write-ahead-log journaling +** and the destination and source page sizes differ, or +**
    3. the destination database is an in-memory database and the +** destination and source page sizes differ. +**
    )^ +** +** ^If sqlite3_backup_step() cannot obtain a required file-system lock, then +** the [sqlite3_busy_handler | busy-handler function] +** is invoked (if one is specified). ^If the +** busy-handler returns non-zero before the lock is available, then +** [SQLITE_BUSY] is returned to the caller. ^In this case the call to +** sqlite3_backup_step() can be retried later. ^If the source +** [database connection] +** is being used to write to the source database when sqlite3_backup_step() +** is called, then [SQLITE_LOCKED] is returned immediately. ^Again, in this +** case the call to sqlite3_backup_step() can be retried later on. ^(If +** [SQLITE_IOERR_ACCESS | SQLITE_IOERR_XXX], [SQLITE_NOMEM], or +** [SQLITE_READONLY] is returned, then +** there is no point in retrying the call to sqlite3_backup_step(). These +** errors are considered fatal.)^ The application must accept +** that the backup operation has failed and pass the backup operation handle +** to the sqlite3_backup_finish() to release associated resources. +** +** ^The first call to sqlite3_backup_step() obtains an exclusive lock +** on the destination file. ^The exclusive lock is not released until either +** sqlite3_backup_finish() is called or the backup operation is complete +** and sqlite3_backup_step() returns [SQLITE_DONE]. ^Every call to +** sqlite3_backup_step() obtains a [shared lock] on the source database that +** lasts for the duration of the sqlite3_backup_step() call. +** ^Because the source database is not locked between calls to +** sqlite3_backup_step(), the source database may be modified mid-way +** through the backup process. ^If the source database is modified by an +** external process or via a database connection other than the one being +** used by the backup operation, then the backup will be automatically +** restarted by the next call to sqlite3_backup_step(). ^If the source +** database is modified by the using the same database connection as is used +** by the backup operation, then the backup database is automatically +** updated at the same time. +** +** [[sqlite3_backup_finish()]] sqlite3_backup_finish() +** +** When sqlite3_backup_step() has returned [SQLITE_DONE], or when the +** application wishes to abandon the backup operation, the application +** should destroy the [sqlite3_backup] by passing it to sqlite3_backup_finish(). +** ^The sqlite3_backup_finish() interfaces releases all +** resources associated with the [sqlite3_backup] object. +** ^If sqlite3_backup_step() has not yet returned [SQLITE_DONE], then any +** active write-transaction on the destination database is rolled back. +** The [sqlite3_backup] object is invalid +** and may not be used following a call to sqlite3_backup_finish(). +** +** ^The value returned by sqlite3_backup_finish is [SQLITE_OK] if no +** sqlite3_backup_step() errors occurred, regardless or whether or not +** sqlite3_backup_step() completed. +** ^If an out-of-memory condition or IO error occurred during any prior +** sqlite3_backup_step() call on the same [sqlite3_backup] object, then +** sqlite3_backup_finish() returns the corresponding [error code]. +** +** ^A return of [SQLITE_BUSY] or [SQLITE_LOCKED] from sqlite3_backup_step() +** is not a permanent error and does not affect the return value of +** sqlite3_backup_finish(). +** +** [[sqlite3_backup_remaining()]] [[sqlite3_backup_pagecount()]] +** sqlite3_backup_remaining() and sqlite3_backup_pagecount() +** +** ^The sqlite3_backup_remaining() routine returns the number of pages still +** to be backed up at the conclusion of the most recent sqlite3_backup_step(). +** ^The sqlite3_backup_pagecount() routine returns the total number of pages +** in the source database at the conclusion of the most recent +** sqlite3_backup_step(). +** ^(The values returned by these functions are only updated by +** sqlite3_backup_step(). If the source database is modified in a way that +** changes the size of the source database or the number of pages remaining, +** those changes are not reflected in the output of sqlite3_backup_pagecount() +** and sqlite3_backup_remaining() until after the next +** sqlite3_backup_step().)^ +** +** Concurrent Usage of Database Handles +** +** ^The source [database connection] may be used by the application for other +** purposes while a backup operation is underway or being initialized. +** ^If SQLite is compiled and configured to support threadsafe database +** connections, then the source database connection may be used concurrently +** from within other threads. +** +** However, the application must guarantee that the destination +** [database connection] is not passed to any other API (by any thread) after +** sqlite3_backup_init() is called and before the corresponding call to +** sqlite3_backup_finish(). SQLite does not currently check to see +** if the application incorrectly accesses the destination [database connection] +** and so no error code is reported, but the operations may malfunction +** nevertheless. Use of the destination database connection while a +** backup is in progress might also also cause a mutex deadlock. +** +** If running in [shared cache mode], the application must +** guarantee that the shared cache used by the destination database +** is not accessed while the backup is running. In practice this means +** that the application must guarantee that the disk file being +** backed up to is not accessed by any connection within the process, +** not just the specific connection that was passed to sqlite3_backup_init(). +** +** The [sqlite3_backup] object itself is partially threadsafe. Multiple +** threads may safely make multiple concurrent calls to sqlite3_backup_step(). +** However, the sqlite3_backup_remaining() and sqlite3_backup_pagecount() +** APIs are not strictly speaking threadsafe. If they are invoked at the +** same time as another thread is invoking sqlite3_backup_step() it is +** possible that they return invalid values. +*/ +SQLITE_API sqlite3_backup *sqlite3_backup_init( + sqlite3 *pDest, /* Destination database handle */ + const char *zDestName, /* Destination database name */ + sqlite3 *pSource, /* Source database handle */ + const char *zSourceName /* Source database name */ +); +SQLITE_API int sqlite3_backup_step(sqlite3_backup *p, int nPage); +SQLITE_API int sqlite3_backup_finish(sqlite3_backup *p); +SQLITE_API int sqlite3_backup_remaining(sqlite3_backup *p); +SQLITE_API int sqlite3_backup_pagecount(sqlite3_backup *p); + +/* +** CAPI3REF: Unlock Notification +** METHOD: sqlite3 +** +** ^When running in shared-cache mode, a database operation may fail with +** an [SQLITE_LOCKED] error if the required locks on the shared-cache or +** individual tables within the shared-cache cannot be obtained. See +** [SQLite Shared-Cache Mode] for a description of shared-cache locking. +** ^This API may be used to register a callback that SQLite will invoke +** when the connection currently holding the required lock relinquishes it. +** ^This API is only available if the library was compiled with the +** [SQLITE_ENABLE_UNLOCK_NOTIFY] C-preprocessor symbol defined. +** +** See Also: [Using the SQLite Unlock Notification Feature]. +** +** ^Shared-cache locks are released when a database connection concludes +** its current transaction, either by committing it or rolling it back. +** +** ^When a connection (known as the blocked connection) fails to obtain a +** shared-cache lock and SQLITE_LOCKED is returned to the caller, the +** identity of the database connection (the blocking connection) that +** has locked the required resource is stored internally. ^After an +** application receives an SQLITE_LOCKED error, it may call the +** sqlite3_unlock_notify() method with the blocked connection handle as +** the first argument to register for a callback that will be invoked +** when the blocking connections current transaction is concluded. ^The +** callback is invoked from within the [sqlite3_step] or [sqlite3_close] +** call that concludes the blocking connection's transaction. +** +** ^(If sqlite3_unlock_notify() is called in a multi-threaded application, +** there is a chance that the blocking connection will have already +** concluded its transaction by the time sqlite3_unlock_notify() is invoked. +** If this happens, then the specified callback is invoked immediately, +** from within the call to sqlite3_unlock_notify().)^ +** +** ^If the blocked connection is attempting to obtain a write-lock on a +** shared-cache table, and more than one other connection currently holds +** a read-lock on the same table, then SQLite arbitrarily selects one of +** the other connections to use as the blocking connection. +** +** ^(There may be at most one unlock-notify callback registered by a +** blocked connection. If sqlite3_unlock_notify() is called when the +** blocked connection already has a registered unlock-notify callback, +** then the new callback replaces the old.)^ ^If sqlite3_unlock_notify() is +** called with a NULL pointer as its second argument, then any existing +** unlock-notify callback is canceled. ^The blocked connections +** unlock-notify callback may also be canceled by closing the blocked +** connection using [sqlite3_close()]. +** +** The unlock-notify callback is not reentrant. If an application invokes +** any sqlite3_xxx API functions from within an unlock-notify callback, a +** crash or deadlock may be the result. +** +** ^Unless deadlock is detected (see below), sqlite3_unlock_notify() always +** returns SQLITE_OK. +** +** Callback Invocation Details +** +** When an unlock-notify callback is registered, the application provides a +** single void* pointer that is passed to the callback when it is invoked. +** However, the signature of the callback function allows SQLite to pass +** it an array of void* context pointers. The first argument passed to +** an unlock-notify callback is a pointer to an array of void* pointers, +** and the second is the number of entries in the array. +** +** When a blocking connection's transaction is concluded, there may be +** more than one blocked connection that has registered for an unlock-notify +** callback. ^If two or more such blocked connections have specified the +** same callback function, then instead of invoking the callback function +** multiple times, it is invoked once with the set of void* context pointers +** specified by the blocked connections bundled together into an array. +** This gives the application an opportunity to prioritize any actions +** related to the set of unblocked database connections. +** +** Deadlock Detection +** +** Assuming that after registering for an unlock-notify callback a +** database waits for the callback to be issued before taking any further +** action (a reasonable assumption), then using this API may cause the +** application to deadlock. For example, if connection X is waiting for +** connection Y's transaction to be concluded, and similarly connection +** Y is waiting on connection X's transaction, then neither connection +** will proceed and the system may remain deadlocked indefinitely. +** +** To avoid this scenario, the sqlite3_unlock_notify() performs deadlock +** detection. ^If a given call to sqlite3_unlock_notify() would put the +** system in a deadlocked state, then SQLITE_LOCKED is returned and no +** unlock-notify callback is registered. The system is said to be in +** a deadlocked state if connection A has registered for an unlock-notify +** callback on the conclusion of connection B's transaction, and connection +** B has itself registered for an unlock-notify callback when connection +** A's transaction is concluded. ^Indirect deadlock is also detected, so +** the system is also considered to be deadlocked if connection B has +** registered for an unlock-notify callback on the conclusion of connection +** C's transaction, where connection C is waiting on connection A. ^Any +** number of levels of indirection are allowed. +** +** The "DROP TABLE" Exception +** +** When a call to [sqlite3_step()] returns SQLITE_LOCKED, it is almost +** always appropriate to call sqlite3_unlock_notify(). There is however, +** one exception. When executing a "DROP TABLE" or "DROP INDEX" statement, +** SQLite checks if there are any currently executing SELECT statements +** that belong to the same connection. If there are, SQLITE_LOCKED is +** returned. In this case there is no "blocking connection", so invoking +** sqlite3_unlock_notify() results in the unlock-notify callback being +** invoked immediately. If the application then re-attempts the "DROP TABLE" +** or "DROP INDEX" query, an infinite loop might be the result. +** +** One way around this problem is to check the extended error code returned +** by an sqlite3_step() call. ^(If there is a blocking connection, then the +** extended error code is set to SQLITE_LOCKED_SHAREDCACHE. Otherwise, in +** the special "DROP TABLE/INDEX" case, the extended error code is just +** SQLITE_LOCKED.)^ +*/ +SQLITE_API int sqlite3_unlock_notify( + sqlite3 *pBlocked, /* Waiting connection */ + void (*xNotify)(void **apArg, int nArg), /* Callback function to invoke */ + void *pNotifyArg /* Argument to pass to xNotify */ +); + + +/* +** CAPI3REF: String Comparison +** +** ^The [sqlite3_stricmp()] and [sqlite3_strnicmp()] APIs allow applications +** and extensions to compare the contents of two buffers containing UTF-8 +** strings in a case-independent fashion, using the same definition of "case +** independence" that SQLite uses internally when comparing identifiers. +*/ +SQLITE_API int sqlite3_stricmp(const char *, const char *); +SQLITE_API int sqlite3_strnicmp(const char *, const char *, int); + +/* +** CAPI3REF: String Globbing +* +** ^The [sqlite3_strglob(P,X)] interface returns zero if and only if +** string X matches the [GLOB] pattern P. +** ^The definition of [GLOB] pattern matching used in +** [sqlite3_strglob(P,X)] is the same as for the "X GLOB P" operator in the +** SQL dialect understood by SQLite. ^The [sqlite3_strglob(P,X)] function +** is case sensitive. +** +** Note that this routine returns zero on a match and non-zero if the strings +** do not match, the same as [sqlite3_stricmp()] and [sqlite3_strnicmp()]. +** +** See also: [sqlite3_strlike()]. +*/ +SQLITE_API int sqlite3_strglob(const char *zGlob, const char *zStr); + +/* +** CAPI3REF: String LIKE Matching +* +** ^The [sqlite3_strlike(P,X,E)] interface returns zero if and only if +** string X matches the [LIKE] pattern P with escape character E. +** ^The definition of [LIKE] pattern matching used in +** [sqlite3_strlike(P,X,E)] is the same as for the "X LIKE P ESCAPE E" +** operator in the SQL dialect understood by SQLite. ^For "X LIKE P" without +** the ESCAPE clause, set the E parameter of [sqlite3_strlike(P,X,E)] to 0. +** ^As with the LIKE operator, the [sqlite3_strlike(P,X,E)] function is case +** insensitive - equivalent upper and lower case ASCII characters match +** one another. +** +** ^The [sqlite3_strlike(P,X,E)] function matches Unicode characters, though +** only ASCII characters are case folded. +** +** Note that this routine returns zero on a match and non-zero if the strings +** do not match, the same as [sqlite3_stricmp()] and [sqlite3_strnicmp()]. +** +** See also: [sqlite3_strglob()]. +*/ +SQLITE_API int sqlite3_strlike(const char *zGlob, const char *zStr, unsigned int cEsc); + +/* +** CAPI3REF: Error Logging Interface +** +** ^The [sqlite3_log()] interface writes a message into the [error log] +** established by the [SQLITE_CONFIG_LOG] option to [sqlite3_config()]. +** ^If logging is enabled, the zFormat string and subsequent arguments are +** used with [sqlite3_snprintf()] to generate the final output string. +** +** The sqlite3_log() interface is intended for use by extensions such as +** virtual tables, collating functions, and SQL functions. While there is +** nothing to prevent an application from calling sqlite3_log(), doing so +** is considered bad form. +** +** The zFormat string must not be NULL. +** +** To avoid deadlocks and other threading problems, the sqlite3_log() routine +** will not use dynamically allocated memory. The log message is stored in +** a fixed-length buffer on the stack. If the log message is longer than +** a few hundred characters, it will be truncated to the length of the +** buffer. +*/ +SQLITE_API void sqlite3_log(int iErrCode, const char *zFormat, ...); + +/* +** CAPI3REF: Write-Ahead Log Commit Hook +** METHOD: sqlite3 +** +** ^The [sqlite3_wal_hook()] function is used to register a callback that +** is invoked each time data is committed to a database in wal mode. +** +** ^(The callback is invoked by SQLite after the commit has taken place and +** the associated write-lock on the database released)^, so the implementation +** may read, write or [checkpoint] the database as required. +** +** ^The first parameter passed to the callback function when it is invoked +** is a copy of the third parameter passed to sqlite3_wal_hook() when +** registering the callback. ^The second is a copy of the database handle. +** ^The third parameter is the name of the database that was written to - +** either "main" or the name of an [ATTACH]-ed database. ^The fourth parameter +** is the number of pages currently in the write-ahead log file, +** including those that were just committed. +** +** The callback function should normally return [SQLITE_OK]. ^If an error +** code is returned, that error will propagate back up through the +** SQLite code base to cause the statement that provoked the callback +** to report an error, though the commit will have still occurred. If the +** callback returns [SQLITE_ROW] or [SQLITE_DONE], or if it returns a value +** that does not correspond to any valid SQLite error code, the results +** are undefined. +** +** A single database handle may have at most a single write-ahead log callback +** registered at one time. ^Calling [sqlite3_wal_hook()] replaces any +** previously registered write-ahead log callback. ^The return value is +** a copy of the third parameter from the previous call, if any, or 0. +** ^Note that the [sqlite3_wal_autocheckpoint()] interface and the +** [wal_autocheckpoint pragma] both invoke [sqlite3_wal_hook()] and will +** overwrite any prior [sqlite3_wal_hook()] settings. +*/ +SQLITE_API void *sqlite3_wal_hook( + sqlite3*, + int(*)(void *,sqlite3*,const char*,int), + void* +); + +/* +** CAPI3REF: Configure an auto-checkpoint +** METHOD: sqlite3 +** +** ^The [sqlite3_wal_autocheckpoint(D,N)] is a wrapper around +** [sqlite3_wal_hook()] that causes any database on [database connection] D +** to automatically [checkpoint] +** after committing a transaction if there are N or +** more frames in the [write-ahead log] file. ^Passing zero or +** a negative value as the nFrame parameter disables automatic +** checkpoints entirely. +** +** ^The callback registered by this function replaces any existing callback +** registered using [sqlite3_wal_hook()]. ^Likewise, registering a callback +** using [sqlite3_wal_hook()] disables the automatic checkpoint mechanism +** configured by this function. +** +** ^The [wal_autocheckpoint pragma] can be used to invoke this interface +** from SQL. +** +** ^Checkpoints initiated by this mechanism are +** [sqlite3_wal_checkpoint_v2|PASSIVE]. +** +** ^Every new [database connection] defaults to having the auto-checkpoint +** enabled with a threshold of 1000 or [SQLITE_DEFAULT_WAL_AUTOCHECKPOINT] +** pages. The use of this interface +** is only necessary if the default setting is found to be suboptimal +** for a particular application. +*/ +SQLITE_API int sqlite3_wal_autocheckpoint(sqlite3 *db, int N); + +/* +** CAPI3REF: Checkpoint a database +** METHOD: sqlite3 +** +** ^(The sqlite3_wal_checkpoint(D,X) is equivalent to +** [sqlite3_wal_checkpoint_v2](D,X,[SQLITE_CHECKPOINT_PASSIVE],0,0).)^ +** +** In brief, sqlite3_wal_checkpoint(D,X) causes the content in the +** [write-ahead log] for database X on [database connection] D to be +** transferred into the database file and for the write-ahead log to +** be reset. See the [checkpointing] documentation for addition +** information. +** +** This interface used to be the only way to cause a checkpoint to +** occur. But then the newer and more powerful [sqlite3_wal_checkpoint_v2()] +** interface was added. This interface is retained for backwards +** compatibility and as a convenience for applications that need to manually +** start a callback but which do not need the full power (and corresponding +** complication) of [sqlite3_wal_checkpoint_v2()]. +*/ +SQLITE_API int sqlite3_wal_checkpoint(sqlite3 *db, const char *zDb); + +/* +** CAPI3REF: Checkpoint a database +** METHOD: sqlite3 +** +** ^(The sqlite3_wal_checkpoint_v2(D,X,M,L,C) interface runs a checkpoint +** operation on database X of [database connection] D in mode M. Status +** information is written back into integers pointed to by L and C.)^ +** ^(The M parameter must be a valid [checkpoint mode]:)^ +** +**
    +**
    SQLITE_CHECKPOINT_PASSIVE
    +** ^Checkpoint as many frames as possible without waiting for any database +** readers or writers to finish, then sync the database file if all frames +** in the log were checkpointed. ^The [busy-handler callback] +** is never invoked in the SQLITE_CHECKPOINT_PASSIVE mode. +** ^On the other hand, passive mode might leave the checkpoint unfinished +** if there are concurrent readers or writers. +** +**
    SQLITE_CHECKPOINT_FULL
    +** ^This mode blocks (it invokes the +** [sqlite3_busy_handler|busy-handler callback]) until there is no +** database writer and all readers are reading from the most recent database +** snapshot. ^It then checkpoints all frames in the log file and syncs the +** database file. ^This mode blocks new database writers while it is pending, +** but new database readers are allowed to continue unimpeded. +** +**
    SQLITE_CHECKPOINT_RESTART
    +** ^This mode works the same way as SQLITE_CHECKPOINT_FULL with the addition +** that after checkpointing the log file it blocks (calls the +** [busy-handler callback]) +** until all readers are reading from the database file only. ^This ensures +** that the next writer will restart the log file from the beginning. +** ^Like SQLITE_CHECKPOINT_FULL, this mode blocks new +** database writer attempts while it is pending, but does not impede readers. +** +**
    SQLITE_CHECKPOINT_TRUNCATE
    +** ^This mode works the same way as SQLITE_CHECKPOINT_RESTART with the +** addition that it also truncates the log file to zero bytes just prior +** to a successful return. +**
    +** +** ^If pnLog is not NULL, then *pnLog is set to the total number of frames in +** the log file or to -1 if the checkpoint could not run because +** of an error or because the database is not in [WAL mode]. ^If pnCkpt is not +** NULL,then *pnCkpt is set to the total number of checkpointed frames in the +** log file (including any that were already checkpointed before the function +** was called) or to -1 if the checkpoint could not run due to an error or +** because the database is not in WAL mode. ^Note that upon successful +** completion of an SQLITE_CHECKPOINT_TRUNCATE, the log file will have been +** truncated to zero bytes and so both *pnLog and *pnCkpt will be set to zero. +** +** ^All calls obtain an exclusive "checkpoint" lock on the database file. ^If +** any other process is running a checkpoint operation at the same time, the +** lock cannot be obtained and SQLITE_BUSY is returned. ^Even if there is a +** busy-handler configured, it will not be invoked in this case. +** +** ^The SQLITE_CHECKPOINT_FULL, RESTART and TRUNCATE modes also obtain the +** exclusive "writer" lock on the database file. ^If the writer lock cannot be +** obtained immediately, and a busy-handler is configured, it is invoked and +** the writer lock retried until either the busy-handler returns 0 or the lock +** is successfully obtained. ^The busy-handler is also invoked while waiting for +** database readers as described above. ^If the busy-handler returns 0 before +** the writer lock is obtained or while waiting for database readers, the +** checkpoint operation proceeds from that point in the same way as +** SQLITE_CHECKPOINT_PASSIVE - checkpointing as many frames as possible +** without blocking any further. ^SQLITE_BUSY is returned in this case. +** +** ^If parameter zDb is NULL or points to a zero length string, then the +** specified operation is attempted on all WAL databases [attached] to +** [database connection] db. In this case the +** values written to output parameters *pnLog and *pnCkpt are undefined. ^If +** an SQLITE_BUSY error is encountered when processing one or more of the +** attached WAL databases, the operation is still attempted on any remaining +** attached databases and SQLITE_BUSY is returned at the end. ^If any other +** error occurs while processing an attached database, processing is abandoned +** and the error code is returned to the caller immediately. ^If no error +** (SQLITE_BUSY or otherwise) is encountered while processing the attached +** databases, SQLITE_OK is returned. +** +** ^If database zDb is the name of an attached database that is not in WAL +** mode, SQLITE_OK is returned and both *pnLog and *pnCkpt set to -1. ^If +** zDb is not NULL (or a zero length string) and is not the name of any +** attached database, SQLITE_ERROR is returned to the caller. +** +** ^Unless it returns SQLITE_MISUSE, +** the sqlite3_wal_checkpoint_v2() interface +** sets the error information that is queried by +** [sqlite3_errcode()] and [sqlite3_errmsg()]. +** +** ^The [PRAGMA wal_checkpoint] command can be used to invoke this interface +** from SQL. +*/ +SQLITE_API int sqlite3_wal_checkpoint_v2( + sqlite3 *db, /* Database handle */ + const char *zDb, /* Name of attached database (or NULL) */ + int eMode, /* SQLITE_CHECKPOINT_* value */ + int *pnLog, /* OUT: Size of WAL log in frames */ + int *pnCkpt /* OUT: Total number of frames checkpointed */ +); + +/* +** CAPI3REF: Checkpoint Mode Values +** KEYWORDS: {checkpoint mode} +** +** These constants define all valid values for the "checkpoint mode" passed +** as the third parameter to the [sqlite3_wal_checkpoint_v2()] interface. +** See the [sqlite3_wal_checkpoint_v2()] documentation for details on the +** meaning of each of these checkpoint modes. +*/ +#define SQLITE_CHECKPOINT_PASSIVE 0 /* Do as much as possible w/o blocking */ +#define SQLITE_CHECKPOINT_FULL 1 /* Wait for writers, then checkpoint */ +#define SQLITE_CHECKPOINT_RESTART 2 /* Like FULL but wait for for readers */ +#define SQLITE_CHECKPOINT_TRUNCATE 3 /* Like RESTART but also truncate WAL */ + +/* +** CAPI3REF: Virtual Table Interface Configuration +** +** This function may be called by either the [xConnect] or [xCreate] method +** of a [virtual table] implementation to configure +** various facets of the virtual table interface. +** +** If this interface is invoked outside the context of an xConnect or +** xCreate virtual table method then the behavior is undefined. +** +** In the call sqlite3_vtab_config(D,C,...) the D parameter is the +** [database connection] in which the virtual table is being created and +** which is passed in as the first argument to the [xConnect] or [xCreate] +** method that is invoking sqlite3_vtab_config(). The C parameter is one +** of the [virtual table configuration options]. The presence and meaning +** of parameters after C depend on which [virtual table configuration option] +** is used. +*/ +SQLITE_API int sqlite3_vtab_config(sqlite3*, int op, ...); + +/* +** CAPI3REF: Virtual Table Configuration Options +** KEYWORDS: {virtual table configuration options} +** KEYWORDS: {virtual table configuration option} +** +** These macros define the various options to the +** [sqlite3_vtab_config()] interface that [virtual table] implementations +** can use to customize and optimize their behavior. +** +**
    +** [[SQLITE_VTAB_CONSTRAINT_SUPPORT]] +**
    SQLITE_VTAB_CONSTRAINT_SUPPORT
    +**
    Calls of the form +** [sqlite3_vtab_config](db,SQLITE_VTAB_CONSTRAINT_SUPPORT,X) are supported, +** where X is an integer. If X is zero, then the [virtual table] whose +** [xCreate] or [xConnect] method invoked [sqlite3_vtab_config()] does not +** support constraints. In this configuration (which is the default) if +** a call to the [xUpdate] method returns [SQLITE_CONSTRAINT], then the entire +** statement is rolled back as if [ON CONFLICT | OR ABORT] had been +** specified as part of the users SQL statement, regardless of the actual +** ON CONFLICT mode specified. +** +** If X is non-zero, then the virtual table implementation guarantees +** that if [xUpdate] returns [SQLITE_CONSTRAINT], it will do so before +** any modifications to internal or persistent data structures have been made. +** If the [ON CONFLICT] mode is ABORT, FAIL, IGNORE or ROLLBACK, SQLite +** is able to roll back a statement or database transaction, and abandon +** or continue processing the current SQL statement as appropriate. +** If the ON CONFLICT mode is REPLACE and the [xUpdate] method returns +** [SQLITE_CONSTRAINT], SQLite handles this as if the ON CONFLICT mode +** had been ABORT. +** +** Virtual table implementations that are required to handle OR REPLACE +** must do so within the [xUpdate] method. If a call to the +** [sqlite3_vtab_on_conflict()] function indicates that the current ON +** CONFLICT policy is REPLACE, the virtual table implementation should +** silently replace the appropriate rows within the xUpdate callback and +** return SQLITE_OK. Or, if this is not possible, it may return +** SQLITE_CONSTRAINT, in which case SQLite falls back to OR ABORT +** constraint handling. +**
    +** +** [[SQLITE_VTAB_DIRECTONLY]]
    SQLITE_VTAB_DIRECTONLY
    +**
    Calls of the form +** [sqlite3_vtab_config](db,SQLITE_VTAB_DIRECTONLY) from within the +** the [xConnect] or [xCreate] methods of a [virtual table] implmentation +** prohibits that virtual table from being used from within triggers and +** views. +**
    +** +** [[SQLITE_VTAB_INNOCUOUS]]
    SQLITE_VTAB_INNOCUOUS
    +**
    Calls of the form +** [sqlite3_vtab_config](db,SQLITE_VTAB_INNOCUOUS) from within the +** the [xConnect] or [xCreate] methods of a [virtual table] implmentation +** identify that virtual table as being safe to use from within triggers +** and views. Conceptually, the SQLITE_VTAB_INNOCUOUS tag means that the +** virtual table can do no serious harm even if it is controlled by a +** malicious hacker. Developers should avoid setting the SQLITE_VTAB_INNOCUOUS +** flag unless absolutely necessary. +**
    +**
    +*/ +#define SQLITE_VTAB_CONSTRAINT_SUPPORT 1 +#define SQLITE_VTAB_INNOCUOUS 2 +#define SQLITE_VTAB_DIRECTONLY 3 + +/* +** CAPI3REF: Determine The Virtual Table Conflict Policy +** +** This function may only be called from within a call to the [xUpdate] method +** of a [virtual table] implementation for an INSERT or UPDATE operation. ^The +** value returned is one of [SQLITE_ROLLBACK], [SQLITE_IGNORE], [SQLITE_FAIL], +** [SQLITE_ABORT], or [SQLITE_REPLACE], according to the [ON CONFLICT] mode +** of the SQL statement that triggered the call to the [xUpdate] method of the +** [virtual table]. +*/ +SQLITE_API int sqlite3_vtab_on_conflict(sqlite3 *); + +/* +** CAPI3REF: Determine If Virtual Table Column Access Is For UPDATE +** +** If the sqlite3_vtab_nochange(X) routine is called within the [xColumn] +** method of a [virtual table], then it might return true if the +** column is being fetched as part of an UPDATE operation during which the +** column value will not change. The virtual table implementation can use +** this hint as permission to substitute a return value that is less +** expensive to compute and that the corresponding +** [xUpdate] method understands as a "no-change" value. +** +** If the [xColumn] method calls sqlite3_vtab_nochange() and finds that +** the column is not changed by the UPDATE statement, then the xColumn +** method can optionally return without setting a result, without calling +** any of the [sqlite3_result_int|sqlite3_result_xxxxx() interfaces]. +** In that case, [sqlite3_value_nochange(X)] will return true for the +** same column in the [xUpdate] method. +** +** The sqlite3_vtab_nochange() routine is an optimization. Virtual table +** implementations should continue to give a correct answer even if the +** sqlite3_vtab_nochange() interface were to always return false. In the +** current implementation, the sqlite3_vtab_nochange() interface does always +** returns false for the enhanced [UPDATE FROM] statement. +*/ +SQLITE_API int sqlite3_vtab_nochange(sqlite3_context*); + +/* +** CAPI3REF: Determine The Collation For a Virtual Table Constraint +** METHOD: sqlite3_index_info +** +** This function may only be called from within a call to the [xBestIndex] +** method of a [virtual table]. This function returns a pointer to a string +** that is the name of the appropriate collation sequence to use for text +** comparisons on the constraint identified by its arguments. +** +** The first argument must be the pointer to the [sqlite3_index_info] object +** that is the first parameter to the xBestIndex() method. The second argument +** must be an index into the aConstraint[] array belonging to the +** sqlite3_index_info structure passed to xBestIndex. +** +** Important: +** The first parameter must be the same pointer that is passed into the +** xBestMethod() method. The first parameter may not be a pointer to a +** different [sqlite3_index_info] object, even an exact copy. +** +** The return value is computed as follows: +** +**
      +**
    1. If the constraint comes from a WHERE clause expression that contains +** a [COLLATE operator], then the name of the collation specified by +** that COLLATE operator is returned. +**

    2. If there is no COLLATE operator, but the column that is the subject +** of the constraint specifies an alternative collating sequence via +** a [COLLATE clause] on the column definition within the CREATE TABLE +** statement that was passed into [sqlite3_declare_vtab()], then the +** name of that alternative collating sequence is returned. +**

    3. Otherwise, "BINARY" is returned. +**

    +*/ +SQLITE_API SQLITE_EXPERIMENTAL const char *sqlite3_vtab_collation(sqlite3_index_info*,int); + +/* +** CAPI3REF: Determine if a virtual table query is DISTINCT +** METHOD: sqlite3_index_info +** +** This API may only be used from within an [xBestIndex|xBestIndex method] +** of a [virtual table] implementation. The result of calling this +** interface from outside of xBestIndex() is undefined and probably harmful. +** +** ^The sqlite3_vtab_distinct() interface returns an integer that is +** either 0, 1, or 2. The integer returned by sqlite3_vtab_distinct() +** gives the virtual table additional information about how the query +** planner wants the output to be ordered. As long as the virtual table +** can meet the ordering requirements of the query planner, it may set +** the "orderByConsumed" flag. +** +**
    1. +** ^If the sqlite3_vtab_distinct() interface returns 0, that means +** that the query planner needs the virtual table to return all rows in the +** sort order defined by the "nOrderBy" and "aOrderBy" fields of the +** [sqlite3_index_info] object. This is the default expectation. If the +** virtual table outputs all rows in sorted order, then it is always safe for +** the xBestIndex method to set the "orderByConsumed" flag, regardless of +** the return value from sqlite3_vtab_distinct(). +**

    2. +** ^(If the sqlite3_vtab_distinct() interface returns 1, that means +** that the query planner does not need the rows to be returned in sorted order +** as long as all rows with the same values in all columns identified by the +** "aOrderBy" field are adjacent.)^ This mode is used when the query planner +** is doing a GROUP BY. +**

    3. +** ^(If the sqlite3_vtab_distinct() interface returns 2, that means +** that the query planner does not need the rows returned in any particular +** order, as long as rows with the same values in all "aOrderBy" columns +** are adjacent.)^ ^(Furthermore, only a single row for each particular +** combination of values in the columns identified by the "aOrderBy" field +** needs to be returned.)^ ^It is always ok for two or more rows with the same +** values in all "aOrderBy" columns to be returned, as long as all such rows +** are adjacent. ^The virtual table may, if it chooses, omit extra rows +** that have the same value for all columns identified by "aOrderBy". +** ^However omitting the extra rows is optional. +** This mode is used for a DISTINCT query. +**

    +** +** ^For the purposes of comparing virtual table output values to see if the +** values are same value for sorting purposes, two NULL values are considered +** to be the same. In other words, the comparison operator is "IS" +** (or "IS NOT DISTINCT FROM") and not "==". +** +** If a virtual table implementation is unable to meet the requirements +** specified above, then it must not set the "orderByConsumed" flag in the +** [sqlite3_index_info] object or an incorrect answer may result. +** +** ^A virtual table implementation is always free to return rows in any order +** it wants, as long as the "orderByConsumed" flag is not set. ^When the +** the "orderByConsumed" flag is unset, the query planner will add extra +** [bytecode] to ensure that the final results returned by the SQL query are +** ordered correctly. The use of the "orderByConsumed" flag and the +** sqlite3_vtab_distinct() interface is merely an optimization. ^Careful +** use of the sqlite3_vtab_distinct() interface and the "orderByConsumed" +** flag might help queries against a virtual table to run faster. Being +** overly aggressive and setting the "orderByConsumed" flag when it is not +** valid to do so, on the other hand, might cause SQLite to return incorrect +** results. +*/ +SQLITE_API int sqlite3_vtab_distinct(sqlite3_index_info*); + +/* +** CAPI3REF: Identify and handle IN constraints in xBestIndex +** +** This interface may only be used from within an +** [xBestIndex|xBestIndex() method] of a [virtual table] implementation. +** The result of invoking this interface from any other context is +** undefined and probably harmful. +** +** ^(A constraint on a virtual table of the form +** "[IN operator|column IN (...)]" is +** communicated to the xBestIndex method as a +** [SQLITE_INDEX_CONSTRAINT_EQ] constraint.)^ If xBestIndex wants to use +** this constraint, it must set the corresponding +** aConstraintUsage[].argvIndex to a postive integer. ^(Then, under +** the usual mode of handling IN operators, SQLite generates [bytecode] +** that invokes the [xFilter|xFilter() method] once for each value +** on the right-hand side of the IN operator.)^ Thus the virtual table +** only sees a single value from the right-hand side of the IN operator +** at a time. +** +** In some cases, however, it would be advantageous for the virtual +** table to see all values on the right-hand of the IN operator all at +** once. The sqlite3_vtab_in() interfaces facilitates this in two ways: +** +**
      +**
    1. +** ^A call to sqlite3_vtab_in(P,N,-1) will return true (non-zero) +** if and only if the [sqlite3_index_info|P->aConstraint][N] constraint +** is an [IN operator] that can be processed all at once. ^In other words, +** sqlite3_vtab_in() with -1 in the third argument is a mechanism +** by which the virtual table can ask SQLite if all-at-once processing +** of the IN operator is even possible. +** +**

    2. +** ^A call to sqlite3_vtab_in(P,N,F) with F==1 or F==0 indicates +** to SQLite that the virtual table does or does not want to process +** the IN operator all-at-once, respectively. ^Thus when the third +** parameter (F) is non-negative, this interface is the mechanism by +** which the virtual table tells SQLite how it wants to process the +** IN operator. +**

    +** +** ^The sqlite3_vtab_in(P,N,F) interface can be invoked multiple times +** within the same xBestIndex method call. ^For any given P,N pair, +** the return value from sqlite3_vtab_in(P,N,F) will always be the same +** within the same xBestIndex call. ^If the interface returns true +** (non-zero), that means that the constraint is an IN operator +** that can be processed all-at-once. ^If the constraint is not an IN +** operator or cannot be processed all-at-once, then the interface returns +** false. +** +** ^(All-at-once processing of the IN operator is selected if both of the +** following conditions are met: +** +**
      +**
    1. The P->aConstraintUsage[N].argvIndex value is set to a positive +** integer. This is how the virtual table tells SQLite that it wants to +** use the N-th constraint. +** +**

    2. The last call to sqlite3_vtab_in(P,N,F) for which F was +** non-negative had F>=1. +**

    )^ +** +** ^If either or both of the conditions above are false, then SQLite uses +** the traditional one-at-a-time processing strategy for the IN constraint. +** ^If both conditions are true, then the argvIndex-th parameter to the +** xFilter method will be an [sqlite3_value] that appears to be NULL, +** but which can be passed to [sqlite3_vtab_in_first()] and +** [sqlite3_vtab_in_next()] to find all values on the right-hand side +** of the IN constraint. +*/ +SQLITE_API int sqlite3_vtab_in(sqlite3_index_info*, int iCons, int bHandle); + +/* +** CAPI3REF: Find all elements on the right-hand side of an IN constraint. +** +** These interfaces are only useful from within the +** [xFilter|xFilter() method] of a [virtual table] implementation. +** The result of invoking these interfaces from any other context +** is undefined and probably harmful. +** +** The X parameter in a call to sqlite3_vtab_in_first(X,P) or +** sqlite3_vtab_in_next(X,P) must be one of the parameters to the +** xFilter method which invokes these routines, and specifically +** a parameter that was previously selected for all-at-once IN constraint +** processing use the [sqlite3_vtab_in()] interface in the +** [xBestIndex|xBestIndex method]. ^(If the X parameter is not +** an xFilter argument that was selected for all-at-once IN constraint +** processing, then these routines return [SQLITE_MISUSE])^ or perhaps +** exhibit some other undefined or harmful behavior. +** +** ^(Use these routines to access all values on the right-hand side +** of the IN constraint using code like the following: +** +**
    +**    for(rc=sqlite3_vtab_in_first(pList, &pVal);
    +**        rc==SQLITE_OK && pVal
    +**        rc=sqlite3_vtab_in_next(pList, &pVal)
    +**    ){
    +**      // do something with pVal
    +**    }
    +**    if( rc!=SQLITE_OK ){
    +**      // an error has occurred
    +**    }
    +** 
    )^ +** +** ^On success, the sqlite3_vtab_in_first(X,P) and sqlite3_vtab_in_next(X,P) +** routines return SQLITE_OK and set *P to point to the first or next value +** on the RHS of the IN constraint. ^If there are no more values on the +** right hand side of the IN constraint, then *P is set to NULL and these +** routines return [SQLITE_DONE]. ^The return value might be +** some other value, such as SQLITE_NOMEM, in the event of a malfunction. +** +** The *ppOut values returned by these routines are only valid until the +** next call to either of these routines or until the end of the xFilter +** method from which these routines were called. If the virtual table +** implementation needs to retain the *ppOut values for longer, it must make +** copies. The *ppOut values are [protected sqlite3_value|protected]. +*/ +SQLITE_API int sqlite3_vtab_in_first(sqlite3_value *pVal, sqlite3_value **ppOut); +SQLITE_API int sqlite3_vtab_in_next(sqlite3_value *pVal, sqlite3_value **ppOut); + +/* +** CAPI3REF: Constraint values in xBestIndex() +** METHOD: sqlite3_index_info +** +** This API may only be used from within the [xBestIndex|xBestIndex method] +** of a [virtual table] implementation. The result of calling this interface +** from outside of an xBestIndex method are undefined and probably harmful. +** +** ^When the sqlite3_vtab_rhs_value(P,J,V) interface is invoked from within +** the [xBestIndex] method of a [virtual table] implementation, with P being +** a copy of the [sqlite3_index_info] object pointer passed into xBestIndex and +** J being a 0-based index into P->aConstraint[], then this routine +** attempts to set *V to the value of the right-hand operand of +** that constraint if the right-hand operand is known. ^If the +** right-hand operand is not known, then *V is set to a NULL pointer. +** ^The sqlite3_vtab_rhs_value(P,J,V) interface returns SQLITE_OK if +** and only if *V is set to a value. ^The sqlite3_vtab_rhs_value(P,J,V) +** inteface returns SQLITE_NOTFOUND if the right-hand side of the J-th +** constraint is not available. ^The sqlite3_vtab_rhs_value() interface +** can return an result code other than SQLITE_OK or SQLITE_NOTFOUND if +** something goes wrong. +** +** The sqlite3_vtab_rhs_value() interface is usually only successful if +** the right-hand operand of a constraint is a literal value in the original +** SQL statement. If the right-hand operand is an expression or a reference +** to some other column or a [host parameter], then sqlite3_vtab_rhs_value() +** will probably return [SQLITE_NOTFOUND]. +** +** ^(Some constraints, such as [SQLITE_INDEX_CONSTRAINT_ISNULL] and +** [SQLITE_INDEX_CONSTRAINT_ISNOTNULL], have no right-hand operand. For such +** constraints, sqlite3_vtab_rhs_value() always returns SQLITE_NOTFOUND.)^ +** +** ^The [sqlite3_value] object returned in *V is a protected sqlite3_value +** and remains valid for the duration of the xBestIndex method call. +** ^When xBestIndex returns, the sqlite3_value object returned by +** sqlite3_vtab_rhs_value() is automatically deallocated. +** +** The "_rhs_" in the name of this routine is an abbreviation for +** "Right-Hand Side". +*/ +SQLITE_API int sqlite3_vtab_rhs_value(sqlite3_index_info*, int, sqlite3_value **ppVal); + +/* +** CAPI3REF: Conflict resolution modes +** KEYWORDS: {conflict resolution mode} +** +** These constants are returned by [sqlite3_vtab_on_conflict()] to +** inform a [virtual table] implementation what the [ON CONFLICT] mode +** is for the SQL statement being evaluated. +** +** Note that the [SQLITE_IGNORE] constant is also used as a potential +** return value from the [sqlite3_set_authorizer()] callback and that +** [SQLITE_ABORT] is also a [result code]. +*/ +#define SQLITE_ROLLBACK 1 +/* #define SQLITE_IGNORE 2 // Also used by sqlite3_authorizer() callback */ +#define SQLITE_FAIL 3 +/* #define SQLITE_ABORT 4 // Also an error code */ +#define SQLITE_REPLACE 5 + +/* +** CAPI3REF: Prepared Statement Scan Status Opcodes +** KEYWORDS: {scanstatus options} +** +** The following constants can be used for the T parameter to the +** [sqlite3_stmt_scanstatus(S,X,T,V)] interface. Each constant designates a +** different metric for sqlite3_stmt_scanstatus() to return. +** +** When the value returned to V is a string, space to hold that string is +** managed by the prepared statement S and will be automatically freed when +** S is finalized. +** +**
    +** [[SQLITE_SCANSTAT_NLOOP]]
    SQLITE_SCANSTAT_NLOOP
    +**
    ^The [sqlite3_int64] variable pointed to by the V parameter will be +** set to the total number of times that the X-th loop has run.
    +** +** [[SQLITE_SCANSTAT_NVISIT]]
    SQLITE_SCANSTAT_NVISIT
    +**
    ^The [sqlite3_int64] variable pointed to by the V parameter will be set +** to the total number of rows examined by all iterations of the X-th loop.
    +** +** [[SQLITE_SCANSTAT_EST]]
    SQLITE_SCANSTAT_EST
    +**
    ^The "double" variable pointed to by the V parameter will be set to the +** query planner's estimate for the average number of rows output from each +** iteration of the X-th loop. If the query planner's estimates was accurate, +** then this value will approximate the quotient NVISIT/NLOOP and the +** product of this value for all prior loops with the same SELECTID will +** be the NLOOP value for the current loop. +** +** [[SQLITE_SCANSTAT_NAME]]
    SQLITE_SCANSTAT_NAME
    +**
    ^The "const char *" variable pointed to by the V parameter will be set +** to a zero-terminated UTF-8 string containing the name of the index or table +** used for the X-th loop. +** +** [[SQLITE_SCANSTAT_EXPLAIN]]
    SQLITE_SCANSTAT_EXPLAIN
    +**
    ^The "const char *" variable pointed to by the V parameter will be set +** to a zero-terminated UTF-8 string containing the [EXPLAIN QUERY PLAN] +** description for the X-th loop. +** +** [[SQLITE_SCANSTAT_SELECTID]]
    SQLITE_SCANSTAT_SELECT
    +**
    ^The "int" variable pointed to by the V parameter will be set to the +** "select-id" for the X-th loop. The select-id identifies which query or +** subquery the loop is part of. The main query has a select-id of zero. +** The select-id is the same value as is output in the first column +** of an [EXPLAIN QUERY PLAN] query. +**
    +*/ +#define SQLITE_SCANSTAT_NLOOP 0 +#define SQLITE_SCANSTAT_NVISIT 1 +#define SQLITE_SCANSTAT_EST 2 +#define SQLITE_SCANSTAT_NAME 3 +#define SQLITE_SCANSTAT_EXPLAIN 4 +#define SQLITE_SCANSTAT_SELECTID 5 + +/* +** CAPI3REF: Prepared Statement Scan Status +** METHOD: sqlite3_stmt +** +** This interface returns information about the predicted and measured +** performance for pStmt. Advanced applications can use this +** interface to compare the predicted and the measured performance and +** issue warnings and/or rerun [ANALYZE] if discrepancies are found. +** +** Since this interface is expected to be rarely used, it is only +** available if SQLite is compiled using the [SQLITE_ENABLE_STMT_SCANSTATUS] +** compile-time option. +** +** The "iScanStatusOp" parameter determines which status information to return. +** The "iScanStatusOp" must be one of the [scanstatus options] or the behavior +** of this interface is undefined. +** ^The requested measurement is written into a variable pointed to by +** the "pOut" parameter. +** Parameter "idx" identifies the specific loop to retrieve statistics for. +** Loops are numbered starting from zero. ^If idx is out of range - less than +** zero or greater than or equal to the total number of loops used to implement +** the statement - a non-zero value is returned and the variable that pOut +** points to is unchanged. +** +** ^Statistics might not be available for all loops in all statements. ^In cases +** where there exist loops with no available statistics, this function behaves +** as if the loop did not exist - it returns non-zero and leave the variable +** that pOut points to unchanged. +** +** See also: [sqlite3_stmt_scanstatus_reset()] +*/ +SQLITE_API int sqlite3_stmt_scanstatus( + sqlite3_stmt *pStmt, /* Prepared statement for which info desired */ + int idx, /* Index of loop to report on */ + int iScanStatusOp, /* Information desired. SQLITE_SCANSTAT_* */ + void *pOut /* Result written here */ +); + +/* +** CAPI3REF: Zero Scan-Status Counters +** METHOD: sqlite3_stmt +** +** ^Zero all [sqlite3_stmt_scanstatus()] related event counters. +** +** This API is only available if the library is built with pre-processor +** symbol [SQLITE_ENABLE_STMT_SCANSTATUS] defined. +*/ +SQLITE_API void sqlite3_stmt_scanstatus_reset(sqlite3_stmt*); + +/* +** CAPI3REF: Flush caches to disk mid-transaction +** METHOD: sqlite3 +** +** ^If a write-transaction is open on [database connection] D when the +** [sqlite3_db_cacheflush(D)] interface invoked, any dirty +** pages in the pager-cache that are not currently in use are written out +** to disk. A dirty page may be in use if a database cursor created by an +** active SQL statement is reading from it, or if it is page 1 of a database +** file (page 1 is always "in use"). ^The [sqlite3_db_cacheflush(D)] +** interface flushes caches for all schemas - "main", "temp", and +** any [attached] databases. +** +** ^If this function needs to obtain extra database locks before dirty pages +** can be flushed to disk, it does so. ^If those locks cannot be obtained +** immediately and there is a busy-handler callback configured, it is invoked +** in the usual manner. ^If the required lock still cannot be obtained, then +** the database is skipped and an attempt made to flush any dirty pages +** belonging to the next (if any) database. ^If any databases are skipped +** because locks cannot be obtained, but no other error occurs, this +** function returns SQLITE_BUSY. +** +** ^If any other error occurs while flushing dirty pages to disk (for +** example an IO error or out-of-memory condition), then processing is +** abandoned and an SQLite [error code] is returned to the caller immediately. +** +** ^Otherwise, if no error occurs, [sqlite3_db_cacheflush()] returns SQLITE_OK. +** +** ^This function does not set the database handle error code or message +** returned by the [sqlite3_errcode()] and [sqlite3_errmsg()] functions. +*/ +SQLITE_API int sqlite3_db_cacheflush(sqlite3*); + +/* +** CAPI3REF: The pre-update hook. +** METHOD: sqlite3 +** +** ^These interfaces are only available if SQLite is compiled using the +** [SQLITE_ENABLE_PREUPDATE_HOOK] compile-time option. +** +** ^The [sqlite3_preupdate_hook()] interface registers a callback function +** that is invoked prior to each [INSERT], [UPDATE], and [DELETE] operation +** on a database table. +** ^At most one preupdate hook may be registered at a time on a single +** [database connection]; each call to [sqlite3_preupdate_hook()] overrides +** the previous setting. +** ^The preupdate hook is disabled by invoking [sqlite3_preupdate_hook()] +** with a NULL pointer as the second parameter. +** ^The third parameter to [sqlite3_preupdate_hook()] is passed through as +** the first parameter to callbacks. +** +** ^The preupdate hook only fires for changes to real database tables; the +** preupdate hook is not invoked for changes to [virtual tables] or to +** system tables like sqlite_sequence or sqlite_stat1. +** +** ^The second parameter to the preupdate callback is a pointer to +** the [database connection] that registered the preupdate hook. +** ^The third parameter to the preupdate callback is one of the constants +** [SQLITE_INSERT], [SQLITE_DELETE], or [SQLITE_UPDATE] to identify the +** kind of update operation that is about to occur. +** ^(The fourth parameter to the preupdate callback is the name of the +** database within the database connection that is being modified. This +** will be "main" for the main database or "temp" for TEMP tables or +** the name given after the AS keyword in the [ATTACH] statement for attached +** databases.)^ +** ^The fifth parameter to the preupdate callback is the name of the +** table that is being modified. +** +** For an UPDATE or DELETE operation on a [rowid table], the sixth +** parameter passed to the preupdate callback is the initial [rowid] of the +** row being modified or deleted. For an INSERT operation on a rowid table, +** or any operation on a WITHOUT ROWID table, the value of the sixth +** parameter is undefined. For an INSERT or UPDATE on a rowid table the +** seventh parameter is the final rowid value of the row being inserted +** or updated. The value of the seventh parameter passed to the callback +** function is not defined for operations on WITHOUT ROWID tables, or for +** DELETE operations on rowid tables. +** +** The [sqlite3_preupdate_old()], [sqlite3_preupdate_new()], +** [sqlite3_preupdate_count()], and [sqlite3_preupdate_depth()] interfaces +** provide additional information about a preupdate event. These routines +** may only be called from within a preupdate callback. Invoking any of +** these routines from outside of a preupdate callback or with a +** [database connection] pointer that is different from the one supplied +** to the preupdate callback results in undefined and probably undesirable +** behavior. +** +** ^The [sqlite3_preupdate_count(D)] interface returns the number of columns +** in the row that is being inserted, updated, or deleted. +** +** ^The [sqlite3_preupdate_old(D,N,P)] interface writes into P a pointer to +** a [protected sqlite3_value] that contains the value of the Nth column of +** the table row before it is updated. The N parameter must be between 0 +** and one less than the number of columns or the behavior will be +** undefined. This must only be used within SQLITE_UPDATE and SQLITE_DELETE +** preupdate callbacks; if it is used by an SQLITE_INSERT callback then the +** behavior is undefined. The [sqlite3_value] that P points to +** will be destroyed when the preupdate callback returns. +** +** ^The [sqlite3_preupdate_new(D,N,P)] interface writes into P a pointer to +** a [protected sqlite3_value] that contains the value of the Nth column of +** the table row after it is updated. The N parameter must be between 0 +** and one less than the number of columns or the behavior will be +** undefined. This must only be used within SQLITE_INSERT and SQLITE_UPDATE +** preupdate callbacks; if it is used by an SQLITE_DELETE callback then the +** behavior is undefined. The [sqlite3_value] that P points to +** will be destroyed when the preupdate callback returns. +** +** ^The [sqlite3_preupdate_depth(D)] interface returns 0 if the preupdate +** callback was invoked as a result of a direct insert, update, or delete +** operation; or 1 for inserts, updates, or deletes invoked by top-level +** triggers; or 2 for changes resulting from triggers called by top-level +** triggers; and so forth. +** +** When the [sqlite3_blob_write()] API is used to update a blob column, +** the pre-update hook is invoked with SQLITE_DELETE. This is because the +** in this case the new values are not available. In this case, when a +** callback made with op==SQLITE_DELETE is actuall a write using the +** sqlite3_blob_write() API, the [sqlite3_preupdate_blobwrite()] returns +** the index of the column being written. In other cases, where the +** pre-update hook is being invoked for some other reason, including a +** regular DELETE, sqlite3_preupdate_blobwrite() returns -1. +** +** See also: [sqlite3_update_hook()] +*/ +#if defined(SQLITE_ENABLE_PREUPDATE_HOOK) +SQLITE_API void *sqlite3_preupdate_hook( + sqlite3 *db, + void(*xPreUpdate)( + void *pCtx, /* Copy of third arg to preupdate_hook() */ + sqlite3 *db, /* Database handle */ + int op, /* SQLITE_UPDATE, DELETE or INSERT */ + char const *zDb, /* Database name */ + char const *zName, /* Table name */ + sqlite3_int64 iKey1, /* Rowid of row about to be deleted/updated */ + sqlite3_int64 iKey2 /* New rowid value (for a rowid UPDATE) */ + ), + void* +); +SQLITE_API int sqlite3_preupdate_old(sqlite3 *, int, sqlite3_value **); +SQLITE_API int sqlite3_preupdate_count(sqlite3 *); +SQLITE_API int sqlite3_preupdate_depth(sqlite3 *); +SQLITE_API int sqlite3_preupdate_new(sqlite3 *, int, sqlite3_value **); +SQLITE_API int sqlite3_preupdate_blobwrite(sqlite3 *); +#endif + +/* +** CAPI3REF: Low-level system error code +** METHOD: sqlite3 +** +** ^Attempt to return the underlying operating system error code or error +** number that caused the most recent I/O error or failure to open a file. +** The return value is OS-dependent. For example, on unix systems, after +** [sqlite3_open_v2()] returns [SQLITE_CANTOPEN], this interface could be +** called to get back the underlying "errno" that caused the problem, such +** as ENOSPC, EAUTH, EISDIR, and so forth. +*/ +SQLITE_API int sqlite3_system_errno(sqlite3*); + +/* +** CAPI3REF: Database Snapshot +** KEYWORDS: {snapshot} {sqlite3_snapshot} +** +** An instance of the snapshot object records the state of a [WAL mode] +** database for some specific point in history. +** +** In [WAL mode], multiple [database connections] that are open on the +** same database file can each be reading a different historical version +** of the database file. When a [database connection] begins a read +** transaction, that connection sees an unchanging copy of the database +** as it existed for the point in time when the transaction first started. +** Subsequent changes to the database from other connections are not seen +** by the reader until a new read transaction is started. +** +** The sqlite3_snapshot object records state information about an historical +** version of the database file so that it is possible to later open a new read +** transaction that sees that historical version of the database rather than +** the most recent version. +*/ +typedef struct sqlite3_snapshot { + unsigned char hidden[48]; +} sqlite3_snapshot; + +/* +** CAPI3REF: Record A Database Snapshot +** CONSTRUCTOR: sqlite3_snapshot +** +** ^The [sqlite3_snapshot_get(D,S,P)] interface attempts to make a +** new [sqlite3_snapshot] object that records the current state of +** schema S in database connection D. ^On success, the +** [sqlite3_snapshot_get(D,S,P)] interface writes a pointer to the newly +** created [sqlite3_snapshot] object into *P and returns SQLITE_OK. +** If there is not already a read-transaction open on schema S when +** this function is called, one is opened automatically. +** +** The following must be true for this function to succeed. If any of +** the following statements are false when sqlite3_snapshot_get() is +** called, SQLITE_ERROR is returned. The final value of *P is undefined +** in this case. +** +**
      +**
    • The database handle must not be in [autocommit mode]. +** +**
    • Schema S of [database connection] D must be a [WAL mode] database. +** +**
    • There must not be a write transaction open on schema S of database +** connection D. +** +**
    • One or more transactions must have been written to the current wal +** file since it was created on disk (by any connection). This means +** that a snapshot cannot be taken on a wal mode database with no wal +** file immediately after it is first opened. At least one transaction +** must be written to it first. +**
    +** +** This function may also return SQLITE_NOMEM. If it is called with the +** database handle in autocommit mode but fails for some other reason, +** whether or not a read transaction is opened on schema S is undefined. +** +** The [sqlite3_snapshot] object returned from a successful call to +** [sqlite3_snapshot_get()] must be freed using [sqlite3_snapshot_free()] +** to avoid a memory leak. +** +** The [sqlite3_snapshot_get()] interface is only available when the +** [SQLITE_ENABLE_SNAPSHOT] compile-time option is used. +*/ +SQLITE_API SQLITE_EXPERIMENTAL int sqlite3_snapshot_get( + sqlite3 *db, + const char *zSchema, + sqlite3_snapshot **ppSnapshot +); + +/* +** CAPI3REF: Start a read transaction on an historical snapshot +** METHOD: sqlite3_snapshot +** +** ^The [sqlite3_snapshot_open(D,S,P)] interface either starts a new read +** transaction or upgrades an existing one for schema S of +** [database connection] D such that the read transaction refers to +** historical [snapshot] P, rather than the most recent change to the +** database. ^The [sqlite3_snapshot_open()] interface returns SQLITE_OK +** on success or an appropriate [error code] if it fails. +** +** ^In order to succeed, the database connection must not be in +** [autocommit mode] when [sqlite3_snapshot_open(D,S,P)] is called. If there +** is already a read transaction open on schema S, then the database handle +** must have no active statements (SELECT statements that have been passed +** to sqlite3_step() but not sqlite3_reset() or sqlite3_finalize()). +** SQLITE_ERROR is returned if either of these conditions is violated, or +** if schema S does not exist, or if the snapshot object is invalid. +** +** ^A call to sqlite3_snapshot_open() will fail to open if the specified +** snapshot has been overwritten by a [checkpoint]. In this case +** SQLITE_ERROR_SNAPSHOT is returned. +** +** If there is already a read transaction open when this function is +** invoked, then the same read transaction remains open (on the same +** database snapshot) if SQLITE_ERROR, SQLITE_BUSY or SQLITE_ERROR_SNAPSHOT +** is returned. If another error code - for example SQLITE_PROTOCOL or an +** SQLITE_IOERR error code - is returned, then the final state of the +** read transaction is undefined. If SQLITE_OK is returned, then the +** read transaction is now open on database snapshot P. +** +** ^(A call to [sqlite3_snapshot_open(D,S,P)] will fail if the +** database connection D does not know that the database file for +** schema S is in [WAL mode]. A database connection might not know +** that the database file is in [WAL mode] if there has been no prior +** I/O on that database connection, or if the database entered [WAL mode] +** after the most recent I/O on the database connection.)^ +** (Hint: Run "[PRAGMA application_id]" against a newly opened +** database connection in order to make it ready to use snapshots.) +** +** The [sqlite3_snapshot_open()] interface is only available when the +** [SQLITE_ENABLE_SNAPSHOT] compile-time option is used. +*/ +SQLITE_API SQLITE_EXPERIMENTAL int sqlite3_snapshot_open( + sqlite3 *db, + const char *zSchema, + sqlite3_snapshot *pSnapshot +); + +/* +** CAPI3REF: Destroy a snapshot +** DESTRUCTOR: sqlite3_snapshot +** +** ^The [sqlite3_snapshot_free(P)] interface destroys [sqlite3_snapshot] P. +** The application must eventually free every [sqlite3_snapshot] object +** using this routine to avoid a memory leak. +** +** The [sqlite3_snapshot_free()] interface is only available when the +** [SQLITE_ENABLE_SNAPSHOT] compile-time option is used. +*/ +SQLITE_API SQLITE_EXPERIMENTAL void sqlite3_snapshot_free(sqlite3_snapshot*); + +/* +** CAPI3REF: Compare the ages of two snapshot handles. +** METHOD: sqlite3_snapshot +** +** The sqlite3_snapshot_cmp(P1, P2) interface is used to compare the ages +** of two valid snapshot handles. +** +** If the two snapshot handles are not associated with the same database +** file, the result of the comparison is undefined. +** +** Additionally, the result of the comparison is only valid if both of the +** snapshot handles were obtained by calling sqlite3_snapshot_get() since the +** last time the wal file was deleted. The wal file is deleted when the +** database is changed back to rollback mode or when the number of database +** clients drops to zero. If either snapshot handle was obtained before the +** wal file was last deleted, the value returned by this function +** is undefined. +** +** Otherwise, this API returns a negative value if P1 refers to an older +** snapshot than P2, zero if the two handles refer to the same database +** snapshot, and a positive value if P1 is a newer snapshot than P2. +** +** This interface is only available if SQLite is compiled with the +** [SQLITE_ENABLE_SNAPSHOT] option. +*/ +SQLITE_API SQLITE_EXPERIMENTAL int sqlite3_snapshot_cmp( + sqlite3_snapshot *p1, + sqlite3_snapshot *p2 +); + +/* +** CAPI3REF: Recover snapshots from a wal file +** METHOD: sqlite3_snapshot +** +** If a [WAL file] remains on disk after all database connections close +** (either through the use of the [SQLITE_FCNTL_PERSIST_WAL] [file control] +** or because the last process to have the database opened exited without +** calling [sqlite3_close()]) and a new connection is subsequently opened +** on that database and [WAL file], the [sqlite3_snapshot_open()] interface +** will only be able to open the last transaction added to the WAL file +** even though the WAL file contains other valid transactions. +** +** This function attempts to scan the WAL file associated with database zDb +** of database handle db and make all valid snapshots available to +** sqlite3_snapshot_open(). It is an error if there is already a read +** transaction open on the database, or if the database is not a WAL mode +** database. +** +** SQLITE_OK is returned if successful, or an SQLite error code otherwise. +** +** This interface is only available if SQLite is compiled with the +** [SQLITE_ENABLE_SNAPSHOT] option. +*/ +SQLITE_API SQLITE_EXPERIMENTAL int sqlite3_snapshot_recover(sqlite3 *db, const char *zDb); + +/* +** CAPI3REF: Serialize a database +** +** The sqlite3_serialize(D,S,P,F) interface returns a pointer to memory +** that is a serialization of the S database on [database connection] D. +** If P is not a NULL pointer, then the size of the database in bytes +** is written into *P. +** +** For an ordinary on-disk database file, the serialization is just a +** copy of the disk file. For an in-memory database or a "TEMP" database, +** the serialization is the same sequence of bytes which would be written +** to disk if that database where backed up to disk. +** +** The usual case is that sqlite3_serialize() copies the serialization of +** the database into memory obtained from [sqlite3_malloc64()] and returns +** a pointer to that memory. The caller is responsible for freeing the +** returned value to avoid a memory leak. However, if the F argument +** contains the SQLITE_SERIALIZE_NOCOPY bit, then no memory allocations +** are made, and the sqlite3_serialize() function will return a pointer +** to the contiguous memory representation of the database that SQLite +** is currently using for that database, or NULL if the no such contiguous +** memory representation of the database exists. A contiguous memory +** representation of the database will usually only exist if there has +** been a prior call to [sqlite3_deserialize(D,S,...)] with the same +** values of D and S. +** The size of the database is written into *P even if the +** SQLITE_SERIALIZE_NOCOPY bit is set but no contiguous copy +** of the database exists. +** +** A call to sqlite3_serialize(D,S,P,F) might return NULL even if the +** SQLITE_SERIALIZE_NOCOPY bit is omitted from argument F if a memory +** allocation error occurs. +** +** This interface is omitted if SQLite is compiled with the +** [SQLITE_OMIT_DESERIALIZE] option. +*/ +SQLITE_API unsigned char *sqlite3_serialize( + sqlite3 *db, /* The database connection */ + const char *zSchema, /* Which DB to serialize. ex: "main", "temp", ... */ + sqlite3_int64 *piSize, /* Write size of the DB here, if not NULL */ + unsigned int mFlags /* Zero or more SQLITE_SERIALIZE_* flags */ +); + +/* +** CAPI3REF: Flags for sqlite3_serialize +** +** Zero or more of the following constants can be OR-ed together for +** the F argument to [sqlite3_serialize(D,S,P,F)]. +** +** SQLITE_SERIALIZE_NOCOPY means that [sqlite3_serialize()] will return +** a pointer to contiguous in-memory database that it is currently using, +** without making a copy of the database. If SQLite is not currently using +** a contiguous in-memory database, then this option causes +** [sqlite3_serialize()] to return a NULL pointer. SQLite will only be +** using a contiguous in-memory database if it has been initialized by a +** prior call to [sqlite3_deserialize()]. +*/ +#define SQLITE_SERIALIZE_NOCOPY 0x001 /* Do no memory allocations */ + +/* +** CAPI3REF: Deserialize a database +** +** The sqlite3_deserialize(D,S,P,N,M,F) interface causes the +** [database connection] D to disconnect from database S and then +** reopen S as an in-memory database based on the serialization contained +** in P. The serialized database P is N bytes in size. M is the size of +** the buffer P, which might be larger than N. If M is larger than N, and +** the SQLITE_DESERIALIZE_READONLY bit is not set in F, then SQLite is +** permitted to add content to the in-memory database as long as the total +** size does not exceed M bytes. +** +** If the SQLITE_DESERIALIZE_FREEONCLOSE bit is set in F, then SQLite will +** invoke sqlite3_free() on the serialization buffer when the database +** connection closes. If the SQLITE_DESERIALIZE_RESIZEABLE bit is set, then +** SQLite will try to increase the buffer size using sqlite3_realloc64() +** if writes on the database cause it to grow larger than M bytes. +** +** The sqlite3_deserialize() interface will fail with SQLITE_BUSY if the +** database is currently in a read transaction or is involved in a backup +** operation. +** +** It is not possible to deserialized into the TEMP database. If the +** S argument to sqlite3_deserialize(D,S,P,N,M,F) is "temp" then the +** function returns SQLITE_ERROR. +** +** If sqlite3_deserialize(D,S,P,N,M,F) fails for any reason and if the +** SQLITE_DESERIALIZE_FREEONCLOSE bit is set in argument F, then +** [sqlite3_free()] is invoked on argument P prior to returning. +** +** This interface is omitted if SQLite is compiled with the +** [SQLITE_OMIT_DESERIALIZE] option. +*/ +SQLITE_API int sqlite3_deserialize( + sqlite3 *db, /* The database connection */ + const char *zSchema, /* Which DB to reopen with the deserialization */ + unsigned char *pData, /* The serialized database content */ + sqlite3_int64 szDb, /* Number bytes in the deserialization */ + sqlite3_int64 szBuf, /* Total size of buffer pData[] */ + unsigned mFlags /* Zero or more SQLITE_DESERIALIZE_* flags */ +); + +/* +** CAPI3REF: Flags for sqlite3_deserialize() +** +** The following are allowed values for 6th argument (the F argument) to +** the [sqlite3_deserialize(D,S,P,N,M,F)] interface. +** +** The SQLITE_DESERIALIZE_FREEONCLOSE means that the database serialization +** in the P argument is held in memory obtained from [sqlite3_malloc64()] +** and that SQLite should take ownership of this memory and automatically +** free it when it has finished using it. Without this flag, the caller +** is responsible for freeing any dynamically allocated memory. +** +** The SQLITE_DESERIALIZE_RESIZEABLE flag means that SQLite is allowed to +** grow the size of the database using calls to [sqlite3_realloc64()]. This +** flag should only be used if SQLITE_DESERIALIZE_FREEONCLOSE is also used. +** Without this flag, the deserialized database cannot increase in size beyond +** the number of bytes specified by the M parameter. +** +** The SQLITE_DESERIALIZE_READONLY flag means that the deserialized database +** should be treated as read-only. +*/ +#define SQLITE_DESERIALIZE_FREEONCLOSE 1 /* Call sqlite3_free() on close */ +#define SQLITE_DESERIALIZE_RESIZEABLE 2 /* Resize using sqlite3_realloc64() */ +#define SQLITE_DESERIALIZE_READONLY 4 /* Database is read-only */ + +/* +** Undo the hack that converts floating point types to integer for +** builds on processors without floating point support. +*/ +#ifdef SQLITE_OMIT_FLOATING_POINT +# undef double +#endif + +#ifdef __cplusplus +} /* End of the 'extern "C"' block */ +#endif +#endif /* SQLITE3_H */ + +/******** Begin file sqlite3rtree.h *********/ +/* +** 2010 August 30 +** +** The author disclaims copyright to this source code. In place of +** a legal notice, here is a blessing: +** +** May you do good and not evil. +** May you find forgiveness for yourself and forgive others. +** May you share freely, never taking more than you give. +** +************************************************************************* +*/ + +#ifndef _SQLITE3RTREE_H_ +#define _SQLITE3RTREE_H_ + + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct sqlite3_rtree_geometry sqlite3_rtree_geometry; +typedef struct sqlite3_rtree_query_info sqlite3_rtree_query_info; + +/* The double-precision datatype used by RTree depends on the +** SQLITE_RTREE_INT_ONLY compile-time option. +*/ +#ifdef SQLITE_RTREE_INT_ONLY + typedef sqlite3_int64 sqlite3_rtree_dbl; +#else + typedef double sqlite3_rtree_dbl; +#endif + +/* +** Register a geometry callback named zGeom that can be used as part of an +** R-Tree geometry query as follows: +** +** SELECT ... FROM WHERE MATCH $zGeom(... params ...) +*/ +SQLITE_API int sqlite3_rtree_geometry_callback( + sqlite3 *db, + const char *zGeom, + int (*xGeom)(sqlite3_rtree_geometry*, int, sqlite3_rtree_dbl*,int*), + void *pContext +); + + +/* +** A pointer to a structure of the following type is passed as the first +** argument to callbacks registered using rtree_geometry_callback(). +*/ +struct sqlite3_rtree_geometry { + void *pContext; /* Copy of pContext passed to s_r_g_c() */ + int nParam; /* Size of array aParam[] */ + sqlite3_rtree_dbl *aParam; /* Parameters passed to SQL geom function */ + void *pUser; /* Callback implementation user data */ + void (*xDelUser)(void *); /* Called by SQLite to clean up pUser */ +}; + +/* +** Register a 2nd-generation geometry callback named zScore that can be +** used as part of an R-Tree geometry query as follows: +** +** SELECT ... FROM WHERE MATCH $zQueryFunc(... params ...) +*/ +SQLITE_API int sqlite3_rtree_query_callback( + sqlite3 *db, + const char *zQueryFunc, + int (*xQueryFunc)(sqlite3_rtree_query_info*), + void *pContext, + void (*xDestructor)(void*) +); + + +/* +** A pointer to a structure of the following type is passed as the +** argument to scored geometry callback registered using +** sqlite3_rtree_query_callback(). +** +** Note that the first 5 fields of this structure are identical to +** sqlite3_rtree_geometry. This structure is a subclass of +** sqlite3_rtree_geometry. +*/ +struct sqlite3_rtree_query_info { + void *pContext; /* pContext from when function registered */ + int nParam; /* Number of function parameters */ + sqlite3_rtree_dbl *aParam; /* value of function parameters */ + void *pUser; /* callback can use this, if desired */ + void (*xDelUser)(void*); /* function to free pUser */ + sqlite3_rtree_dbl *aCoord; /* Coordinates of node or entry to check */ + unsigned int *anQueue; /* Number of pending entries in the queue */ + int nCoord; /* Number of coordinates */ + int iLevel; /* Level of current node or entry */ + int mxLevel; /* The largest iLevel value in the tree */ + sqlite3_int64 iRowid; /* Rowid for current entry */ + sqlite3_rtree_dbl rParentScore; /* Score of parent node */ + int eParentWithin; /* Visibility of parent node */ + int eWithin; /* OUT: Visibility */ + sqlite3_rtree_dbl rScore; /* OUT: Write the score here */ + /* The following fields are only available in 3.8.11 and later */ + sqlite3_value **apSqlParam; /* Original SQL values of parameters */ +}; + +/* +** Allowed values for sqlite3_rtree_query.eWithin and .eParentWithin. +*/ +#define NOT_WITHIN 0 /* Object completely outside of query region */ +#define PARTLY_WITHIN 1 /* Object partially overlaps query region */ +#define FULLY_WITHIN 2 /* Object fully contained within query region */ + + +#ifdef __cplusplus +} /* end of the 'extern "C"' block */ +#endif + +#endif /* ifndef _SQLITE3RTREE_H_ */ + +/******** End of sqlite3rtree.h *********/ +/******** Begin file sqlite3session.h *********/ + +#if !defined(__SQLITESESSION_H_) && defined(SQLITE_ENABLE_SESSION) +#define __SQLITESESSION_H_ 1 + +/* +** Make sure we can call this stuff from C++. +*/ +#ifdef __cplusplus +extern "C" { +#endif + + +/* +** CAPI3REF: Session Object Handle +** +** An instance of this object is a [session] that can be used to +** record changes to a database. +*/ +typedef struct sqlite3_session sqlite3_session; + +/* +** CAPI3REF: Changeset Iterator Handle +** +** An instance of this object acts as a cursor for iterating +** over the elements of a [changeset] or [patchset]. +*/ +typedef struct sqlite3_changeset_iter sqlite3_changeset_iter; + +/* +** CAPI3REF: Create A New Session Object +** CONSTRUCTOR: sqlite3_session +** +** Create a new session object attached to database handle db. If successful, +** a pointer to the new object is written to *ppSession and SQLITE_OK is +** returned. If an error occurs, *ppSession is set to NULL and an SQLite +** error code (e.g. SQLITE_NOMEM) is returned. +** +** It is possible to create multiple session objects attached to a single +** database handle. +** +** Session objects created using this function should be deleted using the +** [sqlite3session_delete()] function before the database handle that they +** are attached to is itself closed. If the database handle is closed before +** the session object is deleted, then the results of calling any session +** module function, including [sqlite3session_delete()] on the session object +** are undefined. +** +** Because the session module uses the [sqlite3_preupdate_hook()] API, it +** is not possible for an application to register a pre-update hook on a +** database handle that has one or more session objects attached. Nor is +** it possible to create a session object attached to a database handle for +** which a pre-update hook is already defined. The results of attempting +** either of these things are undefined. +** +** The session object will be used to create changesets for tables in +** database zDb, where zDb is either "main", or "temp", or the name of an +** attached database. It is not an error if database zDb is not attached +** to the database when the session object is created. +*/ +SQLITE_API int sqlite3session_create( + sqlite3 *db, /* Database handle */ + const char *zDb, /* Name of db (e.g. "main") */ + sqlite3_session **ppSession /* OUT: New session object */ +); + +/* +** CAPI3REF: Delete A Session Object +** DESTRUCTOR: sqlite3_session +** +** Delete a session object previously allocated using +** [sqlite3session_create()]. Once a session object has been deleted, the +** results of attempting to use pSession with any other session module +** function are undefined. +** +** Session objects must be deleted before the database handle to which they +** are attached is closed. Refer to the documentation for +** [sqlite3session_create()] for details. +*/ +SQLITE_API void sqlite3session_delete(sqlite3_session *pSession); + +/* +** CAPIREF: Conigure a Session Object +** METHOD: sqlite3_session +** +** This method is used to configure a session object after it has been +** created. At present the only valid value for the second parameter is +** [SQLITE_SESSION_OBJCONFIG_SIZE]. +** +** Arguments for sqlite3session_object_config() +** +** The following values may passed as the the 4th parameter to +** sqlite3session_object_config(). +** +**
    SQLITE_SESSION_OBJCONFIG_SIZE
    +** This option is used to set, clear or query the flag that enables +** the [sqlite3session_changeset_size()] API. Because it imposes some +** computational overhead, this API is disabled by default. Argument +** pArg must point to a value of type (int). If the value is initially +** 0, then the sqlite3session_changeset_size() API is disabled. If it +** is greater than 0, then the same API is enabled. Or, if the initial +** value is less than zero, no change is made. In all cases the (int) +** variable is set to 1 if the sqlite3session_changeset_size() API is +** enabled following the current call, or 0 otherwise. +** +** It is an error (SQLITE_MISUSE) to attempt to modify this setting after +** the first table has been attached to the session object. +*/ +SQLITE_API int sqlite3session_object_config(sqlite3_session*, int op, void *pArg); + +/* +*/ +#define SQLITE_SESSION_OBJCONFIG_SIZE 1 + +/* +** CAPI3REF: Enable Or Disable A Session Object +** METHOD: sqlite3_session +** +** Enable or disable the recording of changes by a session object. When +** enabled, a session object records changes made to the database. When +** disabled - it does not. A newly created session object is enabled. +** Refer to the documentation for [sqlite3session_changeset()] for further +** details regarding how enabling and disabling a session object affects +** the eventual changesets. +** +** Passing zero to this function disables the session. Passing a value +** greater than zero enables it. Passing a value less than zero is a +** no-op, and may be used to query the current state of the session. +** +** The return value indicates the final state of the session object: 0 if +** the session is disabled, or 1 if it is enabled. +*/ +SQLITE_API int sqlite3session_enable(sqlite3_session *pSession, int bEnable); + +/* +** CAPI3REF: Set Or Clear the Indirect Change Flag +** METHOD: sqlite3_session +** +** Each change recorded by a session object is marked as either direct or +** indirect. A change is marked as indirect if either: +** +**
      +**
    • The session object "indirect" flag is set when the change is +** made, or +**
    • The change is made by an SQL trigger or foreign key action +** instead of directly as a result of a users SQL statement. +**
    +** +** If a single row is affected by more than one operation within a session, +** then the change is considered indirect if all operations meet the criteria +** for an indirect change above, or direct otherwise. +** +** This function is used to set, clear or query the session object indirect +** flag. If the second argument passed to this function is zero, then the +** indirect flag is cleared. If it is greater than zero, the indirect flag +** is set. Passing a value less than zero does not modify the current value +** of the indirect flag, and may be used to query the current state of the +** indirect flag for the specified session object. +** +** The return value indicates the final state of the indirect flag: 0 if +** it is clear, or 1 if it is set. +*/ +SQLITE_API int sqlite3session_indirect(sqlite3_session *pSession, int bIndirect); + +/* +** CAPI3REF: Attach A Table To A Session Object +** METHOD: sqlite3_session +** +** If argument zTab is not NULL, then it is the name of a table to attach +** to the session object passed as the first argument. All subsequent changes +** made to the table while the session object is enabled will be recorded. See +** documentation for [sqlite3session_changeset()] for further details. +** +** Or, if argument zTab is NULL, then changes are recorded for all tables +** in the database. If additional tables are added to the database (by +** executing "CREATE TABLE" statements) after this call is made, changes for +** the new tables are also recorded. +** +** Changes can only be recorded for tables that have a PRIMARY KEY explicitly +** defined as part of their CREATE TABLE statement. It does not matter if the +** PRIMARY KEY is an "INTEGER PRIMARY KEY" (rowid alias) or not. The PRIMARY +** KEY may consist of a single column, or may be a composite key. +** +** It is not an error if the named table does not exist in the database. Nor +** is it an error if the named table does not have a PRIMARY KEY. However, +** no changes will be recorded in either of these scenarios. +** +** Changes are not recorded for individual rows that have NULL values stored +** in one or more of their PRIMARY KEY columns. +** +** SQLITE_OK is returned if the call completes without error. Or, if an error +** occurs, an SQLite error code (e.g. SQLITE_NOMEM) is returned. +** +**

    Special sqlite_stat1 Handling

    +** +** As of SQLite version 3.22.0, the "sqlite_stat1" table is an exception to +** some of the rules above. In SQLite, the schema of sqlite_stat1 is: +**
    +**        CREATE TABLE sqlite_stat1(tbl,idx,stat)
    +**  
    +** +** Even though sqlite_stat1 does not have a PRIMARY KEY, changes are +** recorded for it as if the PRIMARY KEY is (tbl,idx). Additionally, changes +** are recorded for rows for which (idx IS NULL) is true. However, for such +** rows a zero-length blob (SQL value X'') is stored in the changeset or +** patchset instead of a NULL value. This allows such changesets to be +** manipulated by legacy implementations of sqlite3changeset_invert(), +** concat() and similar. +** +** The sqlite3changeset_apply() function automatically converts the +** zero-length blob back to a NULL value when updating the sqlite_stat1 +** table. However, if the application calls sqlite3changeset_new(), +** sqlite3changeset_old() or sqlite3changeset_conflict on a changeset +** iterator directly (including on a changeset iterator passed to a +** conflict-handler callback) then the X'' value is returned. The application +** must translate X'' to NULL itself if required. +** +** Legacy (older than 3.22.0) versions of the sessions module cannot capture +** changes made to the sqlite_stat1 table. Legacy versions of the +** sqlite3changeset_apply() function silently ignore any modifications to the +** sqlite_stat1 table that are part of a changeset or patchset. +*/ +SQLITE_API int sqlite3session_attach( + sqlite3_session *pSession, /* Session object */ + const char *zTab /* Table name */ +); + +/* +** CAPI3REF: Set a table filter on a Session Object. +** METHOD: sqlite3_session +** +** The second argument (xFilter) is the "filter callback". For changes to rows +** in tables that are not attached to the Session object, the filter is called +** to determine whether changes to the table's rows should be tracked or not. +** If xFilter returns 0, changes are not tracked. Note that once a table is +** attached, xFilter will not be called again. +*/ +SQLITE_API void sqlite3session_table_filter( + sqlite3_session *pSession, /* Session object */ + int(*xFilter)( + void *pCtx, /* Copy of third arg to _filter_table() */ + const char *zTab /* Table name */ + ), + void *pCtx /* First argument passed to xFilter */ +); + +/* +** CAPI3REF: Generate A Changeset From A Session Object +** METHOD: sqlite3_session +** +** Obtain a changeset containing changes to the tables attached to the +** session object passed as the first argument. If successful, +** set *ppChangeset to point to a buffer containing the changeset +** and *pnChangeset to the size of the changeset in bytes before returning +** SQLITE_OK. If an error occurs, set both *ppChangeset and *pnChangeset to +** zero and return an SQLite error code. +** +** A changeset consists of zero or more INSERT, UPDATE and/or DELETE changes, +** each representing a change to a single row of an attached table. An INSERT +** change contains the values of each field of a new database row. A DELETE +** contains the original values of each field of a deleted database row. An +** UPDATE change contains the original values of each field of an updated +** database row along with the updated values for each updated non-primary-key +** column. It is not possible for an UPDATE change to represent a change that +** modifies the values of primary key columns. If such a change is made, it +** is represented in a changeset as a DELETE followed by an INSERT. +** +** Changes are not recorded for rows that have NULL values stored in one or +** more of their PRIMARY KEY columns. If such a row is inserted or deleted, +** no corresponding change is present in the changesets returned by this +** function. If an existing row with one or more NULL values stored in +** PRIMARY KEY columns is updated so that all PRIMARY KEY columns are non-NULL, +** only an INSERT is appears in the changeset. Similarly, if an existing row +** with non-NULL PRIMARY KEY values is updated so that one or more of its +** PRIMARY KEY columns are set to NULL, the resulting changeset contains a +** DELETE change only. +** +** The contents of a changeset may be traversed using an iterator created +** using the [sqlite3changeset_start()] API. A changeset may be applied to +** a database with a compatible schema using the [sqlite3changeset_apply()] +** API. +** +** Within a changeset generated by this function, all changes related to a +** single table are grouped together. In other words, when iterating through +** a changeset or when applying a changeset to a database, all changes related +** to a single table are processed before moving on to the next table. Tables +** are sorted in the same order in which they were attached (or auto-attached) +** to the sqlite3_session object. The order in which the changes related to +** a single table are stored is undefined. +** +** Following a successful call to this function, it is the responsibility of +** the caller to eventually free the buffer that *ppChangeset points to using +** [sqlite3_free()]. +** +**

    Changeset Generation

    +** +** Once a table has been attached to a session object, the session object +** records the primary key values of all new rows inserted into the table. +** It also records the original primary key and other column values of any +** deleted or updated rows. For each unique primary key value, data is only +** recorded once - the first time a row with said primary key is inserted, +** updated or deleted in the lifetime of the session. +** +** There is one exception to the previous paragraph: when a row is inserted, +** updated or deleted, if one or more of its primary key columns contain a +** NULL value, no record of the change is made. +** +** The session object therefore accumulates two types of records - those +** that consist of primary key values only (created when the user inserts +** a new record) and those that consist of the primary key values and the +** original values of other table columns (created when the users deletes +** or updates a record). +** +** When this function is called, the requested changeset is created using +** both the accumulated records and the current contents of the database +** file. Specifically: +** +**
      +**
    • For each record generated by an insert, the database is queried +** for a row with a matching primary key. If one is found, an INSERT +** change is added to the changeset. If no such row is found, no change +** is added to the changeset. +** +**
    • For each record generated by an update or delete, the database is +** queried for a row with a matching primary key. If such a row is +** found and one or more of the non-primary key fields have been +** modified from their original values, an UPDATE change is added to +** the changeset. Or, if no such row is found in the table, a DELETE +** change is added to the changeset. If there is a row with a matching +** primary key in the database, but all fields contain their original +** values, no change is added to the changeset. +**
    +** +** This means, amongst other things, that if a row is inserted and then later +** deleted while a session object is active, neither the insert nor the delete +** will be present in the changeset. Or if a row is deleted and then later a +** row with the same primary key values inserted while a session object is +** active, the resulting changeset will contain an UPDATE change instead of +** a DELETE and an INSERT. +** +** When a session object is disabled (see the [sqlite3session_enable()] API), +** it does not accumulate records when rows are inserted, updated or deleted. +** This may appear to have some counter-intuitive effects if a single row +** is written to more than once during a session. For example, if a row +** is inserted while a session object is enabled, then later deleted while +** the same session object is disabled, no INSERT record will appear in the +** changeset, even though the delete took place while the session was disabled. +** Or, if one field of a row is updated while a session is disabled, and +** another field of the same row is updated while the session is enabled, the +** resulting changeset will contain an UPDATE change that updates both fields. +*/ +SQLITE_API int sqlite3session_changeset( + sqlite3_session *pSession, /* Session object */ + int *pnChangeset, /* OUT: Size of buffer at *ppChangeset */ + void **ppChangeset /* OUT: Buffer containing changeset */ +); + +/* +** CAPI3REF: Return An Upper-limit For The Size Of The Changeset +** METHOD: sqlite3_session +** +** By default, this function always returns 0. For it to return +** a useful result, the sqlite3_session object must have been configured +** to enable this API using sqlite3session_object_config() with the +** SQLITE_SESSION_OBJCONFIG_SIZE verb. +** +** When enabled, this function returns an upper limit, in bytes, for the size +** of the changeset that might be produced if sqlite3session_changeset() were +** called. The final changeset size might be equal to or smaller than the +** size in bytes returned by this function. +*/ +SQLITE_API sqlite3_int64 sqlite3session_changeset_size(sqlite3_session *pSession); + +/* +** CAPI3REF: Load The Difference Between Tables Into A Session +** METHOD: sqlite3_session +** +** If it is not already attached to the session object passed as the first +** argument, this function attaches table zTbl in the same manner as the +** [sqlite3session_attach()] function. If zTbl does not exist, or if it +** does not have a primary key, this function is a no-op (but does not return +** an error). +** +** Argument zFromDb must be the name of a database ("main", "temp" etc.) +** attached to the same database handle as the session object that contains +** a table compatible with the table attached to the session by this function. +** A table is considered compatible if it: +** +**
      +**
    • Has the same name, +**
    • Has the same set of columns declared in the same order, and +**
    • Has the same PRIMARY KEY definition. +**
    +** +** If the tables are not compatible, SQLITE_SCHEMA is returned. If the tables +** are compatible but do not have any PRIMARY KEY columns, it is not an error +** but no changes are added to the session object. As with other session +** APIs, tables without PRIMARY KEYs are simply ignored. +** +** This function adds a set of changes to the session object that could be +** used to update the table in database zFrom (call this the "from-table") +** so that its content is the same as the table attached to the session +** object (call this the "to-table"). Specifically: +** +**
      +**
    • For each row (primary key) that exists in the to-table but not in +** the from-table, an INSERT record is added to the session object. +** +**
    • For each row (primary key) that exists in the to-table but not in +** the from-table, a DELETE record is added to the session object. +** +**
    • For each row (primary key) that exists in both tables, but features +** different non-PK values in each, an UPDATE record is added to the +** session. +**
    +** +** To clarify, if this function is called and then a changeset constructed +** using [sqlite3session_changeset()], then after applying that changeset to +** database zFrom the contents of the two compatible tables would be +** identical. +** +** It an error if database zFrom does not exist or does not contain the +** required compatible table. +** +** If the operation is successful, SQLITE_OK is returned. Otherwise, an SQLite +** error code. In this case, if argument pzErrMsg is not NULL, *pzErrMsg +** may be set to point to a buffer containing an English language error +** message. It is the responsibility of the caller to free this buffer using +** sqlite3_free(). +*/ +SQLITE_API int sqlite3session_diff( + sqlite3_session *pSession, + const char *zFromDb, + const char *zTbl, + char **pzErrMsg +); + + +/* +** CAPI3REF: Generate A Patchset From A Session Object +** METHOD: sqlite3_session +** +** The differences between a patchset and a changeset are that: +** +**
      +**
    • DELETE records consist of the primary key fields only. The +** original values of other fields are omitted. +**
    • The original values of any modified fields are omitted from +** UPDATE records. +**
    +** +** A patchset blob may be used with up to date versions of all +** sqlite3changeset_xxx API functions except for sqlite3changeset_invert(), +** which returns SQLITE_CORRUPT if it is passed a patchset. Similarly, +** attempting to use a patchset blob with old versions of the +** sqlite3changeset_xxx APIs also provokes an SQLITE_CORRUPT error. +** +** Because the non-primary key "old.*" fields are omitted, no +** SQLITE_CHANGESET_DATA conflicts can be detected or reported if a patchset +** is passed to the sqlite3changeset_apply() API. Other conflict types work +** in the same way as for changesets. +** +** Changes within a patchset are ordered in the same way as for changesets +** generated by the sqlite3session_changeset() function (i.e. all changes for +** a single table are grouped together, tables appear in the order in which +** they were attached to the session object). +*/ +SQLITE_API int sqlite3session_patchset( + sqlite3_session *pSession, /* Session object */ + int *pnPatchset, /* OUT: Size of buffer at *ppPatchset */ + void **ppPatchset /* OUT: Buffer containing patchset */ +); + +/* +** CAPI3REF: Test if a changeset has recorded any changes. +** +** Return non-zero if no changes to attached tables have been recorded by +** the session object passed as the first argument. Otherwise, if one or +** more changes have been recorded, return zero. +** +** Even if this function returns zero, it is possible that calling +** [sqlite3session_changeset()] on the session handle may still return a +** changeset that contains no changes. This can happen when a row in +** an attached table is modified and then later on the original values +** are restored. However, if this function returns non-zero, then it is +** guaranteed that a call to sqlite3session_changeset() will return a +** changeset containing zero changes. +*/ +SQLITE_API int sqlite3session_isempty(sqlite3_session *pSession); + +/* +** CAPI3REF: Query for the amount of heap memory used by a session object. +** +** This API returns the total amount of heap memory in bytes currently +** used by the session object passed as the only argument. +*/ +SQLITE_API sqlite3_int64 sqlite3session_memory_used(sqlite3_session *pSession); + +/* +** CAPI3REF: Create An Iterator To Traverse A Changeset +** CONSTRUCTOR: sqlite3_changeset_iter +** +** Create an iterator used to iterate through the contents of a changeset. +** If successful, *pp is set to point to the iterator handle and SQLITE_OK +** is returned. Otherwise, if an error occurs, *pp is set to zero and an +** SQLite error code is returned. +** +** The following functions can be used to advance and query a changeset +** iterator created by this function: +** +**
      +**
    • [sqlite3changeset_next()] +**
    • [sqlite3changeset_op()] +**
    • [sqlite3changeset_new()] +**
    • [sqlite3changeset_old()] +**
    +** +** It is the responsibility of the caller to eventually destroy the iterator +** by passing it to [sqlite3changeset_finalize()]. The buffer containing the +** changeset (pChangeset) must remain valid until after the iterator is +** destroyed. +** +** Assuming the changeset blob was created by one of the +** [sqlite3session_changeset()], [sqlite3changeset_concat()] or +** [sqlite3changeset_invert()] functions, all changes within the changeset +** that apply to a single table are grouped together. This means that when +** an application iterates through a changeset using an iterator created by +** this function, all changes that relate to a single table are visited +** consecutively. There is no chance that the iterator will visit a change +** the applies to table X, then one for table Y, and then later on visit +** another change for table X. +** +** The behavior of sqlite3changeset_start_v2() and its streaming equivalent +** may be modified by passing a combination of +** [SQLITE_CHANGESETSTART_INVERT | supported flags] as the 4th parameter. +** +** Note that the sqlite3changeset_start_v2() API is still experimental +** and therefore subject to change. +*/ +SQLITE_API int sqlite3changeset_start( + sqlite3_changeset_iter **pp, /* OUT: New changeset iterator handle */ + int nChangeset, /* Size of changeset blob in bytes */ + void *pChangeset /* Pointer to blob containing changeset */ +); +SQLITE_API int sqlite3changeset_start_v2( + sqlite3_changeset_iter **pp, /* OUT: New changeset iterator handle */ + int nChangeset, /* Size of changeset blob in bytes */ + void *pChangeset, /* Pointer to blob containing changeset */ + int flags /* SESSION_CHANGESETSTART_* flags */ +); + +/* +** CAPI3REF: Flags for sqlite3changeset_start_v2 +** +** The following flags may passed via the 4th parameter to +** [sqlite3changeset_start_v2] and [sqlite3changeset_start_v2_strm]: +** +**
    SQLITE_CHANGESETAPPLY_INVERT
    +** Invert the changeset while iterating through it. This is equivalent to +** inverting a changeset using sqlite3changeset_invert() before applying it. +** It is an error to specify this flag with a patchset. +*/ +#define SQLITE_CHANGESETSTART_INVERT 0x0002 + + +/* +** CAPI3REF: Advance A Changeset Iterator +** METHOD: sqlite3_changeset_iter +** +** This function may only be used with iterators created by the function +** [sqlite3changeset_start()]. If it is called on an iterator passed to +** a conflict-handler callback by [sqlite3changeset_apply()], SQLITE_MISUSE +** is returned and the call has no effect. +** +** Immediately after an iterator is created by sqlite3changeset_start(), it +** does not point to any change in the changeset. Assuming the changeset +** is not empty, the first call to this function advances the iterator to +** point to the first change in the changeset. Each subsequent call advances +** the iterator to point to the next change in the changeset (if any). If +** no error occurs and the iterator points to a valid change after a call +** to sqlite3changeset_next() has advanced it, SQLITE_ROW is returned. +** Otherwise, if all changes in the changeset have already been visited, +** SQLITE_DONE is returned. +** +** If an error occurs, an SQLite error code is returned. Possible error +** codes include SQLITE_CORRUPT (if the changeset buffer is corrupt) or +** SQLITE_NOMEM. +*/ +SQLITE_API int sqlite3changeset_next(sqlite3_changeset_iter *pIter); + +/* +** CAPI3REF: Obtain The Current Operation From A Changeset Iterator +** METHOD: sqlite3_changeset_iter +** +** The pIter argument passed to this function may either be an iterator +** passed to a conflict-handler by [sqlite3changeset_apply()], or an iterator +** created by [sqlite3changeset_start()]. In the latter case, the most recent +** call to [sqlite3changeset_next()] must have returned [SQLITE_ROW]. If this +** is not the case, this function returns [SQLITE_MISUSE]. +** +** Arguments pOp, pnCol and pzTab may not be NULL. Upon return, three +** outputs are set through these pointers: +** +** *pOp is set to one of [SQLITE_INSERT], [SQLITE_DELETE] or [SQLITE_UPDATE], +** depending on the type of change that the iterator currently points to; +** +** *pnCol is set to the number of columns in the table affected by the change; and +** +** *pzTab is set to point to a nul-terminated utf-8 encoded string containing +** the name of the table affected by the current change. The buffer remains +** valid until either sqlite3changeset_next() is called on the iterator +** or until the conflict-handler function returns. +** +** If pbIndirect is not NULL, then *pbIndirect is set to true (1) if the change +** is an indirect change, or false (0) otherwise. See the documentation for +** [sqlite3session_indirect()] for a description of direct and indirect +** changes. +** +** If no error occurs, SQLITE_OK is returned. If an error does occur, an +** SQLite error code is returned. The values of the output variables may not +** be trusted in this case. +*/ +SQLITE_API int sqlite3changeset_op( + sqlite3_changeset_iter *pIter, /* Iterator object */ + const char **pzTab, /* OUT: Pointer to table name */ + int *pnCol, /* OUT: Number of columns in table */ + int *pOp, /* OUT: SQLITE_INSERT, DELETE or UPDATE */ + int *pbIndirect /* OUT: True for an 'indirect' change */ +); + +/* +** CAPI3REF: Obtain The Primary Key Definition Of A Table +** METHOD: sqlite3_changeset_iter +** +** For each modified table, a changeset includes the following: +** +**
      +**
    • The number of columns in the table, and +**
    • Which of those columns make up the tables PRIMARY KEY. +**
    +** +** This function is used to find which columns comprise the PRIMARY KEY of +** the table modified by the change that iterator pIter currently points to. +** If successful, *pabPK is set to point to an array of nCol entries, where +** nCol is the number of columns in the table. Elements of *pabPK are set to +** 0x01 if the corresponding column is part of the tables primary key, or +** 0x00 if it is not. +** +** If argument pnCol is not NULL, then *pnCol is set to the number of columns +** in the table. +** +** If this function is called when the iterator does not point to a valid +** entry, SQLITE_MISUSE is returned and the output variables zeroed. Otherwise, +** SQLITE_OK is returned and the output variables populated as described +** above. +*/ +SQLITE_API int sqlite3changeset_pk( + sqlite3_changeset_iter *pIter, /* Iterator object */ + unsigned char **pabPK, /* OUT: Array of boolean - true for PK cols */ + int *pnCol /* OUT: Number of entries in output array */ +); + +/* +** CAPI3REF: Obtain old.* Values From A Changeset Iterator +** METHOD: sqlite3_changeset_iter +** +** The pIter argument passed to this function may either be an iterator +** passed to a conflict-handler by [sqlite3changeset_apply()], or an iterator +** created by [sqlite3changeset_start()]. In the latter case, the most recent +** call to [sqlite3changeset_next()] must have returned SQLITE_ROW. +** Furthermore, it may only be called if the type of change that the iterator +** currently points to is either [SQLITE_DELETE] or [SQLITE_UPDATE]. Otherwise, +** this function returns [SQLITE_MISUSE] and sets *ppValue to NULL. +** +** Argument iVal must be greater than or equal to 0, and less than the number +** of columns in the table affected by the current change. Otherwise, +** [SQLITE_RANGE] is returned and *ppValue is set to NULL. +** +** If successful, this function sets *ppValue to point to a protected +** sqlite3_value object containing the iVal'th value from the vector of +** original row values stored as part of the UPDATE or DELETE change and +** returns SQLITE_OK. The name of the function comes from the fact that this +** is similar to the "old.*" columns available to update or delete triggers. +** +** If some other error occurs (e.g. an OOM condition), an SQLite error code +** is returned and *ppValue is set to NULL. +*/ +SQLITE_API int sqlite3changeset_old( + sqlite3_changeset_iter *pIter, /* Changeset iterator */ + int iVal, /* Column number */ + sqlite3_value **ppValue /* OUT: Old value (or NULL pointer) */ +); + +/* +** CAPI3REF: Obtain new.* Values From A Changeset Iterator +** METHOD: sqlite3_changeset_iter +** +** The pIter argument passed to this function may either be an iterator +** passed to a conflict-handler by [sqlite3changeset_apply()], or an iterator +** created by [sqlite3changeset_start()]. In the latter case, the most recent +** call to [sqlite3changeset_next()] must have returned SQLITE_ROW. +** Furthermore, it may only be called if the type of change that the iterator +** currently points to is either [SQLITE_UPDATE] or [SQLITE_INSERT]. Otherwise, +** this function returns [SQLITE_MISUSE] and sets *ppValue to NULL. +** +** Argument iVal must be greater than or equal to 0, and less than the number +** of columns in the table affected by the current change. Otherwise, +** [SQLITE_RANGE] is returned and *ppValue is set to NULL. +** +** If successful, this function sets *ppValue to point to a protected +** sqlite3_value object containing the iVal'th value from the vector of +** new row values stored as part of the UPDATE or INSERT change and +** returns SQLITE_OK. If the change is an UPDATE and does not include +** a new value for the requested column, *ppValue is set to NULL and +** SQLITE_OK returned. The name of the function comes from the fact that +** this is similar to the "new.*" columns available to update or delete +** triggers. +** +** If some other error occurs (e.g. an OOM condition), an SQLite error code +** is returned and *ppValue is set to NULL. +*/ +SQLITE_API int sqlite3changeset_new( + sqlite3_changeset_iter *pIter, /* Changeset iterator */ + int iVal, /* Column number */ + sqlite3_value **ppValue /* OUT: New value (or NULL pointer) */ +); + +/* +** CAPI3REF: Obtain Conflicting Row Values From A Changeset Iterator +** METHOD: sqlite3_changeset_iter +** +** This function should only be used with iterator objects passed to a +** conflict-handler callback by [sqlite3changeset_apply()] with either +** [SQLITE_CHANGESET_DATA] or [SQLITE_CHANGESET_CONFLICT]. If this function +** is called on any other iterator, [SQLITE_MISUSE] is returned and *ppValue +** is set to NULL. +** +** Argument iVal must be greater than or equal to 0, and less than the number +** of columns in the table affected by the current change. Otherwise, +** [SQLITE_RANGE] is returned and *ppValue is set to NULL. +** +** If successful, this function sets *ppValue to point to a protected +** sqlite3_value object containing the iVal'th value from the +** "conflicting row" associated with the current conflict-handler callback +** and returns SQLITE_OK. +** +** If some other error occurs (e.g. an OOM condition), an SQLite error code +** is returned and *ppValue is set to NULL. +*/ +SQLITE_API int sqlite3changeset_conflict( + sqlite3_changeset_iter *pIter, /* Changeset iterator */ + int iVal, /* Column number */ + sqlite3_value **ppValue /* OUT: Value from conflicting row */ +); + +/* +** CAPI3REF: Determine The Number Of Foreign Key Constraint Violations +** METHOD: sqlite3_changeset_iter +** +** This function may only be called with an iterator passed to an +** SQLITE_CHANGESET_FOREIGN_KEY conflict handler callback. In this case +** it sets the output variable to the total number of known foreign key +** violations in the destination database and returns SQLITE_OK. +** +** In all other cases this function returns SQLITE_MISUSE. +*/ +SQLITE_API int sqlite3changeset_fk_conflicts( + sqlite3_changeset_iter *pIter, /* Changeset iterator */ + int *pnOut /* OUT: Number of FK violations */ +); + + +/* +** CAPI3REF: Finalize A Changeset Iterator +** METHOD: sqlite3_changeset_iter +** +** This function is used to finalize an iterator allocated with +** [sqlite3changeset_start()]. +** +** This function should only be called on iterators created using the +** [sqlite3changeset_start()] function. If an application calls this +** function with an iterator passed to a conflict-handler by +** [sqlite3changeset_apply()], [SQLITE_MISUSE] is immediately returned and the +** call has no effect. +** +** If an error was encountered within a call to an sqlite3changeset_xxx() +** function (for example an [SQLITE_CORRUPT] in [sqlite3changeset_next()] or an +** [SQLITE_NOMEM] in [sqlite3changeset_new()]) then an error code corresponding +** to that error is returned by this function. Otherwise, SQLITE_OK is +** returned. This is to allow the following pattern (pseudo-code): +** +**
    +**   sqlite3changeset_start();
    +**   while( SQLITE_ROW==sqlite3changeset_next() ){
    +**     // Do something with change.
    +**   }
    +**   rc = sqlite3changeset_finalize();
    +**   if( rc!=SQLITE_OK ){
    +**     // An error has occurred
    +**   }
    +** 
    +*/ +SQLITE_API int sqlite3changeset_finalize(sqlite3_changeset_iter *pIter); + +/* +** CAPI3REF: Invert A Changeset +** +** This function is used to "invert" a changeset object. Applying an inverted +** changeset to a database reverses the effects of applying the uninverted +** changeset. Specifically: +** +**
      +**
    • Each DELETE change is changed to an INSERT, and +**
    • Each INSERT change is changed to a DELETE, and +**
    • For each UPDATE change, the old.* and new.* values are exchanged. +**
    +** +** This function does not change the order in which changes appear within +** the changeset. It merely reverses the sense of each individual change. +** +** If successful, a pointer to a buffer containing the inverted changeset +** is stored in *ppOut, the size of the same buffer is stored in *pnOut, and +** SQLITE_OK is returned. If an error occurs, both *pnOut and *ppOut are +** zeroed and an SQLite error code returned. +** +** It is the responsibility of the caller to eventually call sqlite3_free() +** on the *ppOut pointer to free the buffer allocation following a successful +** call to this function. +** +** WARNING/TODO: This function currently assumes that the input is a valid +** changeset. If it is not, the results are undefined. +*/ +SQLITE_API int sqlite3changeset_invert( + int nIn, const void *pIn, /* Input changeset */ + int *pnOut, void **ppOut /* OUT: Inverse of input */ +); + +/* +** CAPI3REF: Concatenate Two Changeset Objects +** +** This function is used to concatenate two changesets, A and B, into a +** single changeset. The result is a changeset equivalent to applying +** changeset A followed by changeset B. +** +** This function combines the two input changesets using an +** sqlite3_changegroup object. Calling it produces similar results as the +** following code fragment: +** +**
    +**   sqlite3_changegroup *pGrp;
    +**   rc = sqlite3_changegroup_new(&pGrp);
    +**   if( rc==SQLITE_OK ) rc = sqlite3changegroup_add(pGrp, nA, pA);
    +**   if( rc==SQLITE_OK ) rc = sqlite3changegroup_add(pGrp, nB, pB);
    +**   if( rc==SQLITE_OK ){
    +**     rc = sqlite3changegroup_output(pGrp, pnOut, ppOut);
    +**   }else{
    +**     *ppOut = 0;
    +**     *pnOut = 0;
    +**   }
    +** 
    +** +** Refer to the sqlite3_changegroup documentation below for details. +*/ +SQLITE_API int sqlite3changeset_concat( + int nA, /* Number of bytes in buffer pA */ + void *pA, /* Pointer to buffer containing changeset A */ + int nB, /* Number of bytes in buffer pB */ + void *pB, /* Pointer to buffer containing changeset B */ + int *pnOut, /* OUT: Number of bytes in output changeset */ + void **ppOut /* OUT: Buffer containing output changeset */ +); + + +/* +** CAPI3REF: Changegroup Handle +** +** A changegroup is an object used to combine two or more +** [changesets] or [patchsets] +*/ +typedef struct sqlite3_changegroup sqlite3_changegroup; + +/* +** CAPI3REF: Create A New Changegroup Object +** CONSTRUCTOR: sqlite3_changegroup +** +** An sqlite3_changegroup object is used to combine two or more changesets +** (or patchsets) into a single changeset (or patchset). A single changegroup +** object may combine changesets or patchsets, but not both. The output is +** always in the same format as the input. +** +** If successful, this function returns SQLITE_OK and populates (*pp) with +** a pointer to a new sqlite3_changegroup object before returning. The caller +** should eventually free the returned object using a call to +** sqlite3changegroup_delete(). If an error occurs, an SQLite error code +** (i.e. SQLITE_NOMEM) is returned and *pp is set to NULL. +** +** The usual usage pattern for an sqlite3_changegroup object is as follows: +** +**
      +**
    • It is created using a call to sqlite3changegroup_new(). +** +**
    • Zero or more changesets (or patchsets) are added to the object +** by calling sqlite3changegroup_add(). +** +**
    • The result of combining all input changesets together is obtained +** by the application via a call to sqlite3changegroup_output(). +** +**
    • The object is deleted using a call to sqlite3changegroup_delete(). +**
    +** +** Any number of calls to add() and output() may be made between the calls to +** new() and delete(), and in any order. +** +** As well as the regular sqlite3changegroup_add() and +** sqlite3changegroup_output() functions, also available are the streaming +** versions sqlite3changegroup_add_strm() and sqlite3changegroup_output_strm(). +*/ +SQLITE_API int sqlite3changegroup_new(sqlite3_changegroup **pp); + +/* +** CAPI3REF: Add A Changeset To A Changegroup +** METHOD: sqlite3_changegroup +** +** Add all changes within the changeset (or patchset) in buffer pData (size +** nData bytes) to the changegroup. +** +** If the buffer contains a patchset, then all prior calls to this function +** on the same changegroup object must also have specified patchsets. Or, if +** the buffer contains a changeset, so must have the earlier calls to this +** function. Otherwise, SQLITE_ERROR is returned and no changes are added +** to the changegroup. +** +** Rows within the changeset and changegroup are identified by the values in +** their PRIMARY KEY columns. A change in the changeset is considered to +** apply to the same row as a change already present in the changegroup if +** the two rows have the same primary key. +** +** Changes to rows that do not already appear in the changegroup are +** simply copied into it. Or, if both the new changeset and the changegroup +** contain changes that apply to a single row, the final contents of the +** changegroup depends on the type of each change, as follows: +** +** +** +** +**
    Existing Change New Change Output Change +**
    INSERT INSERT +** The new change is ignored. This case does not occur if the new +** changeset was recorded immediately after the changesets already +** added to the changegroup. +**
    INSERT UPDATE +** The INSERT change remains in the changegroup. The values in the +** INSERT change are modified as if the row was inserted by the +** existing change and then updated according to the new change. +**
    INSERT DELETE +** The existing INSERT is removed from the changegroup. The DELETE is +** not added. +**
    UPDATE INSERT +** The new change is ignored. This case does not occur if the new +** changeset was recorded immediately after the changesets already +** added to the changegroup. +**
    UPDATE UPDATE +** The existing UPDATE remains within the changegroup. It is amended +** so that the accompanying values are as if the row was updated once +** by the existing change and then again by the new change. +**
    UPDATE DELETE +** The existing UPDATE is replaced by the new DELETE within the +** changegroup. +**
    DELETE INSERT +** If one or more of the column values in the row inserted by the +** new change differ from those in the row deleted by the existing +** change, the existing DELETE is replaced by an UPDATE within the +** changegroup. Otherwise, if the inserted row is exactly the same +** as the deleted row, the existing DELETE is simply discarded. +**
    DELETE UPDATE +** The new change is ignored. This case does not occur if the new +** changeset was recorded immediately after the changesets already +** added to the changegroup. +**
    DELETE DELETE +** The new change is ignored. This case does not occur if the new +** changeset was recorded immediately after the changesets already +** added to the changegroup. +**
    +** +** If the new changeset contains changes to a table that is already present +** in the changegroup, then the number of columns and the position of the +** primary key columns for the table must be consistent. If this is not the +** case, this function fails with SQLITE_SCHEMA. If the input changeset +** appears to be corrupt and the corruption is detected, SQLITE_CORRUPT is +** returned. Or, if an out-of-memory condition occurs during processing, this +** function returns SQLITE_NOMEM. In all cases, if an error occurs the state +** of the final contents of the changegroup is undefined. +** +** If no error occurs, SQLITE_OK is returned. +*/ +SQLITE_API int sqlite3changegroup_add(sqlite3_changegroup*, int nData, void *pData); + +/* +** CAPI3REF: Obtain A Composite Changeset From A Changegroup +** METHOD: sqlite3_changegroup +** +** Obtain a buffer containing a changeset (or patchset) representing the +** current contents of the changegroup. If the inputs to the changegroup +** were themselves changesets, the output is a changeset. Or, if the +** inputs were patchsets, the output is also a patchset. +** +** As with the output of the sqlite3session_changeset() and +** sqlite3session_patchset() functions, all changes related to a single +** table are grouped together in the output of this function. Tables appear +** in the same order as for the very first changeset added to the changegroup. +** If the second or subsequent changesets added to the changegroup contain +** changes for tables that do not appear in the first changeset, they are +** appended onto the end of the output changeset, again in the order in +** which they are first encountered. +** +** If an error occurs, an SQLite error code is returned and the output +** variables (*pnData) and (*ppData) are set to 0. Otherwise, SQLITE_OK +** is returned and the output variables are set to the size of and a +** pointer to the output buffer, respectively. In this case it is the +** responsibility of the caller to eventually free the buffer using a +** call to sqlite3_free(). +*/ +SQLITE_API int sqlite3changegroup_output( + sqlite3_changegroup*, + int *pnData, /* OUT: Size of output buffer in bytes */ + void **ppData /* OUT: Pointer to output buffer */ +); + +/* +** CAPI3REF: Delete A Changegroup Object +** DESTRUCTOR: sqlite3_changegroup +*/ +SQLITE_API void sqlite3changegroup_delete(sqlite3_changegroup*); + +/* +** CAPI3REF: Apply A Changeset To A Database +** +** Apply a changeset or patchset to a database. These functions attempt to +** update the "main" database attached to handle db with the changes found in +** the changeset passed via the second and third arguments. +** +** The fourth argument (xFilter) passed to these functions is the "filter +** callback". If it is not NULL, then for each table affected by at least one +** change in the changeset, the filter callback is invoked with +** the table name as the second argument, and a copy of the context pointer +** passed as the sixth argument as the first. If the "filter callback" +** returns zero, then no attempt is made to apply any changes to the table. +** Otherwise, if the return value is non-zero or the xFilter argument to +** is NULL, all changes related to the table are attempted. +** +** For each table that is not excluded by the filter callback, this function +** tests that the target database contains a compatible table. A table is +** considered compatible if all of the following are true: +** +**
      +**
    • The table has the same name as the name recorded in the +** changeset, and +**
    • The table has at least as many columns as recorded in the +** changeset, and +**
    • The table has primary key columns in the same position as +** recorded in the changeset. +**
    +** +** If there is no compatible table, it is not an error, but none of the +** changes associated with the table are applied. A warning message is issued +** via the sqlite3_log() mechanism with the error code SQLITE_SCHEMA. At most +** one such warning is issued for each table in the changeset. +** +** For each change for which there is a compatible table, an attempt is made +** to modify the table contents according to the UPDATE, INSERT or DELETE +** change. If a change cannot be applied cleanly, the conflict handler +** function passed as the fifth argument to sqlite3changeset_apply() may be +** invoked. A description of exactly when the conflict handler is invoked for +** each type of change is below. +** +** Unlike the xFilter argument, xConflict may not be passed NULL. The results +** of passing anything other than a valid function pointer as the xConflict +** argument are undefined. +** +** Each time the conflict handler function is invoked, it must return one +** of [SQLITE_CHANGESET_OMIT], [SQLITE_CHANGESET_ABORT] or +** [SQLITE_CHANGESET_REPLACE]. SQLITE_CHANGESET_REPLACE may only be returned +** if the second argument passed to the conflict handler is either +** SQLITE_CHANGESET_DATA or SQLITE_CHANGESET_CONFLICT. If the conflict-handler +** returns an illegal value, any changes already made are rolled back and +** the call to sqlite3changeset_apply() returns SQLITE_MISUSE. Different +** actions are taken by sqlite3changeset_apply() depending on the value +** returned by each invocation of the conflict-handler function. Refer to +** the documentation for the three +** [SQLITE_CHANGESET_OMIT|available return values] for details. +** +**
    +**
    DELETE Changes
    +** For each DELETE change, the function checks if the target database +** contains a row with the same primary key value (or values) as the +** original row values stored in the changeset. If it does, and the values +** stored in all non-primary key columns also match the values stored in +** the changeset the row is deleted from the target database. +** +** If a row with matching primary key values is found, but one or more of +** the non-primary key fields contains a value different from the original +** row value stored in the changeset, the conflict-handler function is +** invoked with [SQLITE_CHANGESET_DATA] as the second argument. If the +** database table has more columns than are recorded in the changeset, +** only the values of those non-primary key fields are compared against +** the current database contents - any trailing database table columns +** are ignored. +** +** If no row with matching primary key values is found in the database, +** the conflict-handler function is invoked with [SQLITE_CHANGESET_NOTFOUND] +** passed as the second argument. +** +** If the DELETE operation is attempted, but SQLite returns SQLITE_CONSTRAINT +** (which can only happen if a foreign key constraint is violated), the +** conflict-handler function is invoked with [SQLITE_CHANGESET_CONSTRAINT] +** passed as the second argument. This includes the case where the DELETE +** operation is attempted because an earlier call to the conflict handler +** function returned [SQLITE_CHANGESET_REPLACE]. +** +**
    INSERT Changes
    +** For each INSERT change, an attempt is made to insert the new row into +** the database. If the changeset row contains fewer fields than the +** database table, the trailing fields are populated with their default +** values. +** +** If the attempt to insert the row fails because the database already +** contains a row with the same primary key values, the conflict handler +** function is invoked with the second argument set to +** [SQLITE_CHANGESET_CONFLICT]. +** +** If the attempt to insert the row fails because of some other constraint +** violation (e.g. NOT NULL or UNIQUE), the conflict handler function is +** invoked with the second argument set to [SQLITE_CHANGESET_CONSTRAINT]. +** This includes the case where the INSERT operation is re-attempted because +** an earlier call to the conflict handler function returned +** [SQLITE_CHANGESET_REPLACE]. +** +**
    UPDATE Changes
    +** For each UPDATE change, the function checks if the target database +** contains a row with the same primary key value (or values) as the +** original row values stored in the changeset. If it does, and the values +** stored in all modified non-primary key columns also match the values +** stored in the changeset the row is updated within the target database. +** +** If a row with matching primary key values is found, but one or more of +** the modified non-primary key fields contains a value different from an +** original row value stored in the changeset, the conflict-handler function +** is invoked with [SQLITE_CHANGESET_DATA] as the second argument. Since +** UPDATE changes only contain values for non-primary key fields that are +** to be modified, only those fields need to match the original values to +** avoid the SQLITE_CHANGESET_DATA conflict-handler callback. +** +** If no row with matching primary key values is found in the database, +** the conflict-handler function is invoked with [SQLITE_CHANGESET_NOTFOUND] +** passed as the second argument. +** +** If the UPDATE operation is attempted, but SQLite returns +** SQLITE_CONSTRAINT, the conflict-handler function is invoked with +** [SQLITE_CHANGESET_CONSTRAINT] passed as the second argument. +** This includes the case where the UPDATE operation is attempted after +** an earlier call to the conflict handler function returned +** [SQLITE_CHANGESET_REPLACE]. +**
    +** +** It is safe to execute SQL statements, including those that write to the +** table that the callback related to, from within the xConflict callback. +** This can be used to further customize the application's conflict +** resolution strategy. +** +** All changes made by these functions are enclosed in a savepoint transaction. +** If any other error (aside from a constraint failure when attempting to +** write to the target database) occurs, then the savepoint transaction is +** rolled back, restoring the target database to its original state, and an +** SQLite error code returned. +** +** If the output parameters (ppRebase) and (pnRebase) are non-NULL and +** the input is a changeset (not a patchset), then sqlite3changeset_apply_v2() +** may set (*ppRebase) to point to a "rebase" that may be used with the +** sqlite3_rebaser APIs buffer before returning. In this case (*pnRebase) +** is set to the size of the buffer in bytes. It is the responsibility of the +** caller to eventually free any such buffer using sqlite3_free(). The buffer +** is only allocated and populated if one or more conflicts were encountered +** while applying the patchset. See comments surrounding the sqlite3_rebaser +** APIs for further details. +** +** The behavior of sqlite3changeset_apply_v2() and its streaming equivalent +** may be modified by passing a combination of +** [SQLITE_CHANGESETAPPLY_NOSAVEPOINT | supported flags] as the 9th parameter. +** +** Note that the sqlite3changeset_apply_v2() API is still experimental +** and therefore subject to change. +*/ +SQLITE_API int sqlite3changeset_apply( + sqlite3 *db, /* Apply change to "main" db of this handle */ + int nChangeset, /* Size of changeset in bytes */ + void *pChangeset, /* Changeset blob */ + int(*xFilter)( + void *pCtx, /* Copy of sixth arg to _apply() */ + const char *zTab /* Table name */ + ), + int(*xConflict)( + void *pCtx, /* Copy of sixth arg to _apply() */ + int eConflict, /* DATA, MISSING, CONFLICT, CONSTRAINT */ + sqlite3_changeset_iter *p /* Handle describing change and conflict */ + ), + void *pCtx /* First argument passed to xConflict */ +); +SQLITE_API int sqlite3changeset_apply_v2( + sqlite3 *db, /* Apply change to "main" db of this handle */ + int nChangeset, /* Size of changeset in bytes */ + void *pChangeset, /* Changeset blob */ + int(*xFilter)( + void *pCtx, /* Copy of sixth arg to _apply() */ + const char *zTab /* Table name */ + ), + int(*xConflict)( + void *pCtx, /* Copy of sixth arg to _apply() */ + int eConflict, /* DATA, MISSING, CONFLICT, CONSTRAINT */ + sqlite3_changeset_iter *p /* Handle describing change and conflict */ + ), + void *pCtx, /* First argument passed to xConflict */ + void **ppRebase, int *pnRebase, /* OUT: Rebase data */ + int flags /* SESSION_CHANGESETAPPLY_* flags */ +); + +/* +** CAPI3REF: Flags for sqlite3changeset_apply_v2 +** +** The following flags may passed via the 9th parameter to +** [sqlite3changeset_apply_v2] and [sqlite3changeset_apply_v2_strm]: +** +**
    +**
    SQLITE_CHANGESETAPPLY_NOSAVEPOINT
    +** Usually, the sessions module encloses all operations performed by +** a single call to apply_v2() or apply_v2_strm() in a [SAVEPOINT]. The +** SAVEPOINT is committed if the changeset or patchset is successfully +** applied, or rolled back if an error occurs. Specifying this flag +** causes the sessions module to omit this savepoint. In this case, if the +** caller has an open transaction or savepoint when apply_v2() is called, +** it may revert the partially applied changeset by rolling it back. +** +**
    SQLITE_CHANGESETAPPLY_INVERT
    +** Invert the changeset before applying it. This is equivalent to inverting +** a changeset using sqlite3changeset_invert() before applying it. It is +** an error to specify this flag with a patchset. +*/ +#define SQLITE_CHANGESETAPPLY_NOSAVEPOINT 0x0001 +#define SQLITE_CHANGESETAPPLY_INVERT 0x0002 + +/* +** CAPI3REF: Constants Passed To The Conflict Handler +** +** Values that may be passed as the second argument to a conflict-handler. +** +**
    +**
    SQLITE_CHANGESET_DATA
    +** The conflict handler is invoked with CHANGESET_DATA as the second argument +** when processing a DELETE or UPDATE change if a row with the required +** PRIMARY KEY fields is present in the database, but one or more other +** (non primary-key) fields modified by the update do not contain the +** expected "before" values. +** +** The conflicting row, in this case, is the database row with the matching +** primary key. +** +**
    SQLITE_CHANGESET_NOTFOUND
    +** The conflict handler is invoked with CHANGESET_NOTFOUND as the second +** argument when processing a DELETE or UPDATE change if a row with the +** required PRIMARY KEY fields is not present in the database. +** +** There is no conflicting row in this case. The results of invoking the +** sqlite3changeset_conflict() API are undefined. +** +**
    SQLITE_CHANGESET_CONFLICT
    +** CHANGESET_CONFLICT is passed as the second argument to the conflict +** handler while processing an INSERT change if the operation would result +** in duplicate primary key values. +** +** The conflicting row in this case is the database row with the matching +** primary key. +** +**
    SQLITE_CHANGESET_FOREIGN_KEY
    +** If foreign key handling is enabled, and applying a changeset leaves the +** database in a state containing foreign key violations, the conflict +** handler is invoked with CHANGESET_FOREIGN_KEY as the second argument +** exactly once before the changeset is committed. If the conflict handler +** returns CHANGESET_OMIT, the changes, including those that caused the +** foreign key constraint violation, are committed. Or, if it returns +** CHANGESET_ABORT, the changeset is rolled back. +** +** No current or conflicting row information is provided. The only function +** it is possible to call on the supplied sqlite3_changeset_iter handle +** is sqlite3changeset_fk_conflicts(). +** +**
    SQLITE_CHANGESET_CONSTRAINT
    +** If any other constraint violation occurs while applying a change (i.e. +** a UNIQUE, CHECK or NOT NULL constraint), the conflict handler is +** invoked with CHANGESET_CONSTRAINT as the second argument. +** +** There is no conflicting row in this case. The results of invoking the +** sqlite3changeset_conflict() API are undefined. +** +**
    +*/ +#define SQLITE_CHANGESET_DATA 1 +#define SQLITE_CHANGESET_NOTFOUND 2 +#define SQLITE_CHANGESET_CONFLICT 3 +#define SQLITE_CHANGESET_CONSTRAINT 4 +#define SQLITE_CHANGESET_FOREIGN_KEY 5 + +/* +** CAPI3REF: Constants Returned By The Conflict Handler +** +** A conflict handler callback must return one of the following three values. +** +**
    +**
    SQLITE_CHANGESET_OMIT
    +** If a conflict handler returns this value no special action is taken. The +** change that caused the conflict is not applied. The session module +** continues to the next change in the changeset. +** +**
    SQLITE_CHANGESET_REPLACE
    +** This value may only be returned if the second argument to the conflict +** handler was SQLITE_CHANGESET_DATA or SQLITE_CHANGESET_CONFLICT. If this +** is not the case, any changes applied so far are rolled back and the +** call to sqlite3changeset_apply() returns SQLITE_MISUSE. +** +** If CHANGESET_REPLACE is returned by an SQLITE_CHANGESET_DATA conflict +** handler, then the conflicting row is either updated or deleted, depending +** on the type of change. +** +** If CHANGESET_REPLACE is returned by an SQLITE_CHANGESET_CONFLICT conflict +** handler, then the conflicting row is removed from the database and a +** second attempt to apply the change is made. If this second attempt fails, +** the original row is restored to the database before continuing. +** +**
    SQLITE_CHANGESET_ABORT
    +** If this value is returned, any changes applied so far are rolled back +** and the call to sqlite3changeset_apply() returns SQLITE_ABORT. +**
    +*/ +#define SQLITE_CHANGESET_OMIT 0 +#define SQLITE_CHANGESET_REPLACE 1 +#define SQLITE_CHANGESET_ABORT 2 + +/* +** CAPI3REF: Rebasing changesets +** EXPERIMENTAL +** +** Suppose there is a site hosting a database in state S0. And that +** modifications are made that move that database to state S1 and a +** changeset recorded (the "local" changeset). Then, a changeset based +** on S0 is received from another site (the "remote" changeset) and +** applied to the database. The database is then in state +** (S1+"remote"), where the exact state depends on any conflict +** resolution decisions (OMIT or REPLACE) made while applying "remote". +** Rebasing a changeset is to update it to take those conflict +** resolution decisions into account, so that the same conflicts +** do not have to be resolved elsewhere in the network. +** +** For example, if both the local and remote changesets contain an +** INSERT of the same key on "CREATE TABLE t1(a PRIMARY KEY, b)": +** +** local: INSERT INTO t1 VALUES(1, 'v1'); +** remote: INSERT INTO t1 VALUES(1, 'v2'); +** +** and the conflict resolution is REPLACE, then the INSERT change is +** removed from the local changeset (it was overridden). Or, if the +** conflict resolution was "OMIT", then the local changeset is modified +** to instead contain: +** +** UPDATE t1 SET b = 'v2' WHERE a=1; +** +** Changes within the local changeset are rebased as follows: +** +**
    +**
    Local INSERT
    +** This may only conflict with a remote INSERT. If the conflict +** resolution was OMIT, then add an UPDATE change to the rebased +** changeset. Or, if the conflict resolution was REPLACE, add +** nothing to the rebased changeset. +** +**
    Local DELETE
    +** This may conflict with a remote UPDATE or DELETE. In both cases the +** only possible resolution is OMIT. If the remote operation was a +** DELETE, then add no change to the rebased changeset. If the remote +** operation was an UPDATE, then the old.* fields of change are updated +** to reflect the new.* values in the UPDATE. +** +**
    Local UPDATE
    +** This may conflict with a remote UPDATE or DELETE. If it conflicts +** with a DELETE, and the conflict resolution was OMIT, then the update +** is changed into an INSERT. Any undefined values in the new.* record +** from the update change are filled in using the old.* values from +** the conflicting DELETE. Or, if the conflict resolution was REPLACE, +** the UPDATE change is simply omitted from the rebased changeset. +** +** If conflict is with a remote UPDATE and the resolution is OMIT, then +** the old.* values are rebased using the new.* values in the remote +** change. Or, if the resolution is REPLACE, then the change is copied +** into the rebased changeset with updates to columns also updated by +** the conflicting remote UPDATE removed. If this means no columns would +** be updated, the change is omitted. +**
    +** +** A local change may be rebased against multiple remote changes +** simultaneously. If a single key is modified by multiple remote +** changesets, they are combined as follows before the local changeset +** is rebased: +** +**
      +**
    • If there has been one or more REPLACE resolutions on a +** key, it is rebased according to a REPLACE. +** +**
    • If there have been no REPLACE resolutions on a key, then +** the local changeset is rebased according to the most recent +** of the OMIT resolutions. +**
    +** +** Note that conflict resolutions from multiple remote changesets are +** combined on a per-field basis, not per-row. This means that in the +** case of multiple remote UPDATE operations, some fields of a single +** local change may be rebased for REPLACE while others are rebased for +** OMIT. +** +** In order to rebase a local changeset, the remote changeset must first +** be applied to the local database using sqlite3changeset_apply_v2() and +** the buffer of rebase information captured. Then: +** +**
      +**
    1. An sqlite3_rebaser object is created by calling +** sqlite3rebaser_create(). +**
    2. The new object is configured with the rebase buffer obtained from +** sqlite3changeset_apply_v2() by calling sqlite3rebaser_configure(). +** If the local changeset is to be rebased against multiple remote +** changesets, then sqlite3rebaser_configure() should be called +** multiple times, in the same order that the multiple +** sqlite3changeset_apply_v2() calls were made. +**
    3. Each local changeset is rebased by calling sqlite3rebaser_rebase(). +**
    4. The sqlite3_rebaser object is deleted by calling +** sqlite3rebaser_delete(). +**
    +*/ +typedef struct sqlite3_rebaser sqlite3_rebaser; + +/* +** CAPI3REF: Create a changeset rebaser object. +** EXPERIMENTAL +** +** Allocate a new changeset rebaser object. If successful, set (*ppNew) to +** point to the new object and return SQLITE_OK. Otherwise, if an error +** occurs, return an SQLite error code (e.g. SQLITE_NOMEM) and set (*ppNew) +** to NULL. +*/ +SQLITE_API int sqlite3rebaser_create(sqlite3_rebaser **ppNew); + +/* +** CAPI3REF: Configure a changeset rebaser object. +** EXPERIMENTAL +** +** Configure the changeset rebaser object to rebase changesets according +** to the conflict resolutions described by buffer pRebase (size nRebase +** bytes), which must have been obtained from a previous call to +** sqlite3changeset_apply_v2(). +*/ +SQLITE_API int sqlite3rebaser_configure( + sqlite3_rebaser*, + int nRebase, const void *pRebase +); + +/* +** CAPI3REF: Rebase a changeset +** EXPERIMENTAL +** +** Argument pIn must point to a buffer containing a changeset nIn bytes +** in size. This function allocates and populates a buffer with a copy +** of the changeset rebased according to the configuration of the +** rebaser object passed as the first argument. If successful, (*ppOut) +** is set to point to the new buffer containing the rebased changeset and +** (*pnOut) to its size in bytes and SQLITE_OK returned. It is the +** responsibility of the caller to eventually free the new buffer using +** sqlite3_free(). Otherwise, if an error occurs, (*ppOut) and (*pnOut) +** are set to zero and an SQLite error code returned. +*/ +SQLITE_API int sqlite3rebaser_rebase( + sqlite3_rebaser*, + int nIn, const void *pIn, + int *pnOut, void **ppOut +); + +/* +** CAPI3REF: Delete a changeset rebaser object. +** EXPERIMENTAL +** +** Delete the changeset rebaser object and all associated resources. There +** should be one call to this function for each successful invocation +** of sqlite3rebaser_create(). +*/ +SQLITE_API void sqlite3rebaser_delete(sqlite3_rebaser *p); + +/* +** CAPI3REF: Streaming Versions of API functions. +** +** The six streaming API xxx_strm() functions serve similar purposes to the +** corresponding non-streaming API functions: +** +** +** +**
    Streaming functionNon-streaming equivalent
    sqlite3changeset_apply_strm[sqlite3changeset_apply] +**
    sqlite3changeset_apply_strm_v2[sqlite3changeset_apply_v2] +**
    sqlite3changeset_concat_strm[sqlite3changeset_concat] +**
    sqlite3changeset_invert_strm[sqlite3changeset_invert] +**
    sqlite3changeset_start_strm[sqlite3changeset_start] +**
    sqlite3session_changeset_strm[sqlite3session_changeset] +**
    sqlite3session_patchset_strm[sqlite3session_patchset] +**
    +** +** Non-streaming functions that accept changesets (or patchsets) as input +** require that the entire changeset be stored in a single buffer in memory. +** Similarly, those that return a changeset or patchset do so by returning +** a pointer to a single large buffer allocated using sqlite3_malloc(). +** Normally this is convenient. However, if an application running in a +** low-memory environment is required to handle very large changesets, the +** large contiguous memory allocations required can become onerous. +** +** In order to avoid this problem, instead of a single large buffer, input +** is passed to a streaming API functions by way of a callback function that +** the sessions module invokes to incrementally request input data as it is +** required. In all cases, a pair of API function parameters such as +** +**
    +**        int nChangeset,
    +**        void *pChangeset,
    +**  
    +** +** Is replaced by: +** +**
    +**        int (*xInput)(void *pIn, void *pData, int *pnData),
    +**        void *pIn,
    +**  
    +** +** Each time the xInput callback is invoked by the sessions module, the first +** argument passed is a copy of the supplied pIn context pointer. The second +** argument, pData, points to a buffer (*pnData) bytes in size. Assuming no +** error occurs the xInput method should copy up to (*pnData) bytes of data +** into the buffer and set (*pnData) to the actual number of bytes copied +** before returning SQLITE_OK. If the input is completely exhausted, (*pnData) +** should be set to zero to indicate this. Or, if an error occurs, an SQLite +** error code should be returned. In all cases, if an xInput callback returns +** an error, all processing is abandoned and the streaming API function +** returns a copy of the error code to the caller. +** +** In the case of sqlite3changeset_start_strm(), the xInput callback may be +** invoked by the sessions module at any point during the lifetime of the +** iterator. If such an xInput callback returns an error, the iterator enters +** an error state, whereby all subsequent calls to iterator functions +** immediately fail with the same error code as returned by xInput. +** +** Similarly, streaming API functions that return changesets (or patchsets) +** return them in chunks by way of a callback function instead of via a +** pointer to a single large buffer. In this case, a pair of parameters such +** as: +** +**
    +**        int *pnChangeset,
    +**        void **ppChangeset,
    +**  
    +** +** Is replaced by: +** +**
    +**        int (*xOutput)(void *pOut, const void *pData, int nData),
    +**        void *pOut
    +**  
    +** +** The xOutput callback is invoked zero or more times to return data to +** the application. The first parameter passed to each call is a copy of the +** pOut pointer supplied by the application. The second parameter, pData, +** points to a buffer nData bytes in size containing the chunk of output +** data being returned. If the xOutput callback successfully processes the +** supplied data, it should return SQLITE_OK to indicate success. Otherwise, +** it should return some other SQLite error code. In this case processing +** is immediately abandoned and the streaming API function returns a copy +** of the xOutput error code to the application. +** +** The sessions module never invokes an xOutput callback with the third +** parameter set to a value less than or equal to zero. Other than this, +** no guarantees are made as to the size of the chunks of data returned. +*/ +SQLITE_API int sqlite3changeset_apply_strm( + sqlite3 *db, /* Apply change to "main" db of this handle */ + int (*xInput)(void *pIn, void *pData, int *pnData), /* Input function */ + void *pIn, /* First arg for xInput */ + int(*xFilter)( + void *pCtx, /* Copy of sixth arg to _apply() */ + const char *zTab /* Table name */ + ), + int(*xConflict)( + void *pCtx, /* Copy of sixth arg to _apply() */ + int eConflict, /* DATA, MISSING, CONFLICT, CONSTRAINT */ + sqlite3_changeset_iter *p /* Handle describing change and conflict */ + ), + void *pCtx /* First argument passed to xConflict */ +); +SQLITE_API int sqlite3changeset_apply_v2_strm( + sqlite3 *db, /* Apply change to "main" db of this handle */ + int (*xInput)(void *pIn, void *pData, int *pnData), /* Input function */ + void *pIn, /* First arg for xInput */ + int(*xFilter)( + void *pCtx, /* Copy of sixth arg to _apply() */ + const char *zTab /* Table name */ + ), + int(*xConflict)( + void *pCtx, /* Copy of sixth arg to _apply() */ + int eConflict, /* DATA, MISSING, CONFLICT, CONSTRAINT */ + sqlite3_changeset_iter *p /* Handle describing change and conflict */ + ), + void *pCtx, /* First argument passed to xConflict */ + void **ppRebase, int *pnRebase, + int flags +); +SQLITE_API int sqlite3changeset_concat_strm( + int (*xInputA)(void *pIn, void *pData, int *pnData), + void *pInA, + int (*xInputB)(void *pIn, void *pData, int *pnData), + void *pInB, + int (*xOutput)(void *pOut, const void *pData, int nData), + void *pOut +); +SQLITE_API int sqlite3changeset_invert_strm( + int (*xInput)(void *pIn, void *pData, int *pnData), + void *pIn, + int (*xOutput)(void *pOut, const void *pData, int nData), + void *pOut +); +SQLITE_API int sqlite3changeset_start_strm( + sqlite3_changeset_iter **pp, + int (*xInput)(void *pIn, void *pData, int *pnData), + void *pIn +); +SQLITE_API int sqlite3changeset_start_v2_strm( + sqlite3_changeset_iter **pp, + int (*xInput)(void *pIn, void *pData, int *pnData), + void *pIn, + int flags +); +SQLITE_API int sqlite3session_changeset_strm( + sqlite3_session *pSession, + int (*xOutput)(void *pOut, const void *pData, int nData), + void *pOut +); +SQLITE_API int sqlite3session_patchset_strm( + sqlite3_session *pSession, + int (*xOutput)(void *pOut, const void *pData, int nData), + void *pOut +); +SQLITE_API int sqlite3changegroup_add_strm(sqlite3_changegroup*, + int (*xInput)(void *pIn, void *pData, int *pnData), + void *pIn +); +SQLITE_API int sqlite3changegroup_output_strm(sqlite3_changegroup*, + int (*xOutput)(void *pOut, const void *pData, int nData), + void *pOut +); +SQLITE_API int sqlite3rebaser_rebase_strm( + sqlite3_rebaser *pRebaser, + int (*xInput)(void *pIn, void *pData, int *pnData), + void *pIn, + int (*xOutput)(void *pOut, const void *pData, int nData), + void *pOut +); + +/* +** CAPI3REF: Configure global parameters +** +** The sqlite3session_config() interface is used to make global configuration +** changes to the sessions module in order to tune it to the specific needs +** of the application. +** +** The sqlite3session_config() interface is not threadsafe. If it is invoked +** while any other thread is inside any other sessions method then the +** results are undefined. Furthermore, if it is invoked after any sessions +** related objects have been created, the results are also undefined. +** +** The first argument to the sqlite3session_config() function must be one +** of the SQLITE_SESSION_CONFIG_XXX constants defined below. The +** interpretation of the (void*) value passed as the second parameter and +** the effect of calling this function depends on the value of the first +** parameter. +** +**
    +**
    SQLITE_SESSION_CONFIG_STRMSIZE
    +** By default, the sessions module streaming interfaces attempt to input +** and output data in approximately 1 KiB chunks. This operand may be used +** to set and query the value of this configuration setting. The pointer +** passed as the second argument must point to a value of type (int). +** If this value is greater than 0, it is used as the new streaming data +** chunk size for both input and output. Before returning, the (int) value +** pointed to by pArg is set to the final value of the streaming interface +** chunk size. +**
    +** +** This function returns SQLITE_OK if successful, or an SQLite error code +** otherwise. +*/ +SQLITE_API int sqlite3session_config(int op, void *pArg); + +/* +** CAPI3REF: Values for sqlite3session_config(). +*/ +#define SQLITE_SESSION_CONFIG_STRMSIZE 1 + +/* +** Make sure we can call this stuff from C++. +*/ +#ifdef __cplusplus +} +#endif + +#endif /* !defined(__SQLITESESSION_H_) && defined(SQLITE_ENABLE_SESSION) */ + +/******** End of sqlite3session.h *********/ +/******** Begin file fts5.h *********/ +/* +** 2014 May 31 +** +** The author disclaims copyright to this source code. In place of +** a legal notice, here is a blessing: +** +** May you do good and not evil. +** May you find forgiveness for yourself and forgive others. +** May you share freely, never taking more than you give. +** +****************************************************************************** +** +** Interfaces to extend FTS5. Using the interfaces defined in this file, +** FTS5 may be extended with: +** +** * custom tokenizers, and +** * custom auxiliary functions. +*/ + + +#ifndef _FTS5_H +#define _FTS5_H + + +#ifdef __cplusplus +extern "C" { +#endif + +/************************************************************************* +** CUSTOM AUXILIARY FUNCTIONS +** +** Virtual table implementations may overload SQL functions by implementing +** the sqlite3_module.xFindFunction() method. +*/ + +typedef struct Fts5ExtensionApi Fts5ExtensionApi; +typedef struct Fts5Context Fts5Context; +typedef struct Fts5PhraseIter Fts5PhraseIter; + +typedef void (*fts5_extension_function)( + const Fts5ExtensionApi *pApi, /* API offered by current FTS version */ + Fts5Context *pFts, /* First arg to pass to pApi functions */ + sqlite3_context *pCtx, /* Context for returning result/error */ + int nVal, /* Number of values in apVal[] array */ + sqlite3_value **apVal /* Array of trailing arguments */ +); + +struct Fts5PhraseIter { + const unsigned char *a; + const unsigned char *b; +}; + +/* +** EXTENSION API FUNCTIONS +** +** xUserData(pFts): +** Return a copy of the context pointer the extension function was +** registered with. +** +** xColumnTotalSize(pFts, iCol, pnToken): +** If parameter iCol is less than zero, set output variable *pnToken +** to the total number of tokens in the FTS5 table. Or, if iCol is +** non-negative but less than the number of columns in the table, return +** the total number of tokens in column iCol, considering all rows in +** the FTS5 table. +** +** If parameter iCol is greater than or equal to the number of columns +** in the table, SQLITE_RANGE is returned. Or, if an error occurs (e.g. +** an OOM condition or IO error), an appropriate SQLite error code is +** returned. +** +** xColumnCount(pFts): +** Return the number of columns in the table. +** +** xColumnSize(pFts, iCol, pnToken): +** If parameter iCol is less than zero, set output variable *pnToken +** to the total number of tokens in the current row. Or, if iCol is +** non-negative but less than the number of columns in the table, set +** *pnToken to the number of tokens in column iCol of the current row. +** +** If parameter iCol is greater than or equal to the number of columns +** in the table, SQLITE_RANGE is returned. Or, if an error occurs (e.g. +** an OOM condition or IO error), an appropriate SQLite error code is +** returned. +** +** This function may be quite inefficient if used with an FTS5 table +** created with the "columnsize=0" option. +** +** xColumnText: +** This function attempts to retrieve the text of column iCol of the +** current document. If successful, (*pz) is set to point to a buffer +** containing the text in utf-8 encoding, (*pn) is set to the size in bytes +** (not characters) of the buffer and SQLITE_OK is returned. Otherwise, +** if an error occurs, an SQLite error code is returned and the final values +** of (*pz) and (*pn) are undefined. +** +** xPhraseCount: +** Returns the number of phrases in the current query expression. +** +** xPhraseSize: +** Returns the number of tokens in phrase iPhrase of the query. Phrases +** are numbered starting from zero. +** +** xInstCount: +** Set *pnInst to the total number of occurrences of all phrases within +** the query within the current row. Return SQLITE_OK if successful, or +** an error code (i.e. SQLITE_NOMEM) if an error occurs. +** +** This API can be quite slow if used with an FTS5 table created with the +** "detail=none" or "detail=column" option. If the FTS5 table is created +** with either "detail=none" or "detail=column" and "content=" option +** (i.e. if it is a contentless table), then this API always returns 0. +** +** xInst: +** Query for the details of phrase match iIdx within the current row. +** Phrase matches are numbered starting from zero, so the iIdx argument +** should be greater than or equal to zero and smaller than the value +** output by xInstCount(). +** +** Usually, output parameter *piPhrase is set to the phrase number, *piCol +** to the column in which it occurs and *piOff the token offset of the +** first token of the phrase. Returns SQLITE_OK if successful, or an error +** code (i.e. SQLITE_NOMEM) if an error occurs. +** +** This API can be quite slow if used with an FTS5 table created with the +** "detail=none" or "detail=column" option. +** +** xRowid: +** Returns the rowid of the current row. +** +** xTokenize: +** Tokenize text using the tokenizer belonging to the FTS5 table. +** +** xQueryPhrase(pFts5, iPhrase, pUserData, xCallback): +** This API function is used to query the FTS table for phrase iPhrase +** of the current query. Specifically, a query equivalent to: +** +** ... FROM ftstable WHERE ftstable MATCH $p ORDER BY rowid +** +** with $p set to a phrase equivalent to the phrase iPhrase of the +** current query is executed. Any column filter that applies to +** phrase iPhrase of the current query is included in $p. For each +** row visited, the callback function passed as the fourth argument +** is invoked. The context and API objects passed to the callback +** function may be used to access the properties of each matched row. +** Invoking Api.xUserData() returns a copy of the pointer passed as +** the third argument to pUserData. +** +** If the callback function returns any value other than SQLITE_OK, the +** query is abandoned and the xQueryPhrase function returns immediately. +** If the returned value is SQLITE_DONE, xQueryPhrase returns SQLITE_OK. +** Otherwise, the error code is propagated upwards. +** +** If the query runs to completion without incident, SQLITE_OK is returned. +** Or, if some error occurs before the query completes or is aborted by +** the callback, an SQLite error code is returned. +** +** +** xSetAuxdata(pFts5, pAux, xDelete) +** +** Save the pointer passed as the second argument as the extension function's +** "auxiliary data". The pointer may then be retrieved by the current or any +** future invocation of the same fts5 extension function made as part of +** the same MATCH query using the xGetAuxdata() API. +** +** Each extension function is allocated a single auxiliary data slot for +** each FTS query (MATCH expression). If the extension function is invoked +** more than once for a single FTS query, then all invocations share a +** single auxiliary data context. +** +** If there is already an auxiliary data pointer when this function is +** invoked, then it is replaced by the new pointer. If an xDelete callback +** was specified along with the original pointer, it is invoked at this +** point. +** +** The xDelete callback, if one is specified, is also invoked on the +** auxiliary data pointer after the FTS5 query has finished. +** +** If an error (e.g. an OOM condition) occurs within this function, +** the auxiliary data is set to NULL and an error code returned. If the +** xDelete parameter was not NULL, it is invoked on the auxiliary data +** pointer before returning. +** +** +** xGetAuxdata(pFts5, bClear) +** +** Returns the current auxiliary data pointer for the fts5 extension +** function. See the xSetAuxdata() method for details. +** +** If the bClear argument is non-zero, then the auxiliary data is cleared +** (set to NULL) before this function returns. In this case the xDelete, +** if any, is not invoked. +** +** +** xRowCount(pFts5, pnRow) +** +** This function is used to retrieve the total number of rows in the table. +** In other words, the same value that would be returned by: +** +** SELECT count(*) FROM ftstable; +** +** xPhraseFirst() +** This function is used, along with type Fts5PhraseIter and the xPhraseNext +** method, to iterate through all instances of a single query phrase within +** the current row. This is the same information as is accessible via the +** xInstCount/xInst APIs. While the xInstCount/xInst APIs are more convenient +** to use, this API may be faster under some circumstances. To iterate +** through instances of phrase iPhrase, use the following code: +** +** Fts5PhraseIter iter; +** int iCol, iOff; +** for(pApi->xPhraseFirst(pFts, iPhrase, &iter, &iCol, &iOff); +** iCol>=0; +** pApi->xPhraseNext(pFts, &iter, &iCol, &iOff) +** ){ +** // An instance of phrase iPhrase at offset iOff of column iCol +** } +** +** The Fts5PhraseIter structure is defined above. Applications should not +** modify this structure directly - it should only be used as shown above +** with the xPhraseFirst() and xPhraseNext() API methods (and by +** xPhraseFirstColumn() and xPhraseNextColumn() as illustrated below). +** +** This API can be quite slow if used with an FTS5 table created with the +** "detail=none" or "detail=column" option. If the FTS5 table is created +** with either "detail=none" or "detail=column" and "content=" option +** (i.e. if it is a contentless table), then this API always iterates +** through an empty set (all calls to xPhraseFirst() set iCol to -1). +** +** xPhraseNext() +** See xPhraseFirst above. +** +** xPhraseFirstColumn() +** This function and xPhraseNextColumn() are similar to the xPhraseFirst() +** and xPhraseNext() APIs described above. The difference is that instead +** of iterating through all instances of a phrase in the current row, these +** APIs are used to iterate through the set of columns in the current row +** that contain one or more instances of a specified phrase. For example: +** +** Fts5PhraseIter iter; +** int iCol; +** for(pApi->xPhraseFirstColumn(pFts, iPhrase, &iter, &iCol); +** iCol>=0; +** pApi->xPhraseNextColumn(pFts, &iter, &iCol) +** ){ +** // Column iCol contains at least one instance of phrase iPhrase +** } +** +** This API can be quite slow if used with an FTS5 table created with the +** "detail=none" option. If the FTS5 table is created with either +** "detail=none" "content=" option (i.e. if it is a contentless table), +** then this API always iterates through an empty set (all calls to +** xPhraseFirstColumn() set iCol to -1). +** +** The information accessed using this API and its companion +** xPhraseFirstColumn() may also be obtained using xPhraseFirst/xPhraseNext +** (or xInst/xInstCount). The chief advantage of this API is that it is +** significantly more efficient than those alternatives when used with +** "detail=column" tables. +** +** xPhraseNextColumn() +** See xPhraseFirstColumn above. +*/ +struct Fts5ExtensionApi { + int iVersion; /* Currently always set to 3 */ + + void *(*xUserData)(Fts5Context*); + + int (*xColumnCount)(Fts5Context*); + int (*xRowCount)(Fts5Context*, sqlite3_int64 *pnRow); + int (*xColumnTotalSize)(Fts5Context*, int iCol, sqlite3_int64 *pnToken); + + int (*xTokenize)(Fts5Context*, + const char *pText, int nText, /* Text to tokenize */ + void *pCtx, /* Context passed to xToken() */ + int (*xToken)(void*, int, const char*, int, int, int) /* Callback */ + ); + + int (*xPhraseCount)(Fts5Context*); + int (*xPhraseSize)(Fts5Context*, int iPhrase); + + int (*xInstCount)(Fts5Context*, int *pnInst); + int (*xInst)(Fts5Context*, int iIdx, int *piPhrase, int *piCol, int *piOff); + + sqlite3_int64 (*xRowid)(Fts5Context*); + int (*xColumnText)(Fts5Context*, int iCol, const char **pz, int *pn); + int (*xColumnSize)(Fts5Context*, int iCol, int *pnToken); + + int (*xQueryPhrase)(Fts5Context*, int iPhrase, void *pUserData, + int(*)(const Fts5ExtensionApi*,Fts5Context*,void*) + ); + int (*xSetAuxdata)(Fts5Context*, void *pAux, void(*xDelete)(void*)); + void *(*xGetAuxdata)(Fts5Context*, int bClear); + + int (*xPhraseFirst)(Fts5Context*, int iPhrase, Fts5PhraseIter*, int*, int*); + void (*xPhraseNext)(Fts5Context*, Fts5PhraseIter*, int *piCol, int *piOff); + + int (*xPhraseFirstColumn)(Fts5Context*, int iPhrase, Fts5PhraseIter*, int*); + void (*xPhraseNextColumn)(Fts5Context*, Fts5PhraseIter*, int *piCol); +}; + +/* +** CUSTOM AUXILIARY FUNCTIONS +*************************************************************************/ + +/************************************************************************* +** CUSTOM TOKENIZERS +** +** Applications may also register custom tokenizer types. A tokenizer +** is registered by providing fts5 with a populated instance of the +** following structure. All structure methods must be defined, setting +** any member of the fts5_tokenizer struct to NULL leads to undefined +** behaviour. The structure methods are expected to function as follows: +** +** xCreate: +** This function is used to allocate and initialize a tokenizer instance. +** A tokenizer instance is required to actually tokenize text. +** +** The first argument passed to this function is a copy of the (void*) +** pointer provided by the application when the fts5_tokenizer object +** was registered with FTS5 (the third argument to xCreateTokenizer()). +** The second and third arguments are an array of nul-terminated strings +** containing the tokenizer arguments, if any, specified following the +** tokenizer name as part of the CREATE VIRTUAL TABLE statement used +** to create the FTS5 table. +** +** The final argument is an output variable. If successful, (*ppOut) +** should be set to point to the new tokenizer handle and SQLITE_OK +** returned. If an error occurs, some value other than SQLITE_OK should +** be returned. In this case, fts5 assumes that the final value of *ppOut +** is undefined. +** +** xDelete: +** This function is invoked to delete a tokenizer handle previously +** allocated using xCreate(). Fts5 guarantees that this function will +** be invoked exactly once for each successful call to xCreate(). +** +** xTokenize: +** This function is expected to tokenize the nText byte string indicated +** by argument pText. pText may or may not be nul-terminated. The first +** argument passed to this function is a pointer to an Fts5Tokenizer object +** returned by an earlier call to xCreate(). +** +** The second argument indicates the reason that FTS5 is requesting +** tokenization of the supplied text. This is always one of the following +** four values: +** +**
    • FTS5_TOKENIZE_DOCUMENT - A document is being inserted into +** or removed from the FTS table. The tokenizer is being invoked to +** determine the set of tokens to add to (or delete from) the +** FTS index. +** +**
    • FTS5_TOKENIZE_QUERY - A MATCH query is being executed +** against the FTS index. The tokenizer is being called to tokenize +** a bareword or quoted string specified as part of the query. +** +**
    • (FTS5_TOKENIZE_QUERY | FTS5_TOKENIZE_PREFIX) - Same as +** FTS5_TOKENIZE_QUERY, except that the bareword or quoted string is +** followed by a "*" character, indicating that the last token +** returned by the tokenizer will be treated as a token prefix. +** +**
    • FTS5_TOKENIZE_AUX - The tokenizer is being invoked to +** satisfy an fts5_api.xTokenize() request made by an auxiliary +** function. Or an fts5_api.xColumnSize() request made by the same +** on a columnsize=0 database. +**
    +** +** For each token in the input string, the supplied callback xToken() must +** be invoked. The first argument to it should be a copy of the pointer +** passed as the second argument to xTokenize(). The third and fourth +** arguments are a pointer to a buffer containing the token text, and the +** size of the token in bytes. The 4th and 5th arguments are the byte offsets +** of the first byte of and first byte immediately following the text from +** which the token is derived within the input. +** +** The second argument passed to the xToken() callback ("tflags") should +** normally be set to 0. The exception is if the tokenizer supports +** synonyms. In this case see the discussion below for details. +** +** FTS5 assumes the xToken() callback is invoked for each token in the +** order that they occur within the input text. +** +** If an xToken() callback returns any value other than SQLITE_OK, then +** the tokenization should be abandoned and the xTokenize() method should +** immediately return a copy of the xToken() return value. Or, if the +** input buffer is exhausted, xTokenize() should return SQLITE_OK. Finally, +** if an error occurs with the xTokenize() implementation itself, it +** may abandon the tokenization and return any error code other than +** SQLITE_OK or SQLITE_DONE. +** +** SYNONYM SUPPORT +** +** Custom tokenizers may also support synonyms. Consider a case in which a +** user wishes to query for a phrase such as "first place". Using the +** built-in tokenizers, the FTS5 query 'first + place' will match instances +** of "first place" within the document set, but not alternative forms +** such as "1st place". In some applications, it would be better to match +** all instances of "first place" or "1st place" regardless of which form +** the user specified in the MATCH query text. +** +** There are several ways to approach this in FTS5: +** +**
    1. By mapping all synonyms to a single token. In this case, using +** the above example, this means that the tokenizer returns the +** same token for inputs "first" and "1st". Say that token is in +** fact "first", so that when the user inserts the document "I won +** 1st place" entries are added to the index for tokens "i", "won", +** "first" and "place". If the user then queries for '1st + place', +** the tokenizer substitutes "first" for "1st" and the query works +** as expected. +** +**
    2. By querying the index for all synonyms of each query term +** separately. In this case, when tokenizing query text, the +** tokenizer may provide multiple synonyms for a single term +** within the document. FTS5 then queries the index for each +** synonym individually. For example, faced with the query: +** +** +** ... MATCH 'first place' +** +** the tokenizer offers both "1st" and "first" as synonyms for the +** first token in the MATCH query and FTS5 effectively runs a query +** similar to: +** +** +** ... MATCH '(first OR 1st) place' +** +** except that, for the purposes of auxiliary functions, the query +** still appears to contain just two phrases - "(first OR 1st)" +** being treated as a single phrase. +** +**
    3. By adding multiple synonyms for a single term to the FTS index. +** Using this method, when tokenizing document text, the tokenizer +** provides multiple synonyms for each token. So that when a +** document such as "I won first place" is tokenized, entries are +** added to the FTS index for "i", "won", "first", "1st" and +** "place". +** +** This way, even if the tokenizer does not provide synonyms +** when tokenizing query text (it should not - to do so would be +** inefficient), it doesn't matter if the user queries for +** 'first + place' or '1st + place', as there are entries in the +** FTS index corresponding to both forms of the first token. +**
    +** +** Whether it is parsing document or query text, any call to xToken that +** specifies a tflags argument with the FTS5_TOKEN_COLOCATED bit +** is considered to supply a synonym for the previous token. For example, +** when parsing the document "I won first place", a tokenizer that supports +** synonyms would call xToken() 5 times, as follows: +** +** +** xToken(pCtx, 0, "i", 1, 0, 1); +** xToken(pCtx, 0, "won", 3, 2, 5); +** xToken(pCtx, 0, "first", 5, 6, 11); +** xToken(pCtx, FTS5_TOKEN_COLOCATED, "1st", 3, 6, 11); +** xToken(pCtx, 0, "place", 5, 12, 17); +** +** +** It is an error to specify the FTS5_TOKEN_COLOCATED flag the first time +** xToken() is called. Multiple synonyms may be specified for a single token +** by making multiple calls to xToken(FTS5_TOKEN_COLOCATED) in sequence. +** There is no limit to the number of synonyms that may be provided for a +** single token. +** +** In many cases, method (1) above is the best approach. It does not add +** extra data to the FTS index or require FTS5 to query for multiple terms, +** so it is efficient in terms of disk space and query speed. However, it +** does not support prefix queries very well. If, as suggested above, the +** token "first" is substituted for "1st" by the tokenizer, then the query: +** +** +** ... MATCH '1s*' +** +** will not match documents that contain the token "1st" (as the tokenizer +** will probably not map "1s" to any prefix of "first"). +** +** For full prefix support, method (3) may be preferred. In this case, +** because the index contains entries for both "first" and "1st", prefix +** queries such as 'fi*' or '1s*' will match correctly. However, because +** extra entries are added to the FTS index, this method uses more space +** within the database. +** +** Method (2) offers a midpoint between (1) and (3). Using this method, +** a query such as '1s*' will match documents that contain the literal +** token "1st", but not "first" (assuming the tokenizer is not able to +** provide synonyms for prefixes). However, a non-prefix query like '1st' +** will match against "1st" and "first". This method does not require +** extra disk space, as no extra entries are added to the FTS index. +** On the other hand, it may require more CPU cycles to run MATCH queries, +** as separate queries of the FTS index are required for each synonym. +** +** When using methods (2) or (3), it is important that the tokenizer only +** provide synonyms when tokenizing document text (method (2)) or query +** text (method (3)), not both. Doing so will not cause any errors, but is +** inefficient. +*/ +typedef struct Fts5Tokenizer Fts5Tokenizer; +typedef struct fts5_tokenizer fts5_tokenizer; +struct fts5_tokenizer { + int (*xCreate)(void*, const char **azArg, int nArg, Fts5Tokenizer **ppOut); + void (*xDelete)(Fts5Tokenizer*); + int (*xTokenize)(Fts5Tokenizer*, + void *pCtx, + int flags, /* Mask of FTS5_TOKENIZE_* flags */ + const char *pText, int nText, + int (*xToken)( + void *pCtx, /* Copy of 2nd argument to xTokenize() */ + int tflags, /* Mask of FTS5_TOKEN_* flags */ + const char *pToken, /* Pointer to buffer containing token */ + int nToken, /* Size of token in bytes */ + int iStart, /* Byte offset of token within input text */ + int iEnd /* Byte offset of end of token within input text */ + ) + ); +}; + +/* Flags that may be passed as the third argument to xTokenize() */ +#define FTS5_TOKENIZE_QUERY 0x0001 +#define FTS5_TOKENIZE_PREFIX 0x0002 +#define FTS5_TOKENIZE_DOCUMENT 0x0004 +#define FTS5_TOKENIZE_AUX 0x0008 + +/* Flags that may be passed by the tokenizer implementation back to FTS5 +** as the third argument to the supplied xToken callback. */ +#define FTS5_TOKEN_COLOCATED 0x0001 /* Same position as prev. token */ + +/* +** END OF CUSTOM TOKENIZERS +*************************************************************************/ + +/************************************************************************* +** FTS5 EXTENSION REGISTRATION API +*/ +typedef struct fts5_api fts5_api; +struct fts5_api { + int iVersion; /* Currently always set to 2 */ + + /* Create a new tokenizer */ + int (*xCreateTokenizer)( + fts5_api *pApi, + const char *zName, + void *pContext, + fts5_tokenizer *pTokenizer, + void (*xDestroy)(void*) + ); + + /* Find an existing tokenizer */ + int (*xFindTokenizer)( + fts5_api *pApi, + const char *zName, + void **ppContext, + fts5_tokenizer *pTokenizer + ); + + /* Create a new auxiliary function */ + int (*xCreateFunction)( + fts5_api *pApi, + const char *zName, + void *pContext, + fts5_extension_function xFunction, + void (*xDestroy)(void*) + ); +}; + +/* +** END OF REGISTRATION API +*************************************************************************/ + +#ifdef __cplusplus +} /* end of the 'extern "C"' block */ +#endif + +#endif /* _FTS5_H */ + +/******** End of fts5.h *********/ diff --git a/VNode/_software_lib/nanomq-0.22.10/include/nng/supplemental/tls/engine.h b/VNode/_software_lib/nanomq-0.22.10/include/nng/supplemental/tls/engine.h new file mode 100644 index 00000000..5bfe339d --- /dev/null +++ b/VNode/_software_lib/nanomq-0.22.10/include/nng/supplemental/tls/engine.h @@ -0,0 +1,222 @@ +// +// Copyright 2024 Staysail Systems, Inc. +// +// This software is supplied under the terms of the MIT License, a +// copy of which should be located in the distribution where this +// file was obtained (LICENSE.txt). A copy of the license may also be +// found online at https://opensource.org/licenses/MIT. +// + +// This file is used to enable external TLS "engines", so +// that third party TLS libraries can be plugged in + +#ifndef NNG_SUPPLEMENTAL_TLS_ENGINE_H +#define NNG_SUPPLEMENTAL_TLS_ENGINE_H + +#include + +// Locking theory statement for TLS engines. The engine is assumed +// operate only from the context of threads called by the common +// framework. That is to say, the callbacks made by the engine +// should always be on a thread that has context from the framework +// calling into the engine. This means that the lower level send +// and receive functions can assume that they have lock ownership +// inherited on the stack. + +// nng_tls_engine_conn represents the engine-specific private +// state for a TLS connection. It is provided here for type +// safety. Engine implementations should provide the structure +// definition locally. +typedef struct nng_tls_engine_conn nng_tls_engine_conn; + +// nng_tls_engine_config represents the engine-specific private +// state for the TLS configuration. It is provided here for type +// safety. Engine implementations should provide the structure +// definition locally. +typedef struct nng_tls_engine_config nng_tls_engine_config; + +typedef struct nng_tls_engine_conn_ops_s { + // size is the size of the engine's per-connection state. + // The framework will allocate this on behalf of the engine. + // Typically this will be sizeof (struct nng_tls_engine_conn). + size_t size; + + // init is used to initialize a connection object. + // The passed in connection state will be aligned naturally, + // and zeroed. On success this returns 0, else an NNG error code. + int (*init)(nng_tls_engine_conn *, void *, nng_tls_engine_config *); + + // fini destroys a connection object. This will + // be called only when no other external use of the connection + // object exists, and only on fully initialed connection objects. + void (*fini)(nng_tls_engine_conn *); + + // close closes the connection object, but should not + // deallocate any memory. It may also issue a TLS close-notify. + void (*close)(nng_tls_engine_conn *); + + // handshake attempts to complete the SSL handshake phase. + // It returns zero on success, or an error if one occurred. + // The value NNG_EAGAIN should be returned if underlying I/O + // is required to be completed first. The framework will + // ensure that the handshake completes before sending any data + // down. + int (*handshake)(nng_tls_engine_conn *); + + // recv attempts to read data (decrypted) from the connection. + // It returns 0 on success, otherwise an error. The implementation + // should return NNG_EAGAIN if I/O to the underlying stream is + // required to complete the operation. On success, the count + // is updated to reflect the number of bytes actually received. + int (*recv)(nng_tls_engine_conn *, uint8_t *, size_t *); + + // send attempts to write data to the underlying connection. + // It returns zero on success, otherwise an error. The implementation + // should return NNG_EAGAIN if I/O to the underlying stream is + // required to complete the operation. On success, the count + // is updated to reflect the number of bytes actually sent. + int (*send)(nng_tls_engine_conn *, const uint8_t *, size_t *); + + // verified returns true if the connection is fully + // TLS verified, false otherwise. + bool (*verified)(nng_tls_engine_conn *); + + // peer_cn returns the common name of the peer + // The return string needs to be freed. + char *(*peer_cn)(nng_tls_engine_conn *); + + // peer_alt_names returns the subject alternative names. + // The return string list and its strings need to be freed. + char **(*peer_alt_names)(nng_tls_engine_conn *); +} nng_tls_engine_conn_ops; + +typedef struct nng_tls_engine_config_ops_s { + // size is the size of the engine's configuration object. + // The framework will allocate this on behalf of the engine. + // Typically this will be sizeof (struct nng_tls_engine_config). + size_t size; + + // init prepares the configuration object object. + // The mode indicates whether the object should be + // initialized for use as a TLS server or client. + // The config passed in will be aligned on a 64-bit boundary, + // and will be initialized to zero. On success this returns + // 0, else an NNG error code. + int (*init)(nng_tls_engine_config *, nng_tls_mode); + + // fini is used to tear down the configuration object. + // This will only be called on objects that have been properly + // initialized with nte_config_init. + void (*fini)(nng_tls_engine_config *); + + // server is used to set the server name. This can be used in SNI, + // and will also be used on the client to validate the identity. + // If this is not set, then no verification will be performed. + int (*server)(nng_tls_engine_config *, const char *); + + // auth is used to configure the authentication mode. Values: + // NNG_AUTH_MODE_NONE + // No validation of the peer is performed. Public facing + // servers often use this. + // NNG_AUTH_MODE_OPTIONAL + // The peer's identity is validated if a certificate is presented. + // This is typically useful on servers. + // NNG_AUTH_MODE_REQUIRED + // The peer's certificate must be present and is verified. + // This is standard for the client, and on servers it is used + // when client (mutual) authentication is needed. + int (*auth)(nng_tls_engine_config *, nng_tls_auth_mode); + + // ca_chain sets the configuration authorities that will be + // used to validate peers. An optional CRL is supplied as well. + // Both values are C strings (NUL terminated) containing + // PEM data. There may be multiple PEM blocks. The + // CRL may be NULL if not needed. + int (*ca_chain)(nng_tls_engine_config *, const char *, const char *); + + // own_cert configures our identity -- the certificate containing + // our public key, our private key (which might be encrypted), and + // potentially a password used to decrypt the private key. + // All of these are C strings. The cert may actually be a chain + // which will be presented to our peer. This function may be + // called multiple times to register different keys with different + // parameters on a server. (For example, once for RSA parameters, + // and again later with EC parameters.) The certificate and the + // private key may be presented in the same file. The implementation + // is responsible for parsing out the relevant data. If the password + // is NULL, then the key file should be unencrypted. The supplied + // password may be ignored if the key is not encrypted. Not all + // engine implementations need support encryption of the key. + int (*own_cert)( + nng_tls_engine_config *, const char *, const char *, const char *); + + // psk configures a PSK identity and key. This can be called + // once for clients, or multiple times for servers. However, not all + // implementations support multiple PSKs for a server. + int (*psk)( + nng_tls_engine_config *, const char *, const uint8_t *, size_t); + + // version configures the minimum and maximum TLS versions. The + // engine should default to supporting TLS1.0 through 1.2, and + // optionally 1.3 if it can. The engine should restrict the + // the requested range to what it can support -- if no version + // within the range is supported (such as if NNG_TLS_1_3 is + // specified for both min and max, and the engine lacks support + // for v1.3, then NNG_ENOTSUP should be returned. + int (*version)( + nng_tls_engine_config *, nng_tls_version, nng_tls_version); +} nng_tls_engine_config_ops; + +typedef enum nng_tls_engine_version_e { + NNG_TLS_ENGINE_V0 = 0, + NNG_TLS_ENGINE_V1 = 1, // adds FIPS, TLS 1.3 support + NNG_TLS_ENGINE_V2 = 2, // adds PSK support + NNG_TLS_ENGINE_VERSION = NNG_TLS_ENGINE_V2, +} nng_tls_engine_version; + +typedef struct nng_tls_engine_s { + // _version is the engine version. This for now must + // be NNG_TLS_ENGINE_VERSION. If the version does not match + // then registration of the engine will fail. + nng_tls_engine_version version; + + // config_ops is the operations for TLS configuration objects. + nng_tls_engine_config_ops *config_ops; + + // conn_ops is the operations for TLS connections (stream-oriented). + nng_tls_engine_conn_ops *conn_ops; + + // name contains the name of the engine, for example "wolfSSL". + // It is acceptable to append a version number as well. + const char *name; + + // description contains a human readable description. This can + // supply information about the backing library, for example + // "mbed TLS v2.7" + const char *description; + + // fips_mode is true if the engine is in FIPS mode. + // It is expected that this will be enabled either at compile + // time, or via environment variables at engine initialization. + // FIPS mode cannot be changed once the engine is registered. + bool fips_mode; +} nng_tls_engine; + +NNG_DECL int nng_tls_engine_register(const nng_tls_engine *); + +// nng_tls_engine_send is called by the engine to send data over the +// underlying connection. It returns zero on success, NNG_EAGAIN if +// the operation can't be completed yet (the transport is busy and cannot +// accept more data yet), or some other error. On success the count is +// updated with the number of bytes actually sent. The first argument +// is the context structure passed in when starting the engine. +NNG_DECL int nng_tls_engine_send(void *, const uint8_t *, size_t *); + +// nng_tls_engine_recv is called byu the engine to receive data over +// the underlying connection. It returns zero on success, NNG_EAGAIN +// if the operation can't be completed yet (there is no data available +// for reading), or some other error. On success the count is updated +// with the number of bytes actually received. +NNG_DECL int nng_tls_engine_recv(void *, uint8_t *, size_t *); + +#endif // NNG_SUPPLEMENTAL_TLS_ENGINE_H diff --git a/VNode/_software_lib/nanomq-0.22.10/include/nng/supplemental/tls/tls.h b/VNode/_software_lib/nanomq-0.22.10/include/nng/supplemental/tls/tls.h new file mode 100644 index 00000000..e66f5a32 --- /dev/null +++ b/VNode/_software_lib/nanomq-0.22.10/include/nng/supplemental/tls/tls.h @@ -0,0 +1,152 @@ +// +// Copyright 2024 Staysail Systems, Inc. +// Copyright 2018 Capitar IT Group BV +// +// This software is supplied under the terms of the MIT License, a +// copy of which should be located in the distribution where this +// file was obtained (LICENSE.txt). A copy of the license may also be +// found online at https://opensource.org/licenses/MIT. +// + +#ifndef NNG_SUPPLEMENTAL_TLS_TLS_H +#define NNG_SUPPLEMENTAL_TLS_TLS_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include + +#include + +// Note that TLS functions may be stubbed out if TLS is not enabled in +// the build. + +// For some transports, we need TLS configuration, including certificates +// and so forth. A TLS configuration cannot be changed once it is in use. +typedef struct nng_tls_config nng_tls_config; + +typedef enum nng_tls_mode { + NNG_TLS_MODE_CLIENT = 0, + NNG_TLS_MODE_SERVER = 1, +} nng_tls_mode; + +typedef enum nng_tls_auth_mode { + NNG_TLS_AUTH_MODE_NONE = 0, // No verification is performed + NNG_TLS_AUTH_MODE_OPTIONAL = 1, // Verify cert if presented + NNG_TLS_AUTH_MODE_REQUIRED = 2, // Verify cert, close if invalid +} nng_tls_auth_mode; + +// TLS version numbers. We encode the major number and minor number +// as separate byte fields. No support for SSL 3.0 or earlier -- older +// versions are known to be insecure and should not be used. +// When possible applications should restrict themselves to TLS 1.2 or better. +typedef enum nng_tls_version { + NNG_TLS_1_0 = 0x301, + NNG_TLS_1_1 = 0x302, + NNG_TLS_1_2 = 0x303, + NNG_TLS_1_3 = 0x304 +} nng_tls_version; + +// nng_tls_config_alloc creates a TLS configuration using +// reasonable defaults. This configuration can be shared +// with multiple pipes or services/servers. +NNG_DECL int nng_tls_config_alloc(nng_tls_config **, nng_tls_mode); + +// nng_tls_config_hold increments the reference count on the TLS +// configuration object. The hold can be dropped by calling +// nng_tls_config_free later. +NNG_DECL void nng_tls_config_hold(nng_tls_config *); + +// nng_tls_config_free drops the reference count on the TLS +// configuration object, and if zero, deallocates it. +NNG_DECL void nng_tls_config_free(nng_tls_config *); + +// nng_tls_config_server_name sets the server name. This is +// called by clients to set the name that the server supplied +// certificate should be matched against. This can also cause +// the SNI to be sent to the server to tell it which cert to +// use if it supports more than one. +NNG_DECL int nng_tls_config_server_name(nng_tls_config *, const char *); + +// nng_tls_config_ca_cert configures one or more CAs used for validation +// of peer certificates. Multiple CAs (and their chains) may be configured +// by either calling this multiple times, or by specifying a list of +// certificates as concatenated data. The final argument is an optional CRL +// (revocation list) for the CA, also in PEM. Both PEM strings are ASCIIZ +// format (except that the CRL may be NULL). +NNG_DECL int nng_tls_config_ca_chain( + nng_tls_config *, const char *, const char *); + +// nng_tls_config_own_cert is used to load our own certificate and public +// key. For servers, this may be called more than once to configure multiple +// different keys, for example with different algorithms depending on what +// the peer supports. On the client, only a single option is available. +// The first two arguments are the cert (or validation chain) and the +// key as PEM format ASCIIZ strings. The final argument is an optional +// password and may be NULL. +NNG_DECL int nng_tls_config_own_cert( + nng_tls_config *, const char *, const char *, const char *); + +// nng_tls_config_key is used to pass our own private key. +NNG_DECL int nng_tls_config_key(nng_tls_config *, const uint8_t *, size_t); + +// nng_tls_config_pass is used to pass a password used to decrypt +// private keys that are encrypted. +NNG_DECL int nng_tls_config_pass(nng_tls_config *, const char *); + +// nng_tls_config_auth_mode is used to configure the authentication mode use. +// The default is that servers have this off (i.e. no client authentication) +// and clients have it on (they verify the server), which matches typical +// practice. +NNG_DECL int nng_tls_config_auth_mode(nng_tls_config *, nng_tls_auth_mode); + +// nng_tls_config_ca_file is used to pass a CA chain and optional CRL +// via the filesystem. If CRL data is present, it must be contained +// in the file, along with the CA certificate data. The format is PEM. +// The path name must be a legal file name. +NNG_DECL int nng_tls_config_ca_file(nng_tls_config *, const char *); + +// nng_tls_config_cert_key_file is used to pass our own certificate and +// private key data via the filesystem. Both the key and certificate +// must be present as PEM blocks in the same file. A password is used to +// decrypt the private key if it is encrypted and the password supplied is not +// NULL. This may be called multiple times on servers, but only once on a +// client. (Servers can support multiple different certificates and keys for +// different cryptographic algorithms. Clients only get one.) +NNG_DECL int nng_tls_config_cert_key_file( + nng_tls_config *, const char *, const char *); + +// nng_tls_config_psk_identity is used to pass TLS PSK parameters. The +// identity, and an associated key. Clients can only do this once. +// Servers can do it multiple times, potentially, to provide for different +// keys for different client identities. There is no way to remove these +// from a configuration. +NNG_DECL int nng_tls_config_psk( + nng_tls_config *, const char *, const uint8_t *, size_t); + +// Configure supported TLS version. By default we usually restrict +// ourselves to TLS 1.2 and newer. We do not support older versions. +// If the implementation cannot support any version (for example if +// the minimum requested is 1.3 but the TLS implementation lacks support +// for TLS 1.3) then NNG_ENOTSUP will be returned. +NNG_DECL int nng_tls_config_version( + nng_tls_config *, nng_tls_version, nng_tls_version); + +// nng_tls_engine_name returns the "name" of the TLS engine. If no +// TLS engine support is enabled, then "none" is returned. +NNG_DECL const char *nng_tls_engine_name(void); + +// nng_tls_engine_description returns the "description" of the TLS engine. +// If no TLS engine support is enabled, then an empty string is returned. +NNG_DECL const char *nng_tls_engine_description(void); + +// nng_tls_engine_fips_mode returns true if the engine is in FIPS 140-2 mode. +NNG_DECL bool nng_tls_engine_fips_mode(void); + +#ifdef __cplusplus +} +#endif + +#endif // NNG_SUPPLEMENTAL_TLS_TLS_H diff --git a/VNode/_software_lib/nanomq-0.22.10/include/nng/supplemental/util/idhash.h b/VNode/_software_lib/nanomq-0.22.10/include/nng/supplemental/util/idhash.h new file mode 100644 index 00000000..0f71d6d1 --- /dev/null +++ b/VNode/_software_lib/nanomq-0.22.10/include/nng/supplemental/util/idhash.h @@ -0,0 +1,42 @@ +// +// Copyright 2024 Staysail Systems, Inc. +// +// This software is supplied under the terms of the MIT License, a +// copy of which should be located in the distribution where this +// file was obtained (LICENSE.txt). A copy of the license may also be +// found online at https://opensource.org/licenses/MIT. +// + +#ifndef NNG_SUPPLEMENTAL_UTIL_IDHASH_H +#define NNG_SUPPLEMENTAL_UTIL_IDHASH_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +typedef struct nng_id_map_s nng_id_map; + +#define NNG_MAP_RANDOM 1 + +// For NanoNNG +NNG_DECL void nng_id_map_foreach( + nng_id_map *map, void (*)(void *, void *)); +NNG_DECL void nng_id_map_foreach2(nng_id_map *map, + void (*)(void *, void *, void *), void *); + +NNG_DECL int nng_id_map_alloc( + nng_id_map **map, uint64_t lo, uint64_t hi, int flags); +NNG_DECL void nng_id_map_free(nng_id_map *map); +NNG_DECL void *nng_id_get(nng_id_map *, uint64_t); +NNG_DECL int nng_id_set(nng_id_map *, uint64_t, void *); +NNG_DECL int nng_id_alloc(nng_id_map *, uint64_t *, void *); +NNG_DECL int nng_id_remove(nng_id_map *, uint64_t); +NNG_DECL bool nng_id_visit(nng_id_map *, uint64_t *, void **, uint32_t *); + +#ifdef __cplusplus +} +#endif + +#endif // NNG_SUPPLEMENTAL_IDHASH_IDHASH_H diff --git a/VNode/_software_lib/nanomq-0.22.10/include/nng/supplemental/util/options.h b/VNode/_software_lib/nanomq-0.22.10/include/nng/supplemental/util/options.h new file mode 100644 index 00000000..6d0a3c1a --- /dev/null +++ b/VNode/_software_lib/nanomq-0.22.10/include/nng/supplemental/util/options.h @@ -0,0 +1,50 @@ +// +// Copyright 2024 Staysail Systems, Inc. +// Copyright 2018 Capitar IT Group BV +// +// This software is supplied under the terms of the MIT License, a +// copy of which should be located in the distribution where this +// file was obtained (LICENSE.txt). A copy of the license may also be +// found online at https://opensource.org/licenses/MIT. +// + +#ifndef NNG_SUPPLEMENTAL_UTIL_OPTIONS_H +#define NNG_SUPPLEMENTAL_UTIL_OPTIONS_H + +#include + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +// This is a relatively simple "options parsing" library, used to +// parse command line options. We would use getopt(3), but there are +// two problems with getopt(3). First, it isn't available on all +// platforms (especially Win32), and second, it doesn't support long +// options. We *exclusively* support long options. POSIX style +// short option clustering is *NOT* supported. + +struct nng_optspec { + const char *o_name; // Long style name (may be NULL for short only) + int o_short; // Short option (no clustering!) + int o_val; // Value stored on a good parse (>0) + bool o_arg; // Option takes an argument if true +}; + +typedef struct nng_optspec nng_optspec; + +// Call with *optidx set to 1 to start parsing for a standard program. +// The val will store the value of the matched "o_val", optarg will be +// set to match the option string, and optidx will be increment appropriately. +// Returns -1 when the end of options is reached, 0 on success, or +// NNG_EINVAL if the option parse is invalid for any reason. +NNG_DECL int nng_opts_parse(int argc, char *const *argv, + const nng_optspec *opts, int *val, char **optarg, int *optidx); + +#ifdef __cplusplus +} +#endif + +#endif // NNG_SUPPLEMENTAL_UTIL_OPTIONS_H diff --git a/VNode/_software_lib/nanomq-0.22.10/include/nng/supplemental/util/platform.h b/VNode/_software_lib/nanomq-0.22.10/include/nng/supplemental/util/platform.h new file mode 100644 index 00000000..c20ceee9 --- /dev/null +++ b/VNode/_software_lib/nanomq-0.22.10/include/nng/supplemental/util/platform.h @@ -0,0 +1,119 @@ +// +// Copyright 2024 Staysail Systems, Inc. +// Copyright 2018 Capitar IT Group BV +// +// This software is supplied under the terms of the MIT License, a +// copy of which should be located in the distribution where this +// file was obtained (LICENSE.txt). A copy of the license may also be +// found online at https://opensource.org/licenses/MIT. +// + +#ifndef NNG_SUPPLEMENTAL_UTIL_PLATFORM_H +#define NNG_SUPPLEMENTAL_UTIL_PLATFORM_H + +// The declarations in this file are provided to assist with application +// portability. Conceptually these APIs are based on work we have already +// done for NNG internals, and we find that they are useful in building +// portable applications. + +// If it is more natural to use native system APIs like pthreads or C11 +// APIs or Windows APIs, then by all means please feel free to simply +// ignore this. + +#include +#include + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +// Return unix timestamp (milliseconds) . +NNG_DECL nng_time nng_timestamp(void); + +// Get current process Id. +NNG_DECL int nng_getpid(); + +// nng_rwlock is a rwlock. TODO more comments +typedef struct nng_rwlock nng_rwlock; +NNG_DECL int nng_rwlock_alloc(nng_rwlock **); +NNG_DECL void nng_rwlock_free(nng_rwlock *); +NNG_DECL void nng_rwlock_rdlock(nng_rwlock *); +NNG_DECL void nng_rwlock_rwlock(nng_rwlock *); +NNG_DECL void nng_rwlock_unlock(nng_rwlock *); + +// +// Atomics support. This will evolve over time. +// + +// nng_atomic_flag supports only test-and-set and reset operations. +// This can be implemented without locks on any reasonable system, and +// it corresponds to C11 atomic flag. +typedef struct nni_atomic_flag nng_atomic_flag; + +NNG_DECL bool nng_atomic_flag_test_and_set(nng_atomic_flag *); +NNG_DECL void nng_atomic_flag_reset(nng_atomic_flag *); + +// nng_atomic_bool is for boolean flags that need to be checked without +// changing their value. This might require a lock on some systems. +typedef struct nni_atomic_bool nng_atomic_bool; + +NNG_DECL int nng_atomic_alloc_bool(nng_atomic_bool **v); +NNG_DECL void nng_atomic_free_bool(nng_atomic_bool *v); +NNG_DECL void nng_atomic_set_bool(nng_atomic_bool *, bool); +NNG_DECL bool nng_atomic_get_bool(nng_atomic_bool *); +NNG_DECL bool nng_atomic_swap_bool(nng_atomic_bool *, bool); + +typedef struct nni_atomic_u64 nng_atomic_u64; + +NNG_DECL int nng_atomic_alloc64(nng_atomic_u64 **v); +NNG_DECL void nng_atomic_free64(nng_atomic_u64 *v); +NNG_DECL void nng_atomic_add64(nng_atomic_u64 *, uint64_t); +NNG_DECL void nng_atomic_sub64(nng_atomic_u64 *, uint64_t); +NNG_DECL uint64_t nng_atomic_get64(nng_atomic_u64 *); +NNG_DECL void nng_atomic_set64(nng_atomic_u64 *, uint64_t); +NNG_DECL uint64_t nng_atomic_swap64(nng_atomic_u64 *, uint64_t); +NNG_DECL uint64_t nng_atomic_dec64_nv(nng_atomic_u64 *); +NNG_DECL void nng_atomic_inc64(nng_atomic_u64 *); + +// nng_atomic_cas64 is a compare and swap. The second argument is the +// value to compare against, and the third is the new value. Returns +// true if the value was set. +NNG_DECL bool nng_atomic_cas64(nng_atomic_u64 *, uint64_t, uint64_t); + +// In a lot of circumstances, we want a simple atomic reference count, +// or atomic tunable values for integers like queue lengths or TTLs. +// These native integer forms should be preferred over the 64 bit versions +// unless larger bit sizes are truly needed. They will be more efficient +// on many platforms. +typedef struct nni_atomic_int nng_atomic_int; + +NNG_DECL int nng_atomic_alloc(nng_atomic_int **v); +NNG_DECL void nng_atomic_free(nng_atomic_int *v); +NNG_DECL void nng_atomic_add(nng_atomic_int *, int); +NNG_DECL void nng_atomic_sub(nng_atomic_int *, int); +NNG_DECL int nng_atomic_get(nng_atomic_int *); +NNG_DECL void nng_atomic_set(nng_atomic_int *, int); +NNG_DECL int nng_atomic_swap(nng_atomic_int *, int); +NNG_DECL int nng_atomic_dec_nv(nng_atomic_int *); +NNG_DECL void nng_atomic_dec(nng_atomic_int *); +NNG_DECL void nng_atomic_inc(nng_atomic_int *); + +// nng_atomic_cas is a compare and swap. The second argument is the +// value to compare against, and the third is the new value. Returns +// true if the value was set. +NNG_DECL bool nng_atomic_cas(nng_atomic_int *, int, int); + +// atomic pointers. We only support a few operations. +typedef struct nni_atomic_ptr nng_atomic_ptr; +NNG_DECL int nng_atomic_alloc_ptr(nng_atomic_ptr **v); +NNG_DECL void nng_atomic_free_ptr(nng_atomic_ptr *v); +NNG_DECL void nng_atomic_set_ptr(nng_atomic_ptr *, void *); +NNG_DECL void * nng_atomic_get_ptr(nng_atomic_ptr *); + +#ifdef __cplusplus +} +#endif + +#endif // NNG_SUPPLEMENTAL_UTIL_PLATFORM_H diff --git a/VNode/_software_lib/nanomq-0.22.10/include/nng/transport/inproc/inproc.h b/VNode/_software_lib/nanomq-0.22.10/include/nng/transport/inproc/inproc.h new file mode 100644 index 00000000..0c633620 --- /dev/null +++ b/VNode/_software_lib/nanomq-0.22.10/include/nng/transport/inproc/inproc.h @@ -0,0 +1,29 @@ +// +// Copyright 2021 Staysail Systems, Inc. +// Copyright 2017 Capitar IT Group BV +// +// This software is supplied under the terms of the MIT License, a +// copy of which should be located in the distribution where this +// file was obtained (LICENSE.txt). A copy of the license may also be +// found online at https://opensource.org/licenses/MIT. +// + +#ifndef NNG_TRANSPORT_INPROC_INPROC_H +#define NNG_TRANSPORT_INPROC_INPROC_H + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +// inproc transport. This is used for intra-process communication. +#ifndef NNG_ELIDE_DEPRECATED +NNG_DECL int nng_inproc_register(void); +#endif + +#ifdef __cplusplus +} +#endif + +#endif // NNG_TRANSPORT_INPROC_INPROC_H diff --git a/VNode/_software_lib/nanomq-0.22.10/include/nng/transport/ipc/ipc.h b/VNode/_software_lib/nanomq-0.22.10/include/nng/transport/ipc/ipc.h new file mode 100644 index 00000000..cccef9a1 --- /dev/null +++ b/VNode/_software_lib/nanomq-0.22.10/include/nng/transport/ipc/ipc.h @@ -0,0 +1,31 @@ +// +// Copyright 2021 Staysail Systems, Inc. +// Copyright 2018 Capitar IT Group BV +// +// This software is supplied under the terms of the MIT License, a +// copy of which should be located in the distribution where this +// file was obtained (LICENSE.txt). A copy of the license may also be +// found online at https://opensource.org/licenses/MIT. +// + +#ifndef NNG_TRANSPORT_IPC_IPC_H +#define NNG_TRANSPORT_IPC_IPC_H + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +// ipc transport. This is used for inter-process communication on +// the same host computer. + +#ifndef NNG_ELIDE_DEPRECATED +NNG_DECL int nng_ipc_register(void); +#endif + +#ifdef __cplusplus +} +#endif + +#endif // NNG_TRANSPORT_IPC_IPC_H diff --git a/VNode/_software_lib/nanomq-0.22.10/include/nng/transport/mqtt/broker_tcp.h b/VNode/_software_lib/nanomq-0.22.10/include/nng/transport/mqtt/broker_tcp.h new file mode 100644 index 00000000..7b59126b --- /dev/null +++ b/VNode/_software_lib/nanomq-0.22.10/include/nng/transport/mqtt/broker_tcp.h @@ -0,0 +1,30 @@ +// +// Copyright 2021 Staysail Systems, Inc. +// Copyright 2017 Capitar IT Group BV +// +// This software is supplied under the terms of the MIT License, a +// copy of which should be located in the distribution where this +// file was obtained (LICENSE.txt). A copy of the license may also be +// found online at https://opensource.org/licenses/MIT. +// + +#ifndef NNG_TRANSPORT_MQTT_BROKER_TCP_TCP_H +#define NNG_TRANSPORT_MQTT_BROKER_TCP_TCP_H + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +// TCP transport. This is used for communication over TCP/IP. + +#ifndef NNG_ELIDE_DEPRECATED +NNG_DECL int nmq_mqtt_tcp_register(void); +#endif + +#ifdef __cplusplus +} +#endif + +#endif // NNG_TRANSPORT_MQTT_TCP_TCP_H diff --git a/VNode/_software_lib/nanomq-0.22.10/include/nng/transport/mqtts/broker_tls.h b/VNode/_software_lib/nanomq-0.22.10/include/nng/transport/mqtts/broker_tls.h new file mode 100644 index 00000000..e3725a1f --- /dev/null +++ b/VNode/_software_lib/nanomq-0.22.10/include/nng/transport/mqtts/broker_tls.h @@ -0,0 +1,30 @@ +// +// Copyright 2021 Staysail Systems, Inc. +// Copyright 2017 Capitar IT Group BV +// +// This software is supplied under the terms of the MIT License, a +// copy of which should be located in the distribution where this +// file was obtained (LICENSE.txt). A copy of the license may also be +// found online at https://opensource.org/licenses/MIT. +// + +#ifndef NNG_TRANSPORT_MQTT_BROKER_TLS_TCP_H +#define NNG_TRANSPORT_MQTT_BROKER_TLS_TCP_H + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +// TLS transport. This is used for communication over TLS. + +#ifndef NNG_ELIDE_DEPRECATED +NNG_DECL int nmq_mqtt_tls_register(void); +#endif + +#ifdef __cplusplus +} +#endif + +#endif // NNG_TRANSPORT_MQTT_BROKER_TLS_TCP_H diff --git a/VNode/_software_lib/nanomq-0.22.10/include/nng/transport/mqttws/nmq_websocket.h b/VNode/_software_lib/nanomq-0.22.10/include/nng/transport/mqttws/nmq_websocket.h new file mode 100644 index 00000000..0661fc43 --- /dev/null +++ b/VNode/_software_lib/nanomq-0.22.10/include/nng/transport/mqttws/nmq_websocket.h @@ -0,0 +1,35 @@ +// +// Copyright 2021 Staysail Systems, Inc. +// Copyright 2018 Capitar IT Group BV +// +// This software is supplied under the terms of the MIT License, a +// copy of which should be located in the distribution where this +// file was obtained (LICENSE.txt). A copy of the license may also be +// found online at https://opensource.org/licenses/MIT. +// + +#ifndef NNG_TRANSPORT_WS_WEBSOCKET_H +#define NNG_TRANSPORT_WS_WEBSOCKET_H + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +// WebSocket transport. This is used for communication via WebSocket. + +// These aliases are for WSS naming consistency. +#define NNG_OPT_WSS_REQUEST_HEADERS NNG_OPT_WS_REQUEST_HEADERS +#define NNG_OPT_WSS_RESPONSE_HEADERS NNG_OPT_WS_RESPONSE_HEADERS + +#ifndef NNG_ELIDE_DEPRECATED +NNG_DECL int nng_nmq_ws_register(void); +NNG_DECL int nng_nmq_wss_register(void); +#endif + +#ifdef __cplusplus +} +#endif + +#endif // NNG_TRANSPORT_WS_WEBSOCKET_H diff --git a/VNode/_software_lib/nanomq-0.22.10/include/nng/transport/tcp/tcp.h b/VNode/_software_lib/nanomq-0.22.10/include/nng/transport/tcp/tcp.h new file mode 100644 index 00000000..e236c271 --- /dev/null +++ b/VNode/_software_lib/nanomq-0.22.10/include/nng/transport/tcp/tcp.h @@ -0,0 +1,30 @@ +// +// Copyright 2021 Staysail Systems, Inc. +// Copyright 2017 Capitar IT Group BV +// +// This software is supplied under the terms of the MIT License, a +// copy of which should be located in the distribution where this +// file was obtained (LICENSE.txt). A copy of the license may also be +// found online at https://opensource.org/licenses/MIT. +// + +#ifndef NNG_TRANSPORT_TCP_TCP_H +#define NNG_TRANSPORT_TCP_TCP_H + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +// TCP transport. This is used for communication over TCP/IP. + +#ifndef NNG_ELIDE_DEPRECATED +NNG_DECL int nng_tcp_register(void); +#endif + +#ifdef __cplusplus +} +#endif + +#endif // NNG_TRANSPORT_TCP_TCP_H diff --git a/VNode/_software_lib/nanomq-0.22.10/include/nng/transport/tls/tls.h b/VNode/_software_lib/nanomq-0.22.10/include/nng/transport/tls/tls.h new file mode 100644 index 00000000..5e99372b --- /dev/null +++ b/VNode/_software_lib/nanomq-0.22.10/include/nng/transport/tls/tls.h @@ -0,0 +1,30 @@ +// +// Copyright 2019 Staysail Systems, Inc. +// Copyright 2018 Capitar IT Group BV +// +// This software is supplied under the terms of the MIT License, a +// copy of which should be located in the distribution where this +// file was obtained (LICENSE.txt). A copy of the license may also be +// found online at https://opensource.org/licenses/MIT. +// + +#ifndef NNG_TRANSPORT_TLS_TLS_H +#define NNG_TRANSPORT_TLS_TLS_H + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +// TLS transport. This is used for communication via TLS v1.2 over TCP/IP. + +#ifndef NNG_ELIDE_DEPRECATED +NNG_DECL int nng_tls_register(void); +#endif + +#ifdef __cplusplus +} +#endif + +#endif // NNG_TRANSPORT_TLS_TLS_H diff --git a/VNode/_software_lib/nanomq-0.22.10/include/nng/transport/ws/websocket.h b/VNode/_software_lib/nanomq-0.22.10/include/nng/transport/ws/websocket.h new file mode 100644 index 00000000..a5f97d46 --- /dev/null +++ b/VNode/_software_lib/nanomq-0.22.10/include/nng/transport/ws/websocket.h @@ -0,0 +1,35 @@ +// +// Copyright 2021 Staysail Systems, Inc. +// Copyright 2018 Capitar IT Group BV +// +// This software is supplied under the terms of the MIT License, a +// copy of which should be located in the distribution where this +// file was obtained (LICENSE.txt). A copy of the license may also be +// found online at https://opensource.org/licenses/MIT. +// + +#ifndef NNG_TRANSPORT_WS_WEBSOCKET_H +#define NNG_TRANSPORT_WS_WEBSOCKET_H + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +// WebSocket transport. This is used for communication via WebSocket. + +// These aliases are for WSS naming consistency. +#define NNG_OPT_WSS_REQUEST_HEADERS NNG_OPT_WS_REQUEST_HEADERS +#define NNG_OPT_WSS_RESPONSE_HEADERS NNG_OPT_WS_RESPONSE_HEADERS + +#ifndef NNG_ELIDE_DEPRECATED +NNG_DECL int nng_ws_register(void); +NNG_DECL int nng_wss_register(void); +#endif + +#ifdef __cplusplus +} +#endif + +#endif // NNG_TRANSPORT_WS_WEBSOCKET_H diff --git a/VNode/_software_lib/nanomq-0.22.10/include/nng/transport/zerotier/zerotier.h b/VNode/_software_lib/nanomq-0.22.10/include/nng/transport/zerotier/zerotier.h new file mode 100644 index 00000000..b8745dbd --- /dev/null +++ b/VNode/_software_lib/nanomq-0.22.10/include/nng/transport/zerotier/zerotier.h @@ -0,0 +1,161 @@ +// +// Copyright 2019 Staysail Systems, Inc. +// Copyright 2018 Capitar IT Group BV +// +// This software is supplied under the terms of the MIT License, a +// copy of which should be located in the distribution where this +// file was obtained (LICENSE.txt). A copy of the license may also be +// found online at https://opensource.org/licenses/MIT. +// + +#ifndef NNG_TRANSPORT_ZEROTIER_ZEROTIER_H +#define NNG_TRANSPORT_ZEROTIER_ZEROTIER_H + +#include + +// ZeroTier Transport. This sits on the ZeroTier L2 network, which itself +// is implemented on top of UDP. This requires the 3rd party +// libzerotiercore library (which is GPLv3!) and platform specific UDP +// functionality to be built in. Note that care must be taken to link +// dynamically if one wishes to avoid making your entire application GPL3. +// (Alternatively ZeroTier offers commercial licenses which may prevent +// this particular problem.) This implementation does not make use of +// certain advanced capabilities in ZeroTier such as more sophisticated +// route management and TCP fallback. You need to have connectivity +// to the Internet to use this. (Or at least to your Planetary root.) +// +// The ZeroTier URL format we support is zt://.: where +// the component represents the 64-bit hexadecimal ZeroTier +// network ID,the represents the 40-bit hexadecimal ZeroTier +// node (device) ID, and the is a 24-bit (decimal) port number. +// +// A listener may replace the with a wildcard, to just bind to itself, +// in which case the format will be zt://*.: +// +// A listener may also use either 0 or * for the to indicate that +// a random local ephemeral port should be used. +// +// Because ZeroTier takes a while to establish connectivity, it is even +// more important that applications using the ZeroTier transport not +// assume that a connection will be immediately available. It can take +// quite a few seconds for peer-to-peer connectivity to be established. +// +// The ZeroTier transport was funded by Capitar IT Group, BV. +// +// The protocol itself is documented online at: +// http://nanomsg.org/rfcs/sp-zerotier-v0.html +// +// This transport is highly experimental. + +// ZeroTier transport-specific options. + +// NNG_OPT_ZT_HOME is a string containing a directory, where persistent +// state (key files, etc.) will be stored. It should be protected from +// unauthorized viewing and modification. This option must be set on an +// endpoint or socket before the endpoint(s) are started. If the unset, +// or an empty string, then no persistence is used and an ephemeral node +// will be created instead. Note that different endpoints may use different +// values for this option, and that will lead to each endpoint having a +// different ZeroTier identity -- however only one ephemeral node will +// be created for the application. +#define NNG_OPT_ZT_HOME "zt:home" + +// NNG_OPT_ZT_NWID is the 64-bit network ID, represented using a uint64_t in +// native byte order. This is a read-only option; it is derived automatically +// from the URL. +#define NNG_OPT_ZT_NWID "zt:nwid" + +// NNG_OPT_ZT_NODE is the 40-bit node ID, stored in native order in the low +// 40-bits of a uint64_t, of the node. This is a read-only option. +#define NNG_OPT_ZT_NODE "zt:node" + +// NNG_OPT_ZT_NETWORK_STATUS represents the status of the ZeroTier virtual +// network. The option is a read-only value, stored as an integer, which +// takes of the nng_zt_network_status_xxx values listed below. +#define NNG_OPT_ZT_NETWORK_STATUS "zt:network-status" + +// NNG_OPT_ZT_NETWORK_NAME is a human-readable name for the ZeroTier virtual +// network. This will only be set once the ZeroTier network has come up +// as the name comes from the network controller. This is read-only, and +// is presented as an ASCIIZ string. +#define NNG_OPT_ZT_NETWORK_NAME "zt:network-name" + +// NNG_OPT_ZT_PING_TIME and NNG_OPT_ZT_PING_TRIES are used to send ping +// requests when a connection appears to be idled. If a logical session +// has not received traffic from it's peer for ping-time, then a ping packet +// is sent. This will be done up to ping-count times. If no traffic from +// the remote peer is seen after all ping requests are sent, then the peer +// is assumed to be dead or offline, and the session is closed. The +// NNG_OPT_ZT_PING_TIME is a duration (msec, stored as an nng_duration, and +// NNG_OPT_ZT_PING_COUNT is an integer.) This ping process can be disabled +// by setting either ping-time or ping-count to zero. +#define NNG_OPT_ZT_PING_TIME "zt:ping-time" +#define NNG_OPT_ZT_PING_TRIES "zt:ping-tries" + +// NNG_OPT_ZT_CONN_TIME and NNG_OPT_ZT_CONN_TRIES are used to control +// the interval between connection attempts, and the maximum number of +// connection attempts to make before assuming that the peer is absent +// (and returning NNG_ETIMEDOUT). The NNG_OPT_ZT_CONN_TIME is a duration, +// the NNG_OPT_ZT_CONN_TRIES is an integer. +#define NNG_OPT_ZT_CONN_TIME "zt:conn-time" +#define NNG_OPT_ZT_CONN_TRIES "zt:conn-tries" + +// NNG_OPT_ZT_MTU is a read-only size_t and contains the ZeroTier virtual +// network MTU (i.e. the L2 payload MTU). Messages that are larger than this +// (including our 20-byte header data) will be fragmented into multiple +// virtual L2 frames. +#define NNG_OPT_ZT_MTU "zt:mtu" + +// NNG_OPT_ZT_ORBIT is a write-only API to add a "moon" -- this affects the +// endpoint, and all other endpoints using the same node. The value is +// a pair of 64-bit integers -- the first is the moon ID, and the second, if +// non-zero, is the node ID of a server. Conventionally this is the same +// as the moon ID. +#define NNG_OPT_ZT_ORBIT "zt:orbit" + +// NNG_OPT_ZT_DEORBIT removes the moon ID from the node, so that it will +// no longer use that moon. The argument is a moon ID to remove. If the +// node is not already orbiting, then this operation does nothing. +#define NNG_OPT_ZT_DEORBIT "zt:deorbit" + +// NNG_OPT_ZT_ADD_LOCAL_ADDR adds the local address (IP address) as +// local interface address. This facilitates the local startup and +// discovery. Note that this can be called multiple times to add +// additional address. This is optional, and usually not needed. +// The value is an nng_sockaddr corresponding to an IP (or IPv6) address. +#define NNG_OPT_ZT_ADD_LOCAL_ADDR "zt:add-local-addr" + +// NNG_OPT_ZT_CLEAR_LOCAL_ADDRS clears ZeroTier's notion of all +// local addresses. This may be useful when used on a mobile node, +// to reset the notion of what the local addresses are. This +// option takes no argument really. +#define NNG_OPT_ZT_CLEAR_LOCAL_ADDRS "zt:clear-local-addrs" + +#ifdef __cplusplus +extern "C" { +#endif + +// Network status values. +// These values are supplied to help folks checking status. They are the +// return values from zt_opt_status. We avoid hard coding them as defines, +// to keep applications from baking in values that may change if the +// underlying ZeroTier transport changes. +enum nng_zt_status { + NNG_ZT_STATUS_UP, + NNG_ZT_STATUS_CONFIG, + NNG_ZT_STATUS_DENIED, + NNG_ZT_STATUS_NOTFOUND, + NNG_ZT_STATUS_ERROR, + NNG_ZT_STATUS_OBSOLETE, + NNG_ZT_STATUS_UNKNOWN, +}; + +#ifndef NNG_ELIDE_DEPRECATED +NNG_DECL int nng_zt_register(void); +#endif + +#ifdef __cplusplus +} +#endif + +#endif // NNG_TRANSPORT_ZEROTIER_ZEROTIER_H diff --git a/VNode/_software_lib/nanomq-0.22.10/lib/cmake/nng/nng-config-version.cmake b/VNode/_software_lib/nanomq-0.22.10/lib/cmake/nng/nng-config-version.cmake new file mode 100644 index 00000000..592cd1a8 --- /dev/null +++ b/VNode/_software_lib/nanomq-0.22.10/lib/cmake/nng/nng-config-version.cmake @@ -0,0 +1,65 @@ +# This is a basic version file for the Config-mode of find_package(). +# It is used by write_basic_package_version_file() as input file for configure_file() +# to create a version-file which can be installed along a config.cmake file. +# +# The created file sets PACKAGE_VERSION_EXACT if the current version string and +# the requested version string are exactly the same and it sets +# PACKAGE_VERSION_COMPATIBLE if the current version is >= requested version, +# but only if the requested major version is the same as the current one. +# The variable CVF_VERSION must be set before calling configure_file(). + + +set(PACKAGE_VERSION "1.8.0") + +if(PACKAGE_VERSION VERSION_LESS PACKAGE_FIND_VERSION) + set(PACKAGE_VERSION_COMPATIBLE FALSE) +else() + + if("1.8.0" MATCHES "^([0-9]+)\\.") + set(CVF_VERSION_MAJOR "${CMAKE_MATCH_1}") + if(NOT CVF_VERSION_MAJOR VERSION_EQUAL 0) + string(REGEX REPLACE "^0+" "" CVF_VERSION_MAJOR "${CVF_VERSION_MAJOR}") + endif() + else() + set(CVF_VERSION_MAJOR "1.8.0") + endif() + + if(PACKAGE_FIND_VERSION_RANGE) + # both endpoints of the range must have the expected major version + math (EXPR CVF_VERSION_MAJOR_NEXT "${CVF_VERSION_MAJOR} + 1") + if (NOT PACKAGE_FIND_VERSION_MIN_MAJOR STREQUAL CVF_VERSION_MAJOR + OR ((PACKAGE_FIND_VERSION_RANGE_MAX STREQUAL "INCLUDE" AND NOT PACKAGE_FIND_VERSION_MAX_MAJOR STREQUAL CVF_VERSION_MAJOR) + OR (PACKAGE_FIND_VERSION_RANGE_MAX STREQUAL "EXCLUDE" AND NOT PACKAGE_FIND_VERSION_MAX VERSION_LESS_EQUAL CVF_VERSION_MAJOR_NEXT))) + set(PACKAGE_VERSION_COMPATIBLE FALSE) + elseif(PACKAGE_FIND_VERSION_MIN_MAJOR STREQUAL CVF_VERSION_MAJOR + AND ((PACKAGE_FIND_VERSION_RANGE_MAX STREQUAL "INCLUDE" AND PACKAGE_VERSION VERSION_LESS_EQUAL PACKAGE_FIND_VERSION_MAX) + OR (PACKAGE_FIND_VERSION_RANGE_MAX STREQUAL "EXCLUDE" AND PACKAGE_VERSION VERSION_LESS PACKAGE_FIND_VERSION_MAX))) + set(PACKAGE_VERSION_COMPATIBLE TRUE) + else() + set(PACKAGE_VERSION_COMPATIBLE FALSE) + endif() + else() + if(PACKAGE_FIND_VERSION_MAJOR STREQUAL CVF_VERSION_MAJOR) + set(PACKAGE_VERSION_COMPATIBLE TRUE) + else() + set(PACKAGE_VERSION_COMPATIBLE FALSE) + endif() + + if(PACKAGE_FIND_VERSION STREQUAL PACKAGE_VERSION) + set(PACKAGE_VERSION_EXACT TRUE) + endif() + endif() +endif() + + +# if the installed or the using project don't have CMAKE_SIZEOF_VOID_P set, ignore it: +if("${CMAKE_SIZEOF_VOID_P}" STREQUAL "" OR "8" STREQUAL "") + return() +endif() + +# check that the installed version has the same 32/64bit-ness as the one which is currently searching: +if(NOT CMAKE_SIZEOF_VOID_P STREQUAL "8") + math(EXPR installedBits "8 * 8") + set(PACKAGE_VERSION "${PACKAGE_VERSION} (${installedBits}bit)") + set(PACKAGE_VERSION_UNSUITABLE TRUE) +endif() diff --git a/VNode/_software_lib/nanomq-0.22.10/lib/cmake/nng/nng-config.cmake b/VNode/_software_lib/nanomq-0.22.10/lib/cmake/nng/nng-config.cmake new file mode 100644 index 00000000..5de4684e --- /dev/null +++ b/VNode/_software_lib/nanomq-0.22.10/lib/cmake/nng/nng-config.cmake @@ -0,0 +1,50 @@ +# Copyright 2023 Staysail Systems, Inc. +# +# This software is supplied under the terms of the MIT License, a +# copy of which should be located in the distribution where this +# file was obtained (LICENSE.txt). A copy of the license may also be +# found online at https://opensource.org/licenses/MIT. + + + +####### Expanded from @PACKAGE_INIT@ by configure_package_config_file() ####### +####### Any changes to this file will be overwritten by the next CMake run #### +####### The input file was nng-config.cmake.in ######## + +get_filename_component(PACKAGE_PREFIX_DIR "${CMAKE_CURRENT_LIST_DIR}/../../../" ABSOLUTE) + +macro(set_and_check _var _file) + set(${_var} "${_file}") + if(NOT EXISTS "${_file}") + message(FATAL_ERROR "File or directory ${_file} referenced by variable ${_var} does not exist !") + endif() +endmacro() + +macro(check_required_components _NAME) + foreach(comp ${${_NAME}_FIND_COMPONENTS}) + if(NOT ${_NAME}_${comp}_FOUND) + if(${_NAME}_FIND_REQUIRED_${comp}) + set(${_NAME}_FOUND FALSE) + endif() + endif() + endforeach() +endmacro() + +#################################################################################### + +set(NNG_MAJOR_VERSION "1") +set(NNG_MINOR_VERSION "8") +set(NNG_PATCH_VERSION "0") + +set_and_check(NNG_INCLUDE_DIRS "${PACKAGE_PREFIX_DIR}/include/nng") + +include("${CMAKE_CURRENT_LIST_DIR}/nng-targets.cmake") + +# Make sure we find packages for our dependencies +foreach(_PKG IN ITEMS ) + find_package(${_PKG} REQUIRED) +endforeach () + +set(NNG_LIBRARY nng::nng) + +check_required_components(nng) diff --git a/VNode/_software_lib/nanomq-0.22.10/lib/cmake/nng/nng-targets-release.cmake b/VNode/_software_lib/nanomq-0.22.10/lib/cmake/nng/nng-targets-release.cmake new file mode 100644 index 00000000..37386c5f --- /dev/null +++ b/VNode/_software_lib/nanomq-0.22.10/lib/cmake/nng/nng-targets-release.cmake @@ -0,0 +1,19 @@ +#---------------------------------------------------------------- +# Generated CMake target import file for configuration "Release". +#---------------------------------------------------------------- + +# Commands may need to know the format version. +set(CMAKE_IMPORT_FILE_VERSION 1) + +# Import target "nng::nng" for configuration "Release" +set_property(TARGET nng::nng APPEND PROPERTY IMPORTED_CONFIGURATIONS RELEASE) +set_target_properties(nng::nng PROPERTIES + IMPORTED_LINK_INTERFACE_LANGUAGES_RELEASE "C" + IMPORTED_LOCATION_RELEASE "${_IMPORT_PREFIX}/lib/nng.lib" + ) + +list(APPEND _cmake_import_check_targets nng::nng ) +list(APPEND _cmake_import_check_files_for_nng::nng "${_IMPORT_PREFIX}/lib/nng.lib" ) + +# Commands beyond this point should not need to know the version. +set(CMAKE_IMPORT_FILE_VERSION) diff --git a/VNode/_software_lib/nanomq-0.22.10/lib/cmake/nng/nng-targets.cmake b/VNode/_software_lib/nanomq-0.22.10/lib/cmake/nng/nng-targets.cmake new file mode 100644 index 00000000..9fe407f0 --- /dev/null +++ b/VNode/_software_lib/nanomq-0.22.10/lib/cmake/nng/nng-targets.cmake @@ -0,0 +1,108 @@ +# Generated by CMake + +if("${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION}" LESS 2.8) + message(FATAL_ERROR "CMake >= 2.8.0 required") +endif() +if(CMAKE_VERSION VERSION_LESS "2.8.12") + message(FATAL_ERROR "CMake >= 2.8.12 required") +endif() +cmake_policy(PUSH) +cmake_policy(VERSION 2.8.12...3.28) +#---------------------------------------------------------------- +# Generated CMake target import file. +#---------------------------------------------------------------- + +# Commands may need to know the format version. +set(CMAKE_IMPORT_FILE_VERSION 1) + +# Protect against multiple inclusion, which would fail when already imported targets are added once more. +set(_cmake_targets_defined "") +set(_cmake_targets_not_defined "") +set(_cmake_expected_targets "") +foreach(_cmake_expected_target IN ITEMS nng::nng) + list(APPEND _cmake_expected_targets "${_cmake_expected_target}") + if(TARGET "${_cmake_expected_target}") + list(APPEND _cmake_targets_defined "${_cmake_expected_target}") + else() + list(APPEND _cmake_targets_not_defined "${_cmake_expected_target}") + endif() +endforeach() +unset(_cmake_expected_target) +if(_cmake_targets_defined STREQUAL _cmake_expected_targets) + unset(_cmake_targets_defined) + unset(_cmake_targets_not_defined) + unset(_cmake_expected_targets) + unset(CMAKE_IMPORT_FILE_VERSION) + cmake_policy(POP) + return() +endif() +if(NOT _cmake_targets_defined STREQUAL "") + string(REPLACE ";" ", " _cmake_targets_defined_text "${_cmake_targets_defined}") + string(REPLACE ";" ", " _cmake_targets_not_defined_text "${_cmake_targets_not_defined}") + message(FATAL_ERROR "Some (but not all) targets in this export set were already defined.\nTargets Defined: ${_cmake_targets_defined_text}\nTargets not yet defined: ${_cmake_targets_not_defined_text}\n") +endif() +unset(_cmake_targets_defined) +unset(_cmake_targets_not_defined) +unset(_cmake_expected_targets) + + +# Compute the installation prefix relative to this file. +get_filename_component(_IMPORT_PREFIX "${CMAKE_CURRENT_LIST_FILE}" PATH) +get_filename_component(_IMPORT_PREFIX "${_IMPORT_PREFIX}" PATH) +get_filename_component(_IMPORT_PREFIX "${_IMPORT_PREFIX}" PATH) +get_filename_component(_IMPORT_PREFIX "${_IMPORT_PREFIX}" PATH) +if(_IMPORT_PREFIX STREQUAL "/") + set(_IMPORT_PREFIX "") +endif() + +# Create imported target nng::nng +add_library(nng::nng STATIC IMPORTED) + +set_target_properties(nng::nng PROPERTIES + INTERFACE_COMPILE_DEFINITIONS "NNG_STATIC_LIB" + INTERFACE_INCLUDE_DIRECTORIES "${_IMPORT_PREFIX}/include" + INTERFACE_LINK_LIBRARIES "\$;\$;\$" +) + +# Load information for each installed configuration. +file(GLOB _cmake_config_files "${CMAKE_CURRENT_LIST_DIR}/nng-targets-*.cmake") +foreach(_cmake_config_file IN LISTS _cmake_config_files) + include("${_cmake_config_file}") +endforeach() +unset(_cmake_config_file) +unset(_cmake_config_files) + +# Cleanup temporary variables. +set(_IMPORT_PREFIX) + +# Loop over all imported files and verify that they actually exist +foreach(_cmake_target IN LISTS _cmake_import_check_targets) + if(CMAKE_VERSION VERSION_LESS "3.28" + OR NOT DEFINED _cmake_import_check_xcframework_for_${_cmake_target} + OR NOT IS_DIRECTORY "${_cmake_import_check_xcframework_for_${_cmake_target}}") + foreach(_cmake_file IN LISTS "_cmake_import_check_files_for_${_cmake_target}") + if(NOT EXISTS "${_cmake_file}") + message(FATAL_ERROR "The imported target \"${_cmake_target}\" references the file + \"${_cmake_file}\" +but this file does not exist. Possible reasons include: +* The file was deleted, renamed, or moved to another location. +* An install or uninstall procedure did not complete successfully. +* The installation package was faulty and contained + \"${CMAKE_CURRENT_LIST_FILE}\" +but not all the files it references. +") + endif() + endforeach() + endif() + unset(_cmake_file) + unset("_cmake_import_check_files_for_${_cmake_target}") +endforeach() +unset(_cmake_target) +unset(_cmake_import_check_targets) + +# This file does not depend on other imported targets which have +# been exported from the same project but in a separate export set. + +# Commands beyond this point should not need to know the version. +set(CMAKE_IMPORT_FILE_VERSION) +cmake_policy(POP) diff --git a/VNode/_software_lib/nanomq-0.22.10/lib/nng.lib b/VNode/_software_lib/nanomq-0.22.10/lib/nng.lib new file mode 100644 index 00000000..3d894cdd Binary files /dev/null and b/VNode/_software_lib/nanomq-0.22.10/lib/nng.lib differ diff --git a/VNode/_software_lib/nanomq-0.22.10/share/nanomq/cmake/nanomqConfig-release.cmake b/VNode/_software_lib/nanomq-0.22.10/share/nanomq/cmake/nanomqConfig-release.cmake new file mode 100644 index 00000000..65cfa594 --- /dev/null +++ b/VNode/_software_lib/nanomq-0.22.10/share/nanomq/cmake/nanomqConfig-release.cmake @@ -0,0 +1,18 @@ +#---------------------------------------------------------------- +# Generated CMake target import file for configuration "Release". +#---------------------------------------------------------------- + +# Commands may need to know the format version. +set(CMAKE_IMPORT_FILE_VERSION 1) + +# Import target "nanomq" for configuration "Release" +set_property(TARGET nanomq APPEND PROPERTY IMPORTED_CONFIGURATIONS RELEASE) +set_target_properties(nanomq PROPERTIES + IMPORTED_LOCATION_RELEASE "${_IMPORT_PREFIX}/bin/nanomq.exe" + ) + +list(APPEND _cmake_import_check_targets nanomq ) +list(APPEND _cmake_import_check_files_for_nanomq "${_IMPORT_PREFIX}/bin/nanomq.exe" ) + +# Commands beyond this point should not need to know the version. +set(CMAKE_IMPORT_FILE_VERSION) diff --git a/VNode/_software_lib/nanomq-0.22.10/share/nanomq/cmake/nanomqConfig.cmake b/VNode/_software_lib/nanomq-0.22.10/share/nanomq/cmake/nanomqConfig.cmake new file mode 100644 index 00000000..c5e322ec --- /dev/null +++ b/VNode/_software_lib/nanomq-0.22.10/share/nanomq/cmake/nanomqConfig.cmake @@ -0,0 +1,102 @@ +# Generated by CMake + +if("${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION}" LESS 2.8) + message(FATAL_ERROR "CMake >= 2.8.0 required") +endif() +if(CMAKE_VERSION VERSION_LESS "2.8.3") + message(FATAL_ERROR "CMake >= 2.8.3 required") +endif() +cmake_policy(PUSH) +cmake_policy(VERSION 2.8.3...3.28) +#---------------------------------------------------------------- +# Generated CMake target import file. +#---------------------------------------------------------------- + +# Commands may need to know the format version. +set(CMAKE_IMPORT_FILE_VERSION 1) + +# Protect against multiple inclusion, which would fail when already imported targets are added once more. +set(_cmake_targets_defined "") +set(_cmake_targets_not_defined "") +set(_cmake_expected_targets "") +foreach(_cmake_expected_target IN ITEMS nanomq) + list(APPEND _cmake_expected_targets "${_cmake_expected_target}") + if(TARGET "${_cmake_expected_target}") + list(APPEND _cmake_targets_defined "${_cmake_expected_target}") + else() + list(APPEND _cmake_targets_not_defined "${_cmake_expected_target}") + endif() +endforeach() +unset(_cmake_expected_target) +if(_cmake_targets_defined STREQUAL _cmake_expected_targets) + unset(_cmake_targets_defined) + unset(_cmake_targets_not_defined) + unset(_cmake_expected_targets) + unset(CMAKE_IMPORT_FILE_VERSION) + cmake_policy(POP) + return() +endif() +if(NOT _cmake_targets_defined STREQUAL "") + string(REPLACE ";" ", " _cmake_targets_defined_text "${_cmake_targets_defined}") + string(REPLACE ";" ", " _cmake_targets_not_defined_text "${_cmake_targets_not_defined}") + message(FATAL_ERROR "Some (but not all) targets in this export set were already defined.\nTargets Defined: ${_cmake_targets_defined_text}\nTargets not yet defined: ${_cmake_targets_not_defined_text}\n") +endif() +unset(_cmake_targets_defined) +unset(_cmake_targets_not_defined) +unset(_cmake_expected_targets) + + +# Compute the installation prefix relative to this file. +get_filename_component(_IMPORT_PREFIX "${CMAKE_CURRENT_LIST_FILE}" PATH) +get_filename_component(_IMPORT_PREFIX "${_IMPORT_PREFIX}" PATH) +get_filename_component(_IMPORT_PREFIX "${_IMPORT_PREFIX}" PATH) +get_filename_component(_IMPORT_PREFIX "${_IMPORT_PREFIX}" PATH) +if(_IMPORT_PREFIX STREQUAL "/") + set(_IMPORT_PREFIX "") +endif() + +# Create imported target nanomq +add_executable(nanomq IMPORTED) + +# Load information for each installed configuration. +file(GLOB _cmake_config_files "${CMAKE_CURRENT_LIST_DIR}/nanomqConfig-*.cmake") +foreach(_cmake_config_file IN LISTS _cmake_config_files) + include("${_cmake_config_file}") +endforeach() +unset(_cmake_config_file) +unset(_cmake_config_files) + +# Cleanup temporary variables. +set(_IMPORT_PREFIX) + +# Loop over all imported files and verify that they actually exist +foreach(_cmake_target IN LISTS _cmake_import_check_targets) + if(CMAKE_VERSION VERSION_LESS "3.28" + OR NOT DEFINED _cmake_import_check_xcframework_for_${_cmake_target} + OR NOT IS_DIRECTORY "${_cmake_import_check_xcframework_for_${_cmake_target}}") + foreach(_cmake_file IN LISTS "_cmake_import_check_files_for_${_cmake_target}") + if(NOT EXISTS "${_cmake_file}") + message(FATAL_ERROR "The imported target \"${_cmake_target}\" references the file + \"${_cmake_file}\" +but this file does not exist. Possible reasons include: +* The file was deleted, renamed, or moved to another location. +* An install or uninstall procedure did not complete successfully. +* The installation package was faulty and contained + \"${CMAKE_CURRENT_LIST_FILE}\" +but not all the files it references. +") + endif() + endforeach() + endif() + unset(_cmake_file) + unset("_cmake_import_check_files_for_${_cmake_target}") +endforeach() +unset(_cmake_target) +unset(_cmake_import_check_targets) + +# This file does not depend on other imported targets which have +# been exported from the same project but in a separate export set. + +# Commands beyond this point should not need to know the version. +set(CMAKE_IMPORT_FILE_VERSION) +cmake_policy(POP) diff --git a/VNode/_software_lib/nanomq-0.22.10/start.ps1 b/VNode/_software_lib/nanomq-0.22.10/start.ps1 new file mode 100644 index 00000000..51210b0a --- /dev/null +++ b/VNode/_software_lib/nanomq-0.22.10/start.ps1 @@ -0,0 +1,79 @@ +<# +___________________________________________ +| J26/03/2025 - Jérémy CHOMAZ - 1.0 +| Création du script +| +___________________________________________ +| +Ce script à pour but d'ouvrir le broker MQTT avec la bonne congiguration + +#> +# Fonction pour extraire les valeurs des sections +Function Get-ConfigSection { + param ( + [string]$sectionName, + [string]$configContent + ) + + $sectionPattern = "$sectionName\s*{\s*([^}]*)\s*}" + if ($configContent -match $sectionPattern) { + $sectionContent = $matches[1] + $sectionProperties = @{} + foreach ($line in $sectionContent -split "`n") { + if ($line -match "(\w+)\s*=\s*(.*)") { + $propertyName = $matches[1] + $propertyValue = $matches[2] + $sectionProperties[$propertyName] = $propertyValue + } + } + return $sectionProperties + } else { + return @{} + } +} + +Write-Output "Démarrage du service NanoMQ" + +Start-Process -FilePath "$($PSscriptRoot)\bin\nanomq.exe" -ArgumentList "start --conf $($PSscriptRoot)\bin\nanomq.conf" -NoNewWindow + +Start-Sleep -Seconds 1 + +If (Get-Process -Name "Nanomq"){ + Write-Output "Broker MQTT lancé avec succès." + $configContent = Get-Content -Path "$($PSscriptRoot)\bin\nanomq.conf" -Raw + Write-Output "Voici le fichier de configuration utilisé ($($PSscriptRoot)\bin\nanomq.conf) :" + # Fonction pour extraire les valeurs des sections + + # Extraire les sections du fichier de configuration + $mqttSection = Get-ConfigSection -sectionName "mqtt" -configContent $configContent + $listenersTcpSection = Get-ConfigSection -sectionName "listeners.tcp" -configContent $configContent + $listenersWsSection = Get-ConfigSection -sectionName "listeners.ws" -configContent $configContent + $httpServerSection = Get-ConfigSection -sectionName "http_server" -configContent $configContent + $logSection = Get-ConfigSection -sectionName "log" -configContent $configContent + $authSection = Get-ConfigSection -sectionName "auth" -configContent $configContent + + # Fonction pour afficher les propriétés d'une section + function Show-SectionProperties { + param ( + [hashtable]$section, + [string]$sectionName + ) + + Write-Output "Propriétés de la section $sectionName :" + foreach ($property in $section.GetEnumerator()) { + Write-Output "Name : $($property.Name)" + Write-Output "Value : $($property.Value)" + Write-Output "------" + } + } + + # Afficher les propriétés des sections extraites + Show-SectionProperties -section $mqttSection -sectionName "mqtt" + Show-SectionProperties -section $listenersTcpSection -sectionName "listeners.tcp" + Show-SectionProperties -section $listenersWsSection -sectionName "listeners.ws" + Show-SectionProperties -section $httpServerSection -sectionName "http_server" + Show-SectionProperties -section $logSection -sectionName "log" + Show-SectionProperties -section $authSection -sectionName "auth" +} Else { + Write-Output "Le lancement du service a échoué, veuillez réessayer." +} \ No newline at end of file diff --git a/VNode/package-lock.json b/VNode/package-lock.json new file mode 100644 index 00000000..6d415831 --- /dev/null +++ b/VNode/package-lock.json @@ -0,0 +1,463 @@ +{ + "name": "Vulture", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "dependencies": { + "mqtt": "^5.10.1", + "ping": "^0.4.4", + "ws": "^8.18.0" + } + }, + "node_modules/@babel/runtime": { + "version": "7.26.0", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.26.0.tgz", + "integrity": "sha512-FDSOghenHTiToteC/QRlv2q3DhPZ/oOXTBoirfWNx1Cx3TMVcGWQtMMmQcSvb/JjpNeGzx8Pq/b4fKEJuWm1sw==", + "dependencies": { + "regenerator-runtime": "^0.14.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@types/node": { + "version": "22.9.0", + "resolved": "https://registry.npmjs.org/@types/node/-/node-22.9.0.tgz", + "integrity": "sha512-vuyHg81vvWA1Z1ELfvLko2c8f34gyA0zaic0+Rllc5lbCnbSyuvb2Oxpm6TAUAC/2xZN3QGqxBNggD1nNR2AfQ==", + "dependencies": { + "undici-types": "~6.19.8" + } + }, + "node_modules/@types/readable-stream": { + "version": "4.0.18", + "resolved": "https://registry.npmjs.org/@types/readable-stream/-/readable-stream-4.0.18.tgz", + "integrity": "sha512-21jK/1j+Wg+7jVw1xnSwy/2Q1VgVjWuFssbYGTREPUBeZ+rqVFl2udq0IkxzPC0ZhOzVceUbyIACFZKLqKEBlA==", + "dependencies": { + "@types/node": "*", + "safe-buffer": "~5.1.1" + } + }, + "node_modules/@types/ws": { + "version": "8.5.13", + "resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.5.13.tgz", + "integrity": "sha512-osM/gWBTPKgHV8XkTunnegTRIsvF6owmf5w+JtAfOw472dptdm0dlGv4xCt6GwQRcC2XVOvvRE/0bAoQcL2QkA==", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/abort-controller": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/abort-controller/-/abort-controller-3.0.0.tgz", + "integrity": "sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==", + "dependencies": { + "event-target-shim": "^5.0.0" + }, + "engines": { + "node": ">=6.5" + } + }, + "node_modules/base64-js": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", + "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/bl": { + "version": "6.0.16", + "resolved": "https://registry.npmjs.org/bl/-/bl-6.0.16.tgz", + "integrity": "sha512-V/kz+z2Mx5/6qDfRCilmrukUXcXuCoXKg3/3hDvzKKoSUx8CJKudfIoT29XZc3UE9xBvxs5qictiHdprwtteEg==", + "dependencies": { + "@types/readable-stream": "^4.0.0", + "buffer": "^6.0.3", + "inherits": "^2.0.4", + "readable-stream": "^4.2.0" + } + }, + "node_modules/buffer": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz", + "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "dependencies": { + "base64-js": "^1.3.1", + "ieee754": "^1.2.1" + } + }, + "node_modules/buffer-from": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", + "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==" + }, + "node_modules/commist": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/commist/-/commist-3.2.0.tgz", + "integrity": "sha512-4PIMoPniho+LqXmpS5d3NuGYncG6XWlkBSVGiWycL22dd42OYdUGil2CWuzklaJoNxyxUSpO4MKIBU94viWNAw==" + }, + "node_modules/concat-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-2.0.0.tgz", + "integrity": "sha512-MWufYdFw53ccGjCA+Ol7XJYpAlW6/prSMzuPOTRnJGcGzuhLn4Scrz7qf6o8bROZ514ltazcIFJZevcfbo0x7A==", + "engines": [ + "node >= 6.0" + ], + "dependencies": { + "buffer-from": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^3.0.2", + "typedarray": "^0.0.6" + } + }, + "node_modules/concat-stream/node_modules/readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/debug": { + "version": "4.3.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz", + "integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/event-target-shim": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/event-target-shim/-/event-target-shim-5.0.1.tgz", + "integrity": "sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==", + "engines": { + "node": ">=6" + } + }, + "node_modules/events": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz", + "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==", + "engines": { + "node": ">=0.8.x" + } + }, + "node_modules/fast-unique-numbers": { + "version": "8.0.13", + "resolved": "https://registry.npmjs.org/fast-unique-numbers/-/fast-unique-numbers-8.0.13.tgz", + "integrity": "sha512-7OnTFAVPefgw2eBJ1xj2PGGR9FwYzSUso9decayHgCDX4sJkHLdcsYTytTg+tYv+wKF3U8gJuSBz2jJpQV4u/g==", + "dependencies": { + "@babel/runtime": "^7.23.8", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.1.0" + } + }, + "node_modules/help-me": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/help-me/-/help-me-5.0.0.tgz", + "integrity": "sha512-7xgomUX6ADmcYzFik0HzAxh/73YlKR9bmFzf51CZwR+b6YtzU2m0u49hQCqV6SvlqIqsaxovfwdvbnsw3b/zpg==" + }, + "node_modules/ieee754": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", + "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" + }, + "node_modules/js-sdsl": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/js-sdsl/-/js-sdsl-4.3.0.tgz", + "integrity": "sha512-mifzlm2+5nZ+lEcLJMoBK0/IH/bDg8XnJfd/Wq6IP+xoCjLZsTOnV2QpxlVbX9bMnkl5PdEjNtBJ9Cj1NjifhQ==", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/js-sdsl" + } + }, + "node_modules/lru-cache": { + "version": "10.4.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz", + "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==" + }, + "node_modules/minimist": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", + "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/mqtt": { + "version": "5.10.1", + "resolved": "https://registry.npmjs.org/mqtt/-/mqtt-5.10.1.tgz", + "integrity": "sha512-hXCOki8sANoQ7w+2OzJzg6qMBxTtrH9RlnVNV8panLZgnl+Gh0J/t4k6r8Az8+C7y3KAcyXtn0mmLixyUom8Sw==", + "dependencies": { + "@types/readable-stream": "^4.0.5", + "@types/ws": "^8.5.9", + "commist": "^3.2.0", + "concat-stream": "^2.0.0", + "debug": "^4.3.4", + "help-me": "^5.0.0", + "lru-cache": "^10.0.1", + "minimist": "^1.2.8", + "mqtt-packet": "^9.0.0", + "number-allocator": "^1.0.14", + "readable-stream": "^4.4.2", + "reinterval": "^1.1.0", + "rfdc": "^1.3.0", + "split2": "^4.2.0", + "worker-timers": "^7.1.4", + "ws": "^8.17.1" + }, + "bin": { + "mqtt": "build/bin/mqtt.js", + "mqtt_pub": "build/bin/pub.js", + "mqtt_sub": "build/bin/sub.js" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/mqtt-packet": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/mqtt-packet/-/mqtt-packet-9.0.0.tgz", + "integrity": "sha512-8v+HkX+fwbodsWAZIZTI074XIoxVBOmPeggQuDFCGg1SqNcC+uoRMWu7J6QlJPqIUIJXmjNYYHxBBLr1Y/Df4w==", + "dependencies": { + "bl": "^6.0.8", + "debug": "^4.3.4", + "process-nextick-args": "^2.0.1" + } + }, + "node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" + }, + "node_modules/number-allocator": { + "version": "1.0.14", + "resolved": "https://registry.npmjs.org/number-allocator/-/number-allocator-1.0.14.tgz", + "integrity": "sha512-OrL44UTVAvkKdOdRQZIJpLkAdjXGTRda052sN4sO77bKEzYYqWKMBjQvrJFzqygI99gL6Z4u2xctPW1tB8ErvA==", + "dependencies": { + "debug": "^4.3.1", + "js-sdsl": "4.3.0" + } + }, + "node_modules/ping": { + "version": "0.4.4", + "resolved": "https://registry.npmjs.org/ping/-/ping-0.4.4.tgz", + "integrity": "sha512-56ZMC0j7SCsMMLdOoUg12VZCfj/+ZO+yfOSjaNCRrmZZr6GLbN2X/Ui56T15dI8NhiHckaw5X2pvyfAomanwqQ==", + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/process": { + "version": "0.11.10", + "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz", + "integrity": "sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A==", + "engines": { + "node": ">= 0.6.0" + } + }, + "node_modules/process-nextick-args": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==" + }, + "node_modules/readable-stream": { + "version": "4.5.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-4.5.2.tgz", + "integrity": "sha512-yjavECdqeZ3GLXNgRXgeQEdz9fvDDkNKyHnbHRFtOr7/LcfgBcmct7t/ET+HaCTqfh06OzoAxrkN/IfjJBVe+g==", + "dependencies": { + "abort-controller": "^3.0.0", + "buffer": "^6.0.3", + "events": "^3.3.0", + "process": "^0.11.10", + "string_decoder": "^1.3.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + } + }, + "node_modules/regenerator-runtime": { + "version": "0.14.1", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.14.1.tgz", + "integrity": "sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==" + }, + "node_modules/reinterval": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/reinterval/-/reinterval-1.1.0.tgz", + "integrity": "sha512-QIRet3SYrGp0HUHO88jVskiG6seqUGC5iAG7AwI/BV4ypGcuqk9Du6YQBUOUqm9c8pw1eyLoIaONifRua1lsEQ==" + }, + "node_modules/rfdc": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.4.1.tgz", + "integrity": "sha512-q1b3N5QkRUWUl7iyylaaj3kOpIT0N2i9MqIEQXP73GVsN9cw3fdx8X63cEmWhJGi2PPCF23Ijp7ktmd39rawIA==" + }, + "node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + }, + "node_modules/split2": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/split2/-/split2-4.2.0.tgz", + "integrity": "sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg==", + "engines": { + "node": ">= 10.x" + } + }, + "node_modules/string_decoder": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", + "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", + "dependencies": { + "safe-buffer": "~5.2.0" + } + }, + "node_modules/string_decoder/node_modules/safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/tslib": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==" + }, + "node_modules/typedarray": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", + "integrity": "sha512-/aCDEGatGvZ2BIk+HmLf4ifCJFwvKFNb9/JeZPMulfgFracn9QFcAf5GO8B/mweUjSoblS5In0cWhqpfs/5PQA==" + }, + "node_modules/undici-types": { + "version": "6.19.8", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.19.8.tgz", + "integrity": "sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw==" + }, + "node_modules/util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==" + }, + "node_modules/worker-timers": { + "version": "7.1.8", + "resolved": "https://registry.npmjs.org/worker-timers/-/worker-timers-7.1.8.tgz", + "integrity": "sha512-R54psRKYVLuzff7c1OTFcq/4Hue5Vlz4bFtNEIarpSiCYhpifHU3aIQI29S84o1j87ePCYqbmEJPqwBTf+3sfw==", + "dependencies": { + "@babel/runtime": "^7.24.5", + "tslib": "^2.6.2", + "worker-timers-broker": "^6.1.8", + "worker-timers-worker": "^7.0.71" + } + }, + "node_modules/worker-timers-broker": { + "version": "6.1.8", + "resolved": "https://registry.npmjs.org/worker-timers-broker/-/worker-timers-broker-6.1.8.tgz", + "integrity": "sha512-FUCJu9jlK3A8WqLTKXM9E6kAmI/dR1vAJ8dHYLMisLNB/n3GuaFIjJ7pn16ZcD1zCOf7P6H62lWIEBi+yz/zQQ==", + "dependencies": { + "@babel/runtime": "^7.24.5", + "fast-unique-numbers": "^8.0.13", + "tslib": "^2.6.2", + "worker-timers-worker": "^7.0.71" + } + }, + "node_modules/worker-timers-worker": { + "version": "7.0.71", + "resolved": "https://registry.npmjs.org/worker-timers-worker/-/worker-timers-worker-7.0.71.tgz", + "integrity": "sha512-ks/5YKwZsto1c2vmljroppOKCivB/ma97g9y77MAAz2TBBjPPgpoOiS1qYQKIgvGTr2QYPT3XhJWIB6Rj2MVPQ==", + "dependencies": { + "@babel/runtime": "^7.24.5", + "tslib": "^2.6.2" + } + }, + "node_modules/ws": { + "version": "8.18.0", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.18.0.tgz", + "integrity": "sha512-8VbfWfHLbbwu3+N6OKsOMpBdT4kXPDDB9cJk2bJ6mh9ucxdlnNvH1e+roYkKmN9Nxw2yjz7VzeO9oOz2zJ04Pw==", + "engines": { + "node": ">=10.0.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": ">=5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + } + } +} diff --git a/VNode/package.json b/VNode/package.json new file mode 100644 index 00000000..55516781 --- /dev/null +++ b/VNode/package.json @@ -0,0 +1,7 @@ +{ + "dependencies": { + "mqtt": "^5.10.1", + "ping": "^0.4.4", + "ws": "^8.18.0" + } +} diff --git a/VNode/quizz/Quizz-1/festival/MysteryLand.jpg b/VNode/quizz/Quizz-1/festival/MysteryLand.jpg new file mode 100644 index 00000000..3a2a907f Binary files /dev/null and b/VNode/quizz/Quizz-1/festival/MysteryLand.jpg differ diff --git a/VNode/quizz/Quizz-1/geography-history/Q-1.jpeg b/VNode/quizz/Quizz-1/geography-history/Q-1.jpeg new file mode 100644 index 00000000..cc7560bb Binary files /dev/null and b/VNode/quizz/Quizz-1/geography-history/Q-1.jpeg differ diff --git a/VNode/quizz/Quizz-1/geography-history/Q-2.jpeg b/VNode/quizz/Quizz-1/geography-history/Q-2.jpeg new file mode 100644 index 00000000..2c3e6683 Binary files /dev/null and b/VNode/quizz/Quizz-1/geography-history/Q-2.jpeg differ diff --git a/VNode/quizz/Quizz-1/geography-history/Q-3.jpeg b/VNode/quizz/Quizz-1/geography-history/Q-3.jpeg new file mode 100644 index 00000000..d8dc3407 Binary files /dev/null and b/VNode/quizz/Quizz-1/geography-history/Q-3.jpeg differ diff --git a/VNode/quizz/Quizz-1/geography-history/Q-4.jpeg b/VNode/quizz/Quizz-1/geography-history/Q-4.jpeg new file mode 100644 index 00000000..e1d1e216 Binary files /dev/null and b/VNode/quizz/Quizz-1/geography-history/Q-4.jpeg differ diff --git a/VNode/quizz/Quizz-1/geography-history/Q-5.jpeg b/VNode/quizz/Quizz-1/geography-history/Q-5.jpeg new file mode 100644 index 00000000..8036c7ef Binary files /dev/null and b/VNode/quizz/Quizz-1/geography-history/Q-5.jpeg differ diff --git a/VNode/quizz/Quizz-1/geography-history/config.yml b/VNode/quizz/Quizz-1/geography-history/config.yml new file mode 100644 index 00000000..0323c066 --- /dev/null +++ b/VNode/quizz/Quizz-1/geography-history/config.yml @@ -0,0 +1,27 @@ +name: "Histoire & Géographie" +questions: + 1: + Q: "Quelle bataille célèbre s'est déroulée en 1815, marquant la défaite de Napoléon Bonaparte ?" + T: "Elle a eu lieu en Belgique" + R: "La bataille de Waterloo." + P: "Q-1.jpeg" + 2: + Q: "Quelle est la capitale de l'Australie ?" + T: "Le nom de cette ville commence par la lettre 'C'" + R: "Canberra." + P: "Q-2.jpeg" + 3: + Q: "En quelle année la Seconde Guerre mondiale a-t-elle pris fin ?" + T: "C'est au milieu des années 40." + R: "En 1945." + P: "Q-3.jpeg" + 4: + Q: "Quel fleuve traverse la ville du Caire en Égypte ?" + T: "C'est l'un des plus longs fleuves du monde" + R: "Le Nil." + P: "Q-4.jpeg" + 5: + Q: "Quel pays a été divisé par un mur de 1961 à 1989 ?" + T: "Sa chute a marqué la fin de la guerre froide." + R: "L'Allemagne (le mur de Berlin)." + P: "Q-5.jpeg" diff --git a/VNode/quizz/Quizz-1/geography-history/originales/Q-1.webp b/VNode/quizz/Quizz-1/geography-history/originales/Q-1.webp new file mode 100644 index 00000000..13731496 Binary files /dev/null and b/VNode/quizz/Quizz-1/geography-history/originales/Q-1.webp differ diff --git a/VNode/quizz/Quizz-1/geography-history/originales/Q-2.webp b/VNode/quizz/Quizz-1/geography-history/originales/Q-2.webp new file mode 100644 index 00000000..cc14b62e Binary files /dev/null and b/VNode/quizz/Quizz-1/geography-history/originales/Q-2.webp differ diff --git a/VNode/quizz/Quizz-1/geography-history/originales/Q-3.webp b/VNode/quizz/Quizz-1/geography-history/originales/Q-3.webp new file mode 100644 index 00000000..1579431c Binary files /dev/null and b/VNode/quizz/Quizz-1/geography-history/originales/Q-3.webp differ diff --git a/VNode/quizz/Quizz-1/geography-history/originales/Q-4.webp b/VNode/quizz/Quizz-1/geography-history/originales/Q-4.webp new file mode 100644 index 00000000..f6c29ec7 Binary files /dev/null and b/VNode/quizz/Quizz-1/geography-history/originales/Q-4.webp differ diff --git a/VNode/quizz/Quizz-1/geography-history/originales/Q-5.webp b/VNode/quizz/Quizz-1/geography-history/originales/Q-5.webp new file mode 100644 index 00000000..eaa6ad79 Binary files /dev/null and b/VNode/quizz/Quizz-1/geography-history/originales/Q-5.webp differ diff --git a/VNode/quizz/Quizz-1/video-games/Original/Q-1.jpg b/VNode/quizz/Quizz-1/video-games/Original/Q-1.jpg new file mode 100644 index 00000000..721ac20d Binary files /dev/null and b/VNode/quizz/Quizz-1/video-games/Original/Q-1.jpg differ diff --git a/VNode/quizz/Quizz-1/video-games/Original/Q-2.jpg b/VNode/quizz/Quizz-1/video-games/Original/Q-2.jpg new file mode 100644 index 00000000..52c5bddd Binary files /dev/null and b/VNode/quizz/Quizz-1/video-games/Original/Q-2.jpg differ diff --git a/VNode/quizz/Quizz-1/video-games/Original/Q-3.webp b/VNode/quizz/Quizz-1/video-games/Original/Q-3.webp new file mode 100644 index 00000000..430f83e4 Binary files /dev/null and b/VNode/quizz/Quizz-1/video-games/Original/Q-3.webp differ diff --git a/VNode/quizz/Quizz-1/video-games/Original/Q-4.webp b/VNode/quizz/Quizz-1/video-games/Original/Q-4.webp new file mode 100644 index 00000000..0543b2a7 Binary files /dev/null and b/VNode/quizz/Quizz-1/video-games/Original/Q-4.webp differ diff --git a/VNode/quizz/Quizz-1/video-games/Original/Q-5.webp b/VNode/quizz/Quizz-1/video-games/Original/Q-5.webp new file mode 100644 index 00000000..f8396fbb Binary files /dev/null and b/VNode/quizz/Quizz-1/video-games/Original/Q-5.webp differ diff --git a/VNode/quizz/Quizz-1/video-games/Q-1.jpeg b/VNode/quizz/Quizz-1/video-games/Q-1.jpeg new file mode 100644 index 00000000..8b9e7f16 Binary files /dev/null and b/VNode/quizz/Quizz-1/video-games/Q-1.jpeg differ diff --git a/VNode/quizz/Quizz-1/video-games/Q-2.jpeg b/VNode/quizz/Quizz-1/video-games/Q-2.jpeg new file mode 100644 index 00000000..52aab10b Binary files /dev/null and b/VNode/quizz/Quizz-1/video-games/Q-2.jpeg differ diff --git a/VNode/quizz/Quizz-1/video-games/Q-3.jpeg b/VNode/quizz/Quizz-1/video-games/Q-3.jpeg new file mode 100644 index 00000000..67a2a1cc Binary files /dev/null and b/VNode/quizz/Quizz-1/video-games/Q-3.jpeg differ diff --git a/VNode/quizz/Quizz-1/video-games/Q-4.jpeg b/VNode/quizz/Quizz-1/video-games/Q-4.jpeg new file mode 100644 index 00000000..1c4f1642 Binary files /dev/null and b/VNode/quizz/Quizz-1/video-games/Q-4.jpeg differ diff --git a/VNode/quizz/Quizz-1/video-games/Q-5.jpeg b/VNode/quizz/Quizz-1/video-games/Q-5.jpeg new file mode 100644 index 00000000..cd5599a8 Binary files /dev/null and b/VNode/quizz/Quizz-1/video-games/Q-5.jpeg differ diff --git a/VNode/quizz/Quizz-1/video-games/config.yml b/VNode/quizz/Quizz-1/video-games/config.yml new file mode 100644 index 00000000..8e42117d --- /dev/null +++ b/VNode/quizz/Quizz-1/video-games/config.yml @@ -0,0 +1,27 @@ +name: "Jeux vidéos" +questions: + 1: + Q: "Quel personnage de jeu vidéo est un plombier moustachu qui saute sur des ennemis pour sauver une princesse ?" + T: "C’est le personnage le plus célèbre de Nintendo, son nom commence par 'M'." + R: "Mario." + P: "Q-1.jpeg" + 2: + Q: "Quel jeu vidéo multijoueur de football avec des voitures est très populaire ?" + T: "Il s'agit d'un mélange de sport et de voitures rapides." + R: "Rocket League." + P: "Q-2.jpeg" + 3: + Q: "Quel jeu vidéo mobile consiste à faire exploser des bonbons en alignant trois pièces identiques ?" + T: "Son nom fait référence aux bonbons." + R: "Candy Crush Saga." + P: "Q-3.jpeg" + 4: + Q: "Quel est le nom du célèbre personnage bleu de SEGA qui court à une vitesse incroyable ?" + T: "Son nom commence par la lettre 'S' et c'est un hérisson." + R: "Sonic" + P: "Q-4.jpeg" + 5: + Q: "Quel jeu permet de construire et explorer un monde fait de blocs, tout en survivant face à des monstres ?" + T: "Le monde est entièrement fait de blocs carrés." + R: "Minecraft." + P: "Q-5.jpeg" diff --git a/VNode/services/buzzer/_a retravailler_test-buzzer-manager.js b/VNode/services/buzzer/_a retravailler_test-buzzer-manager.js new file mode 100644 index 00000000..9caa88e4 --- /dev/null +++ b/VNode/services/buzzer/_a retravailler_test-buzzer-manager.js @@ -0,0 +1,161 @@ +// Import necessary modules +const mqtt = require('mqtt'); + +// MQTT broker configuration +const brokerUrl = 'mqtt://localhost'; // Broker URL (change if needed) +const options = { + clientId: 'test_buzzer_manager', + clean: true +}; + +// Set up MQTT client +const client = mqtt.connect(brokerUrl, options); + +// Variables for tracking test results +let testResults = { + buzzerActivity: false, + confirmationReceived: false, + statusBlocked: false, + statusUnblocked: false, + tiltAddConfirmed: false, + tiltRemoveConfirmed: false, + tiltIgnored: false, + unlockConfirmation: false, + tiltUpdateAdd: false, + tiltUpdateRemove: false +}; + +// Subscribe to topics to capture the responses from the buzzer manager +client.on('connect', () => { + console.log('[INFO] Connected to MQTT broker for testing'); + + // Subscribe to all topics related to the buzzer manager + client.subscribe('vulture/buzzer/#', (err) => { + if (err) console.error('[ERROR] Failed to subscribe to topics for testing'); + else console.log('[INFO] Subscribed to topics successfully'); + }); + + // Run the test sequence after a short delay + setTimeout(runTestSequence, 500); +}); + +// Capture and process incoming MQTT messages +client.on('message', (topic, message) => { + const payload = JSON.parse(message.toString()); + console.log(`[INFO] Message received on ${topic}: ${message.toString()}`); + + // Track the test results based on the topics and payloads + if (topic.startsWith('vulture/buzzer/activity') && payload.buzzer_id === 1) { + testResults.buzzerActivity = true; + } + + if (topic.startsWith(`vulture/buzzer/confirmation/1`) && payload.status === "received") { + testResults.confirmationReceived = true; + } + + if (topic === 'vulture/buzzer/status' && payload.status === "blocked") { + testResults.statusBlocked = true; + } + + if (topic === 'vulture/buzzer/status' && payload.status === "unblocked") { + testResults.statusUnblocked = true; + } + + if (topic.startsWith(`vulture/buzzer/tilt/confirmation/2`) && payload.status === "received" && payload.action === "add") { + testResults.tiltAddConfirmed = true; + } + + if (topic.startsWith(`vulture/buzzer/tilt/confirmation/2`) && payload.status === "received" && payload.action === "remove") { + testResults.tiltRemoveConfirmed = true; + } + + if (topic === `vulture/buzzer/tilt/ignored/2` && payload.status === "tilt_ignored") { + testResults.tiltIgnored = true; + } + + if (topic === 'vulture/buzzer/status' && payload.status === "tilt_update") { + // Check for tilt update with added buzzer + if (payload.tilt_buzzers.includes(2) && payload.message.includes("added")) { + testResults.tiltUpdateAdd = true; + } + + // Check for tilt update with removed buzzer + if (!payload.tilt_buzzers.includes(2) && payload.message.includes("removed")) { + testResults.tiltUpdateRemove = true; + } + } + + if (topic === 'vulture/buzzer/unlock/confirmation' && payload.status === "received") { + testResults.unlockConfirmation = true; + } +}); + +// Function to run the complete test sequence +function runTestSequence() { + console.log('[INFO] Starting test sequence...'); + + // 1. Simulate a buzzer press (buzzer 1, color red) + console.log('[TEST] Simulating buzzer press (ID 1, color #FF0000)...'); + client.publish('vulture/buzzer/pressed/1', JSON.stringify({ + buzzer_id: 1, + color: "#FF0000" + })); + + // 2. Simulate a second buzzer press (buzzer 2, color blue) to check blocking + setTimeout(() => { + console.log('[TEST] Simulating second buzzer press (ID 2, color #0000FF)...'); + client.publish('vulture/buzzer/pressed/2', JSON.stringify({ + buzzer_id: 2, + color: "#0000FF" + })); + }, 1000); + + // 3. Simulate adding a buzzer to tilt mode (buzzer 2) + setTimeout(() => { + console.log('[TEST] Adding buzzer ID 2 to tilt mode...'); + client.publish('vulture/buzzer/tilt', JSON.stringify({ + buzzer_id: 2, + status: "add" + })); + }, 1500); + + // 4. Simulate pressing a buzzer in tilt mode (should be ignored) + setTimeout(() => { + console.log('[TEST] Simulating tilt buzzer press (ID 2, color #0000FF)...'); + client.publish('vulture/buzzer/pressed/2', JSON.stringify({ + buzzer_id: 2, + color: "#0000FF" + })); + }, 2000); + + // 5. Remove tilt mode from buzzer 2 + setTimeout(() => { + console.log('[TEST] Removing tilt mode for buzzer ID 2...'); + client.publish('vulture/buzzer/tilt', JSON.stringify({ + buzzer_id: 2, + status: "remove" + })); + }, 2500); + + // 6. Unlock buzzers to reset state + setTimeout(() => { + console.log('[TEST] Unlocking buzzers...'); + client.publish('vulture/buzzer/unlock', '{}'); + }, 3000); + + // 7. Display results + setTimeout(() => { + console.log('[INFO] Test sequence complete. Results:'); + console.log(`1. Buzzer activity detected for buzzer 1: ${testResults.buzzerActivity ? 'PASSED' : 'FAILED'}`); + console.log(`2. Confirmation received for buzzer 1: ${testResults.confirmationReceived ? 'PASSED' : 'FAILED'}`); + console.log(`3. Buzzer 1 status set to "blocked": ${testResults.statusBlocked ? 'PASSED' : 'FAILED'}`); + console.log(`4. Buzzer status set to "unblocked": ${testResults.statusUnblocked ? 'PASSED' : 'FAILED'}`); + console.log(`5. Tilt mode add confirmed for buzzer 2: ${testResults.tiltAddConfirmed ? 'PASSED' : 'FAILED'}`); + console.log(`6. Tilted buzzer press ignored: ${testResults.tiltIgnored ? 'PASSED' : 'FAILED'}`); + console.log(`7. Tilt status update sent (add): ${testResults.tiltUpdateAdd ? 'PASSED' : 'FAILED'}`); + console.log(`8. Tilt mode remove confirmed for buzzer 2: ${testResults.tiltRemoveConfirmed ? 'PASSED' : 'FAILED'}`); + console.log(`9. Tilt status update sent (remove): ${testResults.tiltUpdateRemove ? 'PASSED' : 'FAILED'}`); + console.log(`10. Unlock confirmation received: ${testResults.unlockConfirmation ? 'PASSED' : 'FAILED'}`); + client.end(); // End the MQTT connection + }, 4000); +} diff --git a/VNode/services/buzzer/buzzer-manager.js b/VNode/services/buzzer/buzzer-manager.js new file mode 100644 index 00000000..92919af4 --- /dev/null +++ b/VNode/services/buzzer/buzzer-manager.js @@ -0,0 +1,223 @@ +// Import necessary modules +const mqtt = require('mqtt'); + +// MQTT broker configuration +const brokerUrl = 'mqtt://localhost'; // Broker URL (change if needed) +const clientId = 'buzzer_manager'; +const options = { + clientId, + clean: true +}; + +// State variables +let buzzerActive = false; // Indicates if buzzers are blocked +let buzzerThatPressed = null; // Stores the ID of the buzzer that pressed first +let tiltBuzzers = new Set(); // List of buzzer IDs currently in "tilt" mode + +// Connect to the MQTT broker +const client = mqtt.connect(brokerUrl, options); + +client.on('connect', () => { + console.log(`[INFO] Connected to MQTT broker ${brokerUrl} with ID ${clientId}`); + + // Subscribe to topics related to buzzer presses, unlocking, and tilt management + client.subscribe('vulture/buzzer/pressed/#', (err) => { + if (err) console.error('[ERROR] Failed to subscribe to buzzer presses'); + else console.log('[INFO] Successfully subscribed to buzzer presses'); + }); + + client.subscribe('vulture/buzzer/unlock', (err) => { + if (err) console.error('[ERROR] Failed to subscribe to buzzer unlock'); + else console.log('[INFO] Successfully subscribed to buzzer unlock'); + }); + + client.subscribe('vulture/buzzer/tilt', (err) => { + if (err) console.error('[ERROR] Failed to subscribe to tilt management'); + else console.log('[INFO] Successfully subscribed to tilt management'); + }); +}); + +// Validate buzzer payload +function validateBuzzerPayload(payload) { + const { buzzer_id, color } = payload; + + // Validate buzzer ID (should be a positive integer) + if (typeof buzzer_id !== 'number' || buzzer_id <= 0) { + console.error(`[ERROR] Invalid buzzer ID: ${buzzer_id}`); + return false; + } + + // Validate color (should be in the format #RRGGBB) + const validColor = /^#[0-9A-F]{6}$/i.test(color); + if (!validColor) { + console.error(`[ERROR] Invalid color: ${color}`); + return false; + } + + return true; +} + +// Send updated tilt status +function sendTiltStatus(action, buzzerId) { + const tiltList = Array.from(tiltBuzzers); // Convert Set to Array + + client.publish('vulture/buzzer/status', JSON.stringify({ + status: "tilt_update", + tilt_buzzers: tiltList, + message: `Buzzer ID ${buzzerId} ${action} to tilt mode`, + timestamp: new Date().toISOString() + })); + + console.log(`[INFO] Tilt status updated: ${tiltList.length} buzzers in tilt mode`); +} + +// Handle incoming messages +client.on('message', (topic, message) => { + let payload; + + // Parse the incoming message + try { + payload = JSON.parse(message.toString()); + } catch (e) { + console.error(`[ERROR] Invalid JSON message received on topic ${topic}: ${message.toString()}`); + return; + } + + // Manage tilt mode for buzzers + if (topic === 'vulture/buzzer/tilt') { + const { buzzer_id, status } = payload; + + if (typeof buzzer_id !== 'number' || !['add', 'remove'].includes(status)) { + console.error('[ERROR] Invalid tilt payload, message ignored.'); + return; + } + + // Update tilt status based on the command + if (status === 'add') { + tiltBuzzers.add(buzzer_id); + console.log(`[INFO] Buzzer ID ${buzzer_id} added to tilt mode`); + } else if (status === 'remove') { + tiltBuzzers.delete(buzzer_id); + console.log(`[INFO] Buzzer ID ${buzzer_id} removed from tilt mode`); + } + + // Confirm that the tilt command has been received + client.publish(`vulture/buzzer/tilt/confirmation/${buzzer_id}`, JSON.stringify({ + status: "received", + action: status, + buzzer_id: buzzer_id, + message: `Tilt command '${status}' received for buzzer ID ${buzzer_id}`, + timestamp: new Date().toISOString() + })); + + // Send the updated tilt status to all components + sendTiltStatus(status === 'add' ? 'added' : 'removed', buzzer_id); + + return; + } + + // Detect a buzzer press + if (topic.startsWith('vulture/buzzer/pressed/')) { + // Validate buzzer payload + if (!validateBuzzerPayload(payload)) { + console.error('[ERROR] Invalid buzzer payload, message ignored.'); + return; + } + + const buzzerId = payload.buzzer_id; // Unique buzzer ID + const color = payload.color; // Associated hex color + + // Always send a confirmation, even if the buzzer is in tilt mode + client.publish(`vulture/buzzer/confirmation/${buzzerId}`, JSON.stringify({ + status: "received", + buzzer_id: buzzerId, + message: `Buzzer ID ${buzzerId} received (Color: ${color})`, + timestamp: new Date().toISOString() + })); + + // Ignore if the buzzer is in tilt mode, but notify this event + if (tiltBuzzers.has(buzzerId)) { + console.log(`[INFO] Buzzer ID ${buzzerId} ignored (Tilt mode active)`); + + // Notify that the buzzer is in tilt mode and ignored + client.publish(`vulture/buzzer/tilt/ignored/${buzzerId}`, JSON.stringify({ + status: "tilt_ignored", + buzzer_id: buzzerId, + message: `Buzzer ID ${buzzerId} is in tilt mode and ignored.`, + timestamp: new Date().toISOString() + })); + return; + } + + // Notify activity even if buzzers are blocked + client.publish('vulture/buzzer/activity', JSON.stringify({ + buzzer_id: buzzerId, + color: color, + status: buzzerActive ? "blocked" : "free", + message: `Activity detected on buzzer ID ${buzzerId} (Color: ${color})`, + timestamp: new Date().toISOString() + })); + + if (!buzzerActive) { + // Block further buzzers and record the first pressed ID + buzzerActive = true; + buzzerThatPressed = buzzerId; + + console.log(`[INFO] Buzzer activated by ID: ${buzzerId} (Color: ${color})`); + + // Notify the light manager to change to the team's color + client.publish('vulture/light/change', JSON.stringify({ + color: color, + effect: 'full_color' + })); + + // Notify all components of buzzer blocking + client.publish('vulture/buzzer/status', JSON.stringify({ + status: "blocked", + buzzer_id: buzzerId, + color: color, + message: `Buzzer activated by ID ${buzzerId} (Color: ${color})`, + timestamp: new Date().toISOString() + })); + + console.log(`[INFO] Buzzers blocked and notification sent`); + } + } + + // Unlock buzzers + if (topic === 'vulture/buzzer/unlock') { + console.log('[INFO] Buzzer unlock requested'); + + // Confirm receipt of unlock command + client.publish('vulture/buzzer/unlock/confirmation', JSON.stringify({ + status: "received", + message: "Buzzer unlock command received.", + timestamp: new Date().toISOString() + })); + // Notify the light manager to change to the team's color + client.publish('vulture/light/change', JSON.stringify({ + color: "#FFFFFF", + effect: 'rainbow' + })); + + + // Reset buzzer manager state + buzzerActive = false; + buzzerThatPressed = null; + + // Notify all components of buzzer unlock + client.publish('vulture/buzzer/status', JSON.stringify({ + status: "unblocked", + message: "Buzzers unblocked and ready for activation.", + timestamp: new Date().toISOString() + })); + + console.log('[INFO] Buzzers unblocked and notification sent'); + } +}); + +client.on('error', (err) => { + console.error(`[ERROR] Error connecting to broker: ${err}`); +}); + +console.log('[INFO] Buzzer manager started...'); diff --git a/VNode/services/buzzer/buzzer-watcher.js b/VNode/services/buzzer/buzzer-watcher.js new file mode 100644 index 00000000..a59eacaa --- /dev/null +++ b/VNode/services/buzzer/buzzer-watcher.js @@ -0,0 +1,39 @@ +const ping = require('ping'); +const mqtt = require('mqtt'); +const fs = require('fs'); + +// Lecture du fichier de configuration +const config = JSON.parse(fs.readFileSync('\services\\config\\config_network.json', 'utf8')); + +// Extraction des informations de config +const { hosts: { buzzers: { IP: buzzerIPs, MQTTconfig: { mqttHost, mqttTopic } } } } = config; + +// Connexion au broker MQTT +const client = mqtt.connect(mqttHost); + +client.on('connect', () => { + console.log(`Connecté au broker MQTT à ${mqttHost}`); + + // Fonction pour pinger les buzzers et publier l'état + const pingAndPublish = async () => { + for (const [buzzerName, ip] of Object.entries(buzzerIPs)) { + try { + const res = await ping.promise.probe(ip); + const status = res.alive ? 'online' : 'offline'; + + // Publication du statut dans le topic MQTT + client.publish(`${mqttTopic}`, JSON.stringify({ buzzer: buzzerName, ip, status })); + console.log(`Ping ${buzzerName} (${ip}) - Status: ${status}`); + } catch (error) { + console.error(`Erreur avec le buzzer ${buzzerName} (${ip}):`, error.message); + } + } + }; + + // Pinger toutes les 5 secondes + setInterval(pingAndPublish, 3000); +}); + +client.on('error', (error) => { + console.error('Erreur de connexion au broker MQTT:', error.message); +}); diff --git a/VNode/services/config/config_game.json b/VNode/services/config/config_game.json new file mode 100644 index 00000000..127e22b6 --- /dev/null +++ b/VNode/services/config/config_game.json @@ -0,0 +1,18 @@ +{ + "services": { + "mqttHost": "mqtt://192.168.1.30", + "score":{ + "MQTTconfig":{ + "mqttScoreTopic": "game/score", + "mqttScoreChangeTopic": "game/score/update" + } + }, + "quizzcollector":{ + "MQTTconfig":{ + "mqttQuizzCollectorListTopic": "game/quizz-collector/list", + "mqttQuizzCollectorCmdTopic": "game/quizz-collector/cmd" + } + } + } + +} \ No newline at end of file diff --git a/VNode/services/config/config_network.json b/VNode/services/config/config_network.json new file mode 100644 index 00000000..47f2ce0d --- /dev/null +++ b/VNode/services/config/config_network.json @@ -0,0 +1,17 @@ +{ + "hosts": { + "buzzers":{ + "IP":{ + "redBuzzerIP": "8.8.8.6", + "blueBuzzerIP": "8.8.8.8", + "greenBuzzerIP": "8.8.8.8", + "yellowBuzzerIP": "8.8.8.8" + }, + "MQTTconfig":{ + "mqttHost": "mqtt://192.168.1.28", + "mqttTopic": "buzzer/watcher" + } + } + } + +} \ No newline at end of file diff --git a/VNode/services/game/quizz-collector.js b/VNode/services/game/quizz-collector.js new file mode 100644 index 00000000..5ca21f09 --- /dev/null +++ b/VNode/services/game/quizz-collector.js @@ -0,0 +1,52 @@ +const fs = require('fs'); +const mqtt = require('mqtt'); + +// Lecture du fichier de configuration +const config = JSON.parse(fs.readFileSync('\services\\config\\config_game.json', 'utf8')); + +// Extraction des informations de config +const { services: { mqttHost, quizzcollector: { MQTTconfig: { mqttQuizzCollectorListTopic, mqttQuizzCollectorCmdTopic } } } } = config; + +// Configuration +const folderPath = 'quizz'; // Remplace par le chemin de ton dossier + +// Connexion au broker MQTT +const client = mqtt.connect(mqttHost); + +client.on('connect', () => { + console.log('Connecté au broker MQTT'); + client.subscribe(mqttQuizzCollectorCmdTopic, (err) => { + if (err) { + console.error("Erreur lors de l'abonnement au topic de commande:", err); + } else { + console.log(`Abonné au topic ${mqttQuizzCollectorCmdTopic}`); + } + }); +}); + +client.on('message', (topic, message) => { + if (topic === mqttQuizzCollectorCmdTopic) { + console.log('Commande reçue, lecture du dossier en cours...'); + Collect(); + } +}); + + +function Collect() { + fs.readdir(folderPath, (err, files) => { + if (err) { + console.error('Erreur lors de la lecture du dossier:', err); + return; + } + + console.log('Dossiers trouvés:', files); + const message = JSON.stringify( files ); + client.publish(mqttQuizzCollectorListTopic, message, { qos: 1 }, (err) => { + if (err) { + console.error('Erreur lors de la publication MQTT:', err); + } else { + console.log('Liste des fichiers publiée sur MQTT'); + } + }); + }); +} diff --git a/VNode/services/game/score-manager.js b/VNode/services/game/score-manager.js new file mode 100644 index 00000000..bb3f9391 --- /dev/null +++ b/VNode/services/game/score-manager.js @@ -0,0 +1,232 @@ +const args = process.argv; + +// Vérification si un paramètre est passé, si c'est le cas c'est qu'on fournis un fichier de score pour reprendre le jeu la ou il était +if (args[2] !== undefined){ + global.ScoreFile = args[2] +}else{ + global.ScoreFile = "XXX.json" +} + +const fs = require('fs'); +const path = require('path'); +const mqtt = require('mqtt'); + +// Fonction pour générer un nom de fichier unique +function generateUniqueFileName(baseName) { + const now = new Date(); + const timestamp = `${now.getFullYear()}-${String(now.getMonth() + 1).padStart(2, '0')}-${String(now.getDate()).padStart(2, '0')}_${String(now.getHours()).padStart(2, '0')}H${String(now.getMinutes()).padStart(2, '0')}`; + return `${baseName}_${timestamp}.json`; +} + +// Chemin vers le dossier "score" et le fichier +global.scoreDir = path.join(__dirname, 'score'); +global.filePath = path.join(scoreDir, ScoreFile); // Remplace "XX.json" par le nom de ton fichier JSON + +// Vérifie si le dossier "score" existe, sinon le crée +if (!fs.existsSync(scoreDir)) { + fs.mkdirSync(scoreDir, { recursive: true }); +} + +// Vérifie si le fichier existe dans le dossier "score" +fs.access(filePath, fs.constants.F_OK, (err) => { + if (!err) { + // Le fichier existe, on le lit et on le parse en JSON + fs.readFile(filePath, 'utf8', (err, data) => { + if (err) { + console.error("Erreur de lecture du fichier :", err); + return; + } + try { + global.jsonData = JSON.parse(data); + console.log("Propriétés importées depuis le fichier JSON :"); + } catch (parseErr) { + console.error("Erreur de parsing JSON :", parseErr); + } + }); + } else { + // Le fichier n'existe pas, on en crée un nouveau avec un nom unique dans "score" + const newFileName = generateUniqueFileName('Score'); + const newFilePath = path.join(scoreDir, newFileName); + const initialContent = { + "TEAM": { + "Red": { + "Name": "XXX", + "TotalScore": 0, + "RoundScore": 0, + "Penality": 0, + "MasterPoint": 0 + }, + "Blue": { + "Name": "XXX", + "TotalScore": 0, + "RoundScore": 0, + "Penality": 0, + "MasterPoint": 0 + }, + "Yellow": { + "Name": "XXX", + "TotalScore": 0, + "RoundScore": 0, + "Penality": 0, + "MasterPoint": 0 + }, + "Green": { + "Name": "XXX", + "TotalScore": 0, + "RoundScore": 0, + "Penality": 0, + "MasterPoint": 0 + } + } + }; + + fs.writeFile(newFilePath, JSON.stringify(initialContent, null, 2), (err) => { + if (err) { + console.error("Erreur de création du fichier :", err); + return; + } + console.log(`Fichier JSON créé avec succès : ${newFilePath}`); + // Mettre à jour ScoreFile et filePath + + // Charger les données initiales si nécessaire + global.jsonData = initialContent; + global.filePath = newFilePath + }); + } +}); + +// Fonction pour mettre à jour le score d'une équipe +function updateTeamTotalScore(teamColor, points) { + fs.readFile(filePath, 'utf8', (err, data) => { + if (err) { + console.error("Erreur de lecture du fichier :", err); + return; + } + try { + const jsonData = JSON.parse(data); + // Vérifier si l'équipe existe + if (!jsonData.TEAM.hasOwnProperty(teamColor)) { + console.error(`L'équipe ${teamColor} n'existe pas.`); + return; + } + + const change = parseInt(points, 10); + + // Mettre à jour le score + jsonData.TEAM[teamColor].TotalScore += points; + console.log(`Le score total pour l'équipe ${teamColor} est de ${jsonData.TEAM[teamColor].TotalScore} points !`) + // Enregistrer les modifications dans le fichier + client.publish(mqttScoreTopic, JSON.stringify(jsonData)); + fs.writeFile(filePath, JSON.stringify(jsonData, null, 2), (err) => { + if (err) { + console.error("Erreur lors de l'écriture du fichier :", err); + } else { + console.log(`Le score total de l'équipe ${teamColor} a été mis à jour avec succès dans le fichier json !`); + } + }); + } catch (parseErr) { + console.error("Erreur de parsing JSON :", parseErr); + } + }); +} + + +// Lecture du fichier de configuration +const config = JSON.parse(fs.readFileSync('\services\\config\\config_game.json', 'utf8')); + +// Extraction des informations de config +const { services: { mqttHost, score: { MQTTconfig: { mqttScoreTopic, mqttScoreChangeTopic } } } } = config; +console.log(mqttScoreChangeTopic) +// Connexion au broker MQTT +const client = mqtt.connect(mqttHost); + +client.on('connect', () => { + console.log(`Connecté au broker MQTT à ${mqttHost}`); + + client.subscribe(mqttScoreChangeTopic, (err) => { + if (err) console.error('[ERROR] impossible de souscrire au topic de gestion du score total'); + else console.log(`[INFO] Souscription réalisée avec succès au topic ${mqttScoreChangeTopic}]`); + }); + +}); + +// Gestion des messages entrants +client.on('message', (topic, message) => { + let payload; + let process; + let Team; + let Action; + + try { + // Analyse du message reçu + payload = JSON.parse(message.toString()); + } catch (e) { + console.error(`[ERROR] Invalid JSON message received on topic ${topic}: ${message.toString()}`); + return; + } + // Vérifie que le payload est bien un objet + if (payload && typeof payload === 'object') { + // Extraire la clé (la couleur) et la valeur associée + Team = Object.keys(payload)[0]; // La première (et unique) clé + Action = payload[Team]; // La valeur associée + //console.log(`Team: ${Team}, Action: ${Action}`); + process = true; + } else { + console.error(typeof payload); + process = false; + } + + if (process === true){ + let currentScore = 0; + let change = 0 ; + switch (Team){ + case "Red": + change = parseInt(Action, 10); // Convertit 'action' en entier + if (!isNaN(change)) { + updateTeamTotalScore("Red", change) + } else { + console.error(`Action invalide : ${action}`); + } + break; + case "Blue": + change = parseInt(Action, 10); // Convertit 'action' en entier + if (!isNaN(change)) { + updateTeamTotalScore("Blue", change) + } else { + console.error(`Action invalide : ${action}`); + } + break; + case "Green": + change = parseInt(Action, 10); // Convertit 'action' en entier + if (!isNaN(change)) { + updateTeamTotalScore("Green", change) + } else { + console.error(`Action invalide : ${action}`); + } + break; + case "Yellow": + change = parseInt(Action, 10); // Convertit 'action' en entier + if (!isNaN(change)) { + updateTeamTotalScore("Yellow", change) + } else { + console.error(`Action invalide : ${action}`); + } + break; + } + } + +}); + +(async () => { + while (true) { + console.log("Boucle en arrière-plan"); + + await new Promise((resolve) => setTimeout(resolve, 2000)); // Pause de 2 secondes + //client.publish(mqttScoreTopic, JSON.stringify(global.jsonData)); + } + })(); + +client.on('error', (error) => { + console.error('Erreur de connexion au broker MQTT:', error.message); +}); + diff --git a/VNode/services/game/score/Score_2024-11-18_19H39.json b/VNode/services/game/score/Score_2024-11-18_19H39.json new file mode 100644 index 00000000..2cd3518b --- /dev/null +++ b/VNode/services/game/score/Score_2024-11-18_19H39.json @@ -0,0 +1,28 @@ +{ + "TEAM": { + "Red": { + "Name": "XXX", + "Score": 0, + "Penality": 0, + "MasterPoint": 0 + }, + "Blue": { + "Name": "XXX", + "Score": 0, + "Penality": 0, + "MasterPoint": 0 + }, + "Yellow": { + "Name": "XXX", + "Score": 0, + "Penality": 0, + "MasterPoint": 0 + }, + "Green": { + "Name": "XXX", + "Score": 0, + "Penality": 0, + "MasterPoint": 0 + } + } +} \ No newline at end of file diff --git a/VNode/services/game/score/Score_2024-11-18_19H48.json b/VNode/services/game/score/Score_2024-11-18_19H48.json new file mode 100644 index 00000000..2cd3518b --- /dev/null +++ b/VNode/services/game/score/Score_2024-11-18_19H48.json @@ -0,0 +1,28 @@ +{ + "TEAM": { + "Red": { + "Name": "XXX", + "Score": 0, + "Penality": 0, + "MasterPoint": 0 + }, + "Blue": { + "Name": "XXX", + "Score": 0, + "Penality": 0, + "MasterPoint": 0 + }, + "Yellow": { + "Name": "XXX", + "Score": 0, + "Penality": 0, + "MasterPoint": 0 + }, + "Green": { + "Name": "XXX", + "Score": 0, + "Penality": 0, + "MasterPoint": 0 + } + } +} \ No newline at end of file diff --git a/VNode/services/game/score/Score_2024-11-18_19H54.json b/VNode/services/game/score/Score_2024-11-18_19H54.json new file mode 100644 index 00000000..2cd3518b --- /dev/null +++ b/VNode/services/game/score/Score_2024-11-18_19H54.json @@ -0,0 +1,28 @@ +{ + "TEAM": { + "Red": { + "Name": "XXX", + "Score": 0, + "Penality": 0, + "MasterPoint": 0 + }, + "Blue": { + "Name": "XXX", + "Score": 0, + "Penality": 0, + "MasterPoint": 0 + }, + "Yellow": { + "Name": "XXX", + "Score": 0, + "Penality": 0, + "MasterPoint": 0 + }, + "Green": { + "Name": "XXX", + "Score": 0, + "Penality": 0, + "MasterPoint": 0 + } + } +} \ No newline at end of file diff --git a/VNode/services/game/score/Score_2024-11-18_19H55.json b/VNode/services/game/score/Score_2024-11-18_19H55.json new file mode 100644 index 00000000..2cd3518b --- /dev/null +++ b/VNode/services/game/score/Score_2024-11-18_19H55.json @@ -0,0 +1,28 @@ +{ + "TEAM": { + "Red": { + "Name": "XXX", + "Score": 0, + "Penality": 0, + "MasterPoint": 0 + }, + "Blue": { + "Name": "XXX", + "Score": 0, + "Penality": 0, + "MasterPoint": 0 + }, + "Yellow": { + "Name": "XXX", + "Score": 0, + "Penality": 0, + "MasterPoint": 0 + }, + "Green": { + "Name": "XXX", + "Score": 0, + "Penality": 0, + "MasterPoint": 0 + } + } +} \ No newline at end of file diff --git a/VNode/services/game/score/Score_2024-11-18_21H35.json b/VNode/services/game/score/Score_2024-11-18_21H35.json new file mode 100644 index 00000000..2cd3518b --- /dev/null +++ b/VNode/services/game/score/Score_2024-11-18_21H35.json @@ -0,0 +1,28 @@ +{ + "TEAM": { + "Red": { + "Name": "XXX", + "Score": 0, + "Penality": 0, + "MasterPoint": 0 + }, + "Blue": { + "Name": "XXX", + "Score": 0, + "Penality": 0, + "MasterPoint": 0 + }, + "Yellow": { + "Name": "XXX", + "Score": 0, + "Penality": 0, + "MasterPoint": 0 + }, + "Green": { + "Name": "XXX", + "Score": 0, + "Penality": 0, + "MasterPoint": 0 + } + } +} \ No newline at end of file diff --git a/VNode/services/game/score/Score_2024-11-18_21H42.json b/VNode/services/game/score/Score_2024-11-18_21H42.json new file mode 100644 index 00000000..2cd3518b --- /dev/null +++ b/VNode/services/game/score/Score_2024-11-18_21H42.json @@ -0,0 +1,28 @@ +{ + "TEAM": { + "Red": { + "Name": "XXX", + "Score": 0, + "Penality": 0, + "MasterPoint": 0 + }, + "Blue": { + "Name": "XXX", + "Score": 0, + "Penality": 0, + "MasterPoint": 0 + }, + "Yellow": { + "Name": "XXX", + "Score": 0, + "Penality": 0, + "MasterPoint": 0 + }, + "Green": { + "Name": "XXX", + "Score": 0, + "Penality": 0, + "MasterPoint": 0 + } + } +} \ No newline at end of file diff --git a/VNode/services/game/score/Score_2024-11-18_21H43.json b/VNode/services/game/score/Score_2024-11-18_21H43.json new file mode 100644 index 00000000..2cd3518b --- /dev/null +++ b/VNode/services/game/score/Score_2024-11-18_21H43.json @@ -0,0 +1,28 @@ +{ + "TEAM": { + "Red": { + "Name": "XXX", + "Score": 0, + "Penality": 0, + "MasterPoint": 0 + }, + "Blue": { + "Name": "XXX", + "Score": 0, + "Penality": 0, + "MasterPoint": 0 + }, + "Yellow": { + "Name": "XXX", + "Score": 0, + "Penality": 0, + "MasterPoint": 0 + }, + "Green": { + "Name": "XXX", + "Score": 0, + "Penality": 0, + "MasterPoint": 0 + } + } +} \ No newline at end of file diff --git a/VNode/services/game/score/Score_2024-11-18_21H44.json b/VNode/services/game/score/Score_2024-11-18_21H44.json new file mode 100644 index 00000000..2cd3518b --- /dev/null +++ b/VNode/services/game/score/Score_2024-11-18_21H44.json @@ -0,0 +1,28 @@ +{ + "TEAM": { + "Red": { + "Name": "XXX", + "Score": 0, + "Penality": 0, + "MasterPoint": 0 + }, + "Blue": { + "Name": "XXX", + "Score": 0, + "Penality": 0, + "MasterPoint": 0 + }, + "Yellow": { + "Name": "XXX", + "Score": 0, + "Penality": 0, + "MasterPoint": 0 + }, + "Green": { + "Name": "XXX", + "Score": 0, + "Penality": 0, + "MasterPoint": 0 + } + } +} \ No newline at end of file diff --git a/VNode/services/game/score/Score_2024-11-18_21H45.json b/VNode/services/game/score/Score_2024-11-18_21H45.json new file mode 100644 index 00000000..2cd3518b --- /dev/null +++ b/VNode/services/game/score/Score_2024-11-18_21H45.json @@ -0,0 +1,28 @@ +{ + "TEAM": { + "Red": { + "Name": "XXX", + "Score": 0, + "Penality": 0, + "MasterPoint": 0 + }, + "Blue": { + "Name": "XXX", + "Score": 0, + "Penality": 0, + "MasterPoint": 0 + }, + "Yellow": { + "Name": "XXX", + "Score": 0, + "Penality": 0, + "MasterPoint": 0 + }, + "Green": { + "Name": "XXX", + "Score": 0, + "Penality": 0, + "MasterPoint": 0 + } + } +} \ No newline at end of file diff --git a/VNode/services/game/score/Score_2024-11-18_21H46.json b/VNode/services/game/score/Score_2024-11-18_21H46.json new file mode 100644 index 00000000..2cd3518b --- /dev/null +++ b/VNode/services/game/score/Score_2024-11-18_21H46.json @@ -0,0 +1,28 @@ +{ + "TEAM": { + "Red": { + "Name": "XXX", + "Score": 0, + "Penality": 0, + "MasterPoint": 0 + }, + "Blue": { + "Name": "XXX", + "Score": 0, + "Penality": 0, + "MasterPoint": 0 + }, + "Yellow": { + "Name": "XXX", + "Score": 0, + "Penality": 0, + "MasterPoint": 0 + }, + "Green": { + "Name": "XXX", + "Score": 0, + "Penality": 0, + "MasterPoint": 0 + } + } +} \ No newline at end of file diff --git a/VNode/services/game/score/Score_2024-11-18_21H47.json b/VNode/services/game/score/Score_2024-11-18_21H47.json new file mode 100644 index 00000000..2cd3518b --- /dev/null +++ b/VNode/services/game/score/Score_2024-11-18_21H47.json @@ -0,0 +1,28 @@ +{ + "TEAM": { + "Red": { + "Name": "XXX", + "Score": 0, + "Penality": 0, + "MasterPoint": 0 + }, + "Blue": { + "Name": "XXX", + "Score": 0, + "Penality": 0, + "MasterPoint": 0 + }, + "Yellow": { + "Name": "XXX", + "Score": 0, + "Penality": 0, + "MasterPoint": 0 + }, + "Green": { + "Name": "XXX", + "Score": 0, + "Penality": 0, + "MasterPoint": 0 + } + } +} \ No newline at end of file diff --git a/VNode/services/game/score/Score_2024-11-18_21H49.json b/VNode/services/game/score/Score_2024-11-18_21H49.json new file mode 100644 index 00000000..2cd3518b --- /dev/null +++ b/VNode/services/game/score/Score_2024-11-18_21H49.json @@ -0,0 +1,28 @@ +{ + "TEAM": { + "Red": { + "Name": "XXX", + "Score": 0, + "Penality": 0, + "MasterPoint": 0 + }, + "Blue": { + "Name": "XXX", + "Score": 0, + "Penality": 0, + "MasterPoint": 0 + }, + "Yellow": { + "Name": "XXX", + "Score": 0, + "Penality": 0, + "MasterPoint": 0 + }, + "Green": { + "Name": "XXX", + "Score": 0, + "Penality": 0, + "MasterPoint": 0 + } + } +} \ No newline at end of file diff --git a/VNode/services/game/score/Score_2024-11-18_21H50.json b/VNode/services/game/score/Score_2024-11-18_21H50.json new file mode 100644 index 00000000..2cd3518b --- /dev/null +++ b/VNode/services/game/score/Score_2024-11-18_21H50.json @@ -0,0 +1,28 @@ +{ + "TEAM": { + "Red": { + "Name": "XXX", + "Score": 0, + "Penality": 0, + "MasterPoint": 0 + }, + "Blue": { + "Name": "XXX", + "Score": 0, + "Penality": 0, + "MasterPoint": 0 + }, + "Yellow": { + "Name": "XXX", + "Score": 0, + "Penality": 0, + "MasterPoint": 0 + }, + "Green": { + "Name": "XXX", + "Score": 0, + "Penality": 0, + "MasterPoint": 0 + } + } +} \ No newline at end of file diff --git a/VNode/services/game/score/Score_2024-11-18_21H51.json b/VNode/services/game/score/Score_2024-11-18_21H51.json new file mode 100644 index 00000000..8780e083 --- /dev/null +++ b/VNode/services/game/score/Score_2024-11-18_21H51.json @@ -0,0 +1,32 @@ +{ + "TEAM": { + "Red": { + "Name": "XXX", + "TotalScore": 22, + "RoundScore": 0, + "Penality": 0, + "MasterPoint": 0 + }, + "Blue": { + "Name": "XXX", + "TotalScore": 63, + "RoundScore": 0, + "Penality": 0, + "MasterPoint": 0 + }, + "Yellow": { + "Name": "XXX", + "TotalScore": 26, + "RoundScore": 0, + "Penality": 0, + "MasterPoint": 0 + }, + "Green": { + "Name": "XXX", + "TotalScore": 15, + "RoundScore": 0, + "Penality": 0, + "MasterPoint": 0 + } + } +} \ No newline at end of file diff --git a/VNode/services/game/score/Score_2025-02-02_20H09.json b/VNode/services/game/score/Score_2025-02-02_20H09.json new file mode 100644 index 00000000..9e418be1 --- /dev/null +++ b/VNode/services/game/score/Score_2025-02-02_20H09.json @@ -0,0 +1,32 @@ +{ + "TEAM": { + "Red": { + "Name": "XXX", + "TotalScore": 0, + "RoundScore": 0, + "Penality": 0, + "MasterPoint": 0 + }, + "Blue": { + "Name": "XXX", + "TotalScore": 0, + "RoundScore": 0, + "Penality": 0, + "MasterPoint": 0 + }, + "Yellow": { + "Name": "XXX", + "TotalScore": 0, + "RoundScore": 0, + "Penality": 0, + "MasterPoint": 0 + }, + "Green": { + "Name": "XXX", + "TotalScore": 0, + "RoundScore": 0, + "Penality": 0, + "MasterPoint": 0 + } + } +} \ No newline at end of file diff --git a/VNode/services/game/score/Score_2025-02-02_20H11.json b/VNode/services/game/score/Score_2025-02-02_20H11.json new file mode 100644 index 00000000..8ade6828 --- /dev/null +++ b/VNode/services/game/score/Score_2025-02-02_20H11.json @@ -0,0 +1,32 @@ +{ + "TEAM": { + "Red": { + "Name": "XXX", + "TotalScore": 20, + "RoundScore": 0, + "Penality": 0, + "MasterPoint": 0 + }, + "Blue": { + "Name": "XXX", + "TotalScore": 0, + "RoundScore": 0, + "Penality": 0, + "MasterPoint": 0 + }, + "Yellow": { + "Name": "XXX", + "TotalScore": 0, + "RoundScore": 0, + "Penality": 0, + "MasterPoint": 0 + }, + "Green": { + "Name": "XXX", + "TotalScore": 0, + "RoundScore": 0, + "Penality": 0, + "MasterPoint": 0 + } + } +} \ No newline at end of file diff --git a/VNode/services/game/score/Score_2025-02-02_20H14.json b/VNode/services/game/score/Score_2025-02-02_20H14.json new file mode 100644 index 00000000..e20a1889 --- /dev/null +++ b/VNode/services/game/score/Score_2025-02-02_20H14.json @@ -0,0 +1,32 @@ +{ + "TEAM": { + "Red": { + "Name": "XXX", + "TotalScore": 1, + "RoundScore": 0, + "Penality": 0, + "MasterPoint": 0 + }, + "Blue": { + "Name": "XXX", + "TotalScore": 0, + "RoundScore": 0, + "Penality": 0, + "MasterPoint": 0 + }, + "Yellow": { + "Name": "XXX", + "TotalScore": 0, + "RoundScore": 0, + "Penality": 0, + "MasterPoint": 0 + }, + "Green": { + "Name": "XXX", + "TotalScore": 0, + "RoundScore": 0, + "Penality": 0, + "MasterPoint": 0 + } + } +} \ No newline at end of file diff --git a/VNode/services/light/light-manager.js b/VNode/services/light/light-manager.js new file mode 100644 index 00000000..3bb87516 --- /dev/null +++ b/VNode/services/light/light-manager.js @@ -0,0 +1,138 @@ +// Import du module MQTT +const mqtt = require('mqtt'); + +// Configuration du broker MQTT et de WLED +const brokerUrl = 'mqtt://localhost'; // Change ce lien si nécessaire +const clientId = 'light_manager_wled'; +const wledTopicBase = 'wled/all'; // Le topic de base pour ton ruban WLED +const options = { + clientId, + clean: true +}; + +// État des lumières +let currentColor = '#FFFFFF'; // Couleur par défaut (blanc) +let currentEffect = 'none'; // Pas d'effet par défaut + +// Connexion au broker MQTT +const client = mqtt.connect(brokerUrl, options); + +client.on('connect', () => { + console.log(`[INFO] Connected to MQTT broker ${brokerUrl} as ${clientId}`); + + // Souscription aux topics de gestion de lumière + client.subscribe('vulture/light/#', (err) => { + if (err) console.error('[ERROR] Subscription to light topics failed'); + else console.log('[INFO] Successfully subscribed to light topics'); + }); +}); + +// Fonction pour envoyer un message au ruban WLED +function sendToWLED(topicSuffix, message) { + const wledTopic = `${wledTopicBase}/${topicSuffix}`; + client.publish(wledTopic, message, { qos: 1 }, (err) => { + if (err) console.error(`[ERROR] Failed to send message to WLED topic: ${wledTopic}`); + else console.log(`[INFO] Sent to WLED (${wledTopic}): ${message}`); + }); +} + +// Fonction pour appliquer un changement de lumière +function applyLightChange(color, effect, intensity) { + currentColor = color || currentColor; + currentEffect = effect || currentEffect; + + console.log(`[INFO] Applying light change: Color=${currentColor}, Effect=${currentEffect}, Intensity=${intensity}`); + + // Envoyer la couleur au ruban WLED + sendToWLED('col', currentColor); + + // Appliquer l'effet si défini + if (currentEffect !== 'none') { + const effectId = getWLEDEffectId(currentEffect); + sendToWLED('api', "FX=" + effectId.toString()); + } + + // Régler l'intensité si spécifiée + if (intensity) { + sendToWLED('api', intensity.toString()); + } + + // Envoi de l'état mis à jour + sendLightStatus(); +} + +// Fonction pour obtenir l'ID d'effet WLED correspondant à un effet donné +function getWLEDEffectId(effect) { + const effectsMap = { + 'none': 0, + 'blink': 1, // Effet de fondu + 'fade': 12, // Clignotement + 'rainbow': 9 // Effet arc-en-ciel + }; + return effectsMap[effect] || 0; // Par défaut, aucun effet +} + +// Fonction pour envoyer l'état actuel des lumières sur le topic de réponse +function sendLightStatus() { + const statusMessage = JSON.stringify({ + status: "updated", + color: currentColor, + effect: currentEffect, + message: `Current light state: Color=${currentColor}, Effect=${currentEffect}`, + timestamp: new Date().toISOString() + }); + + // Envoi de l'état à tous les clients intéressés + client.publish('vulture/light/status/response', statusMessage); + + console.log('[INFO] Light status sent to vulture/light/status/response'); +} + +// Gestion des messages entrants +client.on('message', (topic, message) => { + let payload; + + try { + // Analyse du message reçu + payload = JSON.parse(message.toString()); + } catch (e) { + console.error(`[ERROR] Invalid JSON message received on topic ${topic}: ${message.toString()}`); + return; + } + + // Changement de lumière + if (topic === 'vulture/light/change') { + const { color, effect, intensity } = payload; + + // Valider la couleur et l'effet + if (!/^#[0-9A-F]{6}$/i.test(color)) { + console.error('[ERROR] Invalid color format'); + return; + } + + // Appliquer le changement de lumière + applyLightChange(color, effect, intensity); + + } else if (topic === 'vulture/light/reset') { + // Réinitialisation des lumières à la couleur et l'effet par défaut + console.log('[INFO] Resetting lights to default state'); + applyLightChange('#FFFFFF', 'reset', 255); + + } else if (topic === 'vulture/light/status/request') { + // Répondre à la requête de statut + console.log('[INFO] Light status request received'); + sendLightStatus(); + } else if (topic === 'vulture/light/status/response') { + // Répondre à la requête de statut + console.log('[INFO] Light status response received'); + } else { + console.error(`[ERROR] Unrecognized topic: ${topic}`); + } +}); + +// Gestion des erreurs de connexion +client.on('error', (err) => { + console.error(`[ERROR] Error connecting to broker: ${err}`); +}); + +console.log('[INFO] Light Manager with WLED support and status handling started...'); diff --git a/VNode/services/readme.md b/VNode/services/readme.md new file mode 100644 index 00000000..0fab312c --- /dev/null +++ b/VNode/services/readme.md @@ -0,0 +1,132 @@ +# Présentation des divers services liés à Vulture. + +## 📟 Gestionnaire de Buzzer pour Vulture (*`Buzzer-Manager.js`*) + +Ce script Node.js gère les buzzers du jeu **Vulture** en utilisant MQTT pour la communication entre les buzzers et les autres composants du système. + +### 🚀 Fonctionnalités Principales +* **Connexion au Broker MQTT** : Se connecte à un broker MQTT (*`mqtt://localhost`* par défaut) pour envoyer et recevoir des messages. +* **Gestion des Buzzers** : + * **Blocage/Déblocage** : Bloque les buzzers lorsqu'un est activé pour empêcher les autres de répondre, et les débloque sur demande. + * **Mode Tilt** : Permet d'ignorer certains buzzers en les ajoutant au mode "tilt". +* **Validation des Données** : Vérifie que les informations reçues des buzzers sont valides (ID du buzzer, couleur, etc.). +* **Intégration Lumineuse** : Contrôle les effets lumineux en fonction des actions des buzzers via le gestionnaire de lumières. + + +### 🛠️ Configuration et Utilisation + +* **Installation des Dépendances** : +```bash +npm install mqtt +``` +* **Configuration** : + + * Modifier l'URL du broker MQTT et le client ID si nécessaire dans le script : + +```javascript +// Configuration du broker MQTT +const brokerUrl = 'mqtt://votre-broker'; +const clientId = 'buzzer_manager'; +``` + +* **Lancement du Script** : +```bash +node buzzer-manager.js +``` + +### 📡 Sujets MQTT Utilisés +* **Souscriptions** : + * `Vulture/buzzer/pressed/#` : Détecte lorsqu'un buzzer est pressé. + * `Vulture/buzzer/unlock` : Gère les demandes de déblocage des buzzers. + * `Vulture/buzzer/tilt` : Gère l'ajout ou le retrait des buzzers en mode tilt. +* **Publications** : + * `Vulture/buzzer/confirmation/{buzzer_id}` : Confirme la réception des actions des buzzers. + * `Vulture/buzzer/status` : Informe sur l'état actuel des buzzers (bloqués, débloqués, tilt). + * `Vulture/light/change` : Demande des changements d'effets lumineux au gestionnaire de lumières. + +--- + +## 🖥️ Moniteur de Statut des Buzzers pour Vulture (*`BuzzerWatcher.js`*) + +Ce script Node.js surveille l'état des buzzers du jeu **Vulture** en les pingant régulièrement et en publiant leur statut (en ligne/hors ligne) sur un broker MQTT. + +### 🚀 Fonctionnalités Principales + +* **Surveillance des Buzzers** : Pinge chaque buzzer à intervalles réguliers pour vérifier s'il est en ligne. +* **Publication MQTT** : Envoie le statut (`online` ou `offline`) de chaque buzzer sur un topic MQTT spécifié, permettant aux autres composants du système de réagir en conséquence. +* **Configuration Flexible** : Charge dynamiquement les adresses IP des buzzers et les paramètres MQTT depuis un fichier `config.json`. + +### 🛠️ Installation et Configuration +#### Prérequis + +* **Node.js** installé sur votre machine. +* Modules NPM requis : `ping` et `mqtt`. + +#### Installation des Dépendances +```bash +npm install ping mqtt +``` + +#### Configuration +1. **Fichier de Configuration** : Créez un fichier `config.json` dans le répertoire `\services\config\` avec le contenu suivant : + +```json +{ + "hosts": { + "buzzers": { + "IP": { + "buzzer1": "192.168.1.10", + "buzzer2": "192.168.1.11" + }, + "MQTTconfig": { + "mqttHost": "mqtt://localhost", + "mqttTopic": "Vulture/buzzers/status" + } + } + } +} +``` + +* **Adresses IP des Buzzers** : Remplacez par les adresses IP de vos buzzers. +* **Configuration MQTT** : + * `mqttHost` : L'adresse de votre broker MQTT. + * `mqttTopic` : Le topic sur lequel publier le statut des buzzers. + +2. **Chemin du Fichier de Configuration** : Assurez-vous que le chemin vers `config.json` dans le script est correct : + +```javascript +const config = JSON.parse(fs.readFileSync('\\services\\config\\config.json', 'utf8')); +``` + +### ▶️ Utilisation + +* **Lancement du Script** : +```bash +node BuzzerWatcher.js +``` + +Le script va : + + * Se connecter au broker MQTT spécifié. + * Pinger chaque buzzer toutes les 3 secondes. + * Publier le statut de chaque buzzer sur le topic MQTT configuré. + +### 📡 Topic MQTT Utilisés + +* **Publication** : + * **Topic** : `Vulture/buzzers` + * **Payload Exemple** : + +```json +{ + "buzzer": "buzzer1", + "ip": "192.168.1.10", + "status": "online" +} +``` + +### 💡 Notes +* **Personnalisation de l'Intervalle** : Vous pouvez modifier l'intervalle de ping en changeant la valeur dans `setInterval(pingAndPublish, 3000);` (valeur en millisecondes). +* **Extensibilité** : Pour ajouter plus de buzzers, il suffit d'ajouter leurs adresses IP dans le fichier `config.json`. + +--- \ No newline at end of file diff --git a/VNode/soundplayer-mqtt/assets/sounds/8-bit-coin-fx_G_minor.wav b/VNode/soundplayer-mqtt/assets/sounds/8-bit-coin-fx_G_minor.wav new file mode 100644 index 00000000..b1a9448f Binary files /dev/null and b/VNode/soundplayer-mqtt/assets/sounds/8-bit-coin-fx_G_minor.wav differ diff --git a/VNode/soundplayer-mqtt/assets/sounds/bell.wav b/VNode/soundplayer-mqtt/assets/sounds/bell.wav new file mode 100644 index 00000000..bc3cc375 --- /dev/null +++ b/VNode/soundplayer-mqtt/assets/sounds/bell.wav @@ -0,0 +1 @@ +8-bit-coin-fx_G_minor.wav \ No newline at end of file diff --git a/VNode/soundplayer-mqtt/assets/sounds/coin.wav b/VNode/soundplayer-mqtt/assets/sounds/coin.wav new file mode 100644 index 00000000..bc3cc375 --- /dev/null +++ b/VNode/soundplayer-mqtt/assets/sounds/coin.wav @@ -0,0 +1 @@ +8-bit-coin-fx_G_minor.wav \ No newline at end of file diff --git a/VNode/soundplayer-mqtt/assets/sounds/fail.mp3 b/VNode/soundplayer-mqtt/assets/sounds/fail.mp3 new file mode 100644 index 00000000..301acc58 Binary files /dev/null and b/VNode/soundplayer-mqtt/assets/sounds/fail.mp3 differ diff --git a/VNode/soundplayer-mqtt/config.js b/VNode/soundplayer-mqtt/config.js new file mode 100644 index 00000000..22f1a830 --- /dev/null +++ b/VNode/soundplayer-mqtt/config.js @@ -0,0 +1 @@ +mqttBrokerUrl = 'ws://localhost:9001' diff --git a/VNode/soundplayer-mqtt/package-lock.json b/VNode/soundplayer-mqtt/package-lock.json new file mode 100644 index 00000000..76dd60e7 --- /dev/null +++ b/VNode/soundplayer-mqtt/package-lock.json @@ -0,0 +1,482 @@ +{ + "name": "src", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "dependencies": { + "mqtt": "^5.3.6", + "play-sound": "^1.1.6" + } + }, + "node_modules/@babel/runtime": { + "version": "7.24.0", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.24.0.tgz", + "integrity": "sha512-Chk32uHMg6TnQdvw2e9IlqPpFX/6NLuK0Ys2PqLb7/gL5uFn9mXvK715FGLlOLQrcO4qIkNHkvPGktzzXexsFw==", + "dependencies": { + "regenerator-runtime": "^0.14.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@types/node": { + "version": "20.11.21", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.11.21.tgz", + "integrity": "sha512-/ySDLGscFPNasfqStUuWWPfL78jompfIoVzLJPVVAHBh6rpG68+pI2Gk+fNLeI8/f1yPYL4s46EleVIc20F1Ow==", + "dependencies": { + "undici-types": "~5.26.4" + } + }, + "node_modules/@types/readable-stream": { + "version": "4.0.10", + "resolved": "https://registry.npmjs.org/@types/readable-stream/-/readable-stream-4.0.10.tgz", + "integrity": "sha512-AbUKBjcC8SHmImNi4yK2bbjogQlkFSg7shZCcicxPQapniOlajG8GCc39lvXzCWX4lLRRs7DM3VAeSlqmEVZUA==", + "dependencies": { + "@types/node": "*", + "safe-buffer": "~5.1.1" + } + }, + "node_modules/@types/ws": { + "version": "8.5.10", + "resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.5.10.tgz", + "integrity": "sha512-vmQSUcfalpIq0R9q7uTo2lXs6eGIpt9wtnLdMv9LVpIjCA/+ufZRozlVoVelIYixx1ugCBKDhn89vnsEGOCx9A==", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/abort-controller": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/abort-controller/-/abort-controller-3.0.0.tgz", + "integrity": "sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==", + "dependencies": { + "event-target-shim": "^5.0.0" + }, + "engines": { + "node": ">=6.5" + } + }, + "node_modules/base64-js": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", + "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/bl": { + "version": "6.0.11", + "resolved": "https://registry.npmjs.org/bl/-/bl-6.0.11.tgz", + "integrity": "sha512-Ok/NWrEA0mlEEbWzckkZVLq6Nv1m2xZ+i9Jq5hZ9Ph/YEcP5dExqls9wUzpluhQRPzdeT8oZNOXAytta6YN8pQ==", + "dependencies": { + "@types/readable-stream": "^4.0.0", + "buffer": "^6.0.3", + "inherits": "^2.0.4", + "readable-stream": "^4.2.0" + } + }, + "node_modules/buffer": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz", + "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "dependencies": { + "base64-js": "^1.3.1", + "ieee754": "^1.2.1" + } + }, + "node_modules/buffer-from": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", + "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==" + }, + "node_modules/commist": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/commist/-/commist-3.2.0.tgz", + "integrity": "sha512-4PIMoPniho+LqXmpS5d3NuGYncG6XWlkBSVGiWycL22dd42OYdUGil2CWuzklaJoNxyxUSpO4MKIBU94viWNAw==" + }, + "node_modules/concat-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-2.0.0.tgz", + "integrity": "sha512-MWufYdFw53ccGjCA+Ol7XJYpAlW6/prSMzuPOTRnJGcGzuhLn4Scrz7qf6o8bROZ514ltazcIFJZevcfbo0x7A==", + "engines": [ + "node >= 6.0" + ], + "dependencies": { + "buffer-from": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^3.0.2", + "typedarray": "^0.0.6" + } + }, + "node_modules/concat-stream/node_modules/readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/event-target-shim": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/event-target-shim/-/event-target-shim-5.0.1.tgz", + "integrity": "sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==", + "engines": { + "node": ">=6" + } + }, + "node_modules/events": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz", + "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==", + "engines": { + "node": ">=0.8.x" + } + }, + "node_modules/fast-unique-numbers": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/fast-unique-numbers/-/fast-unique-numbers-9.0.0.tgz", + "integrity": "sha512-lgIjiflW23W7qgagregmo5FFzM+m4/dWaDUVneRi2AV7o2k5npggeEX7srSKlYfJU9fKXvQV2Gzk3272fJT65w==", + "dependencies": { + "@babel/runtime": "^7.23.9", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.2.0" + } + }, + "node_modules/find-exec": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/find-exec/-/find-exec-1.0.3.tgz", + "integrity": "sha512-gnG38zW90mS8hm5smNcrBnakPEt+cGJoiMkJwCU0IYnEb0H2NQk0NIljhNW+48oniCriFek/PH6QXbwsJo/qug==", + "dependencies": { + "shell-quote": "^1.8.1" + } + }, + "node_modules/help-me": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/help-me/-/help-me-5.0.0.tgz", + "integrity": "sha512-7xgomUX6ADmcYzFik0HzAxh/73YlKR9bmFzf51CZwR+b6YtzU2m0u49hQCqV6SvlqIqsaxovfwdvbnsw3b/zpg==" + }, + "node_modules/ieee754": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", + "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" + }, + "node_modules/js-sdsl": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/js-sdsl/-/js-sdsl-4.3.0.tgz", + "integrity": "sha512-mifzlm2+5nZ+lEcLJMoBK0/IH/bDg8XnJfd/Wq6IP+xoCjLZsTOnV2QpxlVbX9bMnkl5PdEjNtBJ9Cj1NjifhQ==", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/js-sdsl" + } + }, + "node_modules/lru-cache": { + "version": "10.2.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.2.0.tgz", + "integrity": "sha512-2bIM8x+VAf6JT4bKAljS1qUWgMsqZRPGJS6FSahIMPVvctcNhyVp7AJu7quxOW9jwkryBReKZY5tY5JYv2n/7Q==", + "engines": { + "node": "14 || >=16.14" + } + }, + "node_modules/minimist": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", + "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/mqtt": { + "version": "5.3.6", + "resolved": "https://registry.npmjs.org/mqtt/-/mqtt-5.3.6.tgz", + "integrity": "sha512-3XeyCdHRFf3zZdUUBt/pqprKPtUABc8O4ZGPGs2QPO4sPNTnJels8U2UtBtMt09QCgpUmw8gLTLy2R7verR7kQ==", + "dependencies": { + "@types/readable-stream": "^4.0.5", + "@types/ws": "^8.5.9", + "commist": "^3.2.0", + "concat-stream": "^2.0.0", + "debug": "^4.3.4", + "help-me": "^5.0.0", + "lru-cache": "^10.0.1", + "minimist": "^1.2.8", + "mqtt": "^5.2.0", + "mqtt-packet": "^9.0.0", + "number-allocator": "^1.0.14", + "readable-stream": "^4.4.2", + "reinterval": "^1.1.0", + "rfdc": "^1.3.0", + "split2": "^4.2.0", + "worker-timers": "^7.0.78", + "ws": "^8.14.2" + }, + "bin": { + "mqtt": "build/bin/mqtt.js", + "mqtt_pub": "build/bin/pub.js", + "mqtt_sub": "build/bin/sub.js" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/mqtt-packet": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/mqtt-packet/-/mqtt-packet-9.0.0.tgz", + "integrity": "sha512-8v+HkX+fwbodsWAZIZTI074XIoxVBOmPeggQuDFCGg1SqNcC+uoRMWu7J6QlJPqIUIJXmjNYYHxBBLr1Y/Df4w==", + "dependencies": { + "bl": "^6.0.8", + "debug": "^4.3.4", + "process-nextick-args": "^2.0.1" + } + }, + "node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + }, + "node_modules/number-allocator": { + "version": "1.0.14", + "resolved": "https://registry.npmjs.org/number-allocator/-/number-allocator-1.0.14.tgz", + "integrity": "sha512-OrL44UTVAvkKdOdRQZIJpLkAdjXGTRda052sN4sO77bKEzYYqWKMBjQvrJFzqygI99gL6Z4u2xctPW1tB8ErvA==", + "dependencies": { + "debug": "^4.3.1", + "js-sdsl": "4.3.0" + } + }, + "node_modules/play-sound": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/play-sound/-/play-sound-1.1.6.tgz", + "integrity": "sha512-09eO4QiXNFXJffJaOW5P6x6F5RLihpLUkXttvUZeWml0fU6x6Zp7AjG9zaeMpgH2ZNvq4GR1ytB22ddYcqJIZA==", + "dependencies": { + "find-exec": "1.0.3" + } + }, + "node_modules/process": { + "version": "0.11.10", + "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz", + "integrity": "sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A==", + "engines": { + "node": ">= 0.6.0" + } + }, + "node_modules/process-nextick-args": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==" + }, + "node_modules/readable-stream": { + "version": "4.5.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-4.5.2.tgz", + "integrity": "sha512-yjavECdqeZ3GLXNgRXgeQEdz9fvDDkNKyHnbHRFtOr7/LcfgBcmct7t/ET+HaCTqfh06OzoAxrkN/IfjJBVe+g==", + "dependencies": { + "abort-controller": "^3.0.0", + "buffer": "^6.0.3", + "events": "^3.3.0", + "process": "^0.11.10", + "string_decoder": "^1.3.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + } + }, + "node_modules/regenerator-runtime": { + "version": "0.14.1", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.14.1.tgz", + "integrity": "sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==" + }, + "node_modules/reinterval": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/reinterval/-/reinterval-1.1.0.tgz", + "integrity": "sha512-QIRet3SYrGp0HUHO88jVskiG6seqUGC5iAG7AwI/BV4ypGcuqk9Du6YQBUOUqm9c8pw1eyLoIaONifRua1lsEQ==" + }, + "node_modules/rfdc": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.3.1.tgz", + "integrity": "sha512-r5a3l5HzYlIC68TpmYKlxWjmOP6wiPJ1vWv2HeLhNsRZMrCkxeqxiHlQ21oXmQ4F3SiryXBHhAD7JZqvOJjFmg==" + }, + "node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + }, + "node_modules/shell-quote": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.8.1.tgz", + "integrity": "sha512-6j1W9l1iAs/4xYBI1SYOVZyFcCis9b4KCLQ8fgAGG07QvzaRLVVRQvAy85yNmmZSjYjg4MWh4gNvlPujU/5LpA==", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/split2": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/split2/-/split2-4.2.0.tgz", + "integrity": "sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg==", + "engines": { + "node": ">= 10.x" + } + }, + "node_modules/string_decoder": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", + "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", + "dependencies": { + "safe-buffer": "~5.2.0" + } + }, + "node_modules/string_decoder/node_modules/safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==" + }, + "node_modules/typedarray": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", + "integrity": "sha512-/aCDEGatGvZ2BIk+HmLf4ifCJFwvKFNb9/JeZPMulfgFracn9QFcAf5GO8B/mweUjSoblS5In0cWhqpfs/5PQA==" + }, + "node_modules/undici-types": { + "version": "5.26.5", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz", + "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==" + }, + "node_modules/util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==" + }, + "node_modules/worker-timers": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/worker-timers/-/worker-timers-7.1.2.tgz", + "integrity": "sha512-iqhXt5+Mc3u2nHj3G/w/E9pXqhlueniA2NlyelB/MQSHQuuW2fmmZGkveAv6yi4SSZvrpbveBBlqPSZ0MDCLww==", + "dependencies": { + "@babel/runtime": "^7.23.9", + "tslib": "^2.6.2", + "worker-timers-broker": "^6.1.2", + "worker-timers-worker": "^7.0.66" + } + }, + "node_modules/worker-timers-broker": { + "version": "6.1.2", + "resolved": "https://registry.npmjs.org/worker-timers-broker/-/worker-timers-broker-6.1.2.tgz", + "integrity": "sha512-slFupigW5vtkGJ1VBCxYPwXFFRmvfioh02bCltBhbMkt3fFnkAbKBCg61pNTetlD0RAsP09mqx/FB0f4UMoHNw==", + "dependencies": { + "@babel/runtime": "^7.23.9", + "fast-unique-numbers": "^9.0.0", + "tslib": "^2.6.2", + "worker-timers-worker": "^7.0.66" + } + }, + "node_modules/worker-timers-worker": { + "version": "7.0.66", + "resolved": "https://registry.npmjs.org/worker-timers-worker/-/worker-timers-worker-7.0.66.tgz", + "integrity": "sha512-VCLa0H5K9fE2DVI/9r5zDuFrMQIpNL3UD/h4Ui49fIiRBTgv1Sqe0RM12brr83anBsm103aUQkvKvCBL+KpNtg==", + "dependencies": { + "@babel/runtime": "^7.23.9", + "tslib": "^2.6.2" + } + }, + "node_modules/ws": { + "version": "8.16.0", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.16.0.tgz", + "integrity": "sha512-HS0c//TP7Ina87TfiPUz1rQzMhHrl/SG2guqRcTOIUYD2q8uhUdNHZYJUaQ8aTGPzCh+c6oawMKW35nFl1dxyQ==", + "engines": { + "node": ">=10.0.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": ">=5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + } + } +} diff --git a/VNode/soundplayer-mqtt/package.json b/VNode/soundplayer-mqtt/package.json new file mode 100644 index 00000000..aa65b003 --- /dev/null +++ b/VNode/soundplayer-mqtt/package.json @@ -0,0 +1,6 @@ +{ + "dependencies": { + "mqtt": "^5.3.6", + "play-sound": "^1.1.6" + } +} diff --git a/VNode/soundplayer-mqtt/soundplayer.js b/VNode/soundplayer-mqtt/soundplayer.js new file mode 100644 index 00000000..313769f0 --- /dev/null +++ b/VNode/soundplayer-mqtt/soundplayer.js @@ -0,0 +1,54 @@ +const config = require('./config') +const player = require('play-sound')(); +const mqtt = require('mqtt') + +// Créer une instance de client MQTT +const client = mqtt.connect(config.mqttBrokerUrl); + + +const messages_sounds_maps = { + 'success': "./assets/sounds/success.mp3", + 'fail': "./assets/sounds/error.mp3", + 'timer': "./assets/sounds/timer.mp3", + 'bell': "/home/lol/Src/fablab/brain-blast-services/src/assets/sounds/coin.wav", + 'applause': "./assets/sound/clap.mp3" +} + +// Gérer les événements de connexion +client.on('connect', function () { + console.log('Connecté au broker MQTT') + + // S'abonner à un topic + client.subscribe('/sound/playsound', function (err) { + if (err) { + console.error('Erreur lors de la souscription au topic', err) + } else { + console.log('Souscription au topic réussie') + } + }); +}); + +// Gérer les messages entrants +client.on('message', function (topic, message) { + let obj = JSON.parse(message) + const audioFile = messages_sounds_maps[obj] + console.log('Message reçu sur le topic', topic, ':', obj) + console.log('Je vais lire le fichier : ', audioFile) + if (audioFile) { + // Jouer le fichier audio correspondant au message reçu + player.play(audioFile, function(err){ + if (err) { + console.error('Erreur lors de la lecture du fichier audio', err); + } else { + console.log('Fichier audio lu avec succès'); + } + }); + } else { + console.warn('Aucun fichier audio correspondant au message reçu'); + } +}); + +// Gérer les erreurs de connexion +client.on('error', function (error) { + console.error('Erreur de connexion au broker MQTT', error); +}); \ No newline at end of file