source: roaraudio/libroar/basic.c @ 1660:99bfd21f00ef

Last change on this file since 1660:99bfd21f00ef was 1660:99bfd21f00ef, checked in by phi, 15 years ago

changed name of fh in con struct to fh, this should all apps requiring the private member to fail to build, added function to get fh, change code to use them both everythere

File size: 10.8 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 if ( server == NULL && (roar_server = getenv("ROAR_SERVER")) != NULL )
55  server = roar_server;
56
57#if !defined(ROAR_TARGET_WIN32) && !defined(ROAR_TARGET_MICROCONTROLLER)
58 if ( server == NULL && (i = readlink("/etc/roarserver", user_sock, 79)) != -1 ) {
59   user_sock[i] = 0;
60   server = user_sock;
61 }
62#endif
63
64 if ( server == NULL || *server == 0 ) {
65  /* connect via defaults */
66
67#ifndef ROAR_TARGET_MICROCONTROLLER
68  roar_server = getenv("HOME");
69#else
70  roar_server = NULL;
71#endif
72
73  if ( roar_server == NULL ) {
74#if !defined(ROAR_TARGET_WIN32) && !defined(ROAR_TARGET_MICROCONTROLLER)
75   if ( (pwd = getpwuid(getuid())) == NULL ) {
76    roar_server = "/NX-HOME-DIR";
77   } else {
78    roar_server = pwd->pw_dir;
79   }
80#else
81   roar_server = "/WIN32-SUCKS";
82#endif
83  }
84
85  snprintf(user_sock, 79, "%s/%s", roar_server, ROAR_DEFAULT_SOCK_USER);
86
87  if ( (fh = roar_socket_connect(user_sock, 0)) != -1 )
88   return fh;
89
90  if ( (fh = roar_socket_connect(ROAR_DEFAULT_SOCK_GLOBAL, 0)) != -1 )
91   return fh;
92
93  if ( (fh = roar_socket_connect(ROAR_DEFAULT_HOST, ROAR_DEFAULT_PORT)) != -1 )
94   return fh;
95
96#ifdef ROAR_HAVE_LIBDNET
97  if ( stat(ROAR_PROC_NET_DECNET, &decnet_stat) == 0 ) {
98   if ( roar_socket_get_local_nodename() ) {
99    snprintf(user_sock, 79, "%s::%s", roar_socket_get_local_nodename(), ROAR_DEFAULT_OBJECT);
100    return roar_socket_connect(user_sock, ROAR_DEFAULT_NUM);
101   }
102  }
103#endif
104
105 } else {
106  /* connect via (char*)server */
107  // find a port:
108  if ( *server != '/' ) { // don't test AF_UNIX sockets for ports
109   for (i = 0; server[i] != 0; i++) {
110    if ( server[i] == ':' ) {
111     if ( server[i+1] == ':' ) { // DECnet, leave unchanged
112      is_decnet = 1;
113      obj = &server[i+2];
114      break;
115     }
116
117     port = atoi(server+i+1);
118     server[i] = 0;
119     break;
120    }
121   }
122  }
123
124  if ( is_decnet ) {
125    *user_sock = 0;
126   if ( *server == ':' ) {
127    if ( roar_socket_get_local_nodename() )
128     strncat(user_sock, roar_socket_get_local_nodename(), 6);
129   }
130
131   strncat(user_sock, server, 79);
132   server = user_sock;
133   if ( *obj == 0 ) {
134#ifdef DN_MAXOBJL
135    strncat(user_sock, ROAR_DEFAULT_OBJECT, DN_MAXOBJL+2);
136#else
137    ROAR_ERR("roar_connect_raw(*): size of DECnet object unknown.");
138#endif
139   }
140  }
141
142  if ( port || is_decnet ) {
143   fh = roar_socket_connect(server, port);
144   // restore the original string
145   server[i] = ':';
146  } else {
147   fh = roar_socket_connect(server, ROAR_DEFAULT_PORT);
148  }
149 }
150
151 if ( fh == -1 )
152  roar_errno = ROAR_ERROR_CONNREFUSED;
153
154 ROAR_DBG("roar_connect_raw(*) = %i", fh);
155
156 return fh;
157}
158
159int roar_connect    (struct roar_connection * con, char * server) {
160 int fh;
161
162 if ( con == NULL ) {
163  roar_errno = ROAR_ERROR_INVAL;
164  return -1;
165 }
166
167 roar_errno = ROAR_ERROR_UNKNOWN;
168 fh = roar_connect_raw(server);
169
170 if ( fh == -1 )
171  return -1;
172
173 return roar_connect_fh(con, fh);
174}
175
176int roar_connect_fh (struct roar_connection * con, int fh) {
177
178 if ( con == NULL || fh == -1 ) {
179  roar_errno = ROAR_ERROR_INVAL;
180  return -1;
181 }
182
183 // specal hack to set an ilegal value used internaly in libroar:
184 if ( fh == -2 )
185  fh = -1;
186
187 memset(con, 0, sizeof(struct roar_connection));
188
189 con->__fh = fh;
190
191 roar_errno = ROAR_ERROR_NONE;
192 return 0;
193}
194
195int roar_get_connection_fh (struct roar_connection * con) {
196 return con->__fh;
197}
198
199int roar_disconnect (struct roar_connection * con) {
200 struct roar_message m;
201
202 m.datalen = 0;
203 m.stream  = 0;
204 m.pos     = 0;
205 m.cmd     = ROAR_CMD_QUIT;
206
207 roar_req(con, &m, NULL);
208
209#ifdef ROAR_HAVE_IO_POSIX
210 close(roar_get_connection_fh(con));
211#endif
212
213 roar_connect_fh(con, -2);
214
215 roar_errno = ROAR_ERROR_NONE;
216
217 return 0;
218}
219
220int roar_identify   (struct roar_connection * con, char * name) {
221 struct roar_message mes;
222 pid_t pid;
223 int max_len;
224
225 roar_errno = ROAR_ERROR_UNKNOWN;
226
227 ROAR_DBG("roar_identify(*): try to identify myself...");
228
229 mes.cmd    = ROAR_CMD_IDENTIFY;
230 mes.stream = 0;
231 mes.pos    = 0;
232
233 ROAR_DBG("roar_identify(*): name=%p", name);
234
235 if ( name == NULL )
236  name = "libroar client";
237
238 ROAR_DBG("roar_identify(*): name=%p", name);
239
240 max_len = strlen(name);
241 ROAR_DBG("roar_identify(*): strlen(name) = %i", max_len);
242
243 if ( max_len > (LIBROAR_BUFFER_MSGDATA - 5) )
244  max_len = LIBROAR_BUFFER_MSGDATA - 5;
245
246 mes.datalen = 5 + max_len;
247 mes.data[0] = 1;
248
249 pid = getpid();
250 *(uint32_t*)(mes.data+1) = ROAR_HOST2NET32(pid);
251 ROAR_DBG("roar_identify(*): pid = %i", pid);
252
253 strncpy(mes.data+5, name, max_len);
254
255 return roar_req(con, &mes, NULL);
256}
257
258#define _ROAR_MESS_BUF_LEN (1 /* version */ + 1 /* cmd */ + 2 /* stream */ + 4 /* pos */ + 2 /* datalen */)
259int roar_send_message (struct roar_connection * con, struct roar_message * mes, char * data) {
260 struct roar_vio_calls vio;
261
262 if ( roar_vio_open_fh_socket(&vio, roar_get_connection_fh(con)) == -1 )
263  return -1;
264
265 return roar_vsend_message(&vio, mes, data);
266}
267
268int roar_vsend_message(struct roar_vio_calls * vio, struct roar_message * mes, char *  data) {
269 char buf[_ROAR_MESS_BUF_LEN];
270
271 roar_errno = ROAR_ERROR_UNKNOWN;
272
273 ROAR_DBG("roar_send_message(*): try to send an request...");
274
275 buf[0] = _ROAR_MESSAGE_VERSION;
276 buf[1] = (unsigned char) mes->cmd;
277 *(uint16_t*)(buf+2) = ROAR_HOST2NET16(mes->stream);
278 *(uint32_t*)(buf+4) = ROAR_HOST2NET32(mes->pos);
279 *(uint16_t*)(buf+8) = ROAR_HOST2NET16(mes->datalen);
280
281 if ( roar_vio_write(vio, buf, _ROAR_MESS_BUF_LEN) != _ROAR_MESS_BUF_LEN ) {
282  roar_errno = ROAR_ERROR_PIPE;
283  return -1;
284 }
285
286 if ( mes->datalen != 0 ) {
287  if ( roar_vio_write(vio, data == NULL ? mes->data : data, mes->datalen) != mes->datalen ) {
288   roar_errno = ROAR_ERROR_PIPE;
289   return -1;
290  }
291 }
292
293 roar_vio_sync(vio); // we need to do this becasue of ssl/compressed links
294
295 roar_errno = ROAR_ERROR_NONE;
296
297 ROAR_DBG("roar_send_message(*) = 0");
298 return 0;
299}
300
301int roar_recv_message (struct roar_connection * con, struct roar_message * mes, char ** data) {
302 struct roar_vio_calls vio;
303
304 if ( roar_vio_open_fh_socket(&vio, roar_get_connection_fh(con)) == -1 )
305  return -1;
306
307 return roar_vrecv_message(&vio, mes, data);
308}
309
310int roar_vrecv_message(struct roar_vio_calls * vio, struct roar_message * mes, char ** data) {
311 char buf[_ROAR_MESS_BUF_LEN];
312
313 roar_errno = ROAR_ERROR_UNKNOWN;
314
315 ROAR_DBG("roar_recv_message(*): try to get a response form the server...");
316
317 if ( data )
318  *data = NULL;
319
320 if ( roar_vio_read(vio, buf, _ROAR_MESS_BUF_LEN) != _ROAR_MESS_BUF_LEN ) {
321  roar_errno = ROAR_ERROR_PROTO;
322  return -1;
323 }
324
325 ROAR_DBG("roar_recv_message(*): Got a header");
326
327 if ( buf[0] != _ROAR_MESSAGE_VERSION ) {
328  roar_errno = ROAR_ERROR_PROTO;
329  return -1;
330 }
331
332 mes->cmd     = (unsigned char)buf[1];
333 mes->stream  = ROAR_NET2HOST16(*(uint16_t*)(buf+2));
334 mes->pos     = ROAR_NET2HOST32(*(uint32_t*)(buf+4));
335 mes->datalen = ROAR_NET2HOST16(*(uint16_t*)(buf+8));
336
337 ROAR_DBG("roar_recv_message(*): command=%i(%s)", mes->cmd,
338           mes->cmd == ROAR_CMD_OK ? "OK" : (mes->cmd == ROAR_CMD_ERROR ? "ERROR" : "UNKNOWN"));
339
340 if ( mes->datalen == 0 ) {
341  ROAR_DBG("roar_recv_message(*): no data in this pkg");
342  ROAR_DBG("roar_recv_message(*) = 0");
343  roar_errno = ROAR_ERROR_NONE;
344  return 0;
345 }
346
347 if ( mes->datalen <= LIBROAR_BUFFER_MSGDATA ) {
348  if ( roar_vio_read(vio, mes->data, mes->datalen) == mes->datalen ) {
349   ROAR_DBG("roar_recv_message(*): Got data!");
350   ROAR_DBG("roar_recv_message(*) = 0");
351   roar_errno = ROAR_ERROR_NONE;
352   return 0;
353  }
354
355  roar_errno = ROAR_ERROR_PIPE;
356  return -1;
357 } else {
358  if ( data == NULL ) {
359   roar_errno = ROAR_ERROR_MSGSIZE;
360   return -1;
361  }
362
363  if ( (*data = malloc(mes->datalen)) == NULL ) {
364   roar_errno = ROAR_ERROR_NOMEM;
365   return -1;
366  }
367
368  if ( mes->datalen == 0 ) {
369   roar_errno = ROAR_ERROR_NONE;
370   return 0;
371  }
372
373  if ( roar_vio_read(vio, *data, mes->datalen) == mes->datalen ) {
374   ROAR_DBG("roar_recv_message(*): Got data!");
375   ROAR_DBG("roar_recv_message(*) = 0");
376   roar_errno = ROAR_ERROR_NONE;
377   return 0;
378  }
379
380  roar_errno = ROAR_ERROR_PIPE;
381  return -1;
382 }
383
384 // what happened here?
385 return -1;
386}
387
388int roar_req (struct roar_connection * con, struct roar_message * mes, char ** data) {
389 struct roar_vio_calls vio;
390
391 if ( roar_vio_open_fh_socket(&vio, roar_get_connection_fh(con)) == -1 )
392  return -1;
393
394 return roar_vreq(&vio, mes, data);
395}
396
397int roar_vreq         (struct roar_vio_calls * vio, struct roar_message * mes, char ** data) {
398 if ( roar_vsend_message(vio, mes, data ? *data : NULL) != 0 )
399  return -1;
400
401 if ( data )
402  free(*data);
403
404 return roar_vrecv_message(vio, mes, data);
405}
406
407int roar_debug_message_print (struct roar_message * mes) {
408 if ( mes == NULL )
409  return -1;
410
411 ROAR_DBG("roar_debug_message_print(*): Command: %i", mes->cmd);
412 ROAR_DBG("roar_debug_message_print(*): Stream : %u", mes->stream);
413 ROAR_DBG("roar_debug_message_print(*): Pos    : %u", mes->pos);
414 ROAR_DBG("roar_debug_message_print(*): Datalen: %i", mes->datalen);
415
416 ROAR_DBG("roar_debug_message_print(*) = 0");
417 return 0;
418}
419
420int roar_debug_audio_info_print (struct roar_audio_info * info) {
421 if ( info == NULL )
422  return -1;
423
424 ROAR_DBG("roar_debug_audio_info_print(*): Rate    : %i", info->rate);
425 ROAR_DBG("roar_debug_audio_info_print(*): Channels: %i", info->channels);
426 ROAR_DBG("roar_debug_audio_info_print(*): Bits    : %i", info->bits);
427 ROAR_DBG("roar_debug_audio_info_print(*): Codec   : %i", info->codec);
428
429 ROAR_DBG("roar_debug_audio_info_print(*) = 0");
430 return 0;
431}
432
433//ll
Note: See TracBrowser for help on using the repository browser.