diff options
Diffstat (limited to 'gemini.go')
-rw-r--r-- | gemini.go | 82 |
1 files changed, 82 insertions, 0 deletions
diff --git a/gemini.go b/gemini.go new file mode 100644 index 0000000..8594de4 --- /dev/null +++ b/gemini.go @@ -0,0 +1,82 @@ +package main + +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(request string, port int) (*GeminiConn, error) { + if !strings.HasPrefix(request, "gemini://") { + request = "gemini://" + request + } + + u, err := url.Parse(request) + if err != nil { + return nil, err + } + + conf := tls.Config{ + InsecureSkipVerify: true, + } + + if strings.Contains(u.Host, ":") { + return &GeminiConn{u.Host, &conf}, nil + } else { + return &GeminiConn{u.Host + ":" + strconv.Itoa(port), &conf}, 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 +} |