ATT(二)

三、ATTRIBUTE PDU

1、有6种类型的PDU:

(1)Requests:由client发送给server,server需要回复responses

(2)Responses:由server发送给client,用来回复client的request

(3)Commands:由client发送给server

(4)Notifications:由server主动发送给client,不需要client允许

(5)Indications:由server主动发送给client,不需要client允许,并且client需要回复confirmations

(6)Confirmations:由client发送给server,用来确定client收到了来自server的indication

注意:

(1)一个Server必须要支持对Find Information Request和Read Request回复相关的response,其他类型的PDU type是否支持由上层协议规定

(2)client发送一个request,那么client需要支持由于这个request而收到的所有可能的response PDU

(3)如果server收到一个它不支持的request,server应该回复Error Response,错误码«Request Not Supported»,Attribute Handle设置为0x0000

(4)如果server收到一个它不支持的command(PDU中Command Flag为1),则server直接忽略

(5)如果server收到一个无效的request(例如:PDU长度错误),server应该回复Error Response,错误码«Invalid PDU»,Attribute Handle设置为0x0000

(6)如果server没有足够的资源处理request,server应该回复Error Response,错误码«Insufficient Resources»,Attribute Handle设置为0x0000

(7)如果server在处理request过程中出现异常,server应该回复Error Response,错误码 «Unlikely Error»,Attribute Handle设置为0x0000

2、Attribute PDU Format

(1)除了Attribute Value字段外,其余的字段都是小端序(低位在前),Attribute Value字段的字节顺序由上层协议规定

(2)Attribute Opcode由3个字段组成:Authentication Signature Flag、Command Flag和Method;

(a)Authentication Signature Flag:长度1 bit,Attribute Opcode的bit 7,表示PDU中是否包含Authentication Signature value,Authentication Signature Flag=1则包含且上图中X=13,Authentication Signature Flag=0则不包含且上图中X=1

(b)Command Flag:长度1 bit,Attribute Opcode的bit 6,这个字段设置为1,则这个PDU是command

(c)Method:长度6 bit,Attribute Opcode的bit 0至bit 5,用来决定Attribute Parameters的格式和含义

(3)Authentication Signature:这个字段值是根据Security Manager协议计算出来的,这个字段是对Attribute Opcode和Attribute Parameters的校验

注意:

(a)一个包含Authentication Signature字段的Attribute PDU不能再加密连接上传输,原因是加密连接上每个数据包已经包含了authentication数据,再添加Authentication Signature没有必要

(b)只有Write Command才有可能包含Authentication Signature字段

3、连续性协议(Sequential Protocol)

(1)Client发送一个request给server,在收到这个request的response之前不能发送其他request

(2)Server发送一个Indications给client,在收到这个Indications的confirmation之前不能发送其他Indications,client在发送confirmation之前可以自由发送commands和requests

(3)notifications由于不需要回复PDU,所以可以在任何时候发送

(4)Commands也不需要回复PDU,所以可以在任何时候发送,这样就有可能导致大量的command在server端堆积,如何处理这种情况由上层协议规定

(5)由于缓冲区溢出或者其他原因导致某些Commands或者notifications没有处理时,应该丢弃这些command或者notifications

注意:

(1)request和response的流控方式是不影响notifications的传输,例如:server收到request后,先发送一个或者多个notifications,然后才发送针对这个request的response;

(2)request和response的流控方式是不影响commands的传输,例如:server收到request还没有回复response的时候又收到一个command

(3)indications和confirmation的流控方式不影响notifications的传输,例如: server发送了一个indication但是没有收到confirmation之前又发送了一个notification

(4)client收到一个indication但是还没有回复confirmation之前,可能发送一个request或者command

疑问:server收到request还没有回复response之前,是否可以发送indication?

4、Transaction(交易)

(1)一对request-response或者indication-confirmation称为一次transaction

request-response对:

在client端,一次transaction从发送request开始,到收到response完成

在server端,一次transaction从收到request开始,到发送response完成

indication-confirmation对:

在server端,一次transaction从发送indication开始,到收到confirmation完成

在client端,一次transaction从收到indication开始,到发送confirmation完成

(2)一次transaction在30s没有完成则认为超时,认为这次transaction失败,并通知上层,失败后不能再向对方发送requests、commands、indications或者notifications,并断开当前ATT Bearer,如果需要发送其他的PDU,则需要在两个设备之间再次建立ATT Bearer

注意:每个Prepare Write Request和对应的response都是一个transaction;同样每个Read Blob Request和对应的response都是一个transaction

四、ATTRIBUTE PROTOCOL PDUS

1、Error Handling

1.1 Error Response

Error Response用来说明给定的request不能执行,并提供原因

注意:Write Command不会产生Error Response

参数说明:

(1)Request Opcode In Error:表示产生Error response的request的Attribute Opcode;

(2)Attribute Handle In Error:表示产生Error response的request的attribute handle,如果request中没有attribute handle或者这个request不支持,则设置为0x0000;

(3)Error Code:产生error response的原因,取值如下:

注意:如果client不理解Error Response中的error code,则client应该认为request不能执行,原因是unknown reason

2、MTU Exchange

2.1 Exchange MTU Request

Exchange MTU Request这个request是client发送sever的,用来告知server自己(client)的RX MTU size,并请求server回复自己(server)的RX MTU size

参数说明:

(1)Client Rx MTU:表示Client的Rx MTU size,这个值应该设置为client能接收的最大attribute PDU size,且这个值>= default ATT_MTU;这个request应该只在client建立连接的过程中发送一次

2.2 Exchange MTU Response

Server发送Exchange MTU Response用来回复收到的Exchange MTU Request

参数说明:

(1)Server Rx MTU:表示server的Rx MTU size,这个值应该设置为server能接收的最大attribute PDU size,且这个值>= default ATT_MTU;

注意:

(1)server和client最终设置的ATT_MTU应该为Client Rx MTU和Server Rx MTU两者中的最小值

(2)server使用ATT_MTU的时机应该在:回复response之后且在发送其他attribute protocol PDU之前;

client使用ATT_MTU的时机应该在:收到response之后且在发送其他attribute protocol PDU之前;

(3)如果Client Rx MTU或者Service Rx MTU小于default ATT_MTU,则ATT_MTU应该设置为default ATT_MTU

(4)如果一个设备既是server又是client,应该按照下面的规则:

(a)这个设备的Exchange MTU Request中的Client Rx MTU应该和Exchange MTU Response中的Service Rx MTU的值是一样的

(b)如果MTU已经在一个方向进行交互了,则两个方向都可以使用,不过两个方向都进行交互也是允许的,结果都是一样的

(c)如果发送MTU Exchange Request之后且收到MTU Exchange Response之前,收到一个 Attribute Protocol Request,则相关的Attribute Protocol Response应该使用default MTU,如下图所示

(d)设备一旦发送了MTU Exchange Request,则这个设备在收到MTU  Exchange Response之前不能发送Attribute Protocol Indication或者Notification

3、Find Information

3.1 Find Information Request

Client用Find Information Request从server端获取attributes及attribute types列表,

 

参数说明:

(1)Starting Handle:请求获取的第一个attribute的handle

(2)Ending Handle:请求获取的最后一个attribute的handle

注意:

(1)在Find Information Response中只会返回Starting Handle和Ending Handle之间的handle,包括Starting Handle和Ending Handle,如果要获取所有attribute的列表,需要设置

Starting Handle=0x0001,Ending Handle=0xFFFF,Starting Handle<= Ending Handle,如果有一个或者多个符合要求的attribute,则server会回复Find Information Response

(2)如果server收到的Find Information Request中Starting Handle大于Ending Handle,或者Starting Handle=0x0000,则server应该回复Error Response,错误码为«Invalid Handle»,Error Response中的Attribute Handle设置为Find Information Request的Starting Handle

(3)如果没有符合要求的attribute,则server应该回复Error Response,错误码为«Attribute Not Found»,Error Response中的Attribute Handle设置为Find Information Request的Starting Handle

(4)server使用Error Response回复Find Information Request时,error code不能设置为«Insufficient Authentication»、«Insufficient Authorization»、«Insufficient Encryption Key Size»或者«Application Error»

3.2 Find Information Response

Server使用Find Information Response回复收到的Find Information Request

参数说明:

