OLD | NEW |
| (Empty) |
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 | |
3 // BSD-style license that can be found in the LICENSE.md file. | |
4 | |
5 #if defined(FLETCH_TARGET_OS_MACOS) | |
6 | |
7 #include <errno.h> | |
8 #include <stdio.h> | |
9 #include <stdlib.h> | |
10 #include <string.h> | |
11 #include <arpa/inet.h> | |
12 #include <pthread.h> | |
13 | |
14 #include "include/dart_api.h" | |
15 #include "include/dart_native_api.h" | |
16 | |
17 | |
18 #include "/usr/include/dns_sd.h" | |
19 | |
20 #include "mdns_extension.h" | |
21 | |
22 // Context passed to the callback receiving the mDNS information. | |
23 struct Context { | |
24 // The Dart port where the result should be delivered. | |
25 Dart_Port port; | |
26 }; | |
27 | |
28 // Print fatal error and exit. | |
29 static void Fatal(const char *message) { | |
30 fprintf(stderr, "%s (errno %d)\n", message, errno); | |
31 exit(-1); | |
32 } | |
33 | |
34 // Code running in the threads started for pumping the results. | |
35 static void* ThreadFunction(void* data) { | |
36 DNSServiceRef ref = reinterpret_cast<DNSServiceRef>(data); | |
37 | |
38 // Preocess results until an error occurs. | |
39 DNSServiceErrorType result = kDNSServiceErr_NoError; | |
40 while (result == kDNSServiceErr_NoError) { | |
41 result = DNSServiceProcessResult(ref); | |
42 } | |
43 // The expected error from deallocation the ref. | |
44 if (result != kDNSServiceErr_BadReference) { | |
45 fprintf(stderr, "Error from DNSServiceProcessResult: %d\n", result); | |
46 } | |
47 | |
48 return NULL; | |
49 } | |
50 | |
51 // Start a thread for receiving results from a specific DNSServiceRef. | |
52 static int StartThread(DNSServiceRef ref) { | |
53 pthread_attr_t attr; | |
54 int result = pthread_attr_init(&attr); | |
55 if (result != 0) Fatal("Error from pthread_attr_init"); | |
56 | |
57 result = pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); | |
58 if (result != 0) Fatal("Error from pthread_attr_setdetachstate"); | |
59 | |
60 pthread_t tid; | |
61 result = pthread_create(&tid, &attr, ThreadFunction, ref); | |
62 if (result != 0) Fatal("Error from pthread_create"); | |
63 | |
64 result = pthread_attr_destroy(&attr); | |
65 if (result != 0) Fatal("Error from pthread_attr_destroy"); | |
66 | |
67 return 0; | |
68 } | |
69 | |
70 // Callback for results initiated by calling DNSServiceGetAddrInfo. | |
71 static void GetAddrInfoCallback(DNSServiceRef ref, | |
72 DNSServiceFlags flags, | |
73 uint32_t interfaceIndex, | |
74 DNSServiceErrorType errorCode, | |
75 const char *hostname, | |
76 const struct sockaddr *address, | |
77 uint32_t ttl, | |
78 void *context) { | |
79 if (address->sa_family == AF_INET) { | |
80 const struct sockaddr_in* address_in = (const struct sockaddr_in*)address; | |
81 const uint8_t* addr = | |
82 reinterpret_cast<const uint8_t*>(&address_in->sin_addr.s_addr); | |
83 | |
84 struct Context* ctx = reinterpret_cast<struct Context*>(context); | |
85 | |
86 // Build the response message. | |
87 Dart_CObject cobject_hostname; | |
88 cobject_hostname.type = Dart_CObject_kString; | |
89 cobject_hostname.value.as_string = const_cast<char*>(hostname); | |
90 Dart_CObject cobject_address; | |
91 cobject_address.type = Dart_CObject_kTypedData; | |
92 cobject_address.value.as_typed_data.length = 4; | |
93 cobject_address.value.as_typed_data.type = Dart_TypedData_kUint8; | |
94 cobject_address.value.as_typed_data.values = const_cast<uint8_t*>(addr); | |
95 Dart_CObject cobject_result; | |
96 cobject_result.type = Dart_CObject_kArray; | |
97 Dart_CObject* result_array[] = {&cobject_hostname, &cobject_address}; | |
98 cobject_result.value.as_array.length = 2; | |
99 cobject_result.value.as_array.values = result_array; | |
100 Dart_PostCObject(ctx->port, &cobject_result); | |
101 | |
102 // Result received, free allocated data and stop lookup. | |
103 free(ctx); | |
104 DNSServiceRefDeallocate(ref); | |
105 } | |
106 } | |
107 | |
108 // Lookup request from Dart. | |
109 void HandleLookup(Dart_Port port_id, char* hostname) { | |
110 DNSServiceRef ref; | |
111 DNSServiceErrorType result; | |
112 struct Context* context = | |
113 reinterpret_cast<struct Context*>(malloc(sizeof(struct Context))); | |
114 context->port = port_id; | |
115 result = DNSServiceGetAddrInfo(&ref, | |
116 0, | |
117 0, | |
118 kDNSServiceProtocol_IPv4, | |
119 hostname, | |
120 &GetAddrInfoCallback, | |
121 context); | |
122 if (result != kDNSServiceErr_NoError) { | |
123 fprintf(stderr, "Error from DNSServiceProcessResult: %d\n", result); | |
124 } else { | |
125 // Start a thread for retreiving the results. | |
126 // TODO(sgjesse): Add a timeout for killing the thread if there | |
127 // are no responses. | |
128 StartThread(ref); | |
129 } | |
130 } | |
131 | |
132 #endif | |
OLD | NEW |