pub const ext = @import("ext.zig");
const nice = @This();

const std = @import("std");
const compat = @import("compat");
const gio = @import("gio2");
const gobject = @import("gobject2");
const glib = @import("glib2");
const gmodule = @import("gmodule2");
/// The `nice.Agent` is the main GObject of the libnice library and represents
/// the ICE agent.
pub const Agent = opaque {
    pub const Parent = gobject.Object;
    pub const Implements = [_]type{};
    pub const Class = nice.AgentClass;
    pub const virtual_methods = struct {};

    pub const properties = struct {
        /// This property defines whether receive/send operations over a TCP socket, in
        /// reliable mode, are considered as packetized or as bytestream.
        /// In unreliable mode, every send/recv is considered as packetized, and
        /// this property is ignored and cannot be set.
        /// <para>
        /// In reliable mode, this property will always return `TRUE` in the
        /// `NICE_COMPATIBILITY_GOOGLE` compatibility mode.
        /// </para>
        /// If the property is `TRUE`, the stream is considered in bytestream mode
        /// and data can be read with any receive size. If the property is `FALSE`, then
        /// the stream is considered packetized and each receive will return one packet
        /// of the same size as what was sent from the peer. If in packetized mode,
        /// then doing a receive with a size smaller than the packet, will cause the
        /// remaining bytes in the packet to be dropped, breaking the reliability
        /// of the stream.
        pub const bytestream_tcp = struct {
            pub const name = "bytestream-tcp";

            pub const Type = c_int;
        };

        /// Whether to omit performing retransmissions and wait for a response for the 0-lifetime
        /// refresh request that is sent by `nice.Agent.closeAsync`. This favors a quick shutdown of
        /// the agent at the risk of lingering TURN server port allocations.
        pub const close_forced = struct {
            pub const name = "close-forced";

            pub const Type = c_int;
        };

        /// The Nice agent can work in various compatibility modes depending on
        /// what the application/peer needs.
        /// <para> See also: `nice.Compatibility`</para>
        pub const compatibility = struct {
            pub const name = "compatibility";

            pub const Type = c_uint;
        };

        /// Whether to perform periodic consent freshness checks as specified in
        /// RFC 7675.  When `TRUE`, the agent will periodically send binding requests
        /// to the peer to maintain the consent to send with the peer.  On receipt
        /// of any authenticated error response, a component will immediately move
        /// to the failed state.
        ///
        /// Setting this property to `TRUE` implies that 'keepalive-conncheck' should
        /// be `TRUE` as well.
        pub const consent_freshness = struct {
            pub const name = "consent-freshness";

            pub const Type = c_int;
        };

        /// Whether the agent has the controlling role. This property should
        /// be modified before gathering candidates, any modification occuring
        /// later will be hold until ICE is restarted.
        pub const controlling_mode = struct {
            pub const name = "controlling-mode";

            pub const Type = c_int;
        };

        /// Force all traffic to go through a relay for added privacy, this
        /// allows hiding the local IP address. When this is enabled, so
        /// local candidates are available before relay servers have been set
        /// with `nice.Agent.setRelayInfo`.
        pub const force_relay = struct {
            pub const name = "force-relay";

            pub const Type = c_int;
        };

        pub const full_mode = struct {
            pub const name = "full-mode";

            pub const Type = c_int;
        };

        /// Whether the agent should use ICE-TCP when gathering candidates.
        /// If the option is disabled, no TCP candidates will be generated. If the
        /// agent is in reliable mode, then pseudotcp will need to be used over UDP
        /// candidates.
        /// <para>
        /// This option should be set before gathering candidates and should not be
        /// modified afterwards.
        /// </para>
        /// The `nice.Agent.properties.ice`-tcp property can be set at the same time as the
        /// `nice.Agent.properties.ice`-udp property, but both cannot be unset at the same time.
        /// If `nice.Agent.properties.ice`-udp is set to `FALSE`, then this property cannot be set
        /// to `FALSE` as well.
        /// <note>
        ///    <para>
        ///    ICE-TCP is only supported for `NICE_COMPATIBILITY_RFC5245`,
        ///    `NICE_COMPATIBILITY_OC2007` and `NICE_COMPATIBILITY_OC2007R2` compatibility
        ///    modes.
        ///    </para>
        /// </note>
        pub const ice_tcp = struct {
            pub const name = "ice-tcp";

            pub const Type = c_int;
        };

        /// Whether to perform Trickle ICE as per draft-ietf-ice-trickle-ice-21.
        /// When `TRUE`, the agent will postpone changing a component state to
        /// `NICE_COMPONENT_STATE_FAILED` until `nice.Agent.peerCandidateGatheringDone`
        /// has been called with the ID of the component's stream.
        pub const ice_trickle = struct {
            pub const name = "ice-trickle";

            pub const Type = c_int;
        };

        /// Whether the agent should use ICE-UDP when gathering candidates.
        /// If the option is disabled, no UDP candidates will be generated. If the
        /// agent is in reliable mode, then pseudotcp will not be used since pseudotcp
        /// works on top of UDP candidates.
        /// <para>
        /// This option should be set before gathering candidates and should not be
        /// modified afterwards.
        /// </para>
        /// The `nice.Agent.properties.ice`-udp property can be set at the same time as the
        /// `nice.Agent.properties.ice`-tcp property, but both cannot be unset at the same time.
        /// If `nice.Agent.properties.ice`-tcp is set to `FALSE`, then this property cannot be set
        /// to `FALSE` as well.
        pub const ice_udp = struct {
            pub const name = "ice-udp";

            pub const Type = c_int;
        };

        /// A final timeout in msec, launched when the agent becomes idle,
        /// before stopping its activity.
        ///
        /// This timer will delay the decision to set a component as failed.
        /// This delay is added to reduce the chance to see the agent receiving
        /// new stun activity just after the conncheck list has been declared
        /// failed (some valid pairs, no nominated pair, and no in-progress
        /// pairs), reactiviting conncheck activity, and causing a (valid)
        /// state transitions like that: connecting -> failed -> connecting ->
        /// connected -> ready.  Such transitions are not buggy per-se, but may
        /// break the test-suite, that counts precisely the number of time each
        /// state has been set, and doesnt expect these transcient failed
        /// states.
        ///
        /// This timer is also useful when the agent is in controlled mode and
        /// the other controlling peer takes some time to elect its nominated
        /// pair (this may be the case for SfB peers).
        ///
        /// This timer is *NOT* part if the RFC5245, as this situation is not
        /// covered in sect 8.1.2 "Updating States", but deals with a real
        /// use-case, where a controlled agent can not wait forever for the
        /// other peer to make a nomination decision.
        ///
        /// Also note that the value of this timeout will not delay the
        /// emission of 'connected' and 'ready' agent signals, and will not
        /// slow down the behaviour of the agent when the peer agent works
        /// in a timely manner.
        pub const idle_timeout = struct {
            pub const name = "idle-timeout";

            pub const Type = c_uint;
        };

        /// Use binding requests as keepalives instead of binding
        /// indications. This means that the keepalives may time out which
        /// will change the component state to `NICE_COMPONENT_STATE_FAILED`.
        ///
        /// Enabing this is a slight violation of RFC 5245 section 10 which
        /// recommends using Binding Indications for keepalives.
        ///
        /// This is always enabled if the compatibility mode is
        /// `NICE_COMPATIBILITY_GOOGLE`.
        ///
        /// This is always enabled if the 'consent-freshness' property is `TRUE`
        pub const keepalive_conncheck = struct {
            pub const name = "keepalive-conncheck";

            pub const Type = c_int;
        };

        /// A GLib main context is needed for all timeouts used by libnice.
        /// This is a property being set by the `nice.Agent.new` call.
        pub const main_context = struct {
            pub const name = "main-context";

            pub const Type = ?*anyopaque;
        };

        pub const max_connectivity_checks = struct {
            pub const name = "max-connectivity-checks";

            pub const Type = c_uint;
        };

        /// The nomination mode used in the ICE specification for describing
        /// the selection of valid pairs to be used upstream.
        /// <para> See also: `nice.NominationMode` </para>
        pub const nomination_mode = struct {
            pub const name = "nomination-mode";

            pub const Type = @compileError("no type information available");
        };

        /// Optional extra headers to append to the HTTP proxy CONNECT request.
        /// Provided as key/value-pairs in hash table corresponding to
        /// header-name/header-value.
        pub const proxy_extra_headers = struct {
            pub const name = "proxy-extra-headers";

            pub const Type = ?*glib.HashTable;
        };

        /// The proxy server IP used to bypass a proxy firewall
        pub const proxy_ip = struct {
            pub const name = "proxy-ip";

            pub const Type = ?[*:0]u8;
        };

        /// The password used to authenticate with the proxy
        pub const proxy_password = struct {
            pub const name = "proxy-password";

            pub const Type = ?[*:0]u8;
        };

        /// The proxy server port used to bypass a proxy firewall
        pub const proxy_port = struct {
            pub const name = "proxy-port";

            pub const Type = c_uint;
        };

        /// The type of proxy set in the proxy-ip property
        pub const proxy_type = struct {
            pub const name = "proxy-type";

            pub const Type = c_uint;
        };

        /// The username used to authenticate with the proxy
        pub const proxy_username = struct {
            pub const name = "proxy-username";

            pub const Type = ?[*:0]u8;
        };

        /// Whether the agent is providing a reliable transport of messages (through
        /// ICE-TCP or PseudoTCP over ICE-UDP)
        pub const reliable = struct {
            pub const name = "reliable";

            pub const Type = c_int;
        };

        /// The initial timeout (msecs) of the STUN binding requests
        /// used in the gathering stage, to find our local candidates.
        /// This property is described as 'RTO' in the RFC 5389 and RFC 5245.
        /// This timeout is doubled for each retransmission, until
        /// `nice.Agent.properties.stun`-max-retransmissions have been done,
        /// with an exception for the last restransmission, where the timeout is
        /// divided by two instead (RFC 5389 indicates that a customisable
        /// multiplier 'Rm' to 'RTO' should be used).
        pub const stun_initial_timeout = struct {
            pub const name = "stun-initial-timeout";

            pub const Type = c_uint;
        };

        /// The maximum number of retransmissions of the STUN binding requests
        /// used in the gathering stage, to find our local candidates, and used
        /// in the connection check stage, to test the validity of each
        /// constructed pair. This property is described as 'Rc' in the RFC
        /// 5389, with a default value of 7. The timeout of each STUN request
        /// is doubled for each retransmission, so the choice of this value has
        /// a direct impact on the time needed to move from the CONNECTED state
        /// to the READY state, and on the time needed to complete the GATHERING
        /// state.
        pub const stun_max_retransmissions = struct {
            pub const name = "stun-max-retransmissions";

            pub const Type = c_uint;
        };

        pub const stun_pacing_timer = struct {
            pub const name = "stun-pacing-timer";

            pub const Type = c_uint;
        };

        /// The initial timeout of the STUN binding requests used
        /// for a reliable timer.
        pub const stun_reliable_timeout = struct {
            pub const name = "stun-reliable-timeout";

            pub const Type = c_uint;
        };

        pub const stun_server = struct {
            pub const name = "stun-server";

            pub const Type = ?[*:0]u8;
        };

        pub const stun_server_port = struct {
            pub const name = "stun-server-port";

            pub const Type = c_uint;
        };

        /// Support RENOMINATION STUN attribute proposed here:
        /// https://tools.ietf.org/html/draft-thatcher-ice-renomination-00 As
        /// soon as RENOMINATION attribute is received from remote
        /// candidate's address, corresponding candidates pair gets
        /// selected. This is specific to Google Chrome/libWebRTC.
        pub const support_renomination = struct {
            pub const name = "support-renomination";

            pub const Type = c_int;
        };

        /// Whether the agent should use UPnP to open a port in the router and
        /// get the external IP
        pub const upnp = struct {
            pub const name = "upnp";

            pub const Type = c_int;
        };

        /// The maximum amount of time (in milliseconds) to wait for UPnP discovery to
        /// finish before signaling the `nice.Agent.signals.candidate`-gathering-done signal
        pub const upnp_timeout = struct {
            pub const name = "upnp-timeout";

            pub const Type = c_uint;
        };
    };

    pub const signals = struct {
        /// This signal is fired whenever a stream has finished gathering its
        /// candidates after a call to `nice.Agent.gatherCandidates`
        pub const candidate_gathering_done = struct {
            pub const name = "candidate-gathering-done";

            pub fn connect(p_instance: anytype, comptime P_Data: type, p_callback: *const fn (@TypeOf(p_instance), p_stream_id: c_uint, P_Data) callconv(.c) void, p_data: P_Data, p_options: gobject.ext.ConnectSignalOptions(P_Data)) c_ulong {
                return gobject.signalConnectClosureById(
                    @ptrCast(@alignCast(gobject.ext.as(Agent, p_instance))),
                    gobject.signalLookup("candidate-gathering-done", Agent.getGObjectType()),
                    glib.quarkFromString(p_options.detail orelse null),
                    gobject.CClosure.new(@ptrCast(p_callback), p_data, @ptrCast(p_options.destroyData)),
                    @intFromBool(p_options.after),
                );
            }
        };

        /// This signal is fired whenever a component’s state changes. There are many
        /// valid state transitions.
        ///
        /// ![State transition diagram](states.png)
        pub const component_state_changed = struct {
            pub const name = "component-state-changed";

            pub fn connect(p_instance: anytype, comptime P_Data: type, p_callback: *const fn (@TypeOf(p_instance), p_stream_id: c_uint, p_component_id: c_uint, p_state: c_uint, P_Data) callconv(.c) void, p_data: P_Data, p_options: gobject.ext.ConnectSignalOptions(P_Data)) c_ulong {
                return gobject.signalConnectClosureById(
                    @ptrCast(@alignCast(gobject.ext.as(Agent, p_instance))),
                    gobject.signalLookup("component-state-changed", Agent.getGObjectType()),
                    glib.quarkFromString(p_options.detail orelse null),
                    gobject.CClosure.new(@ptrCast(p_callback), p_data, @ptrCast(p_options.destroyData)),
                    @intFromBool(p_options.after),
                );
            }
        };

        /// This signal is fired when we received our first binding request from
        /// the peer.
        pub const initial_binding_request_received = struct {
            pub const name = "initial-binding-request-received";

            pub fn connect(p_instance: anytype, comptime P_Data: type, p_callback: *const fn (@TypeOf(p_instance), p_stream_id: c_uint, P_Data) callconv(.c) void, p_data: P_Data, p_options: gobject.ext.ConnectSignalOptions(P_Data)) c_ulong {
                return gobject.signalConnectClosureById(
                    @ptrCast(@alignCast(gobject.ext.as(Agent, p_instance))),
                    gobject.signalLookup("initial-binding-request-received", Agent.getGObjectType()),
                    glib.quarkFromString(p_options.detail orelse null),
                    gobject.CClosure.new(@ptrCast(p_callback), p_data, @ptrCast(p_options.destroyData)),
                    @intFromBool(p_options.after),
                );
            }
        };

        /// This signal is fired when the agent discovers a new local candidate.
        /// When this signal is emitted, a matching `nice.Agent.signals.new`-candidate-full is
        /// also emitted with the candidate.
        ///
        /// See also: `nice.Agent.signals.candidate`-gathering-done,
        /// `nice.Agent.signals.new`-candidate-full
        pub const new_candidate = struct {
            pub const name = "new-candidate";

            pub fn connect(p_instance: anytype, comptime P_Data: type, p_callback: *const fn (@TypeOf(p_instance), p_stream_id: c_uint, p_component_id: c_uint, p_foundation: [*:0]u8, P_Data) callconv(.c) void, p_data: P_Data, p_options: gobject.ext.ConnectSignalOptions(P_Data)) c_ulong {
                return gobject.signalConnectClosureById(
                    @ptrCast(@alignCast(gobject.ext.as(Agent, p_instance))),
                    gobject.signalLookup("new-candidate", Agent.getGObjectType()),
                    glib.quarkFromString(p_options.detail orelse null),
                    gobject.CClosure.new(@ptrCast(p_callback), p_data, @ptrCast(p_options.destroyData)),
                    @intFromBool(p_options.after),
                );
            }
        };

        /// This signal is fired when the agent discovers a new local candidate.
        /// When this signal is emitted, a matching `nice.Agent.signals.new`-candidate is
        /// also emitted with the candidate's foundation.
        ///
        /// See also: `nice.Agent.signals.candidate`-gathering-done,
        /// `nice.Agent.signals.new`-candidate
        pub const new_candidate_full = struct {
            pub const name = "new-candidate-full";

            pub fn connect(p_instance: anytype, comptime P_Data: type, p_callback: *const fn (@TypeOf(p_instance), p_candidate: *nice.Candidate, P_Data) callconv(.c) void, p_data: P_Data, p_options: gobject.ext.ConnectSignalOptions(P_Data)) c_ulong {
                return gobject.signalConnectClosureById(
                    @ptrCast(@alignCast(gobject.ext.as(Agent, p_instance))),
                    gobject.signalLookup("new-candidate-full", Agent.getGObjectType()),
                    glib.quarkFromString(p_options.detail orelse null),
                    gobject.CClosure.new(@ptrCast(p_callback), p_data, @ptrCast(p_options.destroyData)),
                    @intFromBool(p_options.after),
                );
            }
        };

        /// This signal is fired when the agent discovers a new remote
        /// candidate.  This can happen with peer reflexive candidates.  When
        /// this signal is emitted, a matching
        /// `nice.Agent.signals.new`-remote-candidate-full is also emitted with the
        /// candidate.
        ///
        /// See also: `nice.Agent.signals.new`-remote-candidate-full
        pub const new_remote_candidate = struct {
            pub const name = "new-remote-candidate";

            pub fn connect(p_instance: anytype, comptime P_Data: type, p_callback: *const fn (@TypeOf(p_instance), p_stream_id: c_uint, p_component_id: c_uint, p_foundation: [*:0]u8, P_Data) callconv(.c) void, p_data: P_Data, p_options: gobject.ext.ConnectSignalOptions(P_Data)) c_ulong {
                return gobject.signalConnectClosureById(
                    @ptrCast(@alignCast(gobject.ext.as(Agent, p_instance))),
                    gobject.signalLookup("new-remote-candidate", Agent.getGObjectType()),
                    glib.quarkFromString(p_options.detail orelse null),
                    gobject.CClosure.new(@ptrCast(p_callback), p_data, @ptrCast(p_options.destroyData)),
                    @intFromBool(p_options.after),
                );
            }
        };

        /// This signal is fired when the agent discovers a new remote candidate.
        /// This can happen with peer reflexive candidates.
        /// When this signal is emitted, a matching `nice.Agent.signals.new`-remote-candidate is
        /// also emitted with the candidate's foundation.
        ///
        /// See also: `nice.Agent.signals.new`-remote-candidate
        pub const new_remote_candidate_full = struct {
            pub const name = "new-remote-candidate-full";

            pub fn connect(p_instance: anytype, comptime P_Data: type, p_callback: *const fn (@TypeOf(p_instance), p_candidate: *nice.Candidate, P_Data) callconv(.c) void, p_data: P_Data, p_options: gobject.ext.ConnectSignalOptions(P_Data)) c_ulong {
                return gobject.signalConnectClosureById(
                    @ptrCast(@alignCast(gobject.ext.as(Agent, p_instance))),
                    gobject.signalLookup("new-remote-candidate-full", Agent.getGObjectType()),
                    glib.quarkFromString(p_options.detail orelse null),
                    gobject.CClosure.new(@ptrCast(p_callback), p_data, @ptrCast(p_options.destroyData)),
                    @intFromBool(p_options.after),
                );
            }
        };

        /// This signal is fired once a candidate pair is selected for data
        /// transfer for a stream's component This is emitted along with
        /// `nice.Agent.signals.new`-selected-pair-full which has the whole candidate,
        /// the Foundation of a Candidate is not a unique identifier.
        ///
        /// See also: `nice.Agent.signals.new`-selected-pair-full
        pub const new_selected_pair = struct {
            pub const name = "new-selected-pair";

            pub fn connect(p_instance: anytype, comptime P_Data: type, p_callback: *const fn (@TypeOf(p_instance), p_stream_id: c_uint, p_component_id: c_uint, p_lfoundation: [*:0]u8, p_rfoundation: [*:0]u8, P_Data) callconv(.c) void, p_data: P_Data, p_options: gobject.ext.ConnectSignalOptions(P_Data)) c_ulong {
                return gobject.signalConnectClosureById(
                    @ptrCast(@alignCast(gobject.ext.as(Agent, p_instance))),
                    gobject.signalLookup("new-selected-pair", Agent.getGObjectType()),
                    glib.quarkFromString(p_options.detail orelse null),
                    gobject.CClosure.new(@ptrCast(p_callback), p_data, @ptrCast(p_options.destroyData)),
                    @intFromBool(p_options.after),
                );
            }
        };

        /// This signal is fired once a candidate pair is selected for data
        /// transfer for a stream's component. This is emitted along with
        /// `nice.Agent.signals.new`-selected-pair.
        ///
        /// See also: `nice.Agent.signals.new`-selected-pair
        pub const new_selected_pair_full = struct {
            pub const name = "new-selected-pair-full";

            pub fn connect(p_instance: anytype, comptime P_Data: type, p_callback: *const fn (@TypeOf(p_instance), p_stream_id: c_uint, p_component_id: c_uint, p_lcandidate: *nice.Candidate, p_rcandidate: *nice.Candidate, P_Data) callconv(.c) void, p_data: P_Data, p_options: gobject.ext.ConnectSignalOptions(P_Data)) c_ulong {
                return gobject.signalConnectClosureById(
                    @ptrCast(@alignCast(gobject.ext.as(Agent, p_instance))),
                    gobject.signalLookup("new-selected-pair-full", Agent.getGObjectType()),
                    glib.quarkFromString(p_options.detail orelse null),
                    gobject.CClosure.new(@ptrCast(p_callback), p_data, @ptrCast(p_options.destroyData)),
                    @intFromBool(p_options.after),
                );
            }
        };

        /// This signal is fired on `nice.Agent` when the underlying transport becomes writable.
        /// This signal is only emitted when the `nice.Agent.send` function returns less
        /// bytes than requested to send (or -1) and once when the connection
        /// is established.
        ///
        /// Note: Since 0.1.23 this signal also fires for non-reliable transports.
        /// See https://gitlab.freedesktop.org/libnice/libnice/-/issues/202.
        pub const reliable_transport_writable = struct {
            pub const name = "reliable-transport-writable";

            pub fn connect(p_instance: anytype, comptime P_Data: type, p_callback: *const fn (@TypeOf(p_instance), p_stream_id: c_uint, p_component_id: c_uint, P_Data) callconv(.c) void, p_data: P_Data, p_options: gobject.ext.ConnectSignalOptions(P_Data)) c_ulong {
                return gobject.signalConnectClosureById(
                    @ptrCast(@alignCast(gobject.ext.as(Agent, p_instance))),
                    gobject.signalLookup("reliable-transport-writable", Agent.getGObjectType()),
                    glib.quarkFromString(p_options.detail orelse null),
                    gobject.CClosure.new(@ptrCast(p_callback), p_data, @ptrCast(p_options.destroyData)),
                    @intFromBool(p_options.after),
                );
            }
        };

        /// This signal is fired whenever one or more streams are removed from the
        /// `agent`.
        pub const streams_removed = struct {
            pub const name = "streams-removed";

            pub fn connect(p_instance: anytype, comptime P_Data: type, p_callback: *const fn (@TypeOf(p_instance), p_stream_ids: [*]c_uint, P_Data) callconv(.c) void, p_data: P_Data, p_options: gobject.ext.ConnectSignalOptions(P_Data)) c_ulong {
                return gobject.signalConnectClosureById(
                    @ptrCast(@alignCast(gobject.ext.as(Agent, p_instance))),
                    gobject.signalLookup("streams-removed", Agent.getGObjectType()),
                    glib.quarkFromString(p_options.detail orelse null),
                    gobject.CClosure.new(@ptrCast(p_callback), p_data, @ptrCast(p_options.destroyData)),
                    @intFromBool(p_options.after),
                );
            }
        };
    };

    /// Create a new `nice.Agent`.
    /// The returned object must be freed with `gobject.Object.unref`
    extern fn nice_agent_new(p_ctx: *glib.MainContext, p_compat: nice.Compatibility) *nice.Agent;
    pub const new = nice_agent_new;

    /// Create a new `nice.Agent` with parameters that must be be defined at
    /// construction time.
    /// The returned object must be freed with `gobject.Object.unref`
    /// <para> See also: `nice.NominationMode` and `nice.AgentOption`</para>
    extern fn nice_agent_new_full(p_ctx: *glib.MainContext, p_compat: nice.Compatibility, p_flags: nice.AgentOption) *nice.Agent;
    pub const newFull = nice_agent_new_full;

    /// Create a new `nice.Agent` in reliable mode. If the connectivity is established
    /// through ICE-UDP, then a `nice.PseudoTcpSocket` will be transparently used to
    /// ensure reliability of the messages.
    /// The returned object must be freed with `gobject.Object.unref`
    /// <para> See also: `nice.Agent.signals.reliable`-transport-writable </para>
    extern fn nice_agent_new_reliable(p_ctx: *glib.MainContext, p_compat: nice.Compatibility) *nice.Agent;
    pub const newReliable = nice_agent_new_reliable;

    /// Add a local address from which to derive local host candidates for
    /// candidate gathering.
    /// <para>
    /// Since 0.0.5, if this method is not called, libnice will automatically
    /// discover the local addresses available
    /// </para>
    ///
    /// See also: `nice.Agent.gatherCandidates`
    extern fn nice_agent_add_local_address(p_agent: *Agent, p_addr: *nice.Address) c_int;
    pub const addLocalAddress = nice_agent_add_local_address;

    /// Adds a data stream to `agent` containing `n_components` components. The
    /// returned stream ID is guaranteed to be positive on success.
    extern fn nice_agent_add_stream(p_agent: *Agent, p_n_components: c_uint) c_uint;
    pub const addStream = nice_agent_add_stream;

    /// Attaches the stream's component's sockets to the Glib Mainloop Context in
    /// order to be notified whenever data becomes available for a component,
    /// and to enable `nice.Agent` to receive STUN messages (during the
    /// establishment of ICE connectivity).
    ///
    /// This must not be used in combination with `nice.Agent.recvMessages` (or
    /// `NiceIOStream` or `NiceInputStream`) on the same stream/component pair.
    ///
    /// Calling `nice.Agent.attachRecv` with a `NULL` `func` will detach any existing
    /// callback and cause reception to be paused for the given stream/component
    /// pair. You must iterate the previously specified `glib.MainContext` sufficiently to
    /// ensure all pending I/O callbacks have been received before calling this
    /// function to unset `func`, otherwise data loss of received packets may occur.
    extern fn nice_agent_attach_recv(p_agent: *Agent, p_stream_id: c_uint, p_component_id: c_uint, p_ctx: *glib.MainContext, p_func: nice.AgentRecvFunc, p_data: ?*anyopaque) c_int;
    pub const attachRecv = nice_agent_attach_recv;

    /// Asynchronously closes resources the agent has allocated on remote servers.
    ///
    /// The agent will call the callback in the current `glib.MainContext` in
    /// which this function is called. The `gio.AsyncResult` in the callback
    /// can be ignored as this operation never fails.
    ///
    /// Calling this function before freeing the agent makes sure the allocated relay
    /// ports aren't left behind on TURN server but properly removed.
    extern fn nice_agent_close_async(p_agent: *Agent, p_callback: ?gio.AsyncReadyCallback, p_callback_data: ?*anyopaque) void;
    pub const closeAsync = nice_agent_close_async;

    /// Notifies the agent that consent to receive has been revoked.  This will
    /// cause the component to fail with 403 'Forbidden' all incoming STUN binding
    /// requests as specified in RFC 7675.
    ///
    /// A stream with a component in the consent-lost state can be reused by
    /// performing an ice restart with `nice.Agent.restart` or
    /// `nice.Agent.restartStream`.
    ///
    /// Calling the function only has an effect when `agent` has been created with
    /// `NICE_AGENT_OPTION_CONSENT_FRESHNESS`.
    extern fn nice_agent_consent_lost(p_agent: *Agent, p_stream_id: c_uint, p_component_id: c_uint) c_int;
    pub const consentLost = nice_agent_consent_lost;

    /// Forget all the relay servers previously added using
    /// `nice.Agent.setRelayInfo`. Currently connected streams will keep
    /// using the relay as long as they have not been restarted and haven't
    /// succesfully negotiated a different path.
    extern fn nice_agent_forget_relays(p_agent: *Agent, p_stream_id: c_uint, p_component_id: c_uint) c_int;
    pub const forgetRelays = nice_agent_forget_relays;

    /// Allocate and start listening on local candidate ports and start the remote
    /// candidate gathering process.
    /// Once done, `nice.Agent.signals.candidate`-gathering-done is called for the stream.
    /// As soon as this function is called, `nice.Agent.signals.new`-candidate signals may be
    /// emitted, even before this function returns.
    ///
    /// `nice.Agent.getLocalCandidates` will only return non-empty results after
    /// calling this function.
    ///
    /// <para>See also: `nice.Agent.addLocalAddress`</para>
    /// <para>See also: `nice.Agent.setPortRange`</para>
    extern fn nice_agent_gather_candidates(p_agent: *Agent, p_stream_id: c_uint) c_int;
    pub const gatherCandidates = nice_agent_gather_candidates;

    /// Generate an SDP string representing a local candidate.
    ///
    /// <para>See also: `nice.Agent.parseRemoteCandidateSdp` </para>
    /// <para>See also: `nice.Agent.generateLocalSdp` </para>
    /// <para>See also: `nice.Agent.generateLocalStreamSdp` </para>
    extern fn nice_agent_generate_local_candidate_sdp(p_agent: *Agent, p_candidate: *nice.Candidate) [*:0]u8;
    pub const generateLocalCandidateSdp = nice_agent_generate_local_candidate_sdp;

    /// Generate an SDP string containing the local candidates and credentials for
    /// all streams and components in the agent.
    ///
    ///  <note>
    ///    <para>
    ///      The SDP will not contain any codec lines and the 'm' line will not list
    ///      any payload types.
    ///    </para>
    ///    <para>
    ///     It is highly recommended to set names on the streams prior to calling this
    ///     function. Unnamed streams will show up as '-' in the 'm' line, but the SDP
    ///     will not be parseable with `nice.Agent.parseRemoteSdp` if a stream is
    ///     unnamed.
    ///    </para>
    ///    <para>
    ///      The default candidate in the SDP will be selected based on the lowest
    ///      priority candidate for the first component.
    ///    </para>
    ///  </note>
    ///
    /// <para>See also: `nice.Agent.setStreamName` </para>
    /// <para>See also: `nice.Agent.parseRemoteSdp` </para>
    /// <para>See also: `nice.Agent.generateLocalStreamSdp` </para>
    /// <para>See also: `nice.Agent.generateLocalCandidateSdp` </para>
    /// <para>See also: `nice.Agent.getDefaultLocalCandidate` </para>
    extern fn nice_agent_generate_local_sdp(p_agent: *Agent) [*:0]u8;
    pub const generateLocalSdp = nice_agent_generate_local_sdp;

    /// Generate an SDP string containing the local candidates and credentials
    /// for a stream.
    ///
    ///  <note>
    ///    <para>
    ///      The SDP will not contain any codec lines and the 'm' line will not list
    ///      any payload types.
    ///    </para>
    ///    <para>
    ///     It is highly recommended to set the name of the stream prior to calling this
    ///     function. Unnamed streams will show up as '-' in the 'm' line.
    ///    </para>
    ///    <para>
    ///      The default candidate in the SDP will be selected based on the lowest
    ///      priority candidate.
    ///    </para>
    ///  </note>
    ///
    /// <para>See also: `nice.Agent.setStreamName` </para>
    /// <para>See also: `nice.Agent.parseRemoteStreamSdp` </para>
    /// <para>See also: `nice.Agent.generateLocalSdp` </para>
    /// <para>See also: `nice.Agent.generateLocalCandidateSdp` </para>
    /// <para>See also: `nice.Agent.getDefaultLocalCandidate` </para>
    extern fn nice_agent_generate_local_stream_sdp(p_agent: *Agent, p_stream_id: c_uint, p_include_non_ice: c_int) [*:0]u8;
    pub const generateLocalStreamSdp = nice_agent_generate_local_stream_sdp;

    /// Retrieves the current state of a component.
    extern fn nice_agent_get_component_state(p_agent: *Agent, p_stream_id: c_uint, p_component_id: c_uint) nice.ComponentState;
    pub const getComponentState = nice_agent_get_component_state;

    /// This helper function will return the recommended default candidate to be
    /// used for non-ICE compatible clients. This will usually be the candidate
    /// with the lowest priority, since it will be the longest path but the one with
    /// the most chances of success.
    /// <note>
    ///      <para>
    ///      This function is only useful in order to manually generate the
    ///      local SDP
    ///      </para>
    /// </note>
    extern fn nice_agent_get_default_local_candidate(p_agent: *Agent, p_stream_id: c_uint, p_component_id: c_uint) *nice.Candidate;
    pub const getDefaultLocalCandidate = nice_agent_get_default_local_candidate;

    /// Gets a `gio.IOStream` wrapper around the given stream and component in
    /// `agent`. The I/O stream will be valid for as long as `stream_id` is valid.
    /// The `gio.InputStream` and `gio.OutputStream` implement `gio.PollableInputStream` and
    /// `gio.PollableOutputStream`.
    ///
    /// This function may only be called on reliable `NiceAgents`. It is a
    /// programming error to try and create an I/O stream wrapper for an
    /// unreliable stream.
    extern fn nice_agent_get_io_stream(p_agent: *Agent, p_stream_id: c_uint, p_component_id: c_uint) *gio.IOStream;
    pub const getIoStream = nice_agent_get_io_stream;

    /// Retrieve from the agent the list of all local candidates
    /// for a stream's component
    ///
    ///  <note>
    ///    <para>
    ///      The caller owns the returned GSList as well as the candidates contained
    ///      within it.
    ///      To get full results, the client should wait for the
    ///      `nice.Agent.signals.candidate`-gathering-done signal.
    ///    </para>
    ///  </note>
    extern fn nice_agent_get_local_candidates(p_agent: *Agent, p_stream_id: c_uint, p_component_id: c_uint) *glib.SList;
    pub const getLocalCandidates = nice_agent_get_local_candidates;

    /// Gets the local credentials for stream `stream_id`. This may be called any time
    /// after creating a stream using `nice.Agent.addStream`.
    ///
    /// An error will be returned if this is called for a non-existent stream, or if
    /// either of `ufrag` or `pwd` are `NULL`.
    extern fn nice_agent_get_local_credentials(p_agent: *Agent, p_stream_id: c_uint, p_ufrag: *[*:0]u8, p_pwd: *[*:0]u8) c_int;
    pub const getLocalCredentials = nice_agent_get_local_credentials;

    /// Get a list of the remote candidates set on a stream's component
    ///
    ///  <note>
    ///    <para>
    ///      The caller owns the returned GSList as well as the candidates contained
    ///      within it.
    ///    </para>
    ///    <para>
    ///      The list of remote candidates can change during processing.
    ///      The client should register for the `nice.Agent.signals.new`-remote-candidate signal
    ///      to get notified of new remote candidates.
    ///    </para>
    ///  </note>
    extern fn nice_agent_get_remote_candidates(p_agent: *Agent, p_stream_id: c_uint, p_component_id: c_uint) *glib.SList;
    pub const getRemoteCandidates = nice_agent_get_remote_candidates;

    /// Retreive the selected candidate pair for media transmission
    /// for a given stream's component.
    extern fn nice_agent_get_selected_pair(p_agent: *Agent, p_stream_id: c_uint, p_component_id: c_uint, p_local: **nice.Candidate, p_remote: **nice.Candidate) c_int;
    pub const getSelectedPair = nice_agent_get_selected_pair;

    /// Retreive the local socket associated with the selected candidate pair
    /// for media transmission for a given stream's component.
    ///
    /// This is useful for adding ICE support to legacy applications that already
    /// have a protocol that maintains a connection. If the socket is duplicated
    /// before unrefing the agent, the application can take over and continue to use
    /// it. New applications are encouraged to use the built in libnice stream
    /// handling instead and let libnice handle the connection maintenance.
    ///
    /// Users of this method are encouraged to not use a TURN relay or any kind
    /// of proxy, as in this case, the socket will not be available to the
    /// application because the packets are encapsulated.
    extern fn nice_agent_get_selected_socket(p_agent: *Agent, p_stream_id: c_uint, p_component_id: c_uint) ?*gio.Socket;
    pub const getSelectedSocket = nice_agent_get_selected_socket;

    /// Each component can have multiple sockets, this is an API to retrieve them all
    /// to be able to set properties. Most of the sockets for a component are created when
    /// calling `nice.Agent.gatherCandidates`, so this API should be called right after to
    /// able to set properties on the sockets before they are used.
    ///
    /// These sockets can be a mix of UDP & TCP sockets depending on the compatibility mode
    /// and options that have been set.
    extern fn nice_agent_get_sockets(p_agent: *Agent, p_stream_id: c_uint, p_component_id: c_uint) *glib.PtrArray;
    pub const getSockets = nice_agent_get_sockets;

    /// This function will return the name assigned to a stream.
    ///
    /// <para>See also: `nice.Agent.setStreamName`</para>
    extern fn nice_agent_get_stream_name(p_agent: *Agent, p_stream_id: c_uint) [*:0]const u8;
    pub const getStreamName = nice_agent_get_stream_name;

    /// Parse an SDP string and extracts the candidate from it.
    ///
    /// <para>See also: `nice.Agent.generateLocalCandidateSdp` </para>
    /// <para>See also: `nice.Agent.parseRemoteSdp` </para>
    /// <para>See also: `nice.Agent.parseRemoteStreamSdp` </para>
    extern fn nice_agent_parse_remote_candidate_sdp(p_agent: *Agent, p_stream_id: c_uint, p_sdp: [*:0]const u8) *nice.Candidate;
    pub const parseRemoteCandidateSdp = nice_agent_parse_remote_candidate_sdp;

    /// Parse an SDP string and extracts candidates and credentials from it and sets
    /// them on the agent.
    ///
    /// <para>See also: `nice.Agent.setStreamName` </para>
    /// <para>See also: `nice.Agent.generateLocalSdp` </para>
    /// <para>See also: `nice.Agent.parseRemoteStreamSdp` </para>
    /// <para>See also: `nice.Agent.parseRemoteCandidateSdp` </para>
    extern fn nice_agent_parse_remote_sdp(p_agent: *Agent, p_sdp: [*:0]const u8) c_int;
    pub const parseRemoteSdp = nice_agent_parse_remote_sdp;

    /// Parse an SDP string representing a single stream and extracts candidates
    /// and credentials from it.
    ///
    /// <para>See also: `nice.Agent.generateLocalStreamSdp` </para>
    /// <para>See also: `nice.Agent.parseRemoteSdp` </para>
    /// <para>See also: `nice.Agent.parseRemoteCandidateSdp` </para>
    extern fn nice_agent_parse_remote_stream_sdp(p_agent: *Agent, p_stream_id: c_uint, p_sdp: [*:0]const u8, p_ufrag: *[*:0]u8, p_pwd: *[*:0]u8) *glib.SList;
    pub const parseRemoteStreamSdp = nice_agent_parse_remote_stream_sdp;

    /// Notifies the agent that the remote peer has concluded candidate gathering and
    /// thus no more remote candidates are expected to arrive for `stream_id`.
    ///
    /// This will allow the stream components without a successful connectivity check
    /// to stop waiting for more candidates to come and finally transit into
    /// `NICE_COMPONENT_STATE_FAILED`.
    ///
    /// Calling the function has an effect only when `nice.Agent.properties.trickle`-ice is `TRUE`.
    extern fn nice_agent_peer_candidate_gathering_done(p_agent: *Agent, p_stream_id: c_uint) c_int;
    pub const peerCandidateGatheringDone = nice_agent_peer_candidate_gathering_done;

    /// A single-message version of `nice.Agent.recvMessages`.
    extern fn nice_agent_recv(p_agent: *Agent, p_stream_id: c_uint, p_component_id: c_uint, p_buf: [*]u8, p_buf_len: usize, p_cancellable: ?*gio.Cancellable, p_error: ?*?*glib.Error) isize;
    pub const recv = nice_agent_recv;

    /// Block on receiving data from the given stream/component combination on
    /// `agent`, returning only once exactly `n_messages` messages have been received
    /// and written into `messages`, the stream is closed by the other end or by
    /// calling `nice.Agent.removeStream`, or `cancellable` is cancelled.
    ///
    /// Any STUN packets received will not be added to `messages`; instead,
    /// they'll be passed for processing to `nice.Agent` itself. Since `nice.Agent`
    /// does not poll for messages on its own, it's therefore essential to keep
    /// calling this function for ICE connection establishment to work.
    ///
    /// In the non-error case, in reliable mode, this will block until all buffers in
    /// all `n_messages` have been filled with received data (i.e. `messages` is
    /// treated as a large, flat array of buffers). In non-reliable mode, it will
    /// block until `n_messages` messages have been received, each of which does not
    /// have to fill all the buffers in its `nice.InputMessage`. In the non-reliable
    /// case, each `nice.InputMessage` must have enough buffers to contain an entire
    /// message (65536 bytes), or any excess data may be silently dropped.
    ///
    /// For each received message, `nice.InputMessage.signals.length` will be set to the
    /// number of valid bytes stored in the message’s buffers. The bytes are stored
    /// sequentially in the buffers; there are no gaps apart from at the end of the
    /// buffer array (in non-reliable mode). If non-`NULL` on input,
    /// `nice.InputMessage.signals.from` will have the address of the sending peer stored in
    /// it. The base addresses, sizes, and number of buffers in each message will not
    /// be modified in any case.
    ///
    /// This must not be used in combination with `nice.Agent.attachRecv` on the
    /// same stream/component pair.
    ///
    /// If the stream/component pair doesn’t exist, or if a suitable candidate socket
    /// hasn’t yet been selected for it, a `G_IO_ERROR_BROKEN_PIPE` error will be
    /// returned. A `G_IO_ERROR_CANCELLED` error will be returned if the operation was
    /// cancelled. `G_IO_ERROR_FAILED` will be returned for other errors.
    extern fn nice_agent_recv_messages(p_agent: *Agent, p_stream_id: c_uint, p_component_id: c_uint, p_messages: [*]nice.InputMessage, p_n_messages: c_uint, p_cancellable: ?*gio.Cancellable, p_error: ?*?*glib.Error) c_int;
    pub const recvMessages = nice_agent_recv_messages;

    /// Try to receive data from the given stream/component combination on `agent`,
    /// without blocking. If receiving data would block, -1 is returned and
    /// `G_IO_ERROR_WOULD_BLOCK` is set in `error`. If any other error occurs, -1 is
    /// returned and `error` is set accordingly. Otherwise, 0 is returned if (and only
    /// if) `n_messages` is 0. In all other cases, the number of valid messages stored
    /// in `messages` is returned, and will be greater than 0.
    ///
    /// This function behaves similarly to `nice.Agent.recvMessages`, except that it
    /// will not block on filling (in reliable mode) or receiving (in non-reliable
    /// mode) exactly `n_messages` messages. In reliable mode, it will receive bytes
    /// into `messages` until it would block; in non-reliable mode, it will receive
    /// messages until it would block.
    ///
    /// Any STUN packets received will not be added to `messages`; instead,
    /// they'll be passed for processing to `nice.Agent` itself. Since `nice.Agent`
    /// does not poll for messages on its own, it's therefore essential to keep
    /// calling this function for ICE connection establishment to work.
    ///
    /// As this function is non-blocking, `cancellable` is included only for parity
    /// with `nice.Agent.recvMessages`. If `cancellable` is cancelled before this
    /// function is called, a `G_IO_ERROR_CANCELLED` error will be returned
    /// immediately.
    ///
    /// This must not be used in combination with `nice.Agent.attachRecv` on the
    /// same stream/component pair.
    extern fn nice_agent_recv_messages_nonblocking(p_agent: *Agent, p_stream_id: c_uint, p_component_id: c_uint, p_messages: [*]nice.InputMessage, p_n_messages: c_uint, p_cancellable: ?*gio.Cancellable, p_error: ?*?*glib.Error) c_int;
    pub const recvMessagesNonblocking = nice_agent_recv_messages_nonblocking;

    /// A single-message version of `nice.Agent.recvMessagesNonblocking`.
    extern fn nice_agent_recv_nonblocking(p_agent: *Agent, p_stream_id: c_uint, p_component_id: c_uint, p_buf: [*]u8, p_buf_len: usize, p_cancellable: ?*gio.Cancellable, p_error: ?*?*glib.Error) isize;
    pub const recvNonblocking = nice_agent_recv_nonblocking;

    /// Remove and free a previously created data stream from `agent`. If any I/O
    /// streams have been created using `nice.Agent.getIoStream`, they should be
    /// closed completely using `gio.IOStream.close` before this is called, or they
    /// will get broken pipe errors.
    extern fn nice_agent_remove_stream(p_agent: *Agent, p_stream_id: c_uint) void;
    pub const removeStream = nice_agent_remove_stream;

    /// Restarts the session as defined in ICE draft 19. This function
    /// needs to be called both when initiating (ICE spec section 9.1.1.1.
    /// "ICE Restarts"), as well as when reacting (spec section 9.2.1.1.
    /// "Detecting ICE Restart") to a restart.
    ///
    /// If consent-freshness has been enabled on `agent`, as specified in RFC7675
    /// then restarting streams will restore the local consent.
    extern fn nice_agent_restart(p_agent: *Agent) c_int;
    pub const restart = nice_agent_restart;

    /// Restarts a single stream as defined in RFC 5245. This function
    /// needs to be called both when initiating (ICE spec section 9.1.1.1.
    /// "ICE Restarts"), as well as when reacting (spec section 9.2.1.1.
    /// "Detecting ICE Restart") to a restart.
    ///
    /// Unlike `nice.Agent.restart`, this applies to a single stream. It also
    /// does not generate a new tie breaker.
    ///
    /// If consent-freshness has been enabled on `agent`, as specified in RFC7675
    /// then restart `stream_id` will restore the local consent for that stream.
    extern fn nice_agent_restart_stream(p_agent: *Agent, p_stream_id: c_uint) c_int;
    pub const restartStream = nice_agent_restart_stream;

    /// Sends a data payload over a stream's component.
    ///
    ///  <note>
    ///    <para>
    ///      Component state MUST be NICE_COMPONENT_STATE_READY, or as a special case,
    ///      in any state if component was in READY state before and was then restarted
    ///    </para>
    ///    <para>
    ///    In reliable mode, the -1 error value means either that you are not yet
    ///    connected or that the send buffer is full (equivalent to EWOULDBLOCK).
    ///    In both cases, you simply need to wait for the
    ///    `nice.Agent.signals.reliable`-transport-writable signal to be fired before resending
    ///    the data.
    ///    </para>
    ///    <para>
    ///    In non-reliable mode, it will virtually never happen with UDP sockets, but
    ///    it might happen if the active candidate is a TURN-TCP connection that got
    ///    disconnected.
    ///    </para>
    ///    <para>
    ///    In both reliable and non-reliable mode, a -1 error code could also mean that
    ///    the stream_id and/or component_id are invalid.
    ///    </para>
    /// </note>
    extern fn nice_agent_send(p_agent: *Agent, p_stream_id: c_uint, p_component_id: c_uint, p_len: c_uint, p_buf: [*:0]const u8) c_int;
    pub const send = nice_agent_send;

    /// Sends multiple messages on the socket identified by the given
    /// stream/component pair. Transmission is non-blocking, so a
    /// `G_IO_ERROR_WOULD_BLOCK` error may be returned if the send buffer is full.
    ///
    /// As with `nice.Agent.send`, the given component must be in
    /// `NICE_COMPONENT_STATE_READY` or, as a special case, in any state if it was
    /// previously ready and was then restarted.
    ///
    /// On success, the number of messages written to the socket will be returned,
    /// which may be less than `n_messages` if transmission would have blocked
    /// part-way through. Zero will be returned if `n_messages` is zero, or if
    /// transmission would have blocked on the first message.
    ///
    /// In reliable mode, it is instead recommended to use
    /// `nice.Agent.send`.  The return value can be less than `n_messages`
    /// or 0 even if it is still possible to send a partial message. In
    /// this case, "nice-agent-writable" will never be triggered, so the
    /// application would have to use `nice_agent_sent` to fill the buffer or have
    /// to retry sending at a later point.
    ///
    /// On failure, -1 will be returned and `error` will be set. If the `nice.Agent` is
    /// reliable and the socket is not yet connected, `G_IO_ERROR_BROKEN_PIPE` will be
    /// returned; if the write buffer is full, `G_IO_ERROR_WOULD_BLOCK` will be
    /// returned. In both cases, wait for the `nice.Agent.signals.reliable`-transport-writable
    /// signal before trying again. If the given `stream_id` or `component_id` are
    /// invalid or not yet connected, `G_IO_ERROR_BROKEN_PIPE` will be returned.
    /// `G_IO_ERROR_FAILED` will be returned for other errors.
    extern fn nice_agent_send_messages_nonblocking(p_agent: *Agent, p_stream_id: c_uint, p_component_id: c_uint, p_messages: [*]const nice.OutputMessage, p_n_messages: c_uint, p_cancellable: ?*gio.Cancellable, p_error: ?*?*glib.Error) c_int;
    pub const sendMessagesNonblocking = nice_agent_send_messages_nonblocking;

    /// Sets the local credentials for stream `stream_id`.
    ///
    ///  <note>
    ///    <para>
    ///      This is only effective before ICE negotiation has started.
    ///    </para>
    ///  </note>
    ///
    /// Since 0.1.11
    extern fn nice_agent_set_local_credentials(p_agent: *Agent, p_stream_id: c_uint, p_ufrag: [*:0]const u8, p_pwd: [*:0]const u8) c_int;
    pub const setLocalCredentials = nice_agent_set_local_credentials;

    /// Sets a preferred port range for allocating host candidates.
    /// <para>
    /// If a local host candidate cannot be created on that port
    /// range, then the `nice.Agent.gatherCandidates` call will fail.
    /// </para>
    /// <para>
    /// This MUST be called before `nice.Agent.gatherCandidates`
    /// </para>
    extern fn nice_agent_set_port_range(p_agent: *Agent, p_stream_id: c_uint, p_component_id: c_uint, p_min_port: c_uint, p_max_port: c_uint) void;
    pub const setPortRange = nice_agent_set_port_range;

    /// Sets the settings for using a relay server during the candidate discovery.
    /// This may be called multiple times to add multiple relay servers to the
    /// discovery process; one TCP and one UDP, for example.
    extern fn nice_agent_set_relay_info(p_agent: *Agent, p_stream_id: c_uint, p_component_id: c_uint, p_server_ip: [*:0]const u8, p_server_port: c_uint, p_username: [*:0]const u8, p_password: [*:0]const u8, p_type: nice.RelayType) c_int;
    pub const setRelayInfo = nice_agent_set_relay_info;

    /// Sets, adds or updates the remote candidates for a component of a stream.
    ///
    ///  <note>
    ///    <para>
    ///     NICE_AGENT_MAX_REMOTE_CANDIDATES is the absolute maximum limit
    ///     for remote candidates.
    ///    </para>
    ///    <para>
    ///    You must first call `nice.Agent.gatherCandidates` and wait for the
    ///    `nice.Agent.signals.candidate`-gathering-done signale before
    ///    calling `nice.Agent.setRemoteCandidates`
    ///    </para>
    ///    <para>
    ///     Since 0.1.3, there is no need to wait for the candidate-gathering-done signal.
    ///     Remote candidates can be set even while gathering local candidates.
    ///     Newly discovered local candidates will automatically be paired with
    ///     existing remote candidates.
    ///    </para>
    ///  </note>
    extern fn nice_agent_set_remote_candidates(p_agent: *Agent, p_stream_id: c_uint, p_component_id: c_uint, p_candidates: *const glib.SList) c_int;
    pub const setRemoteCandidates = nice_agent_set_remote_candidates;

    /// Sets the remote credentials for stream `stream_id`.
    ///
    ///  <note>
    ///    <para>
    ///      Stream credentials do not override per-candidate credentials if set
    ///    </para>
    ///    <para>
    ///      Due to the native of peer-reflexive candidates, any agent using a per-stream
    ///      credentials (RFC5245, WLM2009, OC2007R2 and DRAFT19) instead of
    ///      per-candidate credentials (GOOGLE, MSN, OC2007), must
    ///      use the `nice.Agent.setRemoteCredentials` API instead of setting the
    ///      username and password on the candidates.
    ///    </para>
    ///  </note>
    extern fn nice_agent_set_remote_credentials(p_agent: *Agent, p_stream_id: c_uint, p_ufrag: [*:0]const u8, p_pwd: [*:0]const u8) c_int;
    pub const setRemoteCredentials = nice_agent_set_remote_credentials;

    /// Sets the selected candidate pair for media transmission
    /// for a given stream's component. Calling this function will
    /// disable all further ICE processing (connection check,
    /// state machine updates, etc). Note that keepalives will
    /// continue to be sent.
    extern fn nice_agent_set_selected_pair(p_agent: *Agent, p_stream_id: c_uint, p_component_id: c_uint, p_lfoundation: [*:0]const u8, p_rfoundation: [*:0]const u8) c_int;
    pub const setSelectedPair = nice_agent_set_selected_pair;

    /// Sets the selected remote candidate for media transmission
    /// for a given stream's component. This is used to force the selection of
    /// a specific remote candidate even when connectivity checks are failing
    /// (e.g. non-ICE compatible candidates).
    /// Calling this function will disable all further ICE processing
    /// (connection check, state machine updates, etc). Note that keepalives will
    /// continue to be sent.
    extern fn nice_agent_set_selected_remote_candidate(p_agent: *Agent, p_stream_id: c_uint, p_component_id: c_uint, p_candidate: *nice.Candidate) c_int;
    pub const setSelectedRemoteCandidate = nice_agent_set_selected_remote_candidate;

    /// This function will set the value of the SOFTWARE attribute to be added to
    /// STUN requests, responses and error responses sent during connectivity checks.
    /// <para>
    /// The SOFTWARE attribute will only be added in the `NICE_COMPATIBILITY_RFC5245`
    /// and `NICE_COMPATIBILITY_WLM2009` compatibility modes.
    ///
    /// </para>
    /// <note>
    ///      <para>
    ///        The `software` argument will be appended with the libnice version before
    ///        being sent.
    ///      </para>
    ///      <para>
    ///        The `software` argument must be in UTF-8 encoding and only the first
    ///        128 characters will be sent.
    ///      </para>
    ///    </note>
    extern fn nice_agent_set_software(p_agent: *Agent, p_software: [*:0]const u8) void;
    pub const setSoftware = nice_agent_set_software;

    /// This function will assign a media type to a stream. The only values
    /// that can be used to produce a valid SDP are: "audio", "video",
    /// "text", "application", "image" and "message".
    ///
    /// This is only useful when parsing and generating an SDP of the
    /// candidates.
    ///
    /// <para>See also: `nice.Agent.generateLocalSdp`</para>
    /// <para>See also: `nice.Agent.parseRemoteSdp`</para>
    /// <para>See also: `nice.Agent.getStreamName`</para>
    extern fn nice_agent_set_stream_name(p_agent: *Agent, p_stream_id: c_uint, p_name: [*:0]const u8) c_int;
    pub const setStreamName = nice_agent_set_stream_name;

    /// Sets the IP_TOS and/or IPV6_TCLASS field on the stream's sockets' options
    extern fn nice_agent_set_stream_tos(p_agent: *Agent, p_stream_id: c_uint, p_tos: c_int) void;
    pub const setStreamTos = nice_agent_set_stream_tos;

    extern fn nice_agent_get_type() usize;
    pub const getGObjectType = nice_agent_get_type;

    extern fn g_object_ref(p_self: *nice.Agent) void;
    pub const ref = g_object_ref;

    extern fn g_object_unref(p_self: *nice.Agent) void;
    pub const unref = g_object_unref;

    pub fn as(p_instance: *Agent, comptime P_T: type) *P_T {
        return gobject.ext.as(P_T, p_instance);
    }

    test {
        @setEvalBranchQuota(100_000);
        std.testing.refAllDecls(@This());
    }
};

