diff --git a/modules/modperl.cpp b/modules/modperl.cpp index 0f00975d..93052077 100644 --- a/modules/modperl.cpp +++ b/modules/modperl.cpp @@ -685,7 +685,7 @@ XS(XS_ZNC_GetString) XS(XS_ZNC_WriteSock) { dXSARGS; - if ( items <= 1 ) + if ( items != 3 ) Perl_croak( aTHX_ "Usage: ZNC::WriteSock( sockhandle, bytes, len )" ); SP -= items; @@ -710,6 +710,27 @@ XS(XS_ZNC_WriteSock) } } +XS(XS_ZNC_CloseSock) +{ + dXSARGS; + if ( items != 1 ) + Perl_croak( aTHX_ "Usage: ZNC::CloseSock( sockhandle )" ); + + SP -= items; + ax = (SP - PL_stack_base) + 1 ; + { + if ( g_ModPerl ) + { + PString sReturn = false; + int iSockFD = SvIV(ST(0)); + CPerlSock *pSock = (CPerlSock *)MANAGER->FindSockByFD( iSockFD ); + if ( ( pSock ) && ( pSock->GetSockName() == ZNCSOCK ) ) + pSock->Close(); + } + PUTBACK; + } +} + XS(XS_ZNC_COREConnect) { dXSARGS; @@ -908,6 +929,7 @@ bool CModPerl::OnLoad( const CString & sArgs ) newXS( "ZNC::LoadMod", XS_ZNC_LoadMod, (char *)file ); newXS( "ZNC::UnLoadMod", XS_ZNC_UnLoadMod, (char *)file ); newXS( "ZNC::WriteSock", XS_ZNC_WriteSock, (char *)file ); + newXS( "ZNC::CloseSock", XS_ZNC_CloseSock, (char *)file ); // this sets up the eval CB that we call from here on out. this way we can grab the error produced SetupZNCScript(); diff --git a/modules/modperl.pm b/modules/modperl.pm index 2596db51..1f198eef 100644 --- a/modules/modperl.pm +++ b/modules/modperl.pm @@ -1,8 +1,4 @@ -# my $sockhandle = ZNC::ListenSock( $port, $bindhostname, $enablereadline ) -# my $sockhandle = ZNC::ListenSockSSL( $port, $bindhostname, $enablereadline ) -# -# store the sockhandle in their class, before every action call 'TestSock', if its true then call the event -# otherwise close the socket +# TODO need Close() package ZNC; use strict; @@ -15,10 +11,6 @@ sub COREEval eval $arg; } -sub COREShutdown() -{ - -} sub CORECallFunc { my ( $Username, $Func, @args ) = @_; @@ -129,6 +121,7 @@ sub CORELoadMod $obj->{ZNC_Username} = $Username; $obj->{ZNC_Name} = $Module; $obj->{ZNC_ModPath} = $FileName; + @{$obj->{socks}} = (); push( @MODS, $obj ); ZNC::PutModule( "Loaded $Module" ); @@ -177,21 +170,49 @@ sub CORECallTimer sub CORECallSock { - my ( $Username, $Func, $ModName, @args ) = @_; + my ( $Username, $Func, $ModName, $fd, @args ) = @_; for( my $i = 0; $i < @MODS; $i++ ) { if ( ( $MODS[$i]->{ZNC_Username} eq $Username ) && ( $MODS[$i]->{ZNC_Name} eq $ModName ) ) { - if ( $MODS[$i]->can( $Func ) ) + my @socks = @{$MODS[$i]->{socks}}; + + ######### Sock methods are in the module directly + if ( @socks == 0 ) + { # ok, try simple manner, overloads in this here class + if ( $MODS[$i]->can( $Func ) ) + { + my $ret = $MODS[$i]->$Func( $fd, @args ); + if ( $Func eq "OnConnectionFrom" ) + { # special case this for now, requires a return value + return( $ret ); + } + } + return( CONTINUE() ); + } + + ########## they sent us a socket to look at, we'll use it + for( my $a = 0; $a < @socks; $a++ ) { - my $ret = $MODS[$i]->$Func( @args ); - if ( $Func eq "OnConnectionFrom" ) - { # special case this for now, requires a return value - return( $ret ); + if ( $socks[$a]->{fd} == $fd ) + { + if ( $socks[$a]->can( $Func ) ) + { + my $ret = $socks[$a]->$Func( @args ); + if ( $Func eq "OnConnectionFrom" ) + { # special case this for now, requires a return value + return( $ret ); + } + elsif ( $Func eq "OnSockDestroy" ) + { + splice( @{$MODS[$i]->{socks}}, $a ); + } + } + return( CONTINUE() ); } } - return( CONTINUE() ); + last; #no point in checking further } } return( HALTMODS() ); @@ -268,8 +289,6 @@ sub PutTarget PutIRC( "PRIVMSG $target :$line" ); } - - sub Connect { my ( $obj, $host, $port, $timeout, $bEnableReadline, $bUseSSL ) = @_; @@ -339,8 +358,54 @@ sub ListenSSL 1; - - +###################### +## use this if you really want to have fun. be sure you don't leave a reference to the +## handle laying around! ZNC will deal with that inside your module, so its properly closed +package ZNCSocket; + +sub new +{ + my ( $classname, $modobj ) = @_; + + my $self = + { + modobj => $modobj, + fd => -1 + }; + + bless( $self, $classname ); + + push( @{$modobj->{socks}}, $self ); + return( $self ); +} + +sub Connect +{ + my ( $me, $host, $port, $timeout, $bEnableReadline, $bUseSSL ) = @_; + $me->{fd} = ZNC::Connect( $me->{modobj}, $host, $port, $timeout, $bEnableReadline, $bUseSSL ); + return( $me->{fd} ); +} + +sub ConnectSSL +{ + my ( $me, $host, $port, $timeout, $bEnableReadline ) = @_; + $me->{fd} = ZNC::ConnectSSL( $me->{modobj}, $host, $port, $timeout, $bEnableReadline ); + return( $me->{fd} ); +} + +sub Write +{ + my ( $me, $data ) = @_; + return( ZNC::WriteSock( $me->{fd}, $data, length( $data ) ) ); +} + +sub Close +{ + my ( $me ) = @_; + ZNC::CloseSock( $me->{fd} ); +} + +1;