status_t MSNManager::TypingNotification(const char *passport, uint16 typing) { LOG(kProtocolName, liDebug, "Typing notify to %s", passport); if ((fConnectionState != otOffline) && (fConnectionState != otConnecting)) { if (fNoticeCon == NULL) { LOG(kProtocolName, liDebug, "Can't send typing notify to %s, fNoticeCon is null", passport); return B_ERROR; } // Set up message Command *msg = new Command("MSG"); msg->AddParam("U"); BString format = "MIME-Version: 1.0\r\n" "Content-Type: text/x-msmsgscontrol\r\n" "TypingUser: "******"\r\n"; format << "\r\n\r\n"; msg->AddPayload(format.String(), format.Length()); // Find connection bool needSB = false; connectionlist::iterator it; for ( it=fConnections.begin(); it != fConnections.end(); it++ ) { MSNSBConnection * c = dynamic_cast<MSNSBConnection*>( *it ); if ( c != NULL && c->IsSingleChatWith( passport ) ) break; } Command *sbReq = NULL; if (it == fConnections.end()) { LOG(kProtocolName, liDebug, "Can't send typing notify to %s, no open connection: opening new", passport); sbReq = new Command("XFR"); sbReq->AddParam("SB"); // Request a SB connection; fNoticeCon->Send(sbReq, qsImmediate); needSB = true; }; if (needSB) { fWaitingSBs[sbReq->TransactionID()] = std::pair<BString,Command*>(passport, msg); } else { (*it)->Send(msg); }; return B_OK; }; LOG(kProtocolName, liHigh, "Error sending typing notification to %s", passport); return B_ERROR; };
status_t MSNConnection::HandleVER( Command * /*command*/ ) { LOG(kProtocolName, liDebug, "C %lX: Processing VER", this); Command *reply = new Command("CVR"); reply->AddParam(kClientVer); reply->AddParam(fManager->Passport()); Send(reply); return B_OK; }
status_t MSNManager::MessageUser(const char *passport, const char *message) { if ((fConnectionState != otOffline) && (fConnectionState != otConnecting)) { if (fNoticeCon == NULL) { LOG(kProtocolName, liDebug, "Could not message %s, fNoticeCon is null", passport); return B_ERROR; } // Set up message Command *msg = new Command("MSG"); msg->AddParam("N"); // Don't ack packet BString format = "MIME-Version: 1.0\r\n" "Content-Type: text/plain; charset=UTF-8\r\n" "X-MMS-IM-Format: FN=Arial; EF=I; CO=0; CS=0; PF=22\r\n\r\n"; format << message; msg->AddPayload(format.String(), format.Length()); // Find connection bool needSB = false; connectionlist::iterator it; for ( it=fConnections.begin(); it != fConnections.end(); it++ ) { MSNSBConnection * c = dynamic_cast<MSNSBConnection*>( *it ); if ( c != NULL && c->IsSingleChatWith( passport ) ) break; } Command *sbReq = NULL; if (it == fConnections.end()) { LOG(kProtocolName, liDebug, "Could not message %s, no open connection: opening new", passport); sbReq = new Command("XFR"); sbReq->AddParam("SB"); // Request a SB connection; fNoticeCon->Send(sbReq, qsImmediate); needSB = true; }; if (needSB) { fWaitingSBs[sbReq->TransactionID()] = std::pair<BString,Command*>(passport, msg); } else { (*it)->Send(msg); }; return B_OK; }; LOG(kProtocolName, liHigh, "Error sending message to %s", passport); return B_ERROR; };
status_t MSNConnection::HandleSBS(Command *command) { printf("SBS Command!\n"); command->Debug(); Command *reply = new Command("CHG"); reply->AddParam("NLN"); BString caps = ""; caps << kOurCaps; reply->AddParam( caps.String() ); return B_OK; };
status_t MSNConnection::HandleCVR( Command * /*command*/ ) { LOG(kProtocolName, liDebug, "C %lX: Processing CVR", this); Command *reply = new Command("USR"); reply->AddParam("SSO"); // Auth type - Single Sign On // reply->AddParam("TWN"); // Authentication type reply->AddParam("I"); // Initiate reply->AddParam(fManager->Passport()); Send(reply); return B_OK; }
status_t MSNManager::SetDisplayName(const char *displayname) { if (fNoticeCon) { fDisplayName = displayname; Command *rea = new Command("PRP"); rea->AddParam("MFN"); rea->AddParam(DisplayName(), true); fNoticeCon->Send(rea); return B_OK; }; return B_ERROR; };
//status_t MSNConnection::HandleSYN( Command * /*command*/ ) { status_t MSNConnection::HandleSYN( Command * command ) { LOG(kProtocolName, liDebug, "C %lX: Processing SYN", this); // process SYN here as needed // ... // send CHG to set our status Command *reply = new Command("CHG"); reply->AddParam("NLN"); BString caps = ""; caps << kOurCaps; reply->AddParam( caps.String() ); Send(reply); return B_OK; };
status_t MSNManager::BlockUser(const char *passport) { status_t ret = B_ERROR; if (fNoticeCon) { buddymap::iterator i = fWaitingAuth.find(passport); if (i != fWaitingAuth.end()) fWaitingAuth.erase(i); Command *com = new Command("ADC"); com->AddParam("BL"); // Disallow to see our presence BString passParam = passport; passParam.Prepend("N="); com->AddParam(passParam.String());// Passport ret = fNoticeCon->Send(com); }; return ret; };
status_t MSNManager::Login(const char *server, uint16 port, const char *passport, const char *password, const char *displayname) { if ((passport == NULL) || (password == NULL)) { LOG(kProtocolName, liHigh, "MSNManager::Login: passport or password not " "set"); return B_ERROR; } fPassport = passport; fPassword = password; fDisplayName = displayname; // set up connection pool while ( fConnectionPool.size() < 3 ) fConnectionPool.push_back( new MSNConnection() ); if (fConnectionState == otOffline) { BMessage msg(msnmsgProgress); msg.AddString("id", "MSN Login"); msg.AddString("message", "MSN: Connecting.."); msg.AddFloat("progress", 0.10 ); BMessenger(this).SendMessage(&msg); if (fNoticeCon == NULL) { fNoticeCon = *fConnectionPool.begin(); fConnectionPool.pop_front(); fConnectionPool.push_back( new MSNConnection() ); fNoticeCon->SetTo( server, port, this ); }; if ( !fNoticeCon || !fNoticeCon->IsConnected() ) { LOG(kProtocolName, liDebug, "MSNManager::Login: Error connecting"); return B_ERROR; } Command *command = new Command("VER"); command->AddParam(kProtocolsVers); fNoticeCon->Send(command); return B_OK; } else { LOG(kProtocolName, liDebug, "MSNManager::Login: Already online"); return B_ERROR; }; };
status_t MSNManager::SetAway(bool away) { if (fNoticeCon) { Command *awayCom = new Command("CHG"); if (away) { awayCom->AddParam("AWY"); fConnectionState = otAway; } else { awayCom->AddParam("NLN"); fConnectionState = otOnline; }; BString caps = ""; caps << kOurCaps; awayCom->AddParam(caps.String()); fNoticeCon->Send(awayCom); return B_OK; }; return B_ERROR; };
void CBuilderCAI::ExecuteResurrect(Command& c) { // not all builders are resurrect-capable by default if (!owner->unitDef->canResurrect) return; CBuilder* builder = (CBuilder*) owner; if (c.params.size() == 1) { unsigned int id = (unsigned int) c.params[0]; if (id >= uh->MaxUnits()) { // resurrect feature CFeature* feature = featureHandler->GetFeature(id - uh->MaxUnits()); if (feature && feature->udef != NULL) { if (((c.options & INTERNAL_ORDER) && !(c.options & CONTROL_KEY) && IsFeatureBeingReclaimed(feature->id, owner)) || !ResurrectObject(feature)) { StopMove(); RemoveUnitFromResurrecters(owner); FinishCommand(); } else { AddUnitToResurrecters(owner); } } else { RemoveUnitFromResurrecters(owner); if (builder->lastResurrected && uh->GetUnitUnsafe(builder->lastResurrected) != NULL && owner->unitDef->canRepair) { // resurrection finished, start repair (by overwriting the current order) c = Command(CMD_REPAIR, c.options | INTERNAL_ORDER); c.AddParam(builder->lastResurrected); builder->lastResurrected = 0; inCommand = false; SlowUpdate(); return; } StopMove(); FinishCommand(); } } else { // resurrect unit RemoveUnitFromResurrecters(owner); FinishCommand(); } } else if (c.params.size() == 4) { // area resurrect const float3 pos = c.GetPos(0); const float radius = c.params[3]; if (FindResurrectableFeatureAndResurrect(pos, radius, c.options, (c.options & META_KEY))) { inCommand = false; SlowUpdate(); return; } if (!(c.options & ALT_KEY)) { FinishCommand(); } } else { // wrong number of parameters RemoveUnitFromResurrecters(owner); FinishCommand(); } return; }
int LuaCallOutHandler::CommandCallOuts::GiveCommand(lua_State* L) { MAI_ASSERT(lua_gettop(L) >= 2); pAIHelper aih = AIHelper::GetActiveInstance(); pIAICallback rcb = aih->GetCallbackHandler(); pAIUnitHandler uh = aih->GetAIUnitHandler(); if (!lua_isnumber(L, 1)) { return 0; } // unitID if (!lua_istable(L, 2)) { return 0; } // commandTbl const Uint32 unitID = lua_tointeger(L, 1); const Uint32 tableIdx = 2; // absolute index if (uh == NULL || uh->GetUnit(unitID) == NULL) { return 0; } Command cmd; // commandTbl = { // "type" = CMD_*, // "opts" = *_KEY, // "args" = { // [0] = 123, // [1] = 456, // [2] = 789, // ... // }, // [ "tag" = 31415927182818, ] // [ "ttl" = MAX_INT, ] // } lua_pushnil(L); while (lua_next(L, tableIdx) != 0) { const int keyType = lua_type(L, -2); const int valType = lua_type(L, -1); if (keyType == LUA_TSTRING) { const std::string key = lua_tostring(L, -2); switch (valType) { case LUA_TNUMBER: { if (key == "type") { cmd.id = lua_tonumber(L, -1); } else if (key == "opts") { cmd.options = lua_tonumber(L, -1); } else if (key == "tag" ) { cmd.tag = lua_tonumber(L, -1); } else if (key == "ttl" ) { cmd.timeOut = lua_tonumber(L, -1); } } break; case LUA_TTABLE: { // args sub-table (array) lua_pushnil(L); while (lua_next(L, -2) != 0) { MAI_ASSERT(lua_type(L, -2) == LUA_TNUMBER); // idx (key) MAI_ASSERT(lua_type(L, -1) == LUA_TNUMBER); // arg (val) cmd.AddParam(lua_tonumber(L, -1)); lua_pop(L, 1); } } break; } } // pop the VALUE lua_pop(L, 1); } lua_pushnumber(L, rcb->GiveOrder(unitID, &cmd)); return 1; }
void MSNManager::MessageReceived(BMessage *msg) { switch (msg->what) { case msnMessageRecveived: { BString passport = msg->FindString("passport"); BString message = msg->FindString("message"); fHandler->MessageFromUser(passport.String(), message.String()); } break; case msnmsgStatusChanged: { uint8 status = msg->FindInt8("status"); BString passport = msg->FindString("passport"); fHandler->StatusChanged(passport.String(), (online_types)status); } break; case msnmsgOurStatusChanged: { uint8 status = msg->FindInt8("status"); fHandler->StatusChanged(fPassport.String(), (online_types)status); fConnectionState = status; } break; case msnmsgNewConnection: { int16 port = 0; char *host = NULL; const char *type = NULL; if (msg->FindString("host", (const char **)&host) != B_OK) { LOG(kProtocolName, liLow, "Got a malformed new connection message" " (Host)"); return; }; if (msg->FindInt16("port", &port) != B_OK) { LOG(kProtocolName, liLow, "Got a malformed new connection message" " (Port)"); return; }; msg->FindString("type", &type); LOG(kProtocolName, liDebug, "Got a new connection to \"%s\":%i of type \"%s\"", host, port, type); if (strcmp(type, "NS") == 0) { //MSNConnection *con = new MSNConnection(host, port, this); MSNConnection *con = *fConnectionPool.begin(); fConnectionPool.pop_front(); fConnectionPool.push_back( new MSNConnection() ); con->SetTo( host, port, this ); //con->Lock(); Command *command = new Command("VER"); command->AddParam(kProtocolsVers); con->Send(command); fNoticeCon = con; LOG(kProtocolName, liDebug, " Set fNoticeCon"); return; } if (strcmp(type, "RNG") == 0) { MSNSBConnection *con = new MSNSBConnection(host, port, this); //con->Run(); const char *auth = msg->FindString("authString"); const char *sessionID = msg->FindString("sessionID"); //const char *inviter = msg->FindString("inviterPassport"); Command *command = new Command("ANS"); command->AddParam(fPassport.String()); command->AddParam(auth); command->AddParam(sessionID); con->Send(command); fConnections.push_back( con ); return; }; if (strcmp(type, "SB") == 0) { MSNSBConnection *con = new MSNSBConnection(host, port, this); //con->Run(); const char *authString = msg->FindString("authString"); Command *command = new Command("USR"); command->AddParam(Passport()); command->AddParam(authString); con->Send(command); waitingmsgmap::iterator it = fWaitingSBs.begin(); if (it != fWaitingSBs.end()) { BString passport = (*it).second.first; Command *message = (*it).second.second; Command *cal = new Command("CAL"); cal->AddParam(passport.String()); con->Send(cal, qsOnline); con->SendMessage(message); // assume it's a MSG here.. fConnections.push_back( con ); fWaitingSBs.erase( (*it).first ); }; }; } break; case msnmsgCloseConnection: { MSNConnection *con = NULL; msg->FindPointer("connection", (void **)&con); if (con != NULL) { LOG(kProtocolName, liLow, "Connection (%lX) closed", con); std::list<thread_id> threads; if (con == fNoticeCon) { LOG(kProtocolName, liLow, " Notice connection closed, go offline"); connectionlist::iterator i; for (i = fConnections.begin(); i != fConnections.end(); i++) { threads.push_back( (*i)->Thread() ); Command * bye = new Command("OUT"); bye->UseTrID(false); (*i)->Send(bye, qsImmediate); BMessenger(*i).SendMessage(B_QUIT_REQUESTED); }; fHandler->StatusChanged(Passport(), otOffline); fNoticeCon = NULL; fConnectionState = otOffline; LOG(kProtocolName, liDebug, " Unset fNoticeCon"); }; threads.push_back( con->Thread() ); BMessenger(con).SendMessage(B_QUIT_REQUESTED); connectionlist::iterator i = find(fConnections.begin(), fConnections.end(), con); if ( i != fConnections.end() ) fConnections.erase( i ); wait_for_threads( threads ); }; } break; case msnmsgRemoveConnection: { MSNConnection *con = NULL; msg->FindPointer("connection", (void **)&con); if (con != NULL) { connectionlist::iterator i = find(fConnections.begin(), fConnections.end(), con); LOG(kProtocolName, liLow, "Connection (%lX) removed", con); if ( i != fConnections.end() ) { // don't call anything in con, it's already deleted. fConnections.erase( i ); } if ( con == fNoticeCon ) { std::list<thread_id> threads; LOG(kProtocolName, liLow, " Notice connection closed, going offline"); connectionlist::iterator i; for (i = fConnections.begin(); i != fConnections.end(); i++) { threads.push_back( (*i)->Thread() ); Command * bye = new Command("OUT"); bye->UseTrID(false); (*i)->Send(bye, qsImmediate); BMessenger(*i).SendMessage(B_QUIT_REQUESTED); } wait_for_threads( threads ); fHandler->StatusChanged(Passport(), otOffline); fNoticeCon = NULL; fConnectionState = otOffline; LOG(kProtocolName, liDebug, " Unset fNoticeCon"); } }; } break; case msnAuthRequest: { // check if that person is already in our AL before asking. BString display = msg->FindString("displayname"); BString passport = msg->FindString("passport"); list_types listType = (list_types)msg->FindInt8("list"); Buddy *bud = new Buddy(passport.String()); bud->Lists(listType); fWaitingAuth[passport] = bud; fHandler->AuthRequest(listType, passport.String(), display.String()); } break; case msnContactInfo: { UpdateContactInfo( msg ); } break; case msnmsgError: { fHandler->Error( msg->FindString("error") ); } break; case msnmsgProgress: { float progress=0.0; if ( msg->FindFloat("progress", &progress) != B_OK ) { LOG(kProtocolName, liHigh, "Malformed msnmsgProgress message received by MSNManager"); break; } fHandler->Progress( msg->FindString("id"), msg->FindString("message"), progress ); } break; default: { BLooper::MessageReceived(msg); }; }; }
status_t MSNConnection::HandleUSR( Command * command ) { LOG(kProtocolName, liDebug, "C %lX: Processing USR", this); status_t result = B_ERROR; if (strcmp(command->Param(0), "OK") == 0) { Progress("MSN Login", "MSN: Logged in!", 1.0); GoOnline(); BMessage statusChange(msnmsgOurStatusChanged); statusChange.AddInt8("status", fState); fManMsgr.SendMessage(&statusChange); /* * Depending on the server protocol, server location and the * account being used (non-hotmail/msn acc), the server will not * respond on the PRP MFN command and our connection will break. * Michael */ BString passport(fManager->Passport()); if ((B_ERROR != passport.FindFirst("@hotmail")) || (B_ERROR != passport.FindFirst("@msn"))) { LOG(kProtocolName, liDebug, "Sending PRP MSN command" ); Command *rea = new Command("PRP"); rea->AddParam("MFN"); rea->AddParam(fManager->DisplayName(), true); Send(rea); } else { LOG(kProtocolName, liDebug, "Not sending PRP MSN command!"); }; fManager->Handler()->ContactList(&fContacts); Command *adl = new Command("ADL"); std::list<BString> contacts; std::map<BString, std::list<BString> > domainUsers; fManager->Handler()->ContactList(&contacts); // Make our contact list into a list by domain for (std::list<BString>::iterator iIt = contacts.begin(); iIt != contacts.end(); iIt++) { BString user; BString domain; if (SplitEmail((*iIt).String(), user, domain) == B_OK) { std::map<BString, std::list<BString> >::iterator dIt = domainUsers.find(domain); if (dIt == domainUsers.end()) { std::list<BString> users; users.push_back(user); domainUsers[domain] = users; } else { dIt->second.push_back(user); }; }; }; BString payload = "<ml l=\"1\">"; // Package each contact by domain for (std::map<BString, std::list<BString> >::iterator dIt = domainUsers.begin(); dIt != domainUsers.end(); dIt++) { payload << "<d n=\"" << dIt->first << "\">"; for (std::list<BString>::iterator uIt = dIt->second.begin(); uIt != dIt->second.end(); uIt++) { payload << "<c n=\"" << (*uIt) << "\" l=\"3\" t=\"1\" />"; }; payload << "</d>"; }; payload << "</ml>"; adl->AddPayload(payload.String()); Send(adl); Command *chg = new Command("CHG"); chg->AddParam("NLN"); BString caps = ""; caps << kOurCaps; chg->AddParam( caps.String() ); Send(chg); result = B_OK; } else { BString URI = command->Param(2); BString nonce = command->Param(3); BString authResp = ""; BString authToken = ""; SSO *auth = new SSO(NULL, fManager->Passport(), fManager->Password(), URI.String(), nonce.String()); result = auth->Response(authToken, authResp); if (result == B_OK) { Command *reply = new Command("USR"); reply->AddParam("SSO"); reply->AddParam("S"); reply->AddParam(authToken.String()); reply->AddParam(authResp.String()); reply->Debug(); Send(reply); }; }; return result; }
status_t MSNConnection::HandleCHL( Command * command ) { LOG(kProtocolName, liDebug, "C %lX: Processing CHL", this); const char *challenge = command->Param(0); int i = 0; unsigned char buf[256]; char chlString[128]; long long high = 0; long long low = 0; long long temp = 0; long long key = 0; long long bskey = 0; int *chlStringArray = (int *)chlString; int *md5hash = (int *)buf; char hash1a[17]; char hash2a[17]; sprintf((char *)buf + 16, "%s%s", challenge, kClientCode); MD5(buf + 16, strlen((char *)buf + 16), buf); for (i = 0; i < 16; i++) { sprintf((char *)buf + 16 + i * 2,"%02x", buf[i]); }; for (i = 0; i < 4; i++) { md5hash[i] = md5hash[i] & 0x7FFFFFFF; }; i = (strlen(challenge) + strlen(kClientID) + 7) & 0xF8; sprintf(chlString,"%s%s00000000", challenge, kClientID); chlString[i] = 0; for (i = 0; i < (int)strlen(chlString) / 4; i += 2) { temp = chlStringArray[i]; temp = (0x0E79A9C1 * temp) % 0x7FFFFFFF; temp += high; temp = md5hash[0] * temp + md5hash[1]; temp = temp % 0x7FFFFFFF; high = chlStringArray[i + 1]; high = (high + temp) % 0x7FFFFFFF; high = md5hash[2] * high + md5hash[3]; high = high % 0x7FFFFFFF; low = low + high + temp; }; high = (high + md5hash[1]) % 0x7FFFFFFF; low = (low + md5hash[3]) % 0x7FFFFFFF; key = (low << 32) + high; for (i= 0; i < 8; i++) { bskey <<= 8; bskey += key & 255; key >>=8; }; strncpy((char *)hash1a, (char *)buf + 16, 16); strncpy((char *)hash2a, (char *)buf + 32, 16); hash1a[16] = '\0'; hash2a[16] = '\0'; sprintf((char *)buf, "%llx%llx", strtoull(hash1a,NULL,16) ^ bskey, strtoull(hash2a,NULL,16) ^ bskey); Command *reply = new Command("QRY"); reply->AddParam(kClientID); reply->AddPayload((char *)buf, 32); Send(reply); reply->Debug(); return B_OK; };