Esempio n. 1
0
static connection_t *_accept_connection(void)
{
    int sock;
    connection_t *con;
    char *ip;
    int serversock; 

    serversock = wait_for_serversock(100);
    if(serversock < 0)
        return NULL;

    /* malloc enough room for a full IP address (including ipv6) */
    ip = (char *)malloc(MAX_ADDR_LEN);

    sock = sock_accept(serversock, ip, MAX_ADDR_LEN);
    if (sock >= 0)
    {
        con = connection_create (sock, serversock, ip);
        if (con == NULL)
            free (ip);

        return con;
    }

    if (!sock_recoverable(sock_error()))
        WARN2("accept() failed with error %d: %s", sock_error(), strerror(sock_error()));
    
    free(ip);

    return NULL;
}
Esempio n. 2
0
static int connection_client_setup (connection_queue_t *node) {
    int err;

    err = -ENOENT;
    if (node->con->con_timeout <= time(NULL))
        return err;

    global_lock();
    err = client_create (&node->client, node->con, node->parser);
    if (err < 0)
        goto out_fail;

    if (sock_set_blocking (node->con->sock, 0) || sock_set_nodelay (node->con->sock)) {
        if (! sock_recoverable(sock_error())) {
            node->con->error = 1;
            err = -EINVAL;
            goto out_fail;
        }
        err = -EINPROGRESS;
        client_send_403 (node->client, "failed to set tcp options on client connection, dropping");
        goto out_fail;
    }
    global_unlock();

    return 0;

out_fail:
    global_unlock();
    return err;
}
Esempio n. 3
0
int sock_connected (sock_t sock, int timeout)
{
    struct pollfd check;
    int val = SOCK_ERROR;
    socklen_t size = sizeof val;

    check.fd = sock;
    check.events = POLLOUT;
    switch (poll (&check, 1, timeout*1000))
    {
    case 0:
        return SOCK_TIMEOUT;
    default:
        /* on windows getsockopt.val is defined as char* */
        if (getsockopt(sock, SOL_SOCKET, SO_ERROR, (void*) &val, &size) == 0)
        {
            if (val == 0)
                return 1;
            sock_set_error (val);
        }
    /* fall through */
    case -1:
        if (sock_recoverable (sock_error()))
            return 0;
        return SOCK_ERROR;
    }
}
Esempio n. 4
0
/* helper function for reading data from a client */
int client_read_bytes (client_t *client, void *buf, unsigned len)
{
    int bytes;
    
    if (client->refbuf && client->refbuf->len)
    {
        /* we have data to read from a refbuf first */
        if (client->refbuf->len < len)
            len = client->refbuf->len;
        memcpy (buf, client->refbuf->data, len);
        if (len < client->refbuf->len)
        {
            char *ptr = client->refbuf->data;
            memmove (ptr, ptr+len, client->refbuf->len - len);
        }
        client->refbuf->len -= len;
        return len;
    }
    bytes = sock_read_bytes (client->con->sock, buf, len);
    if (bytes > 0)
        return bytes;

    if (bytes < 0)
    {
        if (sock_recoverable (sock_error()))
            return -1;
        WARN0 ("source connection has died");
    }
    client->con->error = 1;
    return -1;
}
Esempio n. 5
0
static void *log_commit_thread (void *arg)
{
   INFO0 ("started");
   while (1)
   {
       int ret = util_timed_wait_for_fd (logger_fd[0], 5000);
       if (ret == 0) continue;
       if (ret > 0)
       {
           char cm[80];
           ret = pipe_read (logger_fd[0], cm, sizeof cm);
           if (ret > 0)
           {
               // fprintf (stderr, "logger woken with %d\n", ret);
               log_commit_entries ();
               continue;
           }
       }
       if (ret < 0 && sock_recoverable (sock_error()))
           continue;
       int err = sock_error();
       sock_close (logger_fd[0]);
       sock_close (logger_fd[1]);
       if (worker_count)
       {
           worker_control_create (logger_fd);
           ERROR1 ("logger received code %d", err);
           continue;
       }
       // fprintf (stderr, "logger closed with zero workers\n");
       break;
   }
   return NULL;
}
Esempio n. 6
0
/* handlers (default) for reading and writing a connection_t, no encrpytion
 * used just straight access to the socket
 */
