Implemented processing of the app registration requests and Get{Running,Active}AppInfo().

git-svn-id: file:///srv/svn/repos/haiku/trunk/current@465 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Ingo Weinhold 2002-07-26 20:04:52 +00:00
parent 3a5e755532
commit 1d32138d6f
2 changed files with 464 additions and 12 deletions

View File

@ -25,11 +25,22 @@
// running applications.
//------------------------------------------------------------------------------
#include <new.h>
#include <Application.h>
#include "Debug.h"
#include "RegistrarDefs.h"
#include "RosterAppInfo.h"
#include "TRoster.h"
// constructor
TRoster::TRoster()
: fInfos()
: fRegisteredApps(),
fEarlyPreRegisteredApps(),
fIAPRRequests(),
fActiveApp(-1),
fLastToken(0)
{
}
@ -40,31 +51,450 @@ TRoster::~TRoster()
// HandleAddApplication
void
TRoster::HandleAddApplication(BMessage *message)
TRoster::HandleAddApplication(BMessage *request)
{
FUNCTION_START();
status_t error = B_OK;
// get the parameters
const char *signature;
entry_ref ref;
uint32 flags;
team_id team;
thread_id thread;
port_id port;
bool fullReg;
if (request->FindString("signature", &signature) != B_OK)
signature = NULL;
if (request->FindRef("ref", &ref) != B_OK)
SET_ERROR(error, B_BAD_VALUE);
if (request->FindInt32("flags", (int32*)&flags) != B_OK)
flags = B_REG_DEFAULT_APP_FLAGS;
if (request->FindInt32("team", &team) != B_OK)
team = -1;
if (request->FindInt32("thread", &thread) != B_OK)
thread = -1;
if (request->FindInt32("port", &port) != B_OK)
port = -1;
if (request->FindBool("full_registration", &fullReg) != B_OK)
fullReg = false;
// check the parameters
team_id otherTeam = -1;
uint32 launchFlags = flags & B_LAUNCH_MASK;
// entry_ref
if (error == B_OK) {
// the entry_ref must be valid
if (BEntry(&ref).Exists()) {
PRINT(("flags: %lx\n", flags));
PRINT(("ref: %ld, %lld, %s\n", ref.device, ref.directory, ref.name));
// check single/exclusive launchers
RosterAppInfo *info = NULL;
if ((launchFlags == B_SINGLE_LAUNCH
|| launchFlags == B_EXCLUSIVE_LAUNCH)
&& (((info = fRegisteredApps.InfoFor(&ref)))
|| ((info = fEarlyPreRegisteredApps.InfoFor(&ref))))) {
SET_ERROR(error, B_ALREADY_RUNNING);
otherTeam = info->team;
}
} else
SET_ERROR(error, B_ENTRY_NOT_FOUND);
}
// signature
if (error == B_OK && signature) {
// check exclusive launchers
RosterAppInfo *info = NULL;
if (launchFlags == B_EXCLUSIVE_LAUNCH
&& (((info = fRegisteredApps.InfoFor(signature)))
|| ((info = fEarlyPreRegisteredApps.InfoFor(signature))))) {
SET_ERROR(error, B_ALREADY_RUNNING);
otherTeam = info->team;
}
}
// If no team ID is given, full registration isn't possible.
if (error == B_OK) {
if (team < 0) {
if (fullReg)
SET_ERROR(error, B_BAD_VALUE);
} else if (fRegisteredApps.InfoFor(team))
SET_ERROR(error, B_REG_ALREADY_REGISTERED);
}
// Add the application info.
uint32 token = 0;
if (error == B_OK) {
// alloc and init the info
RosterAppInfo *info = new(nothrow) RosterAppInfo;
if (info) {
info->Init(thread, team, port, flags, &ref, signature);
if (fullReg)
info->state = APP_STATE_REGISTERED;
else
info->state = APP_STATE_PRE_REGISTERED;
info->registration_time = system_time();
// add it to the right list
bool addingSuccess = false;
if (team >= 0)
{
PRINT(("added ref: %ld, %lld, %s\n", info->ref.device, info->ref.directory, info->ref.name));
addingSuccess = fRegisteredApps.AddInfo(info);
}
else {
token = info->token = _NextToken();
addingSuccess = fEarlyPreRegisteredApps.AddInfo(info);
}
if (!addingSuccess)
SET_ERROR(error, B_NO_MEMORY);
} else
SET_ERROR(error, B_NO_MEMORY);
// delete the info on failure
if (error != B_OK && info)
delete info;
}
// reply to the request
if (error == B_OK) {
BMessage reply(B_REG_SUCCESS);
// The token is valid only when no team ID has been supplied.
if (team < 0)
reply.AddInt32("token", (int32)token);
request->SendReply(&reply);
} else {
BMessage reply(B_REG_ERROR);
reply.AddInt32("error", error);
if (otherTeam >= 0)
reply.AddInt32("other_team", otherTeam);
request->SendReply(&reply);
}
FUNCTION_END();
}
// HandleCompleteRegistration
void
TRoster::HandleCompleteRegistration(BMessage *message)
TRoster::HandleCompleteRegistration(BMessage *request)
{
FUNCTION_START();
status_t error = B_OK;
// get the parameters
team_id team;
thread_id thread;
port_id port;
if (request->FindInt32("team", &team) != B_OK)
team = -1;
if (request->FindInt32("thread", &thread) != B_OK)
thread = -1;
if (request->FindInt32("port", &port) != B_OK)
port = -1;
// check the parameters
// port
if (error == B_OK && port < 0)
SET_ERROR(error, B_BAD_VALUE);
// thread
if (error == B_OK && thread < 0)
SET_ERROR(error, B_BAD_VALUE);
// team
if (error == B_OK) {
if (team >= 0) {
// everything is fine -- set the values
if (RosterAppInfo *info = fRegisteredApps.InfoFor(team)) {
info->thread = thread;
info->port = port;
info->state = APP_STATE_REGISTERED;
} else
SET_ERROR(error, B_REG_APP_NOT_REGISTERED);
} else
SET_ERROR(error, B_BAD_VALUE);
}
// reply to the request
if (error == B_OK) {
BMessage reply(B_REG_SUCCESS);
request->SendReply(&reply);
} else {
BMessage reply(B_REG_ERROR);
reply.AddInt32("error", error);
request->SendReply(&reply);
}
FUNCTION_END();
}
// HandleIsAppPreRegistered
void
TRoster::HandleIsAppPreRegistered(BMessage *message)
TRoster::HandleIsAppPreRegistered(BMessage *request)
{
FUNCTION_START();
status_t error = B_OK;
// get the parameters
entry_ref ref;
team_id team;
thread_id thread;
if (request->FindRef("ref", &ref) != B_OK)
SET_ERROR(error, B_BAD_VALUE);
if (request->FindInt32("team", &team) != B_OK)
team = -1;
if (request->FindInt32("thread", &thread) != B_OK)
thread = -1;
// check the parameters
// entry_ref
if (error == B_OK & !BEntry(&ref).Exists())
SET_ERROR(error, B_ENTRY_NOT_FOUND);
// team
if (error == B_OK && team < 0)
SET_ERROR(error, B_BAD_VALUE);
// loop the information up
RosterAppInfo *info = NULL;
if (error == B_OK) {
if ((info = fRegisteredApps.InfoFor(team)) != NULL) {
_ReplyToIAPRRequest(request, info);
} else if ((info = fEarlyPreRegisteredApps.InfoFor(&ref)) != NULL) {
// pre-registered and has no team ID assigned yet -- queue the
// request
be_app->DetachCurrentMessage();
IAPRRequest queuedRequest = { ref, team, request };
fIAPRRequests[team] = queuedRequest;
}
}
// reply to the request
if (error == B_OK)
_ReplyToIAPRRequest(request, info);
else {
BMessage reply(B_REG_ERROR);
reply.AddInt32("error", error);
request->SendReply(&reply);
}
FUNCTION_END();
}
// HandleRemovePreRegApp
void
TRoster::HandleRemovePreRegApp(BMessage *message)
TRoster::HandleRemovePreRegApp(BMessage *request)
{
FUNCTION_START();
status_t error = B_OK;
// get the parameters
uint32 token;
if (request->FindInt32("token", (int32*)&token) != B_OK)
SET_ERROR(error, B_BAD_VALUE);
// remove the app
if (error == B_OK) {
RosterAppInfo *info = fEarlyPreRegisteredApps.InfoForToken(token);
if (info) {
fEarlyPreRegisteredApps.RemoveInfo(info);
delete info;
} else
SET_ERROR(error, B_REG_APP_NOT_PRE_REGISTERED);
}
// reply to the request
if (error == B_OK) {
BMessage reply(B_REG_SUCCESS);
request->SendReply(&reply);
} else {
BMessage reply(B_REG_ERROR);
reply.AddInt32("error", error);
request->SendReply(&reply);
}
FUNCTION_END();
}
// HandleRemoveApp
void
TRoster::HandleRemoveApp(BMessage *message)
TRoster::HandleRemoveApp(BMessage *request)
{
FUNCTION_START();
status_t error = B_OK;
// get the parameters
team_id team;
if (request->FindInt32("team", &team) != B_OK)
team = -1;
// remove the app
if (error == B_OK) {
if (RosterAppInfo *info = fRegisteredApps.InfoFor(team)) {
fRegisteredApps.RemoveInfo(info);
// Cleanup activities go here (e.g. removing message runners)
// ...
delete info;
} else
SET_ERROR(error, B_REG_APP_NOT_REGISTERED);
}
// reply to the request
if (error == B_OK) {
BMessage reply(B_REG_SUCCESS);
request->SendReply(&reply);
} else {
BMessage reply(B_REG_ERROR);
reply.AddInt32("error", error);
request->SendReply(&reply);
}
FUNCTION_END();
}
// HandleSetThreadAndTeam
void
TRoster::HandleSetThreadAndTeam(BMessage *request)
{
FUNCTION_START();
status_t error = B_OK;
// get the parameters
team_id team;
thread_id thread;
uint32 token;
if (request->FindInt32("team", &team) != B_OK)
team = -1;
if (request->FindInt32("thread", &thread) != B_OK)
thread = -1;
if (request->FindInt32("token", (int32*)&token) != B_OK)
SET_ERROR(error, B_BAD_VALUE);
// check the parameters
// team
if (error == B_OK && team < 0)
SET_ERROR(error, B_BAD_VALUE);
// update the app_info
if (error == B_OK) {
RosterAppInfo *info = fEarlyPreRegisteredApps.InfoForToken(token);
if (info) {
// Set thread and team, create a port for the application and
// move the app_info from the list of the early pre-registered
// apps to the list of the (pre-)registered apps.
fEarlyPreRegisteredApps.RemoveInfo(info);
info->team = team;
info->thread = thread;
// create and transfer the port
info->port = create_port(B_REG_APP_LOOPER_PORT_CAPACITY,
kRAppLooperPortName);
if (info->port < 0)
SET_ERROR(error, info->port);
if (error == B_OK)
SET_ERROR(error, set_port_owner(info->port, team));
// add the info to the registered apps list
if (error == B_OK && !fRegisteredApps.AddInfo(info))
SET_ERROR(error, B_NO_MEMORY);
// cleanup on failure
if (error != B_OK) {
if (info->port >= 0)
delete_port(info->port);
delete info;
}
// handle a pending IsAppPreRegistered() request
IAPRRequestMap::iterator it = fIAPRRequests.find(team);
if (it != fIAPRRequests.end()) {
IAPRRequest &request = it->second;
if (error == B_OK)
_ReplyToIAPRRequest(request.request, info);
delete request.request;
fIAPRRequests.erase(it);
}
} else
SET_ERROR(error, B_REG_APP_NOT_PRE_REGISTERED);
}
// reply to the request
if (error == B_OK) {
BMessage reply(B_REG_SUCCESS);
request->SendReply(&reply);
} else {
BMessage reply(B_REG_ERROR);
reply.AddInt32("error", error);
request->SendReply(&reply);
}
FUNCTION_END();
}
// HandleGetRunningAppInfo
void
TRoster::HandleGetRunningAppInfo(BMessage *request)
{
FUNCTION_START();
status_t error = B_OK;
// get the parameters
team_id team;
if (request->FindInt32("team", &team) != B_OK)
team = -1;
// check the parameters
// team -- in case no team is supplied, the active team is meant
if (error == B_OK && team < 0) {
if (fActiveApp >= 0)
team = fActiveApp;
else
error = B_ENTRY_NOT_FOUND;
}
// get the info
RosterAppInfo *info = NULL;
if (error == B_OK) {
info = fRegisteredApps.InfoFor(team);
if (info == NULL)
error = B_ENTRY_NOT_FOUND;
else
PRINT(("found ref: %ld, %lld, %s\n", info->ref.device, info->ref.directory, info->ref.name));
}
// reply to the request
if (error == B_OK) {
BMessage reply(B_REG_SUCCESS);
_AddMessageAppInfo(&reply, info);
request->SendReply(&reply);
} else {
BMessage reply(B_REG_ERROR);
reply.AddInt32("error", error);
request->SendReply(&reply);
}
FUNCTION_END();
}
// _AddMessageAppInfo
status_t
TRoster::_AddMessageAppInfo(BMessage *message, const app_info *info)
{
// An app_info is not completely flat. The entry_ref contains a string
// pointer. Therefore we flatten the info.
flat_app_info flatInfo;
flatInfo.info = *info;
// set the ref name to NULL and copy it into the flat structure
flatInfo.info.ref.name = NULL;
flatInfo.ref_name[0] = '\0';
if (info->ref.name)
strcpy(flatInfo.ref_name, info->ref.name);
// add the flat info
return message->AddData("app_info", B_REG_APP_INFO_TYPE, &flatInfo,
sizeof(flat_app_info));
}
// _NextToken
uint32
TRoster::_NextToken()
{
return ++fLastToken;
}
// _ReplyToIAPRRequest
void
TRoster::_ReplyToIAPRRequest(BMessage *request, const RosterAppInfo *info)
{
// pre-registered or registered?
bool preRegistered = false;
if (info) {
switch (info->state) {
case APP_STATE_PRE_REGISTERED:
preRegistered = true;
break;
case APP_STATE_INVALID:
case APP_STATE_REGISTERED:
preRegistered = false;
break;
}
}
// send reply
BMessage reply(B_REG_SUCCESS);
reply.AddBool("pre-registered", preRegistered);
if (preRegistered)
_AddMessageAppInfo(&reply, info);
request->SendReply(&reply);
}