/// The `nice.PseudoTcpSocket` is the GObject implementing the Pseudo TCP Socket
pub const PseudoTcpSocket = opaque {
    pub const Parent = gobject.Object;
    pub const Implements = [_]type{};
    pub const Class = nice.PseudoTcpSocketClass;
    pub const virtual_methods = struct {};

    pub const properties = struct {
        pub const ack_delay = struct {
            pub const name = "ack-delay";

            pub const Type = c_uint;
        };

        pub const callbacks = struct {
            pub const name = "callbacks";

            pub const Type = ?*anyopaque;
        };

        pub const conversation = struct {
            pub const name = "conversation";

            pub const Type = c_uint;
        };

        pub const no_delay = struct {
            pub const name = "no-delay";

            pub const Type = c_int;
        };

        pub const rcv_buf = struct {
            pub const name = "rcv-buf";

            pub const Type = c_uint;
        };

        pub const snd_buf = struct {
            pub const name = "snd-buf";

            pub const Type = c_uint;
        };

        pub const state = struct {
            pub const name = "state";

            pub const Type = c_uint;
        };

        /// Whether to support the FIN–ACK extension to the pseudo-TCP protocol for
        /// this socket. The extension is only compatible with other libnice pseudo-TCP
        /// stacks, and not with Jingle pseudo-TCP stacks. If enabled, support is
        /// negotiatied on connection setup, so it is safe for a `nice.PseudoTcpSocket` with
        /// support enabled to be used with one with it disabled, or with a Jingle
        /// pseudo-TCP socket which doesn’t support it at all.
        ///
        /// Support is enabled by default.
        pub const support_fin_ack = struct {
            pub const name = "support-fin-ack";

            pub const Type = c_int;
        };
    };

    pub const signals = struct {};

    /// Creates a new `nice.PseudoTcpSocket` for the specified conversation
    ///
    ///  <note>
    ///    <para>
    ///      The `callbacks` must be non-NULL, in order to get notified of packets the
    ///      socket needs to send.
    ///    </para>
    ///    <para>
    ///      If the `callbacks` structure was dynamicly allocated, it can be freed
    ///      after the call `pseudo_tcp_socket_new`
    ///    </para>
    ///  </note>
    extern fn pseudo_tcp_socket_new(p_conversation: u32, p_callbacks: *nice.PseudoTcpCallbacks) *nice.PseudoTcpSocket;
    pub const new = pseudo_tcp_socket_new;

    /// Close the socket for sending. If `force` is set to `FALSE`, the socket will
    /// finish sending pending data before closing. If it is set to `TRUE`, the socket
    /// will discard pending data and close the connection immediately (sending a TCP
    /// RST segment).
    ///
    /// The socket will be closed in both directions – sending and receiving – and
    /// any pending received data must be read before calling this function, by
    /// calling `nice.PseudoTcpSocket.recv` until it blocks. If any pending data is in
    /// the receive buffer when `nice.PseudoTcpSocket.close` is called, a TCP RST
    /// segment will be sent to the peer to notify it of the data loss.
    ///
    ///  <note>
    ///    <para>
    ///      The `nice.PseudoTcpCallbacks`:PseudoTcpClosed callback will not be called once
    ///      the socket gets closed. It is only used for aborted connection.
    ///      Instead, the socket gets closed when the `nice.PseudoTcpSocket.getNextClock`
    ///      function returns FALSE.
    ///    </para>
    ///  </note>
    ///
    /// <para> See also: `nice.PseudoTcpSocket.getNextClock` </para>
    extern fn pseudo_tcp_socket_close(p_self: *PseudoTcpSocket, p_force: c_int) void;
    pub const close = pseudo_tcp_socket_close;

    /// Connects the `nice.PseudoTcpSocket` to the peer with the same conversation id.
    /// The connection will only be successful after the
    /// `nice.PseudoTcpCallbacks`:PseudoTcpOpened callback is called
    extern fn pseudo_tcp_socket_connect(p_self: *PseudoTcpSocket) c_int;
    pub const connect = pseudo_tcp_socket_connect;

    /// Return the last encountered error.
    ///
    ///  <note>
    ///    <para>
    ///      The return value can be :
    ///      <para>
    ///        EINVAL (for `nice.PseudoTcpSocket.connect`).
    ///      </para>
    ///      <para>
    ///        EWOULDBLOCK or ENOTCONN (for `nice.PseudoTcpSocket.recv` and
    ///        `nice.PseudoTcpSocket.send`).
    ///      </para>
    ///    </para>
    ///  </note>
    extern fn pseudo_tcp_socket_get_error(p_self: *PseudoTcpSocket) c_int;
    pub const getError = pseudo_tcp_socket_get_error;

    /// Call this to determine the timeout needed before the next time call
    /// to `nice.PseudoTcpSocket.notifyClock` should be made.
    extern fn pseudo_tcp_socket_get_next_clock(p_self: *PseudoTcpSocket, p_timeout: *u64) c_int;
    pub const getNextClock = pseudo_tcp_socket_get_next_clock;

    /// Gets whether the socket is closed, with the shutdown handshake completed,
    /// and both peers no longer able to read or write data to the connection.
    extern fn pseudo_tcp_socket_is_closed(p_self: *PseudoTcpSocket) c_int;
    pub const isClosed = pseudo_tcp_socket_is_closed;

    /// Gets whether the socket has been closed on the remote peer’s side of the
    /// connection (i.e. whether `nice.PseudoTcpSocket.close` has been called there).
    /// This is guaranteed to return `TRUE` if `nice.PseudoTcpSocket.isClosed` returns
    /// `TRUE`. It will not return `TRUE` after `nice.PseudoTcpSocket.close` is called
    /// until a FIN segment is received from the remote peer.
    extern fn pseudo_tcp_socket_is_closed_remotely(p_self: *PseudoTcpSocket) c_int;
    pub const isClosedRemotely = pseudo_tcp_socket_is_closed_remotely;

    /// Start the processing of receiving data, pending data or syn/acks.
    /// Call this based on timeout value returned by
    /// `nice.PseudoTcpSocket.getNextClock`.
    /// It's ok to call this too frequently.
    ///
    /// <para> See also: `nice.PseudoTcpSocket.getNextClock` </para>
    extern fn pseudo_tcp_socket_notify_clock(p_self: *PseudoTcpSocket) void;
    pub const notifyClock = pseudo_tcp_socket_notify_clock;

    /// Set the MTU of the socket
    extern fn pseudo_tcp_socket_notify_mtu(p_self: *PseudoTcpSocket, p_mtu: u16) void;
    pub const notifyMtu = pseudo_tcp_socket_notify_mtu;

    /// Notify the `nice.PseudoTcpSocket` when a new packet arrives
    extern fn pseudo_tcp_socket_notify_packet(p_self: *PseudoTcpSocket, p_buffer: [*:0]const u8, p_len: u32) c_int;
    pub const notifyPacket = pseudo_tcp_socket_notify_packet;

    /// Receive data from the socket.
    ///
    ///  <note>
    ///    <para>
    ///      Only call this on the `nice.PseudoTcpCallbacks`:PseudoTcpReadable callback.
    ///    </para>
    ///    <para>
    ///      This function should be called in a loop. If this function does not
    ///      return -1 with EWOULDBLOCK as the error, the
    ///      `nice.PseudoTcpCallbacks`:PseudoTcpReadable callback will not be called again.
    ///    </para>
    ///  </note>
    extern fn pseudo_tcp_socket_recv(p_self: *PseudoTcpSocket, p_buffer: [*:0]u8, p_len: usize) c_int;
    pub const recv = pseudo_tcp_socket_recv;

    /// Send data on the socket.
    ///
    ///  <note>
    ///    <para>
    ///      If this function return -1 with EWOULDBLOCK as the error, or if the return
    ///      value is lower than `len`, then the `nice.PseudoTcpCallbacks`:PseudoTcpWritable
    ///      callback will be called when the socket will become writable.
    ///    </para>
    ///  </note>
    extern fn pseudo_tcp_socket_send(p_self: *PseudoTcpSocket, p_buffer: [*:0]const u8, p_len: u32) c_int;
    pub const send = pseudo_tcp_socket_send;

    /// Shut down sending, receiving, or both on the socket, depending on the value
    /// of `how`. The behaviour of `nice.PseudoTcpSocket.send` and
    /// `nice.PseudoTcpSocket.recv` will immediately change after this function returns
    /// (depending on the value of `how`), though the socket may continue to process
    /// network traffic in the background even if sending or receiving data is
    /// forbidden.
    ///
    /// This is equivalent to the POSIX `shutdown` function. Setting `how` to
    /// `PSEUDO_TCP_SHUTDOWN_RDWR` is equivalent to calling `nice.PseudoTcpSocket.close`.
    extern fn pseudo_tcp_socket_shutdown(p_self: *PseudoTcpSocket, p_how: nice.PseudoTcpShutdown) void;
    pub const shutdown = pseudo_tcp_socket_shutdown;

    extern fn pseudo_tcp_socket_get_type() usize;
    pub const getGObjectType = pseudo_tcp_socket_get_type;

    extern fn g_object_ref(p_self: *nice.PseudoTcpSocket) void;
    pub const ref = g_object_ref;

    extern fn g_object_unref(p_self: *nice.PseudoTcpSocket) void;
    pub const unref = g_object_unref;

    pub fn as(p_instance: *PseudoTcpSocket, comptime P_T: type) *P_T {
        return gobject.ext.as(P_T, p_instance);
    }

    test {
        @setEvalBranchQuota(100_000);
        std.testing.refAllDecls(@This());
    }
};

