/* 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; }
/* 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; }
/* 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; }