Imported Upstream version 0.9.0
[deb_shairplay.git] / src / lib / dnssd.m
1 /**
2 * Copyright (C) 2011-2012 Juho Vähä-Herttua
3 *
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
8 *
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
13 */
14
15 #include <stdlib.h>
16
17 #include "dnssd.h"
18 #include "dnssdint.h"
19 #include "global.h"
20 #include "utils.h"
21
22 #import <Foundation/Foundation.h>
23
24 #define MAX_SERVNAME 256
25
26 struct dnssd_s {
27 NSNetService *raopService;
28 NSNetService *airplayService;
29 };
30
31 dnssd_t *
32 dnssd_init(int *error)
33 {
34 dnssd_t *dnssd;
35
36 if (error) *error = DNSSD_ERROR_NOERROR;
37
38 dnssd = calloc(1, sizeof(dnssd_t));
39 if (!dnssd) {
40 if (error) *error = DNSSD_ERROR_OUTOFMEM;
41 return NULL;
42 }
43 return dnssd;
44 }
45
46 void
47 dnssd_destroy(dnssd_t *dnssd)
48 {
49 free(dnssd);
50 }
51
52 int
53 dnssd_register_raop(dnssd_t *dnssd, const char *name, unsigned short port, const char *hwaddr, int hwaddrlen, int password)
54 {
55 char hwaddrstr[MAX_SERVNAME];
56 NSString *serviceString;
57 NSMutableDictionary *txtDict;
58 NSData *txtData;
59 int ret;
60
61 assert(dnssd);
62
63 if (dnssd->raopService != nil) {
64 return -1;
65 }
66
67 /* Convert the hardware address to string */
68 ret = utils_hwaddr_raop(hwaddrstr, sizeof(hwaddrstr), hwaddr, hwaddrlen);
69 if (ret < 0) {
70 return -2;
71 }
72 serviceString = [NSString stringWithFormat:@"%s@%s", hwaddrstr, name];
73
74 txtDict = [NSMutableDictionary dictionaryWithCapacity:0];
75 [txtDict setValue:[NSString stringWithUTF8String:RAOP_TXTVERS] forKey:@"txtvers"];
76 [txtDict setValue:[NSString stringWithUTF8String:RAOP_CH] forKey:@"ch"];
77 [txtDict setValue:[NSString stringWithUTF8String:RAOP_CN] forKey:@"cn"];
78 [txtDict setValue:[NSString stringWithUTF8String:RAOP_ET] forKey:@"et"];
79 [txtDict setValue:[NSString stringWithUTF8String:RAOP_SV] forKey:@"sv"];
80 [txtDict setValue:[NSString stringWithUTF8String:RAOP_DA] forKey:@"da"];
81 [txtDict setValue:[NSString stringWithUTF8String:RAOP_SR] forKey:@"sr"];
82 [txtDict setValue:[NSString stringWithUTF8String:RAOP_SS] forKey:@"ss"];
83 if (password) {
84 [txtDict setValue:@"true" forKey:@"pw"];
85 } else {
86 [txtDict setValue:@"false" forKey:@"pw"];
87 }
88 [txtDict setValue:[NSString stringWithUTF8String:RAOP_VN] forKey:@"vn"];
89 [txtDict setValue:[NSString stringWithUTF8String:RAOP_TP] forKey:@"tp"];
90 [txtDict setValue:[NSString stringWithUTF8String:RAOP_MD] forKey:@"md"];
91 [txtDict setValue:[NSString stringWithUTF8String:GLOBAL_VERSION] forKey:@"vs"];
92 [txtDict setValue:[NSString stringWithUTF8String:RAOP_AM] forKey:@"am"];
93 [txtDict setValue:[NSString stringWithUTF8String:RAOP_SF] forKey:@"sf"];
94 txtData = [NSNetService dataFromTXTRecordDictionary:txtDict];
95
96 /* Create the service and publish it */
97 dnssd->raopService = [[NSNetService alloc] initWithDomain:@""
98 type:@"_raop._tcp"
99 name:serviceString
100 port:port];
101 [dnssd->raopService setTXTRecordData:txtData];
102 [dnssd->raopService publish];
103 return 1;
104 }
105
106 int
107 dnssd_register_airplay(dnssd_t *dnssd, const char *name, unsigned short port, const char *hwaddr, int hwaddrlen)
108 {
109 NSMutableDictionary *txtDict;
110 NSData *txtData;
111 char deviceid[3*MAX_HWADDR_LEN];
112 char features[16];
113 int ret;
114
115 assert(dnssd);
116
117 if (dnssd->airplayService != nil) {
118 return -1;
119 }
120
121 /* Convert hardware address to string */
122 ret = utils_hwaddr_airplay(deviceid, sizeof(deviceid), hwaddr, hwaddrlen);
123 if (ret < 0) {
124 return -2;
125 }
126
127 memset(features, 0, sizeof(features));
128 snprintf(features, sizeof(features)-1, "0x%x", GLOBAL_FEATURES);
129
130 txtDict = [NSMutableDictionary dictionaryWithCapacity:0];
131 [txtDict setValue:[NSString stringWithUTF8String:deviceid] forKey:@"deviceid"];
132 [txtDict setValue:[NSString stringWithUTF8String:features] forKey:@"features"];
133 [txtDict setValue:[NSString stringWithUTF8String:GLOBAL_MODEL] forKey:@"model"];
134 txtData = [NSNetService dataFromTXTRecordDictionary:txtDict];
135
136 /* Create the service and publish it */
137 dnssd->airplayService = [[NSNetService alloc] initWithDomain:@""
138 type:@"_airplay._tcp"
139 name:[NSString stringWithUTF8String:name]
140 port:port];
141 [dnssd->airplayService setTXTRecordData:txtData];
142 [dnssd->airplayService publish];
143 return 1;
144 }
145
146 void
147 dnssd_unregister_raop(dnssd_t *dnssd)
148 {
149 assert(dnssd);
150
151 if (dnssd->raopService == nil) {
152 return;
153 }
154
155 [dnssd->raopService stop];
156 [dnssd->raopService release];
157 dnssd->raopService = nil;
158 }
159
160 void
161 dnssd_unregister_airplay(dnssd_t *dnssd)
162 {
163 assert(dnssd);
164
165 if (dnssd->airplayService == nil) {
166 return;
167 }
168
169 [dnssd->airplayService stop];
170 [dnssd->airplayService release];
171 dnssd->airplayService = nil;
172 }