Appearance
发现服务
说明:主要对发现服务进行一些基础操作,例如节点注册、中继查询、地址上报、地址解析等。
一个典型的终端流程为: 收集地址->地址上报->等待套接字里面的请求
请求地址
开发调试环境(pre)
HTTP协议 http://sls1-scd.star-lock.cn:8080
节点注册
- 调用方法
http
POST {{urlPrefix}}/SL-A-1.0/peer/register
Content-Type: application/json- 参数说明
| 名称 | 类型 | 是否必需 | 示例 | 描述 |
|---|---|---|---|---|
| product | string | Y | "XHJ-LOCK-711" | 产品名称 |
| model | string | Y | "711-ble-plus" | 产品的型号和规格字符串 |
| name | string | Y | "幸福小区2楼家门锁" | 对最终用户显示的名称,不可为空 |
| unique | string | Y | "TMH-1576dd48c9f8" | MAC地址/唯一名称/SN序列化,用于对设备进行唯一定位 |
name字段不可为空,其他字段均为自定义,长度不超过255字节即可,无任何格式要求,也没有唯一性限制,仅为管理后台中筛选和后续对接其他终端时调试使用。
对于智能设备字段建议定义:
product: 产品名称model: 产品的型号和规格字符串name: 对最终用户显示的名称unique: MAC地址/唯一名称/SN序列化均可,用于对设备进行唯一定位
对于APP字段建议定义:
product: APP名称model: 平台+型号,例如 iPhone15 Plusname: 设备的名称字符串,例如 王晓明的iPhone,如果取不到,可以是其他任何能区分这个iPhone和其他iPhone的字符串unique: MAC地址/唯一名称/SN序列化均可,用于对设备进行唯一定位
- 返回说明
| 名称 | 类型 | 描述 |
|---|---|---|
| msg | string | 响应消息 |
| peer | object | 对等节点信息对象 |
| peer.id | string | 对等节点ID,使用RSA公钥的sha256->base58形成 |
| peer.publicKey | string | RSA公钥的HEX格式,约580长度的字符串 |
| peer.privateKey | string | RSA私钥的HEX格式,约2300长度的字符串 |
终端需要将peer字段保存到持久储存,一般只需要在设备第一次通电(或者APP启动)时注册一次。
- 返回示例
json
{
"msg": "success",
"peer": {
"id": "8dBGekdM7dJ6fcrDVcQYap95S68w5HNrS86ge3jjdJsJ",
"publicKey": "约580长度的字符串,hex格式",
"privateKey": "约2300长度的字符串,hex格式"
}
}中继查询
查询可用中继等信息用于后续步骤。
- 调用方法
http
GET {{urlPrefix}}/SL-A-1.0/relay/query- 返回说明
| 名称 | 类型 | 描述 |
|---|---|---|
| msg | string | 响应消息 |
| time | int | 时间戳 |
| stun_server | string | STUN服务器地址 |
| client_addr | string | 客户端地址 |
| relay_list | array|null | 中继列表,如果没有可用中继则为null |
| relay_list[].peerID | string | 中继节点ID |
| relay_list[].name | string | 中继节点名称 |
| relay_list[].listenAddr | string | 监听地址 |
| relay_list[].peerMax | int | 最大负载连接数 |
| relay_list[].peerCurrent | int | 当前负载连接数 |
| relay_list[].health | int | 健康状态 |
| relay_list[].latency | int | 延迟(毫秒) |
- 返回示例
json
{
"msg": "success",
"time": 1730286096,
"stun_server": "stun.syncthing.net:3478",
"client_addr": "127.0.0.1",
"relay_list": [
{
"peerID": "BBGny2DUmDmtMN1gi8zXT4P5qkZ6E2Sy7yzvqbNQJRqX",
"name": "scrd1",
"listenAddr": "udp://10.1.52.155:8083",
"peerMax": 100,
"peerCurrent": 0,
"health": 0,
"latency": 200
}
]
}注意:如果没有可用中继,则relay_list字段为null
地址上报
在进行了上一步的操作后,我们已经准备好了一些信息,现在将这些信息都上报到发现服务中。
请求签名算法
签名参数的计算方法:
cpp
signData = binary.LittleEndian.PutUint32(time.CurrentTimestamp())
sign = hex.EncodeToString(rsa.SignPKCS1v15(RsaPrivateKey, sha256.Sum256(signData)))这段伪代码的目的是生成一个基于当前时间戳的签名。以下是对每一行代码的解释:
- signData = binary.LittleEndian.PutUint32(time.CurrentTimestamp())
- 这里获取了当前时间的时间戳(time.CurrentTimestamp())。
- 然后将这个时间戳(通常是一个整数)以小端字节序的形式编码为二进制数据。binary.LittleEndian.PutUint32 将这个32位的时间戳转换成一个固定长度的字节数组。
- signData 变量最终包含了这个以小端方式编码的二进制时间戳。
- sign = hex.EncodeToString(rsa.SignPKCS1v15(RsaPrivateKey, sha256.Sum256(signData)))
- 首先,对 signData 进行 SHA-256 哈希运算,得到一个哈希值。sha256.Sum256(signData) 会返回一个哈希值的数组。
- 使用 RSA 的 SignPKCS1v15 函数和给定的 RsaPrivateKey 对这个哈希值进行签名。这是基于 PKCS #1 v1.5 的 RSA 签名算法。
- 签名结果是一个二进制数据,然后用 hex.EncodeToString 将这个二进制数据编码成一个十六进制的字符串格式。
- 最终,sign 变量中保存的是这个签名的十六进制字符串。
总结 整个流程的作用是:
- 将当前时间戳转换为一个小端编码的二进制数据。
- 对这个时间戳生成的二进制数据进行 SHA-256 哈希计算。
- 使用 RSA 私钥对哈希值进行签名。
- 将签名结果编码为十六进制字符串格式。
- 调用方法
http
POST {{urlPrefix}}/SL-A-1.0/peer/login
Content-Type: application/json- 参数说明
| 名称 | 类型 | 是否必需 | 示例 | 描述 |
|---|---|---|---|---|
| id | string | Y | "8dBGekdM7dJ6fcrDVcQYap95S68w5HNrS86ge3jjdJsJ" | 对等节点ID |
| public_key | string | Y | "约580长度的字符串,hex格式" | RSA公钥的HEX格式 |
| listen_addr | array | Y | 见示例 | 监听地址列表,按照syncthing的地址格式,搜集所有可用于建立连接的地址 |
| listen_addr[].type | string | Y | "local" | 地址类型:local(本地地址)、externally(外网地址)、relay(中继地址) |
| listen_addr[].address | string | Y | "tcp://192.168.1.2:1888" | 地址字符串,格式为协议://地址:端口 |
| relay_service | object | N | 见示例 | 如果本节点实现了中继服务,在这个对象中公布自己 |
| relay_service.name | string | N | "公益-aliyun-1" | 中继节点名称,自定义 |
| relay_service.listen_addr | string | N | "tcp://aliyun-1.com:8000" | 监听的地址 |
| relay_service.peers_max | int | N | 1000 | 最大负载连接数 |
| relay_service.peers_current | int | N | 0 | 当前负载连接数 |
| time | int | Y | 1730286096 | 当前时间戳 |
| sign | string | Y | "签名的十六进制字符串" | 基于时间戳的RSA签名 |
listen_addr字段说明:
按照syncthing的地址格式,搜集所有可用于建立连接的地址 收集地址部分包括:
- 监听端口并收集所有网卡地址(4&6)
- [可选]UPNP得到自己的上层路由地址
- 在中继查询接口获得自己的外网地址端口(注意:在HTTP接口无法得到此字段,因为不是使用的同一个socket,所以http接口只会反馈IP,外网地址还是需要使用STUN服务获取)
- 中继上线得到中继地址 最终形成一个由若干个地址组成的地址列表,将列表和自己的唯一ID进行地址上报。
收集地址示意图:
diagram
PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHhtbG5zOnhsaW5rPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hsaW5rIiB2ZXJzaW9uPSIxLjEiIHdpZHRoPSI0NjJweCIgaGVpZ2h0PSI1NTJweCIgdmlld0JveD0iLTAuNSAtMC41IDQ2MiA1NTIiIGNvbnRlbnQ9IiZsdDtteGZpbGUgaG9zdD0mcXVvdDtlbWJlZC5kaWFncmFtcy5uZXQmcXVvdDsgYWdlbnQ9JnF1b3Q7TW96aWxsYS81LjAgKFdpbmRvd3MgTlQgMTAuMDsgV2luNjQ7IHg2NCkgQXBwbGVXZWJLaXQvNTM3LjM2IChLSFRNTCwgbGlrZSBHZWNrbykgQ2hyb21lLzEzMS4wLjAuMCBTYWZhcmkvNTM3LjM2IEVkZy8xMzEuMC4wLjAmcXVvdDsgdmVyc2lvbj0mcXVvdDsyNC44LjYmcXVvdDsmZ3Q7Jmx0O2RpYWdyYW0gaWQ9JnF1b3Q7X0pEalRqTmxGWTh3QkxCY2ttM0cmcXVvdDsgbmFtZT0mcXVvdDvnrKwgMSDpobUmcXVvdDsmZ3Q7MVZyYmJ1TTJFUDBhdmhyV2hibzhTcGF5VzZBdGlxYUxkcDhLcnNYWTJzcW1RZE8yM0svdlVLS3NDNW1zbTdVdExZSWc1SEJFaTRkelpnN3BJR2V4S1Q5d3Nsdi93akphSUh1ZWxjaEprRzFiMXR5RFA5SnlyaTJCNWRlR0ZjOHo1ZFFhbnZOL3FUTE9sZldRWjNUZmN4U01GU0xmOVkxTHR0M1NwZWpaQ09mczFIZDdZVVgvVTNka1JUWEQ4NUlVdXZYUFBCTnJ0UXJiYiswZmFiNWFONTlzZVdFOXNpR05zMXJKZmsweWR1cVluQlE1Qzg2WXFGdWJja0VMQ1Y2RFMvM2MweXVqbHhmamRDdXVlY0N0SHppUzRxRFdwdDVMbkp2RjBneldycnFNaXpWYnNTMHAwdFlhYzNiWVpsVE9PSWRlNi9Nell6c3dXbUQ4U29VNHE0MGtCOEhBdEJhYlFvM3FiNjBXc21jSHZsVHZvZDVNRUw2aXlzdXBUZklOTzQrcGxYNmdiRU1GUDRNRHB3VVIrYkcvZTBRRndlcmkxK0lFRFFXVkdUWmJoeTNGS0Y2Z1lDNGJrWStDV0FOeUx6ajc1eEl3ZGg4Q0NJU2Q5TnVVSzhtWjJVdkJUc3MxNFdLMmh4V0x2NlhQYVowTCtyd2pGU0luY0hzTHVpUGxncFp2d3RLTWVpb1l6NFArcVkxdGE2NXM2MDVjTjM3Zmc2UTFqUWdFOVBqNUwvVjgxZmtzT3pQY2RKT3lPNWljVmUrcXlMVkNQWFN0MFdMWENpWkxjU05RL21na24wOGlOSzlDempFQUY0NEZuR1BJamg0S24xQ0VVUnFnQ0JwZ2NWRU1EVXNPQlpZMERyRTFwYnR1eHRUUzZTMXlJZTduUXR1VUMrMTc1VUpMdytDUnFjL3Fwejc3SnJuUG4xRFY5ZzE4OWdwNHF6akxqOUJjaVdwVnRla0xIMXBnK3E0ZjFQbmdDWVVRd0ZEdFV4VFBxeUFIQ1pCVVExRVYyeGlGSVlyMGpQdE9MWkFSUWI2UVBiMmZHSENIWXNBM0VBRGZpUUNodGtIUGYzejZWU2RGVVlEU2Z3MkVEcEJrdjZ2bC8wdGVTb3JjQWlESEdtUUlBMEN1QVIvM0ZnbENyMGkvQTBuT0UwUElIaURrUGhBaFUrMkJTZ05WSjVGRWpXTXB6bXNMVUZSYUlsbUhESGxBQ3ZvVWhYN0Y1cURpdHo0UmxveVBLOUVmSmxMOW0zT0ZQajJ2OSsxSzcwTUcreFpKRk95bnNpeG44Q3VST01PeVg1bGlBclhVR2RSUzE1Uks3bFpMc1RtWDZFTGt1cTJIQnB6ckZ0WFdKMVhXSDI0OUxRWGxVSGlMZDI3cnJQcUJ2bVU3THY2UjluWCt5SDMxeHRCSVYwa2Q0K2tGanlWMkxJUGFxUVdLak9KTDhJWlNmQ3ZKa3FMQXU1SU8ra1R2em9RRlc1TGlPeWxqMjNZcjVyNnAzTjZlRmVFNDN4MDloSlAvUC9FRTJYblJLOTlpWjNBRGRvNTllZFBlMTN6dUhWbHVmSG5UK0kzQWFsMGlLMWFHTlU5akVEU2ZrdCtxVzBoY2NkYVR4SllGRDB2cEV2cVRpTkxoT2R0NTVEbTdPWUZPc0laY3ZzN29STnQ0RjJCNnJQem9iRGJoYTN1akFkendwcy9tUVNGdFR5dGVkYTJBSjhsZ2pCL0pZTU8zQmdiZzZzVG9WMXJmTWwzRGpIcE9kc01CZ29aS2ZhOXpzcTBmajZyd0N0U0ZWaGlod1AwcG1SWmcyQmtSTU04QW1DOHJhaEFxZ1F3SFJLbUxzUkxJSUtxamRKSlU5ZTVJVmVpMjMxNVhZNTMvQVhEUy93QT0mbHQ7L2RpYWdyYW0mZ3Q7Jmx0Oy9teGZpbGUmZ3Q7Ij48ZGVmcy8+PGc+PGcgZGF0YS1jZWxsLWlkPSIwIj48ZyBkYXRhLWNlbGwtaWQ9IjEiPjxnIGRhdGEtY2VsbC1pZD0iNCI+PGc+PHBhdGggZD0iTSA2MSA2MSBMIDYxIDk0LjYzIiBmaWxsPSJub25lIiBzdHJva2U9InJnYigwLCAwLCAwKSIgc3Ryb2tlLW1pdGVybGltaXQ9IjEwIiBwb2ludGVyLWV2ZW50cz0ic3Ryb2tlIi8+PHBhdGggZD0iTSA2MSA5OS44OCBMIDU3LjUgOTIuODggTCA2MSA5NC42MyBMIDY0LjUgOTIuODggWiIgZmlsbD0icmdiKDAsIDAsIDApIiBzdHJva2U9InJnYigwLCAwLCAwKSIgc3Ryb2tlLW1pdGVybGltaXQ9IjEwIiBwb2ludGVyLWV2ZW50cz0iYWxsIi8+PC9nPjwvZz48ZyBkYXRhLWNlbGwtaWQ9IjIiPjxnPjxlbGxpcHNlIGN4PSI2MSIgY3k9IjMxIiByeD0iNTAiIHJ5PSIzMCIgZmlsbD0icmdiKDI1NSwgMjU1LCAyNTUpIiBzdHJva2U9InJnYigwLCAwLCAwKSIgc3Ryb2tlLXdpZHRoPSIyIiBwb2ludGVyLWV2ZW50cz0iYWxsIi8+PC9nPjxnPjxnIHRyYW5zZm9ybT0idHJhbnNsYXRlKC0wLjUgLTAuNSkiPjxzd2l0Y2g+PGZvcmVpZ25PYmplY3QgcG9pbnRlci1ldmVudHM9Im5vbmUiIHdpZHRoPSIxMDAlIiBoZWlnaHQ9IjEwMCUiIHJlcXVpcmVkRmVhdHVyZXM9Imh0dHA6Ly93d3cudzMub3JnL1RSL1NWRzExL2ZlYXR1cmUjRXh0ZW5zaWJpbGl0eSIgc3R5bGU9Im92ZXJmbG93OiB2aXNpYmxlOyB0ZXh0LWFsaWduOiBsZWZ0OyI+PGRpdiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94aHRtbCIgc3R5bGU9ImRpc3BsYXk6IGZsZXg7IGFsaWduLWl0ZW1zOiB1bnNhZmUgY2VudGVyOyBqdXN0aWZ5LWNvbnRlbnQ6IHVuc2FmZSBjZW50ZXI7IHdpZHRoOiA5OHB4OyBoZWlnaHQ6IDFweDsgcGFkZGluZy10b3A6IDMxcHg7IG1hcmdpbi1sZWZ0OiAxMnB4OyI+PGRpdiBkYXRhLWRyYXdpby1jb2xvcnM9ImNvbG9yOiByZ2IoMCwgMCwgMCk7ICIgc3R5bGU9ImJveC1zaXppbmc6IGJvcmRlci1ib3g7IGZvbnQtc2l6ZTogMHB4OyB0ZXh0LWFsaWduOiBjZW50ZXI7Ij48ZGl2IHN0eWxlPSJkaXNwbGF5OiBpbmxpbmUtYmxvY2s7IGZvbnQtc2l6ZTogMTJweDsgZm9udC1mYW1pbHk6IEhlbHZldGljYTsgY29sb3I6IHJnYigwLCAwLCAwKTsgbGluZS1oZWlnaHQ6IDEuMjsgcG9pbnRlci1ldmVudHM6IGFsbDsgd2hpdGUtc3BhY2U6IG5vcm1hbDsgb3ZlcmZsb3ctd3JhcDogbm9ybWFsOyI+5byA5aeLPC9kaXY+PC9kaXY+PC9kaXY+PC9mb3JlaWduT2JqZWN0Pjx0ZXh0IHg9IjYxIiB5PSIzNSIgZmlsbD0icmdiKDAsIDAsIDApIiBmb250LWZhbWlseT0iJnF1b3Q7SGVsdmV0aWNhJnF1b3Q7IiBmb250LXNpemU9IjEycHgiIHRleHQtYW5jaG9yPSJtaWRkbGUiPuW8gOWnizwvdGV4dD48L3N3aXRjaD48L2c+PC9nPjwvZz48ZyBkYXRhLWNlbGwtaWQ9IjE0Ij48Zz48cGF0aCBkPSJNIDEyMSAyMzEgTCAxNjEgMjMxIEwgMTYxIDM0MSBMIDE5NC42MyAzNDEiIGZpbGw9Im5vbmUiIHN0cm9rZT0icmdiKDAsIDAsIDApIiBzdHJva2UtbWl0ZXJsaW1pdD0iMTAiIHBvaW50ZXItZXZlbnRzPSJzdHJva2UiLz48cGF0aCBkPSJNIDE5OS44OCAzNDEgTCAxOTIuODggMzQ0LjUgTCAxOTQuNjMgMzQxIEwgMTkyLjg4IDMzNy41IFoiIGZpbGw9InJnYigwLCAwLCAwKSIgc3Ryb2tlPSJyZ2IoMCwgMCwgMCkiIHN0cm9rZS1taXRlcmxpbWl0PSIxMCIgcG9pbnRlci1ldmVudHM9ImFsbCIvPjwvZz48L2c+PGcgZGF0YS1jZWxsLWlkPSIxOCI+PGc+PHBhdGggZD0iTSAxMjEgMjMxIEwgMTYxIDIzMSBMIDE2MSAxOTEgTCAxOTQuNjMgMTkxIiBmaWxsPSJub25lIiBzdHJva2U9InJnYigwLCAwLCAwKSIgc3Ryb2tlLW1pdGVybGltaXQ9IjEwIiBwb2ludGVyLWV2ZW50cz0ic3Ryb2tlIi8+PHBhdGggZD0iTSAxOTkuODggMTkxIEwgMTkyLjg4IDE5NC41IEwgMTk0LjYzIDE5MSBMIDE5Mi44OCAxODcuNSBaIiBmaWxsPSJyZ2IoMCwgMCwgMCkiIHN0cm9rZT0icmdiKDAsIDAsIDApIiBzdHJva2UtbWl0ZXJsaW1pdD0iMTAiIHBvaW50ZXItZXZlbnRzPSJhbGwiLz48L2c+PC9nPjxnIGRhdGEtY2VsbC1pZD0iMjAiPjxnPjxwYXRoIGQ9Ik0gNjEgMTYxIEwgNjEgMTk0LjYzIiBmaWxsPSJub25lIiBzdHJva2U9InJnYigwLCAwLCAwKSIgc3Ryb2tlLW1pdGVybGltaXQ9IjEwIiBwb2ludGVyLWV2ZW50cz0ic3Ryb2tlIi8+PHBhdGggZD0iTSA2MSAxOTkuODggTCA1Ny41IDE5Mi44OCBMIDYxIDE5NC42MyBMIDY0LjUgMTkyLjg4IFoiIGZpbGw9InJnYigwLCAwLCAwKSIgc3Ryb2tlPSJyZ2IoMCwgMCwgMCkiIHN0cm9rZS1taXRlcmxpbWl0PSIxMCIgcG9pbnRlci1ldmVudHM9ImFsbCIvPjwvZz48L2c+PGcgZGF0YS1jZWxsLWlkPSIzIj48Zz48cmVjdCB4PSIxIiB5PSIxMDEiIHdpZHRoPSIxMjAiIGhlaWdodD0iNjAiIGZpbGw9InJnYigyNTUsIDI1NSwgMjU1KSIgc3Ryb2tlPSJyZ2IoMCwgMCwgMCkiIHN0cm9rZS13aWR0aD0iMiIgcG9pbnRlci1ldmVudHM9ImFsbCIvPjwvZz48Zz48ZyB0cmFuc2Zvcm09InRyYW5zbGF0ZSgtMC41IC0wLjUpIj48c3dpdGNoPjxmb3JlaWduT2JqZWN0IHBvaW50ZXItZXZlbnRzPSJub25lIiB3aWR0aD0iMTAwJSIgaGVpZ2h0PSIxMDAlIiByZXF1aXJlZEZlYXR1cmVzPSJodHRwOi8vd3d3LnczLm9yZy9UUi9TVkcxMS9mZWF0dXJlI0V4dGVuc2liaWxpdHkiIHN0eWxlPSJvdmVyZmxvdzogdmlzaWJsZTsgdGV4dC1hbGlnbjogbGVmdDsiPjxkaXYgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGh0bWwiIHN0eWxlPSJkaXNwbGF5OiBmbGV4OyBhbGlnbi1pdGVtczogdW5zYWZlIGNlbnRlcjsganVzdGlmeS1jb250ZW50OiB1bnNhZmUgY2VudGVyOyB3aWR0aDogMTE4cHg7IGhlaWdodDogMXB4OyBwYWRkaW5nLXRvcDogMTMxcHg7IG1hcmdpbi1sZWZ0OiAycHg7Ij48ZGl2IGRhdGEtZHJhd2lvLWNvbG9ycz0iY29sb3I6IHJnYigwLCAwLCAwKTsgIiBzdHlsZT0iYm94LXNpemluZzogYm9yZGVyLWJveDsgZm9udC1zaXplOiAwcHg7IHRleHQtYWxpZ246IGNlbnRlcjsiPjxkaXYgc3R5bGU9ImRpc3BsYXk6IGlubGluZS1ibG9jazsgZm9udC1zaXplOiAxMnB4OyBmb250LWZhbWlseTogSGVsdmV0aWNhOyBjb2xvcjogcmdiKDAsIDAsIDApOyBsaW5lLWhlaWdodDogMS4yOyBwb2ludGVyLWV2ZW50czogYWxsOyB3aGl0ZS1zcGFjZTogbm9ybWFsOyBvdmVyZmxvdy13cmFwOiBub3JtYWw7Ij7mn6Xor6Lkv6Hmga88L2Rpdj48L2Rpdj48L2Rpdj48L2ZvcmVpZ25PYmplY3Q+PHRleHQgeD0iNjEiIHk9IjEzNSIgZmlsbD0icmdiKDAsIDAsIDApIiBmb250LWZhbWlseT0iJnF1b3Q7SGVsdmV0aWNhJnF1b3Q7IiBmb250LXNpemU9IjEycHgiIHRleHQtYW5jaG9yPSJtaWRkbGUiPuafpeivouS/oeaBrzwvdGV4dD48L3N3aXRjaD48L2c+PC9nPjwvZz48ZyBkYXRhLWNlbGwtaWQ9IjExIj48Zz48cGF0aCBkPSJNIDMxMSA0MSBMIDIxNiA0MSBMIDIxNiAxMTYgTCAxMjcuMzcgMTE2IiBmaWxsPSJub25lIiBzdHJva2U9InJnYigwLCAwLCAwKSIgc3Ryb2tlLW1pdGVybGltaXQ9IjEwIiBwb2ludGVyLWV2ZW50cz0ic3Ryb2tlIi8+PHBhdGggZD0iTSAxMjIuMTIgMTE2IEwgMTI5LjEyIDExMi41IEwgMTI3LjM3IDExNiBMIDEyOS4xMiAxMTkuNSBaIiBmaWxsPSJyZ2IoMCwgMCwgMCkiIHN0cm9rZT0icmdiKDAsIDAsIDApIiBzdHJva2UtbWl0ZXJsaW1pdD0iMTAiIHBvaW50ZXItZXZlbnRzPSJhbGwiLz48L2c+PC9nPjxnIGRhdGEtY2VsbC1pZD0iNyI+PGc+PHBhdGggZD0iTSAzMTEgNjEgTCAzMTEgMjEgQyAzMTEgMTUuNDggMzQ0LjU4IDExIDM4NiAxMSBDIDQyNy40MiAxMSA0NjEgMTUuNDggNDYxIDIxIEwgNDYxIDYxIEMgNDYxIDY2LjUyIDQyNy40MiA3MSAzODYgNzEgQyAzNDQuNTggNzEgMzExIDY2LjUyIDMxMSA2MSBaIiBmaWxsPSJyZ2IoMjU1LCAyNTUsIDI1NSkiIHN0cm9rZT0icmdiKDAsIDAsIDApIiBzdHJva2Utd2lkdGg9IjIiIHN0cm9rZS1taXRlcmxpbWl0PSIxMCIgcG9pbnRlci1ldmVudHM9ImFsbCIvPjxwYXRoIGQ9Ik0gMzExIDIxIEMgMzExIDI2LjUyIDM0NC41OCAzMSAzODYgMzEgQyA0MjcuNDIgMzEgNDYxIDI2LjUyIDQ2MSAyMSIgZmlsbD0ibm9uZSIgc3Ryb2tlPSJyZ2IoMCwgMCwgMCkiIHN0cm9rZS13aWR0aD0iMiIgc3Ryb2tlLW1pdGVybGltaXQ9IjEwIiBwb2ludGVyLWV2ZW50cz0iYWxsIi8+PC9nPjxnPjxnIHRyYW5zZm9ybT0idHJhbnNsYXRlKC0wLjUgLTAuNSkiPjxzd2l0Y2g+PGZvcmVpZ25PYmplY3QgcG9pbnRlci1ldmVudHM9Im5vbmUiIHdpZHRoPSIxMDAlIiBoZWlnaHQ9IjEwMCUiIHJlcXVpcmVkRmVhdHVyZXM9Imh0dHA6Ly93d3cudzMub3JnL1RSL1NWRzExL2ZlYXR1cmUjRXh0ZW5zaWJpbGl0eSIgc3R5bGU9Im92ZXJmbG93OiB2aXNpYmxlOyB0ZXh0LWFsaWduOiBsZWZ0OyI+PGRpdiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94aHRtbCIgc3R5bGU9ImRpc3BsYXk6IGZsZXg7IGFsaWduLWl0ZW1zOiB1bnNhZmUgY2VudGVyOyBqdXN0aWZ5LWNvbnRlbnQ6IHVuc2FmZSBjZW50ZXI7IHdpZHRoOiAxNDhweDsgaGVpZ2h0OiAxcHg7IHBhZGRpbmctdG9wOiA0MXB4OyBtYXJnaW4tbGVmdDogMzEycHg7Ij48ZGl2IGRhdGEtZHJhd2lvLWNvbG9ycz0iY29sb3I6IHJnYigwLCAwLCAwKTsgIiBzdHlsZT0iYm94LXNpemluZzogYm9yZGVyLWJveDsgZm9udC1zaXplOiAwcHg7IHRleHQtYWxpZ246IGNlbnRlcjsiPjxkaXYgc3R5bGU9ImRpc3BsYXk6IGlubGluZS1ibG9jazsgZm9udC1zaXplOiAxMnB4OyBmb250LWZhbWlseTogSGVsdmV0aWNhOyBjb2xvcjogcmdiKDAsIDAsIDApOyBsaW5lLWhlaWdodDogMS4yOyBwb2ludGVyLWV2ZW50czogYWxsOyB3aGl0ZS1zcGFjZTogbm9ybWFsOyBvdmVyZmxvdy13cmFwOiBub3JtYWw7Ij48ZGl2PjxiciAvPjwvZGl2PuWPkeeOsOacjeWKoeWZqDwvZGl2PjwvZGl2PjwvZGl2PjwvZm9yZWlnbk9iamVjdD48dGV4dCB4PSIzODYiIHk9IjQ1IiBmaWxsPSJyZ2IoMCwgMCwgMCkiIGZvbnQtZmFtaWx5PSImcXVvdDtIZWx2ZXRpY2EmcXVvdDsiIGZvbnQtc2l6ZT0iMTJweCIgdGV4dC1hbmNob3I9Im1pZGRsZSI+JiN4YTvlj5HnjrDmnI3liqHlmag8L3RleHQ+PC9zd2l0Y2g+PC9nPjwvZz48L2c+PGcgZGF0YS1jZWxsLWlkPSI5Ij48Zz48ZWxsaXBzZSBjeD0iMTgxIiBjeT0iMTMxIiByeD0iMjAiIHJ5PSIyMCIgZmlsbD0icmdiKDI1NSwgMjU1LCAyNTUpIiBzdHJva2U9InJnYigwLCAwLCAwKSIgcG9pbnRlci1ldmVudHM9ImFsbCIvPjwvZz48Zz48ZyB0cmFuc2Zvcm09InRyYW5zbGF0ZSgtMC41IC0wLjUpIj48c3dpdGNoPjxmb3JlaWduT2JqZWN0IHBvaW50ZXItZXZlbnRzPSJub25lIiB3aWR0aD0iMTAwJSIgaGVpZ2h0PSIxMDAlIiByZXF1aXJlZEZlYXR1cmVzPSJodHRwOi8vd3d3LnczLm9yZy9UUi9TVkcxMS9mZWF0dXJlI0V4dGVuc2liaWxpdHkiIHN0eWxlPSJvdmVyZmxvdzogdmlzaWJsZTsgdGV4dC1hbGlnbjogbGVmdDsiPjxkaXYgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGh0bWwiIHN0eWxlPSJkaXNwbGF5OiBmbGV4OyBhbGlnbi1pdGVtczogdW5zYWZlIGNlbnRlcjsganVzdGlmeS1jb250ZW50OiB1bnNhZmUgY2VudGVyOyB3aWR0aDogMzhweDsgaGVpZ2h0OiAxcHg7IHBhZGRpbmctdG9wOiAxMzFweDsgbWFyZ2luLWxlZnQ6IDE2MnB4OyI+PGRpdiBkYXRhLWRyYXdpby1jb2xvcnM9ImNvbG9yOiByZ2IoMCwgMCwgMCk7ICIgc3R5bGU9ImJveC1zaXppbmc6IGJvcmRlci1ib3g7IGZvbnQtc2l6ZTogMHB4OyB0ZXh0LWFsaWduOiBjZW50ZXI7Ij48ZGl2IHN0eWxlPSJkaXNwbGF5OiBpbmxpbmUtYmxvY2s7IGZvbnQtc2l6ZTogMTJweDsgZm9udC1mYW1pbHk6IEhlbHZldGljYTsgY29sb3I6IHJnYigwLCAwLCAwKTsgbGluZS1oZWlnaHQ6IDEuMjsgcG9pbnRlci1ldmVudHM6IGFsbDsgd2hpdGUtc3BhY2U6IG5vcm1hbDsgb3ZlcmZsb3ctd3JhcDogbm9ybWFsOyI+U1RVTjwvZGl2PjwvZGl2PjwvZGl2PjwvZm9yZWlnbk9iamVjdD48dGV4dCB4PSIxODEiIHk9IjEzNSIgZmlsbD0icmdiKDAsIDAsIDApIiBmb250LWZhbWlseT0iJnF1b3Q7SGVsdmV0aWNhJnF1b3Q7IiBmb250LXNpemU9IjEycHgiIHRleHQtYW5jaG9yPSJtaWRkbGUiPlNUVU48L3RleHQ+PC9zd2l0Y2g+PC9nPjwvZz48L2c+PGcgZGF0YS1jZWxsLWlkPSIxMCI+PGc+PGVsbGlwc2UgY3g9IjE5MSIgY3k9IjEwMSIgcng9IjIwIiByeT0iMjAiIGZpbGw9InJnYigyNTUsIDI1NSwgMjU1KSIgc3Ryb2tlPSJyZ2IoMCwgMCwgMCkiIHBvaW50ZXItZXZlbnRzPSJhbGwiLz48L2c+PGc+PGcgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoLTAuNSAtMC41KSI+PHN3aXRjaD48Zm9yZWlnbk9iamVjdCBwb2ludGVyLWV2ZW50cz0ibm9uZSIgd2lkdGg9IjEwMCUiIGhlaWdodD0iMTAwJSIgcmVxdWlyZWRGZWF0dXJlcz0iaHR0cDovL3d3dy53My5vcmcvVFIvU1ZHMTEvZmVhdHVyZSNFeHRlbnNpYmlsaXR5IiBzdHlsZT0ib3ZlcmZsb3c6IHZpc2libGU7IHRleHQtYWxpZ246IGxlZnQ7Ij48ZGl2IHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hodG1sIiBzdHlsZT0iZGlzcGxheTogZmxleDsgYWxpZ24taXRlbXM6IHVuc2FmZSBjZW50ZXI7IGp1c3RpZnktY29udGVudDogdW5zYWZlIGNlbnRlcjsgd2lkdGg6IDM4cHg7IGhlaWdodDogMXB4OyBwYWRkaW5nLXRvcDogMTAxcHg7IG1hcmdpbi1sZWZ0OiAxNzJweDsiPjxkaXYgZGF0YS1kcmF3aW8tY29sb3JzPSJjb2xvcjogcmdiKDAsIDAsIDApOyAiIHN0eWxlPSJib3gtc2l6aW5nOiBib3JkZXItYm94OyBmb250LXNpemU6IDBweDsgdGV4dC1hbGlnbjogY2VudGVyOyI+PGRpdiBzdHlsZT0iZGlzcGxheTogaW5saW5lLWJsb2NrOyBmb250LXNpemU6IDEycHg7IGZvbnQtZmFtaWx5OiBIZWx2ZXRpY2E7IGNvbG9yOiByZ2IoMCwgMCwgMCk7IGxpbmUtaGVpZ2h0OiAxLjI7IHBvaW50ZXItZXZlbnRzOiBhbGw7IHdoaXRlLXNwYWNlOiBub3JtYWw7IG92ZXJmbG93LXdyYXA6IG5vcm1hbDsiPlJlbGF5PC9kaXY+PC9kaXY+PC9kaXY+PC9mb3JlaWduT2JqZWN0Pjx0ZXh0IHg9IjE5MSIgeT0iMTA1IiBmaWxsPSJyZ2IoMCwgMCwgMCkiIGZvbnQtZmFtaWx5PSImcXVvdDtIZWx2ZXRpY2EmcXVvdDsiIGZvbnQtc2l6ZT0iMTJweCIgdGV4dC1hbmNob3I9Im1pZGRsZSI+UmVsYXk8L3RleHQ+PC9zd2l0Y2g+PC9nPjwvZz48L2c+PGcgZGF0YS1jZWxsLWlkPSIxMyI+PGc+PHJlY3QgeD0iMjAxIiB5PSIzMTEiIHdpZHRoPSIxMjAiIGhlaWdodD0iNjAiIGZpbGw9InJnYigyNTUsIDI1NSwgMjU1KSIgc3Ryb2tlPSJyZ2IoMCwgMCwgMCkiIHN0cm9rZS13aWR0aD0iMiIgcG9pbnRlci1ldmVudHM9ImFsbCIvPjwvZz48Zz48ZyB0cmFuc2Zvcm09InRyYW5zbGF0ZSgtMC41IC0wLjUpIj48c3dpdGNoPjxmb3JlaWduT2JqZWN0IHBvaW50ZXItZXZlbnRzPSJub25lIiB3aWR0aD0iMTAwJSIgaGVpZ2h0PSIxMDAlIiByZXF1aXJlZEZlYXR1cmVzPSJodHRwOi8vd3d3LnczLm9yZy9UUi9TVkcxMS9mZWF0dXJlI0V4dGVuc2liaWxpdHkiIHN0eWxlPSJvdmVyZmxvdzogdmlzaWJsZTsgdGV4dC1hbGlnbjogbGVmdDsiPjxkaXYgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGh0bWwiIHN0eWxlPSJkaXNwbGF5OiBmbGV4OyBhbGlnbi1pdGVtczogdW5zYWZlIGNlbnRlcjsganVzdGlmeS1jb250ZW50OiB1bnNhZmUgY2VudGVyOyB3aWR0aDogMTE4cHg7IGhlaWdodDogMXB4OyBwYWRkaW5nLXRvcDogMzQxcHg7IG1hcmdpbi1sZWZ0OiAyMDJweDsiPjxkaXYgZGF0YS1kcmF3aW8tY29sb3JzPSJjb2xvcjogcmdiKDAsIDAsIDApOyAiIHN0eWxlPSJib3gtc2l6aW5nOiBib3JkZXItYm94OyBmb250LXNpemU6IDBweDsgdGV4dC1hbGlnbjogY2VudGVyOyI+PGRpdiBzdHlsZT0iZGlzcGxheTogaW5saW5lLWJsb2NrOyBmb250LXNpemU6IDEycHg7IGZvbnQtZmFtaWx5OiBIZWx2ZXRpY2E7IGNvbG9yOiByZ2IoMCwgMCwgMCk7IGxpbmUtaGVpZ2h0OiAxLjI7IHBvaW50ZXItZXZlbnRzOiBhbGw7IHdoaXRlLXNwYWNlOiBub3JtYWw7IG92ZXJmbG93LXdyYXA6IG5vcm1hbDsiPuS4ree7p+S4iue6vzxkaXY+5b6X5Yiw5Lit57un5Zyw5Z2APC9kaXY+PGRpdj5yZWxheTwvZGl2PjxkaXY+dWRwOi8veHh4Lnh4eC9teWlkPC9kaXY+PC9kaXY+PC9kaXY+PC9kaXY+PC9mb3JlaWduT2JqZWN0Pjx0ZXh0IHg9IjI2MSIgeT0iMzQ1IiBmaWxsPSJyZ2IoMCwgMCwgMCkiIGZvbnQtZmFtaWx5PSImcXVvdDtIZWx2ZXRpY2EmcXVvdDsiIGZvbnQtc2l6ZT0iMTJweCIgdGV4dC1hbmNob3I9Im1pZGRsZSI+5Lit57un5LiK57q/5b6X5Yiw5Lit57un5Zyw5Z2AcmVsYXkuLi48L3RleHQ+PC9zd2l0Y2g+PC9nPjwvZz48L2c+PGcgZGF0YS1jZWxsLWlkPSIxNSI+PGc+PHJlY3QgeD0iMjAxIiB5PSIyNDEiIHdpZHRoPSIxMjAiIGhlaWdodD0iNjAiIGZpbGw9InJnYigyNTUsIDI1NSwgMjU1KSIgc3Ryb2tlPSJyZ2IoMCwgMCwgMCkiIHN0cm9rZS13aWR0aD0iMiIgcG9pbnRlci1ldmVudHM9ImFsbCIvPjwvZz48Zz48ZyB0cmFuc2Zvcm09InRyYW5zbGF0ZSgtMC41IC0wLjUpIj48c3dpdGNoPjxmb3JlaWduT2JqZWN0IHBvaW50ZXItZXZlbnRzPSJub25lIiB3aWR0aD0iMTAwJSIgaGVpZ2h0PSIxMDAlIiByZXF1aXJlZEZlYXR1cmVzPSJodHRwOi8vd3d3LnczLm9yZy9UUi9TVkcxMS9mZWF0dXJlI0V4dGVuc2liaWxpdHkiIHN0eWxlPSJvdmVyZmxvdzogdmlzaWJsZTsgdGV4dC1hbGlnbjogbGVmdDsiPjxkaXYgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGh0bWwiIHN0eWxlPSJkaXNwbGF5OiBmbGV4OyBhbGlnbi1pdGVtczogdW5zYWZlIGNlbnRlcjsganVzdGlmeS1jb250ZW50OiB1bnNhZmUgY2VudGVyOyB3aWR0aDogMTE4cHg7IGhlaWdodDogMXB4OyBwYWRkaW5nLXRvcDogMjcxcHg7IG1hcmdpbi1sZWZ0OiAyMDJweDsiPjxkaXYgZGF0YS1kcmF3aW8tY29sb3JzPSJjb2xvcjogcmdiKDAsIDAsIDApOyAiIHN0eWxlPSJib3gtc2l6aW5nOiBib3JkZXItYm94OyBmb250LXNpemU6IDBweDsgdGV4dC1hbGlnbjogY2VudGVyOyI+PGRpdiBzdHlsZT0iZGlzcGxheTogaW5saW5lLWJsb2NrOyBmb250LXNpemU6IDEycHg7IGZvbnQtZmFtaWx5OiBIZWx2ZXRpY2E7IGNvbG9yOiByZ2IoMCwgMCwgMCk7IGxpbmUtaGVpZ2h0OiAxLjI7IHBvaW50ZXItZXZlbnRzOiBhbGw7IHdoaXRlLXNwYWNlOiBub3JtYWw7IG92ZXJmbG93LXdyYXA6IG5vcm1hbDsiPlNUVU7mn6Xor6I8ZGl2PuW+l+WIsOWFrOe9keWcsOWdgGV4dGVybmFsbHk8L2Rpdj48ZGl2PnVkcDovL3gueC54Lng6MTIzNDU8L2Rpdj48L2Rpdj48L2Rpdj48L2Rpdj48L2ZvcmVpZ25PYmplY3Q+PHRleHQgeD0iMjYxIiB5PSIyNzUiIGZpbGw9InJnYigwLCAwLCAwKSIgZm9udC1mYW1pbHk9IiZxdW90O0hlbHZldGljYSZxdW90OyIgZm9udC1zaXplPSIxMnB4IiB0ZXh0LWFuY2hvcj0ibWlkZGxlIj5TVFVO5p+l6K+iLi4uPC90ZXh0Pjwvc3dpdGNoPjwvZz48L2c+PC9nPjxnIGRhdGEtY2VsbC1pZD0iMTYiPjxnPjxwYXRoIGQ9Ik0gMTIxIDIzMSBMIDE2MSAyMzEgTCAxNjEgMjcxIEwgMTk0LjYzIDI3MSIgZmlsbD0ibm9uZSIgc3Ryb2tlPSJyZ2IoMCwgMCwgMCkiIHN0cm9rZS1taXRlcmxpbWl0PSIxMCIgcG9pbnRlci1ldmVudHM9InN0cm9rZSIvPjxwYXRoIGQ9Ik0gMTk5Ljg4IDI3MSBMIDE5Mi44OCAyNzQuNSBMIDE5NC42MyAyNzEgTCAxOTIuODggMjY3LjUgWiIgZmlsbD0icmdiKDAsIDAsIDApIiBzdHJva2U9InJnYigwLCAwLCAwKSIgc3Ryb2tlLW1pdGVybGltaXQ9IjEwIiBwb2ludGVyLWV2ZW50cz0iYWxsIi8+PC9nPjwvZz48ZyBkYXRhLWNlbGwtaWQ9IjE3Ij48Zz48cmVjdCB4PSIyMDEiIHk9IjE1MSIgd2lkdGg9IjEyMCIgaGVpZ2h0PSI4MCIgZmlsbD0icmdiKDI1NSwgMjU1LCAyNTUpIiBzdHJva2U9InJnYigwLCAwLCAwKSIgc3Ryb2tlLXdpZHRoPSIyIiBwb2ludGVyLWV2ZW50cz0iYWxsIi8+PC9nPjxnPjxnIHRyYW5zZm9ybT0idHJhbnNsYXRlKC0wLjUgLTAuNSkiPjxzd2l0Y2g+PGZvcmVpZ25PYmplY3QgcG9pbnRlci1ldmVudHM9Im5vbmUiIHdpZHRoPSIxMDAlIiBoZWlnaHQ9IjEwMCUiIHJlcXVpcmVkRmVhdHVyZXM9Imh0dHA6Ly93d3cudzMub3JnL1RSL1NWRzExL2ZlYXR1cmUjRXh0ZW5zaWJpbGl0eSIgc3R5bGU9Im92ZXJmbG93OiB2aXNpYmxlOyB0ZXh0LWFsaWduOiBsZWZ0OyI+PGRpdiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94aHRtbCIgc3R5bGU9ImRpc3BsYXk6IGZsZXg7IGFsaWduLWl0ZW1zOiB1bnNhZmUgY2VudGVyOyBqdXN0aWZ5LWNvbnRlbnQ6IHVuc2FmZSBjZW50ZXI7IHdpZHRoOiAxMThweDsgaGVpZ2h0OiAxcHg7IHBhZGRpbmctdG9wOiAxOTFweDsgbWFyZ2luLWxlZnQ6IDIwMnB4OyI+PGRpdiBkYXRhLWRyYXdpby1jb2xvcnM9ImNvbG9yOiByZ2IoMCwgMCwgMCk7ICIgc3R5bGU9ImJveC1zaXppbmc6IGJvcmRlci1ib3g7IGZvbnQtc2l6ZTogMHB4OyB0ZXh0LWFsaWduOiBjZW50ZXI7Ij48ZGl2IHN0eWxlPSJkaXNwbGF5OiBpbmxpbmUtYmxvY2s7IGZvbnQtc2l6ZTogMTJweDsgZm9udC1mYW1pbHk6IEhlbHZldGljYTsgY29sb3I6IHJnYigwLCAwLCAwKTsgbGluZS1oZWlnaHQ6IDEuMjsgcG9pbnRlci1ldmVudHM6IGFsbDsgd2hpdGUtc3BhY2U6IG5vcm1hbDsgb3ZlcmZsb3ctd3JhcDogbm9ybWFsOyI+5pys5Zyw6YGN5Y6GPGRpdj7lvpfliLDmnKzlnLDlnLDlnYA8L2Rpdj48ZGl2PmxvY2FsPC9kaXY+PGRpdj51ZHA6Ly94LngueC54OjIyMjIyPGJyIC8+PC9kaXY+PGRpdj51ZHA6Ly9baXB2Nl06MjIyMjI8YnIgLz48L2Rpdj48L2Rpdj48L2Rpdj48L2Rpdj48L2ZvcmVpZ25PYmplY3Q+PHRleHQgeD0iMjYxIiB5PSIxOTUiIGZpbGw9InJnYigwLCAwLCAwKSIgZm9udC1mYW1pbHk9IiZxdW90O0hlbHZldGljYSZxdW90OyIgZm9udC1zaXplPSIxMnB4IiB0ZXh0LWFuY2hvcj0ibWlkZGxlIj7mnKzlnLDpgY3ljoblvpfliLDmnKzlnLDlnLDlnYBsb2NhbC4uLjwvdGV4dD48L3N3aXRjaD48L2c+PC9nPjwvZz48ZyBkYXRhLWNlbGwtaWQ9IjIyIj48Zz48cGF0aCBkPSJNIDYxIDI2MSBMIDYxIDM4NC42MyIgZmlsbD0ibm9uZSIgc3Ryb2tlPSJyZ2IoMCwgMCwgMCkiIHN0cm9rZS1taXRlcmxpbWl0PSIxMCIgcG9pbnRlci1ldmVudHM9InN0cm9rZSIvPjxwYXRoIGQ9Ik0gNjEgMzg5Ljg4IEwgNTcuNSAzODIuODggTCA2MSAzODQuNjMgTCA2NC41IDM4Mi44OCBaIiBmaWxsPSJyZ2IoMCwgMCwgMCkiIHN0cm9rZT0icmdiKDAsIDAsIDApIiBzdHJva2UtbWl0ZXJsaW1pdD0iMTAiIHBvaW50ZXItZXZlbnRzPSJhbGwiLz48L2c+PC9nPjxnIGRhdGEtY2VsbC1pZD0iMTkiPjxnPjxyZWN0IHg9IjEiIHk9IjIwMSIgd2lkdGg9IjEyMCIgaGVpZ2h0PSI2MCIgZmlsbD0icmdiKDI1NSwgMjU1LCAyNTUpIiBzdHJva2U9InJnYigwLCAwLCAwKSIgc3Ryb2tlLXdpZHRoPSIyIiBwb2ludGVyLWV2ZW50cz0iYWxsIi8+PC9nPjxnPjxnIHRyYW5zZm9ybT0idHJhbnNsYXRlKC0wLjUgLTAuNSkiPjxzd2l0Y2g+PGZvcmVpZ25PYmplY3QgcG9pbnRlci1ldmVudHM9Im5vbmUiIHdpZHRoPSIxMDAlIiBoZWlnaHQ9IjEwMCUiIHJlcXVpcmVkRmVhdHVyZXM9Imh0dHA6Ly93d3cudzMub3JnL1RSL1NWRzExL2ZlYXR1cmUjRXh0ZW5zaWJpbGl0eSIgc3R5bGU9Im92ZXJmbG93OiB2aXNpYmxlOyB0ZXh0LWFsaWduOiBsZWZ0OyI+PGRpdiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94aHRtbCIgc3R5bGU9ImRpc3BsYXk6IGZsZXg7IGFsaWduLWl0ZW1zOiB1bnNhZmUgY2VudGVyOyBqdXN0aWZ5LWNvbnRlbnQ6IHVuc2FmZSBjZW50ZXI7IHdpZHRoOiAxMThweDsgaGVpZ2h0OiAxcHg7IHBhZGRpbmctdG9wOiAyMzFweDsgbWFyZ2luLWxlZnQ6IDJweDsiPjxkaXYgZGF0YS1kcmF3aW8tY29sb3JzPSJjb2xvcjogcmdiKDAsIDAsIDApOyAiIHN0eWxlPSJib3gtc2l6aW5nOiBib3JkZXItYm94OyBmb250LXNpemU6IDBweDsgdGV4dC1hbGlnbjogY2VudGVyOyI+PGRpdiBzdHlsZT0iZGlzcGxheTogaW5saW5lLWJsb2NrOyBmb250LXNpemU6IDEycHg7IGZvbnQtZmFtaWx5OiBIZWx2ZXRpY2E7IGNvbG9yOiByZ2IoMCwgMCwgMCk7IGxpbmUtaGVpZ2h0OiAxLjI7IHBvaW50ZXItZXZlbnRzOiBhbGw7IHdoaXRlLXNwYWNlOiBub3JtYWw7IG92ZXJmbG93LXdyYXA6IG5vcm1hbDsiPuWIm+W7ulVEUOWll+aOpeWtlzwvZGl2PjwvZGl2PjwvZGl2PjwvZm9yZWlnbk9iamVjdD48dGV4dCB4PSI2MSIgeT0iMjM1IiBmaWxsPSJyZ2IoMCwgMCwgMCkiIGZvbnQtZmFtaWx5PSImcXVvdDtIZWx2ZXRpY2EmcXVvdDsiIGZvbnQtc2l6ZT0iMTJweCIgdGV4dC1hbmNob3I9Im1pZGRsZSI+5Yib5bu6VURQ5aWX5o6l5a2XPC90ZXh0Pjwvc3dpdGNoPjwvZz48L2c+PC9nPjxnIGRhdGEtY2VsbC1pZD0iMjMiPjxnPjxwYXRoIGQ9Ik0gMTIxIDQyMSBMIDM4NiA0MjEgTCAzODYgNzcuMzciIGZpbGw9Im5vbmUiIHN0cm9rZT0icmdiKDAsIDAsIDApIiBzdHJva2UtbWl0ZXJsaW1pdD0iMTAiIHBvaW50ZXItZXZlbnRzPSJzdHJva2UiLz48cGF0aCBkPSJNIDM4NiA3Mi4xMiBMIDM4OS41IDc5LjEyIEwgMzg2IDc3LjM3IEwgMzgyLjUgNzkuMTIgWiIgZmlsbD0icmdiKDAsIDAsIDApIiBzdHJva2U9InJnYigwLCAwLCAwKSIgc3Ryb2tlLW1pdGVybGltaXQ9IjEwIiBwb2ludGVyLWV2ZW50cz0iYWxsIi8+PC9nPjwvZz48ZyBkYXRhLWNlbGwtaWQ9IjI3Ij48Zz48cGF0aCBkPSJNIDYxIDQ1MSBMIDYxIDQ4NC42MyIgZmlsbD0ibm9uZSIgc3Ryb2tlPSJyZ2IoMCwgMCwgMCkiIHN0cm9rZS1taXRlcmxpbWl0PSIxMCIgcG9pbnRlci1ldmVudHM9InN0cm9rZSIvPjxwYXRoIGQ9Ik0gNjEgNDg5Ljg4IEwgNTcuNSA0ODIuODggTCA2MSA0ODQuNjMgTCA2NC41IDQ4Mi44OCBaIiBmaWxsPSJyZ2IoMCwgMCwgMCkiIHN0cm9rZT0icmdiKDAsIDAsIDApIiBzdHJva2UtbWl0ZXJsaW1pdD0iMTAiIHBvaW50ZXItZXZlbnRzPSJhbGwiLz48L2c+PC9nPjxnIGRhdGEtY2VsbC1pZD0iMjEiPjxnPjxyZWN0IHg9IjEiIHk9IjM5MSIgd2lkdGg9IjEyMCIgaGVpZ2h0PSI2MCIgZmlsbD0icmdiKDI1NSwgMjU1LCAyNTUpIiBzdHJva2U9InJnYigwLCAwLCAwKSIgc3Ryb2tlLXdpZHRoPSIyIiBwb2ludGVyLWV2ZW50cz0iYWxsIi8+PC9nPjxnPjxnIHRyYW5zZm9ybT0idHJhbnNsYXRlKC0wLjUgLTAuNSkiPjxzd2l0Y2g+PGZvcmVpZ25PYmplY3QgcG9pbnRlci1ldmVudHM9Im5vbmUiIHdpZHRoPSIxMDAlIiBoZWlnaHQ9IjEwMCUiIHJlcXVpcmVkRmVhdHVyZXM9Imh0dHA6Ly93d3cudzMub3JnL1RSL1NWRzExL2ZlYXR1cmUjRXh0ZW5zaWJpbGl0eSIgc3R5bGU9Im92ZXJmbG93OiB2aXNpYmxlOyB0ZXh0LWFsaWduOiBsZWZ0OyI+PGRpdiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94aHRtbCIgc3R5bGU9ImRpc3BsYXk6IGZsZXg7IGFsaWduLWl0ZW1zOiB1bnNhZmUgY2VudGVyOyBqdXN0aWZ5LWNvbnRlbnQ6IHVuc2FmZSBjZW50ZXI7IHdpZHRoOiAxMThweDsgaGVpZ2h0OiAxcHg7IHBhZGRpbmctdG9wOiA0MjFweDsgbWFyZ2luLWxlZnQ6IDJweDsiPjxkaXYgZGF0YS1kcmF3aW8tY29sb3JzPSJjb2xvcjogcmdiKDAsIDAsIDApOyAiIHN0eWxlPSJib3gtc2l6aW5nOiBib3JkZXItYm94OyBmb250LXNpemU6IDBweDsgdGV4dC1hbGlnbjogY2VudGVyOyI+PGRpdiBzdHlsZT0iZGlzcGxheTogaW5saW5lLWJsb2NrOyBmb250LXNpemU6IDEycHg7IGZvbnQtZmFtaWx5OiBIZWx2ZXRpY2E7IGNvbG9yOiByZ2IoMCwgMCwgMCk7IGxpbmUtaGVpZ2h0OiAxLjI7IHBvaW50ZXItZXZlbnRzOiBhbGw7IHdoaXRlLXNwYWNlOiBub3JtYWw7IG92ZXJmbG93LXdyYXA6IG5vcm1hbDsiPuWcsOWdgOS4iuaKpTwvZGl2PjwvZGl2PjwvZGl2PjwvZm9yZWlnbk9iamVjdD48dGV4dCB4PSI2MSIgeT0iNDI1IiBmaWxsPSJyZ2IoMCwgMCwgMCkiIGZvbnQtZmFtaWx5PSImcXVvdDtIZWx2ZXRpY2EmcXVvdDsiIGZvbnQtc2l6ZT0iMTJweCIgdGV4dC1hbmNob3I9Im1pZGRsZSI+5Zyw5Z2A5LiK5oqlPC90ZXh0Pjwvc3dpdGNoPjwvZz48L2c+PC9nPjxnIGRhdGEtY2VsbC1pZD0iMjQiPjxnPjxlbGxpcHNlIGN4PSIzNjEiIGN5PSIzNzEiIHJ4PSIyMCIgcnk9IjIwIiBmaWxsPSJyZ2IoMjU1LCAyNTUsIDI1NSkiIHN0cm9rZT0icmdiKDAsIDAsIDApIiBwb2ludGVyLWV2ZW50cz0iYWxsIi8+PC9nPjxnPjxnIHRyYW5zZm9ybT0idHJhbnNsYXRlKC0wLjUgLTAuNSkiPjxzd2l0Y2g+PGZvcmVpZ25PYmplY3QgcG9pbnRlci1ldmVudHM9Im5vbmUiIHdpZHRoPSIxMDAlIiBoZWlnaHQ9IjEwMCUiIHJlcXVpcmVkRmVhdHVyZXM9Imh0dHA6Ly93d3cudzMub3JnL1RSL1NWRzExL2ZlYXR1cmUjRXh0ZW5zaWJpbGl0eSIgc3R5bGU9Im92ZXJmbG93OiB2aXNpYmxlOyB0ZXh0LWFsaWduOiBsZWZ0OyI+PGRpdiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94aHRtbCIgc3R5bGU9ImRpc3BsYXk6IGZsZXg7IGFsaWduLWl0ZW1zOiB1bnNhZmUgY2VudGVyOyBqdXN0aWZ5LWNvbnRlbnQ6IHVuc2FmZSBjZW50ZXI7IHdpZHRoOiAzOHB4OyBoZWlnaHQ6IDFweDsgcGFkZGluZy10b3A6IDM3MXB4OyBtYXJnaW4tbGVmdDogMzQycHg7Ij48ZGl2IGRhdGEtZHJhd2lvLWNvbG9ycz0iY29sb3I6IHJnYigwLCAwLCAwKTsgIiBzdHlsZT0iYm94LXNpemluZzogYm9yZGVyLWJveDsgZm9udC1zaXplOiAwcHg7IHRleHQtYWxpZ246IGNlbnRlcjsiPjxkaXYgc3R5bGU9ImRpc3BsYXk6IGlubGluZS1ibG9jazsgZm9udC1zaXplOiAxMnB4OyBmb250LWZhbWlseTogSGVsdmV0aWNhOyBjb2xvcjogcmdiKDAsIDAsIDApOyBsaW5lLWhlaWdodDogMS4yOyBwb2ludGVyLWV2ZW50czogYWxsOyB3aGl0ZS1zcGFjZTogbm9ybWFsOyBvdmVyZmxvdy13cmFwOiBub3JtYWw7Ij7lnLDlnYDliJfooag8L2Rpdj48L2Rpdj48L2Rpdj48L2ZvcmVpZ25PYmplY3Q+PHRleHQgeD0iMzYxIiB5PSIzNzUiIGZpbGw9InJnYigwLCAwLCAwKSIgZm9udC1mYW1pbHk9IiZxdW90O0hlbHZldGljYSZxdW90OyIgZm9udC1zaXplPSIxMnB4IiB0ZXh0LWFuY2hvcj0ibWlkZGxlIj7lnLDlnYDliJfooag8L3RleHQ+PC9zd2l0Y2g+PC9nPjwvZz48L2c+PGcgZGF0YS1jZWxsLWlkPSIyNSI+PGc+PGVsbGlwc2UgY3g9IjQwMSIgY3k9IjM3MSIgcng9IjIwIiByeT0iMjAiIGZpbGw9InJnYigyNTUsIDI1NSwgMjU1KSIgc3Ryb2tlPSJyZ2IoMCwgMCwgMCkiIHBvaW50ZXItZXZlbnRzPSJhbGwiLz48L2c+PGc+PGcgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoLTAuNSAtMC41KSI+PHN3aXRjaD48Zm9yZWlnbk9iamVjdCBwb2ludGVyLWV2ZW50cz0ibm9uZSIgd2lkdGg9IjEwMCUiIGhlaWdodD0iMTAwJSIgcmVxdWlyZWRGZWF0dXJlcz0iaHR0cDovL3d3dy53My5vcmcvVFIvU1ZHMTEvZmVhdHVyZSNFeHRlbnNpYmlsaXR5IiBzdHlsZT0ib3ZlcmZsb3c6IHZpc2libGU7IHRleHQtYWxpZ246IGxlZnQ7Ij48ZGl2IHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hodG1sIiBzdHlsZT0iZGlzcGxheTogZmxleDsgYWxpZ24taXRlbXM6IHVuc2FmZSBjZW50ZXI7IGp1c3RpZnktY29udGVudDogdW5zYWZlIGNlbnRlcjsgd2lkdGg6IDM4cHg7IGhlaWdodDogMXB4OyBwYWRkaW5nLXRvcDogMzcxcHg7IG1hcmdpbi1sZWZ0OiAzODJweDsiPjxkaXYgZGF0YS1kcmF3aW8tY29sb3JzPSJjb2xvcjogcmdiKDAsIDAsIDApOyAiIHN0eWxlPSJib3gtc2l6aW5nOiBib3JkZXItYm94OyBmb250LXNpemU6IDBweDsgdGV4dC1hbGlnbjogY2VudGVyOyI+PGRpdiBzdHlsZT0iZGlzcGxheTogaW5saW5lLWJsb2NrOyBmb250LXNpemU6IDEycHg7IGZvbnQtZmFtaWx5OiBIZWx2ZXRpY2E7IGNvbG9yOiByZ2IoMCwgMCwgMCk7IGxpbmUtaGVpZ2h0OiAxLjI7IHBvaW50ZXItZXZlbnRzOiBhbGw7IHdoaXRlLXNwYWNlOiBub3JtYWw7IG92ZXJmbG93LXdyYXA6IG5vcm1hbDsiPuaIkeeahElEPC9kaXY+PC9kaXY+PC9kaXY+PC9mb3JlaWduT2JqZWN0Pjx0ZXh0IHg9IjQwMSIgeT0iMzc1IiBmaWxsPSJyZ2IoMCwgMCwgMCkiIGZvbnQtZmFtaWx5PSImcXVvdDtIZWx2ZXRpY2EmcXVvdDsiIGZvbnQtc2l6ZT0iMTJweCIgdGV4dC1hbmNob3I9Im1pZGRsZSI+5oiR55qESUQ8L3RleHQ+PC9zd2l0Y2g+PC9nPjwvZz48L2c+PGcgZGF0YS1jZWxsLWlkPSIyNiI+PGc+PHJlY3QgeD0iMSIgeT0iNDkxIiB3aWR0aD0iMTIwIiBoZWlnaHQ9IjYwIiBmaWxsPSJyZ2IoMjU1LCAyNTUsIDI1NSkiIHN0cm9rZT0icmdiKDAsIDAsIDApIiBzdHJva2Utd2lkdGg9IjIiIHBvaW50ZXItZXZlbnRzPSJhbGwiLz48L2c+PGc+PGcgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoLTAuNSAtMC41KSI+PHN3aXRjaD48Zm9yZWlnbk9iamVjdCBwb2ludGVyLWV2ZW50cz0ibm9uZSIgd2lkdGg9IjEwMCUiIGhlaWdodD0iMTAwJSIgcmVxdWlyZWRGZWF0dXJlcz0iaHR0cDovL3d3dy53My5vcmcvVFIvU1ZHMTEvZmVhdHVyZSNFeHRlbnNpYmlsaXR5IiBzdHlsZT0ib3ZlcmZsb3c6IHZpc2libGU7IHRleHQtYWxpZ246IGxlZnQ7Ij48ZGl2IHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hodG1sIiBzdHlsZT0iZGlzcGxheTogZmxleDsgYWxpZ24taXRlbXM6IHVuc2FmZSBjZW50ZXI7IGp1c3RpZnktY29udGVudDogdW5zYWZlIGNlbnRlcjsgd2lkdGg6IDExOHB4OyBoZWlnaHQ6IDFweDsgcGFkZGluZy10b3A6IDUyMXB4OyBtYXJnaW4tbGVmdDogMnB4OyI+PGRpdiBkYXRhLWRyYXdpby1jb2xvcnM9ImNvbG9yOiByZ2IoMCwgMCwgMCk7ICIgc3R5bGU9ImJveC1zaXppbmc6IGJvcmRlci1ib3g7IGZvbnQtc2l6ZTogMHB4OyB0ZXh0LWFsaWduOiBjZW50ZXI7Ij48ZGl2IHN0eWxlPSJkaXNwbGF5OiBpbmxpbmUtYmxvY2s7IGZvbnQtc2l6ZTogMTJweDsgZm9udC1mYW1pbHk6IEhlbHZldGljYTsgY29sb3I6IHJnYigwLCAwLCAwKTsgbGluZS1oZWlnaHQ6IDEuMjsgcG9pbnRlci1ldmVudHM6IGFsbDsgd2hpdGUtc3BhY2U6IG5vcm1hbDsgb3ZlcmZsb3ctd3JhcDogbm9ybWFsOyI+562J5b6F5pWw5o2uPC9kaXY+PC9kaXY+PC9kaXY+PC9mb3JlaWduT2JqZWN0Pjx0ZXh0IHg9IjYxIiB5PSI1MjUiIGZpbGw9InJnYigwLCAwLCAwKSIgZm9udC1mYW1pbHk9IiZxdW90O0hlbHZldGljYSZxdW90OyIgZm9udC1zaXplPSIxMnB4IiB0ZXh0LWFuY2hvcj0ibWlkZGxlIj7nrYnlvoXmlbDmja48L3RleHQ+PC9zd2l0Y2g+PC9nPjwvZz48L2c+PC9nPjwvZz48L2c+PHN3aXRjaD48ZyByZXF1aXJlZEZlYXR1cmVzPSJodHRwOi8vd3d3LnczLm9yZy9UUi9TVkcxMS9mZWF0dXJlI0V4dGVuc2liaWxpdHkiLz48YSB0cmFuc2Zvcm09InRyYW5zbGF0ZSgwLC01KSIgeGxpbms6aHJlZj0iaHR0cHM6Ly93d3cuZHJhd2lvLmNvbS9kb2MvZmFxL3N2Zy1leHBvcnQtdGV4dC1wcm9ibGVtcyIgdGFyZ2V0PSJfYmxhbmsiPjx0ZXh0IHRleHQtYW5jaG9yPSJtaWRkbGUiIGZvbnQtc2l6ZT0iMTBweCIgeD0iNTAlIiB5PSIxMDAlIj5UZXh0IGlzIG5vdCBTVkcgLSBjYW5ub3QgZGlzcGxheTwvdGV4dD48L2E+PC9zd2l0Y2g+PC9zdmc+relay_service字段说明:
如果本节点实现了中继服务,在这个对象中公布自己
name: 中继节点名称,自定义listen_addr: 监听的地址peers_max: 最大负载连接数peers_current: 当前负载连接数
- 请求示例
json
{
"id": "8dBGekdM7dJ6fcrDVcQYap95S68w5HNrS86ge3jjdJsJ",
"public_key": "约580长度的字符串,hex格式",
"listen_addr": [
{"type": "local", "address": "tcp://192.168.1.2:1888"},
{"type": "local", "address": "udp://[fd00:ec60:73ed:8049:8afe:7c71:fe7d:33ab]:1888"},
{"type": "externally", "address": "udp://110.110.110.110:32001"},
{"type": "relay", "address": "udp://baidu.com:8001"}
],
"relay_service": {
"name": "公益-aliyun-1",
"listen_addr": "tcp://aliyun-1.com:8000",
"peers_max": 1000,
"peers_current": 0
},
"time": 1730286096,
"sign": "签名的十六进制字符串"
}- 返回说明
| 名称 | 类型 | 描述 |
|---|---|---|
| msg | string | 响应消息 |
- 返回示例
json
{
"msg": "success"
}地址解析
在我们连接到另一终端时,需要进行此项解析,将对方的ID解析为可通过TCP/IP通信的地址二元组。
- 调用方法
http
GET {{urlPrefix}}/SL-A-1.0/peer/nslookup?id={{peerId}}- 参数说明
| 名称 | 类型 | 是否必需 | 示例 | 描述 |
|---|---|---|---|---|
| id | string | Y | "8dBGekdM7dJ6fcrDVcQYap95S68w5HNrS86ge3jjdJsJ" | 对等节点ID |
- 返回说明
| 名称 | 类型 | 描述 |
|---|---|---|
| TODO | - | TODO |
- 返回示例
json
TODO发现服务是可选的
当你通过其他方式,例如
nmb、mDNS、WS-Discovery、UDP广播等方法获取了对端连接信息,那么你不需要使用发现服务,这提供了无互联网的情况下进行局域网连接的能力。地址上报是可选的
当你只想联系他人,而无需被他人主动找到时,就无需上报地址,只需要解析地址即可
