[interfacekit] Re: BSession

> Hi!

Hi Adi. Thanks for explaining things.

I made a mistake not realising the BSession chunks/fragments messages into 1024 
byte pieces unless
Sync() is ahead of time. So there is a degree of efficiency.

> > status_t write_port_etc(port_id port, int32 code, const void *buffer, 
> > size_t bufferSize,
> uint32
> > flags, bigtime_t timeout);
> > 
> > The "int32 code" parameter is NOT the BMessage's "what".

>       Nope! It IS! See Looper.cpp's:
>               ReadRawFromPort,
>               ReadMessageFromPort,
>               ConvertToMessage
>       methods.
>       A system message with no buffer data IS a valid BMessage.

Ok, so it is used differently. Sometimes it is 'what', sometimes it is for the 
protocol. This is
confusing but perhaps unavoidable. You have to read the implementation to be 
sure. By using it two
ways we fail to establish a convention for others to follow.

[...]
>       In the beginning was PortLink, then came along BSession. When Marc 
> finished BPicture implementation, AreaLink appeared. There was a debate 
> why not to use PortLink over BSession, and I and DW had long talks about 
> that. The fact is, PortLink is message oriented and BSession not 
> streamed, and we need that.

OK, the trade-offs are thus:

You chunk (combine multiple messages) so the server might be able get a second 
message without
waiting on the port queue semaphore. It's optimized for small messages. The 
(unlikely) non-optimal
scenario is a stream of messages larger than 1024 bytes.

You fragment so you can flush at will so don't have to dynamically resize the 
buffer to avoid
overflow.

You lose message boundaries in the deal, but you're going to fix that...

[...]
>       ATM everything is working just fine with this method in server.
>       IF, someone tries to unify those will go into serious problems, because 
> of the handler. I mean, if you have a handler that is mainly oriented on 
> PortMessage/PortLink and you send a message with BSession, you will run 
> into BIIIIIG trouble because BSession messages are NOT complete! The 
> other way a BSession handler and sending with PortLink, no problem 
> appears(as you have noticed, in PortLink already there is a method for 
> sending to BSession hander) but a lot of code needs to be modified;

Is the potential BIIIIIG trouble reason to finish the details before using it 
everywhere?

This thread and your reply serves as documentation for the rest of us.

Looking at the CVS it seemed like there was a BSession vs BPortMessage battle 
going on:
http://cvs.sourceforge.net/viewcvs.py/open-beos/current/src/kits/interface/Window.cpp

>       The conclusion we reached: use BSession where you PortLink can't be 
> used: ServerWindow!

Are we agreed on the engineering trade-offs? Or is it a social compromise?

> 
> > AS_SERVER_PORTLINK
>       And your problem is...?

None, just summarising. Although I might fix the memory management bugs, buffer 
overflow exploit,
and error detection in PortMessage ;-)

[...]
> > Looking at the BSession implementation, write_port() is called for the 
> > 'what' and each data
> item.
>       Where is that you have seen that?

My misunderstanding.

> 
> > This incurs a high overhead in sending/decoding in the number of port 
> > calls. The messages are
> > fragmented to single data items.    
>       High overhead? an automatically write_port() is made for a 1024bytes 
> buffer. "in sending/decoding"? what do you mean?

My misunderstanding.

> 
> > I don't see the advantage of this since the server shouldn't
> > execute a command until it has checked all the parameters.
When I wrote the about I mean like:

Read Command: DRAW_LINE
Read Parameter: x1
Read Parameter: y1
Read Parameter: x2
Read Parameter: y2
Execute(DRAW_LINE, x1, y1, x2, y2);

>       :-))) Wrong! While the client side buffer is filling in (BSession's 
> one) app_server is executing drawing instructions. There is a high 
> probability that, by the time the next write_port() is made and the 
> message reaches the server, the previous commands be already executed.
>       Eh? What do you say about that? Nice, isn't it?

The advantage comes from client-server not from BSession's buffering.

Infact, while the client side is buffering multiple commands, the server could 
be sitting idle.
It's worth noting that the port mechanism already gives you a port queue for 
buffering.

> 
> > The degree of parallelism this offers
> > is insignificant and it causes excessive context-switching.
>       Insignificant? Think again! :-)
>       Oh, BTW, Be did it this way!
> 
>       Excessive context switching? Yes... but I would not call it "excessive" 
> - have have a buffer, don't we?

My misunderstanding.

> 
>       Oh... think if you had PortLink instead of BSession in BWindow/BView? 
> Would you have seen something drawn until BView::Draw() ended? What 
> about if you do a lots of things inside Draw(), how big would have the 
> message been? how long it would have taken for the server to execute 
> instruction found inside? Same is valuable when attaching a large BView 
> tree.

I detect communication problems...I don't know if we're agreeing or disagreeing.

