static void *remote_connect_sync_thread( void *data ) { net_response_t *response; net_ctx_t *ctx = NULL; char *remote_service_name = NULL; int shutdown_fd = 0; fd_set read_fds; struct timeval tv; int sync_interval = 0; logging_printf( LOGGING_DEBUG, "remote_connect_sync_thread: start\n"); logging_printf( LOGGING_DEBUG, "rmeote_connect_sync_thread: sync.interval=%s\n", config_string_get("sync.interval")); shutdown_fd = net_socket_get_shutdown_fd(); logging_printf( LOGGING_DEBUG, "remote_connect_sync_thread: shutdown_fd=%u\n", shutdown_fd ); remote_service_name = config_string_get("remote.connect"); sync_interval = config_int_get("sync.interval"); do { ctx = net_ctx_find_by_name( remote_service_name ); if( ! ctx ) { logging_printf( LOGGING_DEBUG, "remote_connect_sync_thread: No remote connection context\n"); break; } FD_ZERO( &read_fds ); FD_SET( shutdown_fd, &read_fds ); memset( &tv, 0, sizeof( struct timeval ) ); tv.tv_sec = sync_interval; select( shutdown_fd + 1, &read_fds, NULL , NULL, &tv ); logging_printf( LOGGING_DEBUG, "remote_connect_sync_thread: select()=\"%s\"\n", strerror( errno ) ); if( net_socket_get_shutdown_lock() == 1 ) { logging_printf(LOGGING_DEBUG, "remote_connect_sync_thread: shutdown received during poll\n"); break; } response = net_response_sync( ctx->send_ssrc , ctx->start ); net_ctx_send( ctx, response->buffer, response->len, USE_CONTROL_PORT ); hex_dump( response->buffer, response->len ); net_response_destroy( &response ); } while( 1 ); if( net_socket_get_shutdown_lock() == 1 ) { logging_printf(LOGGING_DEBUG, "remote_connect_sync_thread: shutdown received\n"); } logging_printf( LOGGING_DEBUG, "remote_connect_sync_thread: stop\n"); return NULL; }
void remote_connect_init( void ) { dns_service_t *found_service = NULL; char *remote_service_name = NULL; char *client_name = NULL; net_response_t *response = NULL; net_ctx_t *ctx; int use_ipv4, use_ipv6; uint32_t initiator = 0, ssrc = 0; char *p1 = NULL; char *p2 = NULL; int remote_port_number = 0; if( ! config_is_set( "remote.connect" ) ) { logging_printf(LOGGING_WARN, "remote_connect_init: Called with no remote.connect value\n"); return; } remote_service_name = (char *) strdup( config_string_get("remote.connect") ); logging_printf(LOGGING_DEBUG, "remote_connect_init: Looking for [%s]\n", remote_service_name); p1 = remote_service_name; p2 = p1 + strlen( remote_service_name ); /* Work backwards to find a colon ':' */ /* If a ']' character is found first, we'll assume this is going to be an direct connect address */ while( p2 > p1 ) { if( *p2 == ']' ) break; if( *p2 == ':' ) break; p2--; } /* If no colon ':' or ']' was found, we'll assume this is a service name to be located */ if( p2 == p1 ) { use_ipv4 = is_yes( config_string_get("service.ipv4") ) ; use_ipv6 = is_yes( config_string_get("service.ipv6") ) ; if( dns_discover_services( use_ipv4, use_ipv6 ) <= 0 ) { logging_printf(LOGGING_WARN, "remote_connect_init: No services available\n"); free( remote_service_name ); return; } found_service = dns_discover_by_name( remote_service_name ); goto make_remote_connection; } else { /* If there is a colon ':', split the string to determine the port number */ if( *p2 == ':' ) { *p2='\0'; p2++; remote_port_number = atoi( p2 ); p2 = remote_service_name + strlen( remote_service_name ) - 1; } /* If there is a ']', work forwards from the start of the string to remove the '[' */ if ( *p2 == ']' ) { *p2='\0'; while( p1 < p2 ) { if( *p1 == '[' ) break; p1++; } } if( p1 == p2 ) { p1 = remote_service_name; } else { *p1='\0'; p1++; } if( remote_port_number == 0 ) { logging_printf( LOGGING_ERROR, "remote_connect_init: No port number specified\n"); free( remote_service_name ); return; } logging_printf( LOGGING_DEBUG, "remote_connect_init: connect_string=>%s<\n", config_string_get("remote.connect") ); logging_printf( LOGGING_DEBUG, "remote_connect_init: connect_address=>%s<, connect_port=%d\n", p1, remote_port_number ); dns_discover_add( config_string_get("remote.connect"), p1, remote_port_number ); found_service = dns_discover_by_name( config_string_get("remote.connect") ); } make_remote_connection: free( remote_service_name ); if( ! found_service ) { logging_printf(LOGGING_WARN, "remote_connect_init: No service found: %s\n", remote_service_name ); return; } logging_printf( LOGGING_DEBUG, "remote_connect_init: Found name=\"%s\" address=[%s]:%d\n", found_service->name, found_service->ip_address, found_service->port); ssrc = random_number(); initiator = random_number(); client_name = config_string_get("service.name"); if( !client_name ) { client_name = "RaveloxMIDIClient"; } response = net_response_inv( ssrc, initiator, client_name ); if( response ) { ctx = net_ctx_register( ssrc, initiator, found_service->ip_address, found_service->port, found_service->name ); if( ! ctx ) { logging_printf( LOGGING_ERROR, "remote_connect_init: Unable to create socket context\n"); } else { ctx->send_ssrc = ssrc; ctx->status = NET_CTX_STATUS_FIRST_INV; logging_printf( LOGGING_DEBUG, "remote_connect_init: Sending INV request to [%s]:%d\n", ctx->ip_address, ctx->control_port ); net_ctx_send( ctx, response->buffer, response->len , USE_CONTROL_PORT ); } } net_response_destroy( &response ); }
void remote_connect_teardown( void ) { net_applemidi_inv *by = NULL; net_response_t *response = NULL; net_applemidi_command *cmd = NULL; char *remote_service_name = NULL; net_ctx_t *ctx; remote_service_name = config_string_get("remote.connect"); logging_printf( LOGGING_DEBUG, "remote_connect_teardown: Disconnecting from [%s]\n", remote_service_name); remote_connect_wait_for_thread(); ctx = net_ctx_find_by_name( remote_service_name ); if( ! ctx ) { logging_printf( LOGGING_ERROR, "remote_connect_teardown: Unable to find connection for [%s]\n", remote_service_name); return; }; // Build the BY packet by = net_applemidi_inv_create(); if( ! by ) { logging_printf( LOGGING_ERROR, "remote_connect_teardown: Unable to allocate memory for by packet\n"); return; } by->ssrc = ctx->send_ssrc; by->version = 2; by->initiator = ctx->initiator; cmd = net_applemidi_cmd_create( NET_APPLEMIDI_CMD_END ); if( ! cmd ) { logging_printf( LOGGING_ERROR, "remote_connect_teardown: Unable to create AppleMIDI command\n"); net_applemidi_inv_destroy( &by ); goto remote_teardown_fail; } cmd->data = by; response = net_response_create(); if( response ) { int ret = 0; ret = net_applemidi_pack( cmd , &(response->buffer), &(response->len) ); if( ret != 0 ) { logging_printf( LOGGING_ERROR, "remote_connect_teardown: Unable to pack response to by command\n"); } else { net_ctx_send( ctx, response->buffer, response->len , USE_CONTROL_PORT); hex_dump( response->buffer, response->len ); } } else { logging_printf( LOGGING_ERROR, "remote_connect_teardown: Unable to create response packet\n"); } remote_teardown_fail: net_response_destroy( &response ); net_applemidi_cmd_destroy( &cmd ); }
net_response_t * cmd_inv_handler( char *ip_address, uint16_t port, void *data ) { net_applemidi_command *cmd = NULL; net_applemidi_inv *inv = NULL; net_applemidi_inv *accept_inv = NULL; net_ctx_t *ctx = NULL; net_response_t *response; char *service_name = NULL; if( ! data ) return NULL; inv = ( net_applemidi_inv *) data; logging_printf( LOGGING_DEBUG, "INV(%s:%u\n ", ip_address, port ); logging_printf( LOGGING_DEBUG, "\tname=%s\n", inv->name); logging_printf( LOGGING_DEBUG, "\tssrc=0x%08x\n", inv->ssrc); logging_printf( LOGGING_DEBUG, "\tversion=0x%08x\n", inv->version); logging_printf( LOGGING_DEBUG, "\tinitiator=0x%08x )\n", inv->initiator); ctx = net_ctx_find_by_ssrc( inv->ssrc ); if( ! ctx ) { logging_printf( LOGGING_DEBUG, "cmd_inv_hander: Registering new connection\n"); ctx = net_ctx_register( inv->ssrc, inv->initiator, ip_address, port ); if( ! ctx ) { logging_printf( LOGGING_ERROR, "cmd_inv_handler: Error registering connection\n"); } } cmd = new_net_applemidi_command( NET_APPLEMIDI_CMD_ACCEPT ); if( ! cmd ) { logging_printf( LOGGING_ERROR, "Unable to allocate memory for accept_inv command\n"); net_ctx_reset( ctx ); return NULL; } accept_inv = new_net_applemidi_inv(); if( ! accept_inv ) { logging_printf( LOGGING_ERROR, "Unabled to allocate memory for accept_inv command data\n"); free( cmd ); net_ctx_reset( ctx ); return NULL; } accept_inv->ssrc = ctx->send_ssrc; accept_inv->version = 2; accept_inv->initiator = ctx->initiator; service_name = config_get("service.name"); if( service_name ) { accept_inv->name = (char *)strdup( service_name ); } else { accept_inv->name = (char *)strdup( "RaveloxMIDI" ); } cmd->data = accept_inv; response = new_net_response(); if( response ) { int ret = 0; ret = net_applemidi_pack( cmd , &(response->buffer), &(response->len) ); if( ret != 0 ) { logging_printf( LOGGING_ERROR, "Unable to pack response to inv command\n"); net_response_destroy( &response ); } } net_applemidi_cmd_destroy( &cmd ); return response; }