source: roaraudio/libroar/basic.c @ 1066:7c530eda2e41

Last change on this file since 1066:7c530eda2e41 was 1066:7c530eda2e41, checked in by phi, 15 years ago

make OpenBSD security warnings patch a bit happyer...

File size: 9.1 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     strncat(user_sock, roar_socket_get_local_nodename(), 6);
118   }
119
120   strncat(user_sock, server, 79);
121   server = user_sock;
122   if ( *obj == 0 ) {
123#ifdef DN_MAXOBJL
124    strncat(user_sock, ROAR_DEFAULT_OBJECT, DN_MAXOBJL+2);
125#else
126    ROAR_ERR("roar_connect_raw(*): size of DECnet object unknown.");
127#endif
128   }
129  }
130
131  if ( port || is_decnet ) {
132   fh = roar_socket_connect(server, port);
133   // restore the original string
134   server[i] = ':';
135  } else {
136   fh = roar_socket_connect(server, ROAR_DEFAULT_PORT);
137  }
138 }
139
140 if ( fh == -1 )
141  roar_errno = ROAR_ERROR_CONNREFUSED;
142
143 ROAR_DBG("roar_connect_raw(*) = %i", fh);
144
145 return fh;
146}
147
148int roar_connect    (struct roar_connection * con, char * server) {
149 roar_errno = ROAR_ERROR_UNKNOWN;
150 con->fh = roar_connect_raw(server);
151
152 if ( con->fh == -1 )
153  return -1;
154
155 roar_errno = ROAR_ERROR_NONE;
156
157 return 0;
158}
159
160int roar_disconnect (struct roar_connection * con) {
161 struct roar_message m;
162
163 m.datalen = 0;
164 m.stream  = 0;
165 m.pos     = 0;
166 m.cmd     = ROAR_CMD_QUIT;
167
168 roar_req(con, &m, NULL);
169
170 close(con->fh);
171
172 con->fh = -1;
173
174 roar_errno = ROAR_ERROR_NONE;
175
176 return 0;
177}
178
179int roar_identify   (struct roar_connection * con, char * name) {
180 struct roar_message mes;
181 pid_t pid;
182 int max_len;
183
184 roar_errno = ROAR_ERROR_UNKNOWN;
185
186 ROAR_DBG("roar_identify(*): try to identify myself...");
187
188 mes.cmd    = ROAR_CMD_IDENTIFY;
189 mes.stream = 0;
190 mes.pos    = 0;
191
192 ROAR_DBG("roar_identify(*): name=%p", name);
193
194 if ( name == NULL )
195  name = "libroar client";
196
197 ROAR_DBG("roar_identify(*): name=%p", name);
198
199 max_len = strlen(name);
200 ROAR_DBG("roar_identify(*): strlen(name) = %i", max_len);
201
202 if ( max_len > (LIBROAR_BUFFER_MSGDATA - 5) )
203  max_len = LIBROAR_BUFFER_MSGDATA - 5;
204
205 mes.datalen = 5 + max_len;
206 mes.data[0] = 1;
207
208 pid = getpid();
209 *(uint32_t*)(mes.data+1) = ROAR_HOST2NET32(pid);
210 ROAR_DBG("roar_identify(*): pid = %i", pid);
211
212 strncpy(mes.data+5, name, max_len);
213
214 return roar_req(con, &mes, NULL);
215}
216
217#define _ROAR_MESS_BUF_LEN (1 /* version */ + 1 /* cmd */ + 2 /* stream */ + 4 /* pos */ + 2 /* datalen */)
218int roar_send_message (struct roar_connection * con, struct roar_message * mes, char * data) {
219 char buf[_ROAR_MESS_BUF_LEN];
220
221 roar_errno = ROAR_ERROR_UNKNOWN;
222
223 ROAR_DBG("roar_send_message(*): try to send an request...");
224
225 buf[0] = _ROAR_MESSAGE_VERSION;
226 buf[1] = (unsigned char) mes->cmd;
227 *(uint16_t*)(buf+2) = ROAR_HOST2NET16(mes->stream);
228 *(uint32_t*)(buf+4) = ROAR_HOST2NET32(mes->pos);
229 *(uint16_t*)(buf+8) = ROAR_HOST2NET16(mes->datalen);
230
231 if ( write(con->fh, buf, _ROAR_MESS_BUF_LEN) != _ROAR_MESS_BUF_LEN ) {
232  roar_errno = ROAR_ERROR_PIPE;
233  return -1;
234 }
235
236 if ( mes->datalen != 0 ) {
237  if ( write(con->fh, data == NULL ? mes->data : data, mes->datalen) != mes->datalen ) {
238   roar_errno = ROAR_ERROR_PIPE;
239   return -1;
240  }
241 }
242
243 roar_errno = ROAR_ERROR_NONE;
244
245 ROAR_DBG("roar_send_message(*) = 0");
246 return 0;
247}
248
249int roar_recv_message (struct roar_connection * con, struct roar_message * mes, char ** data) {
250 char buf[_ROAR_MESS_BUF_LEN];
251
252 roar_errno = ROAR_ERROR_UNKNOWN;
253
254 ROAR_DBG("roar_recv_message(*): try to get a response form the server...");
255
256 if ( data )
257  *data = NULL;
258
259 if ( read(con->fh, buf, _ROAR_MESS_BUF_LEN) != _ROAR_MESS_BUF_LEN ) {
260  roar_errno = ROAR_ERROR_PROTO;
261  return -1;
262 }
263
264 ROAR_DBG("roar_recv_message(*): Got a header");
265
266 if ( buf[0] != _ROAR_MESSAGE_VERSION ) {
267  roar_errno = ROAR_ERROR_PROTO;
268  return -1;
269 }
270
271 mes->cmd     = (unsigned char)buf[1];
272 mes->stream  = ROAR_NET2HOST16(*(uint16_t*)(buf+2));
273 mes->pos     = ROAR_NET2HOST32(*(uint32_t*)(buf+4));
274 mes->datalen = ROAR_NET2HOST16(*(uint16_t*)(buf+8));
275
276 ROAR_DBG("roar_recv_message(*): command=%i(%s)", mes->cmd,
277           mes->cmd == ROAR_CMD_OK ? "OK" : (mes->cmd == ROAR_CMD_ERROR ? "ERROR" : "UNKNOWN"));
278
279 if ( mes->datalen == 0 ) {
280  ROAR_DBG("roar_recv_message(*): no data in this pkg");
281  ROAR_DBG("roar_recv_message(*) = 0");
282  roar_errno = ROAR_ERROR_NONE;
283  return 0;
284 }
285
286 if ( mes->datalen <= LIBROAR_BUFFER_MSGDATA ) {
287  if ( read(con->fh, mes->data, mes->datalen) == mes->datalen ) {
288   ROAR_DBG("roar_recv_message(*): Got data!");
289   ROAR_DBG("roar_recv_message(*) = 0");
290   roar_errno = ROAR_ERROR_NONE;
291   return 0;
292  }
293
294  roar_errno = ROAR_ERROR_PIPE;
295  return -1;
296 } else {
297  if ( data == NULL ) {
298   roar_errno = ROAR_ERROR_MSGSIZE;
299   return -1;
300  }
301
302  if ( (*data = malloc(mes->datalen)) == NULL ) {
303   roar_errno = ROAR_ERROR_NOMEM;
304   return -1;
305  }
306
307  if ( mes->datalen == 0 ) {
308   roar_errno = ROAR_ERROR_NONE;
309   return 0;
310  }
311
312  if ( read(con->fh, *data, mes->datalen) == mes->datalen ) {
313   ROAR_DBG("roar_recv_message(*): Got data!");
314   ROAR_DBG("roar_recv_message(*) = 0");
315   roar_errno = ROAR_ERROR_NONE;
316   return 0;
317  }
318
319  roar_errno = ROAR_ERROR_PIPE;
320  return -1;
321 }
322
323 // what happened here?
324 return -1;
325}
326
327int roar_req (struct roar_connection * con, struct roar_message * mes, char ** data) {
328 if ( roar_send_message(con, mes, data ? *data : NULL) != 0 )
329  return -1;
330
331 if ( data )
332  free(*data);
333
334 return roar_recv_message(con, mes, data);
335}
336
337int roar_debug_message_print (struct roar_message * mes) {
338 if ( mes == NULL )
339  return -1;
340
341 ROAR_DBG("roar_debug_message_print(*): Command: %i", mes->cmd);
342 ROAR_DBG("roar_debug_message_print(*): Stream : %u", mes->stream);
343 ROAR_DBG("roar_debug_message_print(*): Pos    : %u", mes->pos);
344 ROAR_DBG("roar_debug_message_print(*): Datalen: %i", mes->datalen);
345
346 ROAR_DBG("roar_debug_message_print(*) = 0");
347 return 0;
348}
349
350int roar_debug_audio_info_print (struct roar_audio_info * info) {
351 if ( info == NULL )
352  return -1;
353
354 ROAR_DBG("roar_debug_audio_info_print(*): Rate    : %i", info->rate);
355 ROAR_DBG("roar_debug_audio_info_print(*): Channels: %i", info->channels);
356 ROAR_DBG("roar_debug_audio_info_print(*): Bits    : %i", info->bits);
357 ROAR_DBG("roar_debug_audio_info_print(*): Codec   : %i", info->codec);
358
359 ROAR_DBG("roar_debug_audio_info_print(*) = 0");
360 return 0;
361}
362
363//ll
Note: See TracBrowser for help on using the repository browser.