/// The `nice.Address` structure that represents an IPv4 or IPv6 address.
pub const Address = extern struct {
    anon0: extern union {
        f_addr: ?*anyopaque,
        f_ip4: ?*anyopaque,
        f_ip6: ?*anyopaque,
    },

    /// Create a new `nice.Address` with undefined address
    /// You must free it with `nice.Address.free`
    extern fn nice_address_new() *nice.Address;
    pub const new = nice_address_new;

    /// Fills the sockaddr structure `sin` with the address contained in `addr`
    extern fn nice_address_copy_to_sockaddr(p_addr: *const Address, p_sin: ?*anyopaque) void;
    pub const copyToSockaddr = nice_address_copy_to_sockaddr;

    /// Creates a new `nice.Address` with the same address as `addr`
    extern fn nice_address_dup(p_addr: *const Address) *nice.Address;
    pub const dup = nice_address_dup;

    /// Transforms the address `addr` into a newly allocated human readable string
    extern fn nice_address_dup_string(p_addr: *const Address) [*:0]u8;
    pub const dupString = nice_address_dup_string;

    /// Compares two `nice.Address` structures to see if they contain the same address
    /// and the same port.
    extern fn nice_address_equal(p_a: *const Address, p_b: *const nice.Address) c_int;
    pub const equal = nice_address_equal;

    /// Compares two `nice.Address` structures to see if they contain the same address,
    /// ignoring the port.
    extern fn nice_address_equal_no_port(p_a: *const Address, p_b: *const nice.Address) c_int;
    pub const equalNoPort = nice_address_equal_no_port;

    /// Frees a `nice.Address` created with `nice.Address.new` or `nice.Address.dup`
    extern fn nice_address_free(p_addr: *Address) void;
    pub const free = nice_address_free;

    /// Retreive the port of `addr`
    extern fn nice_address_get_port(p_addr: *const Address) c_uint;
    pub const getPort = nice_address_get_port;

    /// Initialize a `nice.Address` into an undefined address
    extern fn nice_address_init(p_addr: *Address) void;
    pub const init = nice_address_init;

    /// Returns the IP version of the address
    extern fn nice_address_ip_version(p_addr: *const Address) c_int;
    pub const ipVersion = nice_address_ip_version;

    /// Verifies if the address in `addr` is a link-local address or not
    extern fn nice_address_is_linklocal(p_addr: *const Address) c_int;
    pub const isLinklocal = nice_address_is_linklocal;

    /// Verifies if the address in `addr` is a private address or not
    extern fn nice_address_is_private(p_addr: *const Address) c_int;
    pub const isPrivate = nice_address_is_private;

    /// Validate whether the `nice.Address` `addr` is a valid IPv4 or IPv6 address
    extern fn nice_address_is_valid(p_addr: *const Address) c_int;
    pub const isValid = nice_address_is_valid;

    /// Sets an IPv4 or IPv6 address from the sockaddr structure `sin`
    extern fn nice_address_set_from_sockaddr(p_addr: *Address, p_sin: ?*anyopaque) void;
    pub const setFromSockaddr = nice_address_set_from_sockaddr;

    /// Sets an IPv4 or IPv6 address from the string `str`
    extern fn nice_address_set_from_string(p_addr: *Address, p_str: [*:0]const u8) c_int;
    pub const setFromString = nice_address_set_from_string;

    /// Set `addr` to an IPv4 address using the data from `addr_ipv4`
    ///
    ///  <note>
    ///   <para>
    ///    This function will reset the port to 0, so make sure you call it before
    ///    `nice.Address.setPort`
    ///   </para>
    ///  </note>
    extern fn nice_address_set_ipv4(p_addr: *Address, p_addr_ipv4: u32) void;
    pub const setIpv4 = nice_address_set_ipv4;

    /// Set `addr` to an IPv6 address using the data from `addr_ipv6`
    ///
    ///  <note>
    ///   <para>
    ///    This function will reset the port to 0, so make sure you call it before
    ///    `nice.Address.setPort`
    ///   </para>
    ///  </note>
    extern fn nice_address_set_ipv6(p_addr: *Address, p_addr_ipv6: *const u8) void;
    pub const setIpv6 = nice_address_set_ipv6;

    /// Set the port of `addr` to `port`
    extern fn nice_address_set_port(p_addr: *Address, p_port: c_uint) void;
    pub const setPort = nice_address_set_port;

    /// Transforms the address `addr` into a human readable string
    extern fn nice_address_to_string(p_addr: *const Address, p_dst: [*:0]u8) void;
    pub const toString = nice_address_to_string;

    extern fn nice_address_get_type() usize;
    pub const getGObjectType = nice_address_get_type;

    test {
        @setEvalBranchQuota(100_000);
        std.testing.refAllDecls(@This());
    }
};

