# go-multistream

[![](https://img.shields.io/badge/made%20by-Protocol%20Labs-blue.svg?style=flat-square)](http://ipn.io)
[![](https://img.shields.io/badge/project-multiformats-blue.svg?style=flat-square)](https://github.com/multiformats/multiformats)
[![](https://img.shields.io/badge/freenode-%23ipfs-blue.svg?style=flat-square)](https://webchat.freenode.net/?channels=%23ipfs)
[![](https://img.shields.io/badge/readme%20style-standard-brightgreen.svg?style=flat-square)](https://github.com/RichardLitt/standard-readme)
[![GoDoc](https://godoc.org/github.com/multiformats/go-multistream?status.svg)](https://godoc.org/github.com/multiformats/go-multistream)
[![Travis CI](https://img.shields.io/travis/multiformats/go-multistream.svg?style=flat-square&branch=master)](https://travis-ci.org/multiformats/go-multistream)
[![codecov.io](https://img.shields.io/codecov/c/github/multiformats/go-multistream.svg?style=flat-square&branch=master)](https://codecov.io/github/multiformats/go-multistream?branch=master)

> an implementation of the multistream protocol in go

This package implements a simple stream router for the multistream-select protocol.
The protocol is defined [here](https://github.com/multiformats/multistream-select).

## Table of Contents


- [Install](#install)
- [Usage](#usage)
- [Maintainers](#maintainers)
- [Contribute](#contribute)
- [License](#license)

## Install

`go-multistream` is a standard Go module which can be installed with:

```sh
go get github.com/multiformats/go-multistream
```

## Usage

### Example

This example shows how to use a multistream muxer. A muxer uses user-added handlers to handle different "protocols". The first step when interacting with a connection handler by the muxer is to select the protocol (the example uses `SelectProtoOrFail`). This will then let the muxer use the right handler.


```go
package main

import (
	"fmt"
	"io"
	"io/ioutil"
	"net"

	ms "github.com/multiformats/go-multistream"
)

// This example creates a multistream muxer, adds handlers for the protocols
// "/cats" and "/dogs" and exposes it on a localhost:8765. It then opens connections
// to that port, selects the protocols and tests that the handlers are working.
func main() {
	mux := ms.NewMultistreamMuxer[string]()
	mux.AddHandler("/cats", func(proto string, rwc io.ReadWriteCloser) error {
		fmt.Fprintln(rwc, proto, ": HELLO I LIKE CATS")
		return rwc.Close()
	})
	mux.AddHandler("/dogs", func(proto string, rwc io.ReadWriteCloser) error {
		fmt.Fprintln(rwc, proto, ": HELLO I LIKE DOGS")
		return rwc.Close()
	})

	list, err := net.Listen("tcp", ":8765")
	if err != nil {
		panic(err)
	}

	go func() {
		for {
			con, err := list.Accept()
			if err != nil {
				panic(err)
			}

			go mux.Handle(con)
		}
	}()

	// The Muxer is ready, let's test it
	conn, err := net.Dial("tcp", ":8765")
	if err != nil {
		panic(err)
	}

	// Create a new multistream to talk to the muxer
	// which will negotiate that we want to talk with /cats
	mstream := ms.NewMSSelect(conn, "/cats")
	cats, err := ioutil.ReadAll(mstream)
	if err != nil {
		panic(err)
	}
	fmt.Printf("%s", cats)
	mstream.Close()

	// A different way of talking to the muxer
	// is to manually selecting the protocol ourselves
	conn, err = net.Dial("tcp", ":8765")
	if err != nil {
		panic(err)
	}
	defer conn.Close()
	err = ms.SelectProtoOrFail("/dogs", conn)
	if err != nil {
		panic(err)
	}
	dogs, err := ioutil.ReadAll(conn)
	if err != nil {
		panic(err)
	}
	fmt.Printf("%s", dogs)
	conn.Close()
}
```

## Contribute

Contributions welcome. Please check out [the issues](https://github.com/multiformats/go-multistream/issues).

Check out our [contributing document](https://github.com/multiformats/multiformats/blob/master/contributing.md) for more information on how we work, and about contributing in general. Please be aware that all interactions related to multiformats are subject to the IPFS [Code of Conduct](https://github.com/ipfs/community/blob/master/code-of-conduct.md).

Small note: If editing the README, please conform to the [standard-readme](https://github.com/RichardLitt/standard-readme) specification.

## License

[MIT](LICENSE) © 2016 Jeromy Johnson