(1)Format:取值如下

(2)Information Data:这里面是handle-UUID对的列表,具体格式需要根据Format确定,如下图所示:

 

注意:

(1)Find Information Response中必须是完整的handle-UUID对,一个handle-UUID对不能分到两个response中,handle-UUID对,应该按照attribute handles的升序排列

(2)如果两个连续的attributes,但是UUID size不同,那么可能是Find Information Response不能包含所有符合要求的handle-UUID对,这种情况下,client需要发送其他的Find Information Request并设置相应的starting handle去请求接下来的attribute

3.3 Find By Type Value Request

Find By Type Value Request作用是client用来获取具有特定attribute bype(只能是16bit UUID)和attribute value的attribute的handle。当attribute type决定attribute分组时,可以使用Find By Type Value Request找到特定attribute的handle范围(注意:GATT决定如何使用attribute byte对attribute进行分组)

 

参数说明:

(1)Starting Handle和Ending Handle:决定Find By Type Value Request搜索的范围,只有在Starting Handle和Ending Handle之间的(包括Starting Handle和Ending Handle),与attribute type和attribute value匹配且有read权限的attribute才会在Find By Type Value Response中返回,如果要获取所有符合要求的attribute,需要设置Starting Handle=0x0001,Ending Handle=0xFFFF

(2)Attribute Type:只能是16bit的UUID

(3)Attribute Value:具体的attribute值

注意:

(1)如果有一个或者多个符合要求的attribute,则server会回复Find By Type Value Response

(2)如果没有符合要求的attribute,则server应该回复Error Response,错误码为«Attribute Not Found»,Error Response中的Attribute Handle设置为Find Information Request的Starting Handle

(3)Attribute values比较的是长度和二进制数值,Attribute values的长度<=ATT_MTU-7

(4)如果server收到的Find By Type Value Request中Starting Handle> Ending Handle或者Starting Handle=0x0000,则会回复Error Response,错误码«Invalid Handle»,Attribute Handle In Error设置为Starting Handle

(5)server使用Error Response回复Find Information Request时,error code不能设置为«Insufficient Authentication»、«Insufficient Authorization»、«Insufficient Encryption Key Size»、«Insufficient Encryption»或者«Application Error»

3.4 Find By Type Value Response

当server收到Find By Type Value Request时,可以使用Find By Type Value Response进行回复

参数说明:

Handles Information List:包含一个或者多个handle information的列表,每个information的格式如下:

 

注意:

(1)Handles Information List中包含的一个或者多个handle information必须是完整的,一个handle information不能分到两个Find By Type Value Response中,Handles Information List中handle information时按照Found Attribute Handle顺序排序的

(2)如果Find By Type Value Request中的attribute byte对应的是上层协议定义的grouping attribute,则Group End Handle也应该是上层协议定义的;如果Find By Type Value Request中的attribute byte对应的不是上层协议定义的grouping attribute,则Group End Handle= Found Attribute Handle;

(3)Group End Handle可能大于Find By Type Value Request 中的参数Ending Handle

4、Reading Attributes

4.1 Read By Type Request

Read By Type Request作用是根据attribyte type来获取attribute value,当attribute byte知道attribute hanle不知道时可以使用这个request

参数说明:

(1)Starting Handle和Ending Handle:决定Read By Type Request的范围,只有在Starting Handle和Ending Handle之间的(包括Starting Handle和Ending Handle),且具有attribute type相同值的attribute才会在Read By Type Response中返回,如果要获取所有符合要求的attribute,需要设置Starting Handle=0x0001,Ending Handle=0xFFFF

注意:

(1)所有的attribute type都要转换成128bit的UUID进行比较,即使attribute定义是16bit的也需要转换

(2)Starting Handle<=Ending Handle,如果server收到的Read By Type Request中Starting Handle>Ending Handle或者Starting Handle=0,则server应该回复Error Response,error code为«Invalid Handle»,Attribute Handle In Error为Starting Handle

(3)如果没有符合要求的attribute,server应该回复Error Response,error code为«Attribute Not Found»,Attribute Handle In Error为Starting Handle

(4)如果server中的attribute的attribute type符合要求且attribute handle也在要求的范围内,但是attribute values的长度不同,那么client应该使用多个Read By Type Requests读取

