// forward OnQueryError(connectionId, query[], callback[], errno, error[]); int Script::OnQueryError(unsigned int connectionId, const char* query, const char* callback, int error_number, const char* error) { if (OnQueryError_index_ == CallbackNotFoundIndex) return 0; // Attempt to find the OnQueryError callback in the script. if (OnQueryError_index_ == 0) { if (amx_FindPublic(runtime_, "OnQueryError", &OnQueryError_index_) != AMX_ERR_NONE) { OnQueryError_index_ = CallbackNotFoundIndex; return 0; } } cell returnValue, stringCell[3], *physicalCell; // Push the arguments to OnQueryError in reverse order. amx_PushString(runtime_, &stringCell[0], &physicalCell, error, 0, 0); amx_Push(runtime_, error_number); amx_PushString(runtime_, &stringCell[1], &physicalCell, callback, 0, 0); amx_PushString(runtime_, &stringCell[2], &physicalCell, query, 0, 0); amx_Push(runtime_, connectionId); // Execute and get the return value. amx_Exec(runtime_, &returnValue, OnQueryError_index_); // Clean up the strings we pushed to Pawn's stack. amx_Release(runtime_, stringCell[0]); amx_Release(runtime_, stringCell[1]); amx_Release(runtime_, stringCell[2]); return returnValue; }
// forward OnConnectionAttempt(connectionHandle, bool: succeeded, server[], username[], errno, error[]); int Script::OnConnectionAttempt(unsigned int connectionId, bool succeeded, const char* server, const char* username, int error_number, const char* error) { if (OnConnectionAttempt_index_ == CallbackNotFoundIndex) return 0; // Attempt to find the OnConnectionAttempt callback in the script. if (OnConnectionAttempt_index_ == 0) { if (amx_FindPublic(runtime_, "OnConnectionAttempt", &OnConnectionAttempt_index_) != AMX_ERR_NONE) { OnConnectionAttempt_index_ = CallbackNotFoundIndex; return 0; } } cell returnValue, stringCell[3], *physicalCell; // We've now got the callback. Push the arguments in reverse order. amx_PushString(runtime_, &stringCell[0], &physicalCell, error, 0, 0); amx_Push(runtime_, error_number); amx_PushString(runtime_, &stringCell[1], &physicalCell, username, 0, 0); amx_PushString(runtime_, &stringCell[2], &physicalCell, server, 0, 0); amx_Push(runtime_, succeeded); amx_Push(runtime_, connectionId); // Execute and get the return value. amx_Exec(runtime_, &returnValue, OnConnectionAttempt_index_); // Clean up the strings we pushed to Pawn's stack. amx_Release(runtime_, stringCell[0]); amx_Release(runtime_, stringCell[1]); amx_Release(runtime_, stringCell[2]); return returnValue; }
static int AMXAPI amx_DGramIdle(AMX *amx, int AMXAPI Exec(AMX *, cell *, int)) { char message[BUFLEN], source[SRC_BUFSIZE]; cell *amx_addr_src; int len, chars; int err=0; assert(idxReceiveString >= 0 || idxReceivePacket >= 0); if (PrevIdle != NULL) PrevIdle(amx, Exec); /* set up listener (first call only) */ if (!dgramBound) { if (dgramPort==0) dgramPort=AMX_DGRAMPORT; /* use default port if none was set */ if (udp_Listen(dgramPort)==-1) return AMX_ERR_GENERAL; dgramBound=1; } /* if */ if (udp_IsPacket()) { len=udp_Receive(message, sizeof message / sizeof message[0], source); amx_PushString(amx,&amx_addr_src,source,1,0); /* check the presence of a byte order mark: if it is absent, the received * packet is no string; also check the packet size against string length */ if ((message[0]!='\xef' || message[1]!='\xbb' || message[2]!='\xbf' || len!=(int)strlen(message)+1 || idxReceiveString<0) && idxReceivePacket>=0) { /* receive as "packet" */ amx_Push(amx,len); amx_PushArray(amx,NULL,(cell*)message,len); err=Exec(amx,NULL,idxReceivePacket); } else { const char *msg=message; if (msg[0]=='\xef' && msg[1]=='\xbb' && msg[2]=='\xbf') msg+=3; /* skip BOM */ /* optionally convert from UTF-8 to a wide string */ if (amx_UTF8Check(msg,&chars)==AMX_ERR_NONE) { cell *array=alloca((chars+1)*sizeof(cell)); cell *ptr=array; if (array!=NULL) { while (err==AMX_ERR_NONE && *msg!='\0') amx_UTF8Get(msg,&msg,ptr++); *ptr=0; /* zero-terminate */ amx_PushArray(amx,NULL,array,chars+1); } /* if */ } else { amx_PushString(amx,NULL,msg,1,0); } /* if */ err=Exec(amx,NULL,idxReceiveString); } /* if */ while (err==AMX_ERR_SLEEP) err=Exec(amx,NULL,AMX_EXEC_CONT); amx_Release(amx,amx_addr_src); } /* if */ return err; }
bool CCallbackManager::OnRemoteRCONPacket(unsigned int binaryAddress, int port, char *password, bool success, char* command) { int idx = -1; cell ret = 1; for(std::vector<AMX*>::const_iterator iter = m_vecAMX.begin(); iter != m_vecAMX.end(); ++iter) { if(!amx_FindPublic(*iter, "OnRemoteRCONPacket", &idx)) { cell amx_addr, *phys_addr; in_addr in; in.s_addr = binaryAddress; amx_PushString(*iter, &amx_addr, &phys_addr, command, 0, 0); amx_Push(*iter, static_cast<cell>(success)); amx_PushString(*iter, &amx_addr, &phys_addr, password, 0, 0); amx_Push(*iter, static_cast<cell>(port)); amx_PushString(*iter, &amx_addr, &phys_addr, inet_ntoa(in), 0, 0); amx_Exec(*iter, &ret, idx); amx_Release(*iter, amx_addr); if (!ret) return 0; } } return !!ret; }
int Handler::HandleModule(const char *module, bool isClass) { if (m_iModFunc < 0) return 0; /** * This is the most minimalistic handler of them all */ cell hea_addr, *phys_addr, retval; Debugger *pd; pd = DisableDebugHandler(m_pAmx); //temporarily set prenit m_pAmx->flags |= AMX_FLAG_PRENIT; amx_Push(m_pAmx, isClass ? 1 : 0); amx_PushString(m_pAmx, &hea_addr, &phys_addr, module, 0, 0); int err = amx_Exec(m_pAmx, &retval, m_iModFunc); amx_Release(m_pAmx, hea_addr); m_pAmx->flags &= ~AMX_FLAG_PRENIT; EnableDebugHandler(m_pAmx, pd); if (err != AMX_ERR_NONE) return 0; return (int)retval; }
static cell AMX_NATIVE_CALL amx_fpga_load(AMX *amx, const cell *params) { set_port_directions(0); // All as inputs char *fname; amx_StrParam(amx, params[1], fname); uint8_t *buffer; if (amx_Allot(amx, 1024/sizeof(cell), (cell**)&buffer) != 0) return false; bool status = false; if (!fname[0]) { have_custom_image = false; status = fpga_configure(NULL, buffer); set_port_directions(default_pins); } else { have_custom_image = true; FIL file; if (f_open(&file, fname, FA_READ) != FR_OK) return false; status = fpga_configure(&file, buffer); f_close(&file); } amx_Release(amx, (cell*)buffer); return status; }
int amxinit_fpga(AMX *amx) { static const AMX_NATIVE_INFO funcs[] = { {"fpga_load", amx_fpga_load}, {"fpga_config_outputs", amx_fpga_config_outputs}, {"fpga_read_pins", amx_fpga_read_pins}, {"fpga_write_pins", amx_fpga_write_pins}, {"fpga_read", amx_fpga_read}, {"fpga_write", amx_fpga_write}, {0, 0} }; if (have_custom_image) { uint8_t *buffer; if (amx_Allot(amx, 1024/sizeof(cell), (cell**)&buffer) != 0) return false; have_custom_image = false; fpga_configure(NULL, buffer); // Restore original FPGA image amx_Release(amx, (cell*)buffer); } set_port_directions(default_pins); return amx_Register(amx, funcs, -1); }
//__declspec(naked) //__cdecl int FIXES_logprintf(char * str, ...) { va_list ap; char dst[1024]; va_start(ap, str); vsnprintf(dst, 1024, str, ap); va_end(ap); printf("%s\n", dst); // So we can use "printf" without getting stuck in endless loops. if (!bInPrint) { for (int i = 0; i != 17; ++i) { if (gAMXPtr[i] != -1) { cell ret, addr; amx_PushString(gAMXFiles[i], &addr, 0, dst, 0, 0); amx_Exec(gAMXFiles[i], &ret, gAMXPtr[i]); amx_Release(gAMXFiles[i], addr); if (ret == 1) { return 1; } } } } return 1; }
int call(std::vector<int> const& v) { if (amx && fn) { int rezult; std::vector<cell> cells(v.size() + 1); //precall cells[0] = v.size() * sizeof(cell); for (std::size_t param_id = 0, len = v.size(); param_id < len; ++param_id) { cell* phys_addr; amx_Allot(amx, 1, &cells[param_id + 1], &phys_addr); *phys_addr = v[param_id]; } //call rezult = fn(amx, &cells[0]); //postcall for (std::size_t param_id = 0, len = v.size(); param_id < len; ++param_id) { amx_Release(amx, cells[param_id + 1]); } return rezult; } else { assert(false && "error call null amx"); return -1; } }
static void ProcessServerMessage(AMX *amx, const char *msg) { int index; if (amx_FindPublic(amx, "OnServerMessage", &index) == AMX_ERR_NONE) { cell address; amx_PushString(amx, &address, 0, msg, 0, 0); amx_Exec(amx, 0, index); amx_Release(amx, address); } }
int main(int argc,char *argv[]) { extern int amx_ConsoleInit(AMX *amx); extern int amx_ConsoleCleanup(AMX *amx); extern int amx_CoreInit(AMX *amx); extern int amx_CoredCleanp(AMX *amx); size_t memsize; void *program; AMX amx; int index, err; cell amx_addr, *phys_addr; char output[128]; if (argc != 4) PrintUsage(argv[0]); if ((memsize = aux_ProgramSize(argv[1])) == 0) PrintUsage(argv[0]); program = malloc(memsize); if (program == NULL) ErrorExit(NULL, AMX_ERR_MEMORY); err = aux_LoadProgram(&amx, argv[1], program); if (err) ErrorExit(&amx, err); amx_ConsoleInit(amx); err = amx_CoreInit(amx); if (err) ErrorExit(&amx, err); err = amx_FindPublic(&amx, argv[2], &index); if (err) ErrorExit(&amx, err); err = amx_Allot(&amx, strlen(argv[3]) + 1, &amx_addr, &phys_addr); if (err) ErrorExit(&amx, err); amx_SetString(phys_addr, argv[3], 0); err = amx_Exec(&amx, NULL, index, 1, amx_addr); if (err) ErrorExit(&amx, err); amx_GetString(output, phys_addr); amx_Release(&amx, amx_addr); printf("%s returns %s\n", argv[1], output); amx_ConsoleCleanup(&amx); amx_CoreCleanup(&amx); amx_Cleanup(&amx); free(program); return 0; }
void CNetwork::OnClientCommandText(int playerid, const char* recvcmd) { int idx; cell ret = 0; printf("Found command param in recvcmd \"%s\", send it to amx\n", recvcmd); if (!amx_FindPublic(&inimod_amx, "OnClientCommandText", &idx)) { cell amx_addr, *phys_addr; amx_PushString(&inimod_amx, &amx_addr, &phys_addr, recvcmd, 0, 0); amx_Push(&inimod_amx, playerid); amx_Exec(&inimod_amx, &ret, idx); amx_Release(&inimod_amx, amx_addr); } }
uint32_t CGamemodeManager::OnRconLoginAttempt( unsigned char* szIP, unsigned char* szPassword, cell success ) { if (!gmIsInit) return 0; int idx; cell retval; if ( !amx_FindPublic(&gmAMX, "OnRconLoginAttempt", &idx ) ) { cell amx_addr, amx_addr2, *phys_addr; amx_Push( &gmAMX, success ); amx_PushString(&gmAMX, &amx_addr, &phys_addr, (char*)szPassword, 0, 0); amx_PushString(&gmAMX, &amx_addr2, &phys_addr, (char*)szIP, 0, 0); amx_Exec( &gmAMX, &retval, idx ); amx_Release(&gmAMX, amx_addr ); amx_Release(&gmAMX, amx_addr2 ); } return 1; }
void CScriptHttp::Process() { int amxIdx; cell ret = 0; for(uint8_t i = 0; i < 200; i++) { if(this->workers[i].responseCode == 3) { if(!this->workers[i].unk_noCallback) { if(this->workers[i].httpAMX) { if (!amx_FindPublic(this->workers[i].httpAMX, this->workers[i].amxCallback, &amxIdx) ) { cell amx_addr, *phys_addr; cell response; if(this->workers[i].httpClient->response) { amx_PushString(this->workers[i].httpAMX, &amx_addr, &phys_addr, "\0", 0, 0); response = this->workers[i].httpClient->response; } else { amx_PushString(this->workers[i].httpAMX, &amx_addr, &phys_addr, this->workers[i].data, 0, 0); response = this->workers[i].httpClient->unkDword005; } amx_Push(this->workers[i].httpAMX, response); amx_Push(this->workers[i].httpAMX, this->workers[i].threadId); amx_Exec(this->workers[i].httpAMX, &ret, amxIdx); amx_Release(this->workers[i].httpAMX, amx_addr); } } } // if(this->workers[i].httpClient) SAFE_DELETE(this->workers[i].httpClient); memset(&(this->workers[i]), 0, 0x2848); this->workers[i].unkdword = 0; this->workers[i].type = 0; } } }
PLUGIN_EXPORT void PLUGIN_CALL ProcessTick() { while(!amxQueue.empty()) { int amx_idx; attackData toamx; std::list<AMX *>::iterator end = amxList.end(); aat_Debug("* ProcessTick() is not empty, executing..."); boost::mutex::scoped_lock lock(gMutex); toamx = amxQueue.front(); amxQueue.pop(); lock.unlock(); for(std::list<AMX *>::iterator amx = amxList.begin(); amx != end; amx++) { if(toamx.type > 4) { cell amxAddress; if(!amx_FindPublic(*amx, "OnRemoteAttackAttempt", &amx_idx)) { amx_PushString(*amx, &amxAddress, NULL, toamx.data.c_str(), NULL, NULL); amx_Push(*amx, (toamx.type - 5)); amx_Exec(*amx, NULL, amx_idx); amx_Release(*amx, amxAddress); } } else { if(!amx_FindPublic(*amx, "OnIngameAttackAttempt", &amx_idx)) { amx_Push(*amx, atoi(toamx.data.c_str())); amx_Push(*amx, toamx.type); amx_Exec(*amx, NULL, amx_idx); } } } } }
uint32_t CGamemodeManager::OnRconCommand(char* szCommand) { if (!gmIsInit) return 0; int idx; cell ret = 0; uint32_t orig_strlen = strlen(szCommand); if (!amx_FindPublic(&gmAMX, "OnRconCommand", &idx)) { cell amx_addr, *phys_addr; amx_PushString(&gmAMX, &amx_addr, &phys_addr, szCommand, 0, 0); amx_Exec(&gmAMX, &ret, idx); amx_Release(&gmAMX, amx_addr); } return (uint32_t)ret; }
uint32_t CGamemodeManager::OnPlayerCommandText(cell playerid, unsigned char * szCommandText) { if (!gmIsInit) return 0; int idx; cell ret = 0; uint32_t orig_strlen = strlen((char*)szCommandText); if(!__NetGame->playerPool->GetSlotState((_PlayerID)playerid)) return 0; if (!amx_FindPublic(&gmAMX, "OnPlayerCommandText", &idx)) { cell amx_addr, *phys_addr; amx_PushString(&gmAMX, &amx_addr, &phys_addr, (char*)szCommandText, 0, 0); amx_Push(&gmAMX, playerid); amx_Exec(&gmAMX, &ret, idx); amx_Release(&gmAMX, amx_addr); } return (uint32_t)ret; }
bool CCallbackManager::OnServerMessage(char* message) { if (!message) return 0; int idx = -1; cell ret = 1; for(std::vector<AMX*>::const_iterator iter = m_vecAMX.begin(); iter != m_vecAMX.end(); ++iter) { if (!amx_FindPublic(*iter, "OnServerMessage", &idx)) { cell amx_addr, *phys_addr; amx_PushString(*iter, &amx_addr, &phys_addr, message, 0, 0); amx_Exec(*iter, &ret, idx); amx_Release(*iter, amx_addr); if (!ret) return 0; } } return !!ret; }
uint32_t CGamemodeManager::OnDialogResponse(cell playerid, cell dialogid, cell response, cell listitem, unsigned char *szInputText) { if (!gmIsInit) return 0; int idx; cell ret = 0; if(!__NetGame->playerPool->GetSlotState((_PlayerID)playerid)) return 0; if(!amx_FindPublic(&gmAMX, "OnDialogResponse", &idx)) { cell amx_addr, *phys_addr; amx_PushString(&gmAMX, &amx_addr, &phys_addr, (char*)szInputText, 0, 0); amx_Push(&gmAMX, listitem); amx_Push(&gmAMX, response); amx_Push(&gmAMX, dialogid); amx_Push(&gmAMX, playerid); amx_Exec(&gmAMX, &ret, idx); amx_Release(&gmAMX, amx_addr); } return (uint32_t)ret; }
void CCallback::ProcessCallbacks() { CMySQLQuery *Query = NULL; while( (Query = GetNextQuery()) != NULL) { CCallback *Callback = Query->Callback; if(Callback != NULL && (Callback->Name.length() > 0 || Query->OrmObject != NULL) ) { bool PassByReference = Query->Callback->IsInline; if(Query->OrmObject != NULL) { //orm, update the variables with the given result switch(Query->OrmQueryType) { case ORM_QUERYTYPE_SELECT: Query->OrmObject->ApplySelectResult(Query->Result); break; case ORM_QUERYTYPE_INSERT: Query->OrmObject->ApplyInsertResult(Query->Result); break; } } for (list<AMX *>::iterator a = m_AmxList.begin(), end = m_AmxList.end(); a != end; ++a) { AMX *amx = (*a); cell amx_Ret; int amx_Index; cell amx_MemoryAddress = -1; if (amx_FindPublic(amx, Callback->Name.c_str(), &amx_Index) == AMX_ERR_NONE) { CLog::Get()->StartCallback(Callback->Name.c_str()); int StringIndex = Callback->ParamFormat.length()-1; while(!Callback->Parameters.empty() && StringIndex >= 0) { switch(Callback->ParamFormat.at(StringIndex)) { case 'i': case 'd': { int val = 0; ConvertStrToInt(Callback->Parameters.top().c_str(), val); if(PassByReference == false) amx_Push(amx, (cell)val); else { cell tmpAddress; amx_PushArray(amx, &tmpAddress, NULL, (cell*)&val, 1); if(amx_MemoryAddress < NULL) amx_MemoryAddress = tmpAddress; } } break; case 'f': { float float_val = 0.0f; ConvertStrToFloat(Callback->Parameters.top().c_str(), float_val); cell FParam = amx_ftoc(float_val); if(PassByReference == false) amx_Push(amx, FParam); else { cell tmpAddress; amx_PushArray(amx, &tmpAddress, NULL, (cell*)&FParam, 1); if(amx_MemoryAddress < NULL) amx_MemoryAddress = tmpAddress; } } break; default: { cell tmpAddress; amx_PushString(amx, &tmpAddress, NULL, Callback->Parameters.top().c_str(), 0, 0); if(amx_MemoryAddress < NULL) amx_MemoryAddress = tmpAddress; } } StringIndex--; Callback->Parameters.pop(); } Query->ConnHandle->SetActiveResult(Query->Result); Query->Result = NULL; amx_Exec(amx, &amx_Ret, amx_Index); if (amx_MemoryAddress >= NULL) amx_Release(amx, amx_MemoryAddress); if(Query->ConnHandle->IsActiveResultSaved() == false) delete Query->ConnHandle->GetActiveResult(); Query->ConnHandle->SetActiveResult((CMySQLResult *)NULL); CLog::Get()->EndCallback(); break; //we have found our callback, exit loop } } } Query->Destroy(); } }
int Handler::HandleError(const char *msg) { if (m_iErrFunc <= 0) return 0; m_Handling = true; m_pTrace = NULL; m_FmtCache.clear(); Debugger *pDebugger = (Debugger *)m_pAmx->userdata[UD_DEBUGGER]; int error = m_pAmx->error; static char _buffer[512]; if (pDebugger) { pDebugger->SetTracedError(error); m_pTrace = pDebugger->GetTraceStart(); pDebugger->FormatError(_buffer, sizeof(_buffer)-1); m_FmtCache.assign(_buffer); pDebugger->BeginExec(); } else { Debugger::FmtGenericMsg(m_pAmx, error, _buffer, sizeof(_buffer)-1); m_FmtCache.assign(_buffer); } SetErrorMsg(msg); cell hea_addr, *phys_addr, result; amx_PushString(m_pAmx, &hea_addr, &phys_addr, msg, 0, 0); amx_Push(m_pAmx, pDebugger ? 1 : 0); amx_Push(m_pAmx, error); int err = amx_Exec(m_pAmx, &result, m_iErrFunc); if (err != AMX_ERR_NONE) { //handle this manually. if (pDebugger) { pDebugger->SetTracedError(err); pDebugger->DisplayTrace(msg); } else { if (GetLastMsg()) AMXXLOG_Error("%s", GetLastMsg()); Debugger::GenericMessage(m_pAmx, err); } AMXXLOG_Error("[AMXX] NOTE: Runtime failures in an error filter are not good!"); } if (pDebugger) pDebugger->EndExec(); amx_Release(m_pAmx, hea_addr); m_Handling = false; m_pTrace = NULL; m_FmtCache.clear(); if (err != AMX_ERR_NONE || !result) return 0; return result; }
PLUGIN_EXPORT int PLUGIN_CALL ProcessTick() { long long unsigned int time = MicrosecondTime(); //logprintf("Process %d", time); while (!gTimers.empty()) { struct timer_s * next = gTimers.top(); if (next->trigger > time) { return 1; } else { gTimers.pop(); //logprintf("Triggered: %d %d", next->func, next->interval); if (next->repeat) { struct params_s * p0 = next->params; while (p0) { switch (p0->type) { case PARAM_TYPE_CELL: { amx_Push(next->amx, p0->numData); break; } case PARAM_TYPE_ARRAY: case PARAM_TYPE_STRING: { // These are actually done the same way because we // just store the AMX string representation, not the // C char* representation. Just remember the NULL! amx_PushArray(next->amx, &p0->free, 0, p0->arrayData, p0->numData); break; } } p0 = p0->next; } cell ret; amx_Exec(next->amx, &ret, next->func); // Free things. p0 = next->params; while (p0) { switch (p0->type) { case PARAM_TYPE_ARRAY: case PARAM_TYPE_STRING: { amx_Release(next->amx, p0->free); p0->free = 0; break; } } p0 = p0->next; } switch (next->repeat) { case 1: DestroyTimer(next); break; default: --next->repeat; case -1: // Don't rely on the current time or we'll get errors // compounded. next->trigger += next->interval; gTimers.push(next); break; } } else { // Used by "KillTimer". DestroyTimer(next); } } } return 1; }
~Arg() { amx_Release(amx_, address_); }
cell CSPForward::execute(cell *params, ForwardPreparedArray *preparedArrays) { if (isFree) return 0; const int STRINGEX_MAXLENGTH = 128; cell realParams[FORWARD_MAX_PARAMS]; cell *physAddrs[FORWARD_MAX_PARAMS]; if (!m_HasFunc || m_ToDelete) return 0; CPluginMngr::CPlugin *pPlugin = g_plugins.findPluginFast(m_Amx); if (!pPlugin->isExecutable(m_Func)) return 0; m_InExec = true; Debugger *pDebugger = (Debugger *)m_Amx->userdata[UD_DEBUGGER]; if (pDebugger) pDebugger->BeginExec(); // handle strings & arrays int i; for (i = 0; i < m_NumParams; ++i) { if (m_ParamTypes[i] == FP_STRING || m_ParamTypes[i] == FP_STRINGEX) { const char *str = reinterpret_cast<const char*>(params[i]); if (!str) str = ""; cell *tmp; amx_Allot(m_Amx, (m_ParamTypes[i] == FP_STRING) ? strlen(str) + 1 : STRINGEX_MAXLENGTH, &realParams[i], &tmp); amx_SetStringOld(tmp, str, 0, 0); physAddrs[i] = tmp; } else if (m_ParamTypes[i] == FP_ARRAY) { cell *tmp; amx_Allot(m_Amx, preparedArrays[params[i]].size, &realParams[i], &tmp); physAddrs[i] = tmp; if (preparedArrays[params[i]].type == Type_Cell) { memcpy(tmp, preparedArrays[params[i]].ptr, preparedArrays[params[i]].size * sizeof(cell)); } else { char *data = (char*)preparedArrays[params[i]].ptr; for (unsigned int j = 0; j < preparedArrays[params[i]].size; ++j) *tmp++ = (static_cast<cell>(*data++)) & 0xFF; } } else { realParams[i] = params[i]; } } for (i = m_NumParams - 1; i >= 0; i--) amx_Push(m_Amx, realParams[i]); // exec cell retVal; #if defined BINLOG_ENABLED g_BinLog.WriteOp(BinLog_CallPubFunc, pPlugin->getId(), m_Func); #endif int err = amx_Exec(m_Amx, &retVal, m_Func); if (err != AMX_ERR_NONE) { //Did something else set an error? if (pDebugger && pDebugger->ErrorExists()) { //we don't care, something else logged the error. } else if (err != -1) { //nothing logged the error so spit it out anyway LogError(m_Amx, err, NULL); } } if (pDebugger) pDebugger->EndExec(); m_Amx->error = AMX_ERR_NONE; // cleanup strings & arrays for (i = 0; i < m_NumParams; ++i) { if (m_ParamTypes[i] == FP_STRING) { amx_Release(m_Amx, realParams[i]); } else if (m_ParamTypes[i] == FP_STRINGEX) { // copy back amx_GetStringOld(reinterpret_cast<char*>(params[i]), physAddrs[i], 0); amx_Release(m_Amx, realParams[i]); } else if (m_ParamTypes[i] == FP_ARRAY) { // copy back if (preparedArrays[params[i]].copyBack) { cell *tmp = physAddrs[i]; if (preparedArrays[params[i]].type == Type_Cell) { memcpy(preparedArrays[params[i]].ptr, tmp, preparedArrays[params[i]].size * sizeof(cell)); } else { char *data = (char*)preparedArrays[params[i]].ptr; for (unsigned int j = 0; j < preparedArrays[params[i]].size; ++j) *data++ = static_cast<char>(*tmp++ & 0xFF); } } amx_Release(m_Amx, realParams[i]); } } m_InExec = false; return retVal; }
cell AMX_NATIVE_CALL amx_DC_CMD(AMX* amx, cell* params) { cell *addr; int len; amx_GetAddr(amx, params[2], &addr); amx_StrLen(addr, &len); if(len>127) len=127; ++len; char cmdtext[128]; amx_GetString(cmdtext, addr, 0, len); cmdtext[0] = '_'; // converting string to lower case int pos=0, cmd_end; do{ ++pos; if(('A' <= cmdtext[pos]) && (cmdtext[pos] <= 'Z')) cmdtext[pos] += ('a'-'A'); else if(cmdtext[pos] == '\0') break; else if(cmdtext[pos] == ' ') { cmd_end = pos; cmdtext[pos++] = '\0'; goto loop1_exit; } }while(1); cmd_end = 0; loop1_exit: // search for command index in all AMX instances int pubidx; cell retval, params_addr; int i; for(i=0; i<=lastAMX; ++i) { if((amx_List[i].amx != NULL) && (amx_FindPublic(amx_List[i].amx, cmdtext, &pubidx) == AMX_ERR_NONE)) { // if current AMX instance has OnPlayerCommandReceived callback - invoke it if(amx_List[i].OPCR != 0x7FFFFFFF) { // restore some symbols in cmdtext cmdtext[0] = '/'; if(cmd_end>0) cmdtext[cmd_end] = ' '; amx_PushString(amx_List[i].amx, ¶ms_addr, 0, cmdtext, 0, 0); amx_Push(amx_List[i].amx, params[1]); amx_Exec(amx_List[i].amx, &retval, amx_List[i].OPCR); amx_Release(amx_List[i].amx, params_addr); // if OPCR returned 0 - command execution rejected if(retval == 0) return 1; cmdtext[0] = '_'; // restore AMX-styled command name if(cmd_end>0) // and separate it from parameters (again =/) cmdtext[cmd_end] = ' '; } // remove extra space characters between command name and parameters while(cmdtext[pos] == ' ') pos++; amx_PushString(amx_List[i].amx, ¶ms_addr, 0, cmdtext+pos, 0, 0); amx_Push(amx_List[i].amx, params[1]); amx_Exec(amx_List[i].amx, &retval, pubidx); amx_Release(amx_List[i].amx, params_addr); // if current AMX instance has OnPlayerCommandPerformed callback - invoke it if(amx_List[i].OPCP != 0x7FFFFFFF) { cmdtext[0] = '/'; if(cmd_end>0) cmdtext[cmd_end] = ' '; amx_Push(amx_List[i].amx, retval); amx_PushString(amx_List[i].amx, ¶ms_addr, 0, cmdtext, 0, 0); amx_Push(amx_List[i].amx, params[1]); amx_Exec(amx_List[i].amx, &retval, amx_List[i].OPCP); amx_Release(amx_List[i].amx, params_addr); } return 1; } } // if command wasn't found - perhaps this is an alternative command if(Alts_n != 0) { int hash; // remove extra space characters between command name and parameters //logprintf("attempting to find alt %s, len = %d", cmdtext, (cmdtext[pos])?(pos-1):(pos)); Murmur3(cmdtext, (cmdtext[pos])?(pos-1):(pos), &hash); if(cmdtext[pos]) { pos--; while(cmdtext[++pos] == ' '){} } //logprintf((char*)"Murmur3(%s) = 0x%X", cmdtext, hash); boost::unordered_map<int,int>::const_iterator alt; for(i=0; i<=lastAMX; ++i) { if((amx_List[i].amx != NULL) && ((alt = Alts[i].find(hash)) != Alts[i].end())) { pubidx = alt->second; //logprintf("found alt: %s, amx = %d, idx = %d", cmdtext, (int)amx, pubidx); if(amx_List[i].OPCR != 0x7FFFFFFF) { // restore some symbols in cmdtext cmdtext[0] = '/'; if(cmd_end>0) cmdtext[cmd_end] = ' '; amx_PushString(amx_List[i].amx, ¶ms_addr, 0, cmdtext, 0, 0); amx_Push(amx_List[i].amx, params[1]); amx_Exec(amx_List[i].amx, &retval, amx_List[i].OPCR); amx_Release(amx_List[i].amx, params_addr); // if OPCR returned 0 - command execution rejected if(retval == 0) return 1; cmdtext[0] = '_'; // restore AMX-styled command name if(cmd_end>0) // and separate it from parameters (again =/) cmdtext[cmd_end] = ' '; } // remove extra space characters between command name and parameters while(cmdtext[pos] == ' ') pos++; amx_PushString(amx_List[i].amx, ¶ms_addr, 0, cmdtext+pos, 0, 0); amx_Push(amx_List[i].amx, params[1]); amx_Exec(amx_List[i].amx, &retval, pubidx); amx_Release(amx_List[i].amx, params_addr); // if current AMX instance has OnPlayerCommandPerformed callback - invoke it if(amx_List[i].OPCP != 0x7FFFFFFF) { cmdtext[0] = '/'; if(cmd_end>0) cmdtext[cmd_end] = ' '; amx_Push(amx_List[i].amx, retval); amx_PushString(amx_List[i].amx, ¶ms_addr, 0, cmdtext, 0, 0); amx_Push(amx_List[i].amx, params[1]); amx_Exec(amx_List[i].amx, &retval, amx_List[i].OPCP); amx_Release(amx_List[i].amx, params_addr); } return 1; } } } // if command not found - call OnPlayerCommandPerformed callback in gamemode AMX (success = -1) if(amx_List[0].OPCP != 0x7FFFFFFF) { cmdtext[0] = '/'; if(cmd_end>0) cmdtext[cmd_end] = ' '; amx_Push(amx_List[0].amx, -1); amx_PushString(amx_List[0].amx, ¶ms_addr, 0, cmdtext, 0, 0); amx_Push(amx_List[0].amx, params[1]); amx_Exec(amx_List[0].amx, &retval, amx_List[0].OPCP); amx_Release(amx_List[0].amx, params_addr); } return 1; }
// native ArraySortEx(Array:array, const comparefunc[], data[]="", data_size=0); static cell AMX_NATIVE_CALL ArraySortEx(AMX* amx, cell* params) { CellArray* vec = ArrayHandles.lookup(params[1]); if (!vec) { LogError(amx, AMX_ERR_NATIVE, "Invalid array handle provided (%d)", params[1]); return 0; } int len; char* funcName = get_amxstring(amx, params[2], 0, len); int func = registerSPForwardByName(amx, funcName, FP_CELL, FP_CELL, FP_CELL, FP_CELL, FP_CELL, FP_DONE); if (!func) { LogError(amx, AMX_ERR_NATIVE, "The public function \"%s\" was not found.", funcName); return 0; } size_t arraysize = vec->size(); size_t blocksize = vec->blocksize(); cell *array = vec->base(); cell amx_addr1 = 0, amx_addr2 = 0, *phys_addr = NULL; if (blocksize > 1) { int err; if ((err = amx_Allot(amx, blocksize, &amx_addr1, &phys_addr)) != AMX_ERR_NONE || ( err = amx_Allot(amx, blocksize, &amx_addr2, &phys_addr)) != AMX_ERR_NONE) { LogError(amx, err, "Ran out of memory"); return 0; } } ArraySort_s oldinfo = SortInfo; SortInfo.func = func; SortInfo.array_base = array; SortInfo.array_bsize = static_cast<cell>(blocksize); SortInfo.array_hndl = params[1]; SortInfo.data = params[3]; SortInfo.size = params[4]; SortInfo.amx = amx; SortInfo.addr1 = amx_addr1; SortInfo.addr2 = amx_addr2; qsort(array, arraysize, blocksize * sizeof(cell), blocksize > 1 ? SortArrayListExArray : SortArrayListExCell); SortInfo = oldinfo; if (blocksize > 1) { amx_Release(amx, amx_addr1); amx_Release(amx, amx_addr2); } unregisterSPForward(func); return 1; }
int Invoke::callNative(const PAWN::Native * native, ...) { if (amx_list.empty() || amx_map.find(native->name) == amx_map.end()) { return 0; } unsigned int amx_addr = amx_map[native->name], count = strlen(native->data), variables = 0; cell * params = new cell[count + 1], * physAddr[6]; params[0] = count * sizeof(cell); va_list input; va_start(input, native); for (unsigned int i = 0; i < count; ++i) { switch (native->data[i]) { case 'd': case 'i': { params[i + 1] = va_arg(input, int); } break; case 'f': { float value = (float)va_arg(input, double); params[i + 1] = amx_ftoc(value); } break; case 's': { char * string = va_arg(input, char *); amx_Allot(amx_list.front(), strlen(string) + 1, ¶ms[i + 1], &physAddr[variables++]); amx_SetString(physAddr[variables - 1], string, 0, 0, strlen(string) + 1); } break; case 'v': { va_arg(input, void *); amx_Allot(amx_list.front(), 1, ¶ms[i + 1], &physAddr[variables++]); } break; case 'p': { va_arg(input, void *); int size = va_arg(input, int); amx_Allot(amx_list.front(), size, ¶ms[++i], &physAddr[variables++]); params[i + 1] = size; } break; } } va_end(input); amx_Function_t amx_Function = (amx_Function_t)amx_addr; int value = amx_Function(amx_list.front(), params); if (variables) { variables = 0; va_start(input, native); for (unsigned int i = 0; i < count; ++i) { switch (native->data[i]) { case 's': { amx_Release(amx_list.front(), params[i + 1]); } break; case 'v': { unsigned int * value = va_arg(input, unsigned int *), * returnValue = (unsigned int *)physAddr[variables++]; * value = * returnValue; amx_Release(amx_list.front(), params[i + 1]); } break; case 'p': { char * text = va_arg(input, char *); int size = va_arg(input, int); amx_GetString(text, physAddr[variables++], 0, size); amx_Release(amx_list.front(), params[++i]); } break; default: { va_arg(input, void *); } break; } } va_end(input); } delete [] params; return value; }
PLUGIN_EXPORT void PLUGIN_CALL ProcessTick() { if(gCore->isPTEmpty()) return; int idx = NULL; cell amxAddr[3]; std::pair<unsigned int, amxCore::amxPush> data = gCore->getFromPT(); amxPool::svrData fData; for(std::list<AMX *>::iterator i = gCore->amxList.begin(); i != gCore->amxList.end(); i++) { switch(data.first) { case ADDON_CALLBACK_OTWS: // Addon_OnTCPWorkerStarted(workerid); { if(!amx_FindPublic(*i, "Addon_OnTCPWorkerStarted", &idx)) { amx_Push(*i, data.second.clientid); // workerid amx_Exec(*i, NULL, idx); } } break; case ADDON_CALLBACK_OTWE: // Addon_OnTCPWorkerError(workerid, error_code, error[]); { if(!amx_FindPublic(*i, "Addon_OnTCPWorkerError", &idx)) { fData.reset(); fData = data.second.args.at(1); amx_PushString(*i, &amxAddr[0], NULL, fData.string.c_str(), NULL, NULL); // error[] fData.reset(); fData = data.second.args.at(0); amx_Push(*i, fData.integer); // error_code amx_Push(*i, data.second.clientid); // workerid amx_Exec(*i, NULL, idx); amx_Release(*i, amxAddr[0]); } } break; case ADDON_CALLBACK_OCC: // Addon_OnClientConnect(clientid, client_ip[]); { if(!amx_FindPublic(*i, "Addon_OnClientConnect", &idx)) { fData.reset(); fData = data.second.args.at(0); amx_PushString(*i, &amxAddr[0], NULL, fData.string.c_str(), NULL, NULL); // client_ip[] amx_Push(*i, data.second.clientid); // clientid amx_Exec(*i, NULL, idx); amx_Release(*i, amxAddr[0]); } } break; case ADDON_CALLBACK_OCCE: // Addon_OnClientConnectError(client_ip[], error_code, error[]); { if(!amx_FindPublic(*i, "Addon_OnClientConnectError", &idx)) { fData.reset(); fData = data.second.args.at(2); amx_PushString(*i, &amxAddr[0], NULL, fData.string.c_str(), NULL, NULL); // error[] fData.reset(); fData = data.second.args.at(1); amx_Push(*i, fData.integer); // error_code fData.reset(); fData = data.second.args.at(0); amx_PushString(*i, &amxAddr[1], NULL, fData.string.c_str(), NULL, NULL); // client_ip[] amx_Exec(*i, NULL, idx); amx_Release(*i, amxAddr[1]); amx_Release(*i, amxAddr[0]); } } break; case ADDON_CALLBACK_OCD: // Addon_OnClientDisconnect(clientid, client_ip[], reason_code, reason[]); { if(!amx_FindPublic(*i, "Addon_OnClientDisconnect", &idx)) { fData.reset(); fData = data.second.args.at(2); amx_PushString(*i, &amxAddr[0], NULL, fData.string.c_str(), NULL, NULL); // reason[] fData.reset(); fData = data.second.args.at(1); amx_Push(*i, fData.integer); // reason_code fData.reset(); fData = data.second.args.at(0); amx_PushString(*i, &amxAddr[1], NULL, fData.string.c_str(), NULL, NULL); // client_ip[] amx_Push(*i, data.second.clientid); // clientid amx_Exec(*i, NULL, idx); amx_Release(*i, amxAddr[1]); amx_Release(*i, amxAddr[0]); } } break; case ADDON_CALLBACK_OCST: // Addon_OnClientScreenshotTaken(clientid, remote_filename[]); { if(!amx_FindPublic(*i, "Addon_OnClientScreenshotTaken", &idx)) { fData.reset(); fData = data.second.args.at(0); amx_PushString(*i, &amxAddr[0], NULL, fData.string.c_str(), NULL, NULL); // remote_filename[] amx_Push(*i, data.second.clientid); // clientid amx_Exec(*i, NULL, idx); amx_Release(*i, amxAddr[0]); } } break; case ADDON_CALLBACK_OCSE: // Addon_OnClientScreenshotError(clientid, remote_filename[], error[]); { if(!amx_FindPublic(*i, "Addon_OnClientScreenshotError", &idx)) { fData.reset(); fData = data.second.args.at(1); amx_PushString(*i, &amxAddr[0], NULL, fData.string.c_str(), NULL, NULL); // error[] fData.reset(); fData = data.second.args.at(0); amx_PushString(*i, &amxAddr[1], NULL, fData.string.c_str(), NULL, NULL); // remote_filename[] amx_Push(*i, data.second.clientid); // clientid amx_Exec(*i, NULL, idx); amx_Release(*i, amxAddr[1]); amx_Release(*i, amxAddr[0]); } } break; case ADDON_CALLBACK_OLFT: // Addon_OnLocalFileTransfered(filename[], clientid, remote_filename[], bytes_transfered); { // some dirty cleanup amxTransfer *pointer = gPool->getClientSession(data.second.clientid)->pool().fileT; delete pointer; if(!amx_FindPublic(*i, "Addon_OnLocalFileTransfered", &idx)) { fData.reset(); fData = data.second.args.at(2); amx_Push(*i, fData.integer); // bytes_transfered fData.reset(); fData = data.second.args.at(1); amx_PushString(*i, &amxAddr[0], NULL, fData.string.c_str(), NULL, NULL); // remote_filename[] amx_Push(*i, data.second.clientid); // clientid fData.reset(); fData = data.second.args.at(0); amx_PushString(*i, &amxAddr[1], NULL, fData.string.c_str(), NULL, NULL); // filename[] amx_Exec(*i, NULL, idx); amx_Release(*i, amxAddr[1]); amx_Release(*i, amxAddr[0]); } } break; case ADDON_CALLBACK_OLFTE: // Addon_OnLocalFileTransferError(filename[], clientid, remote_filename[], error_code, error[]); { // some dirty cleanup amxTransfer *pointer = gPool->getClientSession(data.second.clientid)->pool().fileT; delete pointer; if(!amx_FindPublic(*i, "Addon_OnLocalFileTransferError", &idx)) { fData.reset(); fData = data.second.args.at(3); amx_PushString(*i, &amxAddr[0], NULL, fData.string.c_str(), NULL, NULL); // error[] fData.reset(); fData = data.second.args.at(2); amx_Push(*i, fData.integer); // error_code fData.reset(); fData = data.second.args.at(1); amx_PushString(*i, &amxAddr[1], NULL, fData.string.c_str(), NULL, NULL); // remote_filename[] amx_Push(*i, data.second.clientid); // clientid fData.reset(); fData = data.second.args.at(0); amx_PushString(*i, &amxAddr[2], NULL, fData.string.c_str(), NULL, NULL); // filename[] amx_Exec(*i, NULL, idx); amx_Release(*i, amxAddr[2]); amx_Release(*i, amxAddr[1]); amx_Release(*i, amxAddr[0]); } } break; case ADDON_CALLBACK_ORFT: // Addon_OnRemoteFileTransfered(remote_filename[], clientid, filename[], bytes_transfered); { // some dirty cleanup amxTransfer *pointer = gPool->getClientSession(data.second.clientid)->pool().fileT; delete pointer; if(!amx_FindPublic(*i, "Addon_OnRemoteFileTransfered", &idx)) { fData.reset(); fData = data.second.args.at(2); amx_Push(*i, fData.integer); // bytes_transfered fData.reset(); fData = data.second.args.at(1); amx_PushString(*i, &amxAddr[0], NULL, fData.string.c_str(), NULL, NULL); // filename[] amx_Push(*i, data.second.clientid); // clientid fData.reset(); fData = data.second.args.at(0); amx_PushString(*i, &amxAddr[1], NULL, fData.string.c_str(), NULL, NULL); // remote_filename[] amx_Exec(*i, NULL, idx); amx_Release(*i, amxAddr[1]); amx_Release(*i, amxAddr[0]); } } break; case ADDON_CALLBACK_ORFTE: // Addon_OnRemoteFileTransferError(remote_filename[], clientid, filename[], error_code, error[]); { // some dirty cleanup amxTransfer *pointer = gPool->getClientSession(data.second.clientid)->pool().fileT; delete pointer; if(!amx_FindPublic(*i, "Addon_OnRemoteFileTransferError", &idx)) { fData.reset(); fData = data.second.args.at(3); amx_PushString(*i, &amxAddr[0], NULL, fData.string.c_str(), NULL, NULL); // error[] fData.reset(); fData = data.second.args.at(2); amx_Push(*i, fData.integer); // error_code fData.reset(); fData = data.second.args.at(1); amx_PushString(*i, &amxAddr[1], NULL, fData.string.c_str(), NULL, NULL); // filename[] amx_Push(*i, data.second.clientid); // clientid fData.reset(); fData = data.second.args.at(0); amx_PushString(*i, &amxAddr[2], NULL, fData.string.c_str(), NULL, NULL); // remote_filename[] amx_Exec(*i, NULL, idx); amx_Release(*i, amxAddr[2]); amx_Release(*i, amxAddr[1]); amx_Release(*i, amxAddr[0]); } } break; } } }
cell CForward::execute(cell *params, ForwardPreparedArray *preparedArrays) { cell realParams[FORWARD_MAX_PARAMS]; cell *physAddrs[FORWARD_MAX_PARAMS]; const int STRINGEX_MAXLENGTH = 128; cell globRetVal = 0; AMXForwardList::iterator iter; for (iter = m_Funcs.begin(); iter != m_Funcs.end(); iter++) { if (iter->pPlugin->isExecutable(iter->func)) { // Get debug info AMX *amx = (*iter).pPlugin->getAMX(); Debugger *pDebugger = (Debugger *)amx->userdata[UD_DEBUGGER]; if (pDebugger) pDebugger->BeginExec(); // handle strings & arrays int i; for (i = 0; i < m_NumParams; ++i) { if (m_ParamTypes[i] == FP_STRING || m_ParamTypes[i] == FP_STRINGEX) { const char *str = reinterpret_cast<const char*>(params[i]); cell *tmp; if (!str) str = ""; amx_Allot(iter->pPlugin->getAMX(), (m_ParamTypes[i] == FP_STRING) ? strlen(str) + 1 : STRINGEX_MAXLENGTH, &realParams[i], &tmp); amx_SetStringOld(tmp, str, 0, 0); physAddrs[i] = tmp; } else if (m_ParamTypes[i] == FP_ARRAY) { cell *tmp; amx_Allot(amx, preparedArrays[params[i]].size, &realParams[i], &tmp); physAddrs[i] = tmp; if (preparedArrays[params[i]].type == Type_Cell) { memcpy(tmp, preparedArrays[params[i]].ptr, preparedArrays[params[i]].size * sizeof(cell)); } else { char *data = (char*)preparedArrays[params[i]].ptr; for (unsigned int j = 0; j < preparedArrays[params[i]].size; ++j) *tmp++ = (static_cast<cell>(*data++)) & 0xFF; } } else { realParams[i] = params[i]; } } //Push the parameters in reverse order. Weird, unfriendly part of Small 3.0! for (i = m_NumParams-1; i >= 0; i--) { amx_Push(amx, realParams[i]); } // exec cell retVal = 0; #if defined BINLOG_ENABLED g_BinLog.WriteOp(BinLog_CallPubFunc, (*iter).pPlugin->getId(), iter->func); #endif int err = amx_Exec(amx, &retVal, iter->func); // log runtime error, if any if (err != AMX_ERR_NONE) { //Did something else set an error? if (pDebugger && pDebugger->ErrorExists()) { //we don't care, something else logged the error. } else if (err != -1) { //nothing logged the error so spit it out anyway LogError(amx, err, NULL); } } amx->error = AMX_ERR_NONE; if (pDebugger) pDebugger->EndExec(); // cleanup strings & arrays for (i = 0; i < m_NumParams; ++i) { if (m_ParamTypes[i] == FP_STRING) { amx_Release(iter->pPlugin->getAMX(), realParams[i]); } else if (m_ParamTypes[i] == FP_STRINGEX) { // copy back amx_GetStringOld(reinterpret_cast<char*>(params[i]), physAddrs[i], 0); amx_Release(iter->pPlugin->getAMX(), realParams[i]); } else if (m_ParamTypes[i] == FP_ARRAY) { // copy back if (preparedArrays[params[i]].copyBack) { cell *tmp = physAddrs[i]; if (preparedArrays[params[i]].type == Type_Cell) { memcpy(preparedArrays[params[i]].ptr, tmp, preparedArrays[params[i]].size * sizeof(cell)); } else { char *data = (char*)preparedArrays[params[i]].ptr; for (unsigned int j = 0; j < preparedArrays[params[i]].size; ++j) *data++ = static_cast<char>(*tmp++ & 0xFF); } } amx_Release(iter->pPlugin->getAMX(), realParams[i]); } } // decide what to do (based on exectype and retval) switch (m_ExecType) { case ET_IGNORE: break; case ET_STOP: if (retVal > 0) return retVal; case ET_STOP2: if (retVal == 1) return 1; else if (retVal > globRetVal) globRetVal = retVal; break; case ET_CONTINUE: if (retVal > globRetVal) globRetVal = retVal; break; } } } return globRetVal; }
WebSocketClient::WebSocketClient( const std::string& connectName, const std::string& failName, const std::string& disconnectName, const std::string& messageName) : m_functionConnectName(connectName), m_functionFailName(failName), m_functionDisconnectName(disconnectName), m_functionMessageName(messageName) { // Disable logging m_client.set_access_channels(websocketpp::log::alevel::none); m_client.set_error_channels(websocketpp::log::alevel::none); // Set handlers m_client.set_open_handler([&](WebsocketConnection) { m_connected = true; int idx = getID(); std::string func = m_functionConnectName; SynchronizationCall::sharedSynronizationCall() += [idx, func]() { int funcIDX = 0; if(!amx_FindPublic(PAWN::GetAMX(), func.c_str(), &funcIDX)) { amx_Push(PAWN::GetAMX(), idx); amx_Exec(PAWN::GetAMX(), NULL, funcIDX); } }; }); m_client.set_fail_handler([&](WebsocketConnection) { m_connected = false; int idx = getID(); std::string func = m_functionFailName; SynchronizationCall::sharedSynronizationCall() += [idx, func]() { int funcIDX = 0; if(!amx_FindPublic(PAWN::GetAMX(), func.c_str(), &funcIDX)) { amx_Push(PAWN::GetAMX(), idx); amx_Exec(PAWN::GetAMX(), NULL, funcIDX); } }; }); m_client.set_close_handler([&](WebsocketConnection) { m_connected = false; int idx = getID(); std::string func = m_functionDisconnectName; SynchronizationCall::sharedSynronizationCall() += [idx, func]() { int funcIDX = 0; if(!amx_FindPublic(PAWN::GetAMX(), func.c_str(), &funcIDX)) { amx_Push(PAWN::GetAMX(), idx); amx_Exec(PAWN::GetAMX(), NULL, funcIDX); } }; }); m_client.set_message_handler([&](WebsocketConnection, WebsocketMessage msg) { try { std::string data = msg->get_payload(); int idx = getID(); std::string func = m_functionMessageName; SynchronizationCall::sharedSynronizationCall() += [idx, func, data]() { int funcIDX = 0; if(!amx_FindPublic(PAWN::GetAMX(), func.c_str(), &funcIDX)) { cell addr = 0; amx_PushString(PAWN::GetAMX(), &addr, NULL, data.c_str(), NULL, NULL); amx_Push(PAWN::GetAMX(), idx); amx_Exec(PAWN::GetAMX(), NULL, funcIDX); amx_Release(PAWN::GetAMX(), addr); } }; } catch(...) { } }); // Initialize ASIO m_client.init_asio(); }