pub const AgentClass = extern struct {
    pub const Instance = nice.Agent;

    f_parent_class: gobject.ObjectClass,

    pub fn as(p_instance: *AgentClass, comptime P_T: type) *P_T {
        return gobject.ext.as(P_T, p_instance);
    }

    test {
        @setEvalBranchQuota(100_000);
        std.testing.refAllDecls(@This());
    }
};

/// A structure to represent an ICE candidate
///  <note>
///    <para>
///    The `priority` is an integer as specified in the ICE draft 19. If you are
///    using the MSN or the GOOGLE compatibility mode (which are based on ICE
///    draft 6, which uses a floating point qvalue as priority), then the `priority`
///    value will represent the qvalue multiplied by 1000.
///    </para>
///  </note>
pub const Candidate = extern struct {
    /// The type of candidate
    f_type: nice.CandidateType,
    /// The transport being used for the candidate
    f_transport: nice.CandidateTransport,
    /// The `nice.Address` of the candidate
    f_addr: nice.Address,
    /// The `nice.Address` of the base address used by the candidate
    f_base_addr: nice.Address,
    /// The priority of the candidate <emphasis> see note </emphasis>
    f_priority: u32,
    /// The ID of the stream to which belongs the candidate
    f_stream_id: c_uint,
    /// The ID of the component to which belongs the candidate
    f_component_id: c_uint,
    /// The foundation of the candidate
    f_foundation: [33]u8,
    /// The candidate-specific username to use (overrides the one set
    /// by `nice.Agent.setLocalCredentials` or `nice.Agent.setRemoteCredentials`)
    f_username: ?[*:0]u8,
    /// The candidate-specific password to use (overrides the one set
    /// by `nice.Agent.setLocalCredentials` or `nice.Agent.setRemoteCredentials`)
    f_password: ?[*:0]u8,

    /// Useful for debugging functions, just returns a static string with the
    /// candidate transport.
    extern fn nice_candidate_transport_to_string(p_transport: nice.CandidateTransport) [*:0]const u8;
    pub const transportToString = nice_candidate_transport_to_string;

    /// Useful for debugging functions, just returns a static string with the
    /// candidate type.
    extern fn nice_candidate_type_to_string(p_type: nice.CandidateType) [*:0]const u8;
    pub const typeToString = nice_candidate_type_to_string;

    /// Creates a new candidate. Must be freed with `nice.Candidate.free`
    extern fn nice_candidate_new(p_type: nice.CandidateType) *nice.Candidate;
    pub const new = nice_candidate_new;

    /// Makes a copy of a `nice.Candidate`
    extern fn nice_candidate_copy(p_candidate: *const Candidate) *nice.Candidate;
    pub const copy = nice_candidate_copy;

    /// Verifies that the candidates point to the same place, meaning they have
    /// the same transport and the same address. It ignores all other aspects.
    extern fn nice_candidate_equal_target(p_candidate1: *const Candidate, p_candidate2: *const nice.Candidate) c_int;
    pub const equalTarget = nice_candidate_equal_target;

    /// Frees a `nice.Candidate`
    extern fn nice_candidate_free(p_candidate: *Candidate) void;
    pub const free = nice_candidate_free;

    /// In case the given candidate is relayed through a TURN server, use this utility function to get
    /// its address.
    extern fn nice_candidate_relay_address(p_candidate: *const Candidate, p_addr: *nice.Address) void;
    pub const relayAddress = nice_candidate_relay_address;

    /// In case the given candidate server-reflexive, use this utility function to get its address. The
    /// address will be filled only if the candidate was generated using an STUN server.
    extern fn nice_candidate_stun_server_address(p_candidate: *const Candidate, p_addr: *nice.Address) c_int;
    pub const stunServerAddress = nice_candidate_stun_server_address;

    extern fn nice_candidate_get_type() usize;
    pub const getGObjectType = nice_candidate_get_type;

    test {
        @setEvalBranchQuota(100_000);
        std.testing.refAllDecls(@This());
    }
};