View File

@ -28,12 +28,22 @@
#ifndef T_ROSTER_H
#define T_ROSTER_H
#include <map>
#include <SupportDefs.h>
#include "AppInfoList.h"
class BMessage;
struct IAPRRequest {
entry_ref ref;
team_id team;
BMessage *request;
};
typedef map<team_id, IAPRRequest> IAPRRequestMap;
// For strategic reasons, as TRoster appears in the BMessenger header.
namespace BPrivate {
@ -42,14 +52,26 @@ public:
TRoster();
virtual ~TRoster();
void HandleAddApplication(BMessage *message);
void HandleCompleteRegistration(BMessage *message);
void HandleIsAppPreRegistered(BMessage *message);
void HandleRemovePreRegApp(BMessage *message);
void HandleRemoveApp(BMessage *message);
void HandleAddApplication(BMessage *request);
void HandleCompleteRegistration(BMessage *request);
void HandleIsAppPreRegistered(BMessage *request);
void HandleRemovePreRegApp(BMessage *request);
void HandleRemoveApp(BMessage *request);
void HandleSetThreadAndTeam(BMessage *request);
void HandleGetRunningAppInfo(BMessage *request);
private:
AppInfoList fInfos;
static status_t _AddMessageAppInfo(BMessage *message,
const app_info *info);
uint32 _NextToken();
void _ReplyToIAPRRequest(BMessage *request, const RosterAppInfo *info);
private:
AppInfoList fRegisteredApps;
AppInfoList fEarlyPreRegisteredApps;
IAPRRequestMap fIAPRRequests;
team_id fActiveApp;
uint32 fLastToken;
};
}; // namespace BPrivate