cannam@89
|
1 /*
|
cannam@89
|
2 * Copyright (C) 2004 Steve Harris
|
cannam@89
|
3 *
|
cannam@89
|
4 * This program is free software; you can redistribute it and/or modify
|
cannam@89
|
5 * it under the terms of the GNU Lesser General Public License as
|
cannam@89
|
6 * published by the Free Software Foundation; either version 2.1 of the
|
cannam@89
|
7 * License, or (at your option) any later version.
|
cannam@89
|
8 *
|
cannam@89
|
9 * This program is distributed in the hope that it will be useful,
|
cannam@89
|
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
cannam@89
|
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
cannam@89
|
12 * GNU Lesser General Public License for more details.
|
cannam@89
|
13 *
|
cannam@89
|
14 * $Id$
|
cannam@89
|
15 */
|
cannam@89
|
16
|
cannam@89
|
17 #include <stdio.h>
|
cannam@89
|
18 #include <stdlib.h>
|
cannam@89
|
19 #include <string.h>
|
cannam@89
|
20 #include <sys/types.h>
|
cannam@89
|
21
|
cannam@89
|
22 #ifdef _MSC_VER
|
cannam@89
|
23 #include <io.h>
|
cannam@89
|
24 #define snprintf _snprintf
|
cannam@89
|
25 #else
|
cannam@89
|
26 #include <unistd.h>
|
cannam@89
|
27 #endif
|
cannam@89
|
28
|
cannam@89
|
29 #ifdef WIN32
|
cannam@89
|
30 #include <winsock2.h>
|
cannam@89
|
31 #include <ws2tcpip.h>
|
cannam@89
|
32 #else
|
cannam@89
|
33 #include <netdb.h>
|
cannam@89
|
34 #include <sys/socket.h>
|
cannam@89
|
35 #endif
|
cannam@89
|
36
|
cannam@89
|
37 #include "lo_types_internal.h"
|
cannam@89
|
38 #include "lo/lo.h"
|
cannam@89
|
39 #include "config.h"
|
cannam@89
|
40
|
cannam@89
|
41 lo_address lo_address_new_with_proto(int proto, const char *host, const char *port)
|
cannam@89
|
42 {
|
cannam@89
|
43 lo_address a;
|
cannam@89
|
44
|
cannam@89
|
45 if(proto != LO_UDP && proto != LO_TCP && proto != LO_UNIX) return NULL;
|
cannam@89
|
46
|
cannam@89
|
47 a = calloc(1, sizeof(struct _lo_address));
|
cannam@89
|
48 if(a == NULL) return NULL;
|
cannam@89
|
49
|
cannam@89
|
50 a->ai = NULL;
|
cannam@89
|
51 a->socket = -1;
|
cannam@89
|
52 a->protocol = proto;
|
cannam@89
|
53 switch(proto) {
|
cannam@89
|
54 default:
|
cannam@89
|
55 case LO_UDP:
|
cannam@89
|
56 case LO_TCP:
|
cannam@89
|
57 if (host) {
|
cannam@89
|
58 a->host = strdup(host);
|
cannam@89
|
59 } else {
|
cannam@89
|
60 a->host = strdup("localhost");
|
cannam@89
|
61 }
|
cannam@89
|
62 break;
|
cannam@89
|
63 case LO_UNIX:
|
cannam@89
|
64 a->host = strdup("localhost");
|
cannam@89
|
65 break;
|
cannam@89
|
66 }
|
cannam@89
|
67 if (port) {
|
cannam@89
|
68 a->port = strdup(port);
|
cannam@89
|
69 } else {
|
cannam@89
|
70 a->port = NULL;
|
cannam@89
|
71 }
|
cannam@89
|
72
|
cannam@89
|
73 a->ttl = -1;
|
cannam@89
|
74
|
cannam@89
|
75 return a;
|
cannam@89
|
76 }
|
cannam@89
|
77
|
cannam@89
|
78 lo_address lo_address_new(const char *host, const char *port)
|
cannam@89
|
79 {
|
cannam@89
|
80 return lo_address_new_with_proto(LO_UDP, host ,port);
|
cannam@89
|
81 }
|
cannam@89
|
82
|
cannam@89
|
83 lo_address lo_address_new_from_url(const char *url)
|
cannam@89
|
84 {
|
cannam@89
|
85 lo_address a;
|
cannam@89
|
86 int protocol;
|
cannam@89
|
87 char *host, *port, *proto;
|
cannam@89
|
88
|
cannam@89
|
89 if (!url || !*url) {
|
cannam@89
|
90 return NULL;
|
cannam@89
|
91 }
|
cannam@89
|
92
|
cannam@89
|
93 protocol = lo_url_get_protocol_id(url);
|
cannam@89
|
94 if (protocol == LO_UDP || protocol == LO_TCP) {
|
cannam@89
|
95 host = lo_url_get_hostname(url);
|
cannam@89
|
96 port = lo_url_get_port(url);
|
cannam@89
|
97 a = lo_address_new_with_proto(protocol, host, port);
|
cannam@89
|
98 if(host) free(host);
|
cannam@89
|
99 if(port) free(port);
|
cannam@89
|
100 #ifndef WIN32
|
cannam@89
|
101 } else if (protocol == LO_UNIX) {
|
cannam@89
|
102 port = lo_url_get_path(url);
|
cannam@89
|
103 a = lo_address_new_with_proto(LO_UNIX, NULL, port);
|
cannam@89
|
104 if(port) free(port);
|
cannam@89
|
105 #endif
|
cannam@89
|
106 } else {
|
cannam@89
|
107 proto = lo_url_get_protocol(url);
|
cannam@89
|
108 fprintf(stderr, PACKAGE_NAME ": protocol '%s' not supported by this "
|
cannam@89
|
109 "version\n", proto);
|
cannam@89
|
110 if(proto) free(proto);
|
cannam@89
|
111
|
cannam@89
|
112 return NULL;
|
cannam@89
|
113 }
|
cannam@89
|
114
|
cannam@89
|
115 return a;
|
cannam@89
|
116 }
|
cannam@89
|
117
|
cannam@89
|
118 const char *lo_address_get_hostname(lo_address a)
|
cannam@89
|
119 {
|
cannam@89
|
120 if (!a) {
|
cannam@89
|
121 return NULL;
|
cannam@89
|
122 }
|
cannam@89
|
123
|
cannam@89
|
124 return a->host;
|
cannam@89
|
125 }
|
cannam@89
|
126
|
cannam@89
|
127 int lo_address_get_protocol(lo_address a)
|
cannam@89
|
128 {
|
cannam@89
|
129 if (!a) {
|
cannam@89
|
130 return -1;
|
cannam@89
|
131 }
|
cannam@89
|
132
|
cannam@89
|
133 return a->protocol;
|
cannam@89
|
134 }
|
cannam@89
|
135
|
cannam@89
|
136 const char *lo_address_get_port(lo_address a)
|
cannam@89
|
137 {
|
cannam@89
|
138 if (!a) {
|
cannam@89
|
139 return NULL;
|
cannam@89
|
140 }
|
cannam@89
|
141
|
cannam@89
|
142 return a->port;
|
cannam@89
|
143 }
|
cannam@89
|
144
|
cannam@89
|
145 static const char* get_protocol_name(int proto)
|
cannam@89
|
146 {
|
cannam@89
|
147 switch(proto) {
|
cannam@89
|
148 case LO_UDP:
|
cannam@89
|
149 return "udp";
|
cannam@89
|
150 case LO_TCP:
|
cannam@89
|
151 return "tcp";
|
cannam@89
|
152 #ifndef WIN32
|
cannam@89
|
153 case LO_UNIX:
|
cannam@89
|
154 return "unix";
|
cannam@89
|
155 #endif
|
cannam@89
|
156 }
|
cannam@89
|
157 return NULL;
|
cannam@89
|
158 }
|
cannam@89
|
159
|
cannam@89
|
160
|
cannam@89
|
161 char *lo_address_get_url(lo_address a)
|
cannam@89
|
162 {
|
cannam@89
|
163 char *buf;
|
cannam@89
|
164 int ret=0;
|
cannam@89
|
165 int needquote = strchr(a->host, ':') ? 1 : 0;
|
cannam@89
|
166 char *fmt;
|
cannam@89
|
167
|
cannam@89
|
168 if (needquote) {
|
cannam@89
|
169 fmt = "osc.%s://[%s]:%s/";
|
cannam@89
|
170 } else {
|
cannam@89
|
171 fmt = "osc.%s://%s:%s/";
|
cannam@89
|
172 }
|
cannam@89
|
173 #ifndef _MSC_VER
|
cannam@89
|
174 ret = snprintf(NULL, 0, fmt,
|
cannam@89
|
175 get_protocol_name(a->protocol), a->host, a->port);
|
cannam@89
|
176 #endif
|
cannam@89
|
177 if (ret <= 0) {
|
cannam@89
|
178 /* this libc is not C99 compliant, guess a size */
|
cannam@89
|
179 ret = 1023;
|
cannam@89
|
180 }
|
cannam@89
|
181 buf = malloc((ret + 2) * sizeof(char));
|
cannam@89
|
182 snprintf(buf, ret+1, fmt,
|
cannam@89
|
183 get_protocol_name(a->protocol), a->host, a->port);
|
cannam@89
|
184
|
cannam@89
|
185 return buf;
|
cannam@89
|
186 }
|
cannam@89
|
187
|
cannam@89
|
188 void lo_address_free(lo_address a)
|
cannam@89
|
189 {
|
cannam@89
|
190 if (a) {
|
cannam@89
|
191 if (a->socket != -1) {
|
cannam@89
|
192 close(a->socket);
|
cannam@89
|
193 }
|
cannam@89
|
194 if (a->host) free(a->host);
|
cannam@89
|
195 if (a->port) free(a->port);
|
cannam@89
|
196 if (a->ai) freeaddrinfo(a->ai);
|
cannam@89
|
197 free(a);
|
cannam@89
|
198 }
|
cannam@89
|
199 }
|
cannam@89
|
200
|
cannam@89
|
201 int lo_address_errno(lo_address a)
|
cannam@89
|
202 {
|
cannam@89
|
203 return a->errnum;
|
cannam@89
|
204 }
|
cannam@89
|
205
|
cannam@89
|
206 const char *lo_address_errstr(lo_address a)
|
cannam@89
|
207 {
|
cannam@89
|
208 char *msg;
|
cannam@89
|
209
|
cannam@89
|
210 if (a->errstr) {
|
cannam@89
|
211 return a->errstr;
|
cannam@89
|
212 }
|
cannam@89
|
213
|
cannam@89
|
214 msg = strerror(a->errnum);
|
cannam@89
|
215 if (msg) {
|
cannam@89
|
216 return msg;
|
cannam@89
|
217 } else {
|
cannam@89
|
218 return "unknown error";
|
cannam@89
|
219 }
|
cannam@89
|
220
|
cannam@89
|
221 return "unknown error";
|
cannam@89
|
222 }
|
cannam@89
|
223
|
cannam@89
|
224 char *lo_url_get_protocol(const char *url)
|
cannam@89
|
225 {
|
cannam@89
|
226 char *protocol,*ret;
|
cannam@89
|
227
|
cannam@89
|
228 if (!url) {
|
cannam@89
|
229 return NULL;
|
cannam@89
|
230 }
|
cannam@89
|
231
|
cannam@89
|
232 protocol = malloc(strlen(url));
|
cannam@89
|
233
|
cannam@89
|
234 if (sscanf(url, "osc://%s", protocol)) {
|
cannam@89
|
235 fprintf(stderr, PACKAGE_NAME " warning: no protocol specified in URL, "
|
cannam@89
|
236 "assuming UDP.\n");
|
cannam@89
|
237 ret = strdup("udp");
|
cannam@89
|
238 } else if (sscanf(url, "osc.%[^:/[]", protocol)) {
|
cannam@89
|
239 ret = strdup(protocol);
|
cannam@89
|
240 } else {
|
cannam@89
|
241 ret = NULL;
|
cannam@89
|
242 }
|
cannam@89
|
243
|
cannam@89
|
244 free(protocol);
|
cannam@89
|
245
|
cannam@89
|
246 return ret;
|
cannam@89
|
247 }
|
cannam@89
|
248
|
cannam@89
|
249 int lo_url_get_protocol_id(const char *url)
|
cannam@89
|
250 {
|
cannam@89
|
251 if(!url) {
|
cannam@89
|
252 return -1;
|
cannam@89
|
253 }
|
cannam@89
|
254
|
cannam@89
|
255 if(!strncmp(url, "osc:", 4)) {
|
cannam@89
|
256 fprintf(stderr, PACKAGE_NAME " warning: no protocol specified in URL, "
|
cannam@89
|
257 "assuming UDP.\n");
|
cannam@89
|
258 return LO_UDP; // should be LO_DEFAULT?
|
cannam@89
|
259 } else if(!strncmp(url, "osc.udp:", 8)) {
|
cannam@89
|
260 return LO_UDP;
|
cannam@89
|
261 } else if(!strncmp(url, "osc.tcp:", 8)) {
|
cannam@89
|
262 return LO_TCP;
|
cannam@89
|
263 } else if(!strncmp(url, "osc.unix:", 9)) {
|
cannam@89
|
264 return LO_UNIX;
|
cannam@89
|
265 }
|
cannam@89
|
266 return -1;
|
cannam@89
|
267 }
|
cannam@89
|
268
|
cannam@89
|
269 char *lo_url_get_hostname(const char *url)
|
cannam@89
|
270 {
|
cannam@89
|
271 char *hostname = malloc(strlen(url));
|
cannam@89
|
272
|
cannam@89
|
273 if (sscanf(url, "osc://%[^[:/]", hostname)) {
|
cannam@89
|
274 return hostname;
|
cannam@89
|
275 }
|
cannam@89
|
276 if (sscanf(url, "osc.%*[^:/]://[%[^]/]]", hostname)) {
|
cannam@89
|
277 return hostname;
|
cannam@89
|
278 }
|
cannam@89
|
279 if (sscanf(url, "osc.%*[^:/]://%[^[:/]", hostname)) {
|
cannam@89
|
280 return hostname;
|
cannam@89
|
281 }
|
cannam@89
|
282
|
cannam@89
|
283 /* doesnt look like an OSC URL */
|
cannam@89
|
284 free(hostname);
|
cannam@89
|
285
|
cannam@89
|
286 return NULL;
|
cannam@89
|
287 }
|
cannam@89
|
288
|
cannam@89
|
289 char *lo_url_get_port(const char *url)
|
cannam@89
|
290 {
|
cannam@89
|
291 char *port = malloc(strlen(url));
|
cannam@89
|
292
|
cannam@89
|
293 if (sscanf(url, "osc://%*[^:]:%[0-9]", port)) {
|
cannam@89
|
294 return port;
|
cannam@89
|
295 }
|
cannam@89
|
296 if (sscanf(url, "osc.%*[^:]://%*[^:]:%[0-9]", port)) {
|
cannam@89
|
297 return port;
|
cannam@89
|
298 }
|
cannam@89
|
299 if (sscanf(url, "osc://[%*[^]]]:%[0-9]", port)) {
|
cannam@89
|
300 return port;
|
cannam@89
|
301 }
|
cannam@89
|
302 if (sscanf(url, "osc.%*[^:]://[%*[^]]]:%[0-9]", port)) {
|
cannam@89
|
303 return port;
|
cannam@89
|
304 }
|
cannam@89
|
305
|
cannam@89
|
306 /* doesnt look like an OSC URL with port number */
|
cannam@89
|
307 free(port);
|
cannam@89
|
308
|
cannam@89
|
309 return NULL;
|
cannam@89
|
310 }
|
cannam@89
|
311
|
cannam@89
|
312 char *lo_url_get_path(const char *url)
|
cannam@89
|
313 {
|
cannam@89
|
314 char *path = malloc(strlen(url));
|
cannam@89
|
315
|
cannam@89
|
316 if (sscanf(url, "osc://%*[^:]:%*[0-9]%s", path)) {
|
cannam@89
|
317 return path;
|
cannam@89
|
318 }
|
cannam@89
|
319 if (sscanf(url, "osc.%*[^:]://%*[^:]:%*[0-9]%s", path) == 1) {
|
cannam@89
|
320 return path;
|
cannam@89
|
321 }
|
cannam@89
|
322 if (sscanf(url, "osc.unix://%*[^/]%s", path) == 1) {
|
cannam@89
|
323 return path;
|
cannam@89
|
324 }
|
cannam@89
|
325 if (sscanf(url, "osc.%*[^:]://%s", path)) {
|
cannam@89
|
326 return path;
|
cannam@89
|
327 }
|
cannam@89
|
328
|
cannam@89
|
329 /* doesnt look like an OSC URL with port number and path*/
|
cannam@89
|
330 free(path);
|
cannam@89
|
331
|
cannam@89
|
332 return NULL;
|
cannam@89
|
333 }
|
cannam@89
|
334
|
cannam@89
|
335 void lo_address_set_ttl(lo_address t, int ttl)
|
cannam@89
|
336 {
|
cannam@89
|
337 if (t->protocol == LO_UDP)
|
cannam@89
|
338 t->ttl = ttl;
|
cannam@89
|
339 }
|
cannam@89
|
340
|
cannam@89
|
341 int lo_address_get_ttl(lo_address t)
|
cannam@89
|
342 {
|
cannam@89
|
343 return t->ttl;
|
cannam@89
|
344 }
|
cannam@89
|
345
|
cannam@89
|
346 /* vi:set ts=8 sts=4 sw=4: */
|