/// Represents a single message received off the network. For reliable
/// connections, this is essentially just an array of buffers (specifically,
/// `from` can be ignored). for non-reliable connections, it represents a single
/// packet as received from the OS.
///
/// `n_buffers` may be -1 to indicate that `buffers` is terminated by a
/// `gio.InputVector` with a `NULL` buffer pointer.
///
/// By providing arrays of `NiceInputMessages` to functions like
/// `nice.Agent.recvMessages`, multiple messages may be received with a single
/// call, which is more efficient than making multiple calls in a loop. In this
/// manner, `nice.Agent.recvMessages` is analogous to `recvmmsg`; and
/// `nice.InputMessage` to struct mmsghdr.
pub const InputMessage = extern struct {
    /// unowned array of `gio.InputVector` buffers to
    /// store data in for this message
    f_buffers: ?[*]gio.InputVector,
    /// number of `GInputVectors` in `buffers`, or -1 to indicate `buffers`
    /// is `NULL`-terminated
    f_n_buffers: c_int,
    /// return location to store the address of the peer who
    /// transmitted the message, or `NULL`
    f_from: ?*nice.Address,
    /// total number of valid bytes contiguously stored in `buffers`
    f_length: usize,

    test {
        @setEvalBranchQuota(100_000);
        std.testing.refAllDecls(@This());
    }
};

