Skip to main content

3. 协议操作 (Protocol Operation)

本节描述 PPTP 协议的操作细节,包括控制连接状态、呼叫状态以及各种操作场景的处理流程。

3.1. 控制连接状态 (Control Connection States)

控制连接是 PAC 和 PNS 之间建立的 TCP 连接,用于交换 PPTP 控制消息。控制连接的建立可以由 PAC 或 PNS 中的任何一方发起。

基本状态转换

控制连接经历以下基本状态:

  1. Idle(空闲) - 没有控制连接存在
  2. Wait-Connect(等待连接) - 已发送连接请求,等待回复
  3. Established(已建立) - 控制连接已成功建立
  4. Wait-Disconnect(等待断开) - 已发送断开请求,等待确认

3.1.1. 控制连接发起方 (Control Connection Originator)

控制连接的发起方(可以是 PAC 或 PNS)执行以下操作:

状态:Idle(空闲)

  • 操作:建立 TCP 连接到对等方
  • 发送:Start-Control-Connection-Request
  • 转换到:Wait-Reply 状态

状态:Wait-Reply(等待回复)

  • 接收:Start-Control-Connection-Reply (Result = 成功)
    • 转换到:Established 状态
  • 接收:Start-Control-Connection-Reply (Result = 错误)
    • 关闭 TCP 连接
    • 转换到:Idle 状态
  • 超时:
    • 关闭 TCP 连接
    • 转换到:Idle 状态

状态:Established(已建立)

  • 可以发送和接收:所有 PPTP 控制消息
  • 发送:Echo-Request(周期性保持活动)
  • 接收:Echo-Reply(响应保持活动)
  • 发送:Stop-Control-Connection-Request(主动关闭)
    • 转换到:Wait-Stop-Reply 状态

状态:Wait-Stop-Reply(等待停止回复)

  • 接收:Stop-Control-Connection-Reply
    • 关闭 TCP 连接
    • 转换到:Idle 状态
  • 超时:
    • 关闭 TCP 连接
    • 转换到:Idle 状态

3.1.2. 控制连接接收方 (Control Connection Receiver)

控制连接的接收方(可以是 PAC 或 PNS)执行以下操作:

状态:Idle(空闲)

  • 监听:TCP 端口 1723
  • 接收:TCP 连接请求
    • 接受 TCP 连接
    • 转换到:Wait-Request 状态

状态:Wait-Request(等待请求)

  • 接收:Start-Control-Connection-Request
    • 验证:协议版本、参数
    • 如果接受:
      • 发送:Start-Control-Connection-Reply (Result = 成功)
      • 转换到:Established 状态
    • 如果拒绝:
      • 发送:Start-Control-Connection-Reply (Result = 错误)
      • 关闭 TCP 连接
      • 转换到:Idle 状态

状态:Established(已建立)

  • 可以发送和接收:所有 PPTP 控制消息
  • 接收:Echo-Request
    • 发送:Echo-Reply
  • 接收:Stop-Control-Connection-Request
    • 发送:Stop-Control-Connection-Reply
    • 关闭 TCP 连接
    • 转换到:Idle 状态

3.1.3. Start Control Connection 初始化请求冲突 (Initiation Request Collision)

当 PAC 和 PNS 同时尝试建立控制连接时,可能会发生冲突。处理方式如下:

  1. 检测冲突:当一方在 Wait-Reply 状态时收到 Start-Control-Connection-Request
  2. 冲突解决
    • 比较 IP 地址(数值大小)
    • IP 地址较小的一方:关闭其发起的连接,接受对方的连接
    • IP 地址较大的一方:继续其发起的连接,拒绝对方的连接
  3. 最终结果:只建立一条控制连接

3.1.4. 保持活动和定时器 (Keep Alives and Timers)

为了维护控制连接的活跃状态,实现以下机制:

