| 23 | } |
| 24 | |
| 25 | int MultiCastClient::init () |
| 26 | { |
| 27 | if (wsa_initialized) |
| 28 | { |
| 29 | return (int)MultiCastReturnCodes::SOCKET_ALREADY_CREATED_ERROR; |
| 30 | } |
| 31 | WSADATA wsadata; |
| 32 | int res = WSAStartup (MAKEWORD (2, 2), &wsadata); |
| 33 | if (res != 0) |
| 34 | { |
| 35 | return (int)MultiCastReturnCodes::WSA_STARTUP_ERROR; |
| 36 | } |
| 37 | wsa_initialized = true; |
| 38 | socket_addr.sin_family = AF_INET; |
| 39 | socket_addr.sin_port = htons (port); |
| 40 | socket_addr.sin_addr.s_addr = htonl (INADDR_ANY); |
| 41 | client_socket = socket (AF_INET, SOCK_DGRAM, IPPROTO_UDP); |
| 42 | if (client_socket == INVALID_SOCKET) |
| 43 | { |
| 44 | return (int)MultiCastReturnCodes::CREATE_SOCKET_ERROR; |
| 45 | } |
| 46 | |
| 47 | // ensure that library will not hang in blocking recv/send call |
| 48 | DWORD timeout = 5000; |
| 49 | DWORD value = 1; |
| 50 | DWORD buf_size = 65000; |
| 51 | setsockopt (client_socket, SOL_SOCKET, SO_REUSEADDR, (char *)&value, sizeof (value)); |
| 52 | setsockopt (client_socket, SOL_SOCKET, SO_RCVTIMEO, (char *)&timeout, sizeof (timeout)); |
| 53 | setsockopt (client_socket, SOL_SOCKET, SO_SNDTIMEO, (char *)&timeout, sizeof (timeout)); |
| 54 | setsockopt (client_socket, SOL_SOCKET, SO_SNDBUF, (const char *)&buf_size, sizeof (buf_size)); |
| 55 | setsockopt (client_socket, SOL_SOCKET, SO_RCVBUF, (const char *)&buf_size, sizeof (buf_size)); |
| 56 | |
| 57 | if (bind (client_socket, (const struct sockaddr *)&socket_addr, sizeof (socket_addr)) != 0) |
| 58 | { |
| 59 | return (int)MultiCastReturnCodes::BIND_ERROR; |
| 60 | } |
| 61 | |
| 62 | struct ip_mreq mreq; |
| 63 | if (inet_pton (AF_INET, ip_addr, &mreq.imr_multiaddr.s_addr) == 0) |
| 64 | { |
| 65 | return (int)MultiCastReturnCodes::PTON_ERROR; |
| 66 | } |
| 67 | char interface_ip[80]; |
| 68 | // use google dns ip to get local address in network |
| 69 | res = SocketClientUDP::get_local_ip_addr ("8.8.8.8", 53, interface_ip); |
| 70 | if (res != (int)SocketClientUDPReturnCodes::STATUS_OK) |
| 71 | { |
| 72 | // use INADDR_ANY if failed to connect, it works only for localhost |
| 73 | mreq.imr_interface.s_addr = htonl (INADDR_ANY); |
| 74 | } |
| 75 | else |
| 76 | { |
| 77 | // use local ip in network |
| 78 | if (inet_pton (AF_INET, interface_ip, &mreq.imr_interface.s_addr) == 0) |
| 79 | { |
| 80 | return (int)MultiCastReturnCodes::PTON_ERROR; |
| 81 | } |
| 82 | } |
nothing calls this directly
no outgoing calls
no test coverage detected