Veteran Member
Join Date: Feb 2011
Location: Stockholm, Sweden
|
08-18-2013
, 08:34
[INC] HTTP2
|
#1
|
Please use HTTP:X instead.
Spoiler
HTTP2
Thank you Bugsy for HTTP v0.4 which this obviously is based on.
This started like a small project to debug and enhance the functions of HTTP v0.4 and ended up in something bigger.
It has now been deprecated and replaced by HTTP:X.
List of functions:
Functions
Code:
/*
* HTTP2
* v2.40
* By [ --{-@ ] Black Rose
*
* Based on HTTP v0.4 by Bugsy
*/
#define HTTP2_MAX_DOWNLOAD_SLOTS 4
#define HTTP2_BUFFER_SIZE 32768
#define HTTP2_THINK_INTERVAL 0.01
#define HTTP2_QUE_INTERVAL 1.0
#define REQUEST_GET 0
#define REQUEST_POST 1
/*
* HTTP2_isFilesizeLarge(Index)
*
* If the filesize in bytes is beyond the limitations of integers the function will return true.
*/
stock bool:HTTP2_isFilesizeLarge(Index)
/*
* HTTP2_getBytesReceived(Index)
*
* Returns total ammount of bytes received for Index.
*/
stock HTTP2_getBytesReceived(Index)
/*
* HTTP2_getBytesReceivedLarge(Index, string[], len)
*
* Formats total ammount of bytes received for Index in string form.
*/
stock HTTP2_getBytesReceivedLarge(Index, string[], len)
/*
* HTTP2_getNewBytesReceived()
*
* Returns the ammount of bytes that was received in this chunk.
*/
stock HTTP2_getNewBytesReceived()
/*
* HTTP2_getFilesize(Index)
*
* Returns the filesize of Index.
* If unknown it will return -1.
*/
stock HTTP2_getFilesize(Index)
/*
* HTTP2_getFilesizeLarge(Index, string[], len)
*
* Formats the large filesize of Index in string form.
*/
stock HTTP2_getFilesizeLarge(Index, string[], len)
/*
* HTTP2_getFilename(Index)
*
* Returns the filename of Index.
*/
stock HTTP2_getFilename(Index, name[], len)
/*
* HTTP2_getData(Data[], len, &datalen)
*
* Fills variable Data[] with the last chunk downloaded.
* len decides the maximum size of Data[].
* datalen will return the ammount of bytes that was received in this chunk.
*
* For performance reasons HTTP2_getData2() should be used whenever possible.
*/
stock HTTP2_getData(Dest[], len, &datalen)
/*
* HTTP2_getDataUnsafe()
* HTTP2_getData2()
*
* This is a direct connection to the data buffer.
* This will be faster because you don't need to spend time copying data between 2 buffers just to read it.
*
* Since the forward is called after the data has been written you don't need to worry about corrupting it.
* So it's not really unsafe.
*/
#define HTTP2_getDataUnsafe() _gHTTP2_DataBuffer
#define HTTP2_getData2() _gHTTP2_DataBuffer
/*
* HTTP2_UpdatePlugin(const URL[])
*
* Updates current plugin with binary from chosen URL.
*/
stock HTTP2_UpdatePlugin(const URL[])
/*
* HTTP2_Abort(Index, bool:DeleteFile = true)
*
* Aborts the transfer of selected download index.
* If DeleteFile is set to true the partially downloaded file will be deleted.
*/
stock HTTP2_Abort(Index, bool:DeleteFile = true)
/*
* HTTP2_AddPostVar(const variable[], const value[])
*
* Adds a POST variable to the header.
* This function is used before HTTP2_Download() or HTTP2_AddToQue(), similar to set/show hudmessage.
* It can be used multiple times before each download.
*/
stock HTTP2_AddPostVar(const variable[], const value[])
/*
* HTTP2_Download(const URL[], const Filename[] = "", const CompleteHandler[] = "", const ProgressHandler[] = "", Port = (80<<443), RequestType = REQUEST_GET, const Username[] = "", const Password[] = "", ...)
*
* Begins download of a URL. Read parameters for information.
*
*
* Parameters:
*
* const URL[]
* URL that you want to download.
*
* (Optional) const Filename[]
* Where should the information be stored? If no filename is entered it will download as a "stream".
* This means the data will be thrown away after it passes the buffer.
* You can read the data on progress forward and make use of it there.
*
* (Optional) const CompleteHandler[] = ""
* The function you want called when the download is complete.
*
* (Optional) const ProgressHandler[] = ""
* The function you want called when the download is in progress.
* This will be called every downloaded chunk
*
* (Optional) Port = (80<<443)
* The port that should be used.
* If this is left at default it will use 80 for http.
*
* (Optional) RequestType = REQUEST_GET
* What type of request should be used.
* If this is left at default it will use GET.
* Possible values so far are REQUEST_GET and REQUEST_POST.
*
* (Optional) const Username[] = ""
* (Optional) const Password[] = ""
* These are used to login to sites that require you to.
* It's only used for Basic authentication, not POST for example.
*
* Returns an index of the download that may be used to abort the download.
*/
stock HTTP2_Download(const URL[], const Filename[] = "", const CompleteHandler[] = "", const ProgressHandler[] = "", Port = (80<<443), RequestType = REQUEST_GET, const Username[] = "", const Password[] = "", ... /* For possible future use */)
/*
* HTTP2_AddToQue(const URL[], const Filename[] = "", const CompleteHandler[] = "", const ProgressHandler[] = "", Port = (80<<443), RequestType = REQUEST_GET, const Username[] = "", const Password[] = "", ...)
*
* Ques up an item to be downloaded. Formatted exactly like HTTP2_Download().
* Use this when you're looping through a lot of downloads to avoid filling up the download slots.
* This function will not generate a direct error. The errors will occur at HTTP2_Download().
*
* Returns position in que.
*/
stock HTTP2_AddToQue(const URL[], const Filename[] = "", const CompleteHandler[] = "", const ProgressHandler[] = "", Port = (80<<443), RequestType = REQUEST_GET, const Username[] = "", const Password[] = "", ... /* For possible future use */)
/*
* Number of parameters for the callbacks are 1 (Index) for the progress event and 2 (Index, Error) for the complete event.
* Error codes:
* 0 Download done. No problems encountered.
* Positive returns is unhandled HTTP return codes. For example 404.
* Negative is internal errors.
* -1 No response code was found in the HTTP response header or it was outside the accepted range (200-307).
* -2 Server is sending bad data or sizes for a chunked transfer or HTTP2 has problems reading them.
* -3 Nothing received in last packet. Most likely due to an error.
* -4 HTTP2 was redirected but could not follow due to a socket error.
*/
Basic examples:
Examples
Downloading data/file and saving it to a file:
Code:
#include <amxmodx>
#include <http2>
new Float:Timer;
public plugin_init() {
register_plugin("HTTP2 Test Plugin 1", "", "");
Timer = get_gametime();
HTTP2_Download("URL goes here. Youtube videos expire so there's no point leaving a link...", "test.mp4", "Complete");
}
public Complete(Index, Error) {
new filename[32];
HTTP2_getFilename(Index, filename, charsmax(filename))
server_print("HTTP2 Done, %s, %0.2fMB, Time: %0.2f seconds, error: %d", filename, HTTP2_getBytesReceived(Index)*1.0/(1024*1024), get_gametime() - Timer, Error);
}
/*
Downloading a youtube video (360p, mp4, 7:29) with different buffer sizes:
65536:
HTTP2 Done, test.mp4, 31.47MB, Time: 6.43 seconds, error: 0
5012KB/s
32768:
HTTP2 Done, test.mp4, 31.47MB, Time: 11.15 seconds, error: 0
2890KB/s
16384:
HTTP2 Done, test.mp4, 31.47MB, Time: 21.18 seconds, error: 0
1521KB/s
8192:
HTTP2 Done, test.mp4, 31.47MB, Time: 41.32 seconds, error: 0
780KB/s
4096:
HTTP2 Done, test.mp4, 31.47MB, Time: 81.63 seconds, error: 0
395KB/s
*/
Parsing a source code on-the-fly. When right value is found, abort download:
Code:
#include <amxmodx>
#include <http2>
new Buffer[HTTP2_BUFFER_SIZE];
public plugin_init() {
register_plugin("HTTP2 Test Plugin 2", "", "");
HTTP2_Download("http://forums.alliedmods.net/index.php", _, _, "Progress");
}
public Progress(Index) {
new len;
HTTP2_getData(Buffer, charsmax(Buffer), len);
server_print("HTTP2 Progress: %d/%d(+%d)", HTTP2_getBytesReceived(Index), HTTP2_getFilesize(Index), len);
if ( contain(Buffer, "SourceMod Discussion") != -1 ) {
server_print("Gaben was found");
return PLUGIN_HANDLED // This will stop the download.
}
return PLUGIN_CONTINUE
}
Code:
HTTP2 Progress: 4/-1(+4)
HTTP2 Progress: 3513/-1(+3509)
HTTP2 Progress: 6427/-1(+2914)
HTTP2 Progress: 7887/-1(+1460)
HTTP2 Progress: 16647/-1(+8760)
HTTP2 Progress: 18107/-1(+1460)
HTTP2 Progress: 26867/-1(+8760)
HTTP2 Progress: 40377/-1(+13510)
Gaben was found
Post example:
Code:
#include <amxmodx>
#include <http2>
new data[HTTP2_BUFFER_SIZE];
public plugin_init() {
register_plugin("HTTP2 POST example", "", "");
HTTP2_AddPostVar("What about gaben?", "No, thank you.");
HTTP2_Download("http://DivinityX.net/posttest.php?Bacon%20sir?=Yes,%20please.", _, _, "Progress", _, REQUEST_POST);
}
public Progress(Index) {
new len;
HTTP2_getData(data, charsmax(data), len);
server_print("%s", data);
}
PHP Code:
<?php echo "\r\nGet variables:\r\n"; print_r($_GET); echo "\r\nPost variables:\r\n"; print_r($_POST); ?>
Code:
Get variables:
Array
(
[Bacon_sir?] => Yes, please.
)
Post variables:
Array
(
[What_about_gaben?] => No, thank you.
)
Large transfer example:
Code:
#include <amxmodx>
#define HTTP2_MAX_DOWNLOAD_SLOTS 1
#define HTTP2_BUFFER_SIZE 131072 // 128KB
#include <http2>
new Float:Timer;
public plugin_init() {
register_plugin("HTTP2 Test Plugin", "1.0", "[ --{-@ ]");
Timer = get_gametime();
HTTP2_Download("DivinityX.eu/Scarface.mkv", "Scarface.mkv", "Complete");
}
public Progress(Index) {
static size[17], recv[17];
if ( HTTP2_isFilesizeLarge(Index) ) {
HTTP2_getFilesizeLarge(Index, size, charsmax(size));
HTTP2_getBytesReceivedLarge(Index, recv, charsmax(recv));
server_print("%s/%sB", recv, size);
}
else
server_print("%s/%sB", HTTP2_getBytesReceived(Index), HTTP2_getFilesize(Index));
}
public Complete(Index, Error) {
new filename[32], size[17];
HTTP2_getFilename(Index, filename, charsmax(filename));
if ( HTTP2_isFilesizeLarge(Index) ) {
HTTP2_getFilesizeLarge(Index, size, charsmax(size));
server_print("HTTP2 Done, %s, %sB, Time: %0.2f seconds, error: %d", filename, size, get_gametime() - Timer, Error);
}
else
server_print("HTTP2 Done, %s, %dB, Time: %0.2f seconds, error: %d", filename, HTTP2_getFilesize(Index), get_gametime() - Timer, Error);
}
/*
HTTP2 Done, Scarface.mkv, 17437741426B, Time: 2903.44 seconds, error: 0
16.24GB, ~48Mb/s data, exluding overhead.
*/
Changelog:
Changelog
Version 1.10:
* Fixed errors in the header parsing.
Version 1.20:
* Replaced strfind() with contain() because of a strfind() problem with long input strings. bug 5901
Version 2.00:
* Replaced the dual buffer system + reading through ALL data to search for chunks. Now it reads data until it reaches a chunk and parses that separately. Much more effective.
* Added functionality for sending POST requests along with the function HTTP2_AddPostVar().
* Added functionality to login using basic authentication.
* Note: This version destroys backwards compatibility because of the scrapped dual buffers.
Version 2.10:
* Replaced all local variables with static to avoid stack errors.
* Included a function to automatically update plugins. Just add this to the script when you want it to be updated: HTTP2_UpdatePlugin("http://example.url.com/example_file.amxx").
Version 2.11:
* Reverted back a lot of the local variables due to unexpected behavior. This might cause unfinished chunked downloads to abort without throwing an error.
Version 2.20:
* Reverted back to engine instead of fakemeta.
* Added a que system for loops that would add more than available slots could hold. Items in que will get downloaded as soon as there's room in the download slots.
Version 2.21:
* Added _HTTP2_URLDecode() for use in the PayPal inc.
Version 2.30:
* Rewrote que system using arrays instead of tries.
* Added support for POST variables in que and 3XX redirection.
* Redirection now supports relative paths.
Version 2.40:
* Fixed critical bug in header parsing that would cause corrupt data on HTTP2 version 2.30.
* Fixed a bug in the URL parsing that would cause some HTTP servers to throw 400 errors due to a case sensitivity issue in the request.
* Fixed the RegEx in URL parsing that would cause hostnames containing hyphens not to be picked up correctly.
* Increased maximum file size from ~2GB to ~8.9PB(petabyte). The limit is theoretical. There may be limits in the file I/O code, operating system or the physical disk. The code to manage these large files are slower and will only be used when the filesize exceeds 2147483647 bytes (1.99GB).
* Added default values and correction of URLs. In other words, "http://" is not needed and "https://" will be replaced with "http://".
Additional notes:
You can use this in any way you want to.
I'm always open to suggestions, feedback and criticism. Please share your thoughts.
__________________
Last edited by Black Rose; 07-24-2017 at 10:59.
|
|