diff options
Diffstat (limited to 'gemini/gemini.go')
-rw-r--r-- | gemini/gemini.go | 86 |
1 files changed, 86 insertions, 0 deletions
diff --git a/gemini/gemini.go b/gemini/gemini.go new file mode 100644 index 0000000..8f4c6ef --- /dev/null +++ b/gemini/gemini.go @@ -0,0 +1,86 @@ +package gemini + +import ( + "crypto/tls" + "fmt" + "net/url" + "os" + "strconv" + "strings" +) + +const GeminiNetwork = "tcp" +const GeminiPort = 1965 +const GeminiPrefix = "gemini://" + +func FormatRequest(request string) []byte { + if !strings.HasPrefix(request, GeminiPrefix) { + request = GeminiPrefix + request + } + request = request + "\r\n" + return []byte(request) +} + +type GeminiConn struct { + host string + config *tls.Config +} + +func NewGeminiConn(host string, port int) *GeminiConn { + conf := tls.Config{ + MinVersion: tls.VersionTLS12, + InsecureSkipVerify: true, + } + + if strings.Contains(host, ":") { + return &GeminiConn{host, &conf} + } else { + return &GeminiConn{host + ":" + strconv.Itoa(port), &conf} + } +} + +func NewGeminiConnFromRequest(request string, port int) (*GeminiConn, error) { + if !strings.HasPrefix(request, GeminiPrefix) { + request = GeminiPrefix + request + } + + u, err := url.Parse(request) + if err != nil { + return nil, err + } + return NewGeminiConn(u.Host, port), nil +} + +func (c *GeminiConn) Get(request []byte, out *os.File) error { + conn, err := tls.Dial(GeminiNetwork, c.host, c.config) + if err != nil { + return err + } + defer conn.Close() + + n, err := conn.Write(request) + if err != nil { + return err + } + + buf := make([]byte, 1024) + + for { + n, err = conn.Read(buf) + if err != nil { + return err + } + written, err := out.Write(buf[:n]) + if written != n { + return fmt.Errorf("Got %d bytes, but only wrote %d bytes", n, written) + } + if err != nil { + return err + } + + if n == 0 { + break + } + } + return nil +} |