[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: yet more FTPAPI questions



Sender: Scott Klement <sk@xxxxxxxxxxxxxxxx>

currently the error message texts are scattered all around the source code; I want to put them into on space (just like the error constants themselves); actually, would not even store the texts but create them when they are requested by FTP_errormsg (unless they are the result of errorstr()).

I don't like the idea of putting them all into FTP_errormsg(). It makes it more difficult to read the code, more difficult to debug, and nearly impossible to put "fill-in" data in the message. (Variable informaion in the error message.)


I was even thinking about putting them into a message file, for ease of localization without recompiling. Opinions?

However, I do like the idea of using message files, particularly with the use of fill-in fields in the message descriptions. The SetError() routine can be modified to only accept the variable data, and FTP_errorMsg() can use an API to compose a human-readable message from the message description and the fill-in data.


As you say, this'll make it easier for localization.

currently the default CCSIDs are constants. how about changing them to "typed constants" (initialized variables)? Again, that would allow changing them without a recompile. as it is, one can change the defaults for the data channel via ftp_codepage, but is stuck on the control channel.

I'd rather that the defaults be constants, and a subprocedure be provided that can change the values (much like FTP_codePage)



A follow-up question to the former one, to Scott. Why did you set the server CCSID for the control channel to 437 and not 367? Is there really any server out there which uses the PC code set on the control channel? (I am aware that the IBM FTP server uses 819, ISO Latin-1, on the data channel per default).

Hmmm.. I had HTTPAPI set to 367 for awhile, but had problems that it didn't translate to many different character sets. 819 seems to work a lot better.


Keep in mind that I originally wrote FTPAPI to accomplish my business goals, and only later decided to make it open source.

When I originally wrote FTPAPI, I used the same table for translating both the control channel and the data channels. Since the files I originally wrote FTPAPI for were 437, I set that as the code page. I added the ability to change this default later because other people needed it.


my last question for the time being, about TCP_Conn. Actually, a few questions on that topic. First, let's see if I understood it right:

- obtain a numerical IP address from the host string
- create a socket
- change the socket to non-blocking, if a timeout is requested
- attempt connect
- when connect suceeds, return happily (I assume, that only happens
 in the blocking mode; can't be *that* quick in non-blocking)

Non-blocking mode should always fail at this point. But, if it doesn't, what should we do? Seems like returning happily is the right thing to do. Obviously, in blocking mode it's the right thing to do.


- if it failed, wait for success via select(); I am assuming that is for timeout/non-blocking mode *only*; but it kind of works as in the other case the timeout is set to zero; mind if I make that "cleaner"?

EINPROGRESS will only be returned if the socket is in non-blocking mode, so it'll never get to the select() API if it's in blocking mode.


- if select returns with failure, we give up

I don't know of any reason why select() would return failure, here. Except, maybe, if the user ends the connection with NETSTAT *CNN and takes option 4.


However, what should we do if it does return failure? Seems to me, the safest thing is to return an error and exit the subprocedure.

Now comes the odd part for me; if select() returns with success, you seem not to trust the sockets API. Instead, you try to connect once more on the same socket and check if it fails with EISCONN (as expected). Um... is the sockets API (specifically select()) really that unreliable?

When select() returns successfully, (i.e. that the socket is writable) it does NOT mean that the connection was made successfully. It means that either the connection was successful, or an error occurred and it stopped trying.


So we need to know which situation happened? Did it succeed? Or did it fail and return an error?

In the past, I've called connect() a second time to see if the socket is connected. That's how I did it in FTPAPI. The problem with that method is that connect() doesn't give you a good error message if the connection failed -- it'll return EINVAL instead of the reason the connection failed.

Recently, I've learned that you can call getsockopt() to get SO_ERROR to find out whether it has succeeded or failed. I need to experiment with this a little more, but I planned to change FTPAPI to use the new code once I've figure it out.

Perhaps a better way to implement a timeout is to use signals. With signals, you'd set up an alarm in XX seconds, then call connect(). If the SIGALRM signal is received, connect() would return EINTR and you'd know it timed out.

Although signals aren't as efficient as select(), the difference in speed probably doesn't matter when connecting. (Though, it would matter more when calling send() and recv(), since we do that much more frequently.)
-----------------------------------------------------------------------
This is the FTPAPI mailing list. To unsubsribe from the list send mail
to majordomo@xxxxxxxxxxxxx with the body: unsubscribe ftpapi mymailaddr
-----------------------------------------------------------------------