spdy: github.com/amahi/spdy Index | Files

package spdy

import "github.com/amahi/spdy"

Amahi SPDY is a library built from scratch in the "Go way" for building SPDY clients and servers in the Go programming language.

It supports a subset of SPDY 3.1 http://www.chromium.org/spdy/spdy-protocol/spdy-protocol-draft3-1

Check the source code, examples and overview at https://github.com/amahi/spdy

This library is used in a streaming server/proxy implementation for Amahi, the [home and media server](https://www.amahi.org).

Goals

The goals are reliability, streaming and performance/scalability.

1) Design for reliability means that network connections are assumed to disconnect at any time, especially when it's most inapropriate for the library to handle. This also includes potential issues with bugs in within the library, so the library tries to handle all crazy errors in the most reasonable way. A client or a server built with this library should be able to run for months and months of reliable operation. It's not there yet, but it will be.

2) Streaming requests, unlike typical HTTP requests (which are short), require working with an arbitrary large number of open requests (streams) simultaneously, and most of them are flow-constrained at the client endpoint. Streaming clients kind of misbehave too, for example, they open and close many streams rapidly with Range request to check certain parts of the file. This is common with endpoint clients like VLC or Quicktime (Safari on iOS or Mac OS X). We wrote this library with the goal of making it not just suitable for HTTP serving, but also for streaming.

3) The library was built with performance and scalability in mind, so things have been done using as little blocking and copying of data as possible. It was meant to be implemented in the "go way", using concurrency extensively and channel communication. The library uses mutexes very sparingly so that handling of errors at all manner of inapropriate times becomes easier. It goes to great lengths to not block, establishing timeouts when network and even channel communication may fail. The library should use very very little CPU, even in the presence of many streams and sessions running simultaneously.

Index

Package Files

client_conn.go debug.go doc.go frame.go header.go misc.go proxy.go server_conn.go session.go stream.go types.go

Constants

const (
    FRAME_SYN_STREAM    = 0x0001
    FRAME_SYN_REPLY     = 0x0002
    FRAME_RST_STREAM    = 0x0003
    FRAME_SETTINGS      = 0x0004
    FRAME_PING          = 0x0006
    FRAME_GOAWAY        = 0x0007
    FRAME_HEADERS       = 0x0008
    FRAME_WINDOW_UPDATE = 0x0009
)
const (
    FLAG_NONE = frameFlags(0x00)
    FLAG_FIN  = frameFlags(0x01)
)
const (
    HEADER_STATUS         string = ":status"
    HEADER_VERSION        string = ":version"
    HEADER_PATH           string = ":path"
    HEADER_METHOD         string = ":method"
    HEADER_HOST           string = ":host"
    HEADER_SCHEME         string = ":scheme"
    HEADER_CONTENT_LENGTH string = "Content-Length"
)
const INITIAL_FLOW_CONTOL_WINDOW int32 = 64 * 1024
const MAX_DATA_PAYLOAD = 1<<24 - 1

maximum number of bytes in a frame

const NORTHBOUND_SLOTS = 5

func EnableDebug Uses

func EnableDebug()

EnableDebug turns on the output of debugging messages to Stdout

func ListenAndServe Uses

func ListenAndServe(addr string, handler http.Handler) (err error)

ListenAndServe listens on the TCP network address addr and then calls Serve with handler to handle requests on incoming connections. Handler is typically nil, in which case the DefaultServeMux is used. This creates a spdy only server without TLS

A trivial example server is:

	package main

	import (
		"io"
		"net/http"
             "github.com/amahi/spdy"
		"log"
	)

	// hello world, the web server
	func HelloServer(w http.ResponseWriter, req *http.Request) {
		io.WriteString(w, "hello, world!\n")
	}

	func main() {
		http.HandleFunc("/hello", HelloServer)
		err := spdy.ListenAndServe(":12345", nil)
		if err != nil {
			log.Fatal("ListenAndServe: ", err)
		}
	}

func ListenAndServeTLS Uses

func ListenAndServeTLS(addr string, certFile string, keyFile string, handler http.Handler) error

ListenAndServeTLS acts identically to ListenAndServe, except that it expects HTTPS connections. Servers created this way have NPN Negotiation and accept requests from both spdy and http clients. Additionally, files containing a certificate and matching private key for the server must be provided. If the certificate is signed by a certificate authority, the certFile should be the concatenation of the server's certificate followed by the CA's certificate.

A trivial example server is:

	import (
		"log"
		"net/http"
             "github.com/amahi/spdy"
	)

	func handler(w http.ResponseWriter, req *http.Request) {
		w.Header().Set("Content-Type", "text/plain")
		w.Write([]byte("This is an example server.\n"))
	}

	func main() {
		http.HandleFunc("/", handler)
		log.Printf("About to listen on 10443. Go to https://127.0.0.1:10443/")
		err := spdy.ListenAndServeTLS(":10443", "cert.pem", "key.pem", nil)
		if err != nil {
			log.Fatal(err)
		}
	}

One can use makecert.sh in /certs to generate certfile and keyfile

func ListenAndServeTLSSpdyOnly Uses

func ListenAndServeTLSSpdyOnly(addr string, certFile string, keyFile string, handler http.Handler) error

func PriorityFor Uses

func PriorityFor(req *url.URL) uint8

PriorityFor returns the recommended priority for the given URL for best opteration with the library.

func SetLog Uses

func SetLog(w io.Writer)

SetLog sets the output of logging to a given io.Writer

type Client Uses

