<commit_before>// Copyright 2015 Google Inc. All Rights Reserved.
// Author: jacobsa@google.com (Aaron Jacobs)

package fuseutil

import (
	"errors"
	"log"

	"bazil.org/fuse"
	fusefs "bazil.org/fuse/fs"
	"golang.org/x/net/context"
)

// A struct representing the status of a mount operation, with methods for
// waiting on the mount to complete, waiting for unmounting, and causing
// unmounting.
type MountedFileSystem struct {
	dir string

	// The result to return from WaitForReady. Not valid until the channel is
	// closed.
	readyStatus          error
	readyStatusAvailable chan struct{}

	// The result to return from Join. Not valid until the channel is closed.
	joinStatus          error
	joinStatusAvailable chan struct{}
}

// Wait until the mount point is ready to be used. After a successful return
// from this function, the contents of the mounted file system should be
// visible in the directory supplied to NewMountPoint. May be called multiple
// times.
func (mfs *MountedFileSystem) WaitForReady(ctx context.Context) error {
	select {
	case <-mfs.readyStatusAvailable:
		return mfs.readyStatus
	case <-ctx.Done():
		return ctx.Err()
	}
}

// Block until a mounted file system has been unmounted. The return value will
// be non-nil if anything unexpected happened while serving. May be called
// multiple times. Must not be called unless WaitForReady has returned nil.
func (mfs *MountedFileSystem) Join(ctx context.Context) error {
	select {
	case <-mfs.joinStatusAvailable:
		return mfs.joinStatus
	case <-ctx.Done():
		return ctx.Err()
	}
}

// Attempt to unmount the file system. Use Join to wait for it to actually be
// unmounted. You must first call WaitForReady to ensure there is no race with
// mounting.
func (mfs *MountedFileSystem) Unmount() error {
	return fuse.Unmount(mfs.dir)
}

// Runs in the background.
func (mfs *MountedFileSystem) mountAndServe(
	fs fusefs.FS,
	options []fuse.MountOption) {
	// Open a FUSE connection.
	log.Println("Opening a FUSE connection.")
	c, err := fuse.Mount(mfs.dir, options...)
	if err != nil {
		mfs.readyStatus = errors.New("fuse.Mount: " + err.Error())
		close(mfs.readyStatusAvailable)
		return
	}

	defer c.Close()

	// Start a goroutine that will notify the MountedFileSystem object when the
	// connection says it is ready (or it fails to become ready).
	go func() {
		<-c.Ready
		mfs.readyStatus = c.MountError
		close(mfs.readyStatusAvailable)
	}()

	// Serve the connection using the file system object.
	if err := fusefs.Serve(c, fs); err != nil {
		mfs.joinStatus = errors.New("fusefs.Serve: " + err.Error())
		close(mfs.joinStatusAvailable)
		return
	}

	// Signal that everything is okay.
	close(mfs.joinStatusAvailable)
}

// Attempt to mount the supplied file system on the given directory.
// mfs.WaitForReady() must be called to find out whether the mount was
// successful.
func MountFileSystem(
	dir string,
	fs fusefs.FS,
	options ...fuse.MountOption) (mfs *MountedFileSystem) {
	// Initialize the struct.
	mfs = &MountedFileSystem{
		dir:                  dir,
		readyStatusAvailable: make(chan struct{}),
	}

	// Mount in the background.
	go mfs.mountAndServe(fs, options)

	return mfs
}
<commit_msg>Fixed a nil channel bug.<commit_after>// Copyright 2015 Google Inc. All Rights Reserved.
// Author: jacobsa@google.com (Aaron Jacobs)

package fuseutil

import (
	"errors"
	"log"

	"bazil.org/fuse"
	fusefs "bazil.org/fuse/fs"
	"golang.org/x/net/context"
)

// A struct representing the status of a mount operation, with methods for
// waiting on the mount to complete, waiting for unmounting, and causing
// unmounting.
type MountedFileSystem struct {
	dir string

	// The result to return from WaitForReady. Not valid until the channel is
	// closed.
	readyStatus          error
	readyStatusAvailable chan struct{}

	// The result to return from Join. Not valid until the channel is closed.
	joinStatus          error
	joinStatusAvailable chan struct{}
}

// Wait until the mount point is ready to be used. After a successful return
// from this function, the contents of the mounted file system should be
// visible in the directory supplied to NewMountPoint. May be called multiple
// times.
func (mfs *MountedFileSystem) WaitForReady(ctx context.Context) error {
	select {
	case <-mfs.readyStatusAvailable:
		return mfs.readyStatus
	case <-ctx.Done():
		return ctx.Err()
	}
}

// Block until a mounted file system has been unmounted. The return value will
// be non-nil if anything unexpected happened while serving. May be called
// multiple times. Must not be called unless WaitForReady has returned nil.
func (mfs *MountedFileSystem) Join(ctx context.Context) error {
	select {
	case <-mfs.joinStatusAvailable:
		return mfs.joinStatus
	case <-ctx.Done():
		return ctx.Err()
	}
}

// Attempt to unmount the file system. Use Join to wait for it to actually be
// unmounted. You must first call WaitForReady to ensure there is no race with
// mounting.
func (mfs *MountedFileSystem) Unmount() error {
	return fuse.Unmount(mfs.dir)
}

// Runs in the background.
func (mfs *MountedFileSystem) mountAndServe(
	fs fusefs.FS,
	options []fuse.MountOption) {
	// Open a FUSE connection.
	log.Println("Opening a FUSE connection.")
	c, err := fuse.Mount(mfs.dir, options...)
	if err != nil {
		mfs.readyStatus = errors.New("fuse.Mount: " + err.Error())
		close(mfs.readyStatusAvailable)
		return
	}

	defer c.Close()

	// Start a goroutine that will notify the MountedFileSystem object when the
	// connection says it is ready (or it fails to become ready).
	go func() {
		<-c.Ready
		mfs.readyStatus = c.MountError
		close(mfs.readyStatusAvailable)
	}()

	// Serve the connection using the file system object.
	if err := fusefs.Serve(c, fs); err != nil {
		mfs.joinStatus = errors.New("fusefs.Serve: " + err.Error())
		close(mfs.joinStatusAvailable)
		return
	}

	// Signal that everything is okay.
	close(mfs.joinStatusAvailable)
}

// Attempt to mount the supplied file system on the given directory.
// mfs.WaitForReady() must be called to find out whether the mount was
// successful.
func MountFileSystem(
	dir string,
	fs fusefs.FS,
	options ...fuse.MountOption) (mfs *MountedFileSystem) {
	// Initialize the struct.
	mfs = &MountedFileSystem{
		dir:                  dir,
		readyStatusAvailable: make(chan struct{}),
		joinStatusAvailable:  make(chan struct{}),
	}

	// Mount in the background.
	go mfs.mountAndServe(fs, options)

	return mfs
}
<|endoftext|>


<commit_before>package gridserver

import (
	"bytes"
	"fmt"
	"image"
	"image/color"
	"image/png"
	"strings"

	"github.com/golang/freetype"
	"github.com/golang/freetype/truetype"
	log "github.com/golang/glog"
	geojson "github.com/paulmach/go.geojson"
	"golang.org/x/image/font/gofont/goregular"
)

const (
	tileSize = 256 // size of tiles in pixels. Accessed by other functions in this package.
	fontSize = 80
)

var (
	imageTileFont *truetype.Font

	white      = color.RGBA{255, 255, 255, 255}
	black      = color.RGBA{0, 0, 0, 255}
	grey       = color.RGBA{0, 0, 0, 128}
	lineColor  = black
	labelColor = grey
)

// Image returns the tile as a 256x256 pixel PNG image.
func (t *TileRef) Image() ([]byte, error) {
	log.Infof("Producing image for tile z/x/y %v/%v/%v (%s)", t.Z, t.X, t.Y, t.Path())
	gj, err := t.GeoJSON()
	if err != nil {
		return nil, err
	}
	// If the font hasn't been set, fallback to the default.
	if imageTileFont == nil {
		if err := SetImageFont(goregular.TTF); err != nil {
			return []byte{}, fmt.Errorf("Failed reading font: %v", err)
		}
	}
	img := image.NewRGBA(image.Rect(0, 0, tileSize, tileSize))
	// Create a context used for adding text to the image.
	ctx := freetype.NewContext()
	ctx.SetDst(img)
	ctx.SetClip(image.Rect(-tileSize, -tileSize, tileSize, tileSize))
	ctx.SetSrc(image.NewUniform(t.Options.LabelColor))
	ctx.SetFont(imageTileFont)

	// Create a colour for the sub-grid, using half-alpha of the label colour.
	r, g, b, a := t.Options.LabelColor.RGBA()
	a = a / 2
	gridCol := color.RGBA{
		uint8(min(r, a)),
		uint8(min(g, a)),
		uint8(min(b, a)),
		uint8(a),
	}
	// Draw and label each OLC grid cell that is returned in the geojson (i.e. feature).
	for _, ft := range gj.Features {
		cell := makeGridCell(ctx, t, ft)
		// Decide if we want to draw the sub-grid, depending on the code length and the pixel width.
		if len(ft.Properties["global_code"].(string)) <= 10 && cell.width > 200 {
			cell.drawGrid(t, img, gridCol, 20, 20)
		} else if len(ft.Properties["global_code"].(string)) > 10 && cell.width > 100 {
			cell.drawGrid(t, img, gridCol, 4, 5)
		}
		// Draw the cell outline.
		cell.drawRect(img, t.Options.LineColor)
		// Draw the label.
		cell.label(featureLabel(ft))
	}
	buf := new(bytes.Buffer)
	png.Encode(buf, img)
	return buf.Bytes(), nil
}

// gridCell represents an OLC grid cell.
type gridCell struct {
	ctx *freetype.Context
	// Latlng coordinates.
	latlo, lnglo, lathi, lnghi float64
	// Pixel coordinates.
	x1, y1, x2, y2 float64
	cx, cy, width  float64
}

// makeGridCell creates a gridCell structure.
func makeGridCell(ctx *freetype.Context, t *TileRef, f *geojson.Feature) *gridCell {
	o := &gridCell{ctx: ctx}
	// Get the bounds and create the pixel coordinates.
	o.latlo, o.lnglo, o.lathi, o.lnghi = bounds(f)
	// The pixels go from top to bottom so the y-coordinates are swapped.
	o.x1, o.y2 = t.LatLngToPixel(o.latlo, o.lnglo, tileSize)
	o.x2, o.y1 = t.LatLngToPixel(o.lathi, o.lnghi, tileSize)
	// Get the pixel center and the width.
	o.cx = (o.x1 + o.x2) / 2
	o.cy = (o.y1 + o.y2) / 2
	o.width = o.x2 - o.x1
	return o
}

// drawRect draws a rectangle utilizing HLine() and VLine()
func (c *gridCell) drawRect(img *image.RGBA, col color.Color) {
	c.drawHoriz(img, col, c.y1)
	c.drawHoriz(img, col, c.y2)
	c.drawVert(img, col, c.x1)
	c.drawVert(img, col, c.x2)
}

// drawGrid draws a grid within the cell of xdiv horizontal and ydiv vertical divisions.
func (c *gridCell) drawGrid(t *TileRef, img *image.RGBA, col color.Color, xdiv, ydiv float64) {
	// Draw the horizontal sub grid. We need to use the lat/lng coordinates for the horizontal lines
	// because the divisions are regular in degrees but not pixels.
	s := (c.lathi - c.latlo) / ydiv
	for i := 1; i <= 19; i++ {
		_, y := t.LatLngToPixel(c.latlo+float64(i)*s, c.lnglo, tileSize)
		c.drawHoriz(img, col, y)
	}
	// Draw the vertical sub grid.
	s = (c.x2 - c.x1) / xdiv
	for i := 1; i <= 19; i++ {
		c.drawVert(img, col, c.x1+float64(i)*s)
	}
}

// drawHoriz draws a horizontal line across the cell.
func (c *gridCell) drawHoriz(img *image.RGBA, col color.Color, y float64) {
	for x := c.x1; x <= c.x2; x++ {
		img.Set(int(x), int(y), col)
	}
}

// drawVert draws a vertical line across the cell.
func (c *gridCell) drawVert(img *image.RGBA, col color.Color, x float64) {
	for y := c.y1; y <= c.y2; y++ {
		img.Set(int(x), int(y), col)
	}
}