Echo-Request/Reply 机制

  • 发送频率:建议每 60 秒发送一次 Echo-Request
  • 超时处理:如果在 60 秒内未收到 Echo-Reply,认为连接失败
  • 重试策略:可以重试 3 次,每次间隔 60 秒
  • 连接失败:连续多次超时后,关闭控制连接

TCP 保持活动

  • 可以使用 TCP 层的保持活动机制作为补充
  • PPTP 层的 Echo 机制是必需的 (MUST)

定时器参数

  • 控制连接建立超时:60 秒
  • 保持活动间隔:60 秒
  • Echo-Reply 超时:60 秒
  • 控制连接关闭超时:60 秒

这些定时器值是建议值,实现可以根据需要调整,但应确保:

  • 保持活动间隔足够短,以便及时检测连接失败
  • 超时值足够长,以避免由于网络延迟导致的误判

3.2. 呼叫状态 (Call States)

3.2.1. 时序考虑 (Timing Considerations)

由于电话信令的实时性,PNS 和 PAC 都应该采用多线程架构实现,以确保与多个呼叫相关的消息不会被串行化和阻塞。PAC 和 PNS 之间的传输延迟不应超过 1 秒。呼叫和连接状态图没有明确指定由定时器引起的异常。隐含的假设是,由于基于 TCP 的控制连接正在通过保持活动消息进行验证,因此对呼叫控制消息维护严格的定时器的需求较少。

建立国际出站呼叫,包括调制解调器训练和协商序列,可能需要超过 1 分钟的时间,因此不建议使用短定时器。

如果状态转换在 1 分钟内未发生(除了处于空闲或已建立状态的连接),则对等方之间协议处理的完整性是可疑的,应关闭并重新启动整个控制连接。每当控制连接启动时,所有呼叫 ID 都会逻辑释放。这大概也有助于防止收费呼叫被"遗失"而永远不被清除。

3.2.2. 呼叫 ID 值 (Call ID Values)

每个对等方为其请求或接受的每个用户会话分配一个呼叫 ID 值。此呼叫 ID 值必须 (MUST) 在它所属的 PNS 和 PAC 之间的隧道内是唯一的。到其他对等方的隧道可以使用相同的呼叫 ID 号码,因此隧道上数据包的接收方需要将用户会话与特定隧道和呼叫 ID 关联起来。建议每个隧道的潜在呼叫 ID 值数量至少是给定隧道上预期最大呼叫数量的两倍。

会话由三元组 (PAC, PNS, Call ID) 定义。

3.2.3. 入站呼叫 (Incoming Calls)

当相关电话线路响铃时,PAC 会生成 Incoming-Call-Request 消息。PAC 选择一个呼叫 ID 和序列号,并指示呼叫承载类型。调制解调器应始终指示模拟呼叫类型。当使用无限制数字服务或速率自适应时,ISDN 呼叫应指示数字类型;当涉及数字调制解调器时,应指示模拟类型。如果从电话网络获得主叫号码、被叫号码和子地址,则可以在消息中包含这些信息。

一旦 PAC 发送 Incoming-Call-Request,它会等待来自 PNS 的响应,但不会应答来自电话网络的呼叫。如果出现以下情况,PNS 可能选择不接受呼叫:

  • 没有可用资源来处理更多会话
  • 被叫、主叫或子地址字段不表示授权用户
  • 承载服务未被授权或不受支持

如果 PNS 选择接受呼叫,它会响应一个 Incoming-Call-Reply,该回复还指示窗口大小(参见第 4.2 节)。当 PAC 收到 Outgoing-Call-Reply 时,它会尝试连接呼叫,假设主叫方尚未挂断。来自 PAC 到 PNS 的最终呼叫连接消息表示 PAC 和 PNS 的呼叫状态都应进入已建立状态。

当拨入客户端挂断时,呼叫正常清除,PAC 发送 Call-Disconnect-Notify 消息。如果 PNS 希望清除呼叫,它会发送 Call-Clear-Request 消息,然后等待 Call-Disconnect-Notify。

