Exemple #1
0
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");
}
Exemple #2
0
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;
}
Exemple #3
0
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();
}
Exemple #4
0
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();
}
Exemple #5
0
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);
    }
}
Exemple #6
0
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;
}