@@ -41,6 +41,12 @@ namespace {
41
41
42
42
constexpr uint8_t kDnssdKeyMaxSize = 32 ;
43
43
44
+ // The number of miliseconds which must elapse without a new "found" event before
45
+ // mDNS browsing is considered finished. We need this timeout because Tizen Native
46
+ // API does not deliver all-for-now signal (such signal is delivered by e.g. Avahi)
47
+ // and the browsing callback is called multiple times (once for each service found).
48
+ constexpr unsigned int kDnssdBrowseTimeoutMs = 250 ;
49
+
44
50
bool IsSupportedProtocol (DnssdServiceProtocol protocol)
45
51
{
46
52
return (protocol == DnssdServiceProtocol::kDnssdProtocolUdp ) || (protocol == DnssdServiceProtocol::kDnssdProtocolTcp );
@@ -109,6 +115,22 @@ gboolean RegisterAsync(GMainLoop * mainLoop, gpointer userData)
109
115
return true ;
110
116
}
111
117
118
+ gboolean OnBrowseTimeout (void * userData)
119
+ {
120
+ ChipLogDetail (DeviceLayer, " DNSsd %s: all for now" , __func__);
121
+
122
+ auto * bCtx = reinterpret_cast <BrowseContext *>(userData);
123
+
124
+ bCtx->MainLoopQuit ();
125
+ bCtx->mCallback (bCtx->mCbContext , bCtx->mServices .data (), bCtx->mServices .size (), CHIP_NO_ERROR);
126
+
127
+ // After this point the context might be no longer valid
128
+ bCtx->mInstance ->RemoveContext (bCtx);
129
+
130
+ // This is a one-shot timer
131
+ return FALSE ;
132
+ }
133
+
112
134
void OnBrowseAdd (BrowseContext * context, const char * type, const char * name, uint32_t interfaceId)
113
135
{
114
136
ChipLogDetail (DeviceLayer, " DNSsd %s: name: %s, type: %s, interfaceId: %u" , __func__, name, type, interfaceId);
@@ -143,8 +165,20 @@ void OnBrowse(dnssd_service_state_e state, dnssd_service_h service, void * data)
143
165
auto bCtx = reinterpret_cast <BrowseContext *>(data);
144
166
int ret;
145
167
146
- // Always stop browsing
147
- bCtx->MainLoopQuit ();
168
+ // If there is already a timeout source, so we need to cancel it.
169
+ if (bCtx->mTimeoutSource != nullptr )
170
+ {
171
+ g_source_destroy (bCtx->mTimeoutSource );
172
+ g_source_unref (bCtx->mTimeoutSource );
173
+ }
174
+
175
+ // Start a timer, so we could detect when there is no more on-browse events.
176
+ // The timeout callback function will be called in the same event loop as the
177
+ // browse callback (this one), so locking is not required.
178
+ auto * source = g_timeout_source_new (kDnssdBrowseTimeoutMs );
179
+ g_source_set_callback (source, OnBrowseTimeout, bCtx, nullptr );
180
+ g_source_attach (source, g_main_context_get_thread_default ());
181
+ bCtx->mTimeoutSource = source;
148
182
149
183
char * type = nullptr ;
150
184
char * name = nullptr ;
@@ -173,23 +207,17 @@ void OnBrowse(dnssd_service_state_e state, dnssd_service_h service, void * data)
173
207
OnBrowseRemove (bCtx, type, name, interfaceId);
174
208
}
175
209
176
- // For now, there is no way to wait for multiple services to be found.
177
- // Darwin implementation just checks if kDNSServiceFlagsMoreComing is set or not,
178
- // but it doesn't ensure that multiple services can be found.
179
- bCtx->mCallback (bCtx->mCbContext , bCtx->mServices .data (), bCtx->mServices .size (), CHIP_NO_ERROR);
180
-
181
210
exit :
182
211
212
+ dnssd_destroy_remote_service (service);
213
+
183
214
if (ret != DNSSD_ERROR_NONE)
184
215
{
185
216
bCtx->mCallback (bCtx->mCbContext , nullptr , 0 , GetChipError (ret));
217
+ // After this point the context might be no longer valid
218
+ bCtx->mInstance ->RemoveContext (bCtx);
186
219
}
187
220
188
- // After this point, the context might be no longer valid
189
- bCtx->mInstance ->RemoveContext (bCtx);
190
-
191
- dnssd_destroy_remote_service (service);
192
-
193
221
g_free (type);
194
222
g_free (name);
195
223
g_free (ifaceName);
@@ -412,6 +440,11 @@ BrowseContext::BrowseContext(DnssdTizen * instance, const char * type, DnssdServ
412
440
413
441
BrowseContext::~BrowseContext ()
414
442
{
443
+ if (mTimeoutSource != nullptr )
444
+ {
445
+ g_source_destroy (mTimeoutSource );
446
+ g_source_unref (mTimeoutSource );
447
+ }
415
448
if (mIsBrowsing )
416
449
{
417
450
dnssd_cancel_browse_service (mBrowserHandle );
0 commit comments