BAppServerLink is now using BApplication::fServerTo/From for its messaging.
Added LinkMsgReader::NeedsReply() method. Completely redone ServerApp messaging: no more "replyport" from BAppServerLink; instead, the registered client reply port is used. Fixed some more weak messaging stuff. ServerApp now recognizes if an unknown message needs a reply, and sends it - for example, the "Screen" preferences app no longer hangs, but crashes on start :) Made LinkMsgReader::Read() virtual again, since it's needed by RAMLinkMsgReader.cpp. Renamed BPortLink::GetNextReply() to GetNextMessage(). Some more cleanup. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@13004 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
@@ -23,7 +23,9 @@ class LinkMsgReader {
|
||||
port_id Port(void) { return fReceivePort; }
|
||||
|
||||
status_t GetNextMessage(int32 &code, bigtime_t timeout = B_INFINITE_TIMEOUT);
|
||||
status_t Read(void *data, ssize_t size);
|
||||
bool NeedsReply() const;
|
||||
|
||||
virtual status_t Read(void *data, ssize_t size);
|
||||
status_t ReadString(char **string);
|
||||
template <class Type> status_t Read(Type *data)
|
||||
{
|
||||
|
||||
@@ -61,7 +61,8 @@ class BPortLink {
|
||||
void SetReplyPort(port_id port);
|
||||
port_id ReplyPort();
|
||||
|
||||
status_t GetNextReply(int32 &code, bigtime_t timeout = B_INFINITE_TIMEOUT);
|
||||
status_t GetNextMessage(int32 &code, bigtime_t timeout = B_INFINITE_TIMEOUT);
|
||||
bool NeedsReply() const;
|
||||
status_t Read(void *data, ssize_t size);
|
||||
status_t ReadString(char **string);
|
||||
status_t ReadRegion(BRegion *region);
|
||||
@@ -71,6 +72,8 @@ class BPortLink {
|
||||
// convenience methods
|
||||
|
||||
status_t FlushWithReply(int32 &code);
|
||||
LinkMsgReader &Reader() { return *fReader; }
|
||||
LinkMsgSender &Sender() { return *fSender; }
|
||||
|
||||
protected:
|
||||
LinkMsgReader *fReader;
|
||||
@@ -148,11 +151,17 @@ BPortLink::ReplyPort()
|
||||
}
|
||||
|
||||
inline status_t
|
||||
BPortLink::GetNextReply(int32 &code, bigtime_t timeout)
|
||||
BPortLink::GetNextMessage(int32 &code, bigtime_t timeout)
|
||||
{
|
||||
return fReader->GetNextMessage(code, timeout);
|
||||
}
|
||||
|
||||
inline bool
|
||||
BPortLink::NeedsReply() const
|
||||
{
|
||||
return fReader->NeedsReply();
|
||||
}
|
||||
|
||||
inline status_t
|
||||
BPortLink::Read(void *data, ssize_t size)
|
||||
{
|
||||
|
||||
@@ -34,7 +34,6 @@
|
||||
|
||||
|
||||
BLocker sLock;
|
||||
port_id sReplyPort = -1;
|
||||
|
||||
|
||||
namespace BPrivate {
|
||||
@@ -44,15 +43,10 @@ BAppServerLink::BAppServerLink(void)
|
||||
sLock.Lock();
|
||||
|
||||
// if there is no be_app, we can't do a whole lot, anyway
|
||||
if (be_app)
|
||||
if (be_app) {
|
||||
SetSendPort(be_app->fServerFrom);
|
||||
|
||||
// There is only one global reply port, and we create it here
|
||||
// (protected by sLock) when it's not yet there
|
||||
if (sReplyPort < B_OK)
|
||||
sReplyPort = create_port(100, "AppServerLink reply port");
|
||||
|
||||
SetReplyPort(sReplyPort);
|
||||
SetReplyPort(be_app->fServerTo);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -65,17 +59,11 @@ BAppServerLink::~BAppServerLink()
|
||||
status_t
|
||||
BAppServerLink::FlushWithReply(int32 *code)
|
||||
{
|
||||
status_t err;
|
||||
|
||||
err = Attach<port_id>(sReplyPort);
|
||||
if (err < B_OK)
|
||||
return err;
|
||||
status_t status = Flush(B_INFINITE_TIMEOUT, true);
|
||||
if (status < B_OK)
|
||||
return status;
|
||||
|
||||
err = Flush();
|
||||
if (err < B_OK)
|
||||
return err;
|
||||
|
||||
return GetNextReply(*code);
|
||||
return GetNextMessage(*code);
|
||||
}
|
||||
|
||||
} // namespace BPrivate
|
||||
|
||||
@@ -102,6 +102,17 @@ LinkMsgReader::GetNextMessage(int32 &code, bigtime_t timeout)
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
LinkMsgReader::NeedsReply() const
|
||||
{
|
||||
if (fReplySize == 0)
|
||||
return false;
|
||||
|
||||
message_header *header = (message_header *)(fRecvBuffer + fRecvStart);
|
||||
return (header->flags & kNeedsReply) != 0;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
LinkMsgReader::ResetBuffer()
|
||||
{
|
||||
|
||||
@@ -92,9 +92,9 @@ BPortLink::AttachShape(BShape &shape)
|
||||
status_t
|
||||
BPortLink::FlushWithReply(int32 &code)
|
||||
{
|
||||
status_t status = Flush();
|
||||
status_t status = Flush(B_INFINITE_TIMEOUT, true);
|
||||
if (status < B_OK)
|
||||
return status;
|
||||
|
||||
return GetNextReply(code);
|
||||
return GetNextMessage(code);
|
||||
}
|
||||
|
||||
@@ -257,22 +257,16 @@ AppServer::~AppServer(void)
|
||||
int32
|
||||
AppServer::PicassoThread(void *data)
|
||||
{
|
||||
int32 i;
|
||||
AppServer *appserver=(AppServer*)data;
|
||||
ServerApp *app;
|
||||
for(;;)
|
||||
{
|
||||
i = 0;
|
||||
acquire_sem(appserver->fAppListLock);
|
||||
for(;;)
|
||||
{
|
||||
app=(ServerApp*)appserver->fAppList->ItemAt(i++);
|
||||
if(!app)
|
||||
for (;;) {
|
||||
acquire_sem(sAppServer->fAppListLock);
|
||||
for (int32 i = 0;;) {
|
||||
ServerApp *app = (ServerApp *)sAppServer->fAppList->ItemAt(i++);
|
||||
if (!app)
|
||||
break;
|
||||
|
||||
app->PingTarget();
|
||||
}
|
||||
release_sem(appserver->fAppListLock);
|
||||
release_sem(sAppServer->fAppListLock);
|
||||
// we do this every other second so as not to suck *too* many CPU cycles
|
||||
snooze(1000000);
|
||||
}
|
||||
@@ -407,7 +401,7 @@ AppServer::MainLoop(void)
|
||||
STRACE(("info: AppServer::MainLoop listening on port %ld.\n", fMessagePort));
|
||||
|
||||
int32 code;
|
||||
status_t err = pmsg.GetNextReply(code);
|
||||
status_t err = pmsg.GetNextMessage(code);
|
||||
if (err < B_OK) {
|
||||
STRACE(("MainLoop:pmsg.GetNextReply failed\n"));
|
||||
continue;
|
||||
@@ -424,12 +418,12 @@ AppServer::MainLoop(void)
|
||||
case AS_SET_DECORATOR:
|
||||
case AS_GET_DECORATOR:
|
||||
case AS_R5_SET_DECORATOR:
|
||||
DispatchMessage(code,pmsg);
|
||||
DispatchMessage(code, pmsg);
|
||||
break;
|
||||
default:
|
||||
{
|
||||
STRACE(("Server::MainLoop received unexpected code %ld(offset %ld)\n",
|
||||
code,code-SERVER_TRUE));
|
||||
STRACE(("Server::MainLoop received unexpected code %ld (offset %ld)\n",
|
||||
code, code - SERVER_TRUE));
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -464,19 +458,19 @@ AppServer::LoadDecorator(const char *path)
|
||||
status_t stat;
|
||||
image_id addon;
|
||||
|
||||
addon= load_add_on(path);
|
||||
if(addon < 0)
|
||||
addon = load_add_on(path);
|
||||
if (addon < B_OK)
|
||||
return false;
|
||||
|
||||
// As of now, we do nothing with decorator versions, but the possibility exists
|
||||
// that the API will change even though I cannot forsee any reason to do so. If
|
||||
// we *did* do anything with decorator versions, the assignment to a global would
|
||||
// go here.
|
||||
|
||||
|
||||
// Get the instantiation function
|
||||
stat= get_image_symbol(addon, "instantiate_decorator", B_SYMBOL_TYPE_TEXT, (void**)&pcreatefunc);
|
||||
if(stat != B_OK)
|
||||
{
|
||||
stat = get_image_symbol(addon, "instantiate_decorator",
|
||||
B_SYMBOL_TYPE_TEXT, (void**)&pcreatefunc);
|
||||
if (stat != B_OK) {
|
||||
unload_add_on(addon);
|
||||
return false;
|
||||
}
|
||||
@@ -497,33 +491,29 @@ AppServer::InitDecorators(void)
|
||||
{
|
||||
BMessage settings;
|
||||
|
||||
BDirectory dir,newdir;
|
||||
if(dir.SetTo(SERVER_SETTINGS_DIR)==B_ENTRY_NOT_FOUND)
|
||||
create_directory(SERVER_SETTINGS_DIR,0777);
|
||||
BDirectory dir;
|
||||
if (dir.SetTo(SERVER_SETTINGS_DIR) == B_ENTRY_NOT_FOUND)
|
||||
create_directory(SERVER_SETTINGS_DIR, 0777);
|
||||
|
||||
BString path(SERVER_SETTINGS_DIR);
|
||||
path+="DecoratorSettings";
|
||||
BFile file(path.String(),B_READ_ONLY);
|
||||
path += "DecoratorSettings";
|
||||
BFile file(path.String(), B_READ_ONLY);
|
||||
|
||||
if(file.InitCheck()==B_OK)
|
||||
{
|
||||
if(settings.Unflatten(&file)==B_OK)
|
||||
{
|
||||
BString itemtext;
|
||||
if(settings.FindString("decorator",&itemtext)==B_OK)
|
||||
{
|
||||
path.SetTo(DECORATORS_DIR);
|
||||
path+=itemtext;
|
||||
if(LoadDecorator(path.String()))
|
||||
return;
|
||||
}
|
||||
if (file.InitCheck() == B_OK
|
||||
&& settings.Unflatten(&file) == B_OK) {
|
||||
BString itemtext;
|
||||
if (settings.FindString("decorator", &itemtext) == B_OK) {
|
||||
path.SetTo(DECORATORS_DIR);
|
||||
path += itemtext;
|
||||
if (LoadDecorator(path.String()))
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// We got this far, so something must have gone wrong. We set make_decorator
|
||||
// to NULL so that the decorator allocation routine knows to utilize the included
|
||||
// default decorator instead of an addon.
|
||||
make_decorator=NULL;
|
||||
make_decorator = NULL;
|
||||
}
|
||||
|
||||
/*!
|
||||
@@ -550,25 +540,26 @@ AppServer::DispatchMessage(int32 code, BPortLink &msg)
|
||||
// Find the necessary data
|
||||
team_id clientTeamID = -1;
|
||||
port_id clientLooperPort = -1;
|
||||
port_id app_port = -1;
|
||||
port_id clientReplyPort = -1;
|
||||
int32 htoken = B_NULL_TOKEN;
|
||||
char *app_signature = NULL;
|
||||
char *appSignature = NULL;
|
||||
|
||||
msg.Read<port_id>(&app_port);
|
||||
msg.Read<port_id>(&clientReplyPort);
|
||||
msg.Read<port_id>(&clientLooperPort);
|
||||
msg.Read<team_id>(&clientTeamID);
|
||||
msg.Read<int32>(&htoken);
|
||||
msg.ReadString(&app_signature);
|
||||
if (msg.ReadString(&appSignature) != B_OK)
|
||||
break;
|
||||
|
||||
port_id server_listen = create_port(DEFAULT_MONITOR_PORT_SIZE, app_signature);
|
||||
if (server_listen < B_OK) {
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
// we let the application own the port, so that we get aware when it's gone
|
||||
if (set_port_owner(server_listen, clientTeamID) < B_OK) {
|
||||
delete_port(server_listen);
|
||||
if (set_port_owner(serverListen, clientTeamID) < B_OK) {
|
||||
delete_port(serverListen);
|
||||
printf("Could not transfer port ownership to client %ld!\n", clientTeamID);
|
||||
break;
|
||||
}
|
||||
@@ -576,21 +567,21 @@ AppServer::DispatchMessage(int32 code, BPortLink &msg)
|
||||
// Create the ServerApp subthread for this app
|
||||
acquire_sem(fAppListLock);
|
||||
|
||||
ServerApp *app = new ServerApp(app_port,server_listen, clientLooperPort,
|
||||
clientTeamID, htoken, app_signature);
|
||||
ServerApp *app = new ServerApp(clientReplyPort, serverListen, clientLooperPort,
|
||||
clientTeamID, htoken, appSignature);
|
||||
|
||||
// add the new ServerApp to the known list of ServerApps
|
||||
fAppList->AddItem(app);
|
||||
|
||||
release_sem(fAppListLock);
|
||||
|
||||
BPortLink replylink(app_port);
|
||||
BPortLink replylink(clientReplyPort);
|
||||
replylink.StartMessage(SERVER_TRUE);
|
||||
replylink.Attach<int32>(server_listen);
|
||||
replylink.Attach<int32>(serverListen);
|
||||
replylink.Flush();
|
||||
|
||||
// This is necessary because BPortLink::ReadString allocates memory
|
||||
free(app_signature);
|
||||
free(appSignature);
|
||||
break;
|
||||
}
|
||||
case AS_DELETE_APP:
|
||||
|
||||
@@ -25,8 +25,8 @@ RAMLinkMsgReader::~RAMLinkMsgReader(void)
|
||||
}
|
||||
|
||||
|
||||
|
||||
void RAMLinkMsgReader::SetBuffer(int8 *buffer)
|
||||
void
|
||||
RAMLinkMsgReader::SetBuffer(int8 *buffer)
|
||||
{
|
||||
if(!buffer)
|
||||
{
|
||||
@@ -48,93 +48,35 @@ void RAMLinkMsgReader::SetBuffer(int8 *buffer)
|
||||
}
|
||||
|
||||
|
||||
int8 *RAMLinkMsgReader::GetBuffer(void)
|
||||
int8 *
|
||||
RAMLinkMsgReader::GetBuffer(void)
|
||||
{
|
||||
return fBuffer;
|
||||
}
|
||||
|
||||
|
||||
size_t RAMLinkMsgReader::GetBufferSize(void)
|
||||
size_t
|
||||
RAMLinkMsgReader::GetBufferSize(void)
|
||||
{
|
||||
return fAttachSize;
|
||||
}
|
||||
|
||||
|
||||
|
||||
status_t RAMLinkMsgReader::Read(void *data, ssize_t size)
|
||||
status_t
|
||||
RAMLinkMsgReader::Read(void *data, ssize_t size)
|
||||
{
|
||||
if(!fBuffer || fAttachSize==0)
|
||||
if (!fBuffer || fAttachSize == 0)
|
||||
return B_NO_INIT;
|
||||
|
||||
if(size<1)
|
||||
|
||||
if (size < 1)
|
||||
return B_BAD_VALUE;
|
||||
|
||||
if(fPosition+size > fAttachStart+fAttachSize)
|
||||
{
|
||||
|
||||
if (fPosition + size > fAttachStart + fAttachSize) {
|
||||
// read past end of buffer
|
||||
return B_BAD_VALUE;
|
||||
}
|
||||
|
||||
|
||||
memcpy(data, fPosition, size);
|
||||
fPosition+=size;
|
||||
fPosition += size;
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
status_t RAMLinkMsgReader::ReadString(char **string)
|
||||
{
|
||||
status_t err;
|
||||
int32 len = 0;
|
||||
|
||||
err = Read<int32>(&len);
|
||||
if (err < B_OK)
|
||||
return err;
|
||||
|
||||
if (len)
|
||||
{
|
||||
*string = (char *)malloc(len);
|
||||
if (*string == NULL)
|
||||
{
|
||||
fPosition -= sizeof(int32);
|
||||
return B_NO_MEMORY;
|
||||
}
|
||||
|
||||
err = Read(*string, len);
|
||||
if (err < B_OK)
|
||||
{
|
||||
free(*string);
|
||||
*string = NULL;
|
||||
fPosition -= sizeof(int32);
|
||||
return err;
|
||||
}
|
||||
(*string)[len-1] = '\0';
|
||||
return B_OK;
|
||||
}
|
||||
else
|
||||
{
|
||||
fPosition -= sizeof(int32);
|
||||
return B_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
// "Forbidden" functions :P
|
||||
status_t RAMLinkMsgReader::GetNextMessage(int32 *code, bigtime_t timeout)
|
||||
{
|
||||
debugger("RAMLinkMsgReader::GetNextMessage is not permitted");
|
||||
return B_ERROR;
|
||||
}
|
||||
|
||||
|
||||
void RAMLinkMsgReader::SetPort(port_id port)
|
||||
{
|
||||
debugger("RAMLinkMsgReader::SetPort is not permitted");
|
||||
}
|
||||
|
||||
|
||||
port_id RAMLinkMsgReader::GetPort(void)
|
||||
{
|
||||
debugger("RAMLinkMsgReader::GetPort is not permitted");
|
||||
return B_ERROR;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -39,38 +39,24 @@
|
||||
size_t buffer size
|
||||
[data buffer]
|
||||
*/
|
||||
class RAMLinkMsgReader : public LinkMsgReader
|
||||
{
|
||||
public:
|
||||
RAMLinkMsgReader(int8 *buffer);
|
||||
RAMLinkMsgReader(void);
|
||||
~RAMLinkMsgReader(void);
|
||||
|
||||
void SetBuffer(int8 *buffer);
|
||||
int8 *GetBuffer(void);
|
||||
size_t GetBufferSize(void);
|
||||
int32 Code(void) { return fCode; }
|
||||
|
||||
status_t Read(void *data, ssize_t size);
|
||||
status_t ReadString(char **string);
|
||||
template <class Type> status_t Read(Type *data)
|
||||
{
|
||||
return Read(data, sizeof(Type));
|
||||
}
|
||||
class RAMLinkMsgReader : public LinkMsgReader {
|
||||
public:
|
||||
RAMLinkMsgReader(int8 *buffer);
|
||||
RAMLinkMsgReader(void);
|
||||
virtual ~RAMLinkMsgReader(void);
|
||||
|
||||
// These should never need to be called where this class is used. However, we do
|
||||
// need to make debugging easier for such contexts...
|
||||
status_t GetNextMessage(int32 *code, bigtime_t timeout);
|
||||
void SetPort(port_id port);
|
||||
port_id GetPort(void);
|
||||
|
||||
protected:
|
||||
|
||||
|
||||
int8 *fBuffer, *fAttachStart;
|
||||
int8 *fPosition;
|
||||
size_t fAttachSize;
|
||||
int32 fCode;
|
||||
void SetBuffer(int8 *buffer);
|
||||
int8 *GetBuffer(void);
|
||||
size_t GetBufferSize(void);
|
||||
int32 Code(void) { return fCode; }
|
||||
|
||||
virtual status_t Read(void *data, ssize_t size);
|
||||
|
||||
protected:
|
||||
int8 *fBuffer, *fAttachStart;
|
||||
int8 *fPosition;
|
||||
size_t fAttachSize;
|
||||
int32 fCode;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -208,7 +208,7 @@ RootLayer::WorkingThread(void *data)
|
||||
|
||||
STRACE(("info: RootLayer(%s)::WorkingThread listening on port %ld.\n", oneRootLayer->GetName(), oneRootLayer->fListenPort));
|
||||
for (;;) {
|
||||
err = messageQueue.GetNextReply(code);
|
||||
err = messageQueue.GetNextMessage(code);
|
||||
if (err < B_OK) {
|
||||
STRACE(("WorkingThread: messageQueue.GetNextReply failed\n"));
|
||||
continue;
|
||||
|
||||
+558
-838
File diff suppressed because it is too large
Load Diff
@@ -30,6 +30,7 @@
|
||||
|
||||
#include <OS.h>
|
||||
#include <String.h>
|
||||
#include <PortLink.h>
|
||||
|
||||
#include "FMWList.h"
|
||||
|
||||
@@ -38,8 +39,6 @@ class BMessage;
|
||||
class BPortLink;
|
||||
class BList;
|
||||
class DisplayDriver;
|
||||
class LinkMsgReader;
|
||||
class LinkMsgSender;
|
||||
class ServerPicture;
|
||||
class ServerCursor;
|
||||
class ServerBitmap;
|
||||
@@ -92,9 +91,9 @@ public:
|
||||
|
||||
private:
|
||||
void DispatchMessage(int32 code, LinkMsgReader &link);
|
||||
|
||||
|
||||
static int32 MonitorApp(void *data);
|
||||
|
||||
|
||||
// our BApplication's event port
|
||||
port_id fClientAppPort;
|
||||
// port we receive messages from our BApplication
|
||||
@@ -104,15 +103,14 @@ private:
|
||||
// as BAppServerLink/BPortlink's messages always contain the reply port
|
||||
// To send a message to the client, write a BMessage to this port
|
||||
port_id fClientLooperPort;
|
||||
|
||||
|
||||
BString fSignature;
|
||||
|
||||
|
||||
thread_id fMonitorThreadID;
|
||||
team_id fClientTeamID;
|
||||
|
||||
LinkMsgReader *fMsgReader;
|
||||
LinkMsgSender *fMsgSender;
|
||||
|
||||
|
||||
BPortLink fLink;
|
||||
|
||||
// TODO:
|
||||
// - Are really Bitmaps and Pictures stored per application and not globally ?
|
||||
// - As we reference these stuff by token, what about putting them in hash tables ?
|
||||
|
||||
@@ -12,7 +12,7 @@ void
|
||||
get_next_message(BPortLink &link, int32 expectedCode)
|
||||
{
|
||||
int32 code;
|
||||
if (link.GetNextReply(code) != B_OK) {
|
||||
if (link.GetNextMessage(code) != B_OK) {
|
||||
fprintf(stderr, "get message failed!\n");
|
||||
exit(-1);
|
||||
}
|
||||
@@ -96,7 +96,7 @@ main()
|
||||
get_next_message(receiver, 'tst5');
|
||||
|
||||
int32 code;
|
||||
status = receiver.GetNextReply(code, 0);
|
||||
status = receiver.GetNextMessage(code, 0);
|
||||
if (status != B_WOULD_BLOCK) {
|
||||
fprintf(stderr, "reading would not block!\n");
|
||||
return -1;
|
||||
|
||||
Reference in New Issue
Block a user