/** * Send redirection event * * @v intf Data transfer interface * @v type New location type * @v args Remaining arguments depend upon location type * @ret rc Return status code */ int xfer_vredirect ( struct interface *intf, int type, va_list args ) { struct interface tmp = INTF_INIT ( null_intf_desc ); struct interface *dest; xfer_vredirect_TYPE ( void * ) *op = intf_get_dest_op_no_passthru ( intf, xfer_vredirect, &dest ); void *object = intf_object ( dest ); int rc; DBGC ( INTF_COL ( intf ), "INTF " INTF_INTF_FMT " redirect\n", INTF_INTF_DBG ( intf, dest ) ); if ( op ) { rc = op ( object, type, args ); } else { /* Default is to reopen the interface as instructed, * then send xfer_window_changed() messages to both * new child and parent interfaces. Since our * original child interface is likely to be closed and * unplugged as a result of the call to * xfer_vreopen(), we create a temporary interface in * order to be able to send xfer_window_changed() to * the parent. */ intf_plug ( &tmp, dest ); rc = xfer_vreopen ( dest, type, args ); if ( rc == 0 ) { xfer_window_changed ( dest ); xfer_window_changed ( &tmp ); } intf_unplug ( &tmp ); } if ( rc != 0 ) { DBGC ( INTF_COL ( intf ), "INTF " INTF_INTF_FMT " redirect " "failed: %s\n", INTF_INTF_DBG ( intf, dest ), strerror ( rc ) ); } intf_put ( dest ); return rc; }
/** * Unplug an object interface * * @v intf Object interface */ void intf_unplug ( struct interface *intf ) { intf_plug ( intf, &null_intf ); }
/** * Plug two object interfaces together * * @v a Object interface A * @v b Object interface B * * Plugs interface A into interface B, and interface B into interface * A. (The basic plug() function is unidirectional; this function is * merely a shorthand for two calls to plug(), hence the name.) */ void intf_plug_plug ( struct interface *a, struct interface *b ) { intf_plug ( a, b ); intf_plug ( b, a ); }