Skip to content

Track amount of bandwidth utilized overall and by a specific user. #150

Closed

Description

@jipson7

Summary

Would like to know how to track the bandwidth used by a user on the turn server. Or simply overall bandwidth to start.

Motivation

Primarily for billing and book keeping.

Describe alternatives you've considered

I looked at the turn-server logging example but couldn't see anything obvious that would lend itself to tracking bandwidth.

Activity

  1. Sean-Der commented on Jan 13, 2026

    @Sean-Der
    Member

    @rg0now @adrianosela What do you think about this one?

    An API that allows me to know

    • Usage per Allocation
    • Usage to Destination
    • usage from Destination
    • ?

    Adding something like this to EventHandler?

          - OnTraffic func(srcAddr, dstAddr net.Addr, protocol, username, realm string, relayAddr, peerAddr net.Addr, direction TrafficDirection, bytes int)
          - TrafficDirection enum: ClientToPeer, PeerToClient
    
  2. adrianosela commented on Jan 13, 2026

    @adrianosela
    Contributor

    @Sean-Der , do we want to add to the api the ability to drop the traffic too? if it exceeds bandwidth limits for example. Or is there already another mechanism to do something like that?

  3. Sean-Der commented on Jan 13, 2026

    @Sean-Der
    Member

    None exists! I am torn between the following

    • Expose a Allocation object?
    • Add APIs like CloseAllocation on the server?

    What feels right to me is GetAllocation(FiveTuple) on the server. We start really simple and just have this?

    struct Allocation {}
    
    func (a *Allocation) Close() error {} 
    

    We can add more in the future

    @rg0now ?

  4. Sean-Der commented on Jan 13, 2026

    @Sean-Der
    Member

    maybe we save for next release @adrianosela I really would like to have you announce a new release in next day or so.

    As long as we can add this other stuff as non-breaking changes, we should hold off! We can do an exciting v5.1 in a month.

  5. rg0now commented on Jan 13, 2026

    @rg0now
    Contributor

    I think the right way to do this is to gently regulating users' traffic to remain under the quota instead of abruptly terminating allocations exceeding it (which one? a user may have tons of allocations and bw quotas apply to the total traffic). The way I'd implement this is wrapping the connections returned from RelayAddressGenerator.AllocatePacketConn and RelayAddressGenerator.AllocateConn with a rate-limiter that consumes tokens from a per-user token bucket and drops packets that exceed the quota. (Do we need 2 token buckets, one for the Read and one for the Write direction??) I'll try to contribute an example.

    Note that the same "wrapped" net.(?Packet)Conn idea can also be used for bw tracking and (in a somewhat hackish way) also for terminating allocations externally. Abstracting essentially all networking in pion/turn over net.Conn and net.PacketConn interfaces is an incredibly elegant and powerful design. I don't know who came up with this but the person was/is a pure genius.

  6. rg0now commented on Jan 13, 2026

    @rg0now
    Contributor

    Hmm, now that I'm thinking of this: we do not pass the username and realm to Allocate(?Packet)Conn. Should we? If yes, this is the best time to do this. Caller site still has the user data.

    CC @Sean-Der @JoTurk

  7. rg0now commented on Jan 13, 2026

    @rg0now
    Contributor

    See #531

  8. rg0now commented on Jan 13, 2026

    @rg0now
    Contributor

    See also #532

  9. JoTurk commented on Jan 13, 2026

    @JoTurk
    Member

    Hmm, now that I'm thinking of this: we do not pass the username and realm to Allocate(?Packet)Conn. Should we? If yes, this is the best time to do this. Caller site still has the user data.

    My 2 cents: this should be the auth layer's job. We should pass whatever identifier the auth layer returns into allocation (could be username, or an internal/opaque user ID), rather than baking username/realm into the allocation API.

  10. rg0now commented on Jan 14, 2026

    @rg0now
    Contributor

    My 2 cents: this should be the auth layer's job. We should pass whatever identifier the auth layer returns into allocation (could be username, or an internal/opaque user ID), rather than baking username/realm into the allocation API.

    @JoTurk @Sean-Der That's a very good point. You mean if one uses standard time-windowed credentials then the username is formatted as timestamp:user-id and then we pass that "username" as we parse it out from the TURN packet, along with the timestamp, through the entire allocation stack, i.e., to the quota handler, to the allocation handlers, and the EventHanlder API. Of course the user can parse the real user-id back but this still sounds silly.

    Should we change the AuthHandler signature to return the userId as well? Then we could store that in the allocation and pass that to the handlers. I'm not sure I see all the possible consequences (good, bad and catastrophic) of such a change. Wdyt?

  11. rg0now commented on Jan 15, 2026

    @rg0now
    Contributor

    Fixed in #532

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions

      ⌂ 换网址