// label draws a multi-line label in the center of the cell - not tile, but grid cell.
// The font size of each line is scaled to fit.
func (c *gridCell) label(label string) {
	// Split the label into it's lines and get the font sizes for each line.
	lines := strings.Split(label, "\n")
	fontSizes := make([]float64, len(lines))
	var total float64
	for n, l := range lines {
		// Get the font size for the label.
		var fs float64
		// If it's the first line, and there are more, then the font size is reduced.
		if n == 0 && len(lines) > 1 {
			fs = scaleFontSize(c.ctx, c.width, strings.Repeat("W", 5)) * 0.9
		} else {
			fs = scaleFontSize(c.ctx, c.width, strings.Repeat("W", len(l)))
		}
		fontSizes[n] = fs
		total += fs
	}
	// Work out the y coordinate for the _last_ line. The y coordinate is the bottom of the line,
	// measured from the top of the cell.
	y := c.cy + total/2
	// Draw the last line, and work backwards to the first line.
	for i := len(lines) - 1; i >= 0; i-- {
		c.ctx.SetFontSize(fontSizes[i])
		w := getStringWidth(c.ctx, lines[i]) / 2
		if _, err := c.ctx.DrawString(lines[i], freetype.Pt(int(c.cx-w), int(y))); err != nil {
			log.Errorf("Error drawing label: %v", err)
		}
		// Reduce the y coordinate by the font size.
		y -= fontSizes[i]
	}
}

// scaleFontSize returns the scaled font size so the label fits within the cell width.
func scaleFontSize(ctx *freetype.Context, cw float64, label string) float64 {
	if len(label) == 0 {
		return 1000
	}
	// Start with the default font size.
	ctx.SetFontSize(fontSize)
	lw := getStringWidth(ctx, label)
	// Scale the font to make the label fit in the cell width.
	return (cw / lw) * fontSize
}

// SetImageFont parses a TTF font and uses it for the image labels.
func SetImageFont(ttf []byte) error {
	// Parse the truetype file.
	font, err := truetype.Parse(ttf)
	imageTileFont = font
	return err
}

// getStringWidth returns the width of the string in the current font and font size.
func getStringWidth(ctx *freetype.Context, s string) float64 {
	if len(s) == 0 {
		return 0
	}
	// Draw it somewhere off the tile.
	st := freetype.Pt(-1000, -1000)
	val, err := ctx.DrawString(s, st)
	if err != nil {
		log.Errorf("Failed drawing string to compute width: %v", err)
		return 0
	}
	w := float64(val.X.Round() - st.X.Round())
	return w
}

func min(a, b uint32) uint32 {
	if a < b {
		return a
	}
	return b
}
<commit_msg>Correct comments<commit_after>package gridserver

import (
	"bytes"
	"fmt"
	"image"
	"image/color"
	"image/png"
	"strings"

	"github.com/golang/freetype"
	"github.com/golang/freetype/truetype"
	log "github.com/golang/glog"
	geojson "github.com/paulmach/go.geojson"
	"golang.org/x/image/font/gofont/goregular"
)

const (
	tileSize = 256 // size of tiles in pixels. Accessed by other functions in this package.
	fontSize = 80
)

var (
	imageTileFont *truetype.Font

	white      = color.RGBA{255, 255, 255, 255}
	black      = color.RGBA{0, 0, 0, 255}
	grey       = color.RGBA{0, 0, 0, 128}
	lineColor  = black
	labelColor = grey
)

// Image returns the tile as a 256x256 pixel PNG image.
func (t *TileRef) Image() ([]byte, error) {
	log.Infof("Producing image for tile z/x/y %v/%v/%v (%s)", t.Z, t.X, t.Y, t.Path())
	gj, err := t.GeoJSON()
	if err != nil {
		return nil, err
	}
	// If the font hasn't been set, fallback to the default.
	if imageTileFont == nil {
		if err := SetImageFont(goregular.TTF); err != nil {
			return []byte{}, fmt.Errorf("Failed reading font: %v", err)
		}
	}
	img := image.NewRGBA(image.Rect(0, 0, tileSize, tileSize))
	// Create a context used for adding text to the image.
	ctx := freetype.NewContext()
	ctx.SetDst(img)
	ctx.SetClip(image.Rect(-tileSize, -tileSize, tileSize, tileSize))
	ctx.SetSrc(image.NewUniform(t.Options.LabelColor))
	ctx.SetFont(imageTileFont)

	// Create a colour for the sub-grid, using half-alpha of the label colour.
	r, g, b, a := t.Options.LabelColor.RGBA()
	a = a / 2
	gridCol := color.RGBA{
		uint8(min(r, a)),
		uint8(min(g, a)),
		uint8(min(b, a)),
		uint8(a),
	}
	// Draw and label each OLC grid cell that is returned in the geojson (i.e. feature).
	for _, ft := range gj.Features {
		cell := makeGridCell(ctx, t, ft)
		// Decide if we want to draw the sub-grid, depending on the code length and the pixel width.
		if len(ft.Properties["global_code"].(string)) <= 10 && cell.width > 200 {
			cell.drawGrid(t, img, gridCol, 20, 20)
		} else if len(ft.Properties["global_code"].(string)) > 10 && cell.width > 100 {
			cell.drawGrid(t, img, gridCol, 4, 5)
		}
		// Draw the cell outline.
		cell.drawRect(img, t.Options.LineColor)
		// Draw the label.
		cell.label(featureLabel(ft))
	}
	buf := new(bytes.Buffer)
	png.Encode(buf, img)
	return buf.Bytes(), nil
}

// gridCell represents an OLC grid cell.
type gridCell struct {
	ctx *freetype.Context
	// Latlng coordinates.
	latlo, lnglo, lathi, lnghi float64
	// Pixel coordinates.
	x1, y1, x2, y2 float64
	cx, cy, width  float64
}

// makeGridCell creates a gridCell structure.
func makeGridCell(ctx *freetype.Context, t *TileRef, f *geojson.Feature) *gridCell {
	o := &gridCell{ctx: ctx}
	// Get the bounds and create the pixel coordinates.
	o.latlo, o.lnglo, o.lathi, o.lnghi = bounds(f)
	// The pixels go from top to bottom so the y-coordinates are swapped.
	o.x1, o.y2 = t.LatLngToPixel(o.latlo, o.lnglo, tileSize)
	o.x2, o.y1 = t.LatLngToPixel(o.lathi, o.lnghi, tileSize)
	// Get the pixel center and the width.
	o.cx = (o.x1 + o.x2) / 2
	o.cy = (o.y1 + o.y2) / 2
	o.width = o.x2 - o.x1
	return o
}

// drawRect draws a rectangle around the cell.
func (c *gridCell) drawRect(img *image.RGBA, col color.Color) {
	c.drawHoriz(img, col, c.y1)
	c.drawHoriz(img, col, c.y2)
	c.drawVert(img, col, c.x1)
	c.drawVert(img, col, c.x2)
}

// drawGrid draws a grid within the cell of xdiv horizontal and ydiv vertical divisions.
func (c *gridCell) drawGrid(t *TileRef, img *image.RGBA, col color.Color, xdiv, ydiv float64) {
	// Draw the horizontal sub grid. We need to use the lat/lng coordinates for the horizontal lines
	// because the divisions are regular in degrees but not pixels.
	s := (c.lathi - c.latlo) / ydiv
	for i := 1; i <= 19; i++ {
		_, y := t.LatLngToPixel(c.latlo+float64(i)*s, c.lnglo, tileSize)
		c.drawHoriz(img, col, y)
	}
	// Draw the vertical sub grid.
	s = (c.x2 - c.x1) / xdiv
	for i := 1; i <= 19; i++ {
		c.drawVert(img, col, c.x1+float64(i)*s)
	}
}

// drawHoriz draws a horizontal line across the cell.
func (c *gridCell) drawHoriz(img *image.RGBA, col color.Color, y float64) {
	for x := c.x1; x <= c.x2; x++ {
		img.Set(int(x), int(y), col)
	}
}

// drawVert draws a vertical line across the cell.
func (c *gridCell) drawVert(img *image.RGBA, col color.Color, x float64) {
	for y := c.y1; y <= c.y2; y++ {
		img.Set(int(x), int(y), col)
	}
}

// label draws a multi-line label in the center of the cell - not tile, but grid cell.
// The font size of each line is scaled to fit the cell width.
func (c *gridCell) label(label string) {
	// Split the label into it's lines and get the font sizes for each line.
	lines := strings.Split(label, "\n")
	fontSizes := make([]float64, len(lines))
	var total float64
	for n, l := range lines {
		// Get the font size for the label.
		var fs float64
		// If it's the first line, and there are more, then the font size is reduced.
		if n == 0 && len(lines) > 1 {
			fs = scaleFontSize(c.ctx, c.width, strings.Repeat("W", 5)) * 0.9
		} else {
			fs = scaleFontSize(c.ctx, c.width, strings.Repeat("W", len(l)))
		}
		fontSizes[n] = fs
		total += fs
	}
	// Work out the y coordinate for the _last_ line. The y coordinate is the bottom of the line,
	// measured from the top of the cell.
	y := c.cy + total/2
	// Draw the last line, and work backwards to the first line.
	for i := len(lines) - 1; i >= 0; i-- {
		c.ctx.SetFontSize(fontSizes[i])
		w := getStringWidth(c.ctx, lines[i]) / 2
		if _, err := c.ctx.DrawString(lines[i], freetype.Pt(int(c.cx-w), int(y))); err != nil {
			log.Errorf("Error drawing label: %v", err)
		}
		// Reduce the y coordinate by the font size.
		y -= fontSizes[i]
	}
}

// scaleFontSize returns the scaled font size to fit the label within the available width.
func scaleFontSize(ctx *freetype.Context, cw float64, label string) float64 {
	if len(label) == 0 {
		return 1000
	}
	// Start with the default font size.
	ctx.SetFontSize(fontSize)
	lw := getStringWidth(ctx, label)
	// Scale the font to make the label fit in the cell width.
	return (cw / lw) * fontSize
}

// SetImageFont parses a TTF font and uses it for the image labels.
func SetImageFont(ttf []byte) error {
	// Parse the truetype file.
	font, err := truetype.Parse(ttf)
	imageTileFont = font
	return err
}

// getStringWidth returns the width of the string in the current font and font size.
func getStringWidth(ctx *freetype.Context, s string) float64 {
	if len(s) == 0 {
		return 0
	}
	// Draw it somewhere off the tile.
	st := freetype.Pt(-1000, -1000)
	val, err := ctx.DrawString(s, st)
	if err != nil {
		log.Errorf("Failed drawing string to compute width: %v", err)
		return 0
	}
	w := float64(val.X.Round() - st.X.Round())
	return w
}

func min(a, b uint32) uint32 {
	if a < b {
		return a
	}
	return b
}
<|endoftext|>


<commit_before>package netascii

import (
	"bufio"
	"bytes"
	"io"
)

func WriteTo(b []byte, bw *bufio.Writer) (n int, err error) {
	b = bytes.Replace(b, []byte{'\r', 0}, []byte{'\r'}, -1)
	b = bytes.Replace(b, []byte{'\r', '\n'}, []byte{'\n'}, -1)
	n, err = bw.Write(b)
	if err != nil {
		return 0, err
	}
	return n, nil
}

func Convert(b []byte) []byte {
	b = bytes.Replace(b, []byte{'\r', 0}, []byte{'\r'}, -1)
	b = bytes.Replace(b, []byte{'\r', '\n'}, []byte{'\n'}, -1)
	return b
}

func ReadFull(r io.Reader, buf []byte) (n int, err error) {
	if len(buf) == 0 {
		return 0, io.ErrShortBuffer
	}
	n, err = r.Read(buf)
	if err != nil {
		return 0, err
	}
	buf = bytes.Replace(buf, []byte{'\r', 0}, []byte{'\r'}, -1)
	buf = bytes.Replace(buf, []byte{'\r', '\n'}, []byte{'\n'}, -1)

	return n, nil
}
<commit_msg>Return the actual size written to bw, even when an error occurs.<commit_after>package netascii

import (
	"bufio"
	"bytes"
	"io"
)