3.2.3.1. PAC 入站呼叫状态 (PAC Incoming Call States)

与 PAC 入站呼叫相关的状态有:

idle(空闲)

  • PAC 在其电话接口之一上检测到入站呼叫。通常这意味着模拟线路正在响铃,或 ISDN TE 检测到入站 Q.931 SETUP 消息。PAC 发送 Incoming-Call-Request 消息并移至 wait_reply 状态。

wait_reply(等待回复)

  • PAC 收到 Incoming-Call-Reply 消息,指示不愿意接受呼叫(一般错误或不接受),并返回到空闲状态。如果回复消息指示接受呼叫,PAC 发送 Incoming-Call-Connected 消息并进入已建立状态。

established(已建立)

  • 数据通过隧道交换。呼叫可能在以下情况后被清除:
    • 电话连接上的事件。PAC 发送 Call-Disconnect-Notify 消息
    • 收到 Call-Clear-Request。PAC 发送 Call-Disconnect-Notify 消息
    • 本地原因。PAC 发送 Call-Disconnect-Notify 消息

状态转换图

    Ring/Send Incoming Call Request          +-----------------+
+----------------------------------------->| wait_reply |
| +-----------------+
| Receive Incoming Call Reply V V V
| Not Accepting | | | Receive Incoming
| +--------------------------------+ | | Call Reply Accept-
| | +------------------------------+ | ing/Answer call;
| | | Abort/Send Call | Send Call
| | | Disconnect Notify V Connected
^ V V +-----------------+
+-----------------+ | established |
| idle |<-----------------------------| |
+-----------------+ Receive Clear Call Request +-----------------+
or telco call dropped
or local disconnect
/Send Call Disconnect Notify

3.2.3.2. PNS 入站呼叫状态 (PNS Incoming Call States)

与 PNS 入站呼叫相关的状态有:

idle(空闲)

  • 收到 Incoming-Call-Request 消息。如果请求不可接受,将 Incoming-Call-Reply 发送回 PAC,PNS 保持在空闲状态。如果 Incoming-Call-Request 消息可接受,则发送 Incoming-Call-Reply,在结果代码中指示接受。会话移至 wait_connect 状态。

wait_connect(等待连接)

  • 如果会话在 PAC 上连接,PAC 向 PNS 发送入站呼叫连接消息,然后 PNS 移至已建立状态。PAC 可能发送 Call-Disconnect-Notify 以指示入站呼叫者无法连接。例如,如果电话用户意外地向 PAC 发起标准语音呼叫,导致被叫调制解调器握手失败,就会发生这种情况。

established(已建立)

  • 会话通过从 PAC 收到 Call-Disconnect-Notify 消息或发送 Call-Clear-Request 来终止。一旦发送了 Call-Clear-Request,会话就进入 wait_disconnect 状态。

wait_disconnect(等待断开)

  • 一旦收到 Call-Disconnect-Notify,会话就移回空闲状态。

状态转换图

  Receive Incoming Call Request
/Send Incoming Call Reply +-----------------+
Not Accepting if Error | Wait-Connect |
+-----+ +-----------------+
| | Receive Incoming Call Req. ^ V V
| | /Send Incoming Call Reply OK | | | Receive Incoming
| | +--------------------------------+ | | Call Connect
^ V ^ V------------------------------+ V
+-----------------+ Receive Call Disconnect +-----------------+
| Idle | Notify +- | Established |
+-----------------+ | +-----------------+
^ ^ | V Local Terminate
| +----------------------------+ | /Send Call Clear
| Receive Call Disconnect | Request
| Notify V
| +-----------------+
+--------------------------------------| Wait-Disconnect |
Receive Call Disconnect +-----------------+
Notify

3.2.4. 出站呼叫 (Outgoing Calls)

