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 |