source: roaraudio/libroar/basic.c @ 5846:21c98581c23b

Last change on this file since 5846:21c98581c23b was 5846:21c98581c23b, checked in by phi, 11 years ago

avoid possible problems with roar_env_get_home() outsite init phase. should also speed up roar_libroar_get_config_ptr() slightly

File size: 22.4 KB
RevLine 
[0]1//basic.c:
2
[690]3/*
[5823]4 *      Copyright (C) Philipp 'ph3-der-loewe' Schafft - 2008-2013
[690]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
[3517]21 *  the Free Software Foundation, 51 Franklin Street, Fifth Floor,
22 *  Boston, MA 02110-1301, USA.
[690]23 *
24 *  NOTE for everyone want's to change something and send patches:
25 *  read README and HACKING! There a addition information on
26 *  the license of this document you need to read before you send
27 *  any patches.
28 *
29 *  NOTE for uses of non-GPL (LGPL,...) software using libesd, libartsc
30 *  or libpulse*:
31 *  The libs libroaresd, libroararts and libroarpulse link this lib
32 *  and are therefore GPL. Because of this it may be illigal to use
33 *  them with any software that uses libesd, libartsc or libpulse*.
34 */
35
[0]36#include "libroar.h"
37
[5843]38enum mode {
39 NORMAL = 0,
40 SYSTEM = 1
41};
42
43static int _connect_server(struct roar_connection * con, const char * server, int type, int flags, uint_least32_t timeout);
44
45int __get_daemonimage(const char ** daemonimage, enum mode * mode, const char * server) {
46 *daemonimage = NULL;
47 *mode = NORMAL;
48
49 if ( !!strncmp(server, "+fork", 5) ) {
50  roar_err_set(ROAR_ERROR_INVAL);
51  return -1;
52 }
53
54 server += 5;
55
56 if ( server[0] == '=' ) {
57  server++;
58
59  if ( server[0] == 0 ) {
60   // no special case, we just ignore it.
61  } else if ( server[0] == 'd' && server[1] == ':' ) {
62   server += 2;
63   *daemonimage = server;
64   *mode = NORMAL;
65  } else if ( server[0] == '!' ) {
66   server += 1;
67   *daemonimage = server;
68   *mode = SYSTEM;
69  } else {
70   roar_err_set(ROAR_ERROR_ILLSEQ);
71   return -1;
72  }
73 }
74
75 if ( *daemonimage == NULL )
76  *daemonimage = roar_libroar_get_config()->daemonimage;
77
78 // we keep this step to be compatible with older versions.
79 if ( *daemonimage == NULL || **daemonimage == 0 ) {
80  *daemonimage = roar_env_get("ROAR_DAEMONIMAGE");
81  if ( *daemonimage != NULL ) {
82   ROAR_WARN("__get_daemonimage(*): Usage of $ROAR_DAEMONIMAGE is obsolete. Use ROAR_OPTIONS=daemonimage:...");
83  }
84 }
85
86 if ( *daemonimage == NULL || **daemonimage == 0 )
87  *daemonimage = roar_libroar_get_path_static("bin-default-daemonimage");
88
89 return 0;
90}
91
92#if defined(ROAR_TARGET_WIN32)
93#define NUM_TRIES 16
94static int _start_server_win32(struct roar_connection * con, const char * server, int type, int flags, uint_least32_t timeout) {
95 enum mode mode = NORMAL;
96 const char * daemonimage = NULL;
97 char buf[64];
98 int port;
99 size_t i;
100 int fh;
101 int ret;
102
103 if ( __get_daemonimage(&daemonimage, &mode, server) == -1 )
104  return -1;
105
106 if ( mode != NORMAL ) {
107  roar_err_set(ROAR_ERROR_NOSYS);
108  return -1;
109 }
110
111 for (i = 0; i < NUM_TRIES; i++) {
112  port = roar_random_uint16();
113  if ( port < 1 )
114   continue;
115
116  fh = roar_socket_connect(ROAR_SOCKET_TYPE_TCP, "localhost", port);
117  if ( fh == -1 )
118   break;
119
120  closesocket(fh);
121 }
122
123 if ( i == NUM_TRIES ) {
124  roar_err_set(ROAR_ERROR_LOOP);
125  return -1;
126 }
127
128 // port is the port to use. It seems to be 'free'.
129
130#if defined(_P_DETACH)
131#define MODE _P_DETACH
132#elif defined(_P_NOWAIT)
133#define MODE _P_NOWAIT
134#else
135#define MODE _P_NOWAITO
136#endif
137
138 snprintf(buf, sizeof(buf), "%i", port);
[5844]139 roar_err_clear_all();
140 if ( _spawnlp(MODE, daemonimage, daemonimage, "--tcp", "--bind", "localhost", "--port", buf, (const char*)NULL) < 0 ) {
141  roar_err_update();
[5846]142  ret = roar_error;
[5844]143  ROAR_ERR("_start_server_win32(server='%s', ...): Can not start server: %s: %s", server, daemonimage, roar_errorstring);
[5846]144  roar_error = ret;
145  ROAR_ERR("_start_server_win32(*): %s", roar_errorstring);
146  roar_error = ret;
147  ROAR_ERR("DUMMY");
148  ROAR_ERR("_start_server_win32(*): %s", roar_errorstring);
149  roar_error = ret;
150  (void)roar_errorstring;
151  ROAR_ERR("_start_server_win32(*): %s", roar_errorstring);
[5844]152  return -1;
153 }
[5843]154
155 snprintf(buf, sizeof(buf), "localhost:%i", port);
156
157 // give the daemon some time to come up:
158 roar_usleep(25000);
159
160 ret = -1;
161 for (i = 0; ret == -1 && i < NUM_TRIES; i++) {
162  ret = _connect_server(con, buf, type, flags, timeout);
163  if ( ret == -1 && i < NUM_TRIES )
164   roar_sleep(1);
165 }
166
[5846]167 ROAR_ERR("_start_server_win32(*): %s", roar_errorstring);
168
[5843]169 if ( ret == -1 )
170  return -1;
171
172 con->flags |= ROAR_CON_FLAGS_TERMINATE;
173
174 return 0;
175}
176#elif !defined(ROAR_TARGET_MICROCONTROLLER)
177static int _start_server_posix(struct roar_connection * con, const char * server, int type, int flags, uint_least32_t timeout) {
178 enum mode mode = NORMAL;
[5369]179 const char * daemonimage = NULL;
180 int socks[2];
181 int r;
182 char fhstr[12];
[5838]183 size_t len;
[5369]184
[5843]185 if ( __get_daemonimage(&daemonimage, &mode, server) == -1 )
186  return -1;
[5369]187
[5838]188 len = roar_mm_strlen(daemonimage) + 9; // 9 = '+fork=' + 'X:' + '\0'
189 con->server_name = roar_mm_malloc(len);
190 if ( con->server_name != NULL ) {
191  snprintf(con->server_name, len, "+fork=%s%s", mode == NORMAL ? "d:" : "!", daemonimage);
192 }
193
[5369]194 if ( socketpair(AF_UNIX, SOCK_STREAM, 0, socks) == -1 ) {
195  roar_err_from_errno();
196  return -1;
197 }
198
[5373]199 r = roar_fork(NULL);
[5369]200
201 if ( r == -1 ) { // error!
[5373]202  ROAR_ERR("_start_server(*): Can not fork: %s", roar_error2str(roar_error));
[5369]203  close(socks[0]);
204  close(socks[1]);
205  return -1;
206 } else if ( r == 0 ) { // we are the child
[5619]207  roar_watchdog_stop();
208
[5369]209  close(socks[0]);
210
211  close(ROAR_STDIN ); // we do not want roard to have any standard input
212  close(ROAR_STDOUT); // STDOUT is also not needed, so we close it,
213                      // but STDERR we keep open for error messages.
214
215  snprintf(fhstr, sizeof(fhstr), "%i", socks[1]);
216
217  switch (mode) {
218   case NORMAL:
219     execlp(daemonimage, daemonimage, "--no-listen", "--client-fh", fhstr, (_LIBROAR_GOOD_CAST char*)NULL);
220    break;
221   case SYSTEM:
222     dup2(socks[1], ROAR_STDIN );
223     dup2(socks[1], ROAR_STDOUT);
[5832]224     execl(roar_libroar_get_path_static("bin-sh"), roar_libroar_get_path_static("bin-sh"), "-c", daemonimage, (_LIBROAR_GOOD_CAST char*)NULL);
[5369]225     execlp("sh", "sh", "-c", daemonimage, (_LIBROAR_GOOD_CAST char*)NULL);
226    break;
227  }
228
229  // we are still alive?
[5373]230  ROAR_ERR("_start_server(*): alive after exec(), that's bad!");
[5619]231  ROAR_U_EXIT(1);
[5369]232 } else { // we are the parent
233  close(socks[1]);
234  if ( roar_vio_open_fh_socket(con->viocon, socks[0]) == -1 ) {
235   close(socks[0]);
236   return -1;
237  } else {
238   con->flags |= ROAR_CON_FLAGS_VIO;
239  }
240  return 0;
241 }
242
243 return -1;
[5843]244}
245#endif
246
247static int _start_server(struct roar_connection * con, const char * server, int type, int flags, uint_least32_t timeout) {
248#if defined(ROAR_TARGET_WIN32)
[5846]249 int ret;
250 ret = _start_server_win32(con, server, type, flags, timeout);
251 ROAR_ERR("_start_server(*): %s", roar_errorstring);
252 return ret;
[5843]253#elif !defined(ROAR_TARGET_MICROCONTROLLER)
254 return _start_server_posix(con, server, type, flags, timeout);
[5369]255#else
[5843]256 ROAR_ERR("_start_server(*): There is no UNIX Domain Socket, download a real OS.");
257 roar_err_set(ROAR_ERROR_NOSYS);
[5369]258 return -1;
259#endif
260}
261
[5373]262static int _connect_internal(struct roar_connection * con, const char * server, int type, int flags, uint_least32_t timeout) {
263 struct roar_libroar_config * config = roar_libroar_get_config();
264 struct roar_vio_calls * vio;
265
266 if ( config->connect_internal != NULL ) {
267  vio = config->connect_internal(con, server, type, flags, timeout);
268  if ( vio == NULL )
269   return -1;
270
271  con->viocon = vio;
272  con->flags |= ROAR_CON_FLAGS_VIO;
273
274  return 0;
275 }
276
277 roar_err_set(ROAR_ERROR_BADHOST);
278 return -1;
279}
280
[5368]281static int _connect_server(struct roar_connection * con, const char * server, int type, int flags, uint_least32_t timeout) {
282#if defined(ROAR_HAVE_STAT) && defined(ROAR_HAVE_H_SYS_STAT)
283 struct stat sockstat;
284#endif
285 const char * obj = NULL;
286 char user_sock[128];
287 int is_decnet = 0;
288 int port = 0;
289 int i = 0;
290 int fh = -1;
291 int err;
[5838]292 int ret;
[5368]293
294 if ( con == NULL || server == NULL ) {
295  roar_err_set(ROAR_ERROR_FAULT);
296  return -1;
297 }
298
299 if ( !strcmp(server, "+invalid") ) {
300  roar_err_set(ROAR_ERROR_CANCELED);
301  return -1;
302 } else if ( !strncmp(server, "+dstr=", 6) ) {
303  if ( roar_vio_open_dstr_simple(con->viocon, server+6, ROAR_VIOF_READWRITE) == -1 )
304   return -1;
305  con->flags |= ROAR_CON_FLAGS_VIO;
[5838]306  con->server_name = roar_mm_strdup(server);
[5368]307  return 0;
[5369]308 } else if ( !strcmp(server, "+fork") || !strncmp(server, "+fork=", 6) ) {
[5846]309  ret = _start_server(con, server, type, flags, timeout);
310  ROAR_ERR("_connect_server(*): %s", roar_errorstring);
311  return ret;
[5373]312 } else if ( !strcmp(server, "+internal") || !strncmp(server, "+internal=", 10) ) {
[5838]313  ret = _connect_internal(con, server, type, flags, timeout);
314  if ( ret == 0 )
315   con->server_name = roar_mm_strdup(server);
316  return ret;
[5368]317 }
318
319 strncpy(user_sock, server, sizeof(user_sock)-1);
320 user_sock[sizeof(user_sock)-1] = 0;
321
322
323 if ( *user_sock != '/' ) { // don't test AF_UNIX sockets for ports
324  for (i = 0; user_sock[i] != 0; i++) {
325   if ( user_sock[i] == ':' ) {
326    if ( user_sock[i+1] == ':' ) { // DECnet, leave unchanged
327     is_decnet = 1;
328     obj = &user_sock[i+2];
329     break;
330    }
331
332    port = atoi(&(user_sock[i+1]));
333    user_sock[i] = 0;
334    break;
335   }
336  }
337 }
338
339 if ( is_decnet ) {
340  if ( *user_sock == ':' ) {
341   if ( roar_socket_get_local_nodename() != NULL ) {
342    strncpy(user_sock, roar_socket_get_local_nodename(), sizeof(user_sock)-1);
343    user_sock[sizeof(user_sock)-1] = 0;
344    roar_mm_strlcat(user_sock, server, sizeof(user_sock)-1);
345    user_sock[sizeof(user_sock)-1] = 0;
346    obj  = strstr(user_sock, "::");
347    obj += 2;
348   }
349  }
350
351  if ( *obj == 0 ) {
352   roar_mm_strlcat(user_sock, ROAR_DEFAULT_OBJECT, sizeof(user_sock)-1);
353   user_sock[sizeof(user_sock)-1] = 0;
354  }
[5838]355
356  ROAR_DBG("roar_connect_raw(*): user_sock='%s'", user_sock);
[5368]357 }
358
359 if ( port || is_decnet ) {
[5375]360  fh = roar_socket_connect(type, user_sock, port);
[5368]361  // restore the original string
362  user_sock[i] = ':';
363 } else {
364#if defined(ROAR_HAVE_STAT) && defined(ROAR_HAVE_H_SYS_STAT)
365  if ( user_sock[0] == '/' ) {
366   if ( stat(user_sock, &sockstat) == 0 ) {
367    if ( S_ISCHR(sockstat.st_mode) ) {
[5406]368#ifdef O_NOCTTY
[5428]369     fh = open(user_sock, O_RDWR|O_NOCTTY, 0666);
[5406]370#else
[5428]371     fh = open(user_sock, O_RDWR, 0666);
[5406]372#endif
[5368]373    }
374   }
375  }
376#endif
[5428]377  if ( fh == -1 )
378   fh = roar_socket_connect(type, user_sock, ROAR_DEFAULT_PORT);
[5368]379 }
380
381 if ( fh == -1 )
382  return -1;
383
384 if ( roar_vio_open_fh_socket(con->viocon, fh) == -1 ) {
385  err = roar_error;
386#ifdef ROAR_TARGET_WIN32
387  closesocket(fh);
388#else
389  close(fh);
390#endif
391  roar_error = err;
392  return -1;
393 } else {
394  con->flags |= ROAR_CON_FLAGS_VIO;
395 }
396
[5838]397 con->server_name = roar_mm_strdup(server);
398
[5368]399 roar_err_set(ROAR_ERROR_NONE);
400 return 0;
401}
402
403static int roar_connect_raw (struct roar_connection * con, const char * server, int flags, uint_least32_t timeout) {
[4780]404#ifdef ROAR_HAVE_LIBSLP
[4653]405 struct roar_libroar_config * config = roar_libroar_get_config();
[4780]406#endif
[5745]407#if defined(ROAR_HAVE_UNIX)
[5114]408 char user_sock[128];
[5754]409 const char * roar_server;
[5393]410#endif
411#if defined(ROAR_HAVE_LIBSLP) || !defined(ROAR_TARGET_MICROCONTROLLER)
[701]412 int i = 0;
[5393]413#endif
[1475]414#if !defined(ROAR_TARGET_WIN32) && !defined(ROAR_TARGET_MICROCONTROLLER)
[1026]415 struct passwd * pwd;
[1393]416#endif
[828]417#ifdef ROAR_HAVE_LIBDNET
418 struct stat decnet_stat;
419#endif
[3372]420#ifdef ROAR_HAVE_LIBX11
421 struct roar_x11_connection * x11con;
422#endif
[4945]423#ifdef ROAR_HAVE_LIBSLP
[4806]424 struct roar_server * list;
425 int workarounds_store;
[4945]426#endif
[0]427
[4873]428 roar_err_set(ROAR_ERROR_UNKNOWN);
[807]429
[4806]430 if ( timeout != 0 ) {
[4873]431  roar_err_set(ROAR_ERROR_INVAL);
[4806]432  return -1;
433 }
434
435 if ( flags & ROAR_ENUM_FLAG_HARDNONBLOCK )
436  flags |= ROAR_ENUM_FLAG_NONBLOCK;
437
438
[5368]439 if ( server == NULL || *server == 0 )
[2567]440  server = roar_libroar_get_server();
441
[5368]442 if ( server == NULL || *server == 0 )
[5754]443  server = roar_env_get("ROAR_SERVER");
[0]444
[3372]445#ifdef ROAR_HAVE_LIBX11
[5368]446 if ( server == NULL || *server == 0 ) {
[3372]447  if ( (x11con = roar_x11_connect(NULL)) != NULL ) {
448   server = roar_x11_get_prop(x11con, "ROAR_SERVER");
449   roar_x11_disconnect(x11con);
450  }
451 }
452#endif
453
[1436]454#if !defined(ROAR_TARGET_WIN32) && !defined(ROAR_TARGET_MICROCONTROLLER)
[5832]455 if ( (server == NULL || *server == 0) && (i = readlink(roar_libroar_get_path_static("sysconf-roarserver"), user_sock, sizeof(user_sock)-1)) != -1 ) {
[448]456   user_sock[i] = 0;
457   server = user_sock;
458 }
[1093]459#endif
[448]460
[3077]461 if ( server != NULL && !strcasecmp(server, "+slp") ) {
[3076]462  server = roar_slp_find_roard(0);
463  if ( server == NULL ) {
464   return -1;
465  }
466 }
467
[5471]468 // "+default" is an alias for NULL.
469 if ( server != NULL && !strcasecmp(server, "+default") ) {
470  server = NULL;
471 }
472
[61]473 if ( server == NULL || *server == 0 ) {
[0]474  /* connect via defaults */
475
[1764]476#ifdef ROAR_HAVE_UNIX
[1436]477#ifndef ROAR_TARGET_MICROCONTROLLER
[5754]478  roar_server = roar_env_get("HOME");
[1435]479#else
480  roar_server = NULL;
481#endif
[1026]482
483  if ( roar_server == NULL ) {
[1436]484#if !defined(ROAR_TARGET_WIN32) && !defined(ROAR_TARGET_MICROCONTROLLER)
[1026]485   if ( (pwd = getpwuid(getuid())) == NULL ) {
[5832]486    roar_server = roar_libroar_get_path_static("dir-nx-home");
[1026]487   } else {
488    roar_server = pwd->pw_dir;
489   }
[1078]490#else
491   roar_server = "/WIN32-SUCKS";
492#endif
[1026]493  }
494
[5114]495  snprintf(user_sock, sizeof(user_sock)-1, "%s/%s", roar_server, ROAR_DEFAULT_SOCK_USER);
496  user_sock[sizeof(user_sock)-1] = 0;
[0]497
[5368]498  if ( _connect_server(con, user_sock, ROAR_SOCKET_TYPE_UNIX, flags, timeout) == 0 )
499   return 0;
[0]500
[5368]501  if ( _connect_server(con, ROAR_DEFAULT_SOCK_GLOBAL, ROAR_SOCKET_TYPE_UNIX, flags, timeout) == 0 )
502   return 0;
[1764]503#endif
[237]504
[5368]505  if ( _connect_server(con, ROAR_DEFAULT_HOSTPORT, ROAR_SOCKET_TYPE_TCP, flags, timeout) == 0 )
506   return 0;
[0]507
[828]508#ifdef ROAR_HAVE_LIBDNET
509  if ( stat(ROAR_PROC_NET_DECNET, &decnet_stat) == 0 ) {
510   if ( roar_socket_get_local_nodename() ) {
511    snprintf(user_sock, 79, "%s::%s", roar_socket_get_local_nodename(), ROAR_DEFAULT_OBJECT);
[5368]512    if ( _connect_server(con, user_sock, ROAR_SOCKET_TYPE_DECNET, flags, timeout) == 0 )
513     return 0;
[828]514   }
[522]515  }
[828]516#endif
[2007]517
[5375]518  if ( _connect_server(con, "+abstract", ROAR_SOCKET_TYPE_UNKNOWN, flags, timeout) == 0 )
[5368]519   return 0;
[4109]520
[2007]521#ifdef ROAR_HAVE_LIBSLP
[4806]522 if ( !(config->workaround.workarounds & ROAR_LIBROAR_CONFIG_WAS_NO_SLP) &&
[5373]523      !(flags & ROAR_ENUM_FLAG_NONBLOCK) &&
524      !(flags & ROAR_ENUM_FLAG_LOCALONLY)
[4806]525    ) {
526  if ( (server = roar_slp_find_roard(0)) != NULL ) {
[5375]527   if ( _connect_server(con, server, ROAR_SOCKET_TYPE_UNKNOWN, 0, 0) == 0 )
[5368]528    return 0;
[2014]529
[4806]530   /* in case we can not connect to the server given this may be a cache problem,
531      we do a new lookup with the cache disabled in this case                     */
[5237]532   ROAR_WARN("roar_connect_raw(*): Can not connect to SLP located server, disabling cache");
[4806]533   if ( (server = roar_slp_find_roard(1)) != NULL )
[5375]534    if ( _connect_server(con, server, ROAR_SOCKET_TYPE_UNKNOWN, 0, 0) == 0 )
[5368]535     return 0;
[4806]536  }
537 }
538
539 workarounds_store = config->workaround.workarounds;
540 config->workaround.workarounds |= ROAR_LIBROAR_CONFIG_WAS_NO_SLP;
541 list = roar_enum_servers(flags, -1, -1);
542 config->workaround.workarounds = workarounds_store;
543 if ( list != NULL ) {
544  for (i = 0; list[i].server != NULL; i++) {
[5375]545   if ( _connect_server(con, list[i].server, ROAR_SOCKET_TYPE_UNKNOWN, 0, 0) == 0 ) {
[4806]546    roar_enum_servers_free(list);
[5368]547    return 0;
[4806]548   }
549  }
550  roar_enum_servers_free(list);
[4653]551 }
[2007]552#endif
[522]553
[2014]554 return -1;
555
[0]556 } else {
557  /* connect via (char*)server */
[5375]558  if ( _connect_server(con, server, ROAR_SOCKET_TYPE_UNKNOWN, flags, timeout) != 0 )
[5369]559   return -1;
560  return 0;
[0]561 }
562
[5368]563 roar_err_set(ROAR_ERROR_NODEV);
564 ROAR_DBG("roar_connect_raw(*) = -1 // error=NODEV");
565 return -1;
[0]566}
567
[5237]568int roar_connect     (struct roar_connection * con, const char * server, int flags, uint_least32_t timeout) {
[5373]569 struct roar_libroar_config * config = roar_libroar_get_config();
570
[1315]571 if ( con == NULL ) {
[4873]572  roar_err_set(ROAR_ERROR_FAULT);
[1315]573  return -1;
574 }
575
[5368]576 if ( roar_connect_none(con) == -1 )
[0]577  return -1;
578
[5373]579 if ( roar_connect_raw(con, server, flags | config->serverflags, timeout) == -1 )
[5296]580  return -1;
581
582 return 0;
[1315]583}
584
[5365]585int roar_connect_none (struct roar_connection * con) {
[5465]586 struct roar_libroar_config * config = roar_libroar_get_config();
587
[5365]588 if ( con == NULL ) {
[4873]589  roar_err_set(ROAR_ERROR_INVAL);
[1315]590  return -1;
591 }
592
593 memset(con, 0, sizeof(struct roar_connection));
[5296]594 con->refc        = 1;
[5467]595 con->flags       = ROAR_CON_FLAGS_ISCLIENT;
[5465]596 con->version     = _ROAR_MESSAGE_VERSION;
[5232]597 con->cb_userdata = NULL;
598 con->cb          = NULL;
[5296]599 con->server_stds = NULL;
600 con->server_name = NULL;
[5232]601
602 roar_err_init(&(con->errorframe));
[1315]603
[5296]604 con->viocon = &(con->viocon_store);
605
[5365]606// con->flags |= ROAR_CON_FLAGS_VIO;
607
[5465]608 if ( config->protocolversion != -1 )
609  roar_set_connection_version(con, config->protocolversion);
610
[5365]611 roar_err_set(ROAR_ERROR_NONE);
612 return 0;
613}
614
615int roar_connect_vio (struct roar_connection * con, struct roar_vio_calls * vio) {
616 if ( con == NULL || vio == NULL ) {
617  roar_err_set(ROAR_ERROR_INVAL);
618  return -1;
619 }
620
621 if ( roar_connect_none(con) == -1 )
622  return -1;
623
624 con->viocon = vio;
625 con->flags |= ROAR_CON_FLAGS_VIO;
626
627 return -1;
628}
629
630int roar_connect_fh (struct roar_connection * con, int fh) {
631
632 if ( con == NULL || fh == -1 ) {
633  roar_err_set(ROAR_ERROR_INVAL);
634  return -1;
635 }
636
637 if ( roar_connect_none(con) == -1 )
638  return -1;
639
[5637]640 // special hack to set an illegal value used internally in libroar:
[5365]641 if ( fh == -2 )
642  fh = -1;
643
[5296]644 if ( roar_vio_open_fh_socket(con->viocon, fh) != -1 ) {
[3869]645  con->flags |= ROAR_CON_FLAGS_VIO;
[5608]646 } else {
647  return -1;
[5231]648 }
[1315]649
[4873]650 roar_err_set(ROAR_ERROR_NONE);
[0]651 return 0;
652}
653
[1660]654int roar_get_connection_fh (struct roar_connection * con) {
[5231]655 int fh;
656
657 ROAR_DBG("roar_get_connection_fh(con=%p) = ?", con);
658
[3869]659 roar_debug_warn_sysio("roar_get_connection_fh", "roar_get_connection_vio2", NULL);
[2809]660
[2043]661 if ( con == NULL )
662  return -1;
663
[5231]664 ROAR_DBG("roar_get_connection_fh(con=%p) = ?", con);
665
[5792]666 if ( roar_vio_ctl(con->viocon, ROAR_VIO_CTL_GET_FH, &fh) == -1 ) {
667#ifdef ROAR_TARGET_WIN32
668  if ( roar_vio_ctl(con->viocon, ROAR_VIO_CTL_GET_SELECT_FH, &fh) == -1 )
669   return -1;
670#else
[3869]671  return -1;
[5792]672#endif
673 }
[3869]674
[5231]675 ROAR_DBG("roar_get_connection_fh(con=%p) = %i", con, fh);
[3869]676
[5231]677 return fh;
[2043]678}
679
[3869]680struct roar_vio_calls * roar_get_connection_vio2 (struct roar_connection * con) {
[5608]681 if ( con == NULL ) {
682  roar_err_set(ROAR_ERROR_FAULT);
[3869]683  return NULL;
[5608]684 }
[3869]685
686 if ( con->flags & ROAR_CON_FLAGS_VIO )
[5296]687  return con->viocon;
[3869]688
689// TODO: try to open the VIO.
690
[5608]691 roar_err_set(ROAR_ERROR_BADFH);
[3869]692 return NULL;
693}
694
[5296]695const char * roar_get_connection_server(struct roar_connection * con) {
696 if ( con == NULL ) {
697  roar_err_set(ROAR_ERROR_FAULT);
698  return NULL;
699 }
700
701 return con->server_name;
702}
703
704int roar_connectionref(struct roar_connection * con) {
705 if ( con == NULL ) {
706  roar_err_set(ROAR_ERROR_FAULT);
707  return -1;
708 }
709
710 con->refc++;
711
712 return 0;
713}
714
715int roar_connectionunref(struct roar_connection * con) {
[3869]716 struct roar_vio_calls * vio;
[0]717 struct roar_message m;
718
[5296]719 if ( con == NULL ) {
720  roar_err_set(ROAR_ERROR_FAULT);
721  return -1;
722 }
723
724 con->refc--;
725
726 if ( con->refc )
727  return 0;
728
[5841]729 if ( con->flags & ROAR_CON_FLAGS_TERMINATE ) {
730  if ( roar_terminate(con, 1) == -1 ) {
731   ROAR_WARN("roar_connectionunref(con=%p{.server_name='%s'}): Can not terminate server as requested.", con, con->server_name);
[5843]732   if ( roar_terminate(con, 0) == -1 ) {
733    ROAR_ERR("roar_connectionunref(con=%p{.server_name='%s'}): Can not exit server. BAD.", con, con->server_name);
734   }
[5841]735  }
736 }
737
[3875]738 memset(&m, 0, sizeof(m));
739
[5144]740 m.datalen =  0;
741 m.stream  = -1;
742 m.pos     =  0;
[0]743 m.cmd     = ROAR_CMD_QUIT;
744
745 roar_req(con, &m, NULL);
746
[3869]747 if ( (vio = roar_get_connection_vio2(con)) != NULL ) {
748  roar_vio_close(vio);
[2809]749 }
[0]750
[5296]751 if ( con->server_stds != NULL ) {
752  roar_stds_free(con->server_stds);
753  con->server_stds = NULL;
754 }
[0]755
[5296]756 if ( con->server_name != NULL ) {
757  roar_mm_free(con->server_name);
758  con->server_name = NULL;
759 }
760
761 if ( con->flags & ROAR_CON_FLAGS_FREESELF ) {
762  roar_mm_free(con);
763 } else {
764  roar_connect_fh(con, -2);
765 }
[807]766
[0]767 return 0;
768}
769
[3913]770int roar_set_connection_callback(struct roar_connection * con,
771                                 void (*cb)(struct roar_connection * con,
772                                            struct roar_message    * mes,
[5231]773                                            void                   * data,
[3913]774                                            void                   * userdata),
775                                 void * userdata) {
[5465]776 if ( con == NULL ) {
777  roar_err_set(ROAR_ERROR_FAULT);
[3913]778  return -1;
[5465]779 }
[3913]780
781 con->cb       = cb;
[5231]782 con->cb_userdata = userdata;
[3913]783
784 return 0;
785}
786
[5465]787int roar_set_connection_version(struct roar_connection * con, int version) {
788 if ( con == NULL ) {
789  roar_err_set(ROAR_ERROR_FAULT);
790  return -1;
791 }
792
793 if ( version == -1 )
794  version = _ROAR_MESSAGE_VERSION;
795
796 if ( version < 0 ) {
797  roar_err_set(ROAR_ERROR_INVAL);
798  return -1;
799 }
800
801 con->version = version;
802
803 if ( version == 2 ) {
804  con->flags |= ROAR_CON_FLAGS_SUPPORT_V2;
805 }
806
807 return 0;
808}
809
[5467]810int16_t roar_message_genseq(struct roar_connection * con, int is_client) {
811 static int16_t store = 0;
812 int16_t ret = 0;
813
814 ret = store++;
815
[5468]816 if ( ret == 0 )
817  ret = store++;
818
[5467]819 if ( is_client == -1 ) {
820  if ( con != NULL ) {
821   is_client = con->flags & ROAR_CON_FLAGS_ISCLIENT ? 1 : 0;
822  }
823 }
824
825 if ( is_client == -1 )
826  is_client = 1;
827
828 ret |= 0x8000U;
829 if ( !is_client )
830  ret -= 0x8000U;
831
832 return ret;
833}
834
[3914]835int roar_sync         (struct roar_connection * con) {
836 // wait for any non-client reqs
837 return roar_wait_msg(con, 0x0000, 0x8000);
838}
839
840int roar_wait_msg     (struct roar_connection * con, int16_t seq, int16_t seqmask) {
[5148]841 roar_err_set(ROAR_ERROR_NOSYS);
[3914]842 return -1;
843}
[3913]844
[3836]845int roar_noop         (struct roar_connection * con) {
846 struct roar_message mes;
847
848 if ( con == NULL ) {
[5148]849  roar_err_set(ROAR_ERROR_FAULT);
[3836]850  return -1;
851 }
852
853 memset(&mes, 0, sizeof(mes));
854
855 mes.cmd = ROAR_CMD_NOOP;
[5144]856 mes.stream = -1;
[3836]857
[5146]858 return roar_req3(con, &mes, NULL);
[3836]859}
860
[5114]861int roar_identify   (struct roar_connection * con, const char * name) {
[0]862 struct roar_message mes;
[5132]863 uint32_t pid;
[0]864 int max_len;
865
[4873]866 roar_err_set(ROAR_ERROR_UNKNOWN);
[807]867
[0]868 ROAR_DBG("roar_identify(*): try to identify myself...");
869
[3875]870 memset(&mes, 0, sizeof(mes));
871
[0]872 mes.cmd    = ROAR_CMD_IDENTIFY;
[5144]873 mes.stream = -1;
874 mes.pos    =  0;
[0]875
876 ROAR_DBG("roar_identify(*): name=%p", name);
877
878 if ( name == NULL )
879  name = "libroar client";
880
881 ROAR_DBG("roar_identify(*): name=%p", name);
882
[5114]883 max_len = roar_mm_strlen(name);
[0]884 ROAR_DBG("roar_identify(*): strlen(name) = %i", max_len);
885
886 if ( max_len > (LIBROAR_BUFFER_MSGDATA - 5) )
887  max_len = LIBROAR_BUFFER_MSGDATA - 5;
888
889 mes.datalen = 5 + max_len;
890 mes.data[0] = 1;
891
892 pid = getpid();
[5132]893 mes.data[1] = (pid & 0xFF000000UL) >> 24;
894 mes.data[2] = (pid & 0x00FF0000UL) >> 16;
895 mes.data[3] = (pid & 0x0000FF00UL) >>  8;
896 mes.data[4] = (pid & 0x000000FFUL) >>  0;
897 ROAR_DBG("roar_identify(*): pid = %i", (int)pid);
[0]898
899 strncpy(mes.data+5, name, max_len);
900
[5146]901 return roar_req3(con, &mes, NULL);
[0]902}
903
904//ll
Note: See TracBrowser for help on using the repository browser.