func WriteTo(b []byte, bw *bufio.Writer) (n int, err error) {
	b = bytes.Replace(b, []byte{'\r', 0}, []byte{'\r'}, -1)
	b = bytes.Replace(b, []byte{'\r', '\n'}, []byte{'\n'}, -1)
	n, err = bw.Write(b)
	if err != nil {
		return n, err
	}
	return n, nil
}

func Convert(b []byte) []byte {
	b = bytes.Replace(b, []byte{'\r', 0}, []byte{'\r'}, -1)
	b = bytes.Replace(b, []byte{'\r', '\n'}, []byte{'\n'}, -1)
	return b
}

func ReadFull(r io.Reader, buf []byte) (n int, err error) {
	if len(buf) == 0 {
		return 0, io.ErrShortBuffer
	}
	n, err = r.Read(buf)
	if err != nil {
		return 0, err
	}
	buf = bytes.Replace(buf, []byte{'\r', 0}, []byte{'\r'}, -1)
	buf = bytes.Replace(buf, []byte{'\r', '\n'}, []byte{'\n'}, -1)

	return n, nil
}
<|endoftext|>


<commit_before>package network

import (
	"context"
	"crypto"
	"net"
	"testing"
	"time"

	"github.com/ava-labs/avalanchego/ids"
	"github.com/ava-labs/avalanchego/snow/networking/benchlist"
	"github.com/ava-labs/avalanchego/snow/validators"
	"github.com/ava-labs/avalanchego/utils"
	"github.com/ava-labs/avalanchego/utils/hashing"
	"github.com/ava-labs/avalanchego/utils/logging"
	"github.com/ava-labs/avalanchego/version"
	"github.com/prometheus/client_golang/prometheus"
	"github.com/stretchr/testify/assert"
)

type TestMsg struct {
	op    Op
	bytes []byte
}

func newTestMsg(op Op, bits []byte) *TestMsg {
	return &TestMsg{op: op, bytes: bits}
}

func (m *TestMsg) Op() Op {
	return m.op
}

func (*TestMsg) Get(Field) interface{} {
	return nil
}

func (m *TestMsg) Bytes() []byte {
	return m.bytes
}

func TestPeer_Close(t *testing.T) {
	log := logging.NoLog{}
	ip := utils.NewDynamicIPDesc(
		net.IPv6loopback,
		0,
	)
	id := ids.ShortID(hashing.ComputeHash160Array([]byte(ip.IP().String())))
	networkID := uint32(0)
	appVersion := version.NewDefaultApplication("app", 0, 1, 0)
	versionParser := version.NewDefaultApplicationParser()

	listener := &testListener{
		addr: &net.TCPAddr{
			IP:   net.IPv6loopback,
			Port: 0,
		},
		inbound: make(chan net.Conn, 1<<10),
		closed:  make(chan struct{}),
	}
	caller := &testDialer{
		addr: &net.TCPAddr{
			IP:   net.IPv6loopback,
			Port: 0,
		},
		outbounds: make(map[string]*testListener),
	}
	serverUpgrader0 := NewTLSServerUpgrader(tlsConfig0)
	clientUpgrader0 := NewTLSClientUpgrader(tlsConfig0)

	vdrs := validators.NewSet()
	handler := &testHandler{}

	versionManager := version.NewCompatibility(
		appVersion,
		appVersion,
		time.Now(),
		appVersion,
		appVersion,
		time.Now(),
		appVersion,
	)

	netwrk := NewDefaultNetwork(
		prometheus.NewRegistry(),
		log,
		id,
		ip,
		networkID,
		versionManager,
		versionParser,
		listener,
		caller,
		serverUpgrader0,
		clientUpgrader0,
		vdrs,
		vdrs,
		handler,
		time.Duration(0),
		0,
		defaultSendQueueSize,
		HealthConfig{},
		benchlist.NewManager(&benchlist.Config{}),
		defaultAliasTimeout,
		cert0.PrivateKey.(crypto.Signer),
		defaultPeerListSize,
		defaultGossipPeerListTo,
		defaultGossipPeerListFreq,
		NewDialerConfig(0, 30*time.Second),
		false,
		defaultGossipAcceptedFrontierSize,
		defaultGossipOnAcceptSize,
	)
	assert.NotNil(t, netwrk)

	ip1 := utils.NewDynamicIPDesc(
		net.IPv6loopback,
		1,
	)
	caller.outbounds[ip1.IP().String()] = listener
	conn, err := caller.Dial(context.Background(), ip1.IP())
	assert.NoError(t, err)

	basenetwork := netwrk.(*network)

	newmsgbytes := []byte("hello")

	// fake a peer, and write a message
	peer := newPeer(basenetwork, conn, ip1.IP())
	peer.sender = make(chan []byte, 10)
	testMsg := newTestMsg(GetVersion, newmsgbytes)
	peer.Send(testMsg, true)

	// make sure the net pending and peer pending bytes updated
	if basenetwork.pendingBytes != int64(len(newmsgbytes)) {
		t.Fatalf("pending bytes invalid")
	}
	if peer.pendingBytes != int64(len(newmsgbytes)) {
		t.Fatalf("pending bytes invalid")
	}

	go func() {
		err := netwrk.Close()
		assert.NoError(t, err)
	}()

	peer.Close()

	// The network pending bytes should be reduced back to zero on close.
	if basenetwork.pendingBytes != int64(0) {
		t.Fatalf("pending bytes invalid")
	}
	if peer.pendingBytes != int64(len(newmsgbytes)) {
		t.Fatalf("pending bytes invalid")
	}
}
<commit_msg>add test<commit_after>package network

import (
	"context"
	"crypto"
	"net"
	"testing"
	"time"

	"github.com/ava-labs/avalanchego/ids"
	"github.com/ava-labs/avalanchego/snow/networking/benchlist"
	"github.com/ava-labs/avalanchego/snow/validators"
	"github.com/ava-labs/avalanchego/utils"
	"github.com/ava-labs/avalanchego/utils/hashing"
	"github.com/ava-labs/avalanchego/utils/logging"
	"github.com/ava-labs/avalanchego/version"
	"github.com/prometheus/client_golang/prometheus"
	"github.com/stretchr/testify/assert"
)

type TestMsg struct {
	op    Op
	bytes []byte
}

func newTestMsg(op Op, bits []byte) *TestMsg {
	return &TestMsg{op: op, bytes: bits}
}

func (m *TestMsg) Op() Op {
	return m.op
}

func (*TestMsg) Get(Field) interface{} {
	return nil
}

func (m *TestMsg) Bytes() []byte {
	return m.bytes
}

func TestPeer_Close(t *testing.T) {
	log := logging.NoLog{}
	ip := utils.NewDynamicIPDesc(
		net.IPv6loopback,
		0,
	)
	id := ids.ShortID(hashing.ComputeHash160Array([]byte(ip.IP().String())))
	networkID := uint32(0)
	appVersion := version.NewDefaultApplication("app", 0, 1, 0)
	versionParser := version.NewDefaultApplicationParser()

	listener := &testListener{
		addr: &net.TCPAddr{
			IP:   net.IPv6loopback,
			Port: 0,
		},
		inbound: make(chan net.Conn, 1<<10),
		closed:  make(chan struct{}),
	}
	caller := &testDialer{
		addr: &net.TCPAddr{
			IP:   net.IPv6loopback,
			Port: 0,
		},
		outbounds: make(map[string]*testListener),
	}
	serverUpgrader0 := NewTLSServerUpgrader(tlsConfig0)
	clientUpgrader0 := NewTLSClientUpgrader(tlsConfig0)

	vdrs := validators.NewSet()
	handler := &testHandler{}

	versionManager := version.NewCompatibility(
		appVersion,
		appVersion,
		time.Now(),
		appVersion,
		appVersion,
		time.Now(),
		appVersion,
	)

	netwrk := NewDefaultNetwork(
		prometheus.NewRegistry(),
		log,
		id,
		ip,
		networkID,
		versionManager,
		versionParser,
		listener,
		caller,
		serverUpgrader0,
		clientUpgrader0,
		vdrs,
		vdrs,
		handler,
		time.Duration(0),
		0,
		defaultSendQueueSize,
		HealthConfig{},
		benchlist.NewManager(&benchlist.Config{}),
		defaultAliasTimeout,
		cert0.PrivateKey.(crypto.Signer),
		defaultPeerListSize,
		defaultGossipPeerListTo,
		defaultGossipPeerListFreq,
		NewDialerConfig(0, 30*time.Second),
		false,
		defaultGossipAcceptedFrontierSize,
		defaultGossipOnAcceptSize,
	)
	assert.NotNil(t, netwrk)

	ip1 := utils.NewDynamicIPDesc(
		net.IPv6loopback,
		1,
	)
	caller.outbounds[ip1.IP().String()] = listener
	conn, err := caller.Dial(context.Background(), ip1.IP())
	assert.NoError(t, err)

	basenetwork := netwrk.(*network)

	newmsgbytes := []byte("hello")

	// fake a peer, and write a message
	peer := newPeer(basenetwork, conn, ip1.IP())
	peer.sender = make(chan []byte, 10)
	testMsg := newTestMsg(GetVersion, newmsgbytes)
	peer.Send(testMsg, true)

	// make sure the net pending and peer pending bytes updated
	if basenetwork.pendingBytes != int64(len(newmsgbytes)) {
		t.Fatalf("pending bytes invalid")
	}
	if peer.pendingBytes != int64(len(newmsgbytes)) {
		t.Fatalf("pending bytes invalid")
	}

	go func() {
		err := netwrk.Close()
		assert.NoError(t, err)
	}()

	peer.Close()

	// The network pending bytes should be reduced back to zero on close.
	if basenetwork.pendingBytes != int64(0) {
		t.Fatalf("pending bytes invalid")
	}
	if peer.pendingBytes != int64(len(newmsgbytes)) {
		t.Fatalf("pending bytes invalid")
	}
}

func TestShouldCompress(t *testing.T) {
	p := newPeer(nil, nil, utils.IPDesc{}) // Dummy values are OK here
	shouldNotCompressOps := []Op{Version, GetVersion, PeerList, GetPeerList, Ping, Pong}
	shouldCompressOps := []Op{Put, Get, MultiPut, GetAncestors, Accepted, AcceptedFrontier, GetAccepted, GetAcceptedFrontier, PushQuery, PullQuery, Chits}
	for _, op := range shouldCompressOps {
		// Shouldn't compress because [p.canHandleCompressed] == false
		assert.False(t, p.shouldCompress(op))
	}
	for _, op := range shouldNotCompressOps {
		assert.False(t, p.shouldCompress(op))
	}

	p.canHandleCompressed = true
	for _, op := range shouldCompressOps {
		assert.True(t, p.shouldCompress(op))
	}
	for _, op := range shouldNotCompressOps {
		assert.False(t, p.shouldCompress(op))
	}
}
<|endoftext|>


<commit_before>package torpedo_lastfm_plugin

import (
	"flag"
	"fmt"
	"strings"

	common "github.com/tb0hdan/torpedo_common"
	"github.com/tb0hdan/torpedo_registry"

	"github.com/shkh/lastfm-go/lastfm"
)

var (
	LastFmKey *string
	LastFmSecret *string
)

func ConfigureLastFmPlugin(cfg *torpedo_registry.ConfigStruct) {
	LastFmKey = flag.String("lastfm_key", "", "Last.FM API Key")
	LastFmSecret = flag.String("lastfm_secret", "", "Last.FM API Secret")

}

func ParseLastFmPlugin(cfg *torpedo_registry.ConfigStruct) {
	cfg.SetConfig("lastfmkey", *LastFmKey)
	cfg.SetConfig("lastfmsecret", *LastFmSecret)
	if cfg.GetConfig()["lastfmkey"] == "" {
		cfg.SetConfig("lastfmkey", common.GetStripEnv("LASTFM_KEY"))
	}
	if cfg.GetConfig()["lastfmsecret"] == "" {
		cfg.SetConfig("lastfmsecret", common.GetStripEnv("LASTFM_SECRET"))
	}
}

type LastFmWrapper struct {
	LastFmKey    string
	LastFmSecret string
}