int connection_read (connection_t *con, void *buf, size_t len)
{
    int bytes = sock_read_bytes (con->sock, buf, len);
    if (bytes == 0)
        con->error = 1;
    if (bytes == -1 && !sock_recoverable (sock_error()))
        con->error = 1;
    return bytes;
}
Esempio n. 7
0
int connection_send (connection_t *con, const void *buf, size_t len)
{
    int bytes = sock_write_bytes (con->sock, buf, len);
    if (bytes < 0)
    {
        if (!sock_recoverable (sock_error()))
            con->error = 1;
    }
    else
        con->sent_bytes += bytes;
    return bytes;
}
Esempio n. 8
0
/* determines if the passed socket is still connected */
int sock_active (sock_t sock)
{
    char c;
    int l;

    l = recv (sock, &c, 1, MSG_PEEK);
    if (l == 0)
        return 0;
    if (l == SOCK_ERROR && sock_recoverable (sock_error()))
        return 1;
    return 0;
}
Esempio n. 9
0
/* helper function for sending the data to a client */
int client_send_bytes (client_t *client, const void *buf, unsigned len)
{
    int ret = sock_write_bytes (client->con->sock, buf, len);
    if (ret < 0 && !sock_recoverable (sock_error()))
    {
        DEBUG0 ("Client connection died");
        client->con->error = 1;
    }
    if (ret > 0)
        client->con->sent_bytes += ret;
    return ret;
}
Esempio n. 10
0
/* get some data from the source. The stream data is placed in a refbuf
 * and sent back, however NULL is also valid as in the case of a short
 * timeout and there's no data pending.
 */
static refbuf_t *get_next_buffer (source_t *source)
{
    refbuf_t *refbuf = NULL;
    int delay = 250;

    if (source->short_delay)
        delay = 0;
    while (global.running == ICE_RUNNING && source->running)
    {
        int fds;
        time_t current = time (NULL);

        fds = util_timed_wait_for_fd (source->con->sock, delay);

        if (fds < 0)
        {
            if (! sock_recoverable (sock_error()))
            {
                WARN0 ("Error while waiting on socket, Disconnecting source");
                source->running = 0;
            }
            break;
        }
        if (fds == 0)
        {
            if (source->last_read + (time_t)source->timeout < current)
            {
                DEBUG3 ("last %ld, timeout %ld, now %ld", source->last_read, source->timeout, current);
                WARN0 ("Disconnecting source due to socket timeout");
                source->running = 0;
            }
            break;
        }
        source->last_read = current;
        refbuf = source->format->get_buffer (source);
        if (refbuf)
            break;
    }

    return refbuf;
}
Esempio n. 11
0
static connection_t *_accept_connection(int duration)
{
    sock_t sock, serversock;
    char *ip;

    serversock = wait_for_serversock (duration);
    if (serversock == SOCK_ERROR)
        return NULL;

    /* malloc enough room for a full IP address (including ipv6) */
    ip = (char *)malloc(MAX_ADDR_LEN);

    sock = sock_accept(serversock, ip, MAX_ADDR_LEN);
    if (sock != SOCK_ERROR)
    {
        connection_t *con = NULL;
        /* Make any IPv4 mapped IPv6 address look like a normal IPv4 address */
        if (strncmp (ip, "::ffff:", 7) == 0)
            memmove (ip, ip+7, strlen (ip+7)+1);

        if (accept_ip_address (ip))
            con = connection_create (sock, serversock, ip);
        if (con)
            return con;
        sock_close (sock);
    }
    else
    {
        if (!sock_recoverable(sock_error()))
        {
            WARN2("accept() failed with error %d: %s", sock_error(), strerror(sock_error()));
            thread_sleep (500000);
        }
    }
    free(ip);
    return NULL;
}
Esempio n. 12
0
int sock_connected (sock_t sock, int timeout)
{
    fd_set wfds;
    int val = SOCK_ERROR;
    socklen_t size = sizeof val;
    struct timeval tv, *timeval = NULL;

    /* make a timeout of <0 be indefinite */
    if (timeout >= 0)
    {
        tv.tv_sec = timeout;
        tv.tv_usec = 0;
        timeval = &tv;
    }

    FD_ZERO(&wfds);
    FD_SET(sock, &wfds);

    switch (select(sock + 1, NULL, &wfds, NULL, timeval))
    {
    case 0:
        return SOCK_TIMEOUT;
    default:
        /* on windows getsockopt.val is defined as char* */
        if (getsockopt(sock, SOL_SOCKET, SO_ERROR, (void*) &val, &size) == 0)
        {
            if (val == 0)
                return 1;
            sock_set_error (val);
        }
    /* fall through */
    case -1:
        if (sock_recoverable (sock_error()))
            return 0;
        return SOCK_ERROR;
    }
}
Esempio n. 13
0
int connection_bufs_send (connection_t *con, struct connection_bufs *vectors, int skip)
{
    IOVEC *p = vectors->block, old_vals;
    int i = vectors->count,  offset = 0, ret = -1;

    i = connbufs_locate_start (vectors, skip, &old_vals, &offset);
    p = vectors->block + i;

    if (i >= 0)
    {
        if (not_ssl_connection (con))
        {
            ret = sock_writev (con->sock, p, vectors->count - i);
            if (ret < 0 && !sock_recoverable (sock_error()))
                con->error = 1;
        }
#ifdef HAVE_OPENSSL
        else
        {
            IOVEC *io = p;
            int bytes = 0;
            for (; i < vectors->count; i++, io++)
            {
               int v = connection_send_ssl (con, IO_VECTOR_BASE(io), IO_VECTOR_LEN(io));
               if (v > 0) bytes += v;
               if (v < IO_VECTOR_LEN(io)) break;
            }
            if (bytes > 0)  ret = bytes;
        }
#endif
        if (offset)
            *p = old_vals;
        if (ret > 0)
            con->sent_bytes += ret;
    }
    return ret;
}
Esempio n. 14
0
/* main plugin handler for getting a buffer for the queue. In here we
 * just add an incoming page to the codecs and process it until either
 * more data is needed or we prodice a buffer for the queue.
 */
