func (_ IP) Apply(m ma.Multiaddr, side int, ctx match.Context) error { p := m.Protocols()[0] name := p.Name s, _ := m.ValueForProtocol(p.Code) mctx := ctx.Misc() ip := net.ParseIP(s) if ip == nil { return fmt.Errorf("incorrect ip %s", m) } switch name { case "ip4": if ip = ip.To4(); ip == nil { return fmt.Errorf("incorrect ip4 %s", m) } case "ip6": if ip = ip.To16(); ip == nil { return fmt.Errorf("incorrent ip6 %s", m) } } mctx.IPs = append(mctx.IPs, ip) return nil }
func (w WS) Apply(m ma.Multiaddr, side int, ctx match.Context) error { var path string // ws client matches /http/ws too, so /ws might not be the first protocol for _, p := range m.Protocols() { if p.Name == "ws" { pth, err := m.ValueForProtocol(p.Code) if err != nil { return err } path = pth break } } sctx := ctx.Special() mctx := ctx.Misc() switch side { case match.S_Client: // resolve url var url string if mctx.Host != "" { // this will make mctx.Host appear in http request headers, // cloud servers often require that url = fmt.Sprintf("ws://%s/%s", mctx.Host, path) } else { switch t := sctx.NetConn.(type) { case *net.TCPConn: url = fmt.Sprintf("ws://%s/%s", t.RemoteAddr().String(), path) default: url = fmt.Sprintf("ws://foo.bar/%s", path) } } wcon, err := w.Select(sctx.NetConn, url) if err != nil { return err } sctx.NetConn = wcon return nil case match.S_Server: if mctx.HTTPMux == nil { // help the user out if /http is missing before /ws HTTP{}.Apply(m, match.S_Server, ctx) } ln, err := w.Handle(mctx.HTTPMux, "/"+path) if err != nil { return err } sctx.NetListener = ln sctx.CloseFn = ConcatClose(ln.Close, sctx.CloseFn) return nil } return fmt.Errorf("incorrect side constant") }
func (t TCP) Apply(m ma.Multiaddr, side int, ctx match.Context) error { p := m.Protocols()[0] portstr, _ := m.ValueForProtocol(p.Code) port, err := strconv.Atoi(portstr) if err != nil { return err } mctx := ctx.Misc() sctx := ctx.Special() if len(mctx.IPs) == 0 { return fmt.Errorf("no ips in context") } switch side { case match.S_Client: var con net.Conn var err error if len(mctx.IPs) == 1 { con, err = t.Dial(mctx.IPs[0], port) } else { con, err = t.DialMany(mctx.IPs, port) } if err != nil { return err } sctx.NetConn = con sctx.CloseFn = con.Close return nil case match.S_Server: netln, err := t.Listen(mctx.IPs[0], port) if err != nil { return err } sctx.NetListener = netln sctx.CloseFn = netln.Close return nil } return fmt.Errorf("incorrect side constant") }
func (p HTTP) Apply(m ma.Multiaddr, side int, ctx match.Context) error { mctx := ctx.Misc() sctx := ctx.Special() mctx.HTTPMux = p.Server(sctx.NetListener) ctx.Reuse(&httpreuser{ctx.Special().PreAddr}) return nil }
func (_ DNS) Apply(m ma.Multiaddr, side int, ctx match.Context) error { p := m.Protocols()[0] host, _ := m.ValueForProtocol(p.Code) ips, err := net.LookupIP(host) if err != nil { return err } if len(ips) == 0 { return fmt.Errorf("failed to resolve domain") } mctx := ctx.Misc() mctx.Host = host mctx.IPs = ips return nil }
func (ctx context) CopyTo(target match.Context) { // shallow copy *target.Misc() = ctx.misc *target.Special() = ctx.special trg := target.Map() for k, val := range ctx.Map() { // If we want to allow pointers to structs in the map, we have to copy // one level deeper, i.e. instead of copying the pointer, reflect and // copy what it points to. rval := reflect.ValueOf(val) if rval.Kind() == reflect.Ptr { rv := reflect.New(rval.Type().Elem()) rv.Elem().Set(rval.Elem()) trg[k] = rv.Interface() } else { trg[k] = val } } }
func (rc *reusableContext) Apply(m ma.Multiaddr, side int, ctx match.Context) error { rc.Context.CopyTo(ctx) ctx.Special().CloseFn = rc.Close rc.usecount++ return nil }