Commands could be write_port'ed one by one for speed or grouped for efficiency. 
What I object to
is fragmenting a command. Each write_port() should deal with complete messages.

If you want to avoid flicker then the user shouldn't see a BView being drawn 
command by command.
So you would optimize for minimal total drawing time, rather than try and get 
the first command of
many drawn as soon as possible -- assuming you want double 
buffered/vtrace/vblank drawing as
default on the appserver.

> 
> > Also BSession had all the return error codes removed. I'm unable to create 
> > robust software
> with
> > it.
> > 
> > void BSession::ReadData( void* data, int32 size );
> > void BSession::WriteData(const void* data, int32 size);
> > void BSession::Sync();
>       Yes, I have added them, then removed. I no longer need them.
> a
>       code = AS_NO_MESSAGE;
>       ses->ReadInt32(&code)
> would tell me if something went wrong. This case... the port has been 
> deleted.

So you have to remember to reset "code" to AS_NO_MESSAGE, and assume that 
nothing will actually
send an int32 with the value of AS_NO_MESSAGE, and you have to get a reply to 
know whether or not
your send was sucessful. If you don't get a reply, you won't know if it's a 
problem with your
send, or a problem with the server replying.

ses->WriteInt32(COMMAND_1);
ses->WriteInt32(PARAMETER_1);
ses->WriteInt32(COMMAND_2);
ses->ReadInt32(&REPLY_1);

If for some reason WriteInt32(COMMAND_1); failed, then PARAMETER_1 might be 
interpreted by the
server as COMMAND_3 and COMMAND_2 as a parameter.

Then I get REPLY_1 and assume that both COMMAND_1 and COMMAND_2 were 
sucessfully processed.

Another example, internal to BSession:

char* BSession::ReadString(){
        int16           len = 0;
        char            *str = NULL;

        ReadData( &len, sizeof(int16));

        if (len > 0){
                str = (char*)malloc(len);
                ReadData(str, len);
        }
        return str;
}

Good we remembered to initialise len = 0. 
We ReadData() the length of the string correctly, it is 80.
The third-party application crashes before the string could be written.
We ReadData(str, len) on an invalid port.
The code returns str as non-null.
Our server printf's the unterminated buffer and segfaults.
Or maybe uses some bogus data to corrupt something important.

It may work if we code perfectly, but it's not defensive programming.

>       Why do you need to use BSession? it is private!

Besides the fact I hack on more than one appserver, the Java, Python, and 
BePascal groups may
eventually want to interface directly with the appserver.

> 
> > If we receive multiple logical messages in one port call, and the appserver 
> > does not recognize
> the
> > 'what' of the first message, the remaining messages have to be dumped 
> > because we don't know
> where
> > the message boundaries are. What should be the policy here? Should the 
> > client be disconnected?
>       No, all datas will be dumped until the next code is recognized.
>       I know about this... and I had in plan to suffix each instruction 
> with... AS_END_INSTRUCTION.

But some parameter may have the value of AS_END_INSTRUCTION.

> 
> > If there is any deviation in the number or size of data items outside of 
> > what we expect, the
> whole
> > stream becomes out of sync without error detection. We could be reading 
> > bogus data without
> knowing
> > it as missing data is taken from the next message, and extra data becomes 
> > the head of the next
> > message.
>       In 99.99999% of cases this won't happen. Unless a bad user or program 
> will write to a ServerWindow port. I have discussed this with Michael 
> and he said it is not concerned by security.

Bad users will be happy that we didn't secure the most obvious exploits. Bad 
third-party programs
are a fact of life. Bugs are inevitable. You never know where the problem could 
cascade to. It's
bad design.

As developers of appserver we ourselves will find it hard to debug. We will 
have a lot of
incomplete code and changing protocols. We have to disable BWindow sending X 
notification
eventhough we've implemented it because the appserver isn't ready to deal with 
message X, and
sending it will de-synchronize our stream.

> 
> > In anycase, if we decided to have BSession as a streamlined protocol, I 
> > suggest it be only be
> used
> > for non-critical communications, such as drawing instructions. Structural 
> > or state change
> messages
> > should not use this protocol if we tolerate dropping messages in BSession.
>       Sorry but it is the only one suited for BWindow/BView <-> app_server 
> communication. It worked perfectly until now and I don't see any 
> problems appearing. Hell... Be used it, and look what a nice graphical 
> interface R5 has.
> 
> > Do we really need BSession?
>       Yup!

Considering the trade-offs, I need more persuasion.

> 
> > What problem is it meant to solve?
>       No you have some answers.

What does BSession fix? Did we profile? Is the cure worse than the problem?

> Bye,
> Adi.

Cheers,
Paul.



        
                
__________________________________
Do you Yahoo!?
Yahoo! Tax Center - File online by April 15th
http://taxes.yahoo.com/filing.html

Other related posts: