* Multicast interface selection to UnixSocket - added methods Bind and JoinMCastGroup with <char *if_name> argument * Interface handling to NetInterface class tree - new field and its initialization/usage in Slave branch. * Multicast interface selection to NetSlaves (Adapter/Driver) and NetMaster, where master can now listen all interfaces.pull/27/head
| @@ -35,7 +35,7 @@ namespace Jack | |||
| because we don't have full parametering right now, parameters will be parsed from the param list, | |||
| and then JackNetSlaveInterface will be filled with proper values. | |||
| */ | |||
| char multicast_ip[32]; | |||
| char multicast_ip[32],multicast_if[32]; | |||
| uint udp_port; | |||
| GetHostName(fParams.fName, JACK_CLIENT_NAME_SIZE); | |||
| fSocket.GetName(fParams.fSlaveNetName); | |||
| @@ -58,11 +58,10 @@ namespace Jack | |||
| udp_port = (default_udp_port) ? atoi(default_udp_port) : DEFAULT_PORT; | |||
| const char* default_multicast_ip = getenv("JACK_NETJACK_MULTICAST"); | |||
| if (default_multicast_ip) { | |||
| strcpy(multicast_ip, default_multicast_ip); | |||
| } else { | |||
| strcpy(multicast_ip, DEFAULT_MULTICAST_IP); | |||
| } | |||
| strcpy(multicast_ip, (default_multicast_ip) ? default_multicast_ip : DEFAULT_MULTICAST_IP); | |||
| const char* default_multicast_if = getenv("JACK_NETJACK_INTERFACE"); | |||
| strcpy(multicast_if, (default_multicast_if) ? default_multicast_if : DEFAULT_MULTICAST_IF); | |||
| //options parsing | |||
| const JSList* node; | |||
| @@ -76,6 +75,10 @@ namespace Jack | |||
| assert(strlen(param->value.str) < 32); | |||
| strcpy(multicast_ip, param->value.str); | |||
| break; | |||
| case 'f' : | |||
| assert(strlen(param->value.str) < 32); | |||
| strcpy(multicast_if, param->value.str); | |||
| break; | |||
| case 'p' : | |||
| udp_port = param->value.ui; | |||
| break; | |||
| @@ -128,6 +131,8 @@ namespace Jack | |||
| } | |||
| strcpy(fMulticastIP, multicast_ip); | |||
| if(strcmp(multicast_if,DEFAULT_MULTICAST_IF)) | |||
| strcpy(fMulticastIF, multicast_if); | |||
| // Set the socket parameters | |||
| fSocket.SetPort(udp_port); | |||
| @@ -424,6 +429,9 @@ extern "C" | |||
| strcpy(value.str, DEFAULT_MULTICAST_IP); | |||
| jack_driver_descriptor_add_parameter(desc, &filler, "multicast-ip", 'a', JackDriverParamString, &value, NULL, "Multicast address, or explicit IP of the master", NULL); | |||
| strcpy(value.str, DEFAULT_MULTICAST_IF); | |||
| jack_driver_descriptor_add_parameter(desc, &filler, "multicast-if", 'f', JackDriverParamString, &value, NULL, "Multicast interface name, any or all", "Multicast interface to send probes from (any - kernel chosen (default), all - all available, if_name - explicit bind)"); | |||
| value.i = DEFAULT_PORT; | |||
| jack_driver_descriptor_add_parameter(desc, &filler, "udp-net-port", 'p', JackDriverParamInt, &value, NULL, "UDP port", NULL); | |||
| @@ -28,7 +28,7 @@ using namespace std; | |||
| namespace Jack | |||
| { | |||
| JackNetDriver::JackNetDriver(const char* name, const char* alias, JackLockedEngine* engine, JackSynchro* table, | |||
| const char* ip, int udp_port, int mtu, int midi_input_ports, int midi_output_ports, | |||
| const char* ip, int udp_port, const char* mcif, int mtu, int midi_input_ports, int midi_output_ports, | |||
| char* net_name, uint transport_sync, int network_latency, | |||
| int celt_encoding, int opus_encoding, bool auto_save) | |||
| : JackWaiterDriver(name, alias, engine, table), JackNetSlaveInterface(ip, udp_port) | |||
| @@ -39,6 +39,8 @@ namespace Jack | |||
| if (strcmp(net_name, "") == 0) { | |||
| GetHostName(net_name, JACK_CLIENT_NAME_SIZE); | |||
| } | |||
| if(strcmp(mcif,DEFAULT_MULTICAST_IF)) | |||
| strcpy(fMulticastIF,mcif); | |||
| fParams.fMtu = mtu; | |||
| @@ -676,6 +678,9 @@ namespace Jack | |||
| strcpy(value.str, DEFAULT_MULTICAST_IP); | |||
| jack_driver_descriptor_add_parameter(desc, &filler, "multicast-ip", 'a', JackDriverParamString, &value, NULL, "Multicast address, or explicit IP of the master", NULL); | |||
| strcpy(value.str, DEFAULT_MULTICAST_IF); | |||
| jack_driver_descriptor_add_parameter(desc, &filler, "multicast-if", 'f', JackDriverParamString, &value, NULL, "Multicast interface name, any or all", "Multicast interface to send probes from (any - kernel chosen (default), all - all available, if_name - explicit bind)"); | |||
| value.i = DEFAULT_PORT; | |||
| jack_driver_descriptor_add_parameter(desc, &filler, "udp-net-port", 'p', JackDriverParamInt, &value, NULL, "UDP port", NULL); | |||
| @@ -719,8 +724,9 @@ Deactivated for now.. | |||
| SERVER_EXPORT Jack::JackDriverClientInterface* driver_initialize(Jack::JackLockedEngine* engine, Jack::JackSynchro* table, const JSList* params) | |||
| { | |||
| char multicast_if[32]; | |||
| char multicast_ip[32]; | |||
| char net_name[JACK_CLIENT_NAME_SIZE+1] = {0}; | |||
| char net_name[JACK_CLIENT_NAME_SIZE + 1] = {0}; | |||
| int udp_port; | |||
| int mtu = DEFAULT_MTU; | |||
| // Desactivated for now... | |||
| @@ -747,6 +753,9 @@ Deactivated for now.. | |||
| const char* default_multicast_ip = getenv("JACK_NETJACK_MULTICAST"); | |||
| strcpy(multicast_ip, (default_multicast_ip) ? default_multicast_ip : DEFAULT_MULTICAST_IP); | |||
| const char* default_multicast_if = getenv("JACK_NETJACK_INTERFACE"); | |||
| strcpy(multicast_if, (default_multicast_if) ? default_multicast_if : DEFAULT_MULTICAST_IF); | |||
| for (node = params; node; node = jack_slist_next(node)) { | |||
| param = (const jack_driver_param_t*) node->data; | |||
| switch (param->character) | |||
| @@ -755,6 +764,10 @@ Deactivated for now.. | |||
| assert(strlen(param->value.str) < 32); | |||
| strcpy(multicast_ip, param->value.str); | |||
| break; | |||
| case 'f' : | |||
| assert(strlen(param->value.str) < 32); | |||
| strcpy(multicast_if, param->value.str); | |||
| break; | |||
| case 'p': | |||
| udp_port = param->value.ui; | |||
| break; | |||
| @@ -808,7 +821,7 @@ Deactivated for now.. | |||
| try { | |||
| Jack::JackDriverClientInterface* driver = new Jack::JackWaitThreadedDriver( | |||
| new Jack::JackNetDriver("system", "net_pcm", engine, table, multicast_ip, udp_port, mtu, | |||
| new Jack::JackNetDriver("system", "net_pcm", engine, table, multicast_ip, udp_port, multicast_if, mtu, | |||
| midi_input_ports, midi_output_ports, | |||
| net_name, transport_sync, | |||
| network_latency, celt_encoding, opus_encoding, auto_save)); | |||
| @@ -79,7 +79,7 @@ namespace Jack | |||
| public: | |||
| JackNetDriver(const char* name, const char* alias, JackLockedEngine* engine, JackSynchro* table, | |||
| const char* ip, int port, int mtu, int midi_input_ports, int midi_output_ports, | |||
| const char* ip, int port, const char* mcif, int mtu, int midi_input_ports, int midi_output_ports, | |||
| char* net_name, uint transport_sync, int network_latency, int celt_encoding, | |||
| int opus_encoding, bool auto_save); | |||
| virtual ~JackNetDriver(); | |||
| @@ -57,6 +57,7 @@ namespace Jack | |||
| fSetTimeOut = false; | |||
| fTxBuffer = NULL; | |||
| fRxBuffer = NULL; | |||
| fMulticastIF[0]=0; | |||
| fNetAudioCaptureBuffer = NULL; | |||
| fNetAudioPlaybackBuffer = NULL; | |||
| fNetMidiCaptureBuffer = NULL; | |||
| @@ -700,6 +701,12 @@ namespace Jack | |||
| if (fSocket.IsLocal(fMulticastIP)) { | |||
| jack_info("Local IP is used..."); | |||
| } else if (fMulticastIF[0]) { | |||
| // bind the socket & interface | |||
| if (fSocket.Bind(fMulticastIF) == SOCKET_ERROR) { | |||
| jack_error("Can't bind the socket : %s", StrError(NET_ERROR_CODE)); | |||
| return NET_SOCKET_ERROR; | |||
| } | |||
| } else { | |||
| // bind the socket | |||
| if (fSocket.Bind() == SOCKET_ERROR) { | |||
| @@ -719,8 +726,7 @@ namespace Jack | |||
| } | |||
| // send 'AVAILABLE' until 'SLAVE_SETUP' received | |||
| jack_info("Waiting for a master..."); | |||
| jack_info("Waiting for a master on %s...",(fMulticastIF[0])?fMulticastIF:"default"); | |||
| do { | |||
| // send 'available' | |||
| session_params_t net_params; | |||
| @@ -27,6 +27,7 @@ namespace Jack | |||
| { | |||
| #define DEFAULT_MULTICAST_IP "225.3.19.154" | |||
| #define DEFAULT_MULTICAST_IF "any" | |||
| #define DEFAULT_PORT 19000 | |||
| #define DEFAULT_MTU 1500 | |||
| #define MAX_MTU 9000 | |||
| @@ -60,6 +61,7 @@ namespace Jack | |||
| session_params_t fParams; | |||
| JackNetSocket fSocket; | |||
| char fMulticastIP[32]; | |||
| char fMulticastIF[32]; | |||
| // headers | |||
| packet_header_t fTxHeader; | |||
| @@ -505,7 +505,7 @@ namespace Jack | |||
| if (out) { | |||
| memset(out, 0, sizeof(float) * fParams.fPeriodSize); | |||
| } | |||
| fNetAudioPlaybackBuffer->SetBuffer(audio_port_index, out))); | |||
| fNetAudioPlaybackBuffer->SetBuffer(audio_port_index, out); | |||
| #endif | |||
| } | |||
| @@ -660,6 +660,13 @@ namespace Jack | |||
| strcpy(fMulticastIP, DEFAULT_MULTICAST_IP); | |||
| } | |||
| const char* default_multicast_if = getenv("JACK_NETJACK_INTERFACE"); | |||
| if (default_multicast_if) { | |||
| strcpy(fMulticastIF, default_multicast_if); | |||
| } else { | |||
| strcpy(fMulticastIF, DEFAULT_MULTICAST_IF); | |||
| } | |||
| for (node = params; node; node = jack_slist_next(node)) { | |||
| param = (const jack_driver_param_t*) node->data; | |||
| @@ -672,6 +679,14 @@ namespace Jack | |||
| } | |||
| break; | |||
| case 'f' : | |||
| if (strlen(param->value.str) < 32) { | |||
| strcpy(fMulticastIF, param->value.str); | |||
| } else { | |||
| jack_error("Can't use multicast interface %s, using default %s", param->value.ui, DEFAULT_MULTICAST_IF); | |||
| } | |||
| break; | |||
| case 'p': | |||
| fSocket.SetPort(param->value.ui); | |||
| break; | |||
| @@ -761,7 +776,7 @@ namespace Jack | |||
| { | |||
| JackNetMasterManager* master_manager = static_cast<JackNetMasterManager*>(arg); | |||
| jack_info("Starting Jack NetManager"); | |||
| jack_info("Listening on '%s:%d'", master_manager->fMulticastIP, master_manager->fSocket.GetPort()); | |||
| jack_info("Listening on '%s:%d%%%s'", master_manager->fMulticastIP, master_manager->fSocket.GetPort(),master_manager->fMulticastIF); | |||
| master_manager->Run(); | |||
| return NULL; | |||
| } | |||
| @@ -797,7 +812,7 @@ namespace Jack | |||
| } | |||
| //join multicast group | |||
| if (fSocket.JoinMCastGroup(fMulticastIP) == SOCKET_ERROR) { | |||
| if (fSocket.JoinMCastGroup(fMulticastIP,fMulticastIF) == SOCKET_ERROR) { | |||
| jack_error("Can't join multicast group : %s", StrError(NET_ERROR_CODE)); | |||
| } | |||
| @@ -843,6 +858,7 @@ namespace Jack | |||
| } | |||
| break; | |||
| default: | |||
| jack_log("JackNetMasterManager::Run: read: %d; type: %d; peer: %s",rx_bytes,host_params.fPacketID,host_params.fName); | |||
| break; | |||
| } | |||
| } | |||
| @@ -949,6 +965,9 @@ extern "C" | |||
| strcpy(value.str, DEFAULT_MULTICAST_IP); | |||
| jack_driver_descriptor_add_parameter(desc, &filler, "multicast-ip", 'a', JackDriverParamString, &value, NULL, "Multicast address", NULL); | |||
| strcpy(value.str, DEFAULT_MULTICAST_IF); | |||
| jack_driver_descriptor_add_parameter(desc, &filler, "multicast-if", 'f', JackDriverParamString, &value, NULL, "Multicast interface", "Multicast interface to bind to. ('all' - all ip ifs; 'any' (default) kernel chosen; ifname i.e. eth0)"); | |||
| value.i = DEFAULT_PORT; | |||
| jack_driver_descriptor_add_parameter(desc, &filler, "udp-net-port", 'p', JackDriverParamInt, &value, NULL, "UDP port", NULL); | |||
| @@ -112,6 +112,7 @@ namespace Jack | |||
| jack_client_t* fClient; | |||
| const char* fName; | |||
| char fMulticastIP[32]; | |||
| char fMulticastIF[32]; | |||
| JackNetSocket fSocket; | |||
| jack_native_thread_t fThread; | |||
| master_list_t fMasterList; | |||
| @@ -20,6 +20,10 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | |||
| #include "JackNetUnixSocket.h" | |||
| #include "JackError.h" | |||
| #include <arpa/inet.h> | |||
| #include <sys/socket.h> | |||
| #include <ifaddrs.h> | |||
| #include <net/if.h> | |||
| #include <unistd.h> | |||
| #include <fcntl.h> | |||
| @@ -171,6 +175,16 @@ namespace Jack | |||
| { | |||
| return bind(fSockfd, reinterpret_cast<socket_address_t*>(&fRecvAddr), sizeof(socket_address_t)); | |||
| } | |||
| int JackNetUnixSocket::Bind(const char *if_name) | |||
| { | |||
| struct ip_mreq multicast_req; | |||
| int ret = Bind(); | |||
| if(!ret && strcmp(if_name,"any")) { | |||
| multicast_req.imr_multiaddr.s_addr = fSendAddr.sin_addr.s_addr; | |||
| ret = BindMCastIface(if_name, IP_MULTICAST_IF, &multicast_req); | |||
| } | |||
| return ret; | |||
| } | |||
| int JackNetUnixSocket::BindWith(const char* ip) | |||
| { | |||
| @@ -267,11 +281,53 @@ namespace Jack | |||
| } | |||
| int JackNetUnixSocket::JoinMCastGroup(const char* ip) | |||
| { | |||
| return JoinMCastGroup(ip,"any"); | |||
| } | |||
| int JackNetUnixSocket::JoinMCastGroup(const char* ip, const char *if_name) | |||
| { | |||
| struct ip_mreq multicast_req; | |||
| inet_aton(ip, &multicast_req.imr_multiaddr); | |||
| multicast_req.imr_interface.s_addr = htonl(INADDR_ANY); | |||
| return SetOption(IPPROTO_IP, IP_ADD_MEMBERSHIP, &multicast_req, sizeof(multicast_req)); | |||
| if(!strcmp(if_name,"any")) { | |||
| multicast_req.imr_interface.s_addr = htonl(INADDR_ANY); | |||
| return SetOption(IPPROTO_IP, IP_ADD_MEMBERSHIP, &multicast_req, sizeof(multicast_req)); | |||
| } else { | |||
| return BindMCastIface(if_name, IP_ADD_MEMBERSHIP, &multicast_req); | |||
| } | |||
| } | |||
| int JackNetUnixSocket::BindMCastIface(const char *if_name, const int option, struct ip_mreq *mreq) | |||
| { | |||
| struct ifaddrs *ifas, *ifa; | |||
| int specific = strcmp("all",if_name); | |||
| int ret=-1; | |||
| char *if_last="any"; | |||
| if (getifaddrs(&ifas) == -1) { | |||
| jack_error("JackNetUnixSocket::BindMCastIface error in getifaddrs"); | |||
| return -1; | |||
| } | |||
| for (ifa = ifas; ifa != NULL; ifa = ifa->ifa_next) { | |||
| if (ifa->ifa_addr == NULL) | |||
| continue; // Address is mandatory | |||
| if(!ifa->ifa_name || !strcmp(if_last,ifa->ifa_name)) | |||
| continue; // Name as well, also skip already enabled interface | |||
| if(!(ifa->ifa_flags & IFF_MULTICAST) || !(ifa->ifa_flags & IFF_RUNNING)) | |||
| continue; // And non multicast or down interface | |||
| if(ifa->ifa_addr->sa_family != AF_INET) | |||
| continue; // And for the moment we're dealing with IPv4 only | |||
| if(!specific || !strcmp(ifa->ifa_name,if_name)) { | |||
| mreq->imr_interface.s_addr = ((struct sockaddr_in *)(ifa->ifa_addr))->sin_addr.s_addr; | |||
| ret = SetOption(IPPROTO_IP, option, mreq, sizeof(struct ip_mreq)); | |||
| if(ret) | |||
| break; | |||
| if_last = ifa->ifa_name; | |||
| jack_log("JackNetUnixSocket::BindMCastIface attaching to %s", if_last); | |||
| } | |||
| } | |||
| freeifaddrs(ifas); | |||
| if(!strcmp(if_last,"any")) | |||
| jack_error("JackNetUnixSocket::BindMCastIface cannot find valid interface"); | |||
| return ret; | |||
| } | |||
| //options************************************************************************************************************ | |||
| @@ -468,6 +524,7 @@ namespace Jack | |||
| int JackNetUnixSocket::CatchHost(void* buffer, size_t nbytes, int flags) | |||
| { | |||
| jack_log("JackNetUnixSocket::CatchHost"); | |||
| socklen_t addr_len = sizeof(socket_address_t); | |||
| #if defined(__sun__) || defined(sun) | |||
| if (WaitRead() < 0) { | |||
| @@ -64,6 +64,7 @@ namespace Jack | |||
| //socket management | |||
| int NewSocket(); | |||
| int Bind(); | |||
| int Bind(const char *if_name); | |||
| int BindWith(const char* ip); | |||
| int BindWith(int port); | |||
| int Connect(); | |||
| @@ -84,6 +85,8 @@ namespace Jack | |||
| //utility | |||
| int GetName(char* name); | |||
| int JoinMCastGroup(const char* mcast_ip); | |||
| int JoinMCastGroup(const char* mcast_ip, const char* if_name); | |||
| int BindMCastIface(const char *if_name, const int option, struct ip_mreq *mreq); | |||
| //options management | |||
| int SetOption(int level, int optname, const void* optval, socklen_t optlen); | |||