Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(366)

Side by Side Diff: src/pkg/mdns/mdns_extension_macos.cc

Issue 1416833009: Add multiple results and timeout handling to the Mac OS mDNS native extension (Closed) Base URL: git@github.com:dart-lang/fletch.git@master
Patch Set: Created 5 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « src/pkg/mdns/mdns_extension_linux.cc ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2015, the Fletch project authors. Please see the AUTHORS file 1 // Copyright (c) 2015, the Fletch project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a 2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE.md file. 3 // BSD-style license that can be found in the LICENSE.md file.
4 4
5 #if defined(FLETCH_TARGET_OS_MACOS) 5 #if defined(FLETCH_TARGET_OS_MACOS)
6 6
7 #include <errno.h> 7 #include <errno.h>
8 #include <stdio.h> 8 #include <stdio.h>
9 #include <stdlib.h> 9 #include <stdlib.h>
10 #include <string.h> 10 #include <string.h>
11 #include <arpa/inet.h> 11 #include <arpa/inet.h>
12 #include <pthread.h> 12 #include <pthread.h>
13 #include <sys/time.h>
13 14
14 #include <dns_sd.h> 15 #include <dns_sd.h>
15 16
16 #include "include/dart_api.h" 17 #include "include/dart_api.h"
17 #include "include/dart_native_api.h" 18 #include "include/dart_native_api.h"
18 19
19 #include "mdns_extension.h" 20 #include "mdns_extension.h"
20 21
22 // Constants.
23 static uint32_t kUsecsInSecs = 1000000;
24 static uint32_t kMillisecsInUsecs = 1000;
25
21 // Context passed to the callback receiving the mDNS information. 26 // Context passed to the callback receiving the mDNS information.
22 struct Context { 27 struct Context {
28 DNSServiceRef ref;
29 // The timeout waiting for results.
30 int timeout;
23 // The Dart port where the result should be delivered. 31 // The Dart port where the result should be delivered.
24 Dart_Port port; 32 Dart_Port port;
25 }; 33 };
26 34
27 // Print fatal error and exit. 35 // Print fatal error and exit.
28 static void Fatal(const char *message) { 36 static void Fatal(const char *message) {
29 fprintf(stderr, "%s (errno %d)\n", message, errno); 37 fprintf(stderr, "%s (errno %d)\n", message, errno);
30 exit(-1); 38 exit(-1);
31 } 39 }
32 40
41 int64_t timeval_to_usec(const struct timeval* tv) {
42 return( (int64_t)tv->tv_sec * kUsecsInSecs + tv->tv_usec ) ;
43 }
44
45 struct timeval* usec_to_timeval(int64_t usec, struct timeval* tv) {
46 tv->tv_sec = usec / kUsecsInSecs;
47 tv->tv_usec = usec % kUsecsInSecs;
48 return tv;
49 }
50
51 // Free allocated resources associated with a context.
52 static void FreeContext(Context* ctx) {
53 DNSServiceRefDeallocate(ctx->ref);
54 free(ctx);
55 }
56
33 // Code running in the threads started for pumping the results. 57 // Code running in the threads started for pumping the results.
34 static void* ThreadFunction(void* data) { 58 static void* ThreadFunction(void* data) {
35 DNSServiceRef ref = reinterpret_cast<DNSServiceRef>(data); 59 Context* ctx = reinterpret_cast<Context*>(data);
36 60
37 // Preocess results until an error occurs. 61 // Determint the end-time for responses to this request. Timeout from Dart
38 DNSServiceErrorType result = kDNSServiceErr_NoError; 62 // is in milliseconds.
39 while (result == kDNSServiceErr_NoError) { 63 struct timeval time;
40 result = DNSServiceProcessResult(ref); 64 if (gettimeofday(&time, NULL) == -1) {
65 FreeContext(ctx);
66 return NULL;
41 } 67 }
42 // The expected error from deallocation the ref. 68 int64_t end_time = timeval_to_usec(&time) + ctx->timeout * kMillisecsInUsecs;
43 if (result != kDNSServiceErr_BadReference) { 69
44 fprintf(stderr, "Error from DNSServiceProcessResult: %d\n", result); 70 // Setup single file descriptor for select.
71 int fd = DNSServiceRefSockFD(ctx->ref);
72 fd_set readfds;
73 FD_ZERO(&readfds);
74 FD_SET(fd, &readfds);
75 while (true) {
76 struct timeval timeout;
77 int64_t timeout_usec = end_time - timeval_to_usec(&time);
78 if (timeout_usec <= 0) break;
79 usec_to_timeval(timeout_usec, &timeout);
80 int rc = select(fd + 1, &readfds, NULL, NULL, &timeout);
81 if (rc == -1 && errno == EINTR) continue;
82
83 // Terminate the loop if timeout or error.
84 if (rc <= 0) break;
85
86 // Process the result which is ready.
87 DNSServiceErrorType result = kDNSServiceErr_NoError;
88 result = DNSServiceProcessResult(ctx->ref);
wibling 2015/11/10 14:44:56 NIT: Merge the two above lines into one.
Søren Gjesse 2015/11/10 15:30:05 Done.
89 if (result != kDNSServiceErr_NoError) break;
90
91 // Prepare new timeout.
92 if (gettimeofday(&time, NULL) == -1) break;
45 } 93 }
46 94
95 FreeContext(ctx);
47 return NULL; 96 return NULL;
48 } 97 }
49 98
50 // Start a thread for receiving results from a specific DNSServiceRef. 99 // Start a thread for receiving results from a specific DNSServiceRef.
51 static int StartThread(DNSServiceRef ref) { 100 static int StartThread(Context* ctx) {
52 pthread_attr_t attr; 101 pthread_attr_t attr;
53 int result = pthread_attr_init(&attr); 102 int result = pthread_attr_init(&attr);
54 if (result != 0) Fatal("Error from pthread_attr_init"); 103 if (result != 0) Fatal("Error from pthread_attr_init");
55 104
56 result = pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); 105 result = pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
57 if (result != 0) Fatal("Error from pthread_attr_setdetachstate"); 106 if (result != 0) Fatal("Error from pthread_attr_setdetachstate");
58 107
59 pthread_t tid; 108 pthread_t tid;
60 result = pthread_create(&tid, &attr, ThreadFunction, ref); 109 result = pthread_create(&tid, &attr, ThreadFunction, ctx);
61 if (result != 0) Fatal("Error from pthread_create"); 110 if (result != 0) Fatal("Error from pthread_create");
62 111
63 result = pthread_attr_destroy(&attr); 112 result = pthread_attr_destroy(&attr);
64 if (result != 0) Fatal("Error from pthread_attr_destroy"); 113 if (result != 0) Fatal("Error from pthread_attr_destroy");
65 114
66 return 0; 115 return 0;
67 } 116 }
68 117
69 118
70 // Callback for results initiated by calling DNSServiceQueryRecord. 119 // Callback for results initiated by calling DNSServiceQueryRecord.
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
106 cobject_data.value.as_typed_data.type = Dart_TypedData_kUint8; 155 cobject_data.value.as_typed_data.type = Dart_TypedData_kUint8;
107 cobject_data.value.as_typed_data.values = 156 cobject_data.value.as_typed_data.values =
108 const_cast<uint8_t*>(reinterpret_cast<const uint8_t*>(rdata)); 157 const_cast<uint8_t*>(reinterpret_cast<const uint8_t*>(rdata));
109 Dart_CObject cobject_result; 158 Dart_CObject cobject_result;
110 cobject_result.type = Dart_CObject_kArray; 159 cobject_result.type = Dart_CObject_kArray;
111 Dart_CObject* result_array[] = 160 Dart_CObject* result_array[] =
112 {&cobject_fullname, &cobject_type, &cobject_ttl, &cobject_data}; 161 {&cobject_fullname, &cobject_type, &cobject_ttl, &cobject_data};
113 cobject_result.value.as_array.length = 4; 162 cobject_result.value.as_array.length = 4;
114 cobject_result.value.as_array.values = result_array; 163 cobject_result.value.as_array.values = result_array;
115 Dart_PostCObject(ctx->port, &cobject_result); 164 Dart_PostCObject(ctx->port, &cobject_result);
116
117 // Result received, free allocated data and stop lookup.
118 free(ctx);
119 DNSServiceRefDeallocate(ref);
120 } 165 }
121 166
122 // Lookup request from Dart. 167 // Lookup request from Dart.
123 void HandleLookup(Dart_Port port_id, int type, char* fullname) { 168 void HandleLookup(Dart_Port port_id, int type, char* fullname, int timeout) {
124 DNSServiceRef ref; 169 DNSServiceRef ref;
125 DNSServiceErrorType result; 170 DNSServiceErrorType result;
126 struct Context* context = 171 struct Context* context =
127 reinterpret_cast<struct Context*>(malloc(sizeof(struct Context))); 172 reinterpret_cast<struct Context*>(malloc(sizeof(struct Context)));
128 context->port = port_id;
129 result = DNSServiceQueryRecord(&ref, 173 result = DNSServiceQueryRecord(&ref,
130 0, 174 0,
131 0, 175 0,
132 fullname, 176 fullname,
133 type, 177 type,
134 kDNSServiceClass_IN, 178 kDNSServiceClass_IN,
135 &QueryRecordCallback, 179 &QueryRecordCallback,
136 context); 180 context);
137 if (result != kDNSServiceErr_NoError) { 181 if (result != kDNSServiceErr_NoError) {
138 fprintf(stderr, "Error from DNSServiceQueryRecord: %d\n", result); 182 fprintf(stderr, "Error from DNSServiceQueryRecord: %d\n", result);
139 } else { 183 } else {
140 // Start a thread for retreiving the results. 184 // Start a thread for pumping the results.
141 // TODO(sgjesse): Add a timeout for killing the thread if there 185 context->ref = ref;
142 // are no responses. 186 context->timeout = timeout;
143 StartThread(ref); 187 context->port = port_id;
188 StartThread(context);
144 } 189 }
145 } 190 }
146 191
147 #endif 192 #endif
OLDNEW
« no previous file with comments | « src/pkg/mdns/mdns_extension_linux.cc ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698