On Tue, 27 Apr 1999, Olivier Booklage wrote:

----- snip ----- re: BNet and TCP response when remote BNet machine is RESET
>
>warm reset by back side button, not shutdown.prg

So you mean 'hard warm reset' rather than 'soft warm reset' as I thought.

Actually a 'resvector'+'resvalid' patch could catch that case as well,
but I am unsure of how/if this is handled both by MagiC and by BNet,
and the port drivers might not work in that state. (Never tested AFAIK.)

I think even such a reset can be handled 'transparently', since some
game programs do exactly that.  (Reset switch has no visible effect.)
The only way to reset them is power-cycling. (hard cold reset)


----- snip ----- re: how you define 'CIB' present
>
>present is memory available by CNgetinfo

Ok, but if the connection had a CIB earlier CNgetinfo only tests if the
handle remains valid.  If it does, then any CIB it owned also remains.
The release of a CIB can only occur _after_ the handle is made invalid.


>>>CNbyte_count >= 0 but if try a TCP_close(), it return  E_BADCLOSE (-14) !!!!!
>>
>>If BNet has already called TCP_close for that connection, as it should,
>
>I do not think so by pressing back side warm reset button :)

I think you are correct for now, but it is not a necessary limitation.
(Unless MagiC somehow makes it so, which unfortunately seems likely.)


>>>So it is a "GOST" link, and it stay hours... :( is very bad.
>>
>>That is of course a bug.  It may legally stay for up to 1000 seconds, due to
>>failed closure negotiation, but no longer.  At least that is the intention
>>of the present code (the time limit is arbitrary, as no standard exists).
>
>Noticed.

Ok. So we agree on what it _should_ do.  Now we need to find why it doesn't !


>>>If somebody can confirm that.
>>>
>>I'll experiment a bit and see what I can find out.  If the procedure you
>>describe has this result consistently, then we have a simple method of
>>testing if a new patch fixes this problem.

(answering myself here)
I still haven't taken time to test this properly myself, but I think you
have a valid bug there.


>>Btw:
>>Can someone also confirm the horribly bad results I get with aFTP 1.51b ?
>>I get an almost perfectly constant upload rate of 1024 cps, regardless
>>of my bitrate.  I've tried up to 153600 bps, and still only get 1024cps !
>>No other FTP client shows this symptom AFAIK.
>
>I confirm.

Good, then it is not just my setup.
Can someone please test aFTP 1.51b upload under STiK as well, and compare
the effective cps with that of Newsie for the same file and server, and
report results back here.

If STiK results correspond with those under STinG, then it definitely is
some error in the aFTP code that causes the slow upload.


>Maybe the problem is when :
>
>TCP_open() +
>CNbytes_count() loop ( == 0 )

Sorry, the above is too abbreviated for me to understand what you mean.


>you will never if the remote is crashed, no ?

'you will never' do what ?  I'm not sure what you mean, so I must guess.

Possibly you meant that CNbytes_count never reaches zero, but that does
not really matter.  If TCP_close is called, then CNbytes_count is not a
factor for the internal close negotiation code.  Only the ACKing of the
remote and its final FIN packet matter then.  Both of those will never
come in from a remote that is reset in a such a way that its BNet can't
send the 'abort' message, so the 1000 second timeout should apply here
instead.

But, in another recent mail Vassili states that BNet does _NOT_ call
the TCP_close at abort anyway, but waits until a new call from the
same remote comes in before closing the old connection...

As I see it that should then be done regardless of whether any 'abort'
message ever arrived, since it would be silly to have two different
connections for a single purpose.  And if this is done, then I see no
sense in the use of the 'abort' message at all...


>a TCP_wait_ack() is a solution as PING for IRC servers ?

No, that operation requires an exchange of real TCP data, going both
ways. The PING is not over until the server has the full PONG message
from the PINGed client, or after a timeout without such response.
No TCP_ack_wait should be needed (or even useful).

NB: TCP_ack_wait now really is, as described in the old STiK docs,
    "a kludge that you should probably never use".  There may be
    exceptions, but I don't think IRC PING is one of them.

But you need to check this in RFC 1459, which deals with IRC.
That should also be your main reference for development of new
commands in your IRCD. (Which I think motivated your question.)
Plus advice from the IRC veterans of course. (Lonny ?  Flinny ?)

Here is part of what the RFC says about the IRC PING:
----- RFC 1459 partial quote start -----
4.6.2 Ping message

      Command: PING
   Parameters: <server1> [<server2>]

   The PING message is used to test the presence of an active client at
   the other end of the connection.  A PING message is sent at regular
   intervals if no other activity detected coming from a connection.  If
   a connection fails to respond to a PING command within a set amount
   of time, that connection is closed.

   Any client which receives a PING message must respond to <server1>
   (server which sent the PING message out) as quickly as possible with
   an appropriate PONG message to indicate it is still there and alive.
   Servers should not respond to PING commands but rely on PINGs from
   the other end of the connection to indicate the connection is alive.
   If the <server2> parameter is specified, the PING message gets
   forwarded there.
----- RFC 1459 partial quote end -----

Note that the above contains a method that helps minimize the risk of
any longterm 'remnant' connections if clients 'drop the line'.  They
should then be cleaned out completely 1000 seconds after the PING
timeout without PONG response (since server should close then).
There is a risk that these connections will instead suffer the same
fate as the BNet connections that this thread was really about,  but
when that bug is fixed the effect should be as I described in the
previous sentence.


----- snip ----- re: SLOW (1024cps) uploads with  aFTP 1.51b
>
>I confirm, CNbytes_count() loop too slow ?

I think that they have a low limit on the number of TCP_send calls per
evnt_loop (1?), with a fixed small send size, and use a long timer event.
That is the only thing I can think of that would give so constant and
low transfer rate for all the bps rates that I tried.

But it is a totally insane method !  They should know better !

Simple arithmetic says that:
cps_rate_for_a_loop = sends_per_loop * send_size / loop_period

So assuming that send_size (except at EOF) and loop_period are constants,
the only way to get high upload speed is to _not_ limit sends_per_loop,
but let this climb to whatever the bps used can handle.


Here is one method that I would prefer for any server or client APP:

First we have the event loop start, being of the normal 'forever' kind
(to be exited by break), or some other construct with similar effect.

Then we should record the current time, using a clock() call. since that
works for both STiK and STinG (unlike TIMER_now). This value will be
used later to see if the long loop time has been exceeded.
(Let's call this variable loop_start_time here.)

That is then followed by the usual kind of evnt_multi call scanning
for clicks, menu_events etc, including a _minimal_ timeout event.

Having a fairly long time interval for the main event work is no problem,
but it is wrong to use a long timer event to achieve it.  Instead a short
timer event should be used, just to allow immediate (almost) exit when no
other event type expected has occurred.

Then the main event work code should be executed, handling the stuff
that needs to be done once only per long loop period, and responding
to any non-timer events that were returned by the evnt_multi call.
(Menu, Window, Dialog, and other update stuff etc etc.)

After that there should be an inner loop, with a loop condition like
    "while ( (clock() - loop_start_time) < long_event_period )"

The inner loop should contain all the TCP_send and CN_get* calls and
other stuff that may need to be repeated more than once in the long
period, such as listening for server connections etc, but it should
_not_ contain any further loops. (Such could defeat the purpose.)

Last inside the inner loop should be a call to _appl_yield(), the
minimum-delay AES call discussed many times before, which is also
defined by an assembly source and .H binding in most of my STinG
sources for Pure_C.  (See NetD package for example.)

That call, placed in that position, ensures that each inner loop pass
allows other tasks to be unblocked, but without causing any task switch
before the loop code has been executed at least once.

And after that call both loops end, and so does my little example.


Hmmm.  Perhaps I should send them a copy of this...
What do you guys think ?

I don't want to seem to be 'patronizing' them, but the present aFTP
upload performance is _totally_ useless to me.  Until they fix it
I'm going back to aFTP 1.5b again.

