-
Notifications
You must be signed in to change notification settings - Fork 126
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
RFC2217 support integration #95
Comments
A more serious problem: The totally-asynchronous nature of RFC2217 commands can cause some problems, especially during program initialization and startup. When a new port is added, first The problem is that, at this point, negotiation has not completed, and the port settings are not, yet, known. So the term library copies in its Once the RFC2217 port is added, it gets configured, by calling This is a very real problem: The (rational) user expectation is that the port has been configured (to the command-line settings values) before picocom enters its main loop. This problem can easily manifest if the user does something like, for example:
The string is sent to the port, before the port has been configured, which is clearly wrong. Possible solution: The solution would be to wait for the respective RFC2217-commands to complete (i.e. their outstanding responses actually received by the tn2217 code). This must happen, possibly, every time a configuration change is requested (i.e. Postscript 1: A question occurs: What to do with user-data that are received from the port while waiting for the outstanding operations to complete? Hopefully, I believe, that the easy answer (discard them) is adequate. I'm almost certain it is ok to discard them at initialization and initial configuration phases---but I think it would also be ok to discard them at subsequent configuration change-requests (since a configuration change-request is a disruptive operation, anyhow). Postscript 2: If discarding user-data, as described in postscript 1, i not acceptable, then the only solution (and it is a much harder one) is to buffer them, and have |
Clean-up and refactoring / restructuring for the integration with picocom is mostly done... More testing is needed and (most-likely) more small tweaks will come-up during testing. Most important, for now, is the error / problem described in the comment above... |
Before picocom enters it's main loop and data are written to serial port, and also before the first data are read from the port, the port must first be configured. That is: The first data read from picocom's standard input (or the initstring) must be written to the port, *after* the port has been configured to the settings specified by picocom's command-line arguments; also, the first data must be read from the port, after the port has been configured (as any data read before, will most likely be garbage). When tn2217_write() is called it checks that the initial negotiations have completed, and that the RFC2217 port-configuration commands have been transmitted. If this is not true, then the function waits by reading from the port and processing commands until the condition becomes true or a timeout expires. When tn2217_read() is called it checks that the initial negotiations have completed, that the RFC2217 port-configuration commands have been transmitted *AND* that their replies have been received. Any user-data read by picocom before the replies to the commands are received will most likely be data read by the server using the old port configuration and therefore useless (garbage). To make the test easier, we actually check that an equal number of replies-to-configuration-commands has been received as configuration-commands have been sent (a misbehaving server can confuse us by sending multiple replies to commands, but this is always the case). Again, then the function waits by reading from the port and processing commands until the condition becomes true or a timeout expires. See also discussion in issue #95
Commit 0f2194d is a solution to the issue described in #95 (comment) |
Hi, @npat-efault Yes that is a problem in non-interactive mode. I think i see how 0f2194d operates, and I suspect I can achieve a fix with less complexity. I would make You wondered what to do with user data received while waiting for option negotiations to settle? I would send them to stdout. I recommend not discarding them because sometimes just the act of accessing a remote port can cause the service to dump its own rx buffers, which may contain valuable content. |
I'm not sure how to reference it here through github, but please see a perhaps simpler fix at https://github.com/dleonard0/picocom/tree/tn2217-init-fixes
|
@dleonard0 Hmm, maybe not open Also: You will see a couple of FIXME comments on top of the "wait for config" code in On the other hand maybe this is too complicated, and we should always (regardless of --noinit) wait for negotiations to finish... |
Less complicated is good. Perhaps it would be easier to document caveats about Telnet mode than to close all the differences with local terms? |
Regarding https://github.com/dleonard0/picocom/tree/tn2217-init-fixes I believe that before we start reading from the port, the port must have been configured to the requested settings. That is: configuration commands send, and replied. We do not want to read (show to the user) data comming from a remote device that is configured to work at a different baudrate than the port it's connected to (i.e garbage data). More detailed explanation: If I run:
Then I expect that at the requested port, a device is connected that is configured to operate @ 19200. Obviously, I don't want to see ANY data from this device, received before the port is configured to the requested settings (as this data will by definition be garbage). This means I have to wait for the config command to be replied, and discard any data received in between. On the other hand, if I run:
Then yes, I assume the port is already properly configured, and I want to see data coming from it, as soon as I open it / connect to it... |
Sadly, I believe that once the server accepts the TCP connection it may begin reading from its port, even before RFC2217 support is negotiated, making this an impossible problem to solve. |
The servers I have seen tend to retain the UART settings of their port. The ones I am most familiar with are console servers which have their port speeds already set up. So, specifying |
The server may start reading immediately, but we should discard any data read and sent (to us) before the port is configured. That is, any data sent (to us) before the replies to the config commands. This not very different to what happens when you open a local port. Any data received by the driver before the port is configured are normally discarded / flushed... |
Two questions: 1/ What would it mean for the server to accept COMPORT, while we haven't? That it's ok for us to send COMPORT commands, but not ok for him to send responses? Or that it would not be ok for him to send notifications? (Since I believe the server never initiates COMPORT commands, anyway). The distinction seems a bit moot 2/ In what way would the behavior of the server (or ours, for that matter) be different before BINARY is negotiated? |
I see: This is the "init" (non-noinit) case where the picocom user is in full control of the port, and discarding garbage makes sense. For this to work, I think we'd have to keep track of the first time we receive confirmation of UART changes, and discard rx'd data up to that point? I'm not sure how that should go. Perhaps a call to tn2217_read() could be interpreted to indicate that setup has completed?
That was a mistake, fixed in 3cf7f7b. We only implemet the client half of COM-PORT, so we need only send a DO, and not a WILL. Update: also, we could start sending the COM-PORT sub-commands immediately and maybe the remote end will process or discard them. But we really shouldn't until the remote has told us that it WILL COM_PORT.
Without BINARY, the peer could conceivably choke on characters that are not NVT-ASCII. I've always thought of BINARY to mean "8-bit clean". The details are in https://tools.ietf.org/html/rfc856 and NVT-ASCII is defined in RFC 854 and is basically 7-bit ASCII with a few holes in it:
(Yet another edit:) In a UTF-8 world, we pretty much need 8-bit :) |
If you think of it, our differences are: 1/ You (say we should) wait for COMPORT to be negotiated, always. I (say we should) wait for the initial COMPORT commands to be replied, unless run with 2/ While waiting, you timeout using alarm signals. I timeout using select() (and I prefer it very much this way). 3/ I add a 4/ I agree with you that the "waiting for negotiations" should better happen in 5/ You say we should dump everything read from the server (even before negotiations are complete, and regardless of I think it's a fair assessment, don't you? |
The way I see it, any data rx'ed (by us) before the replies to the COMPORT config commands, are data (read by the server) before its UART was reconfigured. Any data received (by us) after the replies, are data (read by the server) after its UART was reconfigured. It is conceivable that a server could behave differently, but it would have to be a very strange implementation (and in any case we can do nothing better in this case). |
I think you got it backwards... Copying from RFC2217:
So we need to send a WILL and not a DO |
!%@#%, you're right!
Yes that's pretty fair. Perhaps this reveals the extent that I have had expediency beaten into me ;) |
Actually, if the meaning of the option is that the peer will send |
Debatable... It depends on how you interpret the "willing to accept" part of the following:
Is sending the reply / acknowledgement part of me accepting a command? Or is it considered another command altogether? I tend to lean towards the former interpretation based on the wording of this:
This of-course leaves open the case of unsolicited access server notifications (e.g MODEMSTATE or LINESTATE notifications), but these are never mentioned as "commands" and they need not be acknowledge by the client. So I tend to believe that the intention was for the client to announce with WILL, and the access server to ack with DO, and not the other way around... The opposite (the access server anouncting with WILL and the client acking with DO) would (to me) indicate the intention of the access server to initiate himself COMPORT commands (for whatever reason I cannot think of)... |
BTW I have also started to wonder if this feature is "too big" for picocom. Perhaps a separated pty-rfc2217 approach would be better... I think I would prefer that picocom stay "pico". |
I have also thought of this, but no... 1/ The memory footprint is not too large 2/ It can be conditionally compiled out 3/ The implications to the rest of picocom are not too big (and most of them, like the abstraction of term are rather good) Actually picocom has stopped being truly, really, honest to god, "pico" quite some time ago (not that it's getting huge... I don't mean that)... |
OOPS! Important! Now I remembered why I didn't put the "waiting for negotiations" code in Because, at this point, the port configuration settings have not been passed to tn2217 anyway (since Aside: As a matter of fact, your code in So my "wait for port ready" code in The first time you are asked to read (user data) from the port, or write (user data) to the port, see if the port's configuration has been requested. If so, make sure that all negotiations have finished and that the port has actually been configured to the requested settings, before going ahead with the read, or the write. If, instead, no port configuration has been requested, then go ahead with the read or the write immediately, as the port's existing configuration can be assumed operable. The check for "if the port's configuration has been requested", is not currently done, but it's the subject of the So, try to peruse through the code at the tip of my rfc2217 branch, and you'll see that it's neither too complicated, not too ad-hoc and irrational. The things I'm not very happy with are: 1/ I would prefer it if there was a function like 2/ The fact that 2/ I would be open to different ways of verifying that the configuration commands have been replied, but the current one (of counting requests against replies) seem ok to me. 3/ The thing about the COMPORT negotiation being symmetric or not, we discussed before. EDIT: FIXED TYPOS |
Regarding COMPORT negotiation: I ran a little test with sredird. If picocom sends, by itself, neither (If picocom does sent This seems to support the case that clients should send |
Some additional tests with ser2net, which seems much more polished than sredird. I've rigged picocom's debugging output to show all messages exchanged during negotiation (I will commit this, when I polish it up a bit). I 've also removed irrelevant debugging output... First a run when picocom initiates no negotiation (no WILL no DO) at all:
Ok, the implementation seems not to be exactly RFC854 compliant, since it sends several superfluous messages, but it does not attempt to send any Next, I send him only
Again no intention from ser2net to send Third run, I sent it
Now things are clear: Although it operates as an RFC2217 access server, it replies to |
All these lead me to believe that the correct (most robust) thing to do is
The transaction with ser2net, with the above described settings is as follows:
And the option values, end up like this (
|
A test: Two ports, connected with null-modem cable: First I run:
And then, from another terminal, within 20sec, I run:
I wait for both to finish, and do:
They match. Then I configure ser2net to have a default baudrate of 19200 on port
Again, at the end, the files match. NOTE 1: When picocom is run with NOTE 2: Observe that the sending picocom has no |
Regarding negotiations, again. A correction about the handling of the
|
Combined commit. No time and too messy to split it up. - Cleaned up, improved debugging output - Correct options negotiations - Refactored wait_cond(), waid_cmd(), not to repeat code from read() See also discussion in issue #95
Branch rfc2217 is, for the most part, ready for merging to master. Will let it wait some time for additional testing and merge it at some point the next couple of weeks... |
Thanks to @dleonard0 who contributed the implementation, picocom is in the process of gaining support for RFC2217-protocol remote ports.
Here is the original PR #93 submitted by @dleonard0
Integration work currently happens in branch rfc2217, so keep monitoring this if interested.
I open this issue to have a convenient place for the relevant discussion...
The text was updated successfully, but these errors were encountered: