source: rtems-libbsd/mDNSResponder/mDNSPosix/Client.c @ 4a5f546

55-freebsd-126-freebsd-12
Last change on this file since 4a5f546 was 9449f15, checked in by Sebastian Huber <sebastian.huber@…>, on 01/30/14 at 12:52:13

mDNS: Import

The sources can be obtained via:

http://opensource.apple.com/tarballs/mDNSResponder/mDNSResponder-544.tar.gz

  • Property mode set to 100755
File size: 7.5 KB
Line 
1/* -*- Mode: C; tab-width: 4 -*-
2 *
3 * Copyright (c) 2002-2004 Apple Computer, Inc. All rights reserved.
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 *
9 *     http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17
18#include <assert.h>
19#include <signal.h>
20#include <stdio.h>
21#include <string.h>
22#include <unistd.h>
23#include <stdlib.h>
24
25#include "mDNSEmbeddedAPI.h" // Defines the interface to the mDNS core code
26#include "mDNSPosix.h"    // Defines the specific types needed to run mDNS on this platform
27#include "ExampleClientApp.h"
28
29// Globals
30static mDNS mDNSStorage;       // mDNS core uses this to store its globals
31static mDNS_PlatformSupport PlatformStorage;  // Stores this platform's globals
32#define RR_CACHE_SIZE 500
33static CacheEntity gRRCache[RR_CACHE_SIZE];
34
35mDNSexport const char ProgramName[] = "mDNSClientPosix";
36
37static const char *gProgramName = ProgramName;
38
39static void BrowseCallback(mDNS *const m, DNSQuestion *question, const ResourceRecord *const answer, QC_result AddRecord)
40// A callback from the core mDNS code that indicates that we've received a
41// response to our query.  Note that this code runs on the main thread
42// (in fact, there is only one thread!), so we can safely printf the results.
43{
44    domainlabel name;
45    domainname type;
46    domainname domain;
47    char nameC  [MAX_DOMAIN_LABEL+1];           // Unescaped name: up to 63 bytes plus C-string terminating NULL.
48    char typeC  [MAX_ESCAPED_DOMAIN_NAME];
49    char domainC[MAX_ESCAPED_DOMAIN_NAME];
50    const char *state;
51
52    (void)m;        // Unused
53    (void)question; // Unused
54
55    assert(answer->rrtype == kDNSType_PTR);
56
57    DeconstructServiceName(&answer->rdata->u.name, &name, &type, &domain);
58
59    ConvertDomainLabelToCString_unescaped(&name, nameC);
60    ConvertDomainNameToCString(&type, typeC);
61    ConvertDomainNameToCString(&domain, domainC);
62
63    // If the TTL has hit 0, the service is no longer available.
64    if (!AddRecord) {
65        state = "Lost ";
66    } else {
67        state = "Found";
68    }
69    fprintf(stderr, "*** %s name = '%s', type = '%s', domain = '%s'\n", state, nameC, typeC, domainC);
70}
71
72static mDNSBool CheckThatServiceTypeIsUsable(const char *serviceType, mDNSBool printExplanation)
73// Checks that serviceType is a reasonable service type
74// label and, if it isn't and printExplanation is true, prints
75// an explanation of why not.
76{
77    mDNSBool result;
78
79    result = mDNStrue;
80    if (result && strlen(serviceType) > 63) {
81        if (printExplanation) {
82            fprintf(stderr,
83                    "%s: Service type specified by -t is too long (must be 63 characters or less)\n",
84                    gProgramName);
85        }
86        result = mDNSfalse;
87    }
88    if (result && serviceType[0] == 0) {
89        if (printExplanation) {
90            fprintf(stderr,
91                    "%s: Service type specified by -t can't be empty\n",
92                    gProgramName);
93        }
94        result = mDNSfalse;
95    }
96    return result;
97}
98
99static const char kDefaultServiceType[] = "_afpovertcp._tcp";
100static const char kDefaultDomain[]      = "local.";
101
102static void PrintUsage()
103{
104    fprintf(stderr,
105            "Usage: %s [-v level] [-t type] [-d domain]\n",
106            gProgramName);
107    fprintf(stderr, "          -v verbose mode, level is a number from 0 to 2\n");
108    fprintf(stderr, "             0 = no debugging info (default)\n");
109    fprintf(stderr, "             1 = standard debugging info\n");
110    fprintf(stderr, "             2 = intense debugging info\n");
111    fprintf(stderr, "          -t uses 'type' as the service type (default is '%s')\n", kDefaultServiceType);
112    fprintf(stderr, "          -d uses 'domain' as the domain to browse (default is '%s')\n", kDefaultDomain);
113}
114
115static const char *gServiceType      = kDefaultServiceType;
116static const char *gServiceDomain    = kDefaultDomain;
117
118static void ParseArguments(int argc, char **argv)
119// Parses our command line arguments into the global variables
120// listed above.
121{
122    int ch;
123
124    // Set gProgramName to the last path component of argv[0]
125
126    gProgramName = strrchr(argv[0], '/');
127    if (gProgramName == NULL) {
128        gProgramName = argv[0];
129    } else {
130        gProgramName += 1;
131    }
132
133    // Parse command line options using getopt.
134
135    do {
136        ch = getopt(argc, argv, "v:t:d:");
137        if (ch != -1) {
138            switch (ch) {
139            case 'v':
140                gMDNSPlatformPosixVerboseLevel = atoi(optarg);
141                if (gMDNSPlatformPosixVerboseLevel < 0 || gMDNSPlatformPosixVerboseLevel > 2) {
142                    fprintf(stderr,
143                            "%s: Verbose mode must be in the range 0..2\n",
144                            gProgramName);
145                    exit(1);
146                }
147                break;
148            case 't':
149                gServiceType = optarg;
150                if ( !CheckThatServiceTypeIsUsable(gServiceType, mDNStrue) ) {
151                    exit(1);
152                }
153                break;
154            case 'd':
155                gServiceDomain = optarg;
156                break;
157            case '?':
158            default:
159                PrintUsage();
160                exit(1);
161                break;
162            }
163        }
164    } while (ch != -1);
165
166    // Check for any left over command line arguments.
167
168    if (optind != argc) {
169        fprintf(stderr, "%s: Unexpected argument '%s'\n", gProgramName, argv[optind]);
170        exit(1);
171    }
172}
173
174int main(int argc, char **argv)
175// The program's main entry point.  The program does a trivial
176// mDNS query, looking for all AFP servers in the local domain.
177{
178    int result;
179    mStatus status;
180    DNSQuestion question;
181    domainname type;
182    domainname domain;
183
184    // Parse our command line arguments.  This won't come back if there's an error.
185    ParseArguments(argc, argv);
186
187    // Initialise the mDNS core.
188    status = mDNS_Init(&mDNSStorage, &PlatformStorage,
189                       gRRCache, RR_CACHE_SIZE,
190                       mDNS_Init_DontAdvertiseLocalAddresses,
191                       mDNS_Init_NoInitCallback, mDNS_Init_NoInitCallbackContext);
192    if (status == mStatus_NoError) {
193
194        // Construct and start the query.
195
196        MakeDomainNameFromDNSNameString(&type, gServiceType);
197        MakeDomainNameFromDNSNameString(&domain, gServiceDomain);
198
199        status = mDNS_StartBrowse(&mDNSStorage, &question, &type, &domain, mDNSNULL, mDNSInterface_Any, 0, mDNSfalse, mDNSfalse, BrowseCallback, NULL);
200
201        // Run the platform main event loop until the user types ^C.
202        // The BrowseCallback routine is responsible for printing
203        // any results that we find.
204
205        if (status == mStatus_NoError) {
206            fprintf(stderr, "Hit ^C when you're bored waiting for responses.\n");
207            ExampleClientEventLoop(&mDNSStorage);
208            mDNS_StopQuery(&mDNSStorage, &question);
209            mDNS_Close(&mDNSStorage);
210        }
211    }
212
213    if (status == mStatus_NoError) {
214        result = 0;
215    } else {
216        result = 2;
217    }
218    if ( (result != 0) || (gMDNSPlatformPosixVerboseLevel > 0) ) {
219        fprintf(stderr, "%s: Finished with status %d, result %d\n", gProgramName, (int)status, result);
220    }
221
222    return 0;
223}
Note: See TracBrowser for help on using the repository browser.