#include "AppServer.h"
#include "ServerApp.h"
#include "ServerProtocol.h"
#include <Accelerant.h>
#include <AppDefs.h>
#include <Directory.h>
#include <Entry.h>
#include <File.h>
#include <Message.h>
#include <Path.h>
#include <PortLink.h>
#include <StopWatch.h>
#include <stdio.h>
#include <stdlib.h>
#ifdef DEBUG_KEYHANDLING
# define KBTRACE(x) printf x
#else
# define KBTRACE(x) ;
#endif
#ifdef DEBUG_SERVER
# define STRACE(x) printf x
#else
# define STRACE(x) ;
#endif
port_id gAppServerPort;
static AppServer *sAppServer = NULL;
AppServer::AppServer(void)
:
fCursorSem(-1),
fCursorArea(-1)
{
fMessagePort = create_port(200, SERVER_PORT_NAME);
if (fMessagePort == B_NO_MORE_PORTS)
debugger("app_server could not create message port");
gAppServerPort = fMessagePort;
fAppList = new BList();
fQuittingServer = false;
sAppServer = this;
fActiveAppLock = create_sem(1,"app_server_active_sem");
fAppListLock = create_sem(1,"app_server_applist_sem");
fPicassoThreadID = spawn_thread(PicassoThread, "picasso", B_NORMAL_PRIORITY, this);
if (fPicassoThreadID >= 0)
resume_thread(fPicassoThreadID);
}
AppServer::~AppServer()
{
}
int32
AppServer::PicassoThread(void *data)
{
for (;;) {
acquire_sem(sAppServer->fAppListLock);
for (int32 i = 0;;) {
ServerApp *app = (ServerApp *)sAppServer->fAppList->ItemAt(i++);
if (!app)
break;
app->PingTarget();
}
release_sem(sAppServer->fAppListLock);
snooze(1000000);
}
return 0;
}
void
AppServer::LaunchInputServer()
{
}
void
AppServer::LaunchCursorThread()
{
}
thread_id
AppServer::Run(void)
{
MainLoop();
kill_thread(fPicassoThreadID);
return 0;
}
void
AppServer::MainLoop(void)
{
BPrivate::PortLink pmsg(-1, fMessagePort);
while (1) {
STRACE(("info: AppServer::MainLoop listening on port %ld.\n", fMessagePort));
int32 code;
status_t err = pmsg.GetNextMessage(code);
if (err < B_OK) {
STRACE(("MainLoop:pmsg.GetNextMessage() failed\n"));
continue;
}
switch (code) {
case B_QUIT_REQUESTED:
case AS_GET_DESKTOP:
case AS_CREATE_APP:
case AS_DELETE_APP:
DispatchMessage(code, pmsg);
break;
default:
{
STRACE(("Server::MainLoop received unexpected code %ld\n",
code));
break;
}
}
}
}
void
AppServer::DispatchMessage(int32 code, BPrivate::PortLink &msg)
{
switch (code) {
case AS_GET_DESKTOP:
{
port_id replyPort;
if (msg.Read<port_id>(&replyPort) < B_OK)
break;
int32 userID;
msg.Read<int32>(&userID);
BPrivate::LinkSender reply(replyPort);
reply.StartMessage(B_OK);
reply.Attach<port_id>(fMessagePort);
reply.Flush();
break;
}
case AS_CREATE_APP:
{
team_id clientTeamID = -1;
port_id clientLooperPort = -1;
port_id clientReplyPort = -1;
int32 clientToken;
char *appSignature = NULL;
msg.Read<port_id>(&clientReplyPort);
msg.Read<port_id>(&clientLooperPort);
msg.Read<team_id>(&clientTeamID);
msg.Read<int32>(&clientToken);
if (msg.ReadString(&appSignature) != B_OK)
break;
port_id serverListen = create_port(DEFAULT_MONITOR_PORT_SIZE, appSignature);
if (serverListen < B_OK) {
printf("No more ports left. Time to crash. Have a nice day! :)\n");
break;
}
if (set_port_owner(serverListen, clientTeamID) < B_OK) {
delete_port(serverListen);
printf("Could not transfer port ownership to client %ld!\n", clientTeamID);
break;
}
acquire_sem(fAppListLock);
ServerApp *app = new ServerApp(clientReplyPort, serverListen, clientLooperPort,
clientTeamID, clientToken, appSignature);
fAppList->AddItem(app);
release_sem(fAppListLock);
BPrivate::PortLink replylink(clientReplyPort);
replylink.StartMessage(B_OK);
replylink.Attach<int32>(serverListen);
replylink.Flush();
free(appSignature);
break;
}
case AS_DELETE_APP:
{
int32 i = 0, appnum = fAppList->CountItems();
ServerApp *srvapp = NULL;
thread_id srvapp_id = -1;
if (msg.Read<thread_id>(&srvapp_id) < B_OK)
break;
acquire_sem(fAppListLock);
for (i = 0; i < appnum; i++) {
srvapp = (ServerApp *)fAppList->ItemAt(i);
if (srvapp != NULL && srvapp->MonitorThreadID() == srvapp_id) {
srvapp = (ServerApp *)fAppList->RemoveItem(i);
if (srvapp) {
delete srvapp;
srvapp = NULL;
}
break;
}
}
release_sem(fAppListLock);
break;
}
case B_QUIT_REQUESTED:
break;
default:
break;
}
}
void
AppServer::Broadcast(int32 code)
{
acquire_sem(fAppListLock);
for (int32 i = 0; i < fAppList->CountItems(); i++) {
ServerApp *app = (ServerApp *)fAppList->ItemAt(i);
if (!app)
{ printf("PANIC in AppServer::Broadcast()\n"); continue; }
app->PostMessage(code);
}
release_sem(fAppListLock);
}
ServerApp *
AppServer::FindApp(const char *sig)
{
if (!sig)
return NULL;
ServerApp *foundapp=NULL;
acquire_sem(fAppListLock);
for(int32 i=0; i<fAppList->CountItems();i++)
{
foundapp=(ServerApp*)fAppList->ItemAt(i);
if(foundapp && foundapp->Title() == sig)
{
release_sem(fAppListLock);
return foundapp;
}
}
release_sem(fAppListLock);
return NULL;
}
int
main(int argc, char** argv)
{
if (find_port(SERVER_PORT_NAME) >= B_OK)
return -1;
AppServer app_server;
app_server.Run();
return 0;
}