Пример #1
0
/* Function to receive data
 *  ip and port of sender is put into ip_port.
 *  Packet data is put into data.
 *  Packet length is put into length.
 *  Dump all empty packets.
 */
static int receivepacket(sock_t sock, IP_Port *ip_port, uint8_t *data, uint32_t *length)
{
    struct sockaddr_storage addr;
#ifdef WIN32
    int addrlen = sizeof(addr);
#else
    socklen_t addrlen = sizeof(addr);
#endif
    *length = 0;
    int fail_or_len = recvfrom(sock, (char *) data, MAX_UDP_PACKET_SIZE, 0, (struct sockaddr *)&addr, &addrlen);

    if (fail_or_len <= 0) {
#ifdef LOGGING

        if ((fail_or_len < 0) && (errno != EWOULDBLOCK)) {
            sprintf(logbuffer, "Unexpected error reading from socket: %u, %s\n", errno, strerror(errno));
            loglog(logbuffer);
        }

#endif
        return -1; /* Nothing received or empty packet. */
    }

    *length = (uint32_t)fail_or_len;

#ifdef TOX_ENABLE_IPV6

    if (addr.ss_family == AF_INET) {
        struct sockaddr_in *addr_in = (struct sockaddr_in *)&addr;
        ip_port->ip.family = addr_in->sin_family;
        ip_port->ip.ip4.in_addr = addr_in->sin_addr;
        ip_port->port = addr_in->sin_port;
    } else if (addr.ss_family == AF_INET6) {
        struct sockaddr_in6 *addr_in6 = (struct sockaddr_in6 *)&addr;
        ip_port->ip.family = addr_in6->sin6_family;
        ip_port->ip.ip6.in6_addr = addr_in6->sin6_addr;
        ip_port->port = addr_in6->sin6_port;
    } else
        return -1;

#else

    if (addr.ss_family == AF_INET) {
        struct sockaddr_in *addr_in = (struct sockaddr_in *)&addr;
        ip_port->ip.in_addr = addr_in->sin_addr;
        ip_port->port = addr_in->sin_port;
    } else
        return -1;

#endif

#ifdef LOGGING
    loglogdata("=>O", data, MAX_UDP_PACKET_SIZE, ip_port, *length);
#endif

    return 0;
}
Пример #2
0
/* Basic network functions:
 * Function to send packet(data) of length length to ip_port.
 */
int sendpacket(Networking_Core *net, IP_Port ip_port, uint8_t *data, uint32_t length)
{
#ifdef TOX_ENABLE_IPV6

    /* socket AF_INET, but target IP NOT: can't send */
    if ((net->family == AF_INET) && (ip_port.ip.family != AF_INET))
        return -1;

#endif

    struct sockaddr_storage addr;
    size_t addrsize = 0;

#ifdef TOX_ENABLE_IPV6

    if (ip_port.ip.family == AF_INET) {
        if (net->family == AF_INET6) {
            /* must convert to IPV4-in-IPV6 address */
            addrsize = sizeof(struct sockaddr_in6);
            struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *)&addr;
            addr6->sin6_family = AF_INET6;
            addr6->sin6_port = ip_port.port;

            /* there should be a macro for this in a standards compliant
             * environment, not found */
            IP6 ip6;

            ip6.uint32[0] = 0;
            ip6.uint32[1] = 0;
            ip6.uint32[2] = htonl(0xFFFF);
            ip6.uint32[3] = ip_port.ip.ip4.uint32;
            addr6->sin6_addr = ip6.in6_addr;

            addr6->sin6_flowinfo = 0;
            addr6->sin6_scope_id = 0;
        } else {
            IP4 ip4 = ip_port.ip.ip4;
#else
    IP4 ip4 = ip_port.ip;
#endif
            addrsize = sizeof(struct sockaddr_in);
            struct sockaddr_in *addr4 = (struct sockaddr_in *)&addr;
            addr4->sin_family = AF_INET;
            addr4->sin_addr = ip4.in_addr;
            addr4->sin_port = ip_port.port;
#ifdef TOX_ENABLE_IPV6
        }
    } else if (ip_port.ip.family == AF_INET6)
    {
        addrsize = sizeof(struct sockaddr_in6);
        struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *)&addr;
        addr6->sin6_family = AF_INET6;
        addr6->sin6_port = ip_port.port;
        addr6->sin6_addr = ip_port.ip.ip6.in6_addr;

        addr6->sin6_flowinfo = 0;
        addr6->sin6_scope_id = 0;
    } else
    {
        /* unknown address type*/
        return -1;
    }

#endif

    int res = sendto(net->sock, (char *) data, length, 0, (struct sockaddr *)&addr, addrsize);
#ifdef LOGGING
    loglogdata("O=>", data, length, &ip_port, res);
#endif

    if (res == length)
        net->send_fail_eagain = 0;
#ifdef WIN32
    else if ((res < 0) && (errno == WSAEWOULDBLOCK))
#else
    else if ((res < 0) && (errno == EAGAIN))
#endif
    	net->send_fail_eagain = current_time();
    return res;
}
Пример #3
0
/* Basic network functions:
 * Function to send packet(data) of length length to ip_port.
 */
int sendpacket(Networking_Core *net, IP_Port ip_port, uint8_t *data, uint32_t length)
{
    /* socket AF_INET, but target IP NOT: can't send */
    if ((net->family == AF_INET) && (ip_port.ip.family != AF_INET))
        return -1;

    struct sockaddr_storage addr;
    size_t addrsize = 0;

    if (ip_port.ip.family == AF_INET) {
        if (net->family == AF_INET6) {
            /* must convert to IPV4-in-IPV6 address */
            struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *)&addr;

            addrsize = sizeof(struct sockaddr_in6);
            addr6->sin6_family = AF_INET6;
            addr6->sin6_port = ip_port.port;

            /* there should be a macro for this in a standards compliant
             * environment, not found */
            IP6 ip6;

            ip6.uint32[0] = 0;
            ip6.uint32[1] = 0;
            ip6.uint32[2] = htonl(0xFFFF);
            ip6.uint32[3] = ip_port.ip.ip4.uint32;
            addr6->sin6_addr = ip6.in6_addr;

            addr6->sin6_flowinfo = 0;
            addr6->sin6_scope_id = 0;
        } else {
            struct sockaddr_in *addr4 = (struct sockaddr_in *)&addr;

            addrsize = sizeof(struct sockaddr_in);
            addr4->sin_family = AF_INET;
            addr4->sin_addr = ip_port.ip.ip4.in_addr;
            addr4->sin_port = ip_port.port;
        }
    } else if (ip_port.ip.family == AF_INET6) {
        struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *)&addr;

        addrsize = sizeof(struct sockaddr_in6);
        addr6->sin6_family = AF_INET6;
        addr6->sin6_port = ip_port.port;
        addr6->sin6_addr = ip_port.ip.ip6.in6_addr;

        addr6->sin6_flowinfo = 0;
        addr6->sin6_scope_id = 0;
    } else {
        /* unknown address type*/
        return -1;
    }

    int res = sendto(net->sock, (char *) data, length, 0, (struct sockaddr *)&addr, addrsize);

    loglogdata("O=>", data, length, ip_port, res);


    if ((res >= 0) && ((uint32_t)res == length))
        net->send_fail_eagain = 0;
    else if ((res < 0) && (errno == EWOULDBLOCK))
        net->send_fail_eagain = current_time_monotonic();

    return res;
}