Raised This Month: $12 Target: $400
 3% 

Throw error in calling plugin if call origin is a native


Post New Thread Reply   
 
Thread Tools Display Modes
Author Message
rhelgeby
Veteran Member
Join Date: Oct 2008
Location: 0x4E6F72776179
Old 10-26-2014 , 14:47   Throw error in calling plugin if call origin is a native
Reply With Quote #1

I'm aware of both ThrowError and ThrowNativeError, but I need a universal function that will throw a native error if the call origin is from a native that I've implemented.

The reason for this is to keep the code that validates and throws errors close to the logic, but I want to avoid duplicated validation code in the native callback and internal code.

If the caller is another plugin, I simply want the error to bubble up to that plugin. If I called the function myself from within the plugin (from anything else than a native callback), it's my fault if something is not valid and my plugin should get the error.

Is this possible?
__________________
Richard Helgeby

Zombie:Reloaded | PawnUnit | Object Library
(Please don't send private messages for support, they will be ignored. Use the forum.)
rhelgeby is offline
Send a message via MSN to rhelgeby
Dr. Greg House
Professional Troll,
Part-Time Asshole
Join Date: Jun 2010
Old 10-26-2014 , 14:57   Re: Throw error in calling plugin if call origin is a native
Reply With Quote #2

Can't you safely verify the params first?
__________________
Santa or Satan?

Watch out when you're paying people for private requests! Most stuff already exists and you can hardly assess the quality of what you'll get, and if it's worth the money.
Dr. Greg House is offline
rhelgeby
Veteran Member
Join Date: Oct 2008
Location: 0x4E6F72776179
Old 10-26-2014 , 16:51   Re: Throw error in calling plugin if call origin is a native
Reply With Quote #3

I do, but third party plugins still may pass invalid parameters to my native. I don't want do duplicate validation logic in the native and in my "service" functions.
__________________
Richard Helgeby

Zombie:Reloaded | PawnUnit | Object Library
(Please don't send private messages for support, they will be ignored. Use the forum.)
rhelgeby is offline
Send a message via MSN to rhelgeby
Powerlord
AlliedModders Donor
Join Date: Jun 2008
Location: Seduce Me!
Old 10-26-2014 , 17:32   Re: Throw error in calling plugin if call origin is a native
Reply With Quote #4

Unfortunately, I'm not aware of one. I've done tests in the past and ThrowNativeError will bomb out with an error (something like "not called from a native") if you call it from something other than a native.
__________________
Not currently working on SourceMod plugin development.
Powerlord is offline
rhelgeby
Veteran Member
Join Date: Oct 2008
Location: 0x4E6F72776179
Old 10-26-2014 , 18:13   Re: Throw error in calling plugin if call origin is a native
Reply With Quote #5

Yes, I discovered that myself. A combination would be useful, where it would just fall back to ThrowError if it's not in a native call.
__________________
Richard Helgeby

Zombie:Reloaded | PawnUnit | Object Library
(Please don't send private messages for support, they will be ignored. Use the forum.)
rhelgeby is offline
Send a message via MSN to rhelgeby
Dr. Greg House
Professional Troll,
Part-Time Asshole
Join Date: Jun 2010
Old 10-26-2014 , 20:37   Re: Throw error in calling plugin if call origin is a native
Reply With Quote #6

Quote:
Originally Posted by rhelgeby View Post
I do, but third party plugins still may pass invalid parameters to my native. I don't want do duplicate validation logic in the native and in my "service" functions.
I don't understand. You should do the verification inside the native. Not inside the plugin that calls it.
__________________
Santa or Satan?

Watch out when you're paying people for private requests! Most stuff already exists and you can hardly assess the quality of what you'll get, and if it's worth the money.
Dr. Greg House is offline
rhelgeby
Veteran Member
Join Date: Oct 2008
Location: 0x4E6F72776179
Old 10-27-2014 , 12:44   Re: Throw error in calling plugin if call origin is a native
Reply With Quote #7

No, that's not how I do it. The native simply delegates work to my "service" layer that will do it's own validation. If I add validation logic in the native handler, it will be duplicated.
__________________
Richard Helgeby

Zombie:Reloaded | PawnUnit | Object Library
(Please don't send private messages for support, they will be ignored. Use the forum.)
rhelgeby is offline
Send a message via MSN to rhelgeby
Greyscale
SourceMod Plugin Approver
Join Date: Dec 2007
Location: strYoMommasHouse[you];
Old 10-27-2014 , 17:12   Re: Throw error in calling plugin if call origin is a native
Reply With Quote #8

Validation only need be done in the external API (because it's not guaranteed that your consumers will provide valid inputs). The internal implementation shouldn't need validation as all its usages are known.

Oh and hey how's it goin?
__________________
Greyscale is offline
Powerlord
AlliedModders Donor
Join Date: Jun 2008
Location: Seduce Me!
Old 10-27-2014 , 21:10   Re: Throw error in calling plugin if call origin is a native
Reply With Quote #9

Quote:
Originally Posted by Greyscale View Post
Validation only need be done in the external API (because it's not guaranteed that your consumers will provide valid inputs). The internal implementation shouldn't need validation as all its usages are known.

Oh and hey how's it goin?
You should probably also do validation in any stocks you plan on distributing to the public.
__________________
Not currently working on SourceMod plugin development.
Powerlord is offline
rhelgeby
Veteran Member
Join Date: Oct 2008
Location: 0x4E6F72776179
Old 10-28-2014 , 08:15   Re: Throw error in calling plugin if call origin is a native
Reply With Quote #10

I should have provided some examples earlier. Here's a real case:

Consider this native handler:
PHP Code:
/**
 * Creates a new module. The new module is bound to the calling plugin.
 *
 * Warning: You must call ZM_DeleteModule when the module is no longer in use,
 *          such as in OnPluginEnd. Otherwise the module manager will never know
 *          when the module is removed.
 *
 * Note: A plugin is only allowed to create one module. The module will remain
 *       registered until the plugin is unloaded.
 *
 * @param name          Unique module name. Used by lookup functions.
 *
 * @return              Module ID.
 * @error               Plugin has already created a module, name is already in
 *                      use or name is empty.
 */
//native ZMModule:ZM_CreateModule(const String:name[]);
public API_CreateModule(Handle:pluginnumParams)
{
    new 
String:name[MODULE_STRING_LEN];
    
GetNativeString(1namesizeof(name));
    
    if (!
AssertPluginHasNoModule(plugin)
        || !
AssertModuleNameNotExists(name))
    {
        return 
0;
    }
    
    new 
ZMModule:module AddModule(pluginname);
    return 
_:module;

Look at how clean it is. I do as little as possible there. I'm just fetching parameters and delegating the work to another function. The asserts should probably be moved down to the service layer.

Here's AddModule:
PHP Code:
ZMModule:AddModule(Handle:ownerPlugin, const String:moduleName[])
{
    new 
ZMModule:module CreateModule(ownerPluginmoduleName);
    
    
AddModuleToList(module);
    
AddModuleToIndex(module);
    
    return 
module;

AddModule belongs to the service layer. It doesn't create the module itself, but it adds it to an index so the plugin know which modules are available.

And here's CreateModule:
PHP Code:
ZMModule:CreateModule(Handle:plugin, const String:name[])
{
    if (
plugin == INVALID_HANDLE)
    {
        
ThrowNativeError(SP_ERROR_ABORTED"Plugin not specified.");
    }
    
    if (
PluginHasModule(plugin))
    {
        
ThrowNativeError(SP_ERROR_ABORTED"A module for this plugin already exists. Only one module per plugin is allowed.");
    }
    
    if (
strlen(name) == 0)
    {
        
ThrowNativeError(SP_ERROR_ABORTED"Name is empty.");
    }
    
    
InitModuleType();
    
    new 
Object:module ObjLib_CreateObject(ModuleType);
    
ObjLib_SetHandle(module"plugin"plugin);
    
ObjLib_SetString(module"name"name);
    
    
LogMessage("Created module: \"%s\" (%x)"namemodule);
    
    return 
ZMModule:module;

CreateModule belongs to the domain layer. This layer should be as isolated as possible and it do its own validation. This architecture is based on a rich domain model where domain objects (modules in this case) are smart and doesn't just contain data.

This is where my problem is, since it's used by natives I'm forced to use ThrowNativeError. What I'm looking for is a combination of ThrowError and ThrowNativeError. I don't see any technical limitations of this, since SourceMod tells me if the call does not come from a native handler. SourceMod could instead just fall back to ThrowError, or provide an additional native that does so.

Here's the complete code for those who are interested: https://github.com/rhelgeby/sm-zombiereloaded
__________________
Richard Helgeby

Zombie:Reloaded | PawnUnit | Object Library
(Please don't send private messages for support, they will be ignored. Use the forum.)

Last edited by rhelgeby; 10-29-2014 at 18:39.
rhelgeby is offline
Send a message via MSN to rhelgeby
Reply


Thread Tools
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off

Forum Jump


All times are GMT -4. The time now is 22:10.


Powered by vBulletin®
Copyright ©2000 - 2024, vBulletin Solutions, Inc.
Theme made by Freecode