⚡ Sangsakala Proxy 🏠 Home
Skip to content

Multi service browsers of the same type create excessive queries #721

Closed

Description

@bdraco

If we are already browsing for a type we should suppress additional question generation. We need to call soon thread safe coordination when adding and removing a service browser

Activity

  1. bdraco commented on Jun 18, 2021

    @bdraco
    MemberAuthor

    Maybe move ServiceBrowser* into _services.browser and the. Add a ServiceBrowserCoorindator class that manages the next times

  2. bdraco commented on Jun 18, 2021

    @bdraco
    MemberAuthor

    Example here is that home assistant uses a browser for discovery and pychromecast starts another one

  3. bdraco commented on Jun 19, 2021

    @bdraco
    MemberAuthor

    This is a bit better after #737 since it will at least share known answers, but its still going to generate more queries

  4. bdraco commented on Jun 19, 2021

    @bdraco
    MemberAuthor

    At least after #737 we are sending the queries at the same time so there is a greater chance of Duplicate Question Suppression https://datatracker.ietf.org/doc/html/rfc6762#section-7.3

    grep _googlecast._tcp.local home-assistant.log

    2021-06-19 08:49:24 DEBUG (MainThread) [zeroconf] Sending to (None, 5353) (40 bytes #1) <DNSOutgoing:{multicast=True, flags=0, questions=[ptr[question,QM,in,_googlecast._tcp.local.]], answers=[], authorities=[], additionals=[]}> as b'\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x0b_googlecast\x04_tcp\x05local\x00\x00\x0c\x00\x01'...
    2021-06-19 08:49:24 DEBUG (MainThread) [zeroconf] Received from '192.168.107.5':5353 (socket 25): <DNSIncoming:{id=0, flags=0, truncated=False, n_q=1, n_ans=0, n_auth=0, n_add=0, questions=[ptr[question,QM,in,_googlecast._tcp.local.]], answers=[]}> (40 bytes) as [b'\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x0b_googlecast\x04_tcp\x05local\x00\x00\x0c\x00\x01']
    2021-06-19 08:49:24 DEBUG (MainThread) [zeroconf] Sending to (None, 5353) (40 bytes #1) <DNSOutgoing:{multicast=True, flags=0, questions=[ptr[question,QM,in,_googlecast._tcp.local.]], answers=[], authorities=[], additionals=[]}> as b'\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x0b_googlecast\x04_tcp\x05local\x00\x00\x0c\x00\x01'...
    2021-06-19 08:49:24 DEBUG (MainThread) [zeroconf] Received from '192.168.107.3':5353 (socket 25): <DNSIncoming:{id=0, flags=33792, truncated=False, n_q=0, n_ans=1, n_auth=0, n_add=3, questions=[], answers=[record[ptr,in,_googlecast._tcp.local.]=120/119,Zolo-Mojo-8f3ff1fca49f3b5932a9ddf0a552c4e4._googlecast._tcp.local., record[txt,in-unique,Zolo-Mojo-8f3ff1fca49f3b5932a9ddf0a552c4e4._googlecast._tcp.local.]=4500/4499,b'#id=8f3'..., record[srv,in-unique,Zolo-Mojo-8f3ff1fca49f3b5932a9ddf0a552c4e4._googlecast._tcp.local.]=120/119,8f3ff1fc-a49f-3b59-32a9-ddf0a552c4e4.local.:8009, record[a,in-unique,8f3ff1fc-a49f-3b59-32a9-ddf0a552c4e4.local.]=120/119,192.168.107.3]}> (364 bytes) as [b'\x00\x00\x84\x00\x00\x00\x00\x01\x00\x00\x00\x03\x0b_googlecast\x04_tcp\x05local\x00\x00\x0c\x00\x01\x00\x00\x00x\x00-*Zolo-Mojo-8f3ff1fca49f3b5932a9ddf0a552c4e4\xc0\x0c\xc0.\x00\x10\x80\x01\x00\x00\x11\x94\x00\xbc#id=8f3ff1fca49f3b5932a9ddf0a552c4e4#cd=0CC3AD1C84EA89BBDC61582A2B5D3387\x13rm=B63D199BF3B3D7A5\x05ve=05\x0cmd=Zolo Mojo\x12ic=/setup/icon.png\x13fn=Backyard Speaker\x07ca=2052\x04st=0\x0fbs=FA8FCA6CEA94\x04nf=1\x03rs=\xc0.\x00!\x80\x01\x00\x00\x00x\x00-\x00\x00\x00\x00\x1fI$8f3ff1fc-a49f-3b59-32a9-ddf0a552c4e4\xc0\x1d\xc15\x00\x01\x80\x01\x00\x00\x00x\x00\x04\xc0\xa8k\x03']
    2021-06-19 08:50:54 DEBUG (MainThread) [zeroconf] Sending to (None, 5353) (40 bytes #1) <DNSOutgoing:{multicast=True, flags=0, questions=[ptr[question,QM,in,_googlecast._tcp.local.]], answers=[], authorities=[], additionals=[]}> as b'\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x0b_googlecast\x04_tcp\x05local\x00\x00\x0c\x00\x01'...
    2021-06-19 08:50:54 DEBUG (MainThread) [zeroconf] Received from '192.168.107.5':5353 (socket 25): <DNSIncoming:{id=0, flags=0, truncated=False, n_q=1, n_ans=0, n_auth=0, n_add=0, questions=[ptr[question,QM,in,_googlecast._tcp.local.]], answers=[]}> (40 bytes) as [b'\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x0b_googlecast\x04_tcp\x05local\x00\x00\x0c\x00\x01']
    2021-06-19 08:50:54 DEBUG (MainThread) [zeroconf] Sending to (None, 5353) (40 bytes #1) <DNSOutgoing:{multicast=True, flags=0, questions=[ptr[question,QM,in,_googlecast._tcp.local.]], answers=[], authorities=[], additionals=[]}> as b'\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x0b_googlecast\x04_tcp\x05local\x00\x00\x0c\x00\x01'...
    2021-06-19 08:50:54 DEBUG (MainThread) [zeroconf] Received from '192.168.107.3':5353 (socket 25): <DNSIncoming:{id=0, flags=33792, truncated=False, n_q=0, n_ans=1, n_auth=0, n_add=3, questions=[], answers=[record[ptr,in,_googlecast._tcp.local.]=120/119,Zolo-Mojo-8f3ff1fca49f3b5932a9ddf0a552c4e4._googlecast._tcp.local., record[txt,in-unique,Zolo-Mojo-8f3ff1fca49f3b5932a9ddf0a552c4e4._googlecast._tcp.local.]=4500/4499,b'#id=8f3'..., record[srv,in-unique,Zolo-Mojo-8f3ff1fca49f3b5932a9ddf0a552c4e4._googlecast._tcp.local.]=120/119,8f3ff1fc-a49f-3b59-32a9-ddf0a552c4e4.local.:8009, record[a,in-unique,8f3ff1fc-a49f-3b59-32a9-ddf0a552c4e4.local.]=120/119,192.168.107.3]}> (364 bytes) as [b'\x00\x00\x84\x00\x00\x00\x00\x01\x00\x00\x00\x03\x0b_googlecast\x04_tcp\x05local\x00\x00\x0c\x00\x01\x00\x00\x00x\x00-*Zolo-Mojo-8f3ff1fca49f3b5932a9ddf0a552c4e4\xc0\x0c\xc0.\x00\x10\x80\x01\x00\x00\x11\x94\x00\xbc#id=8f3ff1fca49f3b5932a9ddf0a552c4e4#cd=0CC3AD1C84EA89BBDC61582A2B5D3387\x13rm=B63D199BF3B3D7A5\x05ve=05\x0cmd=Zolo Mojo\x12ic=/setup/icon.png\x13fn=Backyard Speaker\x07ca=2052\x04st=0\x0fbs=FA8FCA6CEA94\x04nf=1\x03rs=\xc0.\x00!\x80\x01\x00\x00\x00x\x00-\x00\x00\x00\x00\x1fI$8f3ff1fc-a49f-3b59-32a9-ddf0a552c4e4\xc0\x1d\xc15\x00\x01\x80\x01\x00\x00\x00x\x00\x04\xc0\xa8k\x03']
    
    
  5. bdraco commented on Jun 19, 2021

    @bdraco
    MemberAuthor

    Need to be careful not to coordinate QU / addr browsers

  6. bdraco commented on Jun 19, 2021

    @bdraco
    MemberAuthor

    If we have a ServiceQueryCoordinator that does all the sends in event loop, the ServiceBrowser thread can simplify be a SimpleQueue that reads and fires handlers. Maybe reuse the original async sender code

  7. bdraco commented on Jun 19, 2021

    @bdraco
    MemberAuthor

    That would make everything much simpler and we would be using the preferred pythonic way to communicate between threads.

  8. bdraco commented on Jun 19, 2021

    @bdraco
    MemberAuthor

    Maybe a set_next_time for type_, addr, port?

  9. bdraco commented on Jun 19, 2021

    @bdraco
    MemberAuthor

    We still have to solve the waiting in serviceinfo as well. We could import the async code and run it in the event loop with run coroutine thread safe. We would need the same safety to throw if someone tried to do that from the event loop. Like we have with the close function

    Then we can get rid of all the notify wakes which are really expensive when there is a lot of traffic

  10. bdraco commented on Jun 19, 2021

    @bdraco
    MemberAuthor

    I think we just move the next time. Also we can stop the waits since we can use asyncio.Event.

  11. bdraco commented on Jun 19, 2021

    @bdraco
    MemberAuthor

    We can make this so much simpler now

    async_update_records_complete can just add to the queue or fire the event.

    Then we have the browser coordinator sending the queries in a task

    In the record processing we can tell the coordinator to schedule a query sooner and set a condition to wake it up

  12. bdraco commented on Jun 20, 2021

    @bdraco
    MemberAuthor

    Maybe

    QuestionType.QM, QuestionType.QU

    cancel = ServiceBrowserCoordinator.async_register(types, addr, port, QuestionType.QM)

    cancel() to deregister

    Then we do
    start send loop task if none running, otherwise update the data structs, reset the delay/next_time for everything just registered, and async_notify_all

    on deregister
    update data structs, cancel the task if nothing left.

    on loop.
    Similar to now, but when a type is ready we built sets of qu or qm questions for each target group (addr, port, QuestionType.QM) for any like sets, then fire off the questions to the addr/port/type for each group we built. As an optimization we could see which target groups have the same sets of questions and only build them once and still fire off to all the dests.

  13. bdraco commented on Jun 20, 2021

    @bdraco
    MemberAuthor

    Probably enumerate types and then create buckets of question types and put each type into the bucket. Then generate questions from buckets and send

  14. bdraco commented on Jun 20, 2021

    @bdraco
    MemberAuthor

    Started building the Coordinator and I think its the wrong solution

    We need internal duplicate question suppression

    https://datatracker.ietf.org/doc/html/rfc6762#section-7.3

  15. bdraco commented on Jun 20, 2021

    @bdraco
    MemberAuthor
    # grep 'was suppressed by the question history' home-assistant.log 
    2021-06-20 18:16:39 DEBUG (MainThread) [zeroconf] Asking ptr[question,QM,in,_googlecast._tcp.local.] was suppressed by the question history
    
    

    That does it and it works for other types as well

  16. bdraco commented on Jun 20, 2021

    @bdraco
    MemberAuthor
    2021-06-20 18:25:37 DEBUG (MainThread) [zeroconf] Asking ptr[question,QM,in,_googlecast._tcp.local.] was suppressed by the question history
    2021-06-20 18:25:37 DEBUG (MainThread) [zeroconf] Asking ptr[question,QM,in,_googlecast._tcp.local.] was suppressed by the question history
    2021-06-20 18:28:37 DEBUG (MainThread) [zeroconf] Asking ptr[question,QM,in,_googlecast._tcp.local.] was suppressed by the question history
    2021-06-20 18:28:37 DEBUG (MainThread) [zeroconf] Asking ptr[question,QM,in,_googlecast._tcp.local.] was suppressed by the question history
    2021-06-20 18:34:37 DEBUG (MainThread) [zeroconf] Asking ptr[question,QM,in,_googlecast._tcp.local.] was suppressed by the question history
    2021-06-20 18:34:37 DEBUG (MainThread) [zeroconf] Asking ptr[question,QM,in,_googlecast._tcp.local.] was suppressed by the question history
    
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions