Rename a file that had a confusing filename.
[deb_shairplay.git] / src / dnssd.m
1 #include <stdlib.h>
2
3 #include "dnssd.h"
4 #include "dnssdint.h"
5 #include "global.h"
6 #include "utils.h"
7
8 #import <Foundation/Foundation.h>
9
10 #define MAX_SERVNAME 256
11
12 struct dnssd_s {
13 char hwaddr[MAX_HWADDR_LEN];
14 int hwaddrlen;
15
16 NSNetService *raopService;
17 NSNetService *airplayService;
18 };
19
20 dnssd_t *
21 dnssd_init(const char *hwaddr, int hwaddrlen, int *error)
22 {
23 dnssd_t *dnssd;
24
25 if (error) *error = DNSSD_ERROR_NOERROR;
26 if (hwaddrlen > MAX_HWADDR_LEN) {
27 if (error) *error = DNSSD_ERROR_HWADDRLEN;
28 return NULL;
29 }
30
31 dnssd = calloc(1, sizeof(dnssd_t));
32 if (!dnssd) {
33 if (error) *error = DNSSD_ERROR_OUTOFMEM;
34 return NULL;
35 }
36 memcpy(dnssd->hwaddr, hwaddr, hwaddrlen);
37 dnssd->hwaddrlen = hwaddrlen;
38
39 return dnssd;
40 }
41
42 void
43 dnssd_destroy(dnssd_t *dnssd)
44 {
45 free(dnssd);
46 }
47
48 int
49 dnssd_register_raop(dnssd_t *dnssd, const char *name, unsigned short port)
50 {
51 char hwaddrstr[MAX_SERVNAME];
52 NSString *serviceString;
53 NSMutableDictionary *txtDict;
54 NSData *txtData;
55 int ret;
56
57 assert(dnssd);
58
59 if (dnssd->raopService != nil) {
60 return -1;
61 }
62
63 /* Convert the hardware address to string */
64 ret = utils_hwaddr_raop(hwaddrstr, sizeof(hwaddrstr), dnssd->hwaddr, dnssd->hwaddrlen);
65 if (ret < 0) {
66 return -2;
67 }
68 serviceString = [NSString stringWithFormat:@"%s@%s", hwaddrstr, name];
69
70 txtDict = [NSMutableDictionary dictionaryWithCapacity:0];
71 [txtDict setValue:[NSString stringWithUTF8String:RAOP_TXTVERS] forKey:@"txtvers"];
72 [txtDict setValue:[NSString stringWithUTF8String:RAOP_CH] forKey:@"ch"];
73 [txtDict setValue:[NSString stringWithUTF8String:RAOP_CN] forKey:@"cn"];
74 [txtDict setValue:[NSString stringWithUTF8String:RAOP_ET] forKey:@"et"];
75 [txtDict setValue:[NSString stringWithUTF8String:RAOP_SV] forKey:@"sv"];
76 [txtDict setValue:[NSString stringWithUTF8String:RAOP_DA] forKey:@"da"];
77 [txtDict setValue:[NSString stringWithUTF8String:RAOP_SR] forKey:@"sr"];
78 [txtDict setValue:[NSString stringWithUTF8String:RAOP_SS] forKey:@"ss"];
79 [txtDict setValue:[NSString stringWithUTF8String:RAOP_PW] forKey:@"pw"];
80 [txtDict setValue:[NSString stringWithUTF8String:RAOP_VN] forKey:@"vn"];
81 [txtDict setValue:[NSString stringWithUTF8String:RAOP_TP] forKey:@"tp"];
82 [txtDict setValue:[NSString stringWithUTF8String:RAOP_MD] forKey:@"md"];
83 [txtDict setValue:[NSString stringWithUTF8String:GLOBAL_VERSION] forKey:@"vs"];
84 [txtDict setValue:[NSString stringWithUTF8String:RAOP_AM] forKey:@"am"];
85 [txtDict setValue:[NSString stringWithUTF8String:RAOP_SF] forKey:@"sf"];
86 txtData = [NSNetService dataFromTXTRecordDictionary:txtDict];
87
88 /* Create the service and publish it */
89 dnssd->raopService = [[NSNetService alloc] initWithDomain:@""
90 type:@"_raop._tcp"
91 name:serviceString
92 port:port];
93 [dnssd->raopService setTXTRecordData:txtData];
94 [dnssd->raopService publish];
95 return 1;
96 }
97
98 int
99 dnssd_register_airplay(dnssd_t *dnssd, const char *name, unsigned short port)
100 {
101 NSMutableDictionary *txtDict;
102 NSData *txtData;
103 char deviceid[3*MAX_HWADDR_LEN];
104 char features[16];
105 int ret;
106
107 assert(dnssd);
108
109 if (dnssd->airplayService != nil) {
110 return -1;
111 }
112
113 /* Convert hardware address to string */
114 ret = utils_hwaddr_airplay(deviceid, sizeof(deviceid), dnssd->hwaddr, dnssd->hwaddrlen);
115 if (ret < 0) {
116 return -2;
117 }
118
119 memset(features, 0, sizeof(features));
120 snprintf(features, sizeof(features)-1, "0x%x", GLOBAL_FEATURES);
121
122 txtDict = [NSMutableDictionary dictionaryWithCapacity:0];
123 [txtDict setValue:[NSString stringWithUTF8String:deviceid] forKey:@"deviceid"];
124 [txtDict setValue:[NSString stringWithUTF8String:features] forKey:@"features"];
125 [txtDict setValue:[NSString stringWithUTF8String:GLOBAL_MODEL] forKey:@"model"];
126 txtData = [NSNetService dataFromTXTRecordDictionary:txtDict];
127
128 /* Create the service and publish it */
129 dnssd->airplayService = [[NSNetService alloc] initWithDomain:@""
130 type:@"_airplay._tcp"
131 name:[NSString stringWithUTF8String:name]
132 port:port];
133 [dnssd->airplayService setTXTRecordData:txtData];
134 [dnssd->airplayService publish];
135 return 1;
136 }
137
138 void
139 dnssd_unregister_raop(dnssd_t *dnssd)
140 {
141 assert(dnssd);
142
143 if (dnssd->raopService == nil) {
144 return;
145 }
146
147 [dnssd->raopService stop];
148 [dnssd->raopService release];
149 dnssd->raopService = nil;
150 }
151
152 void
153 dnssd_unregister_airplay(dnssd_t *dnssd)
154 {
155 assert(dnssd);
156
157 if (dnssd->airplayService == nil) {
158 return;
159 }
160
161 [dnssd->airplayService stop];
162 [dnssd->airplayService release];
163 dnssd->airplayService = nil;
164 }