/// Represents a single message to transmit on the network. For
/// reliable connections, this is essentially just an array of
/// buffer. for non-reliable connections, it represents a single packet
/// to send to the OS.
///
/// `n_buffers` may be -1 to indicate that `buffers` is terminated by a
/// `gio.OutputVector` with a `NULL` buffer pointer.
///
/// By providing arrays of `NiceOutputMessages` to functions like
/// `nice.Agent.sendMessagesNonblocking`, multiple messages may be transmitted
/// with a single call, which is more efficient than making multiple calls in a
/// loop. In this manner, `nice.Agent.sendMessagesNonblocking` is analogous to
/// `sendmmsg`; and `nice.OutputMessage` to struct mmsghdr.
pub const OutputMessage = extern struct {
    /// unowned array of `gio.OutputVector` buffers
    /// which contain data to transmit for this message
    f_buffers: ?[*]gio.OutputVector,
    /// number of `GOutputVectors` in `buffers`, or -1 to indicate `buffers`
    /// is `NULL`-terminated
    f_n_buffers: c_int,

    test {
        @setEvalBranchQuota(100_000);
        std.testing.refAllDecls(@This());
    }
};

/// A structure containing callbacks functions that will be called by the
/// `nice.PseudoTcpSocket` when some events happen.
/// <para> See also: `nice.PseudoTcpWriteResult` </para>
pub const PseudoTcpCallbacks = extern struct {
    /// A user defined pointer to be passed to the callbacks
    f_user_data: ?*anyopaque,
    /// The `nice.PseudoTcpSocket` is now connected
    f_PseudoTcpOpened: ?*const fn (p_tcp: *nice.PseudoTcpSocket, p_data: *anyopaque) callconv(.c) void,
    /// The socket is readable
    f_PseudoTcpReadable: ?*const fn (p_tcp: *nice.PseudoTcpSocket, p_data: *anyopaque) callconv(.c) void,
    /// The socket is writable
    f_PseudoTcpWritable: ?*const fn (p_tcp: *nice.PseudoTcpSocket, p_data: *anyopaque) callconv(.c) void,
    /// The socket was closed (both sides)
    f_PseudoTcpClosed: ?*const fn (p_tcp: *nice.PseudoTcpSocket, p_error: u32, p_data: *anyopaque) callconv(.c) void,
    /// This callback is called when the socket needs to send data.
    f_WritePacket: ?*const fn (p_tcp: *nice.PseudoTcpSocket, p_buffer: [*:0]const u8, p_len: u32, p_data: *anyopaque) callconv(.c) nice.PseudoTcpWriteResult,

    test {
        @setEvalBranchQuota(100_000);
        std.testing.refAllDecls(@This());
    }
};

