/*
 * CDDL HEADER START
 *
 * The contents of this file are subject to the terms of the
 * Common Development and Distribution License (the "Licence").
 * You may not use this file except in compliance with the Licence.
 *
 * You can obtain a copy of the licence at RISC OS path @.^.LICENCE
 * or  http://www.riscosdev.com/lanman98/LICENCE.CDDL
 * See the Licence for the specific language governing permissions
 * and limitations under the Licence.
 *
 * CDDL HEADER END
 */

/*
 *   Portions Copyright RISC OS Developments 2019+, credited to the RISC OS One Project.
 *
 *   Finding servers without being told where they are.
 *
 *   Machines that offer file sharing say so on the local network, and have
 *   done for years: a question is asked of everybody at once and whoever
 *   offers the service answers.  That is how a Mac, a Synology or a QNAP
 *   appears in somebody else's list without being configured anywhere.
 *
 *   The question goes to everybody, but because it is asked from an
 *   ordinary port rather than the one the service uses, the answers come
 *   back to that port alone.  Nothing has to be joined or listened to
 *   beyond the socket the question went out of, which is the only reason
 *   this fits in the space available.
 */

#ifndef _DISCOVER_
#define _DISCOVER_

typedef struct found_s
{
    struct found_s *next;
    char *name;                 /* what the machine calls itself */
    char addr[20];              /* its address, in dotted form */
    int port;
} *found_t;

found_t DiscoverServers(int wait_cs);
/*
    Ask, wait the given number of centiseconds, and return what answered.
    NULL if nothing did, which is not an error - a network may have nothing
    on it that announces itself.
*/

char *DiscoverResolve(const char *name, int wait_cs);
/*
    Ask the network what address one machine is at, by name, and return it
    in dotted form for the caller to free - or NULL if nothing answered.

    This is the same question the announcements are made of, asked about a
    single name rather than about everything at once, and it is how a name
    ending in .local is meant to be looked up.  It is also worth asking for
    a plain name: a machine that answers to "webserver" here is usually the
    same one that answers to "webserver.local", and on a network with no
    name server and no NetBIOS it is the only thing that will answer at
    all.
*/

void DiscoverFree(found_t list);

typedef struct sweep_s *sweep_t;

sweep_t DiscoverBegin(int wait_cs);
/*
    Ask, and return somewhere to collect the answers - the same question
    DiscoverServers asks, but without waiting for anybody to reply.  This
    is for a caller that cannot block: a sweep run from a callback asks
    here, returns to the machine, and comes back through DiscoverPoll.

    Throws if the question could not be asked at all.
*/

int DiscoverPoll(sweep_t sw);
/*
    Take whatever has arrived since last time, without waiting.  Returns
    non-zero while the collecting period asked for still has time left in
    it, so a caller loops until it returns 0 and then calls DiscoverEnd.
*/

found_t DiscoverEnd(sweep_t sw);
/*
    Finish a sweep and hand back what answered, for DiscoverFree.  The
    sweep itself is destroyed.
*/

void DiscoverAbandon(sweep_t sw);
/*
    Throw a sweep away along with anything it had collected.  Safe on NULL,
    and the way to drop one that is still in progress.
*/

#endif