type Client struct {
    // contains filtered or unexported fields
}

spdy client

func NewClient Uses

func NewClient(addr string) (*Client, error)

returns a client with tcp connection created using net.Dial

func NewClientConn Uses

func NewClientConn(c net.Conn) (*Client, error)

returns a client that reads and writes on c

func (*Client) Close Uses

func (c *Client) Close() error

func (*Client) Do Uses

func (c *Client) Do(req *http.Request) (*http.Response, error)

to get a response from the client

func (*Client) Ping Uses

func (c *Client) Ping(d time.Duration) (pinged bool, err error)

type ResponseRecorder Uses

type ResponseRecorder struct {
    Code      int           // the HTTP response code from WriteHeader
    HeaderMap http.Header   // the HTTP response headers
    Body      *bytes.Buffer // if non-nil, the bytes.Buffer to append written data to
    // contains filtered or unexported fields
}

ResponseRecorder is an implementation of http.ResponseWriter that is used to get a response.

func NewRecorder Uses

func NewRecorder() *ResponseRecorder

NewRecorder returns an initialized ResponseRecorder.

func (*ResponseRecorder) Header Uses

func (rw *ResponseRecorder) Header() http.Header

Header returns the response headers.

func (*ResponseRecorder) Write Uses

func (rw *ResponseRecorder) Write(buf []byte) (int, error)

Write always succeeds and writes to rw.Body.

func (*ResponseRecorder) WriteHeader Uses

func (rw *ResponseRecorder) WriteHeader(code int)

WriteHeader sets rw.Code.

type Server Uses

type Server struct {
    Handler   http.Handler
    Addr      string
    TLSConfig *tls.Config
    // contains filtered or unexported fields
}

spdy server

func (*Server) Close Uses

func (s *Server) Close() (err error)

close spdy server and return Any blocked Accept operations will be unblocked and return errors.

func (*Server) ListenAndServe Uses

func (s *Server) ListenAndServe() (err error)

ListenAndServe listens on the TCP network address s.Addr and then calls Serve to handle requests on incoming connections.

func (*Server) ListenAndServeTLSSpdyOnly Uses

func (srv *Server) ListenAndServeTLSSpdyOnly(certFile, keyFile string) error

ListenAndServeTLSSpdyOnly listens on the TCP network address srv.Addr and then calls Serve to handle requests on incoming TLS connections. This is a spdy-only server with TLS and no NPN.

Filenames containing a certificate and matching private key for the server must be provided. If the certificate is signed by a certificate authority, the certFile should be the concatenation of the server's certificate followed by the CA's certificate.

func (*Server) Serve Uses

func (s *Server) Serve(ln net.Listener) (err error)

Serve accepts incoming connections on the Listener l, creating a new service goroutine for each. The service goroutines read requests and then call srv.Handler to reply to them.

type Session Uses

type Session struct {
    // contains filtered or unexported fields
}

func NewClientSession Uses

func NewClientSession(conn net.Conn) *Session

NewClientSession creates a new Session that should be used as a client. the given http.Server will be used to serve requests arriving. The user should call Serve() once it's ready to start serving. New streams will be created as per the SPDY protocol.

func NewServerSession Uses

func NewServerSession(conn net.Conn, server *http.Server) *Session

NewServerSession creates a new Session with the given network connection. This Session should be used as a server, and the given http.Server will be used to serve requests arriving. The user should call Serve() once it's ready to start serving. New streams will be created as per the SPDY protocol.

func (*Session) Close Uses

func (s *Session) Close()

Close closes the Session and the underlaying network connection. It should be called when the Session is idle for best results.

func (*Session) NewClientStream Uses

func (s *Session) NewClientStream() *Stream

NewClientStream starts a new Stream (in the given Session), to be used as a client

func (*Session) NewStreamProxy Uses

func (s *Session) NewStreamProxy(r *http.Request, w http.ResponseWriter) (err error)

NewStreamProxy starts a new stream and proxies the given HTTP Request to it, writing the response to the given ResponseWriter. If there is an error, it will be returned, but the ResponseWriter will get a 404 Not Found.

func (*Session) Ping Uses

func (s *Session) Ping(d time.Duration) (pinged bool)

Ping issues a SPDY PING frame and returns true if it the other side returned the PING frame within the duration, else it returns false. NOTE only one outstanting ping works in the current implementation.

func (*Session) SendGoaway Uses

func (s *Session) SendGoaway(f frameFlags, dat []byte)

func (*Session) Serve Uses

func (s *Session) Serve() (err error)

Serve starts serving a Session. This implementation of Serve only returns when there has been an error condition.

type Stream Uses

type Stream struct {
    // contains filtered or unexported fields
}

func (*Stream) Header Uses

func (s *Stream) Header() http.Header

Header makes streams compatible with the net/http handlers interface

func (*Stream) Request Uses

func (s *Stream) Request(request *http.Request, writer http.ResponseWriter) (err error)

Request makes an http request down the client that gets a client Stream started and returning the request in the ResponseWriter

func (*Stream) String Uses

func (s *Stream) String() string

String returns the Stream ID of the Stream

func (*Stream) Write Uses

func (s *Stream) Write(p []byte) (n int, err error)

Write makes streams compatible with the net/http handlers interface

func (*Stream) WriteHeader Uses

func (s *Stream) WriteHeader(code int)

WriteHeader makes streams compatible with the net/http handlers interface

Package spdy imports 20 packages (graph). Updated 2018-03-13. Refresh now. Tools for package owners.