static refbuf_t *ogg_get_buffer (source_t *source)
{
    ogg_state_t *ogg_info = source->format->_state;
    char *data = NULL;
    int bytes;

    while (1)
    {
        while (1)
        {
            ogg_page page;
            refbuf_t *refbuf;
            ogg_codec_t *codec = ogg_info->current;

            /* if a codec has just been given a page then process it */
            if (codec && codec->process)
            {
                refbuf = codec->process (ogg_info, codec);
                if (refbuf)
                    return complete_buffer (source, refbuf);

                ogg_info->current = NULL;
            }

            if (ogg_sync_pageout (&ogg_info->oy, &page) > 0)
            {
                if (ogg_page_bos (&page))
                {
                    process_initial_page (source->format, &page);
                    continue;
                }
                ogg_info->bos_completed = 1;
                refbuf = process_ogg_page (ogg_info, &page);
                if (ogg_info->error)
                {
                    ERROR0 ("Problem processing stream");
                    source->running = 0;
                    return NULL;
                }
                if (refbuf)
                    return complete_buffer (source, refbuf);
                continue;
            }
            /* need more stream data */
            break;
        }
        /* we need more data to continue getting pages */
        data = ogg_sync_buffer (&ogg_info->oy, 4096);

        bytes = sock_read_bytes (source->con->sock, data, 4096);
        if (bytes < 0)
        {
            if (sock_recoverable (sock_error()))
                return NULL;
            WARN0 ("source connection has died");
            ogg_sync_wrote (&ogg_info->oy, 0);
            source->running = 0;
            return NULL;
        }
        if (bytes == 0)
        {
            INFO1 ("End of Stream %s", source->mount);
            ogg_sync_wrote (&ogg_info->oy, 0);
            source->running = 0;
            return NULL;
        }
        ogg_sync_wrote (&ogg_info->oy, bytes);
    }
}
Esempio n. 15
0
/* issue a connect, but return after the timeout (seconds) is reached. If
 * timeout is 0 or less then we will wait until the OS gives up on the connect
 * The socket is returned
 */
sock_t sock_connect_wto_bind (const char *hostname, int port, const char *bnd, int timeout)
{
    sock_t sock = SOCK_ERROR;
    struct addrinfo *ai, *head, *b_head=NULL, hints;
    char service[8];

    memset (&hints, 0, sizeof (hints));
    hints.ai_family = AF_UNSPEC;
    hints.ai_socktype = SOCK_STREAM;
    snprintf (service, sizeof (service), "%u", port);

    if (getaddrinfo (hostname, service, &hints, &head))
        return SOCK_ERROR;

    ai = head;
    while (ai)
    {
        int type = ai->ai_socktype;
        if ((sock = sock_open (ai->ai_family, type, ai->ai_protocol)) >= 0)
        {
            sock_set_cloexec (sock);
            if (timeout > 0)
                sock_set_blocking (sock, 0);

            if (bnd)
            {
                struct addrinfo b_hints;
                memset (&b_hints, 0, sizeof(b_hints));
                b_hints.ai_family = ai->ai_family;
                b_hints.ai_socktype = ai->ai_socktype;
                b_hints.ai_protocol = ai->ai_protocol;
                if (getaddrinfo (bnd, NULL, &b_hints, &b_head) ||
                        bind (sock, b_head->ai_addr, b_head->ai_addrlen) < 0)
                {
                    sock_close (sock);
                    sock = SOCK_ERROR;
                    break;
                }
            }

            if (connect (sock, ai->ai_addr, ai->ai_addrlen) == 0)
                break;

            /* loop as the connect maybe async */
            while (sock != SOCK_ERROR)
            {
                if (sock_recoverable (sock_error()))
                {
                    int connected = sock_connected (sock, timeout);
                    if (connected == 0)  /* try again, interrupted */
                        continue;
                    if (connected == 1) /* connected */
                    {
                        if (timeout >= 0)
                            sock_set_blocking(sock, 1);
                        break;
                    }
                }
                sock_close (sock);
                sock = SOCK_ERROR;
            }
            if (sock != SOCK_ERROR)
                break;
        }
        ai = ai->ai_next;
    }
    if (b_head)
        freeaddrinfo (b_head);
    freeaddrinfo (head);

    return sock;
}
Esempio n. 16
0
static client_t *accept_client (void)
{
    client_t *client = NULL;
    sock_t sock, serversock = wait_for_serversock ();
    char addr [200];

    if (serversock == SOCK_ERROR)
        return NULL;

    sock = sock_accept (serversock, addr, 200);
    if (sock == SOCK_ERROR)
    {
        if (sock_recoverable (sock_error()))
            return NULL;
        WARN2 ("accept() failed with error %d: %s", sock_error(), strerror(sock_error()));
        thread_sleep (500000);
        return NULL;
    }
    do
    {
        int i, num;
        refbuf_t *r;

        if (sock_set_blocking (sock, 0) || sock_set_nodelay (sock))
        {
            WARN0 ("failed to set tcp options on client connection, dropping");
            break;
        }
        client = calloc (1, sizeof (client_t));
        if (client == NULL || connection_init (&client->connection, sock, addr) < 0)
            break;

        client->shared_data = r = refbuf_new (PER_CLIENT_REFBUF_SIZE);
        r->len = 0; // for building up the request coming in

        global_lock ();
        client_register (client);

        for (i=0; i < global.server_sockets; i++)
        {
            if (global.serversock[i] == serversock)
            {
                client->server_conn = global.server_conn[i];
                client->server_conn->refcount++;
                if (client->server_conn->ssl && ssl_ok)
                    connection_uses_ssl (&client->connection);
                if (client->server_conn->shoutcast_compat)
                    client->ops = &shoutcast_source_ops;
                else
                    client->ops = &http_request_ops;
                break;
            }
        }
        num = global.clients;
        global_unlock ();
        stats_event_args (NULL, "clients", "%d", num);
        client->flags |= CLIENT_ACTIVE;
        return client;
    } while (0);

    free (client);
    sock_close (sock);
    return NULL;
}
Esempio n. 17
0
/* get some data from the source. The stream data is placed in a refbuf
 * and sent back, however NULL is also valid as in the case of a short
 * timeout and there's no data pending.
 */
static refbuf_t *get_next_buffer (source_t *source)
{
    refbuf_t *refbuf = NULL;
    int delay = 250;

    if (source->short_delay)
        delay = 0;
    while (global.running == ICE_RUNNING && source->running)
    {
        int fds = 0;
        time_t current = time (NULL);

        if (source->client)
            fds = util_timed_wait_for_fd (source->con->sock, delay);
        else
        {
            thread_sleep (delay*1000);
            source->last_read = current;
        }

        if (current >= source->client_stats_update)
        {
            stats_event_args (source->mount, "total_bytes_read",
                    "%"PRIu64, source->format->read_bytes);
            stats_event_args (source->mount, "total_bytes_sent",
                    "%"PRIu64, source->format->sent_bytes);
            source->client_stats_update = current + 5;
        }
        if (fds < 0)
        {
            if (! sock_recoverable (sock_error()))
            {
                WARN0 ("Error while waiting on socket, Disconnecting source");
                source->running = 0;
            }
            break;
        }
        if (fds == 0)
        {
            if (source->last_read + (time_t)source->timeout < current)
            {
                DEBUG3 ("last %ld, timeout %d, now %ld", (long)source->last_read,
                        source->timeout, (long)current);
                WARN0 ("Disconnecting source due to socket timeout");
                source->running = 0;
            }
            break;
        }
        source->last_read = current;
        refbuf = source->format->get_buffer (source);
        if (source->client->con && source->client->con->error)
        {
            INFO1 ("End of Stream %s", source->mount);
            source->running = 0;
            continue;
        }
        if (refbuf)
            break;
    }

    return refbuf;
}