Documentation ¶
Index ¶
- Constants
- Variables
- func CertTemplate() (*x509.Certificate, error)
- func CreateCert(template, parent *x509.Certificate, pub interface{}, parentPriv interface{}) (cert *x509.Certificate, certPEM []byte, err error)
- func DialAndRunClient(serverAddress string, client Client)
- func DialAndRunClientTLS(serverAddress string, client Client)
- func FileIDString(fileID []byte) string
- func GenerateCert(hosts []string, isCA bool)
- func GeneratePEM(hosts []string) (pemCert []byte, pemKey []byte, pin []byte, err error)
- func GeneratePEMWithRoot() (pemCert []byte, pemKey []byte, rootCertPEM []byte)
- func GenerateRootCert() (rootCert *x509.Certificate, rootCertPEM []byte, rootKeyPEM []byte, ...)
- func GenerateServCert(rootCert *x509.Certificate, rootKey interface{}) (servCert *x509.Certificate, servCertPEM []byte, servKeyPEM []byte, ...)
- func GetCert(certName string) (certPEM []byte, certKey []byte)
- func ListenAndServe(addr string, handler Server)
- func ListenAndServeTLS(addr string, handler Server)
- type BigFileHeader
- func (b *BigFileHeader) FileHash() []byte
- func (b *BigFileHeader) FileID() []byte
- func (b *BigFileHeader) FileName() string
- func (b *BigFileHeader) FileSize() uint64
- func (b *BigFileHeader) SetFileHash(fileHash []byte)
- func (b *BigFileHeader) SetFileID(fileID []byte)
- func (b *BigFileHeader) SetFileName(fileName string)
- func (b *BigFileHeader) SetFileSize(fileSize uint64)
- type BigFileReceiver
- type BigFileReceiverWorker
- type BigFileRequest
- type BigFileResponse
- type BigFileSender
- type Body
- type Client
- type Distributer
- type Header
- type Message
- type MessageReceiver
- type MessageSender
- type Packet
- type PacketReceiver
- type ReceiveClient
- type ReceiveServer
- type Receiver
- type SendClient
- type SendServer
- type Sender
- type Server
- type SimpleFile
- type SimpleFileReceiver
- type SimpleFileSender
Constants ¶
const ( ServerCert = "server" ClientCert = "client" )
const PacketTypeBigFileHeader = 4
const PacketTypeBigFileRequest = 5
const PacketTypeBigFileResponse = 6
const PacketTypeMessage uint16 = 2
const PacketTypeSimpleFile uint16 = 3
Variables ¶
var DefaultBlockSize uint64 = 1 * 1024 * 1024 // 1 MiB
Functions ¶
func CertTemplate ¶
func CertTemplate() (*x509.Certificate, error)
CertTemplate is a helper function to create a cert template with a serial number and other required fields https://ericchiang.github.io/post/go-tls/
func CreateCert ¶
func CreateCert(template, parent *x509.Certificate, pub interface{}, parentPriv interface{}) ( cert *x509.Certificate, certPEM []byte, err error)
CreateCert
func DialAndRunClient ¶
DialAndRunClient 连接服务器,完成 client 的 Do
func DialAndRunClientTLS ¶
DialAndRunClientTLS 作用和 DialAndRunClient 一样,不过使用更安全的 TLS 连接
func FileIDString ¶
FileIDString returns Sprintf("%x", fileID)
func GenerateCert ¶
Generate a self-signed X.509 certificate for a TLS server. https://golang.org/src/crypto/tls/generate_cert.go
func GeneratePEM ¶
GeneratePEM 生成 PEM 证书 返回 PEM 证书, PEM-Key 和 SKPI (PIN码, 公共证书的指纹) https://mojotv.cn/2018/12/26/how-to-create-self-signed-and-pinned-certificates-in-go
Bug:
x509: certificate relies on legacy Common Name field, use SANs or temporarily enable Common Name matching with GODEBUG=x509ignoreCN=0
func GeneratePEMWithRoot ¶
func GenerateRootCert ¶
func GenerateRootCert() ( rootCert *x509.Certificate, rootCertPEM []byte, rootKeyPEM []byte, rootKey *rsa.PrivateKey)
func GenerateServCert ¶
func GenerateServCert(rootCert *x509.Certificate, rootKey interface{}) ( servCert *x509.Certificate, servCertPEM []byte, servKeyPEM []byte, servKey *rsa.PrivateKey)
func GetCert ¶
GetCert 读取指定文件名的,用 openssl 生成的证书文件。
certName 传入 ServerCert 或 ClientCert
see static/certs/generate_cert.sh
func ListenAndServe ¶
ListenAndServe listens on the TCP network address addr and then calls Serve with handler to handle requests on incoming connections.
func ListenAndServeTLS ¶
ListenAndServeTLS 作用和 ListenAndServe 一样,不过使用更安全的 TLS 连接
Types ¶
type BigFileHeader ¶
type BigFileHeader struct { *Packet // contains filtered or unexported fields }
BigFileHeader 是大文件 sender 发给 Receiver 的文件信息说明。 包含传输过程需要的一些关键属性:
- fileID : 文件ID,用来在后面的传输过程中表识文件,具体的实现是文件的 md5 和
- fileName: 文件名
- fileSize: 文件大小, 单位是 Byte
- fileHash: 文件摘要,用来做最终校验,实现上其实就是 fileID
BigFileHeader is Packet that:
- Type: 4
- Info: fileID(fileHash)
- Data: fileSize (const 8 Byte), fileName
func NewBigFileHeader ¶
func NewBigFileHeader(fileID []byte, fileName string, fileSize uint64) *BigFileHeader
func PacketAsBigFileHeader ¶
func PacketAsBigFileHeader(packet *Packet) *BigFileHeader
PacketAsBigFileHeader convert packet to BigFileHeader Notice: only for packets whose Type==PacketTypeBigFileHeader
func (*BigFileHeader) FileHash ¶
func (b *BigFileHeader) FileHash() []byte
func (*BigFileHeader) FileID ¶
func (b *BigFileHeader) FileID() []byte
func (*BigFileHeader) FileName ¶
func (b *BigFileHeader) FileName() string
func (*BigFileHeader) FileSize ¶
func (b *BigFileHeader) FileSize() uint64
func (*BigFileHeader) SetFileHash ¶
func (b *BigFileHeader) SetFileHash(fileHash []byte)
func (*BigFileHeader) SetFileID ¶
func (b *BigFileHeader) SetFileID(fileID []byte)
func (*BigFileHeader) SetFileName ¶
func (b *BigFileHeader) SetFileName(fileName string)
func (*BigFileHeader) SetFileSize ¶
func (b *BigFileHeader) SetFileSize(fileSize uint64)
type BigFileReceiver ¶
type BigFileReceiver struct {
// contains filtered or unexported fields
}
BigFileSender 是收大文件用的东西: 实现了 PacketReceiver 接口
接收大文件这里设计成用 Master-Worker 模式: BigFileReceiver 是 Master, 只是指派、管理工作; 而具体的文件下载工作由 BigFileReceiverWorker 来做。
func NewBigFileReceiver ¶
func NewBigFileReceiver() *BigFileReceiver
type BigFileReceiverWorker ¶
type BigFileReceiverWorker struct {
// contains filtered or unexported fields
}
BigFileReceiverWorker 负责接收一个大文件。
一个 Worker 只专注处理一个大文件。 BigFileReceiver 通过把 BigFileHeader 指派给 Worker,让 Worker 自行处理一个大文件的下载工作。
Worker 会在 $PWD 新建一个以 ".{fileID}" 为名的目录(称为 saveDir), 每次请求下载 blockSize 大小的文件片段, 保存到 saveDir, 文件名为 "{blockIndex}.block", 把 savedBlock 中对应的块位置标记为 1。
重复下载过程,直到 savedBlock 全为 1,然后合并文件,计算 md5 和,检查是否正确。 正确则 mv mergedFile $PWD/{fileName}, 不正确就丢弃。
断点续传: Worker 并不是直接新建 saveDir。如果 saveDir 存在,则打开, 从里面读取已保存的文件片段,更新 savedBlock,然后再开始下载缺失部分。
func NewBigFileReceiverWorker ¶
func NewBigFileReceiverWorker(header *BigFileHeader) *BigFileReceiverWorker
func (BigFileReceiverWorker) BlockTmpFilePath ¶
func (w BigFileReceiverWorker) BlockTmpFilePath(block uint64) string
BlockTmpFilePath 获取一个文件的一个块的临时文件路径。 returns "{fileIDString}/{block}.block"
func (*BigFileReceiverWorker) Receive ¶
func (w *BigFileReceiverWorker) Receive(response *BigFileResponse)
Receive 接收一个该 Worker 负责的文件的 BigFileResponse
type BigFileRequest ¶
type BigFileRequest struct { *Packet // contains filtered or unexported fields }
BigFileRequest 是大文件的 Receiver 发给 sender 的文件段请求。
Receiver 通过发送 BigFileRequest 给 sender 来请求某一段文件。 所以说, BigFileRequest 中包括请求文件的 fileID 以及文件段的起始 位置 start (字节数) 和请求下载长度 length (字节数)。
BigFileRequest is Packet that:
- Type: 5
- Info: fileID
- Data: start(const 8 Byte), length(const 8 Byte)
func NewBigFileRequest ¶
func NewBigFileRequest(fileID []byte, start uint64, length uint64) *BigFileRequest
func PacketAsBigFileRequest ¶
func PacketAsBigFileRequest(packet *Packet) *BigFileRequest
PacketAsBigFileRequest convert packet to BigFileRequest Notice: only for packets whose Type==PacketTypeBigFileRequest
func (*BigFileRequest) FileID ¶
func (b *BigFileRequest) FileID() []byte
func (*BigFileRequest) Length ¶
func (b *BigFileRequest) Length() uint64
func (*BigFileRequest) SetFileID ¶
func (b *BigFileRequest) SetFileID(fileID []byte)
func (*BigFileRequest) SetLength ¶
func (b *BigFileRequest) SetLength(length uint64)
func (*BigFileRequest) SetStart ¶
func (b *BigFileRequest) SetStart(start uint64)
func (*BigFileRequest) Start ¶
func (b *BigFileRequest) Start() uint64
type BigFileResponse ¶
type BigFileResponse struct { *Packet // contains filtered or unexported fields }
BigFileResponse 是大文件的 sender 发给 Receiver 的文件段
- fileID: 文件 ID
- start: 起始位置
- fileContent: 文件段的内容
BigFileResponse is Packet that:
- Type: 6
- Info: start(const 8 Byte), fileID
- Data: fileContent
func NewBigFileResponse ¶
func NewBigFileResponse(fileID []byte, start uint64, fileContent []byte) *BigFileResponse
func PacketAsBigFileResponse ¶
func PacketAsBigFileResponse(packet *Packet) *BigFileResponse
PacketAsBigFileResponse convert packet to BigFileResponse Notice: only for packets whose Type==PacketTypeBigFileResponse
func (*BigFileResponse) FileContent ¶
func (b *BigFileResponse) FileContent() []byte
func (*BigFileResponse) FileID ¶
func (b *BigFileResponse) FileID() []byte
func (*BigFileResponse) SetFileContent ¶
func (b *BigFileResponse) SetFileContent(fileContent []byte)
func (*BigFileResponse) SetFileID ¶
func (b *BigFileResponse) SetFileID(fileID []byte)
func (*BigFileResponse) SetStart ¶
func (b *BigFileResponse) SetStart(start uint64)
func (*BigFileResponse) Start ¶
func (b *BigFileResponse) Start() uint64
type BigFileSender ¶
type BigFileSender struct {
// contains filtered or unexported fields
}
BigFileSender 是发大文件用的东西 实现 Sender 接口
和 Message、SimpleFile 那种不同, BigFileSender 其实是一个"服务"了, 它监听 conn, 从里面读请求(BigFileRequest),写响应(BigFileResponse)
func NewBigFileSender ¶
func NewBigFileSender() *BigFileSender
func (*BigFileSender) AppendFile ¶
func (s *BigFileSender) AppendFile(filePath string)
func (BigFileSender) Send ¶
func (s BigFileSender) Send(conn net.Conn)
Send 向 conn 发送一次头(sendHeader),然后调用 sendResponse 监听 conn, 从里面读请求(BigFileRequest),写响应(BigFileResponse); 如果长时间没有请求则重新使用 sendHeader 发送 Header
type Body ¶
type Body struct { // Info: 数据的描述, 数据长度由指定 InfoSize 指定 Info []byte // Data: 数据, 长度由指定 DataSize 指定 Data []byte }
Body 是 Packet 中长度不确定的数据区域:
- Info �是数据的特定信息, 例如 Type 为文件时, Info 可能就是文件名
- Data 即主体数据, 例如消息内容、文件内容...
type Distributer ¶
type Distributer struct {
// contains filtered or unexported fields
}
Distributer 是一个 PacketReceiver
所有 Receiver 接收到的 packet 都会交给这个东西,由这个东西分发给其他 PacketReceiver 具体处理 其他所有的 PacketReceiver 都应该在这里注册。
func DistributerInstance ¶
func DistributerInstance() *Distributer
DistributerInstance 获取 Distributer 单例
func (*Distributer) Receive ¶
func (d *Distributer) Receive(packet *Packet, conn net.Conn) chan bool
Receive 完成 Distributer 的分发工作
func (*Distributer) Register ¶
func (d *Distributer) Register(packetType uint16, packetReceiver PacketReceiver)
Register 注册一个 PacketReceiver
type Header ¶
type Header struct { // Type: 数据类型, 固定 2 Byte Type uint16 // InfoSize: 描述信息的大小, 固定 4 Byte InfoSize uint32 // DataSize: 数据的大小, 固定 4 Byte DataSize uint32 }
Header 是 Packet 中固定长度 (20 Byte) 的描述区域:
- Type 描述数据的类型, 例如 2 表示消息, 3 表示文件
- InfoSize 和 DataSize, 描述 Info 和 Data 的长度 (in Bytes)
type Message ¶
type Message struct { *Packet // contains filtered or unexported fields }
Message 表示一条即时通讯的消息
Message is Packet that:
- Type: 2
- Info: string, message `info`
- Data: string, message `content`
func NewMessage ¶
func PacketAsMessage ¶
PacketAsMessage convert packet to message Notice: a packet should be convert to message if and only if its Type==PacketTypeMessage
func (Message) GetContent ¶
func (*Message) SetContent ¶
type MessageReceiver ¶
type MessageReceiver struct{}
MessageReceiver 是接收一条消息并处理的东西
func NewMessageReceiver ¶
func NewMessageReceiver() *MessageReceiver
type MessageSender ¶
type MessageSender struct {
// contains filtered or unexported fields
}
MessageSender 是用来发一条消息的东西
func NewMessageSender ¶
func NewMessageSender(msgInfo string, msgContent string) *MessageSender
func (MessageSender) Send ¶
func (m MessageSender) Send(conn net.Conn)
type Packet ¶
Packet 是数据传输的一个"数据包"。
相当于一个自定义的协议:
| | Header | Body | | ---- | ---- - -------- - -------- - --------- | -------- - -------- | | PART | Type | InfoSize | DataSize | RESERVED* | Info | Data | | ---- | ---- | -------- | -------- | --------- | -------- | -------- | | SIZE | 2B | 4B | 4B | 2B | InfoSize | DataSize | * RESERVED: 保留字段, 暂时没用. 只是让 Header 对齐到 8/2 的整数倍。
Packet 主要由两部分数据组成: Header 和 Body:
Header 是固定长度的描述区域:
- Type 描述数据的类型, 例如 2 表示消息, 3 表示文件
- InfoSize 和 DataSize, 描述 Info 和 Data 的长度 (in Bytes)
Body 是长度不确定的数据区域:
- Info �是数据的特定信息, 例如 Type 为文件时, Info 可能就是文件名
- Data 即主体数据, 例如消息内容、文件内容...
func PacketFromBytes ¶
PacketFromBytes decodes []byte => Packet
func PacketFromReader ¶
PacketFromReader 从 reader 中读取字节, 解码成 Packet
type PacketReceiver ¶
PacketReceiver 处理接收到的 Packet
其实应该叫做 Handler,但为了呼应 Sender,就叫做 PacketReceiver 了。
type ReceiveClient ¶
type ReceiveClient struct {
*Receiver
}
ReceiveClient 是接收的客户端 接入某服务器, 接收对方发来的 Packet, 解析并处理接收到的 Packet。
func NewReceiveClient ¶
func NewReceiveClient() *ReceiveClient
type ReceiveServer ¶
type ReceiveServer struct {
*Receiver
}
ReceiveServer 接收服务
监听指定地址, 等待客户端连接接入, 接收对方发来的 Packet, 解析并处理接收到的 Packet。
func NewReceiveServer ¶
func NewReceiveServer() *ReceiveServer
func (ReceiveServer) ServeConn ¶
func (r ReceiveServer) ServeConn(conn net.Conn)
ServeConn 监听指定地址, 等待客户端连接接入, 接收对方发来的 Packet, 交给 HandlePacket 处理
type Receiver ¶
type Receiver struct {
Distributer *Distributer
}
Receiver 负责从 conn 接收 packet, 然后分发给各种 PacketReceiver 处理
⚠️ 注意:
Receiver 不是 PacketReceiver。Receiver 位于更底层,是和网络连接的 conn、 网络中的数据流打交道的,而 PacketReceiver 只和抽象封装的 Packet 对象打交道。
func NewReceiver ¶
func NewReceiver() *Receiver
type SendClient ¶
type SendClient struct {
Sender
}
SendClient 是发送的客户端
func NewSendClient ¶
func NewSendClient(s Sender) *SendClient
type SendServer ¶
type SendServer struct {
Sender
}
SendServer 发送服务
监听指定地址, 有客户端连接接入, 就给对方发送 PacketToSend
func NewSendServer ¶
func NewSendServer(s Sender) *SendServer
func (SendServer) ServeConn ¶
func (s SendServer) ServeConn(conn net.Conn)
ServeConn 监听指定地址, 有客户端连接接入, 就给对方发送 PacketToSend
type SimpleFile ¶
type SimpleFile struct { *Packet // contains filtered or unexported fields }
SimpleFile 是简单的文件。
SimpleFile is Packet that:
- Type: 3
- Info: string, `fileName`
- Data: string, `fileContent`
SimpleFile 在构建的过程中会把整个文件读取到 Packet.Data 中,因而只试用于很小的文件。
func NewSimpleFile ¶
func NewSimpleFile(filePath string) *SimpleFile
func PacketAsSimpleFile ¶
func PacketAsSimpleFile(packet *Packet) *SimpleFile
PacketAsSimpleFile convert packet to SimpleFile Notice: a packet should be convert to SimpleFile if and only if its Type==PacketTypeSimpleFile
func (SimpleFile) FileContent ¶
func (s SimpleFile) FileContent() []byte
func (SimpleFile) FileName ¶
func (s SimpleFile) FileName() string
func (*SimpleFile) SetFileContent ¶
func (s *SimpleFile) SetFileContent(fileContent []byte)
func (*SimpleFile) SetFileName ¶
func (s *SimpleFile) SetFileName(fileName string)
func (SimpleFile) WriteFileContent ¶
func (s SimpleFile) WriteFileContent(writer io.Writer) (written int, err error)
WriteFileContent 把 FileContent 写入到 writer 里
type SimpleFileReceiver ¶
type SimpleFileReceiver struct{}
SimpleFileSender 负责处理一个接收到的 SimpleFile 类型的 Packet
func NewSimpleFileReceiver ¶
func NewSimpleFileReceiver() *SimpleFileReceiver
type SimpleFileSender ¶
type SimpleFileSender struct {
// contains filtered or unexported fields
}
SimpleFileSender 负责发一个文件
func NewSimpleFileSender ¶
func NewSimpleFileSender(filePath string) *SimpleFileSender
func (SimpleFileSender) Send ¶
func (s SimpleFileSender) Send(conn net.Conn)