(5)如果server中多个attribute符合要求,应该按照下面规则:

       (a)只能可读的attribute可以通过Read By Type Response返回

(b)如果符合要求的attribute集合中有一个attribute会引起Error Response,则这个attribute不应该包含在Read By Type Response中,这个attribute之前的attribute会通过Read By Type Response返回

(c)如果符合要求的attribute集合中第一个attribute会引起Error Response,则认为没有一个符合要求的attribute

(6)如果client由于insufficient authorization导致read attribute失败,则server会回复Error Response,错误码«Insufficient Authorization»,Attribute Handle In Error设置为导致这个Error Response的那个attribute的handle

(7)如果client由于insufficient security导致read attribute失败,则server会回复Error Response,错误码«Insufficient Authentication»,Attribute Handle In Error设置为导致这个Error Response的那个attribute的handle

(8)如果client由于insufficient encryption key size导致read attribute失败,则server会回复Error Response,错误码«Insufficient Encryption Key Size»,Attribute Handle In Error设置为导致这个Error Response的那个attribute的handle

(9)如果client没有enabled encryption而导致read attribute失败,则server会回复Error Response,错误码«Insufficient Encryption»,Attribute Handle In Error设置为导致这个Error Response的那个attribute的handle

(10)如果请求的attribute由于权限不足导致读取失败,则server会回复Error Response,错误码«Read Not Permitted»,Attribute Handle In Error设置为导致这个Error Response的那个attribute的handle

(11)如果有多个符合要求的attribute,那么client需要获取下一个attribute时需要再次发送Read By Type Request并更新参数starting handle,client判断是否还有符合要求的attribute的方法是:当client发送Read By Type Request收到Error Response且error code为«Attribute Not Found»时表示server端没有符合要求的attribute了

(12)符合要求的attribute且具有相同长度可以在使用一个request全部读取

4.2 Read By Type Response

Read By Type Response是server用来回复Read By Type Request的

 

参数说明:

Length:表示一个handle-value对的长度,最大255byte,因此Read By Type Response中attribute value长度的最大值是(Length – 2) = 253byte(Attribute Data List只有一个handle-value对时,handle长度是2,所以255-2=253)

Attribute Data List:一个或者多个handle-pair对,每个handle-pair对格式如下:

 

 

注意:

(1)Read By Type Response中包含的必须都是完整的handle-value对,一个handle-value对不能分到两个Read By Type Response中,handle-value对根据handle进行排序

(2)如果attribute value长度大于(ATT_MTU - 4) 或者253个字节,那么Read By Type Response会包含attribute value的前N个(N表示(ATT_MTU - 4) 或者253中较小的值)字节,Read Blob Request可以用来读取剩余的字节

4.3 Read Request

Client用Read Request请求server读取某个attribute的value值,如果attribute权限允许read,且handle有效,则server会使用Read Response返回attribute value

 

注意:

(1)如果client由于insufficient authorization导致read attribute失败,则server会回复Error Response,错误码«Insufficient Authorization»

(2)如果client由于insufficient security导致read attribute失败,则server会回复Error Response,错误码«Insufficient Authentication»

(3)如果client由于insufficient encryption key size导致read attribute失败,则server会回复Error Response,错误码«Insufficient Encryption Key Size»

(4)如果client没有enabled encryption而导致read attribute失败,则server会回复Error Response,错误码«Insufficient Encryption»,

(5)如果handle无效,则server会回复Error Response,错误码«Invalid Handle»

(6)如果attribute没有read权限,则server会回复Error Response,错误码«Read Not Permitted»

4.4 Read Response

read response是server用来回复Read Request的

注意:如果attribute value的长度大于(ATT_MTU-1) ,那么Read Response中会包含attribute value的前(ATT_MTU-1)个字节,剩余的字节可以使用Read Blob Request读取

4.5 Read Blob Request

Client发送Read Blob Request可以请求server根据attribute handle和Value Offset读取特定attribute的value特定一部分,并用Read Blob Response回复

 

Value Offset:以0为基准,第一个字节的offset为0

注意:

(1)handle有效、value offset小于等于attribute value的长度、并且attribute有read权限,server才会返回Read Blob Response

(2)如果client由于insufficient authorization导致read attribute失败,则server会回复Error Response,错误码«Insufficient Authorization»

(3)如果client由于insufficient security导致read attribute失败,则server会回复Error Response,错误码«Insufficient Authentication»

(4)如果client由于insufficient encryption key size导致read attribute失败,则server会回复Error Response,错误码«Insufficient Encryption Key Size»

(5)如果client没有enabled encryption而导致read attribute失败,则server会回复Error Response,错误码«Insufficient Encryption»,

(6)如果handle无效,则server会回复Error Response,错误码«Invalid Handle»

(7)如果attribute没有read权限,则server会回复Error Response,错误码«Read Not Permitted»

(8)如果value offset的值大于attribute value的长度,则server会回复Error Response,错误码«Invalid Offset»

(9)如果attribute value有固定长度且<= (ATT_MTU - 3),则server会回复Error Response,错误码«Attribute Not Long»

(10)如果value offset的值等于attribute value的长度,则server回复的Read Blob Response中Part Attribute Value的长度应该是0

(11)如果attribute value的长度大于(ATT_MTU-1)个字节,那么Read Blob Request是唯一可以读取多余部分的方法,attribute value的前(ATT_MTU-1)个字节可以使用Read Request、Handle Value Notification或者Handle Value Indication读取

(12)关于Long attributes上层协议可能指定也可能没有指定具体长度,如果Long attributes长度是可变的,那么只能使用Read Blob Request每次读取一部分一直到收到Error Response,错误码是 «Invalid Offset»,此时就表示结束了

(13)Long Attribute在一个Read Blob Request和下一个Read Blob Request之间可能会改变,至于如何处理由上层协议决定

4.6 Read Blob Response

Server用Read Blob Response回复Read Blob Request

 

如果Read Blob Request 中value offset的值等于attribute value的长度,则Part Attribute Value的长度为0,如果attribute value的长度> (Value Offset + ATT_MTU-1),则返回从Value Offset开始的前(ATT_MTU-1)个字节

4.7 Read Multiple Request

Client使用Read Multiple Request请求server读取2个或者更多的attribute的value并通过

Read Multiple Response返回。

注意:

(1)只有attribute value长度是已知的固定值的才可以读取,但是最后一个attribute value的长度可以是可变的,至于哪些attribute的value的长度是固定值有上层协议规定

(2)当Read Multiple Request参数Set Of Values中的所有handle都有有效的,且对应的attribute都有read权限,server才会回复Read Multiple Response

(3)Set Of Values中的所有handle对应的attribute values的长度不必都一样

(4)Set Of Values中的所有handle不必排序,Read Multiple Response中的attribute value的顺序要跟Set Of Handles中的一样

(5)如果client由于insufficient authorization导致read attribute失败,则server会回复Error Response,错误码«Insufficient Authorization»

(6)如果client由于insufficient security导致read attribute失败,则server会回复Error Response,错误码«Insufficient Authentication»

(7)如果client由于insufficient encryption key size导致read attribute失败,则server会回复Error Response,错误码«Insufficient Encryption Key Size»

(8)如果client没有enabled encryption而导致read attribute失败,则server会回复Error Response,错误码«Insufficient Encryption»,

(9)如果任何一个handle无效,则server会回复Error Response,错误码«Invalid Handle»

(10)如果attribute没有read权限,则server会回复Error Response,错误码«Read Not Permitted»

(11)Error Response中的参数Attribute Handle In Error设置为第一个导致error产生的attribute的handle

4.8 Read Multiple Response

Server用Read Multiple Response回复Read Multiple Request

 

Set Of Values参数中应该包含一系列的attribute value,他们的顺序与request中handle的顺序是对应的。

如果Set Of Values的长度大于(ATT_MTU-1),则只有前(ATT_MTU-1)个字节会包含在Read Multiple Response中

注意:如果client收到的Read Multiple Response中Set Of Values的长度是(ATT_MTU-1),那么client不应该使用这个response里面的attribute value,因为不确定最后一个attribute value是否完整

4.9 Read by Group Type Request

