gofer

package
v0.0.0-...-e888e98 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Dec 28, 2023 License: MIT Imports: 28 Imported by: 0

Documentation

Index

Constants

View Source
const (
	ServerCert = "server"
	ClientCert = "client"
)
View Source
const PacketTypeBigFileHeader = 4
View Source
const PacketTypeBigFileRequest = 5
View Source
const PacketTypeBigFileResponse = 6
View Source
const PacketTypeMessage uint16 = 2
View Source
const PacketTypeSimpleFile uint16 = 3

Variables

View Source
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

func DialAndRunClient(serverAddress string, client Client)

DialAndRunClient 连接服务器,完成 client 的 Do

func DialAndRunClientTLS

func DialAndRunClientTLS(serverAddress string, client Client)

DialAndRunClientTLS 作用和 DialAndRunClient 一样,不过使用更安全的 TLS 连接

func FileIDString

func FileIDString(fileID []byte) string

FileIDString returns Sprintf("%x", fileID)

func GenerateCert

func GenerateCert(hosts []string, isCA bool)

Generate a self-signed X.509 certificate for a TLS server. https://golang.org/src/crypto/tls/generate_cert.go

func GeneratePEM

func GeneratePEM(hosts []string) (pemCert []byte, pemKey []byte, pin []byte, err error)

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 GeneratePEMWithRoot() (pemCert []byte, pemKey []byte, rootCertPEM []byte)

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

func GetCert(certName string) (certPEM []byte, certKey []byte)

GetCert 读取指定文件名的,用 openssl 生成的证书文件。

certName 传入 ServerCert 或 ClientCert

see static/certs/generate_cert.sh

func ListenAndServe

func ListenAndServe(addr string, handler Server)

ListenAndServe listens on the TCP network address addr and then calls Serve with handler to handle requests on incoming connections.

func ListenAndServeTLS

func ListenAndServeTLS(addr string, handler Server)

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

func (*BigFileReceiver) Receive

func (r *BigFileReceiver) Receive(packet *Packet, conn net.Conn) chan bool

Receive 处理接收到的 BigFileHeader 和 BigFileResponse 分发给 handleBigFileHeader 和 handleBigFileResponse 方法处理

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

func (*BigFileReceiverWorker) Run

func (w *BigFileReceiverWorker) Run(conn net.Conn) chan string

Run 初始化 Worker,从 conn 请求下载所有文件片段。 全部下载完成后,做 merge,最后把 fileID 发到该函数返回的 chan,并回传 header 通知发送端结束工作,。

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 Client

type Client interface {
	Do(conn net.Conn) chan bool // Do 完成对服务端的请求, 结束后往返回的通道扔值
}

Client 是客户端接口

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 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 NewMessage(info string, content string) *Message

func PacketAsMessage

func PacketAsMessage(packet *Packet) *Message

PacketAsMessage convert packet to message Notice: a packet should be convert to message if and only if its Type==PacketTypeMessage

func (Message) GetContent

func (m Message) GetContent() string

func (Message) GetInfo

func (m Message) GetInfo() string

func (*Message) SetContent

func (m *Message) SetContent(content string)

func (*Message) SetInfo

func (m *Message) SetInfo(info string)

type MessageReceiver

type MessageReceiver struct{}

MessageReceiver 是接收一条消息并处理的东西

func NewMessageReceiver

func NewMessageReceiver() *MessageReceiver

func (MessageReceiver) Receive

func (m MessageReceiver) Receive(packet *Packet, conn net.Conn) chan bool

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

type Packet struct {
	Header
	Body
}

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 NewPacket

func NewPacket(typ uint16, info []byte, data []byte) *Packet

func PacketFromBytes

func PacketFromBytes(b []byte) (*Packet, error)

PacketFromBytes decodes []byte => Packet

func PacketFromReader

func PacketFromReader(reader io.Reader) (*Packet, error)

PacketFromReader 从 reader 中读取字节, 解码成 Packet

func (*Packet) ToBytes

func (p *Packet) ToBytes() []byte

ToBytes encodes Packet => []byte

func (*Packet) WriteTo

func (p *Packet) WriteTo(writer io.Writer) (written int, err error)

WriteTo 把 Packet 写到一个 writer 里

type PacketReceiver

type PacketReceiver interface {
	Receive(packet *Packet, conn net.Conn) chan bool // 收完了就往里面传值
}

PacketReceiver 处理接收到的 Packet

其实应该叫做 Handler,但为了呼应 Sender,就叫做 PacketReceiver 了。

type ReceiveClient

type ReceiveClient struct {
	*Receiver
}

ReceiveClient 是接收的客户端 接入某服务器, 接收对方发来的 Packet, 解析并处理接收到的 Packet。

func NewReceiveClient

func NewReceiveClient() *ReceiveClient

func (ReceiveClient) Do

func (r ReceiveClient) Do(conn net.Conn) chan bool

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

func (Receiver) ReceiveAndHandle

func (r Receiver) ReceiveAndHandle(conn net.Conn) chan bool

ReceiveAndHandle 接收并处理数据包

type SendClient

type SendClient struct {
	Sender
}

SendClient 是发送的客户端

func NewSendClient

func NewSendClient(s Sender) *SendClient

func (SendClient) Do

func (s SendClient) Do(conn net.Conn) chan bool

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 Sender

type Sender interface {
	Send(conn net.Conn)
}

Sender 是发送者接口

type Server

type Server interface {
	ServeConn(conn net.Conn)
}

Server 服务器接口

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

func (SimpleFileReceiver) Receive

func (s SimpleFileReceiver) Receive(packet *Packet, conn net.Conn) chan bool

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)

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL