<commit_before>// Copyright (c) 2016 Uber Technologies, Inc.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.

package tchannel

import (
	"net"
	"time"

	"github.com/yarpc/yarpc-go/transport"

	"github.com/uber/tchannel-go"
	"golang.org/x/net/context"
)

// Inbound represents a TChannel Inbound. It is the same as a transport
// Inbound except it exposes the address on which the system is listening for
// connections.
type Inbound interface {
	transport.Inbound

	// Address on which the server is listening. Returns nil if Start has not
	// been called yet.
	Addr() net.Addr
}

// InboundOption configures Inbound.
type InboundOption func(*inbound)

// ListenAddr changes the address on which the TChannel server will listen for
// connections. By default, the server listens on an OS-assigned port.
//
// This option has no effect if the Chanel provided to NewInbound is already
// listening for connections when Start() is called.
func ListenAddr(addr string) InboundOption {
	return func(i *inbound) { i.addr = addr }
}

// NewInbound builds a new TChannel inbound from the given Channel.
func NewInbound(ch *tchannel.Channel, opts ...InboundOption) Inbound {
	i := &inbound{ch: ch}
	for _, opt := range opts {
		opt(i)
	}
	return i
}

type inbound struct {
	ch       *tchannel.Channel
	addr     string
	listener net.Listener
}

func (i *inbound) Start(h transport.Handler) error {
	i.ch.GetSubChannel(i.ch.ServiceName()).SetHandler(handler{h})

	if i.ch.State() == tchannel.ChannelListening {
		// Already listening. Don't need to do anything besides setting up the
		// handler.
		return nil
	}

	addr := i.addr
	if addr == "" {
		addr = ":0"
	}

	var err error
	i.listener, err = net.Listen("tcp", addr)
	if err != nil {
		return err
	}
	i.addr = i.listener.Addr().String() // in case it changed

	if err := i.ch.Serve(i.listener); err != nil {
		return err
	}

	return nil
}

func (i *inbound) Stop() error {
	i.ch.Close()
	return nil
}

func (i *inbound) Addr() net.Addr {
	if i.listener == nil {
		return nil
	}
	return i.listener.Addr()
}

type handler struct{ Handler transport.Handler }<commit_msg>tchannel/inbound: use tchannel.ListenIP by default<commit_after>// Copyright (c) 2016 Uber Technologies, Inc.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.

package tchannel

import (
	"net"
	"time"

	"github.com/yarpc/yarpc-go/transport"

	"github.com/uber/tchannel-go"
	"golang.org/x/net/context"
)

// Inbound represents a TChannel Inbound. It is the same as a transport
// Inbound except it exposes the address on which the system is listening for
// connections.
type Inbound interface {
	transport.Inbound

	// Address on which the server is listening. Returns nil if Start has not
	// been called yet.
	Addr() net.Addr
}

// InboundOption configures Inbound.
type InboundOption func(*inbound)

// ListenAddr changes the address on which the TChannel server will listen for
// connections. By default, the server listens on an OS-assigned port.
//
// This option has no effect if the Chanel provided to NewInbound is already
// listening for connections when Start() is called.
func ListenAddr(addr string) InboundOption {
	return func(i *inbound) { i.addr = addr }
}

// NewInbound builds a new TChannel inbound from the given Channel.
func NewInbound(ch *tchannel.Channel, opts ...InboundOption) Inbound {
	i := &inbound{ch: ch}
	for _, opt := range opts {
		opt(i)
	}
	return i
}

type inbound struct {
	ch       *tchannel.Channel
	addr     string
	listener net.Listener
}

func (i *inbound) Start(h transport.Handler) error {
	i.ch.GetSubChannel(i.ch.ServiceName()).SetHandler(handler{h})

	if i.ch.State() == tchannel.ChannelListening {
		// Already listening. Don't need to do anything besides setting up the
		// handler.
		return nil
	}

	addr := i.addr
	if addr == "" {
		listenIP, err := tchannel.ListenIP()
		if err != nil {
			return err
		}

		addr = listenIP.String() + ":0"
		// TODO(abg): Find a way to export this to users
	}

	var err error
	i.listener, err = net.Listen("tcp", addr)
	if err != nil {
		return err
	}
	i.addr = i.listener.Addr().String() // in case it changed

	if err := i.ch.Serve(i.listener); err != nil {
		return err
	}

	return nil
}

func (i *inbound) Stop() error {
	i.ch.Close()
	return nil
}

func (i *inbound) Addr() net.Addr {
	if i.listener == nil {
		return nil
	}
	return i.listener.Addr()
}

type handler struct{ Handler transport.Handler }
{'fraction_non_alphanumeric': 0.09774203526136716, 'fraction_numerical': 0.001546551190844417, 'mean_word_length': 3.5255423372988104, 'pattern_counts': {'":': 2, '<': 3, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2860387', 'n_tokens_mistral': 1974, 'n_tokens_neox': 1882, 'n_words': 820}