mirror of
https://github.com/openharmony/third_party_sane-airscan.git
synced 2026-06-30 21:17:55 -04:00
WSDD: management of extended discovery time revisited (see also #151e440)
See #151e440 for problem description and workaround method being used The criterion of applying extended time was simplified. Instead of looking for unpaired WSDD/MDNS device we simply compare count of WSDD/MDNS devices, discovered so far, with problematic model names This change not only makes things conceptually simpler, but also allows to take in account MDNS-devices early, with not yet completed discovery/resolving process
This commit is contained in:
@@ -16,6 +16,7 @@
|
||||
#include <avahi-common/domain.h>
|
||||
#include <avahi-common/error.h>
|
||||
|
||||
#include <fnmatch.h>
|
||||
#include <string.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdlib.h>
|
||||
@@ -70,6 +71,7 @@ typedef struct {
|
||||
*/
|
||||
static log_ctx *mdns_log;
|
||||
static ll_head mdns_finding_list;
|
||||
static size_t mdns_finding_list_count;
|
||||
static const AvahiPoll *mdns_avahi_poll;
|
||||
static AvahiTimeout *mdns_avahi_restart_timer;
|
||||
static AvahiClient *mdns_avahi_client;
|
||||
@@ -368,6 +370,7 @@ mdns_finding_get (ZEROCONF_METHOD method, int ifindex, const char *name,
|
||||
mdns = mdns_finding_new(method, ifindex, name, initscan);
|
||||
|
||||
ll_push_end(&mdns_finding_list, &mdns->node_list);
|
||||
mdns_finding_list_count ++;
|
||||
|
||||
return mdns;
|
||||
}
|
||||
@@ -401,7 +404,10 @@ mdns_finding_del (mdns_finding *mdns)
|
||||
if (mdns->is_published) {
|
||||
zeroconf_finding_withdraw(&mdns->finding);
|
||||
}
|
||||
|
||||
ll_del(&mdns->node_list);
|
||||
mdns_finding_list_count --;
|
||||
|
||||
mdns_finding_kill_resolvers(mdns);
|
||||
mdns_finding_free(mdns);
|
||||
}
|
||||
@@ -1281,6 +1287,68 @@ mdns_query_get_ptr (const mdns_query *query)
|
||||
return query->ptr;
|
||||
}
|
||||
|
||||
/***** Miscellaneous *****/
|
||||
|
||||
/* mdns_device_count_by_model returns count of distinct devices
|
||||
* with model names matching the specified parent.
|
||||
*
|
||||
* Several instances of the same device (i.e. printer vs scanner) are
|
||||
* counted only once per network interface.
|
||||
*
|
||||
* WSDD uses this function to decide when to use extended discovery
|
||||
* time (some devices are known to be hard for WD-Discovery)
|
||||
*
|
||||
* Pattern is the glob-style expression, applied to the model name
|
||||
* of discovered devices.
|
||||
*/
|
||||
unsigned int
|
||||
mdns_device_count_by_model (int ifindex, const char *pattern)
|
||||
{
|
||||
mdns_finding **findings;
|
||||
unsigned int findings_count = 0;
|
||||
unsigned int i, answer;
|
||||
ll_node *node;
|
||||
|
||||
/* Collect matching devices */
|
||||
if (mdns_finding_list_count == 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
findings = alloca(sizeof(*findings) * mdns_finding_list_count);
|
||||
|
||||
for (LL_FOR_EACH(node, &mdns_finding_list)) {
|
||||
mdns_finding *mdns = OUTER_STRUCT(node, mdns_finding, node_list);
|
||||
|
||||
if (mdns->finding.ifindex == ifindex &&
|
||||
mdns->finding.model != NULL &&
|
||||
fnmatch(pattern, mdns->finding.model, 0) == 0) {
|
||||
|
||||
findings[findings_count] = mdns;
|
||||
findings_count ++;
|
||||
}
|
||||
}
|
||||
|
||||
/* Sort by ifindex + name, then count only distinct devices */
|
||||
qsort(findings, findings_count, sizeof(*findings),
|
||||
zeroconf_finding_qsort_by_index_name);
|
||||
|
||||
if (findings_count <= 1) {
|
||||
return findings_count;
|
||||
}
|
||||
|
||||
answer = 1;
|
||||
for (i = 1; i < findings_count; i ++) {
|
||||
mdns_finding **p1 = &findings[i - 1];
|
||||
mdns_finding **p2 = &findings[i];
|
||||
|
||||
if (zeroconf_finding_qsort_by_index_name(p1, p2) != 0) {
|
||||
answer ++;
|
||||
}
|
||||
}
|
||||
|
||||
return answer;
|
||||
}
|
||||
|
||||
/***** Initialization and cleanup *****/
|
||||
|
||||
/* Initialize MDNS
|
||||
|
||||
+49
-3
@@ -11,6 +11,7 @@
|
||||
#include "airscan.h"
|
||||
|
||||
#include <errno.h>
|
||||
#include <fnmatch.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
@@ -42,6 +43,7 @@
|
||||
typedef struct {
|
||||
int fd; /* File descriptor */
|
||||
int ifindex; /* Interface index */
|
||||
netif_name ifname; /* Interface name, for logging */
|
||||
bool ipv6; /* We are on IPv6 */
|
||||
eloop_fdpoll *fdpoll; /* Socket fdpoll */
|
||||
eloop_timer *timer; /* Retransmit timer */
|
||||
@@ -1177,12 +1179,39 @@ wsdd_resolver_read_callback (int fd, void *data, ELOOP_FDPOLL_MASK mask)
|
||||
}
|
||||
}
|
||||
|
||||
/* Count discovered devices with model names matching the specified parent.
|
||||
*
|
||||
* Pattern is the glob-style expression, applied to the model name
|
||||
* of discovered devices.
|
||||
*/
|
||||
static unsigned int
|
||||
wsdd_resolver_count_devices_by_model (wsdd_resolver *resolver, const char *pattern)
|
||||
{
|
||||
unsigned int answer = 0;
|
||||
ll_node *node;
|
||||
wsdd_finding *wsdd;
|
||||
|
||||
/* Lookup existent finding */
|
||||
for (LL_FOR_EACH(node, &wsdd_finding_list)) {
|
||||
wsdd = OUTER_STRUCT(node, wsdd_finding, list_node);
|
||||
if (wsdd->finding.ifindex == resolver->ifindex &&
|
||||
wsdd->finding.model != NULL &&
|
||||
wsdd->published &&
|
||||
fnmatch(pattern, wsdd->finding.model, 0) == 0) {
|
||||
answer ++;
|
||||
}
|
||||
}
|
||||
|
||||
return answer;
|
||||
}
|
||||
|
||||
/* Retransmit timer callback
|
||||
*/
|
||||
static void
|
||||
wsdd_resolver_timer_callback (void *data)
|
||||
{
|
||||
wsdd_resolver *resolver = data;
|
||||
const char pattern[] = "Pantum*";
|
||||
|
||||
resolver->timer = NULL;
|
||||
|
||||
@@ -1190,9 +1219,25 @@ wsdd_resolver_timer_callback (void *data)
|
||||
* Should we use extended discovery time?
|
||||
*/
|
||||
if (resolver->time_elapsed >= resolver->time_limit &&
|
||||
resolver->time_limit < WSDD_DISCOVERY_TIME_EX &&
|
||||
zeroconf_device_exist_unpaired_mdns(resolver->ifindex, "Pantum*")) {
|
||||
resolver->time_limit = WSDD_DISCOVERY_TIME_EX;
|
||||
resolver->time_limit < WSDD_DISCOVERY_TIME_EX) {
|
||||
unsigned int cnt_mdns, cnt_wsdd;
|
||||
|
||||
cnt_mdns = mdns_device_count_by_model(resolver->ifindex, pattern);
|
||||
cnt_wsdd = wsdd_resolver_count_devices_by_model(resolver, pattern);
|
||||
|
||||
if (cnt_wsdd < cnt_mdns) {
|
||||
const char *proto = resolver->ipv6 ? "ipv6" : "ipv4";
|
||||
|
||||
log_debug(wsdd_log, "%s@%s: \"%s\": MDNS/WSDD count: %d/%d",
|
||||
proto, resolver->ifname.text,
|
||||
pattern, cnt_mdns, cnt_wsdd);
|
||||
|
||||
log_debug(wsdd_log, "%s@%s: extending discovery time (%d->%d ms)",
|
||||
proto, resolver->ifname.text,
|
||||
resolver->time_limit, WSDD_DISCOVERY_TIME_EX);
|
||||
|
||||
resolver->time_limit = WSDD_DISCOVERY_TIME_EX;
|
||||
}
|
||||
}
|
||||
|
||||
/* Time limit not reached yet? */
|
||||
@@ -1296,6 +1341,7 @@ wsdd_resolver_new (const netif_addr *addr, bool initscan)
|
||||
|
||||
/* Build resolver structure */
|
||||
resolver->ifindex = addr->ifindex;
|
||||
resolver->ifname = addr->ifname;
|
||||
resolver->time_limit = WSDD_DISCOVERY_TIME;
|
||||
|
||||
/* Open a socket */
|
||||
|
||||
+22
-53
@@ -393,59 +393,6 @@ zeroconf_device_is_blacklisted (zeroconf_device *device)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Check if there are unpaired MDNS-only devices with model names
|
||||
* matching the specified parent.
|
||||
*
|
||||
* WSDD uses this function to decide when to use extended discovery
|
||||
* time (some devices are known to be hard for WD-Discovery)
|
||||
*
|
||||
* Pattern is the glob-style expression, applied to the model name
|
||||
* of discovered devices.
|
||||
*/
|
||||
bool
|
||||
zeroconf_device_exist_unpaired_mdns (int ifindex, const char *pattern)
|
||||
{
|
||||
ll_node *node, *node2;
|
||||
zeroconf_device *device;
|
||||
zeroconf_finding *finding;
|
||||
|
||||
for (LL_FOR_EACH(node, &zeroconf_device_list)) {
|
||||
device = OUTER_STRUCT(node, zeroconf_device, node_list);
|
||||
|
||||
/* If not the MDNS device or device already paired with the
|
||||
* WSDD buddy -- skip the device
|
||||
*/
|
||||
if (!zeroconf_device_is_mdns(device) || device->buddy != NULL) {
|
||||
continue;
|
||||
}
|
||||
|
||||
/* If model name doesn't match - skip the device
|
||||
*/
|
||||
if (device->model == NULL ||
|
||||
fnmatch(pattern, zeroconf_device_model(device), 0) != 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
/* The last check: does the device seen on the specified interface?
|
||||
*/
|
||||
for (LL_FOR_EACH(node2, &device->findings)) {
|
||||
finding = OUTER_STRUCT(node2, zeroconf_finding, list_node);
|
||||
|
||||
if (finding->ifindex == ifindex) {
|
||||
log_debug(zeroconf_log,
|
||||
"Found unpaired MDNS device; WSDD discovery time extended");
|
||||
log_debug(zeroconf_log,
|
||||
"Unpaired MDNS device: \"%s\" (interface %d)",
|
||||
device->model, ifindex);
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/******************** Merging devices *********************/
|
||||
/* Recompute device->buddy for all devices
|
||||
*/
|
||||
@@ -880,6 +827,28 @@ zeroconf_find_static_by_ident (const char *ident)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/***** Miscellaneous functions for zeroconf_finding *****/
|
||||
|
||||
/* Compare two pointers to pointers to zeroconf_finding (zeroconf_finding**)
|
||||
* by index+name, for qsort
|
||||
*/
|
||||
int
|
||||
zeroconf_finding_qsort_by_index_name (const void *p1, const void *p2)
|
||||
{
|
||||
const zeroconf_finding *f1 = *(const zeroconf_finding * const *) p1;
|
||||
const zeroconf_finding *f2 = *(const zeroconf_finding * const *) p2;
|
||||
|
||||
if (f1->ifindex < f2->ifindex) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (f1->ifindex > f2->ifindex) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
return strcmp(f1->name, f2->name);
|
||||
}
|
||||
|
||||
/******************** Events from discovery providers *********************/
|
||||
/* Publish the zeroconf_finding.
|
||||
*/
|
||||
|
||||
@@ -2852,6 +2852,12 @@ typedef struct {
|
||||
ll_node list_node; /* Node in device's list of findings */
|
||||
} zeroconf_finding;
|
||||
|
||||
/* Compare two pointers to pointers to zeroconf_finding (zeroconf_finding**)
|
||||
* by index+name, for qsort
|
||||
*/
|
||||
int
|
||||
zeroconf_finding_qsort_by_index_name (const void *p1, const void *p2);
|
||||
|
||||
/* Publish the zeroconf_finding.
|
||||
*
|
||||
* Memory, referred by the finding, remains owned by
|
||||
@@ -2896,18 +2902,6 @@ zeroconf_init (void);
|
||||
void
|
||||
zeroconf_cleanup (void);
|
||||
|
||||
/* Check if there are unpaired MDNS-only devices with model names
|
||||
* matching the specified parent.
|
||||
*
|
||||
* WSDD uses this function to decide when to use extended discovery
|
||||
* time (some devices are known to be hard for WD-Discovery)
|
||||
*
|
||||
* Pattern is the glob-style expression, applied to the model name
|
||||
* of discovered devices.
|
||||
*/
|
||||
bool
|
||||
zeroconf_device_exist_unpaired_mdns (int ifindex, const char *pattern);
|
||||
|
||||
/* Get list of devices, in SANE format
|
||||
*/
|
||||
const SANE_Device**
|
||||
@@ -3067,6 +3061,21 @@ mdns_query_get_answer (const mdns_query *query);
|
||||
void*
|
||||
mdns_query_get_ptr (const mdns_query *query);
|
||||
|
||||
/* mdns_device_count_by_model returns count of distinct devices
|
||||
* with model names matching the specified parent.
|
||||
*
|
||||
* Several instances of the same device (i.e. printer vs scanner) are
|
||||
* counted only once per network interface.
|
||||
*
|
||||
* WSDD uses this function to decide when to use extended discovery
|
||||
* time (some devices are known to be hard for WD-Discovery)
|
||||
*
|
||||
* Pattern is the glob-style expression, applied to the model name
|
||||
* of discovered devices.
|
||||
*/
|
||||
unsigned int
|
||||
mdns_device_count_by_model (int ifindex, const char *pattern);
|
||||
|
||||
/******************** WS-Discovery ********************/
|
||||
/* Called by zeroconf to notify wsdd about initial scan timer expiration
|
||||
*/
|
||||
|
||||
Reference in New Issue
Block a user