source: roaraudio/libroar/basic.c @ 2897:a5e99d13e1fa

Last change on this file since 2897:a5e99d13e1fa was 2897:a5e99d13e1fa, checked in by phi, 15 years ago

load config on connect

File size: 11.7 KB
Line 
1//basic.c:
2
3/*
4 *      Copyright (C) Philipp 'ph3-der-loewe' Schafft - 2008
5 *
6 *  This file is part of libroar a part of RoarAudio,
7 *  a cross-platform sound system for both, home and professional use.
8 *  See README for details.
9 *
10 *  This file is free software; you can redistribute it and/or modify
11 *  it under the terms of the GNU General Public License version 3
12 *  as published by the Free Software Foundation.
13 *
14 *  libroar is distributed in the hope that it will be useful,
15 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
16 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17 *  GNU General Public License for more details.
18 *
19 *  You should have received a copy of the GNU General Public License
20 *  along with this software; see the file COPYING.  If not, write to
21 *  the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
22 *
23 *  NOTE for everyone want's to change something and send patches:
24 *  read README and HACKING! There a addition information on
25 *  the license of this document you need to read before you send
26 *  any patches.
27 *
28 *  NOTE for uses of non-GPL (LGPL,...) software using libesd, libartsc
29 *  or libpulse*:
30 *  The libs libroaresd, libroararts and libroarpulse link this lib
31 *  and are therefore GPL. Because of this it may be illigal to use
32 *  them with any software that uses libesd, libartsc or libpulse*.
33 */
34
35#include "libroar.h"
36
37int roar_connect_raw (char * server) {
38 char user_sock[80];
39 char * roar_server;
40 int i = 0;
41 int port = 0;
42 int fh = -1;
43 int is_decnet = 0;
44 char * obj = NULL;
45#if !defined(ROAR_TARGET_WIN32) && !defined(ROAR_TARGET_MICROCONTROLLER)
46 struct passwd * pwd;
47#endif
48#ifdef ROAR_HAVE_LIBDNET
49 struct stat decnet_stat;
50#endif
51
52 roar_errno = ROAR_ERROR_UNKNOWN;
53
54 // load config
55 roar_libroar_get_config();
56
57 if ( server == NULL )
58  server = roar_libroar_get_server();
59
60 if ( server == NULL && (roar_server = getenv("ROAR_SERVER")) != NULL )
61  server = roar_server;
62
63#if !defined(ROAR_TARGET_WIN32) && !defined(ROAR_TARGET_MICROCONTROLLER)
64 if ( server == NULL && (i = readlink("/etc/roarserver", user_sock, 79)) != -1 ) {
65   user_sock[i] = 0;
66   server = user_sock;
67 }
68#endif
69
70 if ( server == NULL || *server == 0 ) {
71  /* connect via defaults */
72
73#ifdef ROAR_HAVE_UNIX
74#ifndef ROAR_TARGET_MICROCONTROLLER
75  roar_server = getenv("HOME");
76#else
77  roar_server = NULL;
78#endif
79
80  if ( roar_server == NULL ) {
81#if !defined(ROAR_TARGET_WIN32) && !defined(ROAR_TARGET_MICROCONTROLLER)
82   if ( (pwd = getpwuid(getuid())) == NULL ) {
83    roar_server = "/NX-HOME-DIR";
84   } else {
85    roar_server = pwd->pw_dir;
86   }
87#else
88   roar_server = "/WIN32-SUCKS";
89#endif
90  }
91
92  snprintf(user_sock, 79, "%s/%s", roar_server, ROAR_DEFAULT_SOCK_USER);
93
94  if ( (fh = roar_socket_connect(user_sock, 0)) != -1 )
95   return fh;
96
97  if ( (fh = roar_socket_connect(ROAR_DEFAULT_SOCK_GLOBAL, 0)) != -1 )
98   return fh;
99#endif
100
101  if ( (fh = roar_socket_connect(ROAR_DEFAULT_HOST, ROAR_DEFAULT_PORT)) != -1 )
102   return fh;
103
104#ifdef ROAR_HAVE_LIBDNET
105  if ( stat(ROAR_PROC_NET_DECNET, &decnet_stat) == 0 ) {
106   if ( roar_socket_get_local_nodename() ) {
107    snprintf(user_sock, 79, "%s::%s", roar_socket_get_local_nodename(), ROAR_DEFAULT_OBJECT);
108    if ( (fh = roar_socket_connect(user_sock, ROAR_DEFAULT_NUM)) != -1 )
109     return fh;
110   }
111  }
112#endif
113
114#ifdef ROAR_HAVE_LIBSLP
115 if ( (server = roar_slp_find_roard(0)) != NULL )
116  if ( (fh = roar_connect_raw(server)) != -1 )
117   return fh;
118
119 /* in case we can not connect to the server given this may be a cache problem,
120    we do a new lookup with the cache disabled in this case                     */
121 ROAR_WARN("roar_connect_raw(*): Can not connect to SLP located server, disabling cache");
122 if ( (server = roar_slp_find_roard(1)) != NULL )
123  if ( (fh = roar_connect_raw(server)) != -1 )
124   return fh;
125#endif
126
127 return -1;
128
129 } else {
130  /* connect via (char*)server */
131  // find a port:
132  if ( *server != '/' ) { // don't test AF_UNIX sockets for ports
133   for (i = 0; server[i] != 0; i++) {
134    if ( server[i] == ':' ) {
135     if ( server[i+1] == ':' ) { // DECnet, leave unchanged
136      is_decnet = 1;
137      obj = &server[i+2];
138      break;
139     }
140
141     port = atoi(server+i+1);
142     server[i] = 0;
143     break;
144    }
145   }
146  }
147
148  if ( is_decnet ) {
149    *user_sock = 0;
150   if ( *server == ':' ) {
151    if ( roar_socket_get_local_nodename() )
152     strncat(user_sock, roar_socket_get_local_nodename(), 6);
153   }
154
155   strncat(user_sock, server, 79);
156   server = user_sock;
157   if ( *obj == 0 ) {
158#ifdef DN_MAXOBJL
159    strncat(user_sock, ROAR_DEFAULT_OBJECT, DN_MAXOBJL+2);
160#else
161    ROAR_ERR("roar_connect_raw(*): size of DECnet object unknown.");
162#endif
163   }
164  }
165
166  if ( port || is_decnet ) {
167   fh = roar_socket_connect(server, port);
168   // restore the original string
169   server[i] = ':';
170  } else {
171   fh = roar_socket_connect(server, ROAR_DEFAULT_PORT);
172  }
173 }
174
175 if ( fh == -1 )
176  roar_errno = ROAR_ERROR_CONNREFUSED;
177
178 ROAR_DBG("roar_connect_raw(*) = %i", fh);
179
180 return fh;
181}
182
183int roar_connect    (struct roar_connection * con, char * server) {
184 int fh;
185
186 if ( con == NULL ) {
187  roar_errno = ROAR_ERROR_INVAL;
188  return -1;
189 }
190
191 roar_errno = ROAR_ERROR_UNKNOWN;
192 fh = roar_connect_raw(server);
193
194 if ( fh == -1 )
195  return -1;
196
197 return roar_connect_fh(con, fh);
198}
199
200int roar_connect_fh (struct roar_connection * con, int fh) {
201
202 if ( con == NULL || fh == -1 ) {
203  roar_errno = ROAR_ERROR_INVAL;
204  return -1;
205 }
206
207 // specal hack to set an ilegal value used internaly in libroar:
208 if ( fh == -2 )
209  fh = -1;
210
211 memset(con, 0, sizeof(struct roar_connection));
212
213 con->__fh = fh;
214
215 roar_errno = ROAR_ERROR_NONE;
216 return 0;
217}
218
219int roar_get_connection_fh (struct roar_connection * con) {
220 roar_debug_warn_sysio("roar_get_connection_fh", "roar_get_connection_vio", NULL);
221
222 if ( con == NULL )
223  return -1;
224
225 return con->__fh;
226}
227
228int roar_get_connection_vio (struct roar_connection * con, struct roar_vio_calls * vio) {
229 if ( con == NULL || vio == NULL )
230  return -1;
231
232 return roar_vio_open_fh_socket(vio, con->__fh);
233}
234
235int roar_disconnect (struct roar_connection * con) {
236 struct roar_vio_calls vio;
237 struct roar_message m;
238
239 m.datalen = 0;
240 m.stream  = 0;
241 m.pos     = 0;
242 m.cmd     = ROAR_CMD_QUIT;
243
244 roar_req(con, &m, NULL);
245
246 if ( roar_get_connection_vio(con, &vio) != -1 ) {
247  roar_vio_close(&vio);
248 }
249
250 roar_connect_fh(con, -2);
251
252 roar_errno = ROAR_ERROR_NONE;
253
254 return 0;
255}
256
257int roar_identify   (struct roar_connection * con, char * name) {
258 struct roar_message mes;
259 pid_t pid;
260 int max_len;
261
262 roar_errno = ROAR_ERROR_UNKNOWN;
263
264 ROAR_DBG("roar_identify(*): try to identify myself...");
265
266 mes.cmd    = ROAR_CMD_IDENTIFY;
267 mes.stream = 0;
268 mes.pos    = 0;
269
270 ROAR_DBG("roar_identify(*): name=%p", name);
271
272 if ( name == NULL )
273  name = "libroar client";
274
275 ROAR_DBG("roar_identify(*): name=%p", name);
276
277 max_len = strlen(name);
278 ROAR_DBG("roar_identify(*): strlen(name) = %i", max_len);
279
280 if ( max_len > (LIBROAR_BUFFER_MSGDATA - 5) )
281  max_len = LIBROAR_BUFFER_MSGDATA - 5;
282
283 mes.datalen = 5 + max_len;
284 mes.data[0] = 1;
285
286 pid = getpid();
287 *(uint32_t*)(mes.data+1) = ROAR_HOST2NET32(pid);
288 ROAR_DBG("roar_identify(*): pid = %i", pid);
289
290 strncpy(mes.data+5, name, max_len);
291
292 return roar_req(con, &mes, NULL);
293}
294
295#define _ROAR_MESS_BUF_LEN (1 /* version */ + 1 /* cmd */ + 2 /* stream */ + 4 /* pos */ + 2 /* datalen */)
296int roar_send_message (struct roar_connection * con, struct roar_message * mes, char * data) {
297 struct roar_vio_calls vio;
298
299 if ( roar_get_connection_vio(con, &vio) == -1 )
300  return -1;
301
302 return roar_vsend_message(&vio, mes, data);
303}
304
305int roar_vsend_message(struct roar_vio_calls * vio, struct roar_message * mes, char *  data) {
306 char buf[_ROAR_MESS_BUF_LEN];
307
308 roar_errno = ROAR_ERROR_UNKNOWN;
309
310 ROAR_DBG("roar_send_message(*): try to send an request...");
311
312 buf[0] = _ROAR_MESSAGE_VERSION;
313 buf[1] = (unsigned char) mes->cmd;
314 *(uint16_t*)(buf+2) = ROAR_HOST2NET16(mes->stream);
315 *(uint32_t*)(buf+4) = ROAR_HOST2NET32(mes->pos);
316 *(uint16_t*)(buf+8) = ROAR_HOST2NET16(mes->datalen);
317
318 if ( roar_vio_write(vio, buf, _ROAR_MESS_BUF_LEN) != _ROAR_MESS_BUF_LEN ) {
319  roar_errno = ROAR_ERROR_PIPE;
320  return -1;
321 }
322
323 if ( mes->datalen != 0 ) {
324  if ( roar_vio_write(vio, data == NULL ? mes->data : data, mes->datalen) != mes->datalen ) {
325   roar_errno = ROAR_ERROR_PIPE;
326   return -1;
327  }
328 }
329
330 roar_errno = ROAR_ERROR_NONE;
331
332 ROAR_DBG("roar_send_message(*) = 0");
333 return 0;
334}
335
336int roar_recv_message (struct roar_connection * con, struct roar_message * mes, char ** data) {
337 struct roar_vio_calls vio;
338
339 if ( roar_get_connection_vio(con, &vio) == -1 )
340  return -1;
341
342 return roar_vrecv_message(&vio, mes, data);
343}
344
345int roar_vrecv_message(struct roar_vio_calls * vio, struct roar_message * mes, char ** data) {
346 char buf[_ROAR_MESS_BUF_LEN];
347
348 roar_errno = ROAR_ERROR_UNKNOWN;
349
350 ROAR_DBG("roar_recv_message(*): try to get a response form the server...");
351
352 if ( data )
353  *data = NULL;
354
355 if ( roar_vio_read(vio, buf, _ROAR_MESS_BUF_LEN) != _ROAR_MESS_BUF_LEN ) {
356  roar_errno = ROAR_ERROR_PROTO;
357  return -1;
358 }
359
360 ROAR_DBG("roar_recv_message(*): Got a header");
361
362 if ( buf[0] != _ROAR_MESSAGE_VERSION ) {
363  roar_errno = ROAR_ERROR_PROTO;
364  return -1;
365 }
366
367 mes->cmd     = (unsigned char)buf[1];
368 mes->stream  = ROAR_NET2HOST16(*(uint16_t*)(buf+2));
369 mes->pos     = ROAR_NET2HOST32(*(uint32_t*)(buf+4));
370 mes->datalen = ROAR_NET2HOST16(*(uint16_t*)(buf+8));
371
372 ROAR_DBG("roar_recv_message(*): command=%i(%s)", mes->cmd,
373           mes->cmd == ROAR_CMD_OK ? "OK" : (mes->cmd == ROAR_CMD_ERROR ? "ERROR" : "UNKNOWN"));
374
375 if ( mes->datalen == 0 ) {
376  ROAR_DBG("roar_recv_message(*): no data in this pkg");
377  ROAR_DBG("roar_recv_message(*) = 0");
378  roar_errno = ROAR_ERROR_NONE;
379  return 0;
380 }
381
382 if ( mes->datalen <= LIBROAR_BUFFER_MSGDATA ) {
383  if ( roar_vio_read(vio, mes->data, mes->datalen) == mes->datalen ) {
384   ROAR_DBG("roar_recv_message(*): Got data!");
385   ROAR_DBG("roar_recv_message(*) = 0");
386   roar_errno = ROAR_ERROR_NONE;
387   return 0;
388  }
389
390  roar_errno = ROAR_ERROR_PIPE;
391  return -1;
392 } else {
393  if ( data == NULL ) {
394   roar_errno = ROAR_ERROR_MSGSIZE;
395   return -1;
396  }
397
398  if ( (*data = malloc(mes->datalen)) == NULL ) {
399   roar_errno = ROAR_ERROR_NOMEM;
400   return -1;
401  }
402
403  if ( mes->datalen == 0 ) {
404   roar_errno = ROAR_ERROR_NONE;
405   return 0;
406  }
407
408  if ( roar_vio_read(vio, *data, mes->datalen) == mes->datalen ) {
409   ROAR_DBG("roar_recv_message(*): Got data!");
410   ROAR_DBG("roar_recv_message(*) = 0");
411   roar_errno = ROAR_ERROR_NONE;
412   return 0;
413  }
414
415  roar_errno = ROAR_ERROR_PIPE;
416  return -1;
417 }
418
419 // what happened here?
420 return -1;
421}
422
423int roar_req (struct roar_connection * con, struct roar_message * mes, char ** data) {
424 struct roar_vio_calls vio;
425
426 if ( roar_get_connection_vio(con, &vio) == -1 )
427  return -1;
428
429 return roar_vreq(&vio, mes, data);
430}
431
432int roar_vreq         (struct roar_vio_calls * vio, struct roar_message * mes, char ** data) {
433 if ( roar_vsend_message(vio, mes, data ? *data : NULL) != 0 )
434  return -1;
435
436 if ( data )
437  free(*data);
438
439 roar_vio_sync(vio); // we need to do this becasue of ssl/compressed links
440
441 return roar_vrecv_message(vio, mes, data);
442}
443
444int roar_debug_message_print (struct roar_message * mes) {
445 if ( mes == NULL )
446  return -1;
447
448 ROAR_DBG("roar_debug_message_print(*): Command: %i", mes->cmd);
449 ROAR_DBG("roar_debug_message_print(*): Stream : %u", mes->stream);
450 ROAR_DBG("roar_debug_message_print(*): Pos    : %u", mes->pos);
451 ROAR_DBG("roar_debug_message_print(*): Datalen: %i", mes->datalen);
452
453 ROAR_DBG("roar_debug_message_print(*) = 0");
454 return 0;
455}
456
457int roar_debug_audio_info_print (struct roar_audio_info * info) {
458 if ( info == NULL )
459  return -1;
460
461 ROAR_DBG("roar_debug_audio_info_print(*): Rate    : %i", info->rate);
462 ROAR_DBG("roar_debug_audio_info_print(*): Channels: %i", info->channels);
463 ROAR_DBG("roar_debug_audio_info_print(*): Bits    : %i", info->bits);
464 ROAR_DBG("roar_debug_audio_info_print(*): Codec   : %i", info->codec);
465
466 ROAR_DBG("roar_debug_audio_info_print(*) = 0");
467 return 0;
468}
469
470//ll
Note: See TracBrowser for help on using the repository browser.