pub const PseudoTcpSocketClass = opaque {
    pub const Instance = nice.PseudoTcpSocket;

    pub fn as(p_instance: *PseudoTcpSocketClass, comptime P_T: type) *P_T {
        return gobject.ext.as(P_T, p_instance);
    }

    test {
        @setEvalBranchQuota(100_000);
        std.testing.refAllDecls(@This());
    }
};

/// An enum representing the type of transport to use
pub const CandidateTransport = enum(c_int) {
    udp = 0,
    tcp_active = 1,
    tcp_passive = 2,
    tcp_so = 3,
    _,

    test {
        @setEvalBranchQuota(100_000);
        std.testing.refAllDecls(@This());
    }
};

/// An enum representing the type of a candidate
pub const CandidateType = enum(c_int) {
    host = 0,
    server_reflexive = 1,
    peer_reflexive = 2,
    relayed = 3,
    _,

    test {
        @setEvalBranchQuota(100_000);
        std.testing.refAllDecls(@This());
    }
};

/// An enum to specify which compatible specifications the `nice.Agent` should use.
/// Use with `nice.Agent.new`
///
/// <warning>`NICE_COMPATIBILITY_DRAFT19` is deprecated and should not be used
/// in newly-written code. It is kept for compatibility reasons and
/// represents the same compatibility as `NICE_COMPATIBILITY_RFC5245` </warning>
///  <note>
///    <para>
///    If `NICE_COMPATIBILITY_RFC5245` compatibility mode is used for a non-reliable
///    agent, then ICE-UDP will be used with higher priority and ICE-TCP will also
///    be used when the UDP connectivity fails. If it is used with a reliable agent,
///    then ICE-UDP will be used with the TCP-Over-UDP (`nice.PseudoTcpSocket`) if ICE-TCP
///    fails and ICE-UDP succeeds.
///   </para>
///  </note>
pub const Compatibility = enum(c_int) {
    rfc5245 = 0,
    google = 1,
    msn = 2,
    wlm2009 = 3,
    oc2007 = 4,
    oc2007r2 = 5,
    _,

    pub const draft19 = Compatibility.rfc5245;
    pub const last = Compatibility.oc2007r2;

    test {
        @setEvalBranchQuota(100_000);
        std.testing.refAllDecls(@This());
    }
};