当知道attribute type不知道handle时,client可以使用Read By Group Type Request从server端获取attribute value,Attribute Group Type由上层协议定义

参数说明:

(1)Starting Handle和Ending Handle:决定Read by Group Type Request的范围,只有在Starting Handle和Ending Handle之间的(包括Starting Handle和Ending Handle),且具有Attribute Group Type相同值的attribute才会在Read by Group Type Response中返回,如果要获取所有符合要求的attribute,需要设置Starting Handle=0x0001,Ending Handle=0xFFFF

注意:

(1)所有的attribute type都要转换成128bit的UUID进行比较,即使attribute定义是16bit的也需要转换

(2)Starting Handle<=Ending Handle,如果server收到的Read By Group Type Request中Starting Handle>Ending Handle或者Starting Handle=0,则server应该回复Error Response,error code为«Invalid Handle»,Attribute Handle In Error为Starting Handle

(3)如果Attribute Group Type不是上层协议规定支持的attribute group,则server应该回复Error Response,error code为«Unsupported Group Type»,Attribute Handle In Error为Starting Handle

(4)如果没有符合要求的attribute,server应该回复Error Response,error code为«Attribute Not Found»,Attribute Handle In Error为Starting Handle

(5)如果server中的attribute的attribute type符合要求且attribute handle也在要求的范围内,但是attribute values的长度不同,那么client应该使用多个Read By Group Type Requests读取

(6)如果server中多个attribute符合要求,应该按照下面规则:

       (a)只能可读的attribute可以通过Read By Group Type Response返回

(b)如果符合要求的attribute集合中有一个attribute会引起Error Response,则这个attribute不应该包含在Read By Group Type Response中,这个attribute之前的attribute会通过Read By Type Response返回

(c)如果符合要求的attribute集合中第一个attribute会引起Error Response,则认为没有一个符合要求的attribute

(7)如果client由于insufficient authorization导致read attribute失败,则server会回复Error Response,错误码«Insufficient Authorization»,Attribute Handle In Error设置为导致这个Error Response的那个attribute的handle

(8)如果client由于insufficient security导致read attribute失败,则server会回复Error Response,错误码«Insufficient Authentication»,Attribute Handle In Error设置为导致这个Error Response的那个attribute的handle

(9)如果client由于insufficient encryption key size导致read attribute失败,则server会回复Error Response,错误码«Insufficient Encryption Key Size»,Attribute Handle In Error设置为导致这个Error Response的那个attribute的handle

(10)如果client没有enabled encryption而导致read attribute失败,则server会回复Error Response,错误码«Insufficient Encryption»,Attribute Handle In Error设置为导致这个Error Response的那个attribute的handle

(11)如果请求的attribute由于权限不足导致读取失败,则server会回复Error Response,错误码«Read Not Permitted»,Attribute Handle In Error设置为导致这个Error Response的那个attribute的handle

(12)如果有多个符合要求的attribute,那么client需要获取下一个attribute时需要再次发送Read By Group Type Request并更新参数starting handle,client判断是否还有符合要求的attribute的方法是:当client发送Read By Group Type Request收到Error Response且error code为«Attribute Not Found»时表示server端没有符合要求的attribute了

(13)符合要求的attribute且具有相同长度可以在使用一个request全部读取

4.10 Read by Group Type Response

Server使用Read By Group Type Response回复收到的Read By Group Type Request

 

参数说明:

Length:表示一个Attribute Data的长度,最大255byte,因此Read by Group Type Response中attribute value长度的最大值是(Length – 4) = 251byte(Attribute Data List只有一个Attribute Data时,Attribute Handle长度是2,End Group Handle长度是2,所以255-4=251)

Attribute Data List:一个或者多个Attribute Data,每个Attribute Data格式如下:

注意:

(1)Read By Group Type Response中包含的必须都是完整的Attribute Data,一个Attribute Data不能分到两个Read By Group Type Response中,Attribute Data List根据attribute handle进行排序

(2)如果attribute value长度大于(ATT_MTU - 6) 或者251个字节,那么Read By Group Type Response会包含attribute value的前N个(N表示(ATT_MTU - 6) 或者251中较小的值)字节,Read Blob Request可以用来读取剩余的字节

 

 

 

 

 

 

 

 

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值