static void check_connect(aeEventLoop *el, int fd, void *data, int mask) { int err = 0; socklen_t optlen; char errstr[ANET_ERR_LEN]; aeDeleteFileEvent(el, fd, AE_WRITABLE); optlen = sizeof(err); if (getsockopt(fd, SOL_SOCKET, SO_ERROR, &err, &optlen) == -1) { Log(WARNING, "getsockopt: %s", strerror(errno)); close(fd); retry_connect(); return; } if (err != 0) { Log(WARNING, "data server disconnected: %s", strerror(err)); close(fd); retry_connect(); return; } if (anetEnableTcpNoDelay(errstr, fd) == ANET_ERR) { Log(WARNING, "anetEnableTcpNoDelay: %s", errstr); } data_stream = sock_init(fd, BUFSIZE, 0); Log(NOTICE, "connected to data stream"); }
int main(int argc, char* argv[]) { if (argc!=3) { fprintf(stderr, "Usage: %s host service\n", argv[0]); exit(1); } setbuf(stderr, NULL); setbuf(stdout, NULL); struct addrinfo hint, *ailist, *aip; int err, sfd; memset(&hint, 0, sizeof(hint)); if ((err=getaddrinfo(argv[1], argv[2], &hint, &ailist))!=0) { fprintf(stderr, "getaddrinfo error: %s\n", gai_strerror(err)); exit(1); } for (aip=ailist; aip!=NULL; aip=aip->ai_next) { if ((sfd=retry_connect(aip->ai_family, SOCK_STREAM, 0, (struct sockaddr*)aip->ai_addr, aip->ai_addrlen))>=0) { request(sfd); fprintf(stderr, "request done\n"); exit(0); } } freeaddrinfo(ailist); fprintf(stderr, "cant connect\n"); return 1; }
static void get_address_reply_cb(DBusPendingCall *pending, void *data) { DBusMessageIter iter; DBusMessageIter sub; int current_type; char *address = NULL; DBusMessage *msg = NULL; (void) data; msg = dbus_pending_call_steal_reply(pending); if (!msg) { N_WARNING(LOG_CAT "Could not get reply from pending call."); goto retry; } dbus_message_iter_init(msg, &iter); // Reply string is inside DBUS_TYPE_VARIANT while ((current_type = dbus_message_iter_get_arg_type(&iter)) != DBUS_TYPE_INVALID) { if (current_type == DBUS_TYPE_VARIANT) { dbus_message_iter_recurse(&iter, &sub); while ((current_type = dbus_message_iter_get_arg_type(&sub)) != DBUS_TYPE_INVALID) { if (current_type == DBUS_TYPE_STRING) dbus_message_iter_get_basic(&sub, &address); dbus_message_iter_next(&sub); } } dbus_message_iter_next(&iter); } if (address) { N_DEBUG (LOG_CAT "Got PulseAudio DBus address: %s", address); volume_pulse_address = g_strdup(address); // Unref sesssion bus connection, it is not needed anymore. // Real communication is done with peer-to-peer connection. dbus_connection_unref(volume_session_bus); volume_session_bus = NULL; } // Always retry connection, if address was determined, it is used // to get peer-to-peer connection, if address wasn't determined, // we'll need to reconnect and retry anyway. retry: if (msg) dbus_message_unref(msg); if (pending) dbus_pending_call_unref(pending); retry_connect(); }
static void connect_to_pulseaudio () { const char *pulse_address = NULL; gboolean success; if (!volume_pulse_address && (pulse_address = getenv ("PULSE_DBUS_SERVER"))) volume_pulse_address = g_strdup(pulse_address); if (volume_pulse_address) success = connect_peer_to_peer(); else success = connect_get_address(); if (!success) retry_connect(); }
void write_data_buffer(aeEventLoop *el, int fd, void *data, int mask) { /* Write the data stream buffer to the data stream server. If it fails, * free the data stream connection, and try to reconnect in 10 seconds. */ Sock *s = (Sock *)data; if (sock_write(s)) { Log(WARNING, "error sending data stream buffer"); aeDeleteFileEvent(el, s->fd, AE_WRITABLE); sock_free(s); retry_connect(); return; } if (CB_BYTES(s->sendbuf) == 0) { aeDeleteFileEvent(el, s->fd, AE_WRITABLE); } }
static DBusHandlerResult filter_cb (DBusConnection *connection, DBusMessage *msg, void *data) { (void) connection; (void) data; const char *obj_path; char *stream_name; GList *list, *i; SubscribeItem *item; int volume = 0; if (dbus_message_has_interface (msg, DBUS_INTERFACE_LOCAL) && dbus_message_has_path (msg, DBUS_PATH_LOCAL) && dbus_message_has_member (msg, DISCONNECTED_SIG)) { N_DEBUG (LOG_CAT "pulseaudio disconnected, reconnecting in %d seconds", RETRY_TIMEOUT); disconnect_from_pulseaudio (); // After disconnecting re-query stream restore object names. if (subscribe_map && object_map) { list = g_hash_table_get_values (subscribe_map); for (i = g_list_first (list); i; i = g_list_next (i)) { SubscribeItem *item = (SubscribeItem*) i->data; if (item->object_path) { g_free (item->object_path); item->object_path = NULL; } } g_list_free (list); queue_subscribe = TRUE; } // If PulseAudio is restarting path to runtime files may change so we'll // have to request DBus address again. if (volume_pulse_address) { g_free(volume_pulse_address); volume_pulse_address = NULL; } retry_connect(); } else if (subscribe_callback && dbus_message_has_interface (msg, STREAM_RESTORE_IF) && dbus_message_has_path (msg, STREAM_RESTORE_PATH) && dbus_message_has_member (msg, NEW_ENTRY_MEMBER)) { if (!dbus_message_get_args (msg, NULL, DBUS_TYPE_OBJECT_PATH, &obj_path, DBUS_TYPE_INVALID)) { N_WARNING (LOG_CAT "failed to get arguments for new entry"); goto end; } // If the entry is in subscribe_map but not in object_map, look up the entry // and add to object_map if (!object_map_complete && !g_hash_table_lookup (object_map, obj_path)) { if ((stream_name = get_object_name (obj_path))) { if ((item = g_hash_table_lookup (subscribe_map, stream_name))) { item->object_path = g_strdup (obj_path); N_DEBUG (LOG_CAT "stream restore entry for %s appeared (%s)", item->stream_name, item->object_path); update_object_map_listen (); } g_free (stream_name); } } } else if (subscribe_callback && dbus_message_has_interface (msg, STREAM_RESTORE_IF) && dbus_message_has_path (msg, STREAM_RESTORE_PATH) && dbus_message_has_member (msg, ENTRY_REMOVED_MEMBER)) { if (!dbus_message_get_args (msg, NULL, DBUS_TYPE_OBJECT_PATH, &obj_path, DBUS_TYPE_INVALID)) { N_WARNING (LOG_CAT "failed to get arguments for removed entry"); goto end; } if ((item = g_hash_table_lookup (object_map, obj_path))) { g_hash_table_remove (object_map, item->object_path); g_free (item->object_path); item->object_path = NULL; update_object_map_listen (); N_DEBUG (LOG_CAT "removed entry %s from object map (%s)", item->stream_name, obj_path); } } else if (subscribe_callback && dbus_message_has_interface (msg, STREAM_ENTRY_IF) && dbus_message_has_member (msg, VOLUME_UPDATED_MEMBER)) { if (!(obj_path = dbus_message_get_path (msg))) goto end; if ((item = g_hash_table_lookup (object_map, obj_path))) { N_DEBUG (LOG_CAT "volume updated for stream %s (%s)", item->stream_name, item->object_path); if (get_volume (msg, &volume)) { subscribe_callback (item->stream_name, FROM_PA_VOL(volume), item->data, subscribe_userdata); } } } end: return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; }