Alright, I'm trying to use the OSCAR protocol to connect to AIM. I've never done any networking before, so I'm encountering lots of problems with Winsock.
First, check out how a FLAP and a TLV are organized: http://iserverd1.khstu.ru/oscar/basic.html
Then, here is the login sequence: http://iserverd1.khstu.ru/oscar/login.html
Ok, so I set up a non-blocking socket like so:
Code:
Oscar::Oscar(HWND hwnd)
{
m_window=hwnd;
m_dataLen = -1;
m_log=LogManager::getInstance();
if(WSAStartup(MAKEWORD(1, 1), &m_wsaData))
{
int nret=WSAGetLastError();
m_log->Error(true, "Cannot startup Winsock! #%i", nret);
}
m_socket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
WSAAsyncSelect(m_socket, hwnd, WM_USER + 5, FD_CONNECT | FD_READ | FD_CLOSE);
if (m_socket == INVALID_SOCKET)
{
int nret=WSAGetLastError();
m_log->Error(true, "Socket creation failed! #%i", nret);
}
}
In my program that users the Oscar class:
Code:
LRESULT CALLBACK WindowsMsgHandler(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
switch(msg)
{
case WM_USER + 5:
switch(WSAGETSELECTEVENT(lParam))
{
// we have data to read!
case FD_READ:
mainOscar->ReadSocket();
break;
}
break;
....
And finally the ReadSocket command:
Code:
int Oscar::ReadSocket()
{
// don't make more FD_READ messages
WSAAsyncSelect(m_socket, m_window, WM_USER+5, FD_CONNECT|FD_CLOSE);
char byteBuffer;
int ret;
if(m_currBuffer.size() == 0)
{
while((ret=recv(m_socket, &byteBuffer, 1, 0)) == 1)
{
if(byteBuffer == FLAP_DATA_BYTE)
{
m_currBuffer.push_back((BYTE)byteBuffer);
break;
}
}
}
// 1+1+2+2 = 6 bytes before data
if(m_currBuffer.size() < 6 && m_currBuffer.size() > 0)
{
int ret;
while(m_currBuffer.size() < 6)
{
if(recv(m_socket, &byteBuffer, 1, 0) != 1)
break;
m_currBuffer.push_back(*((BYTE*)&byteBuffer));
}
}
// cool, we have the whole header! Now let's extract the data size!
if(m_currBuffer.size() == 6)
{
BYTE tempLen[2];
// do I need this endianness conversion??
tempLen[0]=m_currBuffer[5];
tempLen[1]=m_currBuffer[4];
m_dataLen=*((WORD*)tempLen);
}
// now we're recieving data
if(m_currBuffer.size() >= 6)
{
int ret;
// read while we have data and are still reading from the data
while(m_currBuffer.size() < m_dataLen+6)
{
if(recv(m_socket, &byteBuffer, 1, 0) != 1)
{
ret=WSAGetLastError();
if(ret == WSAEWOULDBLOCK)
Sleep(750);
break;
}
m_currBuffer.push_back(*((BYTE*)&byteBuffer));
}
}
// we're all done reading!
if(m_currBuffer.size() == m_dataLen+6)
{
if(m_currBuffer[0] != FLAP_DATA_BYTE)
{
m_log->Error(false, "Recieved a packet not starting with the FLAP header!");
return -1;
}
m_log->Log(GREEN, "FLAP of size %i bytes recieved!", m_dataLen+6);
m_log->Flush();
// now we have a flap, so continue reading
FLAP *incoming=new FLAP();
// channel
incoming->channel=*((BYTE*)&m_currBuffer[1]);
// sequence num
incoming->sequenceNum=*((WORD*)&m_currBuffer[2]);
// now read in the data
for(int i=0; i < m_dataLen; ++i)
{
incoming->data.push_back(*((BYTE*)&m_currBuffer[6+i]));
}
m_dataLen=-1;
while(m_currBuffer.size())
m_currBuffer.pop_back();
// restore FD_READ messages
WSAAsyncSelect(m_socket, m_window, WM_USER+5, FD_READ|FD_CONNECT|FD_CLOSE);
return 0;
}
Ok, now let's talk about the problem. When I use my endianness thing up top, I get a data length of 4. There are simply no FLAPs (including the error FLAP) that are of size 4. Also, it is being sent on channel 1 when it should most definitely be sent on channel 4.
Is there are endianness issue here, or something else at work?
Thanks!
P.S. I just logged the raw data I recieved and it looks like this (no endianness anythings, just in the order that it comes with line breaks seperating flap bit, flap header, flap data)
2A
01 BC D7 00 04
00 00 00 01
Also, note that I only read from 0 to length, so there may be more bits coming that I don't know about.