Quellcodebibliothek Statistik Leitseite products/Sources/formale Sprachen/C/VLC/src/network/   (VLC Media Plyer ©)  Datei vom 23.9.2026 mit Größe 11 kB image not shown  

Quelle  io.c   Sprache: C

 

/*****************************************************************************
 * io.c: network I/O functions
 *****************************************************************************
 * Copyright (C) 2004-2005, 2007 VLC authors and VideoLAN
 * Copyright © 2005-2006 Rémi Denis-Courmont
 *
 * Authors: Laurent Aimar <fenrir@videolan.org>
 *          Rémi Denis-Courmont
 *          Christophe Mutricy <xtophe at videolan dot org>
 *
 * This program is free software; you can redistribute it and/or modify it
 * under the terms of the GNU Lesser General Public License as published by
 * the Free Software Foundation; either version 2.1 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with this program; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
 *****************************************************************************/


/*****************************************************************************
 * Preamble
 *****************************************************************************/


#ifdef HAVE_CONFIG_H
# include "config.h"
#endif

#include <stdlib.h>
#include <stdio.h>
#include <limits.h>
#include <errno.h>
#include <assert.h>

#include <unistd.h>
#ifdef HAVE_POLL_H
# include <poll.h>
#endif
#ifdef HAVE_LINUX_DCCP_H
/* TODO: use glibc instead of linux-kernel headers */
# include <linux/dccp.h>
# define SOL_DCCP 269
#endif

#include <vlc_common.h>
#include <vlc_network.h>
#include <vlc_poll.h>
#include <vlc_interrupt.h>
#if defined (_WIN32)
#   undef EINPROGRESS
#   define EINPROGRESS WSAEWOULDBLOCK
#   undef EWOULDBLOCK
#   define EWOULDBLOCK WSAEWOULDBLOCK
#   undef EAGAIN
#   define EAGAIN WSAEWOULDBLOCK
#endif

extern int rootwrap_bind (int family, int socktype, int protocol,
                          const struct sockaddr *addr, size_t alen);

int net_Socket (vlc_object_t *p_this, int family, int socktype,
                int protocol)
{
    int fd = vlc_socket (family, socktype, protocol, true);
    if (fd == -1)
    {
        if (net_errno != EAFNOSUPPORT)
            msg_Err (p_this, "cannot create socket: %s",
                     vlc_strerror_c(net_errno));
        return -1;
    }

#ifdef _WIN32
    // Windows expects a BOOL for some getsockopt/setsockopt options
    static_assert(sizeof(int)==sizeof(BOOL), "mismatching type for setsockopt");
#endif
    setsockopt (fd, SOL_SOCKET, SO_REUSEADDR, &(int){ 1 }, sizeof (int));

#ifdef IPV6_V6ONLY
    /*
     * Accepts only IPv6 connections on IPv6 sockets.
     * If possible, we should open two sockets, but it is not always possible.
     */

    if (family == AF_INET6)
        setsockopt (fd, IPPROTO_IPV6, IPV6_V6ONLY, &(int){ 1 }, sizeof (int));
#endif

#if defined (_WIN32)
    if (family == AF_INET6)
        setsockopt (fd, IPPROTO_IPV6, IPV6_PROTECTION_LEVEL,
                    &(int){ PROTECTION_LEVEL_UNRESTRICTED }, sizeof (int));
#endif

#ifdef DCCP_SOCKOPT_SERVICE
    if (socktype == SOL_DCCP)
    {
        char *dccps = var_InheritString (p_this, "dccp-service");
        if (dccps != NULL)
        {
            setsockopt (fd, SOL_DCCP, DCCP_SOCKOPT_SERVICE, dccps,
                        (strlen (dccps) + 3) & ~3);
            free (dccps);
        }
    }
#endif

    return fd;
}

int (net_Connect)(vlc_object_t *obj, const char *host, int serv,
                  int type, int proto)
{
    struct addrinfo hints = {
        .ai_socktype = type,
        .ai_protocol = proto,
        .ai_flags = AI_NUMERICSERV | AI_IDN,
    }, *res;
    int ret = -1;

    int val = vlc_getaddrinfo_i11e(host, serv, &hints, &res);
    if (val)
    {
        msg_Err(obj, "cannot resolve %s port %d : %s", host, serv,
                gai_strerror (val));
        return -1;
    }

    vlc_tick_t timeout = VLC_TICK_FROM_MS(var_InheritInteger(obj,
                                                             "ipv4-timeout"));

    for (struct addrinfo *ptr = res; ptr != NULL; ptr = ptr->ai_next)
    {
        int fd = net_Socket(obj, ptr->ai_family,
                            ptr->ai_socktype, ptr->ai_protocol);
        if (fd == -1)
        {
            msg_Dbg(obj, "socket error: %s", vlc_strerror_c(net_errno));
            continue;
        }

        if (connect(fd, ptr->ai_addr, ptr->ai_addrlen))
        {
            if (net_errno != EINPROGRESS && errno != EINTR)
            {
                msg_Err(obj, "connection failed: %s",
                        vlc_strerror_c(net_errno));
                goto next_ai;
            }

            struct pollfd ufd;
            vlc_tick_t deadline = VLC_TICK_INVALID;

            ufd.fd = fd;
            ufd.events = POLLOUT;
            deadline = vlc_tick_now() + timeout;

            do
            {
                vlc_tick_t now = vlc_tick_now();

                if (vlc_killed())
                    goto next_ai;

                if (now > deadline)
                    now = deadline;

                val = vlc_poll_i11e(&ufd, 1, MS_FROM_VLC_TICK(deadline - now));
            }
            while (val == -1 && errno == EINTR);

            switch (val)
            {
                 case -1: /* error */
                     msg_Err(obj, "polling error: %s", vlc_strerror_c(errno));
                     goto next_ai;

                 case 0: /* timeout */
                     msg_Warn(obj, "connection timed out");
                     goto next_ai;
            }

            /* There is NO WAY around checking SO_ERROR.
             * Don't ifdef it out!!! */

            if (getsockopt(fd, SOL_SOCKET, SO_ERROR, &val,
                           &(socklen_t){ sizeof (val) }) || val)
            {
                msg_Err(obj, "connection failed: %s", vlc_strerror_c(val));
                goto next_ai;
            }
        }

        msg_Dbg(obj, "connection succeeded (socket = %d)", fd);
        ret = fd; /* success! */
        break;

next_ai: /* failure */
        net_Close(fd);
    }

    freeaddrinfo(res);
    return ret;
}

int *net_Listen (vlc_object_t *p_this, const char *psz_host,
                 unsigned i_port, int type, int protocol)
{
    struct addrinfo hints = {
        .ai_socktype = type,
        .ai_protocol = protocol,
        .ai_flags = AI_PASSIVE | AI_NUMERICSERV | AI_IDN,
    }, *res;

    msg_Dbg (p_this, "net: listening to %s port %u",
             (psz_host != NULL) ? psz_host : "*", i_port);

    int i_val = vlc_getaddrinfo (psz_host, i_port, &hints, &res);
    if (i_val)
    {
        msg_Err (p_this, "Cannot resolve %s port %u : %s",
                 (psz_host != NULL) ? psz_host : "", i_port,
                 gai_strerror (i_val));
        return NULL;
    }

    int *sockv = NULL;
    unsigned sockc = 0;

    for (struct addrinfo *ptr = res; ptr != NULL; ptr = ptr->ai_next)
    {
        int fd = net_Socket (p_this, ptr->ai_family, ptr->ai_socktype,
                             ptr->ai_protocol);
        if (fd == -1)
        {
            msg_Dbg (p_this, "socket error: %s", vlc_strerror_c(net_errno));
            continue;
        }

        /* Bind the socket */
        if (bind (fd, ptr->ai_addr, ptr->ai_addrlen))
        {
            int err = net_errno;
            net_Close (fd);
#if !defined(_WIN32)
            fd = rootwrap_bind (ptr->ai_family, ptr->ai_socktype,
                                ptr->ai_protocol,
                                ptr->ai_addr, ptr->ai_addrlen);
            if (fd != -1)
            {
                msg_Dbg (p_this, "got socket %d from rootwrap", fd);
            }
            else
#endif
            {
                msg_Err (p_this, "socket bind error: %s", vlc_strerror_c(err));
                continue;
            }
        }

        /* Listen */
        if (listen(fd, INT_MAX))
        {
            msg_Err(p_this, "socket listen error: %s",
                    vlc_strerror_c(net_errno));
            net_Close(fd);
            continue;
        }

        int *nsockv = (int *)realloc (sockv, (sockc + 2) * sizeof (int));
        if (nsockv != NULL)
        {
            nsockv[sockc++] = fd;
            sockv = nsockv;
        }
        else
            net_Close (fd);
    }

    freeaddrinfo (res);

    if (sockv != NULL)
        sockv[sockc] = -1;

    return sockv;
}

void net_ListenClose(int *fds)
{
    if (fds != NULL)
    {
        for (int *p = fds; *p != -1; p++)
            net_Close(*p);

        free(fds);
    }
}

#undef net_Accept
int net_Accept(vlc_object_t *obj, int *fds)
{
    assert(fds != NULL);

    unsigned n = 0;
    while (fds[n] != -1)
        n++;

    struct pollfd ufd[n];
    /* Initialize file descriptor set */
    for (unsigned i = 0; i < n; i++)
    {
        ufd[i].fd = fds[i];
        ufd[i].events = POLLIN;
    }

    for (;;)
    {
        while (poll(ufd, n, -1) == -1)
        {
            if (errno != EINTR)
            {
                msg_Err(obj, "poll error: %s", vlc_strerror_c(errno));
                return -1;
            }
        }

        for (unsigned i = 0; i < n; i++)
        {
            if (ufd[i].revents == 0)
                continue;

            int sfd = ufd[i].fd;
            int fd = vlc_accept(sfd, NULL, NULL, true);
            if (fd == -1)
            {
                if (net_errno != EAGAIN)
#if (EAGAIN != EWOULDBLOCK)
                if (net_errno != EWOULDBLOCK)
#endif
                    msg_Err(obj, "accept failed (from socket %d): %s", sfd,
                            vlc_strerror_c(net_errno));
                continue;
            }

            msg_Dbg(obj, "accepted socket %d (from socket %d)", fd, sfd);
            setsockopt(fd, SOL_SOCKET, SO_REUSEADDR,
                       &(int){ 1 }, sizeof (int));
            /*
             * Move listening socket to the end to let the others in the
             * set a chance next time.
             */

            memmove(fds + i, fds + i + 1, n - (i + 1));
            fds[n - 1] = sfd;
            return fd;
        }
    }
    vlc_assert_unreachable();
}

ssize_t (net_Read)(vlc_object_t *restrict obj, int fd,
                   void *restrict buf, size_t len)
{
    size_t rd = 0;

    do
    {
        if (vlc_killed())
        {
            vlc_testcancel();
            errno = EINTR;
            return -1;
        }

        ssize_t val = vlc_recv_i11e(fd, buf, len, 0);
        if (val < 0)
        {
            if (errno == EINTR || errno == EAGAIN)
                continue;
#ifdef _WIN32
            else if (WSAGetLastError() == WSAEMSGSIZE) /* datagram too big */
            {
                msg_Warn(obj, "read truncated to %zu bytes", len);
                val = len;
            }
#endif
            else
            {
                msg_Err(obj, "read error: %s", vlc_strerror_c(errno));
                return rd ? (ssize_t)rd : -1;
            }
        }

        rd += val;

        if (val == 0)
            break;

        assert(len >= (size_t)val);
        len -= val;
        buf = ((char *)buf) + val;
    }
    while (len > 0);

    return rd;
}

ssize_t (net_Write)(vlc_object_t *obj, int fd, const void *buf, size_t len)
{
    size_t written = 0;

    do
    {
        if (vlc_killed())
        {
            vlc_testcancel();
            errno = EINTR;
            return -1;
        }

        ssize_t val = vlc_send_i11e(fd, buf, len, 0);
        if (val == -1)
        {
            if (errno == EINTR || errno == EAGAIN)
                continue;

            msg_Err(obj, "write error: %s", vlc_strerror_c(errno));
            return written ? (ssize_t)written : -1;
        }

        if (val == 0)
            break;

        written += val;
        assert(len >= (size_t)val);
        len -= val;
        buf = ((const char *)buf) + val;
    }
    while (len > 0);

    return written;
}

Messung
CHZG
849710093

¤ Dauer der Verarbeitung: 0.2 Sekunden  (vorverarbeitet am  2026-11-04) ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

PVS Prover

Isabelle Prover


Cephes Mathematical Library

Vienna Development Method

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.