source: roaraudio/libroar/basic.c @ 1026:4d1fc7a9a164

Last change on this file since 1026:4d1fc7a9a164 was 1026:4d1fc7a9a164, checked in by phi, 15 years ago

get home dir via NSS if $HOME is not set

File size: 8.9 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 struct passwd * pwd;
46#ifdef ROAR_HAVE_LIBDNET
47 struct stat decnet_stat;
48#endif
49
50 roar_errno = ROAR_ERROR_UNKNOWN;
51
52 if ( server == NULL && (roar_server = getenv("ROAR_SERVER")) != NULL )
53  server = roar_server;
54
55 if ( server == NULL && (i = readlink("/etc/roarserver", user_sock, 79)) != -1 ) {
56   user_sock[i] = 0;
57   server = user_sock;
58 }
59
60 if ( server == NULL || *server == 0 ) {
61  /* connect via defaults */
62
63
64  roar_server = getenv("HOME");
65
66  if ( roar_server == NULL ) {
67   if ( (pwd = getpwuid(getuid())) == NULL ) {
68    roar_server = "/NX-HOME-DIR";
69   } else {
70    roar_server = pwd->pw_dir;
71   }
72  }
73
74  snprintf(user_sock, 79, "%s/%s", roar_server, ROAR_DEFAULT_SOCK_USER);
75
76  if ( (fh = roar_socket_connect(user_sock, 0)) != -1 )
77   return fh;
78
79  if ( (fh = roar_socket_connect(ROAR_DEFAULT_SOCK_GLOBAL, 0)) != -1 )
80   return fh;
81
82  if ( (fh = roar_socket_connect(ROAR_DEFAULT_HOST, ROAR_DEFAULT_PORT)) != -1 )
83   return fh;
84
85#ifdef ROAR_HAVE_LIBDNET
86  if ( stat(ROAR_PROC_NET_DECNET, &decnet_stat) == 0 ) {
87   if ( roar_socket_get_local_nodename() ) {
88    snprintf(user_sock, 79, "%s::%s", roar_socket_get_local_nodename(), ROAR_DEFAULT_OBJECT);
89    return roar_socket_connect(user_sock, ROAR_DEFAULT_NUM);
90   }
91  }
92#endif
93
94 } else {
95  /* connect via (char*)server */
96  // find a port:
97  if ( *server != '/' ) { // don't test AF_UNIX sockets for ports
98   for (i = 0; server[i] != 0; i++) {
99    if ( server[i] == ':' ) {
100     if ( server[i+1] == ':' ) { // DECnet, leave unchanged
101      is_decnet = 1;
102      obj = &server[i+2];
103      break;
104     }
105
106     port = atoi(server+i+1);
107     server[i] = 0;
108     break;
109    }
110   }
111  }
112
113  if ( is_decnet ) {
114    *user_sock = 0;
115   if ( *server == ':' ) {
116    if ( roar_socket_get_local_nodename() )
117     strcat(user_sock, roar_socket_get_local_nodename());
118   }
119
120   strcat(user_sock, server);
121   server = user_sock;
122   if ( *obj == 0 ) {
123    strcat(user_sock, ROAR_DEFAULT_OBJECT);
124   }
125  }
126
127  if ( port || is_decnet ) {
128   fh = roar_socket_connect(server, port);
129   // restore the original string
130   server[i] = ':';
131  } else {
132   fh = roar_socket_connect(server, ROAR_DEFAULT_PORT);
133  }
134 }
135
136 if ( fh == -1 )
137  roar_errno = ROAR_ERROR_CONNREFUSED;
138
139 ROAR_DBG("roar_connect_raw(*) = %i", fh);
140
141 return fh;
142}
143
144int roar_connect    (struct roar_connection * con, char * server) {
145 roar_errno = ROAR_ERROR_UNKNOWN;
146 con->fh = roar_connect_raw(server);
147
148 if ( con->fh == -1 )
149  return -1;
150
151 roar_errno = ROAR_ERROR_NONE;
152
153 return 0;
154}
155
156int roar_disconnect (struct roar_connection * con) {
157 struct roar_message m;
158
159 m.datalen = 0;
160 m.stream  = 0;
161 m.pos     = 0;
162 m.cmd     = ROAR_CMD_QUIT;
163
164 roar_req(con, &m, NULL);
165
166 close(con->fh);
167
168 con->fh = -1;
169
170 roar_errno = ROAR_ERROR_NONE;
171
172 return 0;
173}
174
175int roar_identify   (struct roar_connection * con, char * name) {
176 struct roar_message mes;
177 pid_t pid;
178 int max_len;
179
180 roar_errno = ROAR_ERROR_UNKNOWN;
181
182 ROAR_DBG("roar_identify(*): try to identify myself...");
183
184 mes.cmd    = ROAR_CMD_IDENTIFY;
185 mes.stream = 0;
186 mes.pos    = 0;
187
188 ROAR_DBG("roar_identify(*): name=%p", name);
189
190 if ( name == NULL )
191  name = "libroar client";
192
193 ROAR_DBG("roar_identify(*): name=%p", name);
194
195 max_len = strlen(name);
196 ROAR_DBG("roar_identify(*): strlen(name) = %i", max_len);
197
198 if ( max_len > (LIBROAR_BUFFER_MSGDATA - 5) )
199  max_len = LIBROAR_BUFFER_MSGDATA - 5;
200
201 mes.datalen = 5 + max_len;
202 mes.data[0] = 1;
203
204 pid = getpid();
205 *(uint32_t*)(mes.data+1) = ROAR_HOST2NET32(pid);
206 ROAR_DBG("roar_identify(*): pid = %i", pid);
207
208 strncpy(mes.data+5, name, max_len);
209
210 return roar_req(con, &mes, NULL);
211}
212
213#define _ROAR_MESS_BUF_LEN (1 /* version */ + 1 /* cmd */ + 2 /* stream */ + 4 /* pos */ + 2 /* datalen */)
214int roar_send_message (struct roar_connection * con, struct roar_message * mes, char * data) {
215 char buf[_ROAR_MESS_BUF_LEN];
216
217 roar_errno = ROAR_ERROR_UNKNOWN;
218
219 ROAR_DBG("roar_send_message(*): try to send an request...");
220
221 buf[0] = _ROAR_MESSAGE_VERSION;
222 buf[1] = (unsigned char) mes->cmd;
223 *(uint16_t*)(buf+2) = ROAR_HOST2NET16(mes->stream);
224 *(uint32_t*)(buf+4) = ROAR_HOST2NET32(mes->pos);
225 *(uint16_t*)(buf+8) = ROAR_HOST2NET16(mes->datalen);
226
227 if ( write(con->fh, buf, _ROAR_MESS_BUF_LEN) != _ROAR_MESS_BUF_LEN ) {
228  roar_errno = ROAR_ERROR_PIPE;
229  return -1;
230 }
231
232 if ( mes->datalen != 0 ) {
233  if ( write(con->fh, data == NULL ? mes->data : data, mes->datalen) != mes->datalen ) {
234   roar_errno = ROAR_ERROR_PIPE;
235   return -1;
236  }
237 }
238
239 roar_errno = ROAR_ERROR_NONE;
240
241 ROAR_DBG("roar_send_message(*) = 0");
242 return 0;
243}
244
245int roar_recv_message (struct roar_connection * con, struct roar_message * mes, char ** data) {
246 char buf[_ROAR_MESS_BUF_LEN];
247
248 roar_errno = ROAR_ERROR_UNKNOWN;
249
250 ROAR_DBG("roar_recv_message(*): try to get a response form the server...");
251
252 if ( data )
253  *data = NULL;
254
255 if ( read(con->fh, buf, _ROAR_MESS_BUF_LEN) != _ROAR_MESS_BUF_LEN ) {
256  roar_errno = ROAR_ERROR_PROTO;
257  return -1;
258 }
259
260 ROAR_DBG("roar_recv_message(*): Got a header");
261
262 if ( buf[0] != _ROAR_MESSAGE_VERSION ) {
263  roar_errno = ROAR_ERROR_PROTO;
264  return -1;
265 }
266
267 mes->cmd     = (unsigned char)buf[1];
268 mes->stream  = ROAR_NET2HOST16(*(uint16_t*)(buf+2));
269 mes->pos     = ROAR_NET2HOST32(*(uint32_t*)(buf+4));
270 mes->datalen = ROAR_NET2HOST16(*(uint16_t*)(buf+8));
271
272 ROAR_DBG("roar_recv_message(*): command=%i(%s)", mes->cmd,
273           mes->cmd == ROAR_CMD_OK ? "OK" : (mes->cmd == ROAR_CMD_ERROR ? "ERROR" : "UNKNOWN"));
274
275 if ( mes->datalen == 0 ) {
276  ROAR_DBG("roar_recv_message(*): no data in this pkg");
277  ROAR_DBG("roar_recv_message(*) = 0");
278  roar_errno = ROAR_ERROR_NONE;
279  return 0;
280 }
281
282 if ( mes->datalen <= LIBROAR_BUFFER_MSGDATA ) {
283  if ( read(con->fh, mes->data, mes->datalen) == mes->datalen ) {
284   ROAR_DBG("roar_recv_message(*): Got data!");
285   ROAR_DBG("roar_recv_message(*) = 0");
286   roar_errno = ROAR_ERROR_NONE;
287   return 0;
288  }
289
290  roar_errno = ROAR_ERROR_PIPE;
291  return -1;
292 } else {
293  if ( data == NULL ) {
294   roar_errno = ROAR_ERROR_MSGSIZE;
295   return -1;
296  }
297
298  if ( (*data = malloc(mes->datalen)) == NULL ) {
299   roar_errno = ROAR_ERROR_NOMEM;
300   return -1;
301  }
302
303  if ( mes->datalen == 0 ) {
304   roar_errno = ROAR_ERROR_NONE;
305   return 0;
306  }
307
308  if ( read(con->fh, *data, mes->datalen) == mes->datalen ) {
309   ROAR_DBG("roar_recv_message(*): Got data!");
310   ROAR_DBG("roar_recv_message(*) = 0");
311   roar_errno = ROAR_ERROR_NONE;
312   return 0;
313  }
314
315  roar_errno = ROAR_ERROR_PIPE;
316  return -1;
317 }
318
319 // what happened here?
320 return -1;
321}
322
323int roar_req (struct roar_connection * con, struct roar_message * mes, char ** data) {
324 if ( roar_send_message(con, mes, data ? *data : NULL) != 0 )
325  return -1;
326
327 if ( data )
328  free(*data);
329
330 return roar_recv_message(con, mes, data);
331}
332
333int roar_debug_message_print (struct roar_message * mes) {
334 if ( mes == NULL )
335  return -1;
336
337 ROAR_DBG("roar_debug_message_print(*): Command: %i", mes->cmd);
338 ROAR_DBG("roar_debug_message_print(*): Stream : %u", mes->stream);
339 ROAR_DBG("roar_debug_message_print(*): Pos    : %u", mes->pos);
340 ROAR_DBG("roar_debug_message_print(*): Datalen: %i", mes->datalen);
341
342 ROAR_DBG("roar_debug_message_print(*) = 0");
343 return 0;
344}
345
346int roar_debug_audio_info_print (struct roar_audio_info * info) {
347 if ( info == NULL )
348  return -1;
349
350 ROAR_DBG("roar_debug_audio_info_print(*): Rate    : %i", info->rate);
351 ROAR_DBG("roar_debug_audio_info_print(*): Channels: %i", info->channels);
352 ROAR_DBG("roar_debug_audio_info_print(*): Bits    : %i", info->bits);
353 ROAR_DBG("roar_debug_audio_info_print(*): Codec   : %i", info->codec);
354
355 ROAR_DBG("roar_debug_audio_info_print(*) = 0");
356 return 0;
357}
358
359//ll
Note: See TracBrowser for help on using the repository browser.