func (lfw *LastFmWrapper) LastfmArtist(artist string) (summary, artist_url, artist_corrected, image_url string) {
	var tags string
	lastfm_api := lastfm.New(lfw.LastFmKey, lfw.LastFmSecret)
	r, err := lastfm_api.Artist.GetInfo(lastfm.P{"artist": artist})
	summary = "An error occured while processing your request"
	if err == nil {
		for idx, tag := range r.Tags {
			if idx == 0 {
				tags = tag.Name
			} else {
				tags += fmt.Sprintf(", %s", tag.Name)
			}
		}

		for _, img := range r.Images {
			if img.Size == "large" {
				image_url = img.Url
				break
			}
		}

		summary = fmt.Sprintf("%s\n\nTags: %s\n", r.Bio.Summary, tags)
		artist_url = r.Url
		r, err := lastfm_api.Artist.GetCorrection(lastfm.P{"artist": artist})
		artist_corrected = artist
		if err == nil {
			artist_corrected = r.Correction.Artist.Name
		}
	}
	return
}

func (lfw *LastFmWrapper) LastfmTag(tag string) (result string) {
	var artists string
	lastfm_api := lastfm.New(lfw.LastFmKey, lfw.LastFmSecret)
	r, err := lastfm_api.Tag.GetTopArtists(lastfm.P{"tag": tag})
	result = "An error occured while processing your request"
	if err == nil {
		for idx, artist := range r.Artists {
			if idx == 0 {
				artists = artist.Name
			} else {
				artists += fmt.Sprintf(", %s", artist.Name)
			}
		}
		if artists != "" {
			result = fmt.Sprintf("Artists: %s\n", artists)
		}
	}
	return
}

func (lfw *LastFmWrapper) LastfmUser(user string) (result string) {
	lastfm_api := lastfm.New(lfw.LastFmKey, lfw.LastFmSecret)
	r, err := lastfm_api.User.GetInfo(lastfm.P{"user": user})
	result = "An error occured while processing your request"
	if err == nil {
		result = fmt.Sprintf("Profile information for: %s\n", r.Url)
		result += fmt.Sprintf("Play count: %+v track(s)\n", r.PlayCount)
		result += fmt.Sprintf("\nTop artists:\n")
		r2, _ := lastfm_api.User.GetTopArtists(lastfm.P{"user": user, "limit": 10})
		for idx, artist := range r2.Artists {
			result += fmt.Sprintf("%+v - %s - %s play(s)\n", idx+1, artist.Name, artist.PlayCount)
		}
		result += fmt.Sprintf("\nTop tracks:\n")
		r3, _ := lastfm_api.User.GetTopTracks(lastfm.P{"user": user, "limit": 10})
		for idx, track := range r3.Tracks {
			result += fmt.Sprintf("%+v - %s - %s - %s play(s)\n", idx+1, track.Artist.Name, track.Name, track.PlayCount)
		}
	}
	return
}

func LastFmProcessMessage(api *torpedo_registry.BotAPI, channel interface{}, incoming_message string) {
	var message string
	var richmsg torpedo_registry.RichMessage
	lfm := &LastFmWrapper{LastFmKey: torpedo_registry.Config.GetConfig()["lastfmkey"],
					      LastFmSecret: torpedo_registry.Config.GetConfig()["lastfmsecret"]}
	help := fmt.Sprintf("Usage: %slastfm command\nAvailable commands: artist, tag, user", api.CommandPrefix)
	command := strings.Split(strings.TrimSpace(strings.TrimLeft(incoming_message, fmt.Sprintf("%slastfm", api.CommandPrefix))), " ")[0]

	switch command {
	case "artist":
		artist := strings.TrimSpace(strings.TrimPrefix(incoming_message, fmt.Sprintf("%slastfm %s", api.CommandPrefix, command)))
		if artist != "" {
			summary, artist_url, artist_corrected, image_url := lfm.LastfmArtist(artist)
			richmsg = torpedo_registry.RichMessage{BarColor: "#36a64f",
				Text:      summary,
				Title:     artist_corrected,
				TitleLink: artist_url,
				ImageURL:  image_url}
		} else {
			message = fmt.Sprintf("Please supply artist: %slastfm artist artist_name", api.CommandPrefix)
		}
	case "tag":
		tag := strings.TrimSpace(strings.TrimPrefix(incoming_message, fmt.Sprintf("%slastfm %s", api.CommandPrefix, command)))
		if tag != "" {
			message = lfm.LastfmTag(tag)
		} else {
			message = fmt.Sprintf("Please supply tag: %slastfm tag tag_name", api.CommandPrefix)
		}
	case "user":
		user := strings.TrimSpace(strings.TrimPrefix(incoming_message, fmt.Sprintf("%slastfm %s", api.CommandPrefix, command)))
		if user != "" {
			message = lfm.LastfmUser(user)
		} else {
			message = fmt.Sprintf("Please supply user name: %slastfm user user_name", api.CommandPrefix)
		}
	default:
		message = help
	}

	api.Bot.PostMessage(channel, message, api, richmsg)
}

func init() {
	torpedo_registry.Config.RegisterHelpAndHandler("lastfm", "Query Last.FM for artist, tag, user", LastFmProcessMessage)
	torpedo_registry.Config.RegisterParser("lastfm", ConfigureLastFmPlugin, ParseLastFmPlugin)
}
<commit_msg>forked last.fm repo, until issue is fixed by author<commit_after>package torpedo_lastfm_plugin

import (
	"flag"
	"fmt"
	"strings"

	common "github.com/tb0hdan/torpedo_common"
	"github.com/tb0hdan/torpedo_registry"

	// "github.com/shkh/lastfm-go/lastfm"
	"github.com/tb0hdan/lastfm-go/lastfm"
)

var (
	LastFmKey *string
	LastFmSecret *string
)

func ConfigureLastFmPlugin(cfg *torpedo_registry.ConfigStruct) {
	LastFmKey = flag.String("lastfm_key", "", "Last.FM API Key")
	LastFmSecret = flag.String("lastfm_secret", "", "Last.FM API Secret")

}

func ParseLastFmPlugin(cfg *torpedo_registry.ConfigStruct) {
	cfg.SetConfig("lastfmkey", *LastFmKey)
	cfg.SetConfig("lastfmsecret", *LastFmSecret)
	if cfg.GetConfig()["lastfmkey"] == "" {
		cfg.SetConfig("lastfmkey", common.GetStripEnv("LASTFM_KEY"))
	}
	if cfg.GetConfig()["lastfmsecret"] == "" {
		cfg.SetConfig("lastfmsecret", common.GetStripEnv("LASTFM_SECRET"))
	}
}

type LastFmWrapper struct {
	LastFmKey    string
	LastFmSecret string
}

func (lfw *LastFmWrapper) LastfmArtist(artist string) (summary, artist_url, artist_corrected, image_url string) {
	var tags string
	lastfm_api := lastfm.New(lfw.LastFmKey, lfw.LastFmSecret)
	r, err := lastfm_api.Artist.GetInfo(lastfm.P{"artist": artist})
	summary = "An error occured while processing your request"
	if err == nil {
		for idx, tag := range r.Tags {
			if idx == 0 {
				tags = tag.Name
			} else {
				tags += fmt.Sprintf(", %s", tag.Name)
			}
		}

		for _, img := range r.Images {
			if img.Size == "large" {
				image_url = img.Url
				break
			}
		}

		summary = fmt.Sprintf("%s\n\nTags: %s\n", r.Bio.Summary, tags)
		artist_url = r.Url
		r, err := lastfm_api.Artist.GetCorrection(lastfm.P{"artist": artist})
		artist_corrected = artist
		if err == nil {
			artist_corrected = r.Correction.Artist.Name
		}
	}
	return
}

func (lfw *LastFmWrapper) LastfmTag(tag string) (result string) {
	var artists string
	lastfm_api := lastfm.New(lfw.LastFmKey, lfw.LastFmSecret)
	r, err := lastfm_api.Tag.GetTopArtists(lastfm.P{"tag": tag})
	result = "An error occured while processing your request"
	if err == nil {
		for idx, artist := range r.Artists {
			if idx == 0 {
				artists = artist.Name
			} else {
				artists += fmt.Sprintf(", %s", artist.Name)
			}
		}
		if artists != "" {
			result = fmt.Sprintf("Artists: %s\n", artists)
		}
	}
	return
}

func (lfw *LastFmWrapper) LastfmUser(user string) (result string) {
	lastfm_api := lastfm.New(lfw.LastFmKey, lfw.LastFmSecret)
	r, err := lastfm_api.User.GetInfo(lastfm.P{"user": user})
	result = "An error occured while processing your request"
	if err == nil {
		result = fmt.Sprintf("Profile information for: %s\n", r.Url)
		result += fmt.Sprintf("Play count: %+v track(s)\n", r.PlayCount)
		result += fmt.Sprintf("\nTop artists:\n")
		r2, _ := lastfm_api.User.GetTopArtists(lastfm.P{"user": user, "limit": 10})
		for idx, artist := range r2.Artists {
			result += fmt.Sprintf("%+v - %s - %s play(s)\n", idx+1, artist.Name, artist.PlayCount)
		}
		result += fmt.Sprintf("\nTop tracks:\n")
		r3, _ := lastfm_api.User.GetTopTracks(lastfm.P{"user": user, "limit": 10})
		for idx, track := range r3.Tracks {
			result += fmt.Sprintf("%+v - %s - %s - %s play(s)\n", idx+1, track.Artist.Name, track.Name, track.PlayCount)
		}
	}
	return
}

func LastFmProcessMessage(api *torpedo_registry.BotAPI, channel interface{}, incoming_message string) {
	var message string
	var richmsg torpedo_registry.RichMessage
	lfm := &LastFmWrapper{LastFmKey: torpedo_registry.Config.GetConfig()["lastfmkey"],
					      LastFmSecret: torpedo_registry.Config.GetConfig()["lastfmsecret"]}
	help := fmt.Sprintf("Usage: %slastfm command\nAvailable commands: artist, tag, user", api.CommandPrefix)
	command := strings.Split(strings.TrimSpace(strings.TrimLeft(incoming_message, fmt.Sprintf("%slastfm", api.CommandPrefix))), " ")[0]

	switch command {
	case "artist":
		artist := strings.TrimSpace(strings.TrimPrefix(incoming_message, fmt.Sprintf("%slastfm %s", api.CommandPrefix, command)))
		if artist != "" {
			summary, artist_url, artist_corrected, image_url := lfm.LastfmArtist(artist)
			richmsg = torpedo_registry.RichMessage{BarColor: "#36a64f",
				Text:      summary,
				Title:     artist_corrected,
				TitleLink: artist_url,
				ImageURL:  image_url}
		} else {
			message = fmt.Sprintf("Please supply artist: %slastfm artist artist_name", api.CommandPrefix)
		}
	case "tag":
		tag := strings.TrimSpace(strings.TrimPrefix(incoming_message, fmt.Sprintf("%slastfm %s", api.CommandPrefix, command)))
		if tag != "" {
			message = lfm.LastfmTag(tag)
		} else {
			message = fmt.Sprintf("Please supply tag: %slastfm tag tag_name", api.CommandPrefix)
		}
	case "user":
		user := strings.TrimSpace(strings.TrimPrefix(incoming_message, fmt.Sprintf("%slastfm %s", api.CommandPrefix, command)))
		if user != "" {
			message = lfm.LastfmUser(user)
		} else {
			message = fmt.Sprintf("Please supply user name: %slastfm user user_name", api.CommandPrefix)
		}
	default:
		message = help
	}

	api.Bot.PostMessage(channel, message, api, richmsg)
}

func init() {
	torpedo_registry.Config.RegisterHelpAndHandler("lastfm", "Query Last.FM for artist, tag, user", LastFmProcessMessage)
	torpedo_registry.Config.RegisterParser("lastfm", ConfigureLastFmPlugin, ParseLastFmPlugin)
}
<|endoftext|>


<commit_before>/**
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *  http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */

package cli

import (
	"io/ioutil"
	"os"
	"path"
	"regexp"
	"strings"

	"github.com/spf13/cobra"
	"mynewt.apache.org/newt/newt/interfaces"
	"mynewt.apache.org/newt/newt/newtutil"
	"mynewt.apache.org/newt/newt/project"
	"mynewt.apache.org/newt/util"
)

var NewTypeStr = "pkg"

func pkgNewCmd(cmd *cobra.Command, args []string) {
	NewTypeStr = strings.ToUpper(NewTypeStr)

	pw := project.NewPackageWriter()
	if err := pw.ConfigurePackage(NewTypeStr, args[0]); err != nil {
		NewtUsage(cmd, err)
	}
	if err := pw.WritePackage(); err != nil {
		NewtUsage(cmd, err)
	}
}

func pkgMoveCmd(cmd *cobra.Command, args []string) {
	if len(args) != 2 {
		NewtUsage(cmd, util.NewNewtError("Exactly two arguments required to pkg move"))
	}

	srcLoc := args[0]
	dstLoc := args[1]

	proj := TryGetProject()
	interfaces.SetProject(proj)

	wd, err := os.Getwd()
	if err != nil {
		NewtUsage(cmd, util.NewNewtError(err.Error()))
	}

	if err := os.Chdir(proj.Path() + "/"); err != nil {
		NewtUsage(cmd, util.NewNewtError(err.Error()))
	}

	/* Find source package, defaulting search to the local project if no
	 * repository descriptor is found.
	 */
	srcRepoName, srcName, err := newtutil.ParsePackageString(srcLoc)
	if err != nil {
		os.Chdir(wd)
		NewtUsage(cmd, err)
	}

	srcRepo := proj.LocalRepo()
	if srcRepoName != "" {
		srcRepo = proj.FindRepo(srcRepoName)
	}

	srcPkg, err := proj.ResolvePackage(srcRepo, srcName)
	if err != nil {
		os.Chdir(wd)
		NewtUsage(cmd, err)
	}

	/* Resolve the destination package to a physical location, and then
	 * move the source package to that location.
	 * dstLoc is assumed to be in the format "@repo/pkg/loc"
	 */
	repoName, pkgName, err := newtutil.ParsePackageString(dstLoc)
	if err != nil {
		os.Chdir(wd)
		NewtUsage(cmd, err)
	}

	dstPath := proj.Path() + "/"
	repo := proj.LocalRepo()
	if repoName != "" {
		dstPath += "repos/" + repoName + "/"
		repo = proj.FindRepo(repoName)
		if repo == nil {
			os.Chdir(wd)
			NewtUsage(cmd, util.NewNewtError("Destination repo "+
				repoName+" does not exist"))
		}
	}
	dstPath += pkgName + "/"

	if util.NodeExist(dstPath) {
		os.Chdir(wd)
		NewtUsage(cmd, util.NewNewtError("Cannot overwrite existing package, "+
			"use pkg delete first"))
	}

	util.StatusMessage(util.VERBOSITY_DEFAULT, "Moving package %s to %s\n",
		srcLoc, dstLoc)

	if err := util.MoveDir(srcPkg.BasePath(), dstPath); err != nil {
		os.Chdir(wd)
		NewtUsage(cmd, err)
	}

	/* Replace the package name in the pkg.yml file */
	pkgData, err := ioutil.ReadFile(dstPath + "/pkg.yml")
	if err != nil {
		os.Chdir(wd)
		NewtUsage(cmd, err)
	}

	re := regexp.MustCompile(regexp.QuoteMeta(srcName))
	res := re.ReplaceAllString(string(pkgData), pkgName)

	if err := ioutil.WriteFile(dstPath+"/pkg.yml", []byte(res), 0666); err != nil {
		NewtUsage(cmd, util.ChildNewtError(err))
	}

	/* If the last element of the package path changes, rename the include
	 * directory.
	 */
	if path.Base(pkgName) != path.Base(srcPkg.Name()) {
		util.MoveDir(dstPath+"/include/"+path.Base(srcPkg.Name()),
			dstPath+"/include/"+path.Base(pkgName))
	}

	os.Chdir(wd)
}

func AddPackageCommands(cmd *cobra.Command) {
	/* Add the base package command, on top of which other commands are
	 * keyed
	 */
	pkgHelpText := "Commands for creating and manipulating packages"
	pkgHelpEx := "newt pkg new --type=pkg libs/mylib"

	pkgCmd := &cobra.Command{
		Use:     "pkg",
		Short:   "Create and manage packages in the current workspace",
		Long:    pkgHelpText,
		Example: pkgHelpEx,
		Run: func(cmd *cobra.Command, args []string) {
			cmd.Help()
		},
	}

	cmd.AddCommand(pkgCmd)

	/* Package new command, create a new package */
	newCmdHelpText := ""
	newCmdHelpEx := ""

	newCmd := &cobra.Command{
		Use:     "new",
		Short:   "Create a new package, from a template",
		Long:    newCmdHelpText,
		Example: newCmdHelpEx,
		Run:     pkgNewCmd,
	}

	newCmd.PersistentFlags().StringVarP(&NewTypeStr, "type", "t",
		"pkg", "Type of package to create: pkg, bsp, sdk.  Default pkg.")

	pkgCmd.AddCommand(newCmd)

	moveCmdHelpText := ""
	moveCmdHelpEx := ""

	moveCmd := &cobra.Command{
		Use:     "move",
		Short:   "Move a package from one location to another",
		Long:    moveCmdHelpText,
		Example: moveCmdHelpEx,
		Run:     pkgMoveCmd,
	}

	pkgCmd.AddCommand(moveCmd)
}
<commit_msg>add the pkg remove command to newt<commit_after>/**
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *  http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */

package cli

import (
	"io/ioutil"
	"os"
	"path"
	"regexp"
	"strings"

	"github.com/spf13/cobra"
	"mynewt.apache.org/newt/newt/interfaces"
	"mynewt.apache.org/newt/newt/newtutil"
	"mynewt.apache.org/newt/newt/pkg"
	"mynewt.apache.org/newt/newt/project"
	"mynewt.apache.org/newt/util"
)

var NewTypeStr = "pkg"

func pkgNewCmd(cmd *cobra.Command, args []string) {
	NewTypeStr = strings.ToUpper(NewTypeStr)

	pw := project.NewPackageWriter()
	if err := pw.ConfigurePackage(NewTypeStr, args[0]); err != nil {
		NewtUsage(cmd, err)
	}
	if err := pw.WritePackage(); err != nil {
		NewtUsage(cmd, err)
	}
}

func pkgMoveCmd(cmd *cobra.Command, args []string) {
	if len(args) != 2 {
		NewtUsage(cmd, util.NewNewtError("Exactly two arguments required to pkg move"))
	}

	srcLoc := args[0]
	dstLoc := args[1]

	proj := TryGetProject()
	interfaces.SetProject(proj)

	wd, err := os.Getwd()
	if err != nil {
		NewtUsage(cmd, util.ChildNewtError(err))
	}

	if err := os.Chdir(proj.Path() + "/"); err != nil {
		NewtUsage(cmd, util.ChildNewtError(err))
	}

	/* Find source package, defaulting search to the local project if no
	 * repository descriptor is found.
	 */
	srcRepoName, srcName, err := newtutil.ParsePackageString(srcLoc)
	if err != nil {
		os.Chdir(wd)
		NewtUsage(cmd, err)
	}

	srcRepo := proj.LocalRepo()
	if srcRepoName != "" {
		srcRepo = proj.FindRepo(srcRepoName)
	}

	srcPkg, err := proj.ResolvePackage(srcRepo, srcName)
	if err != nil {
		os.Chdir(wd)
		NewtUsage(cmd, err)
	}

	/* Resolve the destination package to a physical location, and then
	 * move the source package to that location.
	 * dstLoc is assumed to be in the format "@repo/pkg/loc"
	 */
	repoName, pkgName, err := newtutil.ParsePackageString(dstLoc)
	if err != nil {
		os.Chdir(wd)
		NewtUsage(cmd, err)
	}

	dstPath := proj.Path() + "/"
	repo := proj.LocalRepo()
	if repoName != "" {
		dstPath += "repos/" + repoName + "/"
		repo = proj.FindRepo(repoName)
		if repo == nil {
			os.Chdir(wd)
			NewtUsage(cmd, util.NewNewtError("Destination repo "+
				repoName+" does not exist"))
		}
	}
	dstPath += pkgName + "/"

	if util.NodeExist(dstPath) {
		os.Chdir(wd)
		NewtUsage(cmd, util.NewNewtError("Cannot overwrite existing package, "+
			"use pkg delete first"))
	}

	util.StatusMessage(util.VERBOSITY_DEFAULT, "Moving package %s to %s\n",
		srcLoc, dstLoc)

	if err := util.MoveDir(srcPkg.BasePath(), dstPath); err != nil {
		os.Chdir(wd)
		NewtUsage(cmd, err)
	}

	/* Replace the package name in the pkg.yml file */
	pkgData, err := ioutil.ReadFile(dstPath + "/pkg.yml")
	if err != nil {
		os.Chdir(wd)
		NewtUsage(cmd, err)
	}

	re := regexp.MustCompile(regexp.QuoteMeta(srcName))
	res := re.ReplaceAllString(string(pkgData), pkgName)

	if err := ioutil.WriteFile(dstPath+"/pkg.yml", []byte(res), 0666); err != nil {
		NewtUsage(cmd, util.ChildNewtError(err))
	}

	/* If the last element of the package path changes, rename the include
	 * directory.
	 */
	if path.Base(pkgName) != path.Base(srcPkg.Name()) {
		util.MoveDir(dstPath+"/include/"+path.Base(srcPkg.Name()),
			dstPath+"/include/"+path.Base(pkgName))
	}

	os.Chdir(wd)
}

func pkgRemoveCmd(cmd *cobra.Command, args []string) {
	if len(args) != 1 {
		NewtUsage(cmd, util.NewNewtError("Must specify a package name to delete"))
	}

	proj := TryGetProject()
	interfaces.SetProject(proj)

	wd, err := os.Getwd()
	if err != nil {
		NewtUsage(cmd, util.ChildNewtError(err))
	}

	if err := os.Chdir(proj.Path() + "/"); err != nil {
		NewtUsage(cmd, util.ChildNewtError(err))
	}
	/* Resolve package, and get path from package to ensure we're being asked
	 * to remove a valid path.
	 */
	repoName, pkgName, err := newtutil.ParsePackageString(args[0])
	if err != nil {
		os.Chdir(wd)
		NewtUsage(cmd, err)
	}

	repo := proj.LocalRepo()
	if repoName != "" {
		repo = proj.FindRepo(repoName)
		if repo == nil {
			os.Chdir(wd)
			NewtUsage(cmd, util.NewNewtError("Destination repo "+
				repoName+" does not exist"))
		}
	}

	pkg, err := pkg.LoadLocalPackage(repo, pkgName)
	if err != nil {
		os.Chdir(wd)
		NewtUsage(cmd, err)
	}

	util.StatusMessage(util.VERBOSITY_DEFAULT, "Removing package %s\n",
		args[0])

	if err := os.RemoveAll(pkg.BasePath()); err != nil {
		os.Chdir(wd)
		NewtUsage(cmd, util.ChildNewtError(err))
	}

	os.Chdir(wd)
}

func AddPackageCommands(cmd *cobra.Command) {
	/* Add the base package command, on top of which other commands are
	 * keyed
	 */
	pkgHelpText := "Commands for creating and manipulating packages"
	pkgHelpEx := "  newt pkg new --type=pkg libs/mylib"

	pkgCmd := &cobra.Command{
		Use:     "pkg",
		Short:   "Create and manage packages in the current workspace",
		Long:    pkgHelpText,
		Example: pkgHelpEx,
		Run: func(cmd *cobra.Command, args []string) {
			cmd.Help()
		},
	}

	cmd.AddCommand(pkgCmd)

	/* Package new command, create a new package */
	newCmdHelpText := ""
	newCmdHelpEx := ""

	newCmd := &cobra.Command{
		Use:     "new",
		Short:   "Create a new package, from a template",
		Long:    newCmdHelpText,
		Example: newCmdHelpEx,
		Run:     pkgNewCmd,
	}

	newCmd.PersistentFlags().StringVarP(&NewTypeStr, "type", "t",
		"pkg", "Type of package to create: pkg, bsp, sdk.  Default pkg.")

	pkgCmd.AddCommand(newCmd)

	moveCmdHelpText := ""
	moveCmdHelpEx := ""

	moveCmd := &cobra.Command{
		Use:     "move",
		Short:   "Move a package from one location to another",
		Long:    moveCmdHelpText,
		Example: moveCmdHelpEx,
		Run:     pkgMoveCmd,
	}

	pkgCmd.AddCommand(moveCmd)

	removeCmdHelpText := ""
	removeCmdHelpEx := ""

	removeCmd := &cobra.Command{
		Use:     "remove",
		Short:   "Remove a package",
		Long:    removeCmdHelpText,
		Example: removeCmdHelpEx,
		Run:     pkgRemoveCmd,
	}

	pkgCmd.AddCommand(removeCmd)
}
<|endoftext|>


<commit_before>package metadata

import (
	"encoding/json"
	"fmt"
	"io/ioutil"
	"os"
	"reflect"
	"time"

	"github.com/mackerelio/mackerel-agent/config"
	"github.com/mackerelio/mackerel-agent/logging"
)

var logger = logging.GetLogger("metadata")

// Generator generates metadata
type Generator struct {
	Name         string
	Config       *config.MetadataPlugin
	Tempfile     string
	PrevMetadata interface{}
}

// Fetch invokes the command and returns the result
func (g *Generator) Fetch() (interface{}, error) {
	message, stderr, exitCode, err := g.Config.Run()

	if err != nil {
		logger.Warningf("Error occurred while executing a metadata plugin %q: %s", g.Name, err.Error())
		return nil, err
	}

	if stderr != "" {
		logger.Warningf("metadata plugin %q outputs stderr: %s", g.Name, stderr)
	}

	if exitCode != 0 {
		return nil, fmt.Errorf("exits with: %d", exitCode)
	}

	var metadata interface{}
	if err := json.Unmarshal([]byte(message), &metadata); err != nil {
		return nil, fmt.Errorf("outputs invalid JSON: %v", message)
	}

	return metadata, nil
}

// Differs returns whether the metadata has been changed or not
func (g *Generator) Differs(metadata interface{}) bool {
	if g.PrevMetadata == nil {
		g.LoadFromFile()
	}
	return !reflect.DeepEqual(g.PrevMetadata, metadata)
}

// Load loads the previous metadata from file
func (g *Generator) LoadFromFile() {
	data, err := ioutil.ReadFile(g.Tempfile)
	if err != nil { // maybe initial state
		return
	}
	var metadata interface{}
	if err := json.Unmarshal(data, &metadata); err != nil {
		logger.Warningf("metadata plugin %q detected a invalid json in temporary file: %s", g.Name, string(data))
		return
	}
	g.PrevMetadata = metadata
}

// Save stores the metadata locally
func (g *Generator) Save(metadata interface{}) error {
	g.PrevMetadata = metadata
	data, err := json.Marshal(metadata)
	if err != nil {
		return fmt.Errorf("failed to marshal the metadata to json: %v %s", metadata, err.Error())
	}
	if err = writeFileAtomically(g.Tempfile, data); err != nil {
		return fmt.Errorf("failed to write the metadata to temporary file: %v %s", metadata, err.Error())
	}
	return nil
}

func writeFileAtomically(f string, contents []byte) error {
	tmpf, err := ioutil.TempFile("", "")
	if err != nil {
		return err
	}
	defer os.Remove(tmpf.Name())
	_, err = tmpf.Write(contents)
	if err != nil {
		return err
	}
	tmpf.Close()
	return os.Rename(tmpf.Name(), f)
}

const defaultExecutionInterval = 10 * time.Minute

// Interval calculates the time interval of command execution
func (g *Generator) Interval() time.Duration {
	if g.Config.ExecutionInterval == nil {
		return defaultExecutionInterval
	}
	interval := time.Duration(*g.Config.ExecutionInterval) * time.Minute
	if interval < 1*time.Minute {
		return 1 * time.Minute
	}
	return interval
}
<commit_msg>improve comment<commit_after>package metadata

import (
	"encoding/json"
	"fmt"
	"io/ioutil"
	"os"
	"reflect"
	"time"

	"github.com/mackerelio/mackerel-agent/config"
	"github.com/mackerelio/mackerel-agent/logging"
)

var logger = logging.GetLogger("metadata")

// Generator generates metadata
type Generator struct {
	Name         string
	Config       *config.MetadataPlugin
	Tempfile     string
	PrevMetadata interface{}
}

// Fetch invokes the command and returns the result
func (g *Generator) Fetch() (interface{}, error) {
	message, stderr, exitCode, err := g.Config.Run()

	if err != nil {
		logger.Warningf("Error occurred while executing a metadata plugin %q: %s", g.Name, err.Error())
		return nil, err
	}

	if stderr != "" {
		logger.Warningf("metadata plugin %q outputs stderr: %s", g.Name, stderr)
	}

	if exitCode != 0 {
		return nil, fmt.Errorf("exits with: %d", exitCode)
	}

	var metadata interface{}
	if err := json.Unmarshal([]byte(message), &metadata); err != nil {
		return nil, fmt.Errorf("outputs invalid JSON: %v", message)
	}

	return metadata, nil
}

// Differs returns whether the metadata has been changed or not
func (g *Generator) Differs(metadata interface{}) bool {
	if g.PrevMetadata == nil {
		g.LoadFromFile()
	}
	return !reflect.DeepEqual(g.PrevMetadata, metadata)
}

// LoadFromFile loads the previous metadata from file
func (g *Generator) LoadFromFile() {
	data, err := ioutil.ReadFile(g.Tempfile)
	if err != nil { // maybe initial state
		return
	}
	var metadata interface{}
	if err := json.Unmarshal(data, &metadata); err != nil {
		logger.Warningf("metadata plugin %q detected a invalid json in temporary file: %s", g.Name, string(data))
		return
	}
	g.PrevMetadata = metadata
}

// Save stores the metadata locally
func (g *Generator) Save(metadata interface{}) error {
	g.PrevMetadata = metadata
	data, err := json.Marshal(metadata)
	if err != nil {
		return fmt.Errorf("failed to marshal the metadata to json: %v %s", metadata, err.Error())
	}
	if err = writeFileAtomically(g.Tempfile, data); err != nil {
		return fmt.Errorf("failed to write the metadata to temporary file: %v %s", metadata, err.Error())
	}
	return nil
}

func writeFileAtomically(f string, contents []byte) error {
	tmpf, err := ioutil.TempFile("", "")
	if err != nil {
		return err
	}
	defer os.Remove(tmpf.Name())
	_, err = tmpf.Write(contents)
	if err != nil {
		return err
	}
	tmpf.Close()
	return os.Rename(tmpf.Name(), f)
}

const defaultExecutionInterval = 10 * time.Minute

// Interval calculates the time interval of command execution
func (g *Generator) Interval() time.Duration {
	if g.Config.ExecutionInterval == nil {
		return defaultExecutionInterval
	}
	interval := time.Duration(*g.Config.ExecutionInterval) * time.Minute
	if interval < 1*time.Minute {
		return 1 * time.Minute
	}
	return interval
}
<|endoftext|>


<commit_before>// Package astcontext provides context aware utilities to be used within
// editors.
package astcontext

import (
	"errors"
	"fmt"
	"go/ast"
	"go/parser"
	"go/token"
)

// Func represents a declared (*ast.FuncDecl) or an anonymous (*ast.FuncLit) Go
// function
type Func struct {
	FuncPos token.Position `json:"funcPos"` // position of the "func" keyword
	Lbrace  token.Position `json:"lbrace"`  // position of "{"
	Rbrace  token.Position `json:"rbrace"`  // position of "}"

	node ast.Node // either *ast.FuncDecl or *ast.FuncLit
}

func (f *Func) String() string {
	return fmt.Sprintf("{'func': {'line': '%d', 'col':'%d'}, 'lbrace': {'line': '%d', 'col':'%d'}, 'rbrace': {'line': '%d', 'col':'%d'}}",
		f.FuncPos.Line, f.FuncPos.Column, f.Lbrace.Line, f.Lbrace.Column, f.Rbrace.Line, f.Rbrace.Column)

}

// EnclosingFunc returns the enclosing Func for the given offset from the src.
// Src needs to be a valid Go source file content.
func EnclosingFunc(src []byte, offset int) (*Func, error) {
	funcs, err := ParseFuncs(src)
	if err != nil {
		return nil, err
	}

	return enclosingFunc(funcs, offset)
}

// EnclosingFuncFile returns the enclosing *Func for the given offset from the
// filename. File needs to be a valid Go source file.
func EnclosingFuncFile(filename string, offset int) (*Func, error) {
	funcs, err := ParseFuncsFile(filename)
	if err != nil {
		return nil, err
	}

	return enclosingFunc(funcs, offset)
}

// ParseFuncsFile returns a list of Func's from the given filename. The list of
// Func's are sorted according to the order of Go functions in the given
// filename.
func ParseFuncsFile(filename string) ([]*Func, error) {
	fset := token.NewFileSet() // positions are relative to fset
	f, err := parser.ParseFile(fset, filename, nil, 0)
	if err != nil {
		return nil, err
	}
	return parseFuncs(fset, f), nil
}

// ParseFuncs returns a list of Func's from the given src. The list of Func's
// are sorted according to the order of Go functions in the given src.
func ParseFuncs(src []byte) ([]*Func, error) {
	fset := token.NewFileSet() // positions are relative to fset
	f, err := parser.ParseFile(fset, "src.go", src, 0)
	if err != nil {
		return nil, err
	}

	return parseFuncs(fset, f), nil
}

func parseFuncs(fset *token.FileSet, f ast.Node) []*Func {
	var funcs []*Func

	// Inspect the AST and find all function declarements and literals
	ast.Inspect(f, func(n ast.Node) bool {
		switch x := n.(type) {
		case *ast.FuncDecl:
			funcs = append(funcs, &Func{
				Lbrace:  fset.Position(x.Body.Lbrace),
				Rbrace:  fset.Position(x.Body.Rbrace),
				FuncPos: fset.Position(x.Type.Func),
				node:    x,
			})
		case *ast.FuncLit:
			funcs = append(funcs, &Func{
				Lbrace:  fset.Position(x.Body.Lbrace),
				Rbrace:  fset.Position(x.Body.Rbrace),
				FuncPos: fset.Position(x.Type.Func),
				node:    x,
			})
		}
		return true
	})

	return funcs
}

func enclosingFunc(funcs []*Func, offset int) (*Func, error) {
	var encFunc *Func
	for _, fn := range funcs {
		start := fn.Lbrace.Offset
		end := fn.Rbrace.Offset
		if start <= offset && offset <= end {
			encFunc = fn
		}
	}

	if encFunc == nil {
		return &Func{}, errors.New("no enclosing functions found")
	}

	return encFunc, nil
}
<commit_msg>Remvoe whitespace<commit_after>// Package astcontext provides context aware utilities to be used within
// editors.
package astcontext

import (
	"errors"
	"fmt"
	"go/ast"
	"go/parser"
	"go/token"
)

// Func represents a declared (*ast.FuncDecl) or an anonymous (*ast.FuncLit) Go
// function
type Func struct {
	FuncPos token.Position `json:"funcPos"` // position of the "func" keyword
	Lbrace  token.Position `json:"lbrace"`  // position of "{"
	Rbrace  token.Position `json:"rbrace"`  // position of "}"

	node ast.Node // either *ast.FuncDecl or *ast.FuncLit
}

func (f *Func) String() string {
	return fmt.Sprintf("{'func': {'line': '%d', 'col':'%d'}, 'lbrace': {'line': '%d', 'col':'%d'}, 'rbrace': {'line': '%d', 'col':'%d'}}",
		f.FuncPos.Line, f.FuncPos.Column, f.Lbrace.Line, f.Lbrace.Column, f.Rbrace.Line, f.Rbrace.Column)
}

// EnclosingFunc returns the enclosing Func for the given offset from the src.
// Src needs to be a valid Go source file content.
func EnclosingFunc(src []byte, offset int) (*Func, error) {
	funcs, err := ParseFuncs(src)
	if err != nil {
		return nil, err
	}

	return enclosingFunc(funcs, offset)
}

// EnclosingFuncFile returns the enclosing *Func for the given offset from the
// filename. File needs to be a valid Go source file.
func EnclosingFuncFile(filename string, offset int) (*Func, error) {
	funcs, err := ParseFuncsFile(filename)
	if err != nil {
		return nil, err
	}

	return enclosingFunc(funcs, offset)
}

// ParseFuncsFile returns a list of Func's from the given filename. The list of
// Func's are sorted according to the order of Go functions in the given
// filename.
func ParseFuncsFile(filename string) ([]*Func, error) {
	fset := token.NewFileSet() // positions are relative to fset
	f, err := parser.ParseFile(fset, filename, nil, 0)
	if err != nil {
		return nil, err
	}
	return parseFuncs(fset, f), nil
}

// ParseFuncs returns a list of Func's from the given src. The list of Func's
// are sorted according to the order of Go functions in the given src.
func ParseFuncs(src []byte) ([]*Func, error) {
	fset := token.NewFileSet() // positions are relative to fset
	f, err := parser.ParseFile(fset, "src.go", src, 0)
	if err != nil {
		return nil, err
	}

	return parseFuncs(fset, f), nil
}

func parseFuncs(fset *token.FileSet, f ast.Node) []*Func {
	var funcs []*Func

	// Inspect the AST and find all function declarements and literals
	ast.Inspect(f, func(n ast.Node) bool {
		switch x := n.(type) {
		case *ast.FuncDecl:
			funcs = append(funcs, &Func{
				Lbrace:  fset.Position(x.Body.Lbrace),
				Rbrace:  fset.Position(x.Body.Rbrace),
				FuncPos: fset.Position(x.Type.Func),
				node:    x,
			})
		case *ast.FuncLit:
			funcs = append(funcs, &Func{
				Lbrace:  fset.Position(x.Body.Lbrace),
				Rbrace:  fset.Position(x.Body.Rbrace),
				FuncPos: fset.Position(x.Type.Func),
				node:    x,
			})
		}
		return true
	})

	return funcs
}

func enclosingFunc(funcs []*Func, offset int) (*Func, error) {
	var encFunc *Func
	for _, fn := range funcs {
		start := fn.Lbrace.Offset
		end := fn.Rbrace.Offset
		if start <= offset && offset <= end {
			encFunc = fn
		}
	}

	if encFunc == nil {
		return &Func{}, errors.New("no enclosing functions found")
	}

	return encFunc, nil
}
<|endoftext|>


<commit_before>package atomas

func CreateElementGenerator(rand func() int) func(int) int {
	return func(round int) int {
		return rand() % 3 + 1
	}
}<commit_msg>random element generator with small logic<commit_after>package atomas

func CreateElementGenerator(rand func() int) func(int) int {
	return func(round int) int {
		if (round == 0) {
			return rand() % 3 + 1
		}else {
			return rand() % 4
		}
	}
}<|endoftext|>


<commit_before>// Copyright (c) 2003-2005 Maxim Sobolev. All rights reserved.
// Copyright (c) 2006-2014 Sippy Software, Inc. All rights reserved.
// Copyright (c) 2016 Andriy Pylypenko. All rights reserved.
//
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without modification,
// are permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice, this
// list of conditions and the following disclaimer.
//
// 2. Redistributions in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation and/or
// other materials provided with the distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
// ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
package sippy

import (
    "crypto/rand"
    "errors"
    "fmt"
    "math/big"
    "runtime"
    "sync"

    "sippy/conf"
    "sippy/net"
    "sippy/sdp"
    "sippy/types"
)

type Rtp_proxy_session struct {
    caller_session_exists   bool
    call_id                 string
    from_tag                string
    to_tag                  string
    _rtp_proxy_client       sippy_types.RtpProxyClient
    max_index               int
    l4r                     *local4remote
    notify_socket           string
    notify_tag              string
    insert_nortpp           bool
    caller                  _rtpps_side
    callee                  _rtpps_side
    session_lock            sync.Locker
    config                  sippy_conf.Config
    inflight_lock           sync.Mutex
    inflight_cmd            *rtpp_cmd
    rtpp_wi                 chan *rtpp_cmd
}

type rtpproxy_update_result struct {
    rtpproxy_address    string
    rtpproxy_port       string
    family              string
    sendonly            bool
}

type rtpp_cmd struct {
    cmd         string
    cb          func(string)
    rtp_proxy_client sippy_types.RtpProxyClient
}

func (self *rtpproxy_update_result) Address() string {
    return self.rtpproxy_address
}

func NewRtp_proxy_session(config sippy_conf.Config, rtp_proxy_clients []sippy_types.RtpProxyClient, call_id, from_tag, to_tag, notify_socket, notify_tag string, session_lock sync.Locker, callee_origin *sippy_sdp.SdpOrigin) (*Rtp_proxy_session, error) {
    self := &Rtp_proxy_session{
        notify_socket   : notify_socket,
        notify_tag      : notify_tag,
        call_id         : call_id,
        from_tag        : from_tag,
        to_tag          : to_tag,
        insert_nortpp   : false,
        max_index       : -1,
        session_lock    : session_lock,
        config          : config,
        rtpp_wi         : make(chan *rtpp_cmd, 50),
    }
    self.caller.otherside = &self.callee
    self.callee.otherside = &self.caller
    self.caller.owner = self
    self.callee.owner = self
    self.caller.session_exists = false
    self.callee.session_exists = false
    // RFC4566
    // *******
    // For privacy reasons, it is sometimes desirable to obfuscate the
    // username and IP address of the session originator.  If this is a
    // concern, an arbitrary <username> and private <unicast-address> MAY be
    // chosen to populate the "o=" field, provided that these are selected
    // in a manner that does not affect the global uniqueness of the field.
    // *******
    addr := "192.0.2.1" // 192.0.2.0/24 (TEST-NET-1)
    self.caller.origin, _ = sippy_sdp.NewSdpOrigin(addr)
    if callee_origin != nil {
        self.callee.origin = callee_origin.GetCopy()
        // New session means new RTP port so the SDP is now different and the SDP
        // version must be increased.
        self.callee.origin.IncVersion()
    } else {
        self.callee.origin, _ = sippy_sdp.NewSdpOrigin(addr)
    }
    online_clients := []sippy_types.RtpProxyClient{}
    for _, cl := range rtp_proxy_clients {
        if cl.IsOnline() {
            online_clients = append(online_clients, cl)
        }
    }
    n := len(online_clients)
    if n == 0 {
        return nil, fmt.Errorf("No online RTP proxy client has been found")
    }
    idx, err := rand.Int(rand.Reader, big.NewInt(int64(n)))
    if err != nil {
        self._rtp_proxy_client = online_clients[0]
    } else {
        self._rtp_proxy_client = online_clients[idx.Int64()]
    }
    if self.call_id == "" {
        buf := make([]byte, 16)
        rand.Read(buf)
        self.call_id = fmt.Sprintf("%x", buf)
    }
    if from_tag == "" {
        buf := make([]byte, 16)
        rand.Read(buf)
        self.from_tag = fmt.Sprintf("%x", buf)
    }
    if to_tag == "" {
        buf := make([]byte, 16)
        rand.Read(buf)
        self.to_tag = fmt.Sprintf("%x", buf)
    }
    runtime.SetFinalizer(self, rtp_proxy_session_destructor)
    return self, nil
}
/*
    def version(self, result_callback):
        self.send_command("V", self.version_result, result_callback)

    def version_result(self, result, result_callback):
        result_callback(result)
*/
func (self *Rtp_proxy_session) PlayCaller(prompt_name string, times int/*= 1*/, result_callback func(string)/*= nil*/, index int /*= 0*/) {
    self.caller._play(prompt_name, times, result_callback, index)
}

func (self *Rtp_proxy_session) send_command(cmd string, cb func(string)) {
    if rtp_proxy_client := self._rtp_proxy_client; rtp_proxy_client != nil {
        self.inflight_lock.Lock()
        defer self.inflight_lock.Unlock()
        new_cmd := &rtpp_cmd{ cmd, cb, rtp_proxy_client }
        if self.inflight_cmd == nil {
            self.inflight_cmd = new_cmd
            rtp_proxy_client.SendCommand(cmd, self.cmd_done, nil)
        } else {
            self.rtpp_wi <- new_cmd
        }
    }
}

func (self *Rtp_proxy_session) cmd_done(res string) {
    self.inflight_lock.Lock()
    done_cmd := self.inflight_cmd
    select {
        case self.inflight_cmd = <-self.rtpp_wi:
            self.inflight_cmd.rtp_proxy_client.SendCommand(self.inflight_cmd.cmd, self.cmd_done, nil)
        default:
            self.inflight_cmd = nil
    }
    self.inflight_lock.Unlock()
    if done_cmd != nil && done_cmd.cb != nil {
        self.session_lock.Lock()
        done_cmd.cb(res)
        self.session_lock.Unlock()
    }
}

func (self *Rtp_proxy_session) StopPlayCaller(result_callback func(string)/*= nil*/, index int/*= 0*/) {
    if ! self.caller_session_exists {
        return
    }
    command := fmt.Sprintf("S %s-%d %s %s", self.call_id, index, self.from_tag, self.to_tag)
    self.send_command(command, func(r string) { self.command_result(r, result_callback) })
}

func (self *Rtp_proxy_session) StartRecording(rname/*= nil*/ string, result_callback func(string)/*= nil*/, index int/*= 0*/) {
    if ! self.caller.session_exists {
        self.caller.update("0.0.0.0", "0", func(*rtpproxy_update_result) { self._start_recording(rname, result_callback, index) }, "", index, "IP4")
        return
    }
    self._start_recording(rname, result_callback, index)
}

func (self *Rtp_proxy_session) _start_recording(rname string, result_callback func(string), index int) {
    if rname == "" {
        command := fmt.Sprintf("R %s-%d %s %s", self.call_id, index, self.from_tag, self.to_tag)
        self.send_command(command, func (r string) { self.command_result(r, result_callback) })
        return
    }
    command := fmt.Sprintf("C %s-%d %s.a %s %s", self.call_id, index, rname, self.from_tag, self.to_tag)
    self.send_command(command, func(string) { self._start_recording1(rname, result_callback, index) })
}

func (self *Rtp_proxy_session) _start_recording1(rname string, result_callback func(string), index int) {
    command := fmt.Sprintf("C %s-%d %s.o %s %s", self.call_id, index, rname, self.to_tag, self.from_tag)
    self.send_command(command, func (r string) { self.command_result(r, result_callback) })
}

func (self *Rtp_proxy_session) command_result(result string, result_callback func(string)) {
    //print "%s.command_result(%s)" % (id(self), result)
    if result_callback != nil {
        result_callback(result)
    }
}

func (self *Rtp_proxy_session) Delete() {
    if self._rtp_proxy_client == nil {
        return
    }
    for self.max_index >= 0 {
        command := fmt.Sprintf("D %s-%d %s %s", self.call_id, self.max_index, self.from_tag, self.to_tag)
        self.send_command(command, nil)
        self.max_index--
    }
    self._rtp_proxy_client = nil
}

func (self *Rtp_proxy_session) OnCallerSdpChange(sdp_body sippy_types.MsgBody, cc_event sippy_types.CCEvent, result_callback func(sippy_types.MsgBody)) error {
    return self.caller._on_sdp_change(sdp_body, result_callback)
}

func (self *Rtp_proxy_session) OnCalleeSdpChange(sdp_body sippy_types.MsgBody, msg sippy_types.SipMsg, result_callback func(sippy_types.MsgBody)) error {
    return self.callee._on_sdp_change(sdp_body, result_callback)
}

func rtp_proxy_session_destructor(self *Rtp_proxy_session) {
    self.Delete()
}

func (self *Rtp_proxy_session) CallerSessionExists() bool { return self.caller_session_exists }

func (self *Rtp_proxy_session) SetCallerLaddress(addr string) {
    self.caller.laddress = addr
}

func (self *Rtp_proxy_session) SetCallerRaddress(addr *sippy_net.HostPort) {
    self.caller.raddress = addr
}

func (self *Rtp_proxy_session) SetCalleeLaddress(addr string) {
    self.callee.laddress = addr
}

func (self *Rtp_proxy_session) SetCalleeRaddress(addr *sippy_net.HostPort) {
    self.callee.raddress = addr
}

func (self *Rtp_proxy_session) SetInsertNortpp(v bool) {
    self.insert_nortpp = v
}

func (self *Rtp_proxy_session) SetAfterCallerSdpChange(cb func(sippy_types.RtpProxyUpdateResult)) {
    self.caller.after_sdp_change = cb
}

func (self *Rtp_proxy_session) CalleeOrigin() *sippy_sdp.SdpOrigin {
    if self == nil {
        return nil
    }
    return self.callee.origin
}

func (self Rtp_proxy_session) SBindSupported() (bool, error) {
    rtp_proxy_client := self._rtp_proxy_client
    if rtp_proxy_client == nil {
        return true, errors.New("the session already deleted")
    }
    return rtp_proxy_client.SBindSupported(), nil
}

func (self Rtp_proxy_session) IsLocal() (bool, error) {
    rtp_proxy_client := self._rtp_proxy_client
    if rtp_proxy_client == nil {
        return true, errors.New("the session already deleted")
    }
    return rtp_proxy_client.IsLocal(), nil
}

func (self Rtp_proxy_session) TNotSupported() (bool, error) {
    rtp_proxy_client := self._rtp_proxy_client
    if rtp_proxy_client == nil {
        return true, errors.New("the session already deleted")
    }
    return rtp_proxy_client.TNotSupported(), nil
}

func (self Rtp_proxy_session) GetProxyAddress() (string, error) {
    rtp_proxy_client := self._rtp_proxy_client
    if rtp_proxy_client == nil {
        return "", errors.New("the session already deleted")
    }
    return rtp_proxy_client.GetProxyAddress(), nil
}
<commit_msg>Fix typo.<commit_after>// Copyright (c) 2003-2005 Maxim Sobolev. All rights reserved.
// Copyright (c) 2006-2014 Sippy Software, Inc. All rights reserved.
// Copyright (c) 2016 Andriy Pylypenko. All rights reserved.
//
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without modification,
// are permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice, this
// list of conditions and the following disclaimer.
//
// 2. Redistributions in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation and/or
// other materials provided with the distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
// ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
package sippy

import (
    "crypto/rand"
    "errors"
    "fmt"
    "math/big"
    "runtime"
    "sync"

    "sippy/conf"
    "sippy/net"
    "sippy/sdp"
    "sippy/types"
)

type Rtp_proxy_session struct {
    call_id                 string
    from_tag                string
    to_tag                  string
    _rtp_proxy_client       sippy_types.RtpProxyClient
    max_index               int
    l4r                     *local4remote
    notify_socket           string
    notify_tag              string
    insert_nortpp           bool
    caller                  _rtpps_side
    callee                  _rtpps_side
    session_lock            sync.Locker
    config                  sippy_conf.Config
    inflight_lock           sync.Mutex
    inflight_cmd            *rtpp_cmd
    rtpp_wi                 chan *rtpp_cmd
}

type rtpproxy_update_result struct {
    rtpproxy_address    string
    rtpproxy_port       string
    family              string
    sendonly            bool
}

type rtpp_cmd struct {
    cmd         string
    cb          func(string)
    rtp_proxy_client sippy_types.RtpProxyClient
}

func (self *rtpproxy_update_result) Address() string {
    return self.rtpproxy_address
}

func NewRtp_proxy_session(config sippy_conf.Config, rtp_proxy_clients []sippy_types.RtpProxyClient, call_id, from_tag, to_tag, notify_socket, notify_tag string, session_lock sync.Locker, callee_origin *sippy_sdp.SdpOrigin) (*Rtp_proxy_session, error) {
    self := &Rtp_proxy_session{
        notify_socket   : notify_socket,
        notify_tag      : notify_tag,
        call_id         : call_id,
        from_tag        : from_tag,
        to_tag          : to_tag,
        insert_nortpp   : false,
        max_index       : -1,
        session_lock    : session_lock,
        config          : config,
        rtpp_wi         : make(chan *rtpp_cmd, 50),
    }
    self.caller.otherside = &self.callee
    self.callee.otherside = &self.caller
    self.caller.owner = self
    self.callee.owner = self
    self.caller.session_exists = false
    self.callee.session_exists = false
    // RFC4566
    // *******
    // For privacy reasons, it is sometimes desirable to obfuscate the
    // username and IP address of the session originator.  If this is a
    // concern, an arbitrary <username> and private <unicast-address> MAY be
    // chosen to populate the "o=" field, provided that these are selected
    // in a manner that does not affect the global uniqueness of the field.
    // *******
    addr := "192.0.2.1" // 192.0.2.0/24 (TEST-NET-1)
    self.caller.origin, _ = sippy_sdp.NewSdpOrigin(addr)
    if callee_origin != nil {
        self.callee.origin = callee_origin.GetCopy()
        // New session means new RTP port so the SDP is now different and the SDP
        // version must be increased.
        self.callee.origin.IncVersion()
    } else {
        self.callee.origin, _ = sippy_sdp.NewSdpOrigin(addr)
    }
    online_clients := []sippy_types.RtpProxyClient{}
    for _, cl := range rtp_proxy_clients {
        if cl.IsOnline() {
            online_clients = append(online_clients, cl)
        }
    }
    n := len(online_clients)
    if n == 0 {
        return nil, fmt.Errorf("No online RTP proxy client has been found")
    }
    idx, err := rand.Int(rand.Reader, big.NewInt(int64(n)))
    if err != nil {
        self._rtp_proxy_client = online_clients[0]
    } else {
        self._rtp_proxy_client = online_clients[idx.Int64()]
    }
    if self.call_id == "" {
        buf := make([]byte, 16)
        rand.Read(buf)
        self.call_id = fmt.Sprintf("%x", buf)
    }
    if from_tag == "" {
        buf := make([]byte, 16)
        rand.Read(buf)
        self.from_tag = fmt.Sprintf("%x", buf)
    }
    if to_tag == "" {
        buf := make([]byte, 16)
        rand.Read(buf)
        self.to_tag = fmt.Sprintf("%x", buf)
    }
    runtime.SetFinalizer(self, rtp_proxy_session_destructor)
    return self, nil
}
/*
    def version(self, result_callback):
        self.send_command("V", self.version_result, result_callback)

    def version_result(self, result, result_callback):
        result_callback(result)
*/
func (self *Rtp_proxy_session) PlayCaller(prompt_name string, times int/*= 1*/, result_callback func(string)/*= nil*/, index int /*= 0*/) {
    self.caller._play(prompt_name, times, result_callback, index)
}

func (self *Rtp_proxy_session) send_command(cmd string, cb func(string)) {
    if rtp_proxy_client := self._rtp_proxy_client; rtp_proxy_client != nil {
        self.inflight_lock.Lock()
        defer self.inflight_lock.Unlock()
        new_cmd := &rtpp_cmd{ cmd, cb, rtp_proxy_client }
        if self.inflight_cmd == nil {
            self.inflight_cmd = new_cmd
            rtp_proxy_client.SendCommand(cmd, self.cmd_done, nil)
        } else {
            self.rtpp_wi <- new_cmd
        }
    }
}

func (self *Rtp_proxy_session) cmd_done(res string) {
    self.inflight_lock.Lock()
    done_cmd := self.inflight_cmd
    select {
        case self.inflight_cmd = <-self.rtpp_wi:
            self.inflight_cmd.rtp_proxy_client.SendCommand(self.inflight_cmd.cmd, self.cmd_done, nil)
        default:
            self.inflight_cmd = nil
    }
    self.inflight_lock.Unlock()
    if done_cmd != nil && done_cmd.cb != nil {
        self.session_lock.Lock()
        done_cmd.cb(res)
        self.session_lock.Unlock()
    }
}

func (self *Rtp_proxy_session) StopPlayCaller(result_callback func(string)/*= nil*/, index int/*= 0*/) {
    if ! self.caller.session_exists {
        return
    }
    command := fmt.Sprintf("S %s-%d %s %s", self.call_id, index, self.from_tag, self.to_tag)
    self.send_command(command, func(r string) { self.command_result(r, result_callback) })
}

func (self *Rtp_proxy_session) StartRecording(rname/*= nil*/ string, result_callback func(string)/*= nil*/, index int/*= 0*/) {
    if ! self.caller.session_exists {
        self.caller.update("0.0.0.0", "0", func(*rtpproxy_update_result) { self._start_recording(rname, result_callback, index) }, "", index, "IP4")
        return
    }
    self._start_recording(rname, result_callback, index)
}

func (self *Rtp_proxy_session) _start_recording(rname string, result_callback func(string), index int) {
    if rname == "" {
        command := fmt.Sprintf("R %s-%d %s %s", self.call_id, index, self.from_tag, self.to_tag)
        self.send_command(command, func (r string) { self.command_result(r, result_callback) })
        return
    }
    command := fmt.Sprintf("C %s-%d %s.a %s %s", self.call_id, index, rname, self.from_tag, self.to_tag)
    self.send_command(command, func(string) { self._start_recording1(rname, result_callback, index) })
}

func (self *Rtp_proxy_session) _start_recording1(rname string, result_callback func(string), index int) {
    command := fmt.Sprintf("C %s-%d %s.o %s %s", self.call_id, index, rname, self.to_tag, self.from_tag)
    self.send_command(command, func (r string) { self.command_result(r, result_callback) })
}

func (self *Rtp_proxy_session) command_result(result string, result_callback func(string)) {
    //print "%s.command_result(%s)" % (id(self), result)
    if result_callback != nil {
        result_callback(result)
    }
}

func (self *Rtp_proxy_session) Delete() {
    if self._rtp_proxy_client == nil {
        return
    }
    for self.max_index >= 0 {
        command := fmt.Sprintf("D %s-%d %s %s", self.call_id, self.max_index, self.from_tag, self.to_tag)
        self.send_command(command, nil)
        self.max_index--
    }
    self._rtp_proxy_client = nil
}

func (self *Rtp_proxy_session) OnCallerSdpChange(sdp_body sippy_types.MsgBody, cc_event sippy_types.CCEvent, result_callback func(sippy_types.MsgBody)) error {
    return self.caller._on_sdp_change(sdp_body, result_callback)
}

func (self *Rtp_proxy_session) OnCalleeSdpChange(sdp_body sippy_types.MsgBody, msg sippy_types.SipMsg, result_callback func(sippy_types.MsgBody)) error {
    return self.callee._on_sdp_change(sdp_body, result_callback)
}

func rtp_proxy_session_destructor(self *Rtp_proxy_session) {
    self.Delete()
}

func (self *Rtp_proxy_session) CallerSessionExists() bool { return self.caller.session_exists }

func (self *Rtp_proxy_session) SetCallerLaddress(addr string) {
    self.caller.laddress = addr
}

func (self *Rtp_proxy_session) SetCallerRaddress(addr *sippy_net.HostPort) {
    self.caller.raddress = addr
}

func (self *Rtp_proxy_session) SetCalleeLaddress(addr string) {
    self.callee.laddress = addr
}

func (self *Rtp_proxy_session) SetCalleeRaddress(addr *sippy_net.HostPort) {
    self.callee.raddress = addr
}

func (self *Rtp_proxy_session) SetInsertNortpp(v bool) {
    self.insert_nortpp = v
}

func (self *Rtp_proxy_session) SetAfterCallerSdpChange(cb func(sippy_types.RtpProxyUpdateResult)) {
    self.caller.after_sdp_change = cb
}

func (self *Rtp_proxy_session) CalleeOrigin() *sippy_sdp.SdpOrigin {
    if self == nil {
        return nil
    }
    return self.callee.origin
}

func (self Rtp_proxy_session) SBindSupported() (bool, error) {
    rtp_proxy_client := self._rtp_proxy_client
    if rtp_proxy_client == nil {
        return true, errors.New("the session already deleted")
    }
    return rtp_proxy_client.SBindSupported(), nil
}

func (self Rtp_proxy_session) IsLocal() (bool, error) {
    rtp_proxy_client := self._rtp_proxy_client
    if rtp_proxy_client == nil {
        return true, errors.New("the session already deleted")
    }
    return rtp_proxy_client.IsLocal(), nil
}

func (self Rtp_proxy_session) TNotSupported() (bool, error) {
    rtp_proxy_client := self._rtp_proxy_client
    if rtp_proxy_client == nil {
        return true, errors.New("the session already deleted")
    }
    return rtp_proxy_client.TNotSupported(), nil
}

func (self Rtp_proxy_session) GetProxyAddress() (string, error) {
    rtp_proxy_client := self._rtp_proxy_client
    if rtp_proxy_client == nil {
        return "", errors.New("the session already deleted")
    }
    return rtp_proxy_client.GetProxyAddress(), nil
}
<|endoftext|>