Thread: [INC] HTTP2
View Single Post
Black Rose
Veteran Member
Join Date: Feb 2011
Location: Upplands Väsby, Sweden
Old 09-14-2013 , 16:01   Re: [INC] HTTP2
Reply With Quote #22

I was experimenting a little with new functions for HTTP2.
This enables you to download and install modules that is required for your plugin automatically. This only works for natives, if the inc has stocks which you are using it will not work since they are written into the plugin when you compile it.

I'm not sure I'll add this feature to HTTP2. The whole point is to exclude the use of includes and pre-installation of modules.

The point of defining the used natives if there's no include is that you could compile it with the AMXX webcompiler and it will still run. So if you're using this you'll have to copy/paste the neccessary native lines from the inc file. You only need the ones you use in your plugins, you can skip the rest.

library and name are not just made up or guesses. They are defined in the moduleconfig.h as (for example):
#define MODULE_NAME "Test"
#define MODULE_LIBRARY "test"

The only problem I've faced is that you can not restart the server using server_cmd("restart") at the point of plugin_natives(). So you'll have to wait for a mapchange/restart/crash.

What you should know: This does not work with zipped files because AMXX is unable to unpack them without the use of a module. If you want to use this you'll just have to whine to the module author to attach the binary separately.

Method #1, automatic library loading (if the module supports it):
#include <amxmodx> #include <http2> #tryinclude <test> #if !defined _test_included native testfunc(num); #endif #if AMXX_VERSION_NUM >= 175     #pragma reqlib test     #if !defined AMXMODX_NOAUTOLOAD         #pragma loadlib test     #endif #else     #pragma library test #endif public plugin_init() {     register_plugin("Test Plugin 7","","");     server_print("Testfunc: %d", testfunc(9)); } public plugin_natives() {     RequireModule("Test", "test", ""); }

Method #2, library not defined in moduleconfig.h. We'll have to force loading.:
#include <amxmodx> #include <http2> #tryinclude <test> #if !defined _test_included native testfunc(num); #endif public plugin_init() {     register_plugin("Test Plugin 7","","");     server_print("Testfunc: %d", testfunc(9)); } public plugin_natives() {     RequireModule("Test", "test", "", "", true); }

The function (_HTTP2_ParseHeader() and _HTTP2_ParseURL() can be found in HTTP2 inc):
/* name[] is the name of the loaded module, to prevent it from downloading again. filename[] is the filename without "" or "_amxx.dll". windows_binary[] is the URL to the .dll version, while linux_binary[] is the same for linux. WriteModulesToIni tells the function to write the downloaded module to modules.ini. If the module doesn't support automatic loading, this is required. */ stock RequireModule(name[], filename[], windows_binary[] = "", linux_binary[] = "", bool:WriteToModulesIni = false, Port = 80) {         new module_name[32], module_author[32], module_version[10], module_status;     new modulesnum = get_modulesnum();         for ( new i = 0 ; i < modulesnum ; i++ ) {         get_module(i, module_name, charsmax(module_name), module_author, charsmax(module_author), module_version, charsmax(module_version), module_status);                 if ( equali(module_name, name) )             return 0;     }         new linux = is_linux_server();         if ( ( ! linux && ! strlen(windows_binary) ) || ( linux && ! strlen(linux_binary) ) ) {         server_print("[HTTP2] Invalid binary specified for this type of server");         return -1     }         new file_location[192];     new len = get_localinfo("amxx_modulesdir", file_location, charsmax(file_location));     formatex(file_location[len], charsmax(file_location) - len, "/%s%s", filename, linux ? "" : "_amxx.dll");         if ( file_exists(file_location) ) {         server_print("[HTTP2] The file ^"%s^" already exists", file_location);         return -1;     }         new URL2[256];     new hFile, bool:SSL, PathPos = _HTTP2_ParseURL(linux ? linux_binary : windows_binary, URL2, charsmax(URL2), SSL, Port);         if ( ! ( hFile = fopen(file_location, "wb") ) ) {         server_print("[HTTP2] Error creating local file.");         return -1;     }         new ResultNum;     new hSocket = socket_open(URL2, Port, SOCKET_TCP, ResultNum);         if ( ResultNum ) {         switch ( ResultNum ) {             case 1: server_print("[HTTP2] Socket error: Error while creating socket.");             case 2: server_print("[HTTP2] Socket error: Couldn't resolve hostname.");             case 3: server_print("[HTTP2] Socket error: Couldn't connect to given hostname:port.");         }         return -1;     }         if ( PathPos <= 0 )         PathPos = strlen(URL2);             new Request[300];     new RequestLen = formatex(Request, charsmax(Request), "GET /%s HTTP/1.1^r^nHost: %s^r^n^r^n", URL2[PathPos], URL2);         socket_send(hSocket, Request, RequestLen);         new BytesReceived, BufferLen, FileSize, bool:Dummy = true, Status = _HTTP2_STATUS_FIRSTRUN;         while ( Dummy ) {         if ( ! socket_change(hSocket, 1000) )             continue;                 if ( ! ( BufferLen = socket_recv(hSocket, _gHTTP2_DataBuffer, 1024) ) ) {             server_print("[HTTP2] No data received.");             return -1;         }                 if ( Status & _HTTP2_STATUS_FIRSTRUN ) {             Status &= ~_HTTP2_STATUS_FIRSTRUN;                         new _HTTP2_ReturnCodeExtended[32], _HTTP2_Location[128];             new ReturnCode;                         BufferLen -= _HTTP2_ParseHeader(_gHTTP2_DataBuffer, BufferLen, FileSize, Status, ReturnCode, _HTTP2_ReturnCodeExtended, _HTTP2_Location);                         if ( ReturnCode != 200 ) {                 server_print("[HTTP2] Bad return code: %d.", ReturnCode);                 return -1;             }         }                 BytesReceived += fwrite_blocks(hFile, _gHTTP2_DataBuffer, BufferLen, BLOCK_BYTE)                 if ( BytesReceived == FileSize )             break;     }         socket_close(hSocket);     fclose(hFile);         if ( WriteToModulesIni ) {         get_localinfo("amxx_modules", file_location,charsmax(file_location));         hFile = fopen(file_location, "a");         fputs(hFile, "^r^n");         fputs(hFile, filename);         fclose(hFile);     }         return 1; }

Here's a result using method #1:
Run #1:
L 09/14/2013 - 21:04:34: [AMXX] Plugin "test7.amxx" failed to load: Module/Libra
ry "test" required for plugin.  Check modules.ini.
Run #2:
Testfunc: 27

As always, use it however you like. Copy it, modify it, create your version based on it. No need for credit.

The source code of the module in the example is useless but can be found here.

Last edited by Black Rose; 02-15-2014 at 18:29.
Black Rose is offline
Send a message via Skype™ to Black Rose