出站消息由 PNS 发起,指示 PAC 在电话接口上发起呼叫。出站呼叫只有两条消息:Outgoing-Call-Request 和 Outgoing-Call-Reply。PNS 发送 Outgoing-Call-Request,指定被叫方电话号码和子地址以及速度和窗口参数。一旦 PAC 确定以下情况,它必须 (MUST) 使用 Outgoing-Call-Reply 消息响应 Outgoing-Call-Request 消息:

  • 呼叫已成功连接
  • 由于以下原因发生呼叫失败:没有可用于拨出的接口、被叫方忙或未应答、或在为拨号选择的接口上检测不到拨号音

3.2.4.1. PAC 出站呼叫状态 (PAC Outgoing Call States)

与 PAC 出站呼叫相关的状态有:

idle(空闲)

  • 收到 Outgoing-Call-Request。如果接收错误,则使用设置错误条件的 Outgoing-Call-Reply 进行响应。否则,分配物理通道进行拨号。发起出站呼叫,等待连接,并移至 wait_cs_ans 状态。

wait_cs_ans(等待电路交换应答)

  • 如果呼叫未完成,则发送带有非零错误代码的 Outgoing-Call-Reply。如果出站呼叫的定时器过期,则发送带有非零错误代码的 Outgoing-Call-Reply。如果建立了电路交换连接,则发送指示成功的 Outgoing-Call-Reply。

established(已建立)

  • 如果收到 Call-Clear-Request,应 (SHOULD) 通过适当的机制释放电话呼叫,并应 (SHOULD) 向 PNS 发送 Call-Disconnect-Notify 消息。如果客户端或电话接口断开呼叫,应 (SHOULD) 向 PNS 发送 Call-Disconnect-Notify 消息。

状态转换图

Receive Outgoing Call Request in Error
/Send Outgoing Call Reply with Error
|--------+
| | Receive Outgoing Call Request No Error
| | /Off Hook; Dial
| | +-----------------------------------------
^ V ^ V
+-----------------+ Incomplete Call +-----------------+
| idle | /Send Outgoing Call | wait_cs_ans |
+-----------------+ Reply with Error +-----------------+
^ ^ or Recv. Call Clear Req. V V Telco Answer
| | /Send Disconnect Notify| | /Send Outgoing
| +-------------------------------------+ | Call Reply.
| V
| +-----------------+
+-------------------------------------| established |
Receive Call Clear Request +-----------------+
or local terminate
or telco disconnect
/Hangup call and send
Call Disconnect Notify

3.2.4.2. PNS 出站呼叫状态 (PNS Outgoing Call States)

与 PNS 出站呼叫相关的状态有:

idle(空闲)

  • 上层应用程序的打开指示导致发送 Outgoing-Call-Request 并移至 wait_reply 状态。

wait_reply(等待回复)

  • 如果收到带有错误的 Outgoing-Call-Reply,则移回空闲状态。如果收到成功的 Outgoing-Call-Reply,则移至已建立状态。如果在等待 Outgoing-Call-Reply 时发生中止,则发送 Call-Clear-Request 并移至 wait_disconnect 状态。

established(已建立)

  • 如果收到 Call-Disconnect-Notify,则移至空闲状态。如果发生本地终止,则发送 Call-Clear-Request 并移至 wait_disconnect 状态。

wait_disconnect(等待断开)

  • 如果收到 Call-Disconnect-Notify,则移至空闲状态。

状态转换图

                Open Indication                              Abort/Send
/Send Outgoing Call Call Clear
Request +-----------------+Request
+-------------------------------->| Wait-Reply |----------+
| +-----------------+ |
| Receive Outgoing Call Reply V V Receive Outgoing |
| with Error | | Call Reply |
| +-------------------------------+ | No Error |
^ V V |
+-----------------+ +-----------------+ |
| Idle |<-----------------------------| Established | |
+-----------------+ Receive Call Disconnect +-----------------+ |
^ Notify V Local Terminate |
| | /Send Call Clear |
| | Request |
| Receive Call Disconnect V |
| Notify +-----------------+ |
+----------------------------------| Wait-Disconnect |<--------+
+-----------------+