5. Channel Mechanism (信道机制)
5. Channel Mechanism (信道机制)
所有终端会话, 转发连接等均表现为信道 (channel). 任一端均可打开信道. 多个信道被复用到单一连接中.
信道在每一端用编号标识. 两端指代同一信道的编号可以不同. 打开信道的请求包含发送方的信道编号. 任何其他与信道相关的消息包含该信道在接收方的编号.
信道具有流控 (flow control): 在收到表明窗口 (window) 空间可用的消息之前, 不得向信道发送数据.
5.1. Opening a Channel (打开信道)
当任一方希望打开新信道时, 它为该信道分配一个本地编号, 然后向对端发送下列消息, 并在消息中包含本地信道编号与初始窗口大小.
byte SSH_MSG_CHANNEL_OPEN
string channel type in US-ASCII only
uint32 sender channel
uint32 initial window size
uint32 maximum packet size
.... channel type specific data follows
channel type 是一个名称, 如 [SSH-ARCH] 与 [SSH-NUMBERS] 所述并带有类似扩展机制. sender channel 是发送本消息一方使用的信道本地标识符. initial window size 指明在调整窗口之前, 可以向本消息发送方发送多少字节的信道数据. maximum packet size 指明可以发送给发送方的单个数据包的最大长度. 例如, 在慢速链路上对交互式连接可能希望使用较小数据包以获得更好的交互响应.
远端随后决定是否可打开该信道, 并以 SSH_MSG_CHANNEL_OPEN_CONFIRMATION 或 SSH_MSG_CHANNEL_OPEN_FAILURE 响应.
byte SSH_MSG_CHANNEL_OPEN_CONFIRMATION
uint32 recipient channel
uint32 sender channel
uint32 initial window size
uint32 maximum packet size
.... channel type specific data follows
recipient channel 是原打开请求中的信道编号, sender channel 是对端分配的信道编号.
byte SSH_MSG_CHANNEL_OPEN_FAILURE
uint32 recipient channel
uint32 reason code
string description in ISO-10646 UTF-8 encoding [RFC3629]
string language tag [RFC3066]
若 SSH_MSG_CHANNEL_OPEN 的接收方不支持所指定的 channel type, 则仅响应 SSH_MSG_CHANNEL_OPEN_FAILURE. 客户端可以将 description 字符串展示给用户. 若这样做, 客户端软件应采取 [SSH-ARCH] 中讨论的预防措施.
SSH_MSG_CHANNEL_OPEN_FAILURE 的 reason code 取值见下表. 为便于阅读, reason code 以十进制给出, 实际为 uint32.
| Symbolic name | reason code |
|---|---|
SSH_OPEN_ADMINISTRATIVELY_PROHIBITED | 1 |
SSH_OPEN_CONNECT_FAILED | 2 |
SSH_OPEN_UNKNOWN_CHANNEL_TYPE | 3 |
SSH_OPEN_RESOURCE_SHORTAGE | 4 |
在 0x00000005 至 0xFDFFFFFF 范围内为新的 SSH_MSG_CHANNEL_OPEN reason code (及关联 description 文本) 申请赋值时, 必须通过 [RFC2434] 所述的 IETF CONSENSUS 方法. IANA 不会在 0xFE000000 至 0xFFFFFFFF 范围内分配 Channel Connection Failure 的 reason code. 该范围内的取值保留为 PRIVATE USE, 见 [RFC2434].
尽管 IANA 对 0xFE000000 至 0xFFFFFFFF 范围没有控制权, 该范围仍分为两部分并按下列约定管理.
-
0xFE000000 至 0xFEFFFFFF 与本地分配的信道配合使用. 例如, 若提议的
channel type为"[email protected]"但打开失败, 则响应中的reason code要么是 IANA 分配的取值 (如上所列, 且在 0x00000001 至 0xFDFFFFFF 内), 要么是 0xFE000000 至 0xFEFFFFFF 内的本地分配值. 自然, 若服务器不理解所提议的channel type, 即便该类型是本地定义的, 则在发送reason code时该reason code必须为 0x00000003, 如上所述. 若服务器理解该channel type但信道仍无法打开, 则服务器应使用与所提议的本地channel type一致的本地分配reason code. 假定实现者会先尝试使用 IANA 已分配的reason code, 再文档化其本地分配值. -
以 0xFF 开头的范围没有限制或建议. 用于该范围的任何内容均不期望互操作, 本质上供实验使用.
5.2. Data Transfer (数据传输)
窗口大小指明对端在必须等待窗口调整之前可以发送的字节数. 双方使用下列消息调整窗口.
byte SSH_MSG_CHANNEL_WINDOW_ADJUST
uint32 recipient channel
uint32 bytes to add
接收此消息后, 接收方可以比先前允许的多发送给定字节数; 窗口大小递增. 实现必须正确处理最大为 2^32 - 1 字节的窗口. 窗口不得增加到超过 2^32 - 1 字节.
数据传输使用下列类型的消息.
byte SSH_MSG_CHANNEL_DATA
uint32 recipient channel
string data
允许的最大数据量由该信道的最大包长与当前窗口大小中的较小者决定. 窗口大小按已发送数据量减少. 在允许窗口耗尽后, 双方可以忽略所发送的多余数据.
实现预期对 SSH 传输层数据包大小存在某种上限 (对接收数据包的上限必须至少为 32768 字节, 见 [SSH-TRANS]). SSH 连接层的实现:
-
不得公告会导致传输层数据包超过其传输层愿意接收的最大包长;
-
不得生成大于其传输层愿意发送的数据包, 即便远端愿意接受非常大的包.
此外, 某些信道可传输多种类型的数据. 例如交互式会话的 stderr 数据. 此类数据可通过 SSH_MSG_CHANNEL_EXTENDED_DATA 传递, 由单独的整数指明数据类型. 可用类型及其解释取决于信道类型.
byte SSH_MSG_CHANNEL_EXTENDED_DATA
uint32 recipient channel
uint32 data_type_code
string data
通过这些消息发送的数据与普通数据消耗同一窗口.
当前仅定义下列类型. 为便于阅读, data_type_code 以十进制给出, 实际为 uint32.
| Symbolic name | data_type_code |
|---|---|
SSH_EXTENDED_DATA_STDERR | 1 |
Extended Channel Data Transfer 的 data_type_code 值必须按序分配. 在 0x00000002 至 0xFDFFFFFF 范围内为新的 Extended Channel Data Transfer data_type_code 及其关联 data 字符串申请赋值时, 必须通过 [RFC2434] 所述的 IETF CONSENSUS 方法. IANA 不会在 0xFE000000 至 0xFFFFFFFF 范围内分配此类 data_type_code. 该范围内保留为 PRIVATE USE, 见 [RFC2434]. 对 IANA 的具体指示见 [SSH-NUMBERS].
5.3. Closing a Channel (关闭信道)
当一方不再向某信道发送更多数据时, 应发送 SSH_MSG_CHANNEL_EOF.
byte SSH_MSG_CHANNEL_EOF
uint32 recipient channel
对此消息不发送显式响应. 但应用程序可以向信道另一端传递 EOF. 注意发送此消息后信道仍保持打开, 反方向仍可继续发送数据. 此消息不消耗窗口空间, 即便没有可用窗口也可以发送.
当任一方希望终止信道时, 发送 SSH_MSG_CHANNEL_CLOSE. 收到此消息后, 一方必须回送 SSH_MSG_CHANNEL_CLOSE, 除非它已为该信道发送过此消息. 当一方既发送又收到 SSH_MSG_CHANNEL_CLOSE 时, 该信道对该方视为已关闭, 方可复用该信道编号. 一方可以在未发送或未收到 SSH_MSG_CHANNEL_EOF 的情况下发送 SSH_MSG_CHANNEL_CLOSE.
byte SSH_MSG_CHANNEL_CLOSE
uint32 recipient channel
此消息不消耗窗口空间, 即便没有可用窗口也可以发送.
建议尽可能将在此消息之前发送的所有数据递送到实际目的地.
5.4. Channel-Specific Requests (信道相关请求)
许多 channel type 具有仅适用于该类型的扩展. 例如为交互式会话请求 pty (伪终端).
所有信道相关请求使用下列格式.
byte SSH_MSG_CHANNEL_REQUEST
uint32 recipient channel
string request type in US-ASCII characters only
boolean want reply
.... type-specific data follows
若 want reply 为 FALSE, 则不对请求发送响应. 否则接收方以 SSH_MSG_CHANNEL_SUCCESS, SSH_MSG_CHANNEL_FAILURE 或请求特定的后续消息响应. 若无法识别请求或该信道不支持该请求, 则返回 SSH_MSG_CHANNEL_FAILURE.
此消息不消耗窗口空间, 即便没有可用窗口也可以发送. request type 的取值对每种信道类型是局部的.
允许客户端在等待请求响应的同时继续发送其他消息.
request type 名称遵循 [SSH-ARCH] 与 [SSH-NUMBERS] 中的 DNS 可扩展命名约定.
byte SSH_MSG_CHANNEL_SUCCESS
uint32 recipient channel
byte SSH_MSG_CHANNEL_FAILURE
uint32 recipient channel
这些消息不消耗窗口空间, 即便没有可用窗口也可以发送.