mirror of
https://github.com/rancher/os.git
synced 2025-09-04 16:21:07 +00:00
Added tftp datasource for cloud config.
This commit is contained in:
committed by
niusmallnan
parent
8b75752225
commit
66c5f6130a
171
vendor/github.com/pin/tftp/README.md
generated
vendored
Normal file
171
vendor/github.com/pin/tftp/README.md
generated
vendored
Normal file
@@ -0,0 +1,171 @@
|
||||
TFTP server and client library for Golang
|
||||
=========================================
|
||||
|
||||
[](https://godoc.org/github.com/pin/tftp)
|
||||
[](https://travis-ci.org/pin/tftp)
|
||||
|
||||
Implements:
|
||||
* [RFC 1350](https://tools.ietf.org/html/rfc1350) - The TFTP Protocol (Revision 2)
|
||||
* [RFC 2347](https://tools.ietf.org/html/rfc2347) - TFTP Option Extension
|
||||
* [RFC 2348](https://tools.ietf.org/html/rfc2348) - TFTP Blocksize Option
|
||||
|
||||
Partially implements (tsize server side only):
|
||||
* [RFC 2349](https://tools.ietf.org/html/rfc2349) - TFTP Timeout Interval and Transfer Size Options
|
||||
|
||||
Set of features is sufficient for PXE boot support.
|
||||
|
||||
``` go
|
||||
import "github.com/pin/tftp"
|
||||
```
|
||||
|
||||
The package is cohesive to Golang `io`. Particularly it implements
|
||||
`io.ReaderFrom` and `io.WriterTo` interfaces. That allows efficient data
|
||||
transmission without unnecessary memory copying and allocations.
|
||||
|
||||
|
||||
TFTP Server
|
||||
-----------
|
||||
|
||||
```go
|
||||
|
||||
// readHandler is called when client starts file download from server
|
||||
func readHandler(filename string, rf io.ReaderFrom) error {
|
||||
file, err := os.Open(filename)
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, "%v\n", err)
|
||||
return err
|
||||
}
|
||||
n, err := rf.ReadFrom(file)
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, "%v\n", err)
|
||||
return err
|
||||
}
|
||||
fmt.Printf("%d bytes sent\n", n)
|
||||
return nil
|
||||
}
|
||||
|
||||
// writeHandler is called when client starts file upload to server
|
||||
func writeHandler(filename string, wt io.WriterTo) error {
|
||||
file, err := os.OpenFile(filename, os.O_WRONLY|os.O_CREATE|os.O_EXCL, 0644)
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, "%v\n", err)
|
||||
return err
|
||||
}
|
||||
n, err := wt.WriteTo(file)
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, "%v\n", err)
|
||||
return err
|
||||
}
|
||||
fmt.Printf("%d bytes received\n", n)
|
||||
return nil
|
||||
}
|
||||
|
||||
func main() {
|
||||
// use nil in place of handler to disable read or write operations
|
||||
s := tftp.NewServer(readHandler, writeHandler)
|
||||
s.SetTimeout(5 * time.Second) // optional
|
||||
err := s.ListenAndServe(":69") // blocks until s.Shutdown() is called
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stdout, "server: %v\n", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
TFTP Client
|
||||
-----------
|
||||
Upload file to server:
|
||||
|
||||
```go
|
||||
c, err := tftp.NewClient("172.16.4.21:69")
|
||||
file, err := os.Open(path)
|
||||
c.SetTimeout(5 * time.Second) // optional
|
||||
rf, err := c.Send("foobar.txt", "octet")
|
||||
n, err := rf.ReadFrom(file)
|
||||
fmt.Printf("%d bytes sent\n", n)
|
||||
```
|
||||
|
||||
Download file from server:
|
||||
|
||||
```go
|
||||
c, err := tftp.NewClient("172.16.4.21:69")
|
||||
wt, err := c.Receive("foobar.txt", "octet")
|
||||
file, err := os.Create(path)
|
||||
// Optionally obtain transfer size before actual data.
|
||||
if n, ok := wt.(IncomingTransfer).Size(); ok {
|
||||
fmt.Printf("Transfer size: %d\n", n)
|
||||
}
|
||||
n, err := wt.WriteTo(file)
|
||||
fmt.Printf("%d bytes received\n", n)
|
||||
```
|
||||
|
||||
Note: please handle errors better :)
|
||||
|
||||
TSize option
|
||||
------------
|
||||
|
||||
PXE boot ROM often expects tsize option support from a server: client
|
||||
(e.g. computer that boots over the network) wants to know size of a
|
||||
download before the actual data comes. Server has to obtain stream
|
||||
size and send it to a client.
|
||||
|
||||
Often it will happen automatically because TFTP library tries to check
|
||||
if `io.Reader` provided to `ReadFrom` method also satisfies
|
||||
`io.Seeker` interface (`os.File` for instance) and uses `Seek` to
|
||||
determine file size.
|
||||
|
||||
In case `io.Reader` you provide to `ReadFrom` in read handler does not
|
||||
satisfy `io.Seeker` interface or you do not want TFTP library to call
|
||||
`Seek` on your reader but still want to respond with tsize option
|
||||
during outgoing request you can use an `OutgoingTransfer` interface:
|
||||
|
||||
```go
|
||||
|
||||
func readHandler(filename string, rf io.ReaderFrom) error {
|
||||
...
|
||||
// Set transfer size before calling ReadFrom.
|
||||
rf.(tftp.OutgoingTransfer).SetSize(myFileSize)
|
||||
...
|
||||
// ReadFrom ...
|
||||
|
||||
```
|
||||
|
||||
Similarly, it is possible to obtain size of a file that is about to be
|
||||
received using `IncomingTransfer` interface (see `Size` method).
|
||||
|
||||
Remote Address
|
||||
--------------
|
||||
|
||||
The `OutgoingTransfer` and `IncomingTransfer` interfaces also provide the
|
||||
`RemoteAddr` method which returns the peer IP address and port as a
|
||||
`net.UDPAddr`. This can be used for detailed logging in a server handler.
|
||||
|
||||
```go
|
||||
|
||||
func readHandler(filename string, rf io.ReaderFrom) error {
|
||||
...
|
||||
raddr := rf.(tftp.OutgoingTransfer).RemoteAddr()
|
||||
log.Println("RRQ from", raddr.String())
|
||||
...
|
||||
// ReadFrom ...
|
||||
```
|
||||
|
||||
Backoff
|
||||
-------
|
||||
|
||||
The default backoff before retransmitting an unacknowledged packet is a
|
||||
random duration between 0 and 1 second. This behavior can be overridden
|
||||
in clients and servers by providing a custom backoff calculation function.
|
||||
|
||||
```go
|
||||
s := tftp.NewServer(readHandler, writeHandler)
|
||||
s.SetBackoff(func (attempts int) time.Duration {
|
||||
return time.Duration(attempts) * time.Second
|
||||
})
|
||||
```
|
||||
|
||||
or, for no backoff
|
||||
|
||||
```go
|
||||
s.SetBackoff(func (int) time.Duration { return 0 })
|
||||
```
|
Reference in New Issue
Block a user