Code:
#include <amxmodx>
#include <amxmisc>
#include <sqlx>
#include <ggl>
#include <sockets>
#define PLUGIN "ggl_base"
#define VERSION "0.0.5"
#define WEB_SCRIPT_NAME "/ggl.php"
#define WEB_REMOTE_HOST "www.foolyfrag.com" //port 80
// Session ID
static SID[50] = "";
// Server GUID
static GUID[50] = "";
// DB Connection
static Handle:tuple = Empty_Handle;
static Handle:db = Empty_Handle;
// Low Priority MESSAGETYPE:SQL Stack /////
static sspl[_:STACKLOWPLEN][SQML2];
static sspl_callback[_:STACKLOWPLEN];
static SQLTYPE:sspl_sqltype[_:STACKLOWPLEN];
//
static sspl_attic = 0;
static sspl_trash = 0;
//
static sspl_spoon = 0;
static sspl_spoon_servings = 0;
//
static sspl_fork = 0;
static sspl_fork_servings = 0;
///////////////////////////////
// Normal Priority MESSAGETYPE:SQL Stack //
static sspn[_:STACKNORMLEN][SQML2];
static sspn_callback[_:STACKNORMLEN];
static SQLTYPE:sspn_sqltype[_:STACKNORMLEN];
//
static sspn_attic = 0;
static sspn_trash = 0;
//
static sspn_spoon = 0;
static sspn_spoon_servings = 0;
//
static sspn_fork = 0;
static sspn_fork_servings = 0;
///////////////////////////////
// High Priority MESSAGETYPE:SQL Stack /////
static ssph[_:STACKHIGHLEN][SQML2];
static ssph_callback[_:STACKHIGHLEN];
static SQLTYPE:ssph_sqltype[_:STACKHIGHLEN];
//
static ssph_attic = 0;
static ssph_trash = 0;
//
static ssph_spoon = 0;
static ssph_spoon_servings = 0;
//
static ssph_fork = 0;
static ssph_fork_servings = 0;
///////////////////////////////
static plate_sql[SQML2];
static plate_callback;
static SQLTYPE:plate_sqltype;
static sockx[1024];
static sockx_times[1024];
static sockx_callbacks[1024];
static data_callback;
public send_sock(const callback,const data[]){
new error = 0
new constring[1024]
new sock = socket_open(WEB_REMOTE_HOST, 80, SOCKET_TCP, error)
if (sock > 0)
{
format(constring,1023,"POST %s HTTP/1.0^nUser-Agent: %s %s^nContent-Type: application/x-www-form-urlencoded^nContent-Length: %d^nHost: %s^n^ndata=%s",WEB_SCRIPT_NAME,PLUGIN,VERSION,strlen(data)+5,WEB_REMOTE_HOST,data)
//server_print(constring);
socket_send2(sock, constring, strlen(constring))
if (sock){
new sockslot = get_next_open_sockslot();
sockx[sockslot] = sock;
sockx_times[sockslot] = get_systime();
sockx_callbacks[sockslot] = callback;
}
}
else
{
switch (error)
{
case 1: { ggl_msg(HIGH,ERR,"Error creating socket",NOCALLBACK,SIMPLE); }
case 2: { ggl_msg(HIGH,ERR,"Error resolving remote hostname",NOCALLBACK,SIMPLE); }
case 3: { ggl_msg(HIGH,ERR,"Error connecting socket",NOCALLBACK,SIMPLE); }
}
}
return PLUGIN_CONTINUE
}
static check_socks(){
new sockslot = get_next_used_sockslot();
while(sockslot > -1){
if (socket_change(sockx[sockslot])){
new data[1024];
socket_recv(sockx[sockslot], data, 1023)
if (callfunc_begin_i(sockx_callbacks[sockslot]) == 1)
{
callfunc_push_str(data);
callfunc_end();
}
sockx[sockslot] = 0;
sockx_times[sockslot] = 0;
sockx_callbacks[sockslot] = 0;
}
else
{
new timewaited = get_systime() - sockx_times[sockslot];
if (timewaited < 0)
{
ggl_msg(HIGH,ERR,"Something is wrong.",NOCALLBACK,SIMPLE);
sockx[sockslot] = 0;
sockx_times[sockslot] = 0;
sockx_callbacks[sockslot] = 0;
}
if (timewaited > WEB_TIMEOUT)
{
ggl_msg(HIGH,ERR,"Socket Timed out.",NOCALLBACK,SIMPLE);
sockx[sockslot] = 0;
sockx_times[sockslot] = 0;
sockx_callbacks[sockslot] = 0;
}
}
sockslot = get_next_used_sockslot();
}
}
public receive_data(data[]){
new data2[1024];
format(data2,1023,data)
new msg[32][32];
new recording = false;
new a=0;
new field_dial=0;
new ch = 0;
new nex = 0;
new nex2 = 0;
new nexch = 0;
for(new i=0;i<1023;i++){
ch = data2[i];
if(!recording){
nex = (i+1);
nexch = data2[nex];
if (ch == 13 && nexch == 10){ // CRLF
nex = (i+3);
nexch = data2[nex];
nex2 = (i+2);
ch = data2[nex2];
if (ch == 13 && nexch == 10){ // 2 CRLF in a row - Document Begins
i = i + 4;
recording = true;
}
}
}
else
{
if (ch != 0){
if(ch == 10){ // decimal 10 = line feed
field_dial++;
if (field_dial == 32)break;
i++;
a=0;
}
if (a < 32){
msg[field_dial][a] = ch;
a++;
}
}
else
{
break;
}
}
}
if (msg[0][0] == 0)
{
return PLUGIN_CONTINUE;
}
else if (equal(msg[0],"SID"))
{
format(SID,49,msg[1]);
refresh_sid();
server_print(SID)
output_version();
}
else if (equal(msg[0],"ERR"))
{
ggl_msg(HIGH,ERR,msg[1],NOCALLBACK,SIMPLE);
}
else
{
new err[32] = "";
format(err,31,"unknown word: %s",msg[0]);
ggl_msg(HIGH,ERR,err,NOCALLBACK,SIMPLE);
}
return PLUGIN_CONTINUE;
}
static get_next_open_sockslot(){
for(new i=0;i<1024;i++)
{
if (sockx[i] <= 0)
{
return i;
}
}
return -1;
}
static get_next_used_sockslot(){
for(new i=0;i<1024;i++)
{
if (sockx[i] > 0)
{
return i;
}
}
return -1;
}
static add_sql(const PRIORITY:priority,const callback, const query[],SQLTYPE:type){
new pri = clamp(_:priority,_:HIGH,_:LOWP);
switch (pri)
{
case LOWP:
{
if (sspl_spoon_servings - sspl_fork_servings < _:STACKLOWPLEN - 1) //spoon cant pass the fork :P
{
format(sspl[sspl_spoon],SQML1,query);
sspl_callback[sspl_spoon] = callback;
sspl_sqltype[sspl_spoon] = type;
sspl_attic++;
if (sspl_spoon == _:STACKLOWPLEN - 1)
sspl_spoon = 0;
else
sspl_spoon++;
sspl_spoon_servings++;
}
else
{
new msg[MSGL2] = "";
format(msg,MSGL1,"MESSAGETYPE:SQL Stack: PRIORITY:LOWP Full; Trashing data!; sspl_attic=%d; sspl_trash=%d; data=%s",sspl_attic,sspl_trash,query);
ggl_msg(PRIORITY:LOWP,MESSAGETYPE:ERR,msg,NOCALLBACK,SIMPLE);
sspl_trash++;
}
}
case NORM:
{
if (sspn_spoon_servings - sspn_fork_servings < _:STACKNORMLEN - 1) //spoon cant pass the fork :P
{
//sspn[sspn_spoon] = query;
format(sspn[sspn_spoon],SQML1,query);
sspn_callback[sspn_spoon] = callback;
sspn_sqltype[sspn_spoon] = type;
sspn_attic++;
if (sspn_spoon == _:STACKNORMLEN - 1)
sspn_spoon = 0;
else
sspn_spoon++;
sspn_spoon_servings++;
}
else
{
new msg[MSGL2] = "";
format(msg,MSGL1,"MESSAGETYPE:SQL Stack: PRIORITY:NORM Full; Trashing data!; sspn_attic=%d; sspn_trash=%d; data=%s",sspn_attic,sspn_trash,query);
ggl_msg(PRIORITY:NORM,MESSAGETYPE:ERR,msg,NOCALLBACK,SIMPLE);
sspn_trash++;
}
}
case HIGH:
{
if (ssph_spoon_servings - ssph_fork_servings < _:STACKHIGHLEN - 1) //spoon cant pass the fork :P
{
//ssph[ssph_spoon] = query;
format(ssph[ssph_spoon],SQML1,query);
ssph_callback[ssph_spoon] = callback;
ssph_sqltype[ssph_spoon] = type;
ssph_attic++;
if (ssph_spoon == _:STACKHIGHLEN - 1)
ssph_spoon = 0;
else
ssph_spoon++;
ssph_spoon_servings++;
}
else
{
new msg[MSGL2] = "";
format(msg,MSGL1,"MESSAGETYPE:SQL Stack: PRIORITY:HIGH Full; Trashing data!; ssph_attic=%d; ssph_trash=%d; data=%s",ssph_attic,ssph_trash,query);
ggl_msg(PRIORITY:HIGH,MESSAGETYPE:ERR,msg,NOCALLBACK,SIMPLE);
ssph_trash++;
}
}
}
}
static ggl_msg(PRIORITY:priority,MESSAGETYPE:type,msg[],const callback,const SQLTYPE:qtype){
new logmsg[MSGL2];
new msg2[MSGL2];
format(logmsg,MSGL1,"%s%s","[GGL] ",msg);
replace_all(logmsg,MSGL1,"'","\'");
switch (type){
case ERR:{
log_amx(msg);
if (db != Empty_Handle)
{
format(msg2,MSGL1,"insert into ggl_messages(sid,priority,type,msg)values('%s',%d,%d,'%s');",SID,_:priority,_:type,logmsg); //75
query(msg2,SIMPLE,priority);
}
//if (priority == PRIORITY:HIGH)
//{
// db = Empty_Handle;
// tuple = Empty_Handle;
// set_fail_state(msg);
//}
}
case SQL:{
if (db != Empty_Handle)
{
add_sql(priority,callback,msg,qtype);
}
}
case MSG:{
log_amx(logmsg);
if (db != Empty_Handle)
{
format(msg2,MSGL1,"insert into ggl_messages(sid,priority,type,msg)values('%s',%d,%d,'%s');",SID,_:priority,_:type,logmsg); //75
query(msg2,SIMPLE,priority);
}
}
}
}
static output_version(){
new ver[MSGL2];
format(ver,MSGL1,"This is an Alpha version of GGL: %s",VERSION);
ggl_msg(PRIORITY:LOWP,MESSAGETYPE:MSG,ver,NOCALLBACK,SIMPLE);
}
public main(){
data_callback = get_funcid("receive_data","ggl_base.amxx");
if (data_callback == -1)ggl_msg(HIGH,ERR,"Failed getting data callback",NOCALLBACK,SIMPLE);
get_cvar_string("ggl_guid",GUID,49);
replace_all(GUID,49,"'","\'");
if (equal(GUID,""))ggl_msg(PRIORITY:HIGH,MESSAGETYPE:ERR,"Empty GUID",NOCALLBACK,SIMPLE);
set_cvar_string("ggl_guid","");
initdb();
start_session();
tick();
}
static send_sid(const callback[],const plugin[]){
if (callback[0] && plugin[0])
{
if (callfunc_begin ( callback, plugin ) == 1)
{
callfunc_push_str(SID);
callfunc_end ( );
}
}
}
static refresh_sid(){
send_sid("set_sid","ggl_gungame_scorepush.amxx");
send_sid("set_sid","ggl_mapchooser.amxx");
}
static start_session(){
new msg[128] = "";
format(msg,127,"%s|START_SESSION",GUID);
send_sock(data_callback,msg);
//server_print("1");
}
static end_session(){
new sql[256];
format(sql,255,"INSERT INTO `ggl_external`.`ggl_sessions` ( `guid` , `time_end` , `sid` ) VALUES ( '%s', NOW( ) ,'%s');",GUID,SID);
ggl_msg(PRIORITY:HIGH,MESSAGETYPE:SQL,sql,NOCALLBACK,SQLTYPE:SIMPLE);
}
public plugin_init() {
register_plugin(PLUGIN, VERSION, AUTHOR);
register_cvar("ggl_guid","");
set_task(5.0,"main");
}
public plugin_end(){
if(SID[0])
{
end_session();
}
}
public tick(){
eat_stacks();
check_socks();
set_task(1.0,"tick");
return 0;
}
static Handle:query(sql[],SQLTYPE:sqltype,PRIORITY:priority){
//Gotta make sure SQL Statement wasn't truncated somewhere along the line.
if ( ! equal(sql[strlen ( sql ) - 1],";"))
{
new err[MSGL2] = "";
format(err,MSGL1,"SQL statement last char != ; SQL = %s",sql);
db = Empty_Handle;
tuple = Empty_Handle;
ggl_msg(LOWP,ERR,err,NOCALLBACK,SIMPLE);
return Empty_Handle;
}
/*
L 09/26/2007 - 20:07:14: [AMXX] Run time error 3: stack error
L 09/26/2007 - 20:07:14: [AMXX] [0] ggl_base.sma::query (line 304)
L 09/26/2007 - 20:07:14: [AMXX] [1] ggl_base.sma::ggl_msg (line 176)
L 09/26/2007 - 20:07:14: [AMXX] [2] ggl_base.sma::output_version (line 184)
L 09/26/2007 - 20:07:14: [AMXX] [3] ggl_base.sma::main (line 192)
new err[MSGL2] = "";
*/
new err[32] = "";
switch (sqltype){
case EXECUT:{
new Handle:qh = Empty_Handle;
qh = SQL_PrepareQuery(db,sql);
if (qh == Empty_Handle)ggl_msg(priority,MESSAGETYPE:ERR,sql,NOCALLBACK,SIMPLE);
if (SQL_Execute(qh) == 1) {
return qh;
}
else
{
SQL_QueryError(qh,err,31);
format(err,MSGL1,"%s^n%s",err,sql);
ggl_msg(priority,MESSAGETYPE:ERR,err,NOCALLBACK,SIMPLE);
return Empty_Handle;
}
}
case SIMPLE:{
if (SQL_SimpleQuery(db,sql,err,31) != 1)
{
format(err,MSGL1,"%s^n%s",err,sql);
ggl_msg(priority,MESSAGETYPE:ERR,err,NOCALLBACK,SIMPLE);
return Empty_Handle;
}
}
case THREAD:{
//todo: better SQL_ThreadQuery support
//SQL_ThreadQuery(tuple,"handle_threadquery",sql2);
return Empty_Handle;
}
}
return Empty_Handle;
}
static eat_stacks(){
//server_print("LS:%d, LF:%d; NS:%d, NF:%d; HS:%d, HF:%d; ",sspl_spoon,sspl_fork,sspn_spoon,sspn_fork,ssph_spoon,ssph_fork);
for (new PRIORITY:i=HIGH;_:i<_:LOWP+1;_:i++)
{
plate_sql = "";
get_sql(i);
while(plate_sql[0])
{
new Handle:qh = query(plate_sql,plate_sqltype,i);
switch(plate_sqltype){
case EXECUT:
{
if (qh != Empty_Handle){
if (plate_callback != NOCALLBACK)
{
//do the call
new callworked = callfunc_begin_i ( plate_callback );
if (callworked == 1)
{
callfunc_push_int(_:qh);
callfunc_end ( );
}
}
}
}
case SIMPLE:
{
}
}
//complement chef
i=HIGH;
//clean plate
plate_sql = "";
plate_callback = NOCALLBACK;
plate_sqltype = SQLTYPE:SIMPLE;
//get seconds
get_sql(i);
}
}
}
static get_sql(PRIORITY:priority){
new pri = clamp(_:priority,_:HIGH,_:LOWP);
switch (pri){
case LOWP:{
if (sspl_spoon_servings - sspl_fork_servings > 0) // how do you eat if theres no food
{
format(plate_sql,SQML1,sspl[sspl_fork]); // mmmm yummy
plate_callback = sspl_callback[sspl_fork];
plate_sqltype = sspl_sqltype[sspl_fork];
sspl_fork_servings++;
if (sspl_fork == _:STACKLOWPLEN - 1)
sspl_fork = 0;
else
sspl_fork++;
}
}
case NORM:{
if (sspn_spoon_servings - sspn_fork_servings > 0 ) // how do you eat if theres no food
{
format(plate_sql,SQML1,sspn[sspn_fork]); // mmmm yummy
plate_callback = sspn_callback[sspn_fork];
plate_sqltype = sspn_sqltype[sspn_fork];
sspn_fork_servings++;
if (sspn_fork == _:STACKNORMLEN - 1)
sspn_fork = 0;
else
sspn_fork++;
}
}
case HIGH:{
if (ssph_spoon_servings - ssph_fork_servings > 0 ) // how do you eat if theres no food
{
format(plate_sql,SQML1,ssph[ssph_fork]); // mmmm yummy
plate_callback = ssph_callback[ssph_fork];
plate_sqltype = ssph_sqltype[ssph_fork];
ssph_fork_servings++;
if (ssph_fork == _:STACKHIGHLEN - 1)
ssph_fork = 0;
else
ssph_fork++;
}
}
}
}
static initdb(){
static error[MSGL2],errorCode;
static host[64] = "";static user[64] = "";
static pass[64] = "";static dbnm[64] = "";
tuple = SQL_MakeDbTuple(host, user, pass, dbnm);
pass = "";user = "";host = "";dbnm = "";
db = SQL_Connect(tuple, errorCode, error, MSGL1);
if (db == Empty_Handle)
{
tuple = Empty_Handle;
ggl_msg(PRIORITY:HIGH,MESSAGETYPE:ERR,"Database Connection Failed",NOCALLBACK,SIMPLE);
}
}