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