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
RevLine 
[0]1//basic.c:
2
[690]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
[0]35#include "libroar.h"
36
37int roar_connect_raw (char * server) {
38 char user_sock[80];
39 char * roar_server;
[701]40 int i = 0;
[0]41 int port = 0;
42 int fh = -1;
[501]43 int is_decnet = 0;
[516]44 char * obj = NULL;
[1475]45#if !defined(ROAR_TARGET_WIN32) && !defined(ROAR_TARGET_MICROCONTROLLER)
[1026]46 struct passwd * pwd;
[1393]47#endif
[828]48#ifdef ROAR_HAVE_LIBDNET
49 struct stat decnet_stat;
50#endif
[0]51
[807]52 roar_errno = ROAR_ERROR_UNKNOWN;
53
[2897]54 // load config
55 roar_libroar_get_config();
56
[2567]57 if ( server == NULL )
58  server = roar_libroar_get_server();
59
[61]60 if ( server == NULL && (roar_server = getenv("ROAR_SERVER")) != NULL )
[0]61  server = roar_server;
62
[1436]63#if !defined(ROAR_TARGET_WIN32) && !defined(ROAR_TARGET_MICROCONTROLLER)
[448]64 if ( server == NULL && (i = readlink("/etc/roarserver", user_sock, 79)) != -1 ) {
65   user_sock[i] = 0;
66   server = user_sock;
67 }
[1093]68#endif
[448]69
[61]70 if ( server == NULL || *server == 0 ) {
[0]71  /* connect via defaults */
72
[1764]73#ifdef ROAR_HAVE_UNIX
[1436]74#ifndef ROAR_TARGET_MICROCONTROLLER
[1026]75  roar_server = getenv("HOME");
[1435]76#else
77  roar_server = NULL;
78#endif
[1026]79
80  if ( roar_server == NULL ) {
[1436]81#if !defined(ROAR_TARGET_WIN32) && !defined(ROAR_TARGET_MICROCONTROLLER)
[1026]82   if ( (pwd = getpwuid(getuid())) == NULL ) {
83    roar_server = "/NX-HOME-DIR";
84   } else {
85    roar_server = pwd->pw_dir;
86   }
[1078]87#else
88   roar_server = "/WIN32-SUCKS";
89#endif
[1026]90  }
91
92  snprintf(user_sock, 79, "%s/%s", roar_server, ROAR_DEFAULT_SOCK_USER);
[0]93
94  if ( (fh = roar_socket_connect(user_sock, 0)) != -1 )
95   return fh;
96
[237]97  if ( (fh = roar_socket_connect(ROAR_DEFAULT_SOCK_GLOBAL, 0)) != -1 )
98   return fh;
[1764]99#endif
[237]100
[0]101  if ( (fh = roar_socket_connect(ROAR_DEFAULT_HOST, ROAR_DEFAULT_PORT)) != -1 )
102   return fh;
103
[828]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);
[2010]108    if ( (fh = roar_socket_connect(user_sock, ROAR_DEFAULT_NUM)) != -1 )
109     return fh;
[828]110   }
[522]111  }
[828]112#endif
[2007]113
114#ifdef ROAR_HAVE_LIBSLP
[2014]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;
[2007]125#endif
[522]126
[2014]127 return -1;
128
[0]129 } else {
130  /* connect via (char*)server */
[501]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;
[516]137      obj = &server[i+2];
[501]138      break;
139     }
140
141     port = atoi(server+i+1);
142     server[i] = 0;
143     break;
144    }
[0]145   }
146  }
147
[521]148  if ( is_decnet ) {
149    *user_sock = 0;
150   if ( *server == ':' ) {
151    if ( roar_socket_get_local_nodename() )
[1066]152     strncat(user_sock, roar_socket_get_local_nodename(), 6);
[521]153   }
154
[1066]155   strncat(user_sock, server, 79);
[516]156   server = user_sock;
[521]157   if ( *obj == 0 ) {
[1066]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
[521]163   }
[516]164  }
165
[501]166  if ( port || is_decnet ) {
[0]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
[807]175 if ( fh == -1 )
176  roar_errno = ROAR_ERROR_CONNREFUSED;
177
[0]178 ROAR_DBG("roar_connect_raw(*) = %i", fh);
179
180 return fh;
181}
182
183int roar_connect    (struct roar_connection * con, char * server) {
[1315]184 int fh;
185
186 if ( con == NULL ) {
187  roar_errno = ROAR_ERROR_INVAL;
188  return -1;
189 }
190
[807]191 roar_errno = ROAR_ERROR_UNKNOWN;
[1315]192 fh = roar_connect_raw(server);
[0]193
[1315]194 if ( fh == -1 )
[0]195  return -1;
196
[1315]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
[1660]213 con->__fh = fh;
[1315]214
[807]215 roar_errno = ROAR_ERROR_NONE;
[0]216 return 0;
217}
218
[1660]219int roar_get_connection_fh (struct roar_connection * con) {
[2809]220 roar_debug_warn_sysio("roar_get_connection_fh", "roar_get_connection_vio", NULL);
221
[2043]222 if ( con == NULL )
223  return -1;
224
[1660]225 return con->__fh;
226}
227
[2043]228int roar_get_connection_vio (struct roar_connection * con, struct roar_vio_calls * vio) {
229 if ( con == NULL || vio == NULL )
230  return -1;
231
[2809]232 return roar_vio_open_fh_socket(vio, con->__fh);
[2043]233}
234
[0]235int roar_disconnect (struct roar_connection * con) {
[2809]236 struct roar_vio_calls vio;
[0]237 struct roar_message m;
238
239 m.datalen = 0;
240 m.stream  = 0;
[133]241 m.pos     = 0;
[0]242 m.cmd     = ROAR_CMD_QUIT;
243
244 roar_req(con, &m, NULL);
245
[2809]246 if ( roar_get_connection_vio(con, &vio) != -1 ) {
247  roar_vio_close(&vio);
248 }
[0]249
[1660]250 roar_connect_fh(con, -2);
[0]251
[807]252 roar_errno = ROAR_ERROR_NONE;
253
[0]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
[807]262 roar_errno = ROAR_ERROR_UNKNOWN;
263
[0]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
[8]295#define _ROAR_MESS_BUF_LEN (1 /* version */ + 1 /* cmd */ + 2 /* stream */ + 4 /* pos */ + 2 /* datalen */)
[0]296int roar_send_message (struct roar_connection * con, struct roar_message * mes, char * data) {
[1319]297 struct roar_vio_calls vio;
298
[2809]299 if ( roar_get_connection_vio(con, &vio) == -1 )
[1319]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) {
[0]306 char buf[_ROAR_MESS_BUF_LEN];
307
[807]308 roar_errno = ROAR_ERROR_UNKNOWN;
309
[0]310 ROAR_DBG("roar_send_message(*): try to send an request...");
311
[8]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);
[0]317
[1319]318 if ( roar_vio_write(vio, buf, _ROAR_MESS_BUF_LEN) != _ROAR_MESS_BUF_LEN ) {
[807]319  roar_errno = ROAR_ERROR_PIPE;
[0]320  return -1;
[807]321 }
[0]322
[807]323 if ( mes->datalen != 0 ) {
[1319]324  if ( roar_vio_write(vio, data == NULL ? mes->data : data, mes->datalen) != mes->datalen ) {
[807]325   roar_errno = ROAR_ERROR_PIPE;
[0]326   return -1;
[807]327  }
328 }
329
330 roar_errno = ROAR_ERROR_NONE;
[0]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) {
[1319]337 struct roar_vio_calls vio;
338
[2809]339 if ( roar_get_connection_vio(con, &vio) == -1 )
[1319]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) {
[0]346 char buf[_ROAR_MESS_BUF_LEN];
347
[807]348 roar_errno = ROAR_ERROR_UNKNOWN;
349
[0]350 ROAR_DBG("roar_recv_message(*): try to get a response form the server...");
351
352 if ( data )
353  *data = NULL;
354
[1319]355 if ( roar_vio_read(vio, buf, _ROAR_MESS_BUF_LEN) != _ROAR_MESS_BUF_LEN ) {
[807]356  roar_errno = ROAR_ERROR_PROTO;
[0]357  return -1;
[807]358 }
[0]359
360 ROAR_DBG("roar_recv_message(*): Got a header");
361
[807]362 if ( buf[0] != _ROAR_MESSAGE_VERSION ) {
363  roar_errno = ROAR_ERROR_PROTO;
[8]364  return -1;
[807]365 }
[8]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));
[0]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
[104]375 if ( mes->datalen == 0 ) {
376  ROAR_DBG("roar_recv_message(*): no data in this pkg");
377  ROAR_DBG("roar_recv_message(*) = 0");
[807]378  roar_errno = ROAR_ERROR_NONE;
[104]379  return 0;
380 }
381
[0]382 if ( mes->datalen <= LIBROAR_BUFFER_MSGDATA ) {
[1319]383  if ( roar_vio_read(vio, mes->data, mes->datalen) == mes->datalen ) {
[0]384   ROAR_DBG("roar_recv_message(*): Got data!");
385   ROAR_DBG("roar_recv_message(*) = 0");
[807]386   roar_errno = ROAR_ERROR_NONE;
[0]387   return 0;
388  }
[807]389
390  roar_errno = ROAR_ERROR_PIPE;
[0]391  return -1;
392 } else {
[807]393  if ( data == NULL ) {
394   roar_errno = ROAR_ERROR_MSGSIZE;
[0]395   return -1;
[807]396  }
[0]397
[807]398  if ( (*data = malloc(mes->datalen)) == NULL ) {
399   roar_errno = ROAR_ERROR_NOMEM;
[0]400   return -1;
[807]401  }
[0]402
[807]403  if ( mes->datalen == 0 ) {
404   roar_errno = ROAR_ERROR_NONE;
[0]405   return 0;
[807]406  }
[0]407
[1319]408  if ( roar_vio_read(vio, *data, mes->datalen) == mes->datalen ) {
[0]409   ROAR_DBG("roar_recv_message(*): Got data!");
410   ROAR_DBG("roar_recv_message(*) = 0");
[807]411   roar_errno = ROAR_ERROR_NONE;
[0]412   return 0;
413  }
[807]414
415  roar_errno = ROAR_ERROR_PIPE;
[0]416  return -1;
417 }
418
[807]419 // what happened here?
[0]420 return -1;
421}
422
423int roar_req (struct roar_connection * con, struct roar_message * mes, char ** data) {
[1319]424 struct roar_vio_calls vio;
425
[2809]426 if ( roar_get_connection_vio(con, &vio) == -1 )
[1319]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 )
[0]434  return -1;
435
436 if ( data )
437  free(*data);
438
[2053]439 roar_vio_sync(vio); // we need to do this becasue of ssl/compressed links
440
[1319]441 return roar_vrecv_message(vio, mes, data);
[0]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.