/// An enum representing the state of a component.
/// <para> See also: `nice.Agent.signals.component`-state-changed </para>
pub const ComponentState = enum(c_int) {
    disconnected = 0,
    gathering = 1,
    connecting = 2,
    connected = 3,
    ready = 4,
    failed = 5,
    last = 6,
    _,

    test {
        @setEvalBranchQuota(100_000);
        std.testing.refAllDecls(@This());
    }
};

/// Convenience enum representing the type of a component for use as the
/// component_id for RTP/RTCP usages.
///  <example>
///    <title>Example of use.</title>
///    <programlisting>
///    nice_agent_send (agent, stream_id, NICE_COMPONENT_TYPE_RTP, len, buf);
///    </programlisting>
///   </example>
pub const ComponentType = enum(c_int) {
    rtp = 1,
    rtcp = 2,
    _,

    test {
        @setEvalBranchQuota(100_000);
        std.testing.refAllDecls(@This());
    }
};

/// An enum to specity the kind of nomination mode to use by
/// the agent, as described in RFC 5245. Two modes exists,
/// regular and aggressive. They differ by the way the controlling
/// agent chooses to put the USE-CANDIDATE attribute in its STUN
/// messages. The aggressive mode is supposed to nominate a pair
/// faster, than the regular mode, potentially causing the nominated
/// pair to change until the connection check completes.
pub const NominationMode = enum(c_int) {
    regular = 0,
    aggressive = 1,
    _,

    test {
        @setEvalBranchQuota(100_000);
        std.testing.refAllDecls(@This());
    }
};

/// An enum to specify which proxy type to use for relaying.
/// Note that the proxies will only be used with TCP TURN relaying.
/// <para> See also: `nice.Agent.properties.proxy`-type </para>
pub const ProxyType = enum(c_int) {
    none = 0,
    socks5 = 1,
    http = 2,
    _,

    pub const last = ProxyType.http;

    test {
        @setEvalBranchQuota(100_000);
        std.testing.refAllDecls(@This());
    }
};

/// Valid values of debug levels to be set.
pub const PseudoTcpDebugLevel = enum(c_int) {
    none = 0,
    normal = 1,
    verbose = 2,
    _,

    test {
        @setEvalBranchQuota(100_000);
        std.testing.refAllDecls(@This());
    }
};

/// Options for which parts of a connection to shut down when calling
/// `nice.PseudoTcpSocket.shutdown`. These correspond to the values passed to POSIX
/// `shutdown`.
pub const PseudoTcpShutdown = enum(c_int) {
    rd = 0,
    wr = 1,
    rdwr = 2,
    _,

    test {
        @setEvalBranchQuota(100_000);
        std.testing.refAllDecls(@This());
    }
};

/// An enum representing the state of the `nice.PseudoTcpSocket`. These states
/// correspond to the TCP states in RFC 793.
/// <para> See also: `nice.PseudoTcpSocket.properties.state` </para>
pub const PseudoTcpState = enum(c_int) {
    listen = 0,
    syn_sent = 1,
    syn_received = 2,
    established = 3,
    closed = 4,
    fin_wait_1 = 5,
    fin_wait_2 = 6,
    closing = 7,
    time_wait = 8,
    close_wait = 9,
    last_ack = 10,
    _,

    test {
        @setEvalBranchQuota(100_000);
        std.testing.refAllDecls(@This());
    }
};

/// An enum representing the result value of the write operation requested by
/// the `nice.PseudoTcpSocket`.
/// <para> See also: `nice.PseudoTcpCallbacks`:WritePacket </para>
pub const PseudoTcpWriteResult = enum(c_int) {
    success = 0,
    too_large = 1,
    fail = 2,
    _,

    test {
        @setEvalBranchQuota(100_000);
        std.testing.refAllDecls(@This());
    }
};

/// An enum representing the type of relay to use
pub const RelayType = enum(c_int) {
    udp = 0,
    tcp = 1,
    tls = 2,
    _,

    test {
        @setEvalBranchQuota(100_000);
        std.testing.refAllDecls(@This());
    }
};

/// These are options that can be passed to `nice.Agent.newFull`. They set
/// various properties on the agent. Not including them sets the property to
/// the other value.
pub const AgentOption = packed struct(c_uint) {
    regular_nomination: bool = false,
    reliable: bool = false,
    lite_mode: bool = false,
    ice_trickle: bool = false,
    support_renomination: bool = false,
    consent_freshness: bool = false,
    bytestream_tcp: bool = false,
    close_forced: bool = false,
    _padding8: bool = false,
    _padding9: bool = false,
    _padding10: bool = false,
    _padding11: bool = false,
    _padding12: bool = false,
    _padding13: bool = false,
    _padding14: bool = false,
    _padding15: bool = false,
    _padding16: bool = false,
    _padding17: bool = false,
    _padding18: bool = false,
    _padding19: bool = false,
    _padding20: bool = false,
    _padding21: bool = false,
    _padding22: bool = false,
    _padding23: bool = false,
    _padding24: bool = false,
    _padding25: bool = false,
    _padding26: bool = false,
    _padding27: bool = false,
    _padding28: bool = false,
    _padding29: bool = false,
    _padding30: bool = false,
    _padding31: bool = false,

    pub const flags_none: AgentOption = @bitCast(@as(c_uint, 0));
    pub const flags_regular_nomination: AgentOption = @bitCast(@as(c_uint, 1));
    pub const flags_reliable: AgentOption = @bitCast(@as(c_uint, 2));
    pub const flags_lite_mode: AgentOption = @bitCast(@as(c_uint, 4));
    pub const flags_ice_trickle: AgentOption = @bitCast(@as(c_uint, 8));
    pub const flags_support_renomination: AgentOption = @bitCast(@as(c_uint, 16));
    pub const flags_consent_freshness: AgentOption = @bitCast(@as(c_uint, 32));
    pub const flags_bytestream_tcp: AgentOption = @bitCast(@as(c_uint, 64));
    pub const flags_close_forced: AgentOption = @bitCast(@as(c_uint, 128));

    test {
        @setEvalBranchQuota(100_000);
        std.testing.refAllDecls(@This());
    }
};

/// Returns a string representation of the state, generally to use in debug
/// messages.
extern fn nice_component_state_to_string(p_state: nice.ComponentState) [*:0]const u8;
pub const componentStateToString = nice_component_state_to_string;

/// Disables libnice debug output to the terminal
extern fn nice_debug_disable(p_with_stun: c_int) void;
pub const debugDisable = nice_debug_disable;

/// Enables libnice debug output to the terminal. Note that the
/// `G_MESSAGES_DEBUG` and `NICE_DEBUG` environment variables must be set to the
/// set of logging domains to print, in order for any output to be printed. Set
/// them to `all` to print all debugging messages, or any of the following
/// domains:
/// - `libnice-stun`
/// - `libnice-tests`
/// - `libnice-socket`
/// - `libnice`
/// - `libnice-pseudotcp`
/// - `libnice-pseudotcp-verbose`
extern fn nice_debug_enable(p_with_stun: c_int) void;
pub const debugEnable = nice_debug_enable;

/// Returns the interface index match the local address passed. This can
/// by used for APIs that need a specific address.
extern fn nice_interfaces_get_if_index_by_addr(p_addr: *nice.Address) c_uint;
pub const interfacesGetIfIndexByAddr = nice_interfaces_get_if_index_by_addr;

/// Retrieves the IP address of an interface by its name. If this fails, `NULL`
/// is returned.
extern fn nice_interfaces_get_ip_for_interface(p_interface_name: [*:0]u8) ?[*:0]u8;
pub const interfacesGetIpForInterface = nice_interfaces_get_ip_for_interface;

/// Get the list of local interfaces
extern fn nice_interfaces_get_local_interfaces() *glib.List;
pub const interfacesGetLocalInterfaces = nice_interfaces_get_local_interfaces;

/// Get a list of local ipv4 interface addresses
extern fn nice_interfaces_get_local_ips(p_include_loopback: c_int) *glib.List;
pub const interfacesGetLocalIps = nice_interfaces_get_local_ips;

/// Sets the debug level to enable/disable normal/verbose debug messages.
extern fn pseudo_tcp_set_debug_level(p_level: nice.PseudoTcpDebugLevel) void;
pub const pseudoTcpSetDebugLevel = pseudo_tcp_set_debug_level;

/// Callback function when data is received on a component
pub const AgentRecvFunc = *const fn (p_agent: *nice.Agent, p_stream_id: c_uint, p_component_id: c_uint, p_len: c_uint, p_buf: [*:0]u8, p_user_data: ?*anyopaque) callconv(.c) void;

/// Was a limit on the number of remote candidates one can set, but is
/// no longer used by libnice itself.
pub const AGENT_MAX_REMOTE_CANDIDATES = 25;
/// The maximum size a candidate foundation can have.
pub const CANDIDATE_MAX_FOUNDATION = 33;
/// The maximum number of local addresses. The constraint is that the
/// maximum number of local addresses and number of turn servers must
/// fit on 9 bits, to ensure candidate priority uniqueness. See also
/// `NICE_CANDIDATE_MAX_TURN_SERVERS`. We choose 6 bits for the number of
/// local addresses, and 3 bits for the number of turn servers.
pub const CANDIDATE_MAX_LOCAL_ADDRESSES = 64;
/// The maximum number of turns servers.
pub const CANDIDATE_MAX_TURN_SERVERS = 8;

test {
    @setEvalBranchQuota(100_000);
    std.testing.refAllDecls(@This());
    std.testing.refAllDecls(ext);
}
