/* * Result callback for the listAccountsTemplate * * result list form: * { "templateId": "com.palm.aol", "loc_name": "AOL", "validator": "palm://com.palm.imaccountvalidator/checkCredentials", "capabilityProviders": [ { "capability": "MESSAGING", "capabilitySubtype": "IM", "id": "com.palm.aol.aim", "loc_name": "AIM", "loc_shortName": "AIM", "icon": { "loc_32x32": "/usr/palm/public/accounts/com.palm.aol/images/aim32x32.png", "loc_48x48": "/usr/palm/public/accounts/com.palm.aol/images/aim48x48.png", "splitter": "/usr/palm/public/accounts/com.palm.aol/images/aim_transport_splitter.png" }, "implementation": "palm://com.palm.imlibpurple/", "onEnabled": "palm://com.palm.imlibpurple/onEnabled", "serviceName": "type_aim", "dbkinds": { "immessage": "com.palm.immessage.libpurple", "imcommand": "com.palm.imcommand.libpurple" } } ] }, */ MojErr SendOneMessageHandler::listAccountResult(MojObject& result, MojErr err) { if (err) { MojString error; MojErrToString(err, error); MojLogError(IMServiceApp::s_log, _T("listAccountTemplates failed. error %d - %s"), err, error.data()); // not much we can do here...don't leave message pending failMessage(ERROR_SEND_GENERIC_ERROR); } else { IMServiceHandler::logMojObjectJsonString(_T("listAccountTemplates success: %s"), result); // if the flag is not there, assume we can send to a non buddy // if we got here, the message is going to a non buddy bool nonBuddyChatOK = true; // find the template and provider for our service and look for "chatWithNonBuddies":false // "results" in result MojObject results; result.get(_T("results"), results); // check to see if array is empty - should not be... if (!results.empty()){ // find the messaging capability object MojObject capability; MojObject accountTemplate; MojString serviceName; bool found = false; bool foundService = false; MojObject::ConstArrayIterator templItr = results.arrayBegin(); while (templItr != results.arrayEnd()) { accountTemplate = *templItr; IMServiceHandler::logMojObjectJsonString(_T("listAccountTemplates template: %s"), accountTemplate); // now find the capabilityProviders array MojObject providersArray; found = accountTemplate.get(XPORT_CAPABILITY_PROVIDERS, providersArray); if (found) { MojObject::ConstArrayIterator capItr = providersArray.arrayBegin(); while (capItr != providersArray.arrayEnd()) { capability = *capItr; IMServiceHandler::logMojObjectJsonString(_T("listAccountTemplates capability: %s"), capability); // find the one for our service capability.get(XPORT_SERVICE_TYPE, serviceName, found); if (found) { MojLogInfo(IMServiceApp::s_log, _T("listAccountTemplates - capability service %s. "), serviceName.data()); if (0 == serviceName.compare(m_serviceName)) { foundService = true; found = capability.get("chatWithNonBuddies", nonBuddyChatOK); MojLogInfo(IMServiceApp::s_log, _T("listAccountTemplates - found service %s. found %d, chatWithNonBuddies %d"), m_serviceName.data(), found, nonBuddyChatOK); break; } } else MojLogError(IMServiceApp::s_log, _T("error: no service name in capability provider")); capItr++; } } else MojLogError(IMServiceApp::s_log, _T("error: no provider array in templateId")); if (foundService) break; templItr++; } } if (nonBuddyChatOK){ // send to the transport sendToTransport(); } else { // permanent error - no retry option MojLogError(IMServiceApp::s_log, _T("error: Trying to send to user that is not on buddy list")); failMessage(ERROR_SEND_TO_NON_BUDDY); } } return MojErrNone; }
/* * Send one IMCommand that has handler set to transport * * errors returned up to OutgoingIMCommandHandler * * * @param imCmd - imCommand that was read out of the DB with handler set to transport { "id" : "ImCommand", "type" : "object", "properties" : { "command" : {"type" : "string", "enum" : ["blockBuddy","deleteBuddy","sendBuddyInvite","receivedBuddyInvite","createChatGroup","inviteToGroup","leaveGroup"], "description" : "The command to be processed"}, "params" : {"type" : "any", "description" : "Parameters associated with the command are stored here."} "handler" : {"type" : "string", "enum" : ["transport","application"], "description" : "Who is responsible for handling the command"}, "targetUsername" : {"type" : "string", "description" : "The buddyname the command will act on"}, "fromUsername" : {"type" : "string", "description" : "The username that originated the command"}, "serviceName" : {"type" : "string", "description" : "Name of originating service (see IMAddress of contacts load library*)."} } * } */ MojErr SendOneCommandHandler::doSend(const MojObject imCmd) { IMServiceHandler::logMojObjectJsonString(_T("send command: %s"),imCmd); MojString command; LibpurpleAdapter::SendResult retVal = LibpurpleAdapter::SENT; bool found = false; MojErr err = imCmd.get(MOJDB_COMMAND, command, found); MojErrCheck(err); // serviceName err = imCmd.get(MOJDB_SERVICE_NAME, m_serviceName, found); MojErrCheck(err); // get the id so we can update the status in the DB after sending err = imCmd.getRequired(MOJDB_ID, m_currentCmdDbId); MojErrCheck(err); // for receiving invite, the user account and remote user are reversed: targetUsername is us and the fromUsername is the remote buddy if (0 == command.compare(_T("receivedBuddyInvite"))) { // username of current account err = imCmd.get(MOJDB_FROM_USER, m_buddyName, found); MojErrCheck(err); // buddy / remote user err = imCmd.get(MOJODB_TARGET_USER, m_username, found); MojErrCheck(err); } else { // username of current account err = imCmd.get(MOJDB_FROM_USER, m_username, found); MojErrCheck(err); // buddy / remote user err = imCmd.get(MOJODB_TARGET_USER, m_buddyName, found); MojErrCheck(err); } // which command? if (0 == command.compare(_T("blockBuddy"))) { retVal = blockBuddy(imCmd); } else if (0 == command.compare(_T("deleteBuddy"))) { retVal = removeBuddy(imCmd); } else if (0 == command.compare(_T("sendBuddyInvite"))) { retVal = inviteBuddy(imCmd); } else if (0 == command.compare(_T("receivedBuddyInvite"))) { retVal = receivedBuddyInvite(imCmd); } else { MojLogError(IMServiceApp::s_log, _T("doSend: unknown command %s"), command.data()); retVal = LibpurpleAdapter::SEND_FAILED; } // we can't just delete the command if the user is not logged on... // need to save command in "waiting" state waiting for user to login if (LibpurpleAdapter::USER_NOT_LOGGED_IN == retVal) { // user not logged in - put in queued state MojLogError(IMServiceApp::s_log, _T("doSend - can't process command - user not logged in. Waiting for connection")); MojObject propObject; propObject.putString(MOJDB_STATUS, IMMessage::statusStrings[WaitingForConnection]); // id to update propObject.putString(MOJDB_ID, m_currentCmdDbId); // save the new fields - call merge err = m_dbClient.merge(this->m_imSaveCommandSlot, propObject); if (err) { MojLogError(IMServiceApp::s_log, _T("doSend - DB merge command failed. err %d, DB id %s: "), err, m_currentCmdDbId.data() ); } } else { // delete command so we don't keep processing it // put id in an array MojObject idsToDelete; // array err = idsToDelete.push(m_currentCmdDbId); // luna://com.palm.db/del '{"ids":[2]}' IMServiceHandler::logMojObjectJsonString(_T("deleting imcommand: %s"), idsToDelete); err = m_dbClient.del(this->m_imDeleteCommandSlot, idsToDelete.arrayBegin(), idsToDelete.arrayEnd()); if (err) { MojLogError(IMServiceApp::s_log, _T("doSend - DB del command failed. err %d, DB id %s: "), err, m_currentCmdDbId.data() ); } } if (LibpurpleAdapter::SENT != retVal) { // something went wrong - nothing more we can do MojLogError(IMServiceApp::s_log, _T("doSend: command failed")); m_outgoingIMHandler->messageFinished(); } return MojErrNone; }
MojErr OnEnabledHandler::findImLoginStateResult(MojObject& payload, MojErr err) { MojLogTrace(IMServiceApp::s_log); if (err != MojErrNone) { MojString error; MojErrToString(err, error); MojLogCritical(IMServiceApp::s_log, _T("findImLoginStateResult failed: error %d - %s"), err, error.data()); } else { // "results" in result MojObject results; payload.get(_T("results"), results); // check to see if array is empty - normally it will be if this is a newly created account. There should never be more than 1 item here if (!results.empty()){ IMServiceHandler::logMojObjectJsonString(_T("findImLoginStateResult found existing imLoginState record: %s"), payload); // if there is a record already, make sure the account id matches. MojObject loginState; MojObject::ConstArrayIterator itr = results.arrayBegin(); bool foundOne = false; while (itr != results.arrayEnd()) { if (foundOne) { MojLogError(IMServiceApp::s_log, _T("findImLoginStateResult: found more than one ImLoginState with same username/serviceName - using the first one")); break; } loginState = *itr; foundOne = true; itr++; } MojString accountId; MojErr err = loginState.getRequired("accountId", accountId); if (err) { MojLogError(IMServiceApp::s_log, _T("findImLoginStateResult: missing accountId in loginState entry")); } if (0 != accountId.compare(m_accountId)) { MojLogError(IMServiceApp::s_log, _T("findImLoginStateResult: existing loginState record does not have matching account id. accountId = %s"), accountId.data()); // delete this record MojObject idsToDelete; MojString dbId; err = loginState.getRequired("_id", dbId); if (err) { MojLogError(IMServiceApp::s_log, _T("findImLoginStateResult: missing dbId in loginState entry")); } else { idsToDelete.push(dbId); // luna://com.palm.db/del '{"ids":[2]}' MojLogInfo(IMServiceApp::s_log, _T("findImLoginStateResult: deleting loginState entry id: %s"), dbId.data()); err = m_dbClient.del(this->m_deleteImLoginStateSlot, idsToDelete.arrayBegin(), idsToDelete.arrayEnd()); if (err != MojErrNone) { MojString error; MojErrToString(err, error); MojLogError(IMServiceApp::s_log, _T("findImLoginStateResult: db.del() failed: error %d - %s"), err, error.data()); } } } // if the account id matches, leave the old record and we are done else return MojErrNone; } // no existing record found or the old one was deleted - create a new one MojLogInfo(IMServiceApp::s_log, _T("findImLoginStateResult: no matching loginState record found for %s, %s. creating a new one"), m_username.data(), m_serviceName.data()); MojObject imLoginState; imLoginState.putString(_T("_kind"), IM_LOGINSTATE_KIND); imLoginState.put(_T("accountId"), m_accountId); imLoginState.put(_T("serviceName"), m_serviceName); imLoginState.put(_T("username"), m_username); imLoginState.put(_T("capabilityId"), m_capabilityProviderId); imLoginState.putString(_T("state"), LOGIN_STATE_OFFLINE); imLoginState.putInt(_T("availability"), PalmAvailability::ONLINE); //default to online so we automatically login at first imLoginState.put(_T("config"), m_config); MojErr err = m_dbClient.put(m_addImLoginStateSlot, imLoginState); if (err != MojErrNone) { MojString error; MojErrToString(err, error); MojLogError(IMServiceApp::s_log, _T("findImLoginStateResult: db.put() failed: error %d - %s"), err, error.data()); } } return err; }
//TODO: when the connection is lost (no internet), complete/cancel the activity and exit the service MojErr ConnectionState::ConnectionStateHandler::connectionManagerResult(MojObject& result, MojErr err) { // log the parameters IMServiceHandler::logMojObjectJsonString(_T("ConnectionStateHandler::connectionManagerResult: %s"), result); if (err == MojErrNone && result.contains("$activity")) { MojObject activity, requirements, internetRequirements; // The connectionmanager status is under $activity.requirements.internet err = result.getRequired("$activity", activity); if (err == MojErrNone) { err = activity.getRequired("requirements", requirements); if (err == MojErrNone) { err = requirements.getRequired("internet", internetRequirements); } } if (err == MojErrNone) { m_receivedResponse = true; bool prevInetConnected = m_connState->m_inetConnected; internetRequirements.get("isInternetConnectionAvailable", m_connState->m_inetConnected); bool prevWifiConnected = m_connState->m_wifiConnected; bool found = false; MojObject wifiObj; err = internetRequirements.getRequired("wifi", wifiObj); MojString wifiState; err = wifiObj.getRequired("state", wifiState); m_connState->m_wifiConnected = (err == MojErrNone && wifiState.compare("connected") == 0); // If the connection was lost, keep the old ipAddress so it can be used to // notify accounts that were using it if (m_connState->m_wifiConnected == true) { err = wifiObj.get("ipAddress", m_connState->m_wifiIpAddress, found); if (err != MojErrNone || found == false) { // It may claim to be connected, but there's no interface IP address MojLogError(IMServiceApp::s_log, _T("Marking WiFi as disconnected because ipAddress is missing")); m_connState->m_wifiConnected = false; } MojLogInfo(IMServiceApp::s_log, _T("ConnectionStateHandler::connectionManagerResult found=%i, wifi ipAddress=%s"), found, m_connState->m_wifiIpAddress.data()); } bool prevWanConnected = m_connState->m_wanConnected; MojObject wanObj; err = internetRequirements.getRequired("wan", wanObj); MojErrCheck(err); MojString wanState; err = wanObj.getRequired("state", wanState); MojErrCheck(err); m_connState->m_wanConnected = (err == MojErrNone && wanState.compare("connected") == 0); // If the connection was lost, keep the old ipAddress so it can be used to // notify accounts that were using it if (m_connState->m_wanConnected == true) { err = wanObj.get("ipAddress", m_connState->m_wanIpAddress, found); if (err != MojErrNone || found == false) { // It may claim to be connected, but there's no interface IP address MojLogError(IMServiceApp::s_log, _T("Marking WAN as disconnected because ipAddress is missing")); m_connState->m_wanConnected = false; } MojLogInfo(IMServiceApp::s_log, _T("ConnectionStateHandler::connectionManagerResult found=%i, wan ipAddress=%s"), found, m_connState->m_wanIpAddress.data()); } // If the loginState machine setup a listener, then post the change if (m_loginState != NULL) { if (prevInetConnected != m_connState->m_inetConnected || prevWifiConnected != m_connState->m_wifiConnected || prevWanConnected != m_connState->m_wanConnected) { MojLogInfo(IMServiceApp::s_log, _T("ConnectionStateHandler::connectionManagerResult - connection changed - scheduling activity.")); ConnectionState::ConnectionChangedScheduler *changeScheduler = new ConnectionState::ConnectionChangedScheduler(m_service); changeScheduler->scheduleActivity(); } else { MojLogInfo(IMServiceApp::s_log, _T("ConnectionStateHandler::connectionManagerResult - no change from previous state.")); } } } } else { MojLogInfo(IMServiceApp::s_log, _T("ConnectionStateHandler::connectionManagerResult no activity object - ignoring. err = %d"), err); } return MojErrNone; }