SRL Archive - General Botting Help

Stuck in recv function


riwu

2015-01-18 02:50:21

Recently i have been having problem loading RS (in both browser and SMART), requiring multiple tries to load successfully. So i'm trying to setup a loop in SMART so that it auto retry for me when failed to spawn.
After some debugging, i confirmed that it's stuck in https://github.com/BenLand100/SMART/blob/6f5468c817d255584d3f6cf6823a4a1fe5494888/src/SmartRemote.cpp#L131
So i split the code from line130 onwards into

int sel = select(client->socket+1, &rfds, &rfds, NULL, &tv);
if (sel) {
debug << sel << endl;
SOCKET s = client->socket;
char* buf = (char*)&funid;
int len = sizeof(char);
debug << "s: " << s << " buf: " << *buf << " len: " << len << endl;
int intRecv = recv(s, buf, len, 0);

However, the values returned for both failed attempts and successful attempts appear to be the same.
sel is always 1, *buf is always 'I', len is always 1, only s varies from ~1150 to 1250.

So how could i predetermine if it's going to fail or pass so that if it's going to fail i wouldn't go into recv() and get stuck inside?
http://msdn.microsoft.com/en-us/library/windows/desktop/ms740121%28v=vs.85%29.aspx
Changing the flags argument didn't help too.

bonsai

2015-01-18 04:18:44

From: riwu
Recently i have been having problem loading RS (in both browser and SMART), requiring multiple tries to load successfully. So i'm trying to setup a loop in SMART so that it auto retry for me when failed to spawn.
After some debugging, i confirmed that it's stuck in https://github.com/BenLand100/SMART/blob/6f5468c817d255584d3f6cf6823a4a1fe5494888/src/SmartRemote.cpp#L131
So i split the code from line130 onwards into

int sel = select(client->socket+1, &rfds, &rfds, NULL, &tv);
if (sel) {
debug << sel << endl;
SOCKET s = client->socket;
char* buf = (char*)&funid;
int len = sizeof(char);
debug << "s: " << s << " buf: " << *buf << " len: " << len << endl;
int intRecv = recv(s, buf, len, 0);

However, the values returned for both failed attempts and successful attempts appear to be the same.
sel is always 1, *buf is always 'I', len is always 1, only s varies from ~1150 to 1250.

So how could i predetermine if it's going to fail or pass so that if it's going to fail i wouldn't go into recv() and get stuck inside?
http://msdn.microsoft.com/en-us/library/windows/desktop/ms740121%28v=vs.85%29.aspx
Changing the flags argument didn't help too.


I don't know FPC details, but as I recall select() returns -1/0/1 or the number of ready file descriptors. Maybe that test in there should be 'if (sel > 0)'

riwu

2015-01-18 04:31:13

From: bonsai
I don't know FPC details, but as I recall select() returns -1/0/1 or the number of ready file descriptors. Maybe that test in there should be 'if (sel > 0)'

The code is C++ not FP :p
Anyway sel returns 1 both when Smart successfully spawned and when Smart failed to spawn (stuck in recv), so i think i'd need some other tests other than select() to determine if it will be stuck in recv.
@Brandon; any idea?

bonsai

2015-01-18 05:59:58

From: riwu
The code is C++ not FP :p
Anyway sel returns 1 both when Smart successfully spawned and when Smart failed to spawn (stuck in recv), so i think i'd need some other tests other than select() to determine if it will be stuck in recv.
@Brandon; any idea?


Ehehe, I need to stop posting at wake-up time. Yes, I see this is C code :)

I stick to my claim that the test is flawed. Only if select() > 0 is a socket ready. I understand you're saying it is getting a '1' response in this case but sometime it will get SOCKET_ERROR and bug out.

select(client->socket+1, &rfds, &rfds, NULL, &tv);

Notice &rfds is passed as both the readfds and writefds. Select() can return '1' if this socket is writeble. Not readable. Then your read would hang.

I'm going to suggest trying this:

select(client->socket+1, &rfds, NULL, NULL, &tv);

riwu

2015-01-18 07:21:49

From: bonsai
Ehehe, I need to stop posting at wake-up time. Yes, I see this is C code :)

I stick to my claim that the test is flawed. Only if select() > 0 is a socket ready. I understand you're saying it is getting a '1' response in this case but sometime it will get SOCKET_ERROR and bug out.

select(client->socket+1, &rfds, &rfds, NULL, &tv);

Notice &rfds is passed as both the readfds and writefds. Select() can return '1' if this socket is writeble. Not readable. Then your read would hang.

I'm going to suggest trying this:

select(client->socket+1, &rfds, NULL, NULL, &tv);

Hmm you are right that it is returning 1 even though it's not readable (only writable). I thought when u supply arguments to both, it will check and return 1 only if it is both readable and writable, otherwise kind of defeats the purpose of using optional parameters…

Though when i set it to check readable only, it always returns -1, even when the client successfully spawned…
So there's still no test to check whether the call to recv will be blocked.

Brandon

2015-01-18 11:35:29


int CheckSocket(int sock, long sec, long usec, bool Read)
{
fd_set fds = {0};
struct timeval tv = {0};
FD_ZERO(&fds);
FD_SET(sock, &fds);
tv.tv_sec = sec;
tv.tv_usec = usec;
return select(sock + 1, Read ? &fds : NULL, Read ? NULL : &fds, NULL, &tv);
}


#if defined _WIN32 || defined _WIN64
std::string LastErrorMessage()
{
DWORD Error = GetLastError();
LPTSTR lpMsgBuf = nullptr;
FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, nullptr, Error, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), reinterpret_cast<LPTSTR>(&lpMsgBuf), 0, nullptr);
std::string result = std::string(lpMsgBuf);
LocalFree(lpMsgBuf);
return result;
}
#else
std::string LastErrorMessage()
{
return std::string(strerror(errno));
}
#endif



Then call:


for (int i = 0; i < 600; ++i)
{
int sel = CheckSocket(client->socket + 1, 0, 100000, true); //100ms time-out on read.
if (sel > 0) //If the socket is ready to be read and != SOCKET_ERROR aka -1.
{
if (recv(client->socket, (char*)&funid, sizeof(char), 0) != sizeof(char))
{
debug << "Call appears to have failed, or client successfully killed.\n";
debug << "Last Error: "<<LastErrorMessage()<<"\n"; //Print failure in proper format..
}
return;
}
}

riwu

2015-01-23 23:03:35

Thanks Brandon!
Had to add -std=c++0x to g++ build dir in MAKEFILE to get it to compile (nullptr keyword)

Seems like Jagex already fixed the problem though
http://services.runescape.com/m=news/service-disruption?jptg=ia&jptv=news_list

Will see if it works if it happens again :)