int32 MSNConnection::Receiver(void *con) { LOG(kProtocolName, liLow, "C[r] %lX: Receiver init", con); MSNConnection *connection = reinterpret_cast<MSNConnection *>(con); const uint32 kSleep = 2000000; BMessenger **kMsgr = &connection->fSockMsgr; int32 socket = 0; if ( !(*kMsgr)->IsValid() ) { LOG(kProtocolName, liLow, "C[r] %lX: Messenger wasn't valid!", connection); return B_ERROR; } BMessage reply; socket = connection->fSock; struct fd_set read; struct fd_set error; int16 bytes = 0; int32 processed = 0; char buffer[1024]; BString commandBuff = ""; int32 kNewLineLen = strlen("\r\n"); LOG(kProtocolName, liLow, "C[r] %lX: Starting receiver loop", connection); while ((*kMsgr)->IsValid() == true) { FD_ZERO(&read); FD_ZERO(&error); FD_SET(socket, &read); FD_SET(socket, &error); memset(buffer, 0, sizeof(buffer)); if (select(socket + 1, &read, NULL, &error, NULL) > 0) { if (FD_ISSET(socket, &error)) { LOG(kProtocolName, liLow, "C[r] %lX: Got socket error", connection); snooze(kSleep); continue; }; if (FD_ISSET(socket, &read)) { bytes = recv(socket, buffer, sizeof(buffer), 0); if (bytes > 0) { commandBuff.Append(buffer, bytes); processed += bytes; } else { if ((*kMsgr)->IsValid() == false) return B_OK; LOG(kProtocolName, liLow, "C[r] %lX: Socket got less than 0 (or 0)", connection); perror("SOCKET ERROR"); BMessage msg(msnmsgCloseConnection); msg.AddPointer("connection", con); connection->fManMsgr.SendMessage(&msg); connection->fState = otOffline; return B_ERROR; }; }; }; int32 commandLen = commandBuff.FindFirst("\r\n"); while (commandLen > 0) { BString command = ""; int32 totalLen = commandBuff.Length(); commandBuff.MoveInto(command, 0, commandLen + kNewLineLen); processed = totalLen - (commandLen + kNewLineLen); Command *comm = new Command(""); comm->MakeObject(command.String()); int32 payloadLen = 0; if (comm->ExpectsPayload(&payloadLen) == true) { LOG(kProtocolName, liDebug, "C[r] %lX: Payload of %i, have %i bytes", connection, payloadLen, processed); while (processed < payloadLen) { FD_ZERO(&read); FD_ZERO(&error); FD_SET(socket, &read); FD_SET(socket, &error); memset(buffer, 0, sizeof(buffer)); if (select(socket + 1, &read, NULL, &error, NULL) > 0) { if (FD_ISSET(socket, &error)) { LOG(kProtocolName, liLow, "C[r] %lX: Got socket error", connection); snooze(kSleep); continue; }; if (FD_ISSET(socket, &read)) { bytes = recv(socket, buffer, min_c(payloadLen - processed, (int32)sizeof(buffer)), 0); if (bytes > 0) { commandBuff.Append(buffer, bytes); processed += bytes; } else { if ( (*kMsgr)->IsValid() == false) return B_OK; LOG(kProtocolName, liLow, "--C[r] %lX: Socket got less than 0 (or 0: %i)", connection, bytes); perror("SOCKET ERROR"); BMessage msg(msnmsgCloseConnection); msg.AddPointer("connection", con); connection->fManMsgr.SendMessage(&msg); connection->fState = otOffline; return B_ERROR; }; }; }; }; // add payload to message? comm->AddPayload( commandBuff.String(), payloadLen, false ); commandBuff.Remove( 0, payloadLen ); processed = commandBuff.Length(); }; BMessage dataReady(msnmsgDataReady); dataReady.AddPointer("command", comm); (*kMsgr)->SendMessage(&dataReady); // this line needed to process several commands at once if they're in the // buffer commandLen = commandBuff.FindFirst("\r\n"); }; }; return B_OK; };