<commit_before>package main

import (
	"fmt"
	"log"

	"sample"
	"sample/mocks"

	"veyron.io/veyron/veyron/lib/signals"
	"veyron.io/veyron/veyron/profiles"
	_ "veyron.io/veyron/veyron/profiles"
	"veyron.io/veyron/veyron2/ipc"
	"veyron.io/veyron/veyron2/rt"
)

func makeServerAlarm() interface{} {
	return sample.NewServerAlarm(mocks.NewAlarm())
}
func makeServerLightSwitch() interface{} {
	return sample.NewServerLightSwitch(mocks.NewLightSwitch())
}
func makeServerPoolHeater() interface{} {
	return sample.NewServerPoolHeater(mocks.NewPoolHeater())
}
func makeServerSmokeDetector() interface{} {
	return sample.NewServerSmokeDetector(mocks.NewSmokeDetector())
}
func makeServerSpeaker() interface{} {
	return sample.NewServerSpeaker(mocks.NewSpeaker())
}
func makeServerSprinkler() interface{} {
	return sample.NewServerSprinkler(mocks.NewSprinkler())
}

func main() {
	// Create the runtime
	r := rt.Init()

	defer r.Cleanup()

	// Create new server and publish the given server under the given name
	var listenAndServe = func(name string, server interface{}) func() {

		// Create a new server instance.
		s, err := r.NewServer()
		if err != nil {
			log.Fatal("failure creating server: ", err)
		}

		// Create an endpoint and begin listening.
		if endpoint, err := s.Listen(profiles.LocalListenSpec); err == nil {
			fmt.Printf("Listening at: %v\n", endpoint)
		} else {
			log.Fatal("error listening to service: ", err)
		}

		// Serve these services at the given name.
		if err := s.Serve(name, ipc.LeafDispatcher(server, nil)); err != nil {
			log.Fatal("error serving service: ", err)
		}

		return func() {
			s.Stop()
		}
	}

	// Serve bunch of mock services under different names
	defer listenAndServe("house/alarm", makeServerAlarm())()
	defer listenAndServe("house/living-room/lights", makeServerLightSwitch())()
	defer listenAndServe("house/living-room/smoke-detector", makeServerSmokeDetector())()
	defer listenAndServe("house/living-room/blast-speaker", makeServerSpeaker())()
	defer listenAndServe("house/living-room/soundbar", makeServerSpeaker())()
	defer listenAndServe("house/master-bedroom/desk-lamp", makeServerLightSwitch())()
	defer listenAndServe("house/master-bedroom/lights", makeServerLightSwitch())()
	defer listenAndServe("house/master-bedroom/smoke-detector", makeServerSmokeDetector())()
	defer listenAndServe("house/master-bedroom/speaker", makeServerSpeaker())()
	defer listenAndServe("house/kitchen/lights", makeServerLightSwitch())()
	defer listenAndServe("house/kitchen/smoke-detector", makeServerSmokeDetector())()

	defer listenAndServe("cottage/smoke-detector", makeServerSmokeDetector())()
	defer listenAndServe("cottage/alarm", makeServerAlarm())()
	defer listenAndServe("cottage/lights", makeServerLightSwitch())()
	defer listenAndServe("cottage/pool/heater", makeServerPoolHeater())()
	defer listenAndServe("cottage/pool/speaker", makeServerSpeaker())()
	defer listenAndServe("cottage/pool/pool-lights", makeServerLightSwitch())()
	defer listenAndServe("cottage/lawn/front/sprinkler", makeServerSprinkler())()
	defer listenAndServe("cottage/lawn/back/sprinkler", makeServerSprinkler())()
	defer listenAndServe("cottage/lawn/master-sprinkler", makeServerSprinkler())()

	// Wait forever.
	<-signals.ShutdownOnSignals()
}
<commit_msg>veyron-browser: Make sampled work again<commit_after>package main

import (
	"fmt"
	"log"

	"sample"
	"sample/mocks"

	"veyron.io/veyron/veyron/lib/signals"
	"veyron.io/veyron/veyron/profiles"
	_ "veyron.io/veyron/veyron/profiles"
	"veyron.io/veyron/veyron2/ipc"
	"veyron.io/veyron/veyron2/rt"
)

func makeServerAlarm() interface{} {
	return sample.NewServerAlarm(mocks.NewAlarm())
}
func makeServerLightSwitch() interface{} {
	return sample.NewServerLightSwitch(mocks.NewLightSwitch())
}
func makeServerPoolHeater() interface{} {
	return sample.NewServerPoolHeater(mocks.NewPoolHeater())
}
func makeServerSmokeDetector() interface{} {
	return sample.NewServerSmokeDetector(mocks.NewSmokeDetector())
}
func makeServerSpeaker() interface{} {
	return sample.NewServerSpeaker(mocks.NewSpeaker())
}
func makeServerSprinkler() interface{} {
	return sample.NewServerSprinkler(mocks.NewSprinkler())
}

func main() {
	// Create the runtime
	r := rt.Init()

	defer r.Cleanup()

	// Create new server and publish the given server under the given name
	var listenAndServe = func(name string, server interface{}) func() {

		// Create a new server instance.
		s, err := r.NewServer()
		if err != nil {
			log.Fatal("failure creating server: ", err)
		}

		// Create an endpoint and begin listening.
		if endpoint, err := s.Listen(profiles.LocalListenSpec); err == nil {
			fmt.Printf("Listening at: %v\n", endpoint)
		} else {
			log.Fatal("error listening to service: ", err)
		}

		// Serve these services at the given name.
		if err := s.ServeDispatcher(name, ipc.LeafDispatcher(server, nil)); err != nil {
			log.Fatal("error serving service: ", err)
		}

		return func() {
			s.Stop()
		}
	}

	// Serve bunch of mock services under different names
	defer listenAndServe("house/alarm", makeServerAlarm())()
	defer listenAndServe("house/living-room/lights", makeServerLightSwitch())()
	defer listenAndServe("house/living-room/smoke-detector", makeServerSmokeDetector())()
	defer listenAndServe("house/living-room/blast-speaker", makeServerSpeaker())()
	defer listenAndServe("house/living-room/soundbar", makeServerSpeaker())()
	defer listenAndServe("house/master-bedroom/desk-lamp", makeServerLightSwitch())()
	defer listenAndServe("house/master-bedroom/lights", makeServerLightSwitch())()
	defer listenAndServe("house/master-bedroom/smoke-detector", makeServerSmokeDetector())()
	defer listenAndServe("house/master-bedroom/speaker", makeServerSpeaker())()
	defer listenAndServe("house/kitchen/lights", makeServerLightSwitch())()
	defer listenAndServe("house/kitchen/smoke-detector", makeServerSmokeDetector())()

	defer listenAndServe("cottage/smoke-detector", makeServerSmokeDetector())()
	defer listenAndServe("cottage/alarm", makeServerAlarm())()
	defer listenAndServe("cottage/lights", makeServerLightSwitch())()
	defer listenAndServe("cottage/pool/heater", makeServerPoolHeater())()
	defer listenAndServe("cottage/pool/speaker", makeServerSpeaker())()
	defer listenAndServe("cottage/pool/pool-lights", makeServerLightSwitch())()
	defer listenAndServe("cottage/lawn/front/sprinkler", makeServerSprinkler())()
	defer listenAndServe("cottage/lawn/back/sprinkler", makeServerSprinkler())()
	defer listenAndServe("cottage/lawn/master-sprinkler", makeServerSprinkler())()

	// Wait forever.
	<-signals.ShutdownOnSignals()
}
<|endoftext|>


<commit_before>package utils

import (
	"net/http"
	"time"
)

const (
	// ISODate - iso date format
	ISODate string = "2006-01-02"
	// ISODateTime - iso date time format
	ISODateTime string = "2006-01-02 15:04:05"
	// ISODateTimestamp - iso timestamp format
	ISODateTimestamp string = "2006-01-02 15:04:05.000"
	// ISODateTimeZ - iso datetime with timezone format
	ISODateTimeZ string = "2006-01-02 15:04:05Z07:00"
	// ISODateTimestampZ - iso timestamp with timezone format
	ISODateTimestampZ string = "2006-01-02 15:04:05.000Z07:00"
	// ISOTime - iso time format
	ISOTime string = "15:04:05"
	// ISOTimeMS - iso time format with miliseconds
	ISOTimeMS string = "15:04:05.000"
	// DMY - dd/MM/yyyy
	DMY string = "02/01/2006"
	// DMYTime - dd/MM/yyyy HH:m:ss
	DMYTime string = "02/01/2006 15:04:05"
	// UTCDate - date at midnight UTC
	UTCDate string = "UTCDate"
	// UTCDateTime - ISODateTime at UTC
	UTCDateTime string = "UTC"
	// UTCDateTimestamp - ISODateTimestamp at UTC
	UTCDateTimestamp string = "UTCTimestamp"
	// DateOffset - time zone offset
	DateOffset string = "Z07:00"
	// RSSDateTime - rss date time format
	RSSDateTime string = "Mon, 02 Jan 2006 15:04:05 Z07:00"
	// RSSDateTime1 - rss date time format 1
	RSSDateTime1 string = "Mon, _2 Jan 2006 15:04:05 Z07:00"
	// RSSDateTime2 - rss date time format 2
	RSSDateTime2 string = "Mon, 02 Jan 2006 15:04:05 Z0700"
	// RSSDateTime3 - rss date time format 3
	RSSDateTime3 string = "Mon, _2 Jan 2006 15:04:05 Z0700"
	// RSSDateTimeTZ - rss date time format with named timezone
	RSSDateTimeTZ string = "Mon, 02 Jan 2006 15:04:05 MST"
	// RSSDateTimeTZ1 - rss date time format with named timezone 1
	RSSDateTimeTZ1 string = "Mon, _2 Jan 2006 15:04:05 MST"
)

// IsISODate - checks if is in iso date format
func IsISODate(sval string) bool {
	_, err := String2date(sval, ISODate)

	if err != nil {
		return false
	}

	return true
}

// IsISODateTime - checks if is in iso datetime format
func IsISODateTime(sval string) bool {
	_, err := String2date(sval, ISODateTime)

	if err != nil {
		return false
	}

	return true
}

// DateFromISODateTime - Date From ISODateTime
func DateFromISODateTime(sval string) (time.Time, error) {
	return String2date(sval, ISODateTime)
}

// Date2string - Date to string
func Date2string(val time.Time, format string) string {
	switch format {
	case UTCDate:
		return val.UTC().Format(ISODate)
	case UTCDateTime:
		return val.UTC().Format(ISODateTimeZ)
	case UTCDateTimestamp:
		return val.UTC().Format(ISODateTimestampZ)
	default:
		return val.Format(format)
	}
}

// String2dateNoErr - String to date NoErrCheck
func String2dateNoErr(sval string, format string) time.Time {
	dt, err := String2date(sval, format)
	if err != nil {
		panic(err)
	}
	return dt
}

// String2date - String to date
func String2date(sval string, format string) (time.Time, error) {
	switch format {
	case ISODate, ISODateTime, ISODateTimestamp, ISODateTimeZ, ISODateTimestampZ, DMY, DMYTime, DateOffset:
		loc, err := time.LoadLocation("Local")
		if err != nil {
			return time.Now(), err
		}

		t, err := time.ParseInLocation(format, sval, loc)
		if err != nil {
			return time.Now(), err
		}
		return t, nil
	case UTCDate:
		loc, err := time.LoadLocation("UTC")
		if err != nil {
			return time.Now(), err
		}

		t, err := time.ParseInLocation(ISODate, sval, loc)
		if err != nil {
			return time.Now(), err
		}
		return t, nil
	case UTCDateTime:
		loc, err := time.LoadLocation("UTC")
		if err != nil {
			return time.Now(), err
		}

		t, err := time.ParseInLocation(ISODateTime, sval, loc)
		if err != nil {
			return time.Now(), err
		}
		return t, nil
	case UTCDateTimestamp:
		loc, err := time.LoadLocation("UTC")
		if err != nil {
			return time.Now(), err
		}

		t, err := time.ParseInLocation(ISODateTimestamp, sval, loc)
		if err != nil {
			return time.Now(), err
		}
		return t, nil
	default:
		loc, err := time.LoadLocation("UTC")
		if err != nil {
			return time.Now(), err
		}

		t, err := time.ParseInLocation(format, sval, loc)
		if err != nil {
			return time.Now(), err
		}
		return t, nil
	}
}

// Server2ClientDmy - Server2ClientDmy
func Server2ClientDmy(r *http.Request, serverTime time.Time) string {
	t := Server2ClientLocal(r, serverTime)
	return Date2string(t, DMY)
}

// Server2ClientDmyTime - Server2ClientDmyTime
func Server2ClientDmyTime(r *http.Request, serverTime time.Time) string {
	t := Server2ClientLocal(r, serverTime)
	return Date2string(t, DMYTime)
}

// Server2ClientLocal - Server2ClientLocal
func Server2ClientLocal(r *http.Request, serverTime time.Time) time.Time {
	timeOffset := 0

	cookie, err := r.Cookie("time_zone_offset")
	if err != nil && err != http.ErrNoCookie {
		return serverTime.UTC()
	} else if err == http.ErrNoCookie {
		timeOffset = 0
	} else {
		timeOffset = String2int(cookie.Value)
	}

	return serverTime.UTC().Add(time.Duration(-1*timeOffset) * time.Minute)
}

// ParseRSSDate - try to parse RSS date in multiple formats
func ParseRSSDate(sdate string) (time.Time, error) {
	var err error
	var dt time.Time

	formats := []string{
		RSSDateTimeTZ,
		RSSDateTimeTZ1,
		RSSDateTime,
		RSSDateTime1,
		RSSDateTime2,
		RSSDateTime3,
		"02 Jan 2006 15:04:05 Z0700",
		"_2 Jan 2006 15:04:05 Z0700",
		ISODateTime,
		ISODateTimeZ,
	}

	for _, format := range formats {
		dt, err = String2date(sdate, format)
		if err == nil {
			break
		}
	}

	return dt.UTC(), err
}
<commit_msg>More RSS date formats, now with new lines and tabs - amazing<commit_after>package utils

import (
	"net/http"
	"strings"
	"time"
)

const (
	// ISODate - iso date format
	ISODate string = "2006-01-02"
	// ISODateTime - iso date time format
	ISODateTime string = "2006-01-02 15:04:05"
	// ISODateTimestamp - iso timestamp format
	ISODateTimestamp string = "2006-01-02 15:04:05.000"
	// ISODateTimeZ - iso datetime with timezone format
	ISODateTimeZ string = "2006-01-02 15:04:05Z07:00"
	// ISODateTimestampZ - iso timestamp with timezone format
	ISODateTimestampZ string = "2006-01-02 15:04:05.000Z07:00"
	// ISOTime - iso time format
	ISOTime string = "15:04:05"
	// ISOTimeMS - iso time format with miliseconds
	ISOTimeMS string = "15:04:05.000"
	// DMY - dd/MM/yyyy
	DMY string = "02/01/2006"
	// DMYTime - dd/MM/yyyy HH:m:ss
	DMYTime string = "02/01/2006 15:04:05"
	// UTCDate - date at midnight UTC
	UTCDate string = "UTCDate"
	// UTCDateTime - ISODateTime at UTC
	UTCDateTime string = "UTC"
	// UTCDateTimestamp - ISODateTimestamp at UTC
	UTCDateTimestamp string = "UTCTimestamp"
	// DateOffset - time zone offset
	DateOffset string = "Z07:00"
	// RSSDateTime - rss date time format
	RSSDateTime string = "Mon, 02 Jan 2006 15:04:05 Z07:00"
	// RSSDateTime1 - rss date time format 1
	RSSDateTime1 string = "Mon, _2 Jan 2006 15:04:05 Z07:00"
	// RSSDateTime2 - rss date time format 2
	RSSDateTime2 string = "Mon, 02 Jan 2006 15:04:05 Z0700"
	// RSSDateTime3 - rss date time format 3
	RSSDateTime3 string = "Mon, _2 Jan 2006 15:04:05 Z0700"
	// RSSDateTimeTZ - rss date time format with named timezone
	RSSDateTimeTZ string = "Mon, 02 Jan 2006 15:04:05 MST"
	// RSSDateTimeTZ1 - rss date time format with named timezone 1
	RSSDateTimeTZ1 string = "Mon, _2 Jan 2006 15:04:05 MST"
)

// IsISODate - checks if is in iso date format
func IsISODate(sval string) bool {
	_, err := String2date(sval, ISODate)

	if err != nil {
		return false
	}

	return true
}

// IsISODateTime - checks if is in iso datetime format
func IsISODateTime(sval string) bool {
	_, err := String2date(sval, ISODateTime)

	if err != nil {
		return false
	}

	return true
}

// DateFromISODateTime - Date From ISODateTime
func DateFromISODateTime(sval string) (time.Time, error) {
	return String2date(sval, ISODateTime)
}

// Date2string - Date to string
func Date2string(val time.Time, format string) string {
	switch format {
	case UTCDate:
		return val.UTC().Format(ISODate)
	case UTCDateTime:
		return val.UTC().Format(ISODateTimeZ)
	case UTCDateTimestamp:
		return val.UTC().Format(ISODateTimestampZ)
	default:
		return val.Format(format)
	}
}

// String2dateNoErr - String to date NoErrCheck
func String2dateNoErr(sval string, format string) time.Time {
	dt, err := String2date(sval, format)
	if err != nil {
		panic(err)
	}
	return dt
}

// String2date - String to date
func String2date(sval string, format string) (time.Time, error) {
	switch format {
	case ISODate, ISODateTime, ISODateTimestamp, ISODateTimeZ, ISODateTimestampZ, DMY, DMYTime, DateOffset:
		loc, err := time.LoadLocation("Local")
		if err != nil {
			return time.Now(), err
		}

		t, err := time.ParseInLocation(format, sval, loc)
		if err != nil {
			return time.Now(), err
		}
		return t, nil
	case UTCDate:
		loc, err := time.LoadLocation("UTC")
		if err != nil {
			return time.Now(), err
		}

		t, err := time.ParseInLocation(ISODate, sval, loc)
		if err != nil {
			return time.Now(), err
		}
		return t, nil
	case UTCDateTime:
		loc, err := time.LoadLocation("UTC")
		if err != nil {
			return time.Now(), err
		}

		t, err := time.ParseInLocation(ISODateTime, sval, loc)
		if err != nil {
			return time.Now(), err
		}
		return t, nil
	case UTCDateTimestamp:
		loc, err := time.LoadLocation("UTC")
		if err != nil {
			return time.Now(), err
		}

		t, err := time.ParseInLocation(ISODateTimestamp, sval, loc)
		if err != nil {
			return time.Now(), err
		}
		return t, nil
	default:
		loc, err := time.LoadLocation("UTC")
		if err != nil {
			return time.Now(), err
		}

		t, err := time.ParseInLocation(format, sval, loc)
		if err != nil {
			return time.Now(), err
		}
		return t, nil
	}
}

// Server2ClientDmy - Server2ClientDmy
func Server2ClientDmy(r *http.Request, serverTime time.Time) string {
	t := Server2ClientLocal(r, serverTime)
	return Date2string(t, DMY)
}

// Server2ClientDmyTime - Server2ClientDmyTime
func Server2ClientDmyTime(r *http.Request, serverTime time.Time) string {
	t := Server2ClientLocal(r, serverTime)
	return Date2string(t, DMYTime)
}

// Server2ClientLocal - Server2ClientLocal
func Server2ClientLocal(r *http.Request, serverTime time.Time) time.Time {
	timeOffset := 0

	cookie, err := r.Cookie("time_zone_offset")
	if err != nil && err != http.ErrNoCookie {
		return serverTime.UTC()
	} else if err == http.ErrNoCookie {
		timeOffset = 0
	} else {
		timeOffset = String2int(cookie.Value)
	}

	return serverTime.UTC().Add(time.Duration(-1*timeOffset) * time.Minute)
}

// ParseRSSDate - try to parse RSS date in multiple formats
func ParseRSSDate(sdate string) (time.Time, error) {
	var err error
	var dt time.Time

	formats := []string{
		RSSDateTimeTZ,
		RSSDateTimeTZ1,
		RSSDateTime,
		RSSDateTime1,
		RSSDateTime2,
		RSSDateTime3,
		"02 Jan 2006 15:04:05 Z0700",
		"_2 Jan 2006 15:04:05 Z0700",
		ISODateTime,
		ISODateTimeZ,
	}

	sdt := strings.TrimSpace(sdate)

	for _, format := range formats {
		dt, err = String2date(sdt, format)
		if err == nil {
			break
		}
	}

	return dt.UTC(), err
}
<|endoftext|>


<commit_before>package controllers

import (
	"github.com/astaxie/beego"
	"github.com/astaxie/beego/validation"
	"ustackweb/models"
	"ustackweb/utils"
)

type UserForm struct {
	Username    string
	Password    string
	OldPassword string
}

type UsersController struct {
	BaseController
}

func (this *UsersController) Prepare() {
	this.PrepareXsrf()
	this.RequireAuth()
	this.PrepareLayout()
	this.Layout = "layouts/default.html.tpl"
}

func (this *UsersController) Index() {
	this.TplNames = "users/index.html.tpl"
	users := models.Users().All()
	paginator := utils.NewPaginator(this.Ctx.Request, 3, len(users))
	this.Data["paginator"] = paginator
	this.Data["users"] = users[paginator.Offset():utils.Min(paginator.Offset()+paginator.PerPageNums, len(users))]
}

func (this *UsersController) New() {
	this.TplNames = "users/new.html.tpl"
}

func (this *UsersController) Create() {
	userForm := UserForm{}
	err := this.ParseForm(&userForm)
	if err == nil {
		valid := validation.Validation{}
		valid.Required(userForm.Username, "Username")
		if valid.HasErrors() {
			this.Data["Errors"] = valid.Errors
			flash := beego.NewFlash()
			flash.Error("Insufficient data!")
			flash.Store(&this.Controller)
			this.TplNames = "users/new.html.tpl"
		} else {
			created, id := models.Users().Create(userForm.Username, userForm.Password)
			if created {
				this.Redirect(beego.UrlFor("UsersController.Edit", ":id", string(id)), 302)
			} else {
				flash := beego.NewFlash()
				flash.Error("Could not create user!")
				flash.Store(&this.Controller)
				this.TplNames = "users/new.html.tpl"
			}
		}
	} else {
		this.TplNames = "users/new.html.tpl"
	}
}

func (this *UsersController) Edit() {
	this.TplNames = "users/edit.html.tpl"
	id, _ := this.GetInt(":id")
	this.Data["user"] = models.Users().Find(id)
}

func (this *UsersController) UpdateUsername() {
	id := this.GetString(":id")
	intId, _ := this.GetInt(":id")
	this.Data["user"] = models.Users().Find(intId)
	userForm := UserForm{}
	err := this.ParseForm(&userForm)
	if err == nil {
		valid := validation.Validation{}
		valid.Required(userForm.Username, "Username")
		valid.Required(userForm.Password, "Password")
		if valid.HasErrors() {
			this.Data["UpdateUsernameErrors"] = valid.Errors
			flash := beego.NewFlash()
			flash.Error("Insufficient data!")
			flash.Store(&this.Controller)
			this.TplNames = "users/edit.html.tpl"
		} else {
			updated := models.Users().UpdateUsername(id, userForm.Password, userForm.Username)
			if updated {
				this.Redirect(beego.UrlFor("UsersController.Edit", ":id", string(id)), 302)
			} else {
				flash := beego.NewFlash()
				flash.Error("Could not update user!")
				flash.Store(&this.Controller)
				this.TplNames = "users/edit.html.tpl"
			}
		}
	} else {
		this.TplNames = "users/edit.html.tpl"
	}
}

func (this *UsersController) UpdatePassword() {
	id := this.GetString(":id")
	intId, _ := this.GetInt(":id")
	this.Data["user"] = models.Users().Find(intId)
	userForm := UserForm{}
	err := this.ParseForm(&userForm)
	if err == nil {
		valid := validation.Validation{}
		valid.Required(userForm.Password, "Password")
		valid.Required(userForm.OldPassword, "OldPassword")
		if valid.HasErrors() {
			this.Data["UpdatePasswordErrors"] = valid.Errors
			flash := beego.NewFlash()
			flash.Error("Insufficient data!")
			flash.Store(&this.Controller)
			this.TplNames = "users/edit.html.tpl"
		} else {
			updated := models.Users().UpdatePassword(id, userForm.OldPassword, userForm.Password)
			if updated {
				this.Redirect(beego.UrlFor("UsersController.Edit", ":id", string(id)), 302)
			} else {
				flash := beego.NewFlash()
				flash.Error("Could not update user!")
				flash.Store(&this.Controller)
				this.TplNames = "users/edit.html.tpl"
			}
		}
	} else {
		this.TplNames = "users/edit.html.tpl"
	}
}

func (this *UsersController) Destroy() {
	id, _ := this.GetInt(":id")
	user := models.Users().Find(id)
	models.Users().Destroy(user.Name)
	flash := beego.NewFlash()
	flash.Notice("Deleted user " + user.Name)
	flash.Store(&this.Controller)
	this.Redirect(beego.UrlFor("UsersController.Index"), 302)
}
<commit_msg>Improve erro messages.<commit_after>package controllers

import (
	"github.com/astaxie/beego"
	"github.com/astaxie/beego/validation"
	"ustackweb/models"
	"ustackweb/utils"
)

type UserForm struct {
	Username    string
	Password    string
	OldPassword string
}

type UsersController struct {
	BaseController
}

func (this *UsersController) Prepare() {
	this.PrepareXsrf()
	this.RequireAuth()
	this.PrepareLayout()
	this.Layout = "layouts/default.html.tpl"
}

func (this *UsersController) Index() {
	this.TplNames = "users/index.html.tpl"
	users := models.Users().All()
	paginator := utils.NewPaginator(this.Ctx.Request, 3, len(users))
	this.Data["paginator"] = paginator
	this.Data["users"] = users[paginator.Offset():utils.Min(paginator.Offset()+paginator.PerPageNums, len(users))]
}

func (this *UsersController) New() {
	this.TplNames = "users/new.html.tpl"
}

func (this *UsersController) Create() {
	userForm := UserForm{}
	err := this.ParseForm(&userForm)
	if err == nil {
		valid := validation.Validation{}
		valid.Required(userForm.Username, "Username")
		if valid.HasErrors() {
			this.Data["Errors"] = valid.Errors
			flash := beego.NewFlash()
			flash.Error("Could not create user.")
			flash.Store(&this.Controller)
			this.TplNames = "users/new.html.tpl"
		} else {
			created, id := models.Users().Create(userForm.Username, userForm.Password)
			if created {
				this.Redirect(beego.UrlFor("UsersController.Edit", ":id", string(id)), 302)
			} else {
				flash := beego.NewFlash()
				flash.Error("Could not create user!")
				flash.Store(&this.Controller)
				this.TplNames = "users/new.html.tpl"
			}
		}
	} else {
		this.TplNames = "users/new.html.tpl"
	}
}

func (this *UsersController) Edit() {
	this.TplNames = "users/edit.html.tpl"
	id, _ := this.GetInt(":id")
	this.Data["user"] = models.Users().Find(id)
}

func (this *UsersController) UpdateUsername() {
	id := this.GetString(":id")
	intId, _ := this.GetInt(":id")
	this.Data["user"] = models.Users().Find(intId)
	userForm := UserForm{}
	err := this.ParseForm(&userForm)
	if err == nil {
		valid := validation.Validation{}
		valid.Required(userForm.Username, "Username")
		valid.Required(userForm.Password, "Password")
		if valid.HasErrors() {
			this.Data["UpdateUsernameErrors"] = valid.Errors
			flash := beego.NewFlash()
			flash.Error("Could not change username.")
			flash.Store(&this.Controller)
			this.TplNames = "users/edit.html.tpl"
		} else {
			updated := models.Users().UpdateUsername(id, userForm.Password, userForm.Username)
			if updated {
				this.Redirect(beego.UrlFor("UsersController.Edit", ":id", string(id)), 302)
			} else {
				flash := beego.NewFlash()
				flash.Error("Could not update user!")
				flash.Store(&this.Controller)
				this.TplNames = "users/edit.html.tpl"
			}
		}
	} else {
		this.TplNames = "users/edit.html.tpl"
	}
}

func (this *UsersController) UpdatePassword() {
	id := this.GetString(":id")
	intId, _ := this.GetInt(":id")
	this.Data["user"] = models.Users().Find(intId)
	userForm := UserForm{}
	err := this.ParseForm(&userForm)
	if err == nil {
		valid := validation.Validation{}
		valid.Required(userForm.Password, "Password")
		valid.Required(userForm.OldPassword, "OldPassword")
		if valid.HasErrors() {
			this.Data["UpdatePasswordErrors"] = valid.Errors
			flash := beego.NewFlash()
			flash.Error("Could not change password.")
			flash.Store(&this.Controller)
			this.TplNames = "users/edit.html.tpl"
		} else {
			updated := models.Users().UpdatePassword(id, userForm.OldPassword, userForm.Password)
			if updated {
				this.Redirect(beego.UrlFor("UsersController.Edit", ":id", string(id)), 302)
			} else {
				flash := beego.NewFlash()
				flash.Error("Could not update user!")
				flash.Store(&this.Controller)
				this.TplNames = "users/edit.html.tpl"
			}
		}
	} else {
		this.TplNames = "users/edit.html.tpl"
	}
}

func (this *UsersController) Destroy() {
	id, _ := this.GetInt(":id")
	user := models.Users().Find(id)
	models.Users().Destroy(user.Name)
	flash := beego.NewFlash()
	flash.Notice("Deleted user " + user.Name)
	flash.Store(&this.Controller)
	this.Redirect(beego.UrlFor("UsersController.Index"), 302)
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"time"
)

func echo(in <-chan int, out chan<- int) {
	ticker := time.NewTicker(time.Second)
	var i int
	for {
		// NOTE: add solution without select
		select {
		case <-ticker.C:
			fmt.Println(i)
			i = 0
		default:
			out <- <-in
			i++
		}
	}
}

func main() {
	ch1 := make(chan int)
	ch2 := make(chan int)
	go echo(ch1, ch2)
	go echo(ch2, ch1)
	ch1 <- 0
	select {}
}
<commit_msg>[9.5] replaced int to struct<commit_after>package main

import (
	"fmt"
	"time"
)

func echo(in <-chan struct{}, out chan<- struct{}) {
	ticker := time.NewTicker(time.Second)
	var i int
	for {
		// NOTE: add solution without select
		select {
		case <-ticker.C:
			fmt.Printf("\r%d ", i)
			i = 0
		default:
			out <- <-in
			i++
		}
	}
}

func main() {
	ch1 := make(chan struct{})
	ch2 := make(chan struct{})
	go echo(ch1, ch2)
	go echo(ch2, ch1)
	ch1 <- struct{}{}
	select {}
}
<|endoftext|>


<commit_before>package gateway

import (
	"errors"
	"net"
	"time"

	"github.com/NebulousLabs/Sia/crypto"
	"github.com/NebulousLabs/Sia/encoding"
	"github.com/NebulousLabs/Sia/modules"
)

const (
	maxSharedNodes = 10
	minPeers       = 3
)

var (
	errNodeExists = errors.New("node already added")
	errOurAddress = errors.New("can't add our own address")
)

// addNode adds an address to the set of nodes on the network.
func (g *Gateway) addNode(addr modules.NetAddress) error {
	if addr == g.myAddr {
		return errOurAddress
	} else if _, exists := g.nodes[addr]; exists {
		return errNodeExists
	} else if addr.IsValid() != nil {
		return errors.New("address is not valid: " + string(addr))
	} else if net.ParseIP(addr.Host()) == nil {
		return errors.New("address must be an IP address: " + string(addr))
	}
	g.nodes[addr] = struct{}{}
	return nil
}

func (g *Gateway) removeNode(addr modules.NetAddress) error {
	if _, exists := g.nodes[addr]; !exists {
		return errors.New("no record of that node")
	}
	delete(g.nodes, addr)
	g.log.Println("INFO: removed node", addr)
	return nil
}

func (g *Gateway) randomNode() (modules.NetAddress, error) {
	if len(g.nodes) > 0 {
		r, _ := crypto.RandIntn(len(g.nodes))
		for node := range g.nodes {
			if r <= 0 {
				return node, nil
			}
			r--
		}
	}

	return "", errNoPeers
}

// shareNodes is the receiving end of the ShareNodes RPC. It writes up to 10
// randomly selected nodes to the caller.
func (g *Gateway) shareNodes(conn modules.PeerConn) error {
	g.mu.RLock()
	var nodes []modules.NetAddress
	for node := range g.nodes {
		if len(nodes) == maxSharedNodes {
			break
		}
		nodes = append(nodes, node)
	}
	g.mu.RUnlock()
	return encoding.WriteObject(conn, nodes)
}

// requestNodes is the calling end of the ShareNodes RPC.
func (g *Gateway) requestNodes(conn modules.PeerConn) error {
	var nodes []modules.NetAddress
	if err := encoding.ReadObject(conn, &nodes, maxSharedNodes*modules.MaxEncodedNetAddressLength); err != nil {
		return err
	}
	g.mu.Lock()
	for _, node := range nodes {
		err := g.addNode(node)
		if err != nil && err != errNodeExists && err != errOurAddress {
			g.log.Printf("WARN: peer '%v' sent the invalid addr '%v'", conn.RPCAddr(), node)
		}
	}
	g.save()
	g.mu.Unlock()
	return nil
}

// threadedNodeManager tries to keep the Gateway's node list healthy. As long
// as the Gateway has fewer than minNodeListSize nodes, it asks a random peer
// for more nodes. It also continually pings nodes in order to establish their
// connectivity. Unresponsive nodes are aggressively removed.
func (g *Gateway) threadedNodeManager() {
	if g.threads.Add() != nil {
		return
	}
	defer g.threads.Done()

	for {
		select {
		case <-time.After(5 * time.Second):
		case <-g.threads.StopChan():
			return
		}

		g.mu.RLock()
		numNodes := len(g.nodes)
		peer, err := g.randomPeer()
		g.mu.RUnlock()
		if err != nil {
			// can't do much until we have peers
			continue
		}

		if numNodes < minNodeListLen {
			err := g.RPC(peer, "ShareNodes", g.requestNodes)
			if err != nil {
				g.log.Debugf("WARN: RPC ShareNodes failed on peer %q: %v", peer, err)
				continue
			}
		}

		// find an untested node to check
		g.mu.RLock()
		node, err := g.randomNode()
		g.mu.RUnlock()
		if err != nil {
			continue
		}

		// try to connect
		conn, err := net.DialTimeout("tcp", string(node), dialTimeout)
		if err != nil {
			g.mu.Lock()
			g.removeNode(node)
			g.save()
			g.mu.Unlock()
			continue
		}
		// if connection succeeds, supply an unacceptable version to ensure
		// they won't try to add us as a peer
		encoding.WriteObject(conn, "0.0.0")
		conn.Close()
		// sleep for an extra 10 minutes after success; we don't want to spam
		// connectable nodes
		select {
		case <-time.After(10 * time.Minute):
		case <-g.threads.StopChan():
			return
		}
	}
}
<commit_msg>Add more descriptive logging when removing a node<commit_after>package gateway

import (
	"errors"
	"net"
	"time"

	"github.com/NebulousLabs/Sia/crypto"
	"github.com/NebulousLabs/Sia/encoding"
	"github.com/NebulousLabs/Sia/modules"
)

const (
	maxSharedNodes = 10
	minPeers       = 3
)

var (
	errNodeExists = errors.New("node already added")
	errOurAddress = errors.New("can't add our own address")
)

// addNode adds an address to the set of nodes on the network.
func (g *Gateway) addNode(addr modules.NetAddress) error {
	if addr == g.myAddr {
		return errOurAddress
	} else if _, exists := g.nodes[addr]; exists {
		return errNodeExists
	} else if addr.IsValid() != nil {
		return errors.New("address is not valid: " + string(addr))
	} else if net.ParseIP(addr.Host()) == nil {
		return errors.New("address must be an IP address: " + string(addr))
	}
	g.nodes[addr] = struct{}{}
	return nil
}

func (g *Gateway) removeNode(addr modules.NetAddress) error {
	if _, exists := g.nodes[addr]; !exists {
		return errors.New("no record of that node")
	}
	delete(g.nodes, addr)
	return nil
}

func (g *Gateway) randomNode() (modules.NetAddress, error) {
	if len(g.nodes) > 0 {
		r, _ := crypto.RandIntn(len(g.nodes))
		for node := range g.nodes {
			if r <= 0 {
				return node, nil
			}
			r--
		}
	}

	return "", errNoPeers
}

// shareNodes is the receiving end of the ShareNodes RPC. It writes up to 10
// randomly selected nodes to the caller.
func (g *Gateway) shareNodes(conn modules.PeerConn) error {
	g.mu.RLock()
	var nodes []modules.NetAddress
	for node := range g.nodes {
		if len(nodes) == maxSharedNodes {
			break
		}
		nodes = append(nodes, node)
	}
	g.mu.RUnlock()
	return encoding.WriteObject(conn, nodes)
}

// requestNodes is the calling end of the ShareNodes RPC.
func (g *Gateway) requestNodes(conn modules.PeerConn) error {
	var nodes []modules.NetAddress
	if err := encoding.ReadObject(conn, &nodes, maxSharedNodes*modules.MaxEncodedNetAddressLength); err != nil {
		return err
	}
	g.mu.Lock()
	for _, node := range nodes {
		err := g.addNode(node)
		if err != nil && err != errNodeExists && err != errOurAddress {
			g.log.Printf("WARN: peer '%v' sent the invalid addr '%v'", conn.RPCAddr(), node)
		}
	}
	g.save()
	g.mu.Unlock()
	return nil
}

// threadedNodeManager tries to keep the Gateway's node list healthy. As long
// as the Gateway has fewer than minNodeListSize nodes, it asks a random peer
// for more nodes. It also continually pings nodes in order to establish their
// connectivity. Unresponsive nodes are aggressively removed.
func (g *Gateway) threadedNodeManager() {
	if g.threads.Add() != nil {
		return
	}
	defer g.threads.Done()

	for {
		select {
		case <-time.After(5 * time.Second):
		case <-g.threads.StopChan():
			return
		}

		g.mu.RLock()
		numNodes := len(g.nodes)
		peer, err := g.randomPeer()
		g.mu.RUnlock()
		if err != nil {
			// can't do much until we have peers
			continue
		}

		if numNodes < minNodeListLen {
			err := g.RPC(peer, "ShareNodes", g.requestNodes)
			if err != nil {
				g.log.Debugf("WARN: RPC ShareNodes failed on peer %q: %v", peer, err)
				continue
			}
		}

		// find an untested node to check
		g.mu.RLock()
		node, err := g.randomNode()
		g.mu.RUnlock()
		if err != nil {
			continue
		}

		// try to connect
		conn, err := net.DialTimeout("tcp", string(node), dialTimeout)
		if err != nil {
			g.mu.Lock()
			g.removeNode(node)
			g.save()
			g.mu.Unlock()
			g.log.Debugf("INFO: removing node %q because dialing it failed: %v", node, err)
			continue
		}
		// if connection succeeds, supply an unacceptable version to ensure
		// they won't try to add us as a peer
		encoding.WriteObject(conn, "0.0.0")
		conn.Close()
		// sleep for an extra 10 minutes after success; we don't want to spam
		// connectable nodes
		select {
		case <-time.After(10 * time.Minute):
		case <-g.threads.StopChan():
			return
		}
	}
}
<|endoftext|>


<commit_before>package utils

import (
	"testing"
	"time"

	"github.com/stretchr/testify/assert"
)

func TestRepeat(t *testing.T) {
	closing := make(chan bool)
	count := 0
	defer close(closing)

	Repeat(func() { count++ }, 1*time.Millisecond, closing)
	time.Sleep(5 * time.Millisecond)
	assert.True(t, count > 0)
}
<commit_msg>fixed a flaky test<commit_after>package utils

import (
	"testing"
	"time"

	"github.com/stretchr/testify/assert"
)

func TestRepeat(t *testing.T) {
	closing := make(chan bool)
	count := 0
	defer close(closing)

	Repeat(func() { count++ }, 1*time.Millisecond, closing)
	time.Sleep(10 * time.Millisecond)
	assert.True(t, count > 0)
}
<|endoftext|>


<commit_before>/*
 *    Copyright (C) 2014 Michael Wendland
 *
 *    This program is free software: you can redistribute it and/or modify
 *    it under the terms of the GNU Affero General Public License as published
 *    by the Free Software Foundation, either version 3 of the License, or
 *    (at your option) any later version.
 *
 *    This program is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *    GNU Affero General Public License for more details.
 *
 *    You should have received a copy of the GNU Affero General Public License
 *    along with this program.  If not, see <http://www.gnu.org/licenses/>.
 *
 *    Authors:
 *      Michael Wendland <michiwend@michiwend.com>
 */

// RSS module for beehive
package rssbee

import (
	"github.com/muesli/beehive/app"
	"github.com/muesli/beehive/modules"
    rss "github.com/jteeuwen/go-pkg-rss"
)

var (
    eventChan chan modules.Event
)

type RSSBee struct {
	some_flag string
}

func (mod *RSSBee) Name() string {
	return "rssbee"
}

func (mod *RSSBee) Description() string {
	return "A bee that manages RSS-feeds"
}

func (mod *RSSBee) Events() []modules.EventDescriptor {
	events := []modules.EventDescriptor{
        modules.EventDescriptor{
            Namespace: mod.Name(),
            Name: "incoming",
            Description: "A new post has been received through the Feed",
            Options: []modules.PlaceholderDescriptor{
                Name
            }
        }
    }
	return events
}

func (mod *RSSBee) Actions() []modules.ActionDescriptor {
	actions := []modules.ActionDescriptor{}
	return actions
}

func (mod *RSSBee) Run(eventChan chan modules.Event) {
/*	helloEvent := modules.Event{
		Namespace: mod.Name(),
		Name:      "Say Hello",
		Options:   []modules.Placeholder{},
	}

	eventChan <- helloEvent*/
}

func (mod *RSSBee) Action(action modules.Action) []modules.Placeholder {
	return []modules.Placeholder{}
}

func init() {
	hello := RSSBee{}

	app.AddFlags([]app.CliFlag{
		app.CliFlag{&hello.some_flag, "foo", "default value", "some option"},
	})

	modules.RegisterModule(&hello)
}
<commit_msg>implemented rssbee<commit_after>/*
 *    Copyright (C) 2014 Daniel 'grindhold' Brendle
 *
 *    This program is free software: you can redistribute it and/or modify
 *    it under the terms of the GNU Affero General Public License as published
 *    by the Free Software Foundation, either version 3 of the License, or
 *    (at your option) any later version.
 *
 *    This program is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *    GNU Affero General Public License for more details.
 *
 *    You should have received a copy of the GNU Affero General Public License
 *    along with this program.  If not, see <http://www.gnu.org/licenses/>.
 *
 *    Authors:
 *      Daniel 'grindhold' Brendle <grindhold@skarphed.org>
 */

// RSS module for beehive
package rssbee

import (
    "fmt"
    "os"
    "time"
	"github.com/muesli/beehive/app"
	"github.com/muesli/beehive/modules"
    rss "github.com/jteeuwen/go-pkg-rss"
)

var (
    eventChan chan modules.Event
)

type RSSBee struct {
	url string
}

func (mod *RSSBee) Name() string {
	return "rssbee"
}

func (mod *RSSBee) Description() string {
	return "A bee that manages RSS-feeds"
}

func (mod *RSSBee) Events() []modules.EventDescriptor {
	events := []modules.EventDescriptor{
        modules.EventDescriptor{
            Namespace: mod.Name(),
            Name: "newitem",
            Description: "A new item has been received through the Feed",
            Options: []modules.PlaceholderDescriptor{
                modules.PlaceholderDescriptor{
                    Name:           "title",
                    Description:    "Title of the Item",
                    Type:           "string",
                },
                modules.PlaceholderDescriptor{
                    Name:           "links",
                    Description:    "Links referenced by the Item",
                    Type:           "[]string",
                },
                modules.PlaceholderDescriptor{
                    Name:           "description",
                    Description:    "Description of the Item",
                    Type:           "string",
                },
                modules.PlaceholderDescriptor{
                    Name:           "author",
                    Description:    "The person who wrote the Item",
                    Type:           "string",
                },
                modules.PlaceholderDescriptor{
                    Name:           "categories",
                    Description:    "Categories that the Item belongs to",
                    Type:           "[]string",
                },
                modules.PlaceholderDescriptor{
                    Name:           "comments",
                    Description:    "Comments of the Item",
                    Type:           "string",
                },
                modules.PlaceholderDescriptor{
                    Name:           "enclosures",
                    Description:    "Enclosures related to Item",
                    Type:           "[]string",
                },
                modules.PlaceholderDescriptor{
                    Name:           "guid",
                    Description:    "Global unique ID attached to the Item",
                    Type:           "string",
                },
                modules.PlaceholderDescriptor{
                    Name:           "pubdate",
                    Description:    "Date the Item was published on",
                    Type:           "string",
                },
                modules.PlaceholderDescriptor{
                    Name:           "source",
                    Description:    "Source of the Item",
                    Type:           "string",
                },
            },
        },
    }
	return events
}

func (mod *RSSBee) Actions() []modules.ActionDescriptor {
	actions := []modules.ActionDescriptor{}
	return actions
}

func PollFeed(uri string, timeout int) {
    feed := rss.New(timeout, true, chanHandler, itemHandler)

    for {
            if err := feed.Fetch(uri, nil); err != nil {
                fmt.Fprintf(os.Stderr, "[e] %s: %s", uri, err)
                return
            }

        <-time.After(time.Duration(feed.SecondsTillUpdate() * 1e9))
    }
}

func chanHandler(feed *rss.Feed, newchannels []*rss.Channel) {
    //fmt.Printf("%d new channel(s) in %s\n", len(newchannels), feed.Url)
}

func itemHandler(feed *rss.Feed, ch *rss.Channel, newitems []*rss.Item) {
    for i := range(newitems) {
        var links []string
        var categories []string
        var enclosures []string

        for j := range(newitems[i].Links) {
            links = append(links, newitems[i].Links[j].Href)
        }

        for j := range(newitems[i].Categories) {
            categories = append(categories, newitems[i].Categories[j].Text)
        }

        for j := range(newitems[i].Enclosures) {
            enclosures = append(enclosures, newitems[i].Enclosures[j].Url)
        }

        newitemEvent := modules.Event{
            Namespace: "rssbee",
            Name: "newitem",
            Options: []modules.Placeholder{
                modules.Placeholder {
                    Name:   "title",
                    Type:   "string",
                    Value:  newitems[i].Title,
                },
                modules.Placeholder{
                    Name:   "links",
                    Type:   "[]string",
                    Value:  links,
                },
                modules.Placeholder{
                    Name:   "description",
                    Type:   "string",
                    Value:  newitems[i].Description,
                },
                modules.Placeholder{
                    Name:   "author",
                    Type:   "string",
                    Value:  newitems[i].Author.Name,
                },
                modules.Placeholder{
                    Name:   "categories",
                    Type:   "[]string",
                    Value:  categories,
                },
                modules.Placeholder{
                    Name:   "comments",
                    Type:   "string",
                    Value:  newitems[i].Comments,
                },
                modules.Placeholder{
                    Name:   "enclosures",
                    Type:   "[]string",
                    Value:  enclosures,
                },
                modules.Placeholder{
                    Name:   "guid",
                    Type:   "string",
                    Value:  newitems[i].Guid,
                },
                modules.Placeholder{
                    Name:   "pubdate",
                    Type:   "string",
                    Value:  newitems[i].PubDate,
                },
                modules.Placeholder{
                    Name:   "source",
                    Type:   "string",
                    Value:  newitems[i].Source.Url,
                },
            },
        }
        eventChan <- newitemEvent
    }
    fmt.Printf("%d new item(s) in %s\n", len(newitems), feed.Url)
}

func (mod *RSSBee) Run(eventChan chan modules.Event) {
    go PollFeed(mod.url, 5)
}

func (mod *RSSBee) Action(action modules.Action) []modules.Placeholder {
	return []modules.Placeholder{}
}

func init() {
	rssbee := RSSBee{}

	app.AddFlags([]app.CliFlag{
		app.CliFlag{&rssbee.url, "url", "", "The URL, this bee can find the RSS-Feed at"},
	})

	modules.RegisterModule(&rssbee)
}
<|endoftext|>


<commit_before>package main

import (
	"strings"
)

// Returns an RST representation of this PluginDocument
func PluginDocumentToRST(doc PluginDocument) string {
	// Heading
	result := doc.PluginName
	if doc.Comment != "" {
		result += " " + doc.Comment
	}
	result += "\n" + strings.Repeat("=", len(result))

	//
	result += "\n\n"
	result += rstAddLineBreaks(doc.Description, "")
	result += "\n\n"

	//
	if len(doc.Parameters) > 0 {
		result += "Parameters\n----------\n\n"

		for _, p := range doc.Parameters {
			result += "**" + p.name + "**\n"
			result += rstAddLineBreaks(p.desc, "  ")
			result += "\n"
		}
	}

	//
	for paramSetName, paramSet := range doc.ParameterSets {
		head := "Parameters (from " + paramSetName + ")"
		result += head + "\n"
		result += strings.Repeat("-", len(head)) + "\n\n"

		for _, p := range paramSet {
			result += "**" + p.name + "**\n"
			result += rstAddLineBreaks(p.desc, "  ")
			result += "\n"
		}
	}

	//
	result += "Example\n-------\n\n"
	result += ".. code-block:: yaml\n\n"
	result += "\t" + doc.ExampleFirstLine + "\n"
	for _, line := range doc.Example {
		result += "\t" + line + "\n"
	}

	return result
}

func rstAddLineBreaks(text string, prefix string) string {
	sentences := strings.Split(text, ". ")
	result := ""
	skipPrefix := false
	isEnum := false

	for _, s := range sentences {
		sLower := strings.ToLower(s)
		sTrim := strings.Trim(s, " ")
		switch {
		case len(sTrim) <= 1:
			// ignore

		case isEnum && sTrim[0] == enumChar:
			postfix := ". "
			if sTrim[len(sTrim)-1] == '.' {
				postfix = " "
			}
			result += "\n" + prefix + s + postfix

		case isEnum:
			result += sTrim + ". "
			if sLower[0] != ' ' && sLower[1] == ' ' {
				isEnum = false
			}

		case sTrim[0] == enumChar:
			result += prefix + s + ". "
			isEnum = true

		case strings.Contains(sLower, "e.g") || strings.Contains(sLower, "i.e"):
			result += prefix + s + ". "
			skipPrefix = true

		default:
			postfix := ".\n"
			if sTrim[len(sTrim)-1] == '.' {
				postfix = "\n"
			}

			if skipPrefix {
				result += s + postfix
				skipPrefix = false
			} else {
				result += prefix + s + postfix
			}
		}
	}

	if len(result) > 1 && result[len(result)-1] != '\n' {
		result += "\n"
	}

	return result
}

<commit_msg>Fine-tune RST output<commit_after>package main

import (
	"strings"
)

// Returns an RST representation of this PluginDocument
func PluginDocumentToRST(doc PluginDocument) string {
	result := ""

	// Comment
	result += ".. Autogenerated by Gollum RST generator (docs/generator/*.go)\n\n"

	// Heading
	result += doc.PluginName
	if doc.Comment != "" {
		result += " " + doc.Comment
	}
	result += "\n" + strings.Repeat("=", len(result))

	//
	result += "\n\n"
	result += rstAddLineBreaks(doc.Description, "")
	result += "\n\n"

	//
	if len(doc.Parameters) > 0 {
		result += "Parameters\n----------\n\n"

		for _, p := range doc.Parameters {
			result += "**" + p.name + "**\n"
			result += rstAddLineBreaks(p.desc, "  ")
			result += "\n"
		}
	}

	//
	for paramSetName, paramSet := range doc.ParameterSets {
		if len(paramSet) == 0 {
			// Skip title for empty param sets
			continue
		}
		head := "Parameters (from " + paramSetName + ")"
		result += head + "\n"
		result += strings.Repeat("-", len(head)) + "\n\n"

		for _, p := range paramSet {
			result += "**" + p.name + "**\n"
			result += rstAddLineBreaks(p.desc, "  ")
			result += "\n"
		}
	}

	//
	if len(doc.Example) > 0 {
		result += "Example\n-------\n\n"
		result += ".. code-block:: yaml\n\n"
		result += "\t" + doc.ExampleFirstLine + "\n"
		for _, line := range doc.Example {
			result += "\t" + line + "\n"
		}
	}

	return result
}

func rstAddLineBreaks(text string, prefix string) string {
	sentences := strings.Split(text, ". ")
	result := ""
	skipPrefix := false
	isEnum := false

	for _, s := range sentences {
		sLower := strings.ToLower(s)
		sTrim := strings.Trim(s, " ")
		switch {
		case len(sTrim) <= 1:
			// ignore

		case isEnum && sTrim[0] == enumChar:
			postfix := ". "
			if sTrim[len(sTrim)-1] == '.' {
				postfix = " "
			}
			result += "\n" + prefix + s + postfix

		case isEnum:
			result += sTrim + ". "
			if sLower[0] != ' ' && sLower[1] == ' ' {
				isEnum = false
			}

		case sTrim[0] == enumChar:
			result += prefix + s + ". "
			isEnum = true

		case strings.Contains(sLower, "e.g") || strings.Contains(sLower, "i.e"):
			result += prefix + s + ". "
			skipPrefix = true

		default:
			postfix := ".\n"
			if sTrim[len(sTrim)-1] == '.' {
				postfix = "\n"
			}

			if skipPrefix {
				result += s + postfix
				skipPrefix = false
			} else {
				result += prefix + s + postfix
			}
		}
	}

	if len(result) > 1 && result[len(result)-1] != '\n' {
		result += "\n"
	}

	return result
}

<|endoftext|>


<commit_before>package wallet

import (
	"errors"
	"sort"

	"github.com/NebulousLabs/Sia/crypto"
	"github.com/NebulousLabs/Sia/types"
)

var (
	errDefragNotNeeded = errors.New("defragging not needed, wallet is already sufficiently defragged")
)

// managedCreateDefragTransaction creates a transaction that spends multiple existing
// wallet outputs into a single new address.
func (w *Wallet) managedCreateDefragTransaction() ([]types.Transaction, error) {
	w.mu.Lock()
	defer w.mu.Unlock()

	consensusHeight, err := dbGetConsensusHeight(w.dbTx)
	if err != nil {
		return nil, err
	}

	// Collect a value-sorted set of siacoin outputs.
	var so sortedOutputs
	err = dbForEachSiacoinOutput(w.dbTx, func(scoid types.SiacoinOutputID, sco types.SiacoinOutput) {
		if w.checkOutput(w.dbTx, consensusHeight, scoid, sco) == nil {
			so.ids = append(so.ids, scoid)
			so.outputs = append(so.outputs, sco)
		}
	})
	if err != nil {
		return nil, err
	}
	sort.Sort(sort.Reverse(so))

	// Only defrag if there are enough outputs to merit defragging.
	if len(so.ids) <= defragThreshold {
		return nil, errDefragNotNeeded
	}

	// Skip over the 'defragStartIndex' largest outputs, so that the user can
	// still reasonably use their wallet while the defrag is happening.
	var amount types.Currency
	var parentTxn types.Transaction
	var spentScoids []types.SiacoinOutputID
	for i := defragStartIndex; i < defragStartIndex+defragBatchSize; i++ {
		scoid := so.ids[i]
		sco := so.outputs[i]

		// Add a siacoin input for this output.
		outputUnlockConditions := w.keys[sco.UnlockHash].UnlockConditions
		sci := types.SiacoinInput{
			ParentID:         scoid,
			UnlockConditions: outputUnlockConditions,
		}
		parentTxn.SiacoinInputs = append(parentTxn.SiacoinInputs, sci)
		spentScoids = append(spentScoids, scoid)

		// Add the output to the total fund
		amount = amount.Add(sco.Value)
	}

	// Create and add the output that will be used to fund the defrag
	// transaction.
	parentUnlockConditions, err := w.nextPrimarySeedAddress(w.dbTx)
	if err != nil {
		return nil, err
	}
	exactOutput := types.SiacoinOutput{
		Value:      amount,
		UnlockHash: parentUnlockConditions.UnlockHash(),
	}
	parentTxn.SiacoinOutputs = append(parentTxn.SiacoinOutputs, exactOutput)

	// Sign all of the inputs to the parent transaction.
	for _, sci := range parentTxn.SiacoinInputs {
		addSignatures(&parentTxn, types.FullCoveredFields, sci.UnlockConditions, crypto.Hash(sci.ParentID), w.keys[sci.UnlockConditions.UnlockHash()])
	}

	// Create the defrag transaction.
	refundAddr, err := w.nextPrimarySeedAddress(w.dbTx)
	if err != nil {
		return nil, err
	}

	// get the transaction fee
	w.mu.Unlock()
	minFee, _ := w.tpool.FeeEstimation()
	sizeAvgOutput := uint64(250)
	fee := minFee.Mul64(sizeAvgOutput * defragBatchSize)
	w.mu.Lock()

	txn := types.Transaction{
		SiacoinInputs: []types.SiacoinInput{{
			ParentID:         parentTxn.SiacoinOutputID(0),
			UnlockConditions: parentUnlockConditions,
		}},
		SiacoinOutputs: []types.SiacoinOutput{{
			Value:      amount.Sub(fee),
			UnlockHash: refundAddr.UnlockHash(),
		}},
		MinerFees: []types.Currency{fee},
	}
	addSignatures(&txn, types.FullCoveredFields, parentUnlockConditions, crypto.Hash(parentTxn.SiacoinOutputID(0)), w.keys[parentUnlockConditions.UnlockHash()])

	// Mark all outputs that were spent as spent.
	for _, scoid := range spentScoids {
		if err = dbPutSpentOutput(w.dbTx, types.OutputID(scoid), consensusHeight); err != nil {
			return nil, err
		}
	}
	// Mark the parent output as spent. Must be done after the transaction is
	// finished because otherwise the txid and output id will change.
	if err = dbPutSpentOutput(w.dbTx, types.OutputID(parentTxn.SiacoinOutputID(0)), consensusHeight); err != nil {
		return nil, err
	}

	// Construct the final transaction set
	return []types.Transaction{parentTxn, txn}, nil
}

// threadedDefragWallet computes the sum of the 15 largest outputs in the wallet and
// sends that sum to itself, effectively defragmenting the wallet. This defrag
// operation is only performed if the wallet has greater than defragThreshold
// outputs.
func (w *Wallet) threadedDefragWallet() {
	err := w.tg.Add()
	if err != nil {
		return
	}
	defer w.tg.Done()

	// Check that a defrag makes sense.
	w.mu.Lock()
	if !w.unlocked {
		// Can't defrag if the wallet is locked.
		w.mu.Unlock()
		return
	}
	w.mu.Unlock()

	// Create the defrag transaction.
	txnSet, err := w.managedCreateDefragTransaction()
	if err == errDefragNotNeeded {
		// benign
		return
	} else if err != nil {
		w.log.Println("WARN: couldn't create defrag transaction:", err)
		return
	}
	// Submit the defrag to the transaction pool.
	err = w.tpool.AcceptTransactionSet(txnSet)
	if err != nil {
		w.log.Println("WARN: defrag transaction was rejected:", err)
		return
	}
	w.log.Println("Submitting a transaction set to defragment the wallet's outputs, IDs:")
	for _, txn := range txnSet {
		w.log.Println("\t", txn.ID())
	}
}
<commit_msg>safer fee/locking pattern<commit_after>package wallet

import (
	"errors"
	"sort"

	"github.com/NebulousLabs/Sia/crypto"
	"github.com/NebulousLabs/Sia/types"
)

var (
	errDefragNotNeeded = errors.New("defragging not needed, wallet is already sufficiently defragged")
)

// managedCreateDefragTransaction creates a transaction that spends multiple existing
// wallet outputs into a single new address.
func (w *Wallet) managedCreateDefragTransaction() ([]types.Transaction, error) {
	minFee, _ := w.tpool.FeeEstimation()

	w.mu.Lock()
	defer w.mu.Unlock()

	consensusHeight, err := dbGetConsensusHeight(w.dbTx)
	if err != nil {
		return nil, err
	}

	// Collect a value-sorted set of siacoin outputs.
	var so sortedOutputs
	err = dbForEachSiacoinOutput(w.dbTx, func(scoid types.SiacoinOutputID, sco types.SiacoinOutput) {
		if w.checkOutput(w.dbTx, consensusHeight, scoid, sco) == nil {
			so.ids = append(so.ids, scoid)
			so.outputs = append(so.outputs, sco)
		}
	})
	if err != nil {
		return nil, err
	}
	sort.Sort(sort.Reverse(so))

	// Only defrag if there are enough outputs to merit defragging.
	if len(so.ids) <= defragThreshold {
		return nil, errDefragNotNeeded
	}

	// Skip over the 'defragStartIndex' largest outputs, so that the user can
	// still reasonably use their wallet while the defrag is happening.
	var amount types.Currency
	var parentTxn types.Transaction
	var spentScoids []types.SiacoinOutputID
	for i := defragStartIndex; i < defragStartIndex+defragBatchSize; i++ {
		scoid := so.ids[i]
		sco := so.outputs[i]

		// Add a siacoin input for this output.
		outputUnlockConditions := w.keys[sco.UnlockHash].UnlockConditions
		sci := types.SiacoinInput{
			ParentID:         scoid,
			UnlockConditions: outputUnlockConditions,
		}
		parentTxn.SiacoinInputs = append(parentTxn.SiacoinInputs, sci)
		spentScoids = append(spentScoids, scoid)

		// Add the output to the total fund
		amount = amount.Add(sco.Value)
	}

	// Create and add the output that will be used to fund the defrag
	// transaction.
	parentUnlockConditions, err := w.nextPrimarySeedAddress(w.dbTx)
	if err != nil {
		return nil, err
	}
	exactOutput := types.SiacoinOutput{
		Value:      amount,
		UnlockHash: parentUnlockConditions.UnlockHash(),
	}
	parentTxn.SiacoinOutputs = append(parentTxn.SiacoinOutputs, exactOutput)

	// Sign all of the inputs to the parent transaction.
	for _, sci := range parentTxn.SiacoinInputs {
		addSignatures(&parentTxn, types.FullCoveredFields, sci.UnlockConditions, crypto.Hash(sci.ParentID), w.keys[sci.UnlockConditions.UnlockHash()])
	}

	// Create the defrag transaction.
	refundAddr, err := w.nextPrimarySeedAddress(w.dbTx)
	if err != nil {
		return nil, err
	}

	// compute the transaction fee.
	sizeAvgOutput := uint64(250)
	fee := minFee.Mul64(sizeAvgOutput * defragBatchSize)

	txn := types.Transaction{
		SiacoinInputs: []types.SiacoinInput{{
			ParentID:         parentTxn.SiacoinOutputID(0),
			UnlockConditions: parentUnlockConditions,
		}},
		SiacoinOutputs: []types.SiacoinOutput{{
			Value:      amount.Sub(fee),
			UnlockHash: refundAddr.UnlockHash(),
		}},
		MinerFees: []types.Currency{fee},
	}
	addSignatures(&txn, types.FullCoveredFields, parentUnlockConditions, crypto.Hash(parentTxn.SiacoinOutputID(0)), w.keys[parentUnlockConditions.UnlockHash()])

	// Mark all outputs that were spent as spent.
	for _, scoid := range spentScoids {
		if err = dbPutSpentOutput(w.dbTx, types.OutputID(scoid), consensusHeight); err != nil {
			return nil, err
		}
	}
	// Mark the parent output as spent. Must be done after the transaction is
	// finished because otherwise the txid and output id will change.
	if err = dbPutSpentOutput(w.dbTx, types.OutputID(parentTxn.SiacoinOutputID(0)), consensusHeight); err != nil {
		return nil, err
	}

	// Construct the final transaction set
	return []types.Transaction{parentTxn, txn}, nil
}

// threadedDefragWallet computes the sum of the 15 largest outputs in the wallet and
// sends that sum to itself, effectively defragmenting the wallet. This defrag
// operation is only performed if the wallet has greater than defragThreshold
// outputs.
func (w *Wallet) threadedDefragWallet() {
	err := w.tg.Add()
	if err != nil {
		return
	}
	defer w.tg.Done()

	// Check that a defrag makes sense.
	w.mu.Lock()
	if !w.unlocked {
		// Can't defrag if the wallet is locked.
		w.mu.Unlock()
		return
	}
	w.mu.Unlock()

	// Create the defrag transaction.
	txnSet, err := w.managedCreateDefragTransaction()
	if err == errDefragNotNeeded {
		// benign
		return
	} else if err != nil {
		w.log.Println("WARN: couldn't create defrag transaction:", err)
		return
	}
	// Submit the defrag to the transaction pool.
	err = w.tpool.AcceptTransactionSet(txnSet)
	if err != nil {
		w.log.Println("WARN: defrag transaction was rejected:", err)
		return
	}
	w.log.Println("Submitting a transaction set to defragment the wallet's outputs, IDs:")
	for _, txn := range txnSet {
		w.log.Println("\t", txn.ID())
	}
}
<|endoftext|>


<commit_before>/*
 *    Copyright (C) 2014 Christian Muehlhaeuser
 *
 *    This program is free software: you can redistribute it and/or modify
 *    it under the terms of the GNU Affero General Public License as published
 *    by the Free Software Foundation, either version 3 of the License, or
 *    (at your option) any later version.
 *
 *    This program is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *    GNU Affero General Public License for more details.
 *
 *    You should have received a copy of the GNU Affero General Public License
 *    along with this program.  If not, see <http://www.gnu.org/licenses/>.
 *
 *    Authors:
 *      Christian Muehlhaeuser <muesli@gmail.com>
 */

// beehive's web-module.
package webbee

import (
	"encoding/json"
	"github.com/hoisie/web"
	"github.com/muesli/beehive/modules"
	"io/ioutil"
	"log"
)

var (
	eventChan chan modules.Event
)

type WebBee struct {
	Addr string
}

func (mod *WebBee) Name() string {
	return "webbee"
}

func (mod *WebBee) Description() string {
	return "A RESTful HTTP module for beehive"
}

func (mod *WebBee) Run(cin chan modules.Event) {
	eventChan = cin
	go web.Run(mod.Addr)
}

func (mod *WebBee) Events() []modules.EventDescriptor {
	events := []modules.EventDescriptor{
		modules.EventDescriptor{
			Namespace:   mod.Name(),
			Name:        "post",
			Description: "A POST call was received by the HTTP server",
			Options: []modules.PlaceholderDescriptor{
				modules.PlaceholderDescriptor{
					Name:        "json",
					Description: "JSON map received from caller",
					Type:        "map",
				},
				modules.PlaceholderDescriptor{
					Name:        "ip",
					Description: "IP of the caller",
					Type:        "string",
				},
			},
		},
		modules.EventDescriptor{
			Namespace:   mod.Name(),
			Name:        "get",
			Description: "A GET call was received by the HTTP server",
			Options: []modules.PlaceholderDescriptor{
				modules.PlaceholderDescriptor{
					Name:        "query_params",
					Description: "Map of query parameters received from caller",
					Type:        "map",
				},
				modules.PlaceholderDescriptor{
					Name:        "ip",
					Description: "IP of the caller",
					Type:        "string",
				},
			},
		},
	}
	return events
}

func (mod *WebBee) Actions() []modules.ActionDescriptor {
	actions := []modules.ActionDescriptor{}
	return actions
}

func (mod *WebBee) Action(action modules.Action) []modules.Placeholder {
	outs := []modules.Placeholder{}
	return outs
}

func GetRequest(ctx *web.Context) {
	//FIXME
	ms := make(map[string]string)
	ev := modules.Event{
		Namespace: "webbee",
		Name:      "get",
		Options: []modules.Placeholder{
			modules.Placeholder{
				Name:  "query_params",
				Type:  "map",
				Value: ms,
			},
			modules.Placeholder{
				Name:  "ip",
				Type:  "string",
				Value: "tbd",
			},
		},
	}
	eventChan <- ev
}

func PostRequest(ctx *web.Context) {
	b, err := ioutil.ReadAll(ctx.Request.Body)
	if err != nil {
		log.Println("Error:", err)
		return
	}

	var payload interface{}
	err = json.Unmarshal(b, &payload)
	if err != nil {
		log.Println("Error:", err)
		return
	}

	ev := modules.Event{
		Namespace: "webbee",
		Name:      "post",
		Options: []modules.Placeholder{
			modules.Placeholder{
				Name:  "json",
				Type:  "map",
				Value: payload,
			},
			modules.Placeholder{
				Name:  "ip",
				Type:  "string",
				Value: "tbd",
			},
		},
	}
	eventChan <- ev
}

func init() {
	w := WebBee{
		Addr: "0.0.0.0:12345",
	}
	web.Get("/event", GetRequest)
	web.Post("/event", PostRequest)

	modules.RegisterModule(&w)
}
<commit_msg>* addr needs not be public at this point.<commit_after>/*
 *    Copyright (C) 2014 Christian Muehlhaeuser
 *
 *    This program is free software: you can redistribute it and/or modify
 *    it under the terms of the GNU Affero General Public License as published
 *    by the Free Software Foundation, either version 3 of the License, or
 *    (at your option) any later version.
 *
 *    This program is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *    GNU Affero General Public License for more details.
 *
 *    You should have received a copy of the GNU Affero General Public License
 *    along with this program.  If not, see <http://www.gnu.org/licenses/>.
 *
 *    Authors:
 *      Christian Muehlhaeuser <muesli@gmail.com>
 */

// beehive's web-module.
package webbee

import (
	"encoding/json"
	"github.com/hoisie/web"
	"github.com/muesli/beehive/modules"
	"io/ioutil"
	"log"
)

var (
	eventChan chan modules.Event
)

type WebBee struct {
	addr string
}

func (mod *WebBee) Name() string {
	return "webbee"
}

func (mod *WebBee) Description() string {
	return "A RESTful HTTP module for beehive"
}

func (mod *WebBee) Run(cin chan modules.Event) {
	eventChan = cin
	go web.Run(mod.addr)
}

func (mod *WebBee) Events() []modules.EventDescriptor {
	events := []modules.EventDescriptor{
		modules.EventDescriptor{
			Namespace:   mod.Name(),
			Name:        "post",
			Description: "A POST call was received by the HTTP server",
			Options: []modules.PlaceholderDescriptor{
				modules.PlaceholderDescriptor{
					Name:        "json",
					Description: "JSON map received from caller",
					Type:        "map",
				},
				modules.PlaceholderDescriptor{
					Name:        "ip",
					Description: "IP of the caller",
					Type:        "string",
				},
			},
		},
		modules.EventDescriptor{
			Namespace:   mod.Name(),
			Name:        "get",
			Description: "A GET call was received by the HTTP server",
			Options: []modules.PlaceholderDescriptor{
				modules.PlaceholderDescriptor{
					Name:        "query_params",
					Description: "Map of query parameters received from caller",
					Type:        "map",
				},
				modules.PlaceholderDescriptor{
					Name:        "ip",
					Description: "IP of the caller",
					Type:        "string",
				},
			},
		},
	}
	return events
}

func (mod *WebBee) Actions() []modules.ActionDescriptor {
	actions := []modules.ActionDescriptor{}
	return actions
}

func (mod *WebBee) Action(action modules.Action) []modules.Placeholder {
	outs := []modules.Placeholder{}
	return outs
}

func GetRequest(ctx *web.Context) {
	//FIXME
	ms := make(map[string]string)
	ev := modules.Event{
		Namespace: "webbee",
		Name:      "get",
		Options: []modules.Placeholder{
			modules.Placeholder{
				Name:  "query_params",
				Type:  "map",
				Value: ms,
			},
			modules.Placeholder{
				Name:  "ip",
				Type:  "string",
				Value: "tbd",
			},
		},
	}
	eventChan <- ev
}

func PostRequest(ctx *web.Context) {
	b, err := ioutil.ReadAll(ctx.Request.Body)
	if err != nil {
		log.Println("Error:", err)
		return
	}

	var payload interface{}
	err = json.Unmarshal(b, &payload)
	if err != nil {
		log.Println("Error:", err)
		return
	}

	ev := modules.Event{
		Namespace: "webbee",
		Name:      "post",
		Options: []modules.Placeholder{
			modules.Placeholder{
				Name:  "json",
				Type:  "map",
				Value: payload,
			},
			modules.Placeholder{
				Name:  "ip",
				Type:  "string",
				Value: "tbd",
			},
		},
	}
	eventChan <- ev
}

func init() {
	w := WebBee{
		addr: "0.0.0.0:12345",
	}
	web.Get("/event", GetRequest)
	web.Post("/event", PostRequest)

	modules.RegisterModule(&w)
}
<|endoftext|>


<commit_before>package main

import (
	"bytes"
	"encoding/json"
	"errors"
	"fmt"
	"html/template"
	"io"
	"io/ioutil"
	"os"
	"path/filepath"
	"strings"

	"github.com/urfave/cli"
)

type ThreeG struct {
	IMEI           string `json:"imei"`
	IMSI           string `json:"imsi"`
	APN            string `json:"apn"`
	Dial           string `json:"dial"`
	Username       string `json:"username"`
	Password       string `json:"password"`
	DefaultGateway bool   `json:"defaultGateway"`
}

func (c *ThreeG) Prepare() *ThreeG {
	if c.Username == "" {
		c.Username = "0"
	}
	if c.Password == "" {
		c.Password = "0"
	}
	return c
}

func (c *ThreeG) WriteTo(out io.Writer) error {
	cfgTpl := `
[Dialer Defaults]
Init2 = ATQ0 V1 E1 S0=0 &C1 &D2
Modem Type = USB Modem
; Phone = <Target Phone Number>
Phone = {{.Dial}}
ISDN = 0
; Username = <Your Login Name>, 0 if not specified
Username = {{.Username}}
; Password = <Your Password>, 0 if not specified
Password = {{.Password}}
Init1 = ATZ
; modem command port (by IMSI)
Modem = /dev/{{.IMSI}}.imsi
Baud = 115200
; set APN
Init3 = AT+CGDCONT=1,"IP","{{.APN}}"
Stupid Mode = 1
	`
	tpl, err := template.New("cfg").Parse(cfgTpl)
	if err != nil {
		return err
	}
	return tpl.Execute(out, c)
}

type ThreeGState struct {
	Enabled bool    `json:"enabled"`
	Configg *ThreeG `json:"config"`
}

func ThreegCMD(ctx *cli.Context) error {
	if ctx.IsSet(enableFlag) {
		return EnableThreeg(ctx)
	}
	if ctx.IsSet(disableFlag) {
		return DisableThreeg(ctx)
	}
	//if ctx.IsSet(removeFlag) {
	//return RemoveThreeg(ctx)
	//}
	if ctx.IsSet(configFlag) {
		return configThreegCMD(ctx)
	}
	return nil
}

func configThreegCMD(ctx *cli.Context) error {
	base := ctx.String("dir")
	name := ctx.String("name")
	src := ctx.String("config")
	if src == "" {
		return errors.New("fconf: missing configuration source file")
	}
	var b []byte
	var err error
	if src == "stdin" {
		b, err = ReadFromStdin()
		if err != nil {
			return err
		}
	} else {
		b, err = ioutil.ReadFile(src)
		if err != nil {
			return err
		}
	}
	e := ThreeG{}
	err = json.Unmarshal(b, &e)
	if err != nil {
		return err
	}
	e.Prepare()
	err = checkDir(base)
	if err != nil {
		return err
	}
	if strings.Contains(name, "%s") {
		name = fmt.Sprintf(name, e.IMEI)
	}
	filename := filepath.Join(base, name)
	var buf bytes.Buffer
	err = e.WriteTo(&buf)
	if err != nil {
		return err
	}
	err = ioutil.WriteFile(filename, buf.Bytes(), 0644)
	if err != nil {
		return err
	}
	fmt.Printf("successful written 3G configuration to %s \n", filename)
	state := &ThreeGState{Configg: &e}
	ms, err := threeGState(e.IMEI)
	if err == nil {
		state.Enabled = ms.Enabled
	}
	b, _ = json.Marshal(state)
	setInterface(ctx, e.IMEI)
	return keepState(
		fmt.Sprintf(defaultThreeGGConfig, e.IMEI), b)
}

func threeGState(i string) (*ThreeGState, error) {
	dir := os.Getenv("FCONF_CONFIGDIR")
	if dir == "" {
		dir = fconfConfigDir
	}
	b, err := ioutil.ReadFile(filepath.Join(dir,
		fmt.Sprintf(defaultThreeGGConfig, i)))
	if err != nil {
		return nil, err
	}
	f := &ThreeGState{}
	err = json.Unmarshal(b, f)
	if err != nil {
		return nil, err
	}
	if f.Configg == nil {
		return nil, ErrWrongStateFile
	}
	return f, nil
}

func EnableThreeg(ctx *cli.Context) error {
	if ctx.IsSet(configFlag) {
		err := configThreegCMD(ctx)
		if err != nil {
			return err
		}
	}
	i := getInterface(ctx)
	if i == "" {
		return errors.New("missing imei , you must specify imei")
	}
	e, err := threeGState(i)
	if err != nil {
		return err
	}
	service := "wvdial"
	err = restartService(service)
	if err != nil {
		return fmt.Errorf("ERROR: restarting systemd %v ", err)
	}
	err = enableService(service)
	if err != nil {
		return fmt.Errorf("ERROR: enabling systemd %v ", err)
	}
	e.Enabled = true
	data, err := json.Marshal(e)
	if err != nil {
		return err
	}
	fmt.Printf("successfully enabled 3g for %s \n", i)
	return keepState(
		fmt.Sprintf(defaultThreeGGConfig, i), data)
}

func DisableThreeg(ctx *cli.Context) error {
	if ctx.IsSet(configFlag) {
		fmt.Println("WARN: config flag will be ignored when diable flag is used")
	}
	i := getInterface(ctx)
	if i == "" {
		return errors.New("missing imei, you must specify imei")
	}
	e, err := threeGState(i)
	if err != nil {
		return err
	}
	e.Enabled = false
	data, err := json.Marshal(e)
	if err != nil {
		return err
	}
	service := "wvdial"
	err = stopService(service)
	if err != nil {
		return err
	}
	err = disableService(service)
	if err != nil {
		return err
	}
	fmt.Println("successfully disabled 3G for ", i)
	return keepState(
		fmt.Sprintf(defaultThreeGGConfig, i), data)
}
<commit_msg>3g: Add remove command<commit_after>package main

import (
	"bytes"
	"encoding/json"
	"errors"
	"fmt"
	"html/template"
	"io"
	"io/ioutil"
	"os"
	"path/filepath"
	"strings"

	"github.com/urfave/cli"
)

type ThreeG struct {
	IMEI           string `json:"imei"`
	IMSI           string `json:"imsi"`
	APN            string `json:"apn"`
	Dial           string `json:"dial"`
	Username       string `json:"username"`
	Password       string `json:"password"`
	DefaultGateway bool   `json:"defaultGateway"`
}

func (c *ThreeG) Prepare() *ThreeG {
	if c.Username == "" {
		c.Username = "0"
	}
	if c.Password == "" {
		c.Password = "0"
	}
	return c
}

func (c *ThreeG) WriteTo(out io.Writer) error {
	cfgTpl := `
[Dialer Defaults]
Init2 = ATQ0 V1 E1 S0=0 &C1 &D2
Modem Type = USB Modem
; Phone = <Target Phone Number>
Phone = {{.Dial}}
ISDN = 0
; Username = <Your Login Name>, 0 if not specified
Username = {{.Username}}
; Password = <Your Password>, 0 if not specified
Password = {{.Password}}
Init1 = ATZ
; modem command port (by IMSI)
Modem = /dev/{{.IMSI}}.imsi
Baud = 115200
; set APN
Init3 = AT+CGDCONT=1,"IP","{{.APN}}"
Stupid Mode = 1
	`
	tpl, err := template.New("cfg").Parse(cfgTpl)
	if err != nil {
		return err
	}
	return tpl.Execute(out, c)
}

type ThreeGState struct {
	Enabled bool    `json:"enabled"`
	Configg *ThreeG `json:"config"`
}

func ThreegCMD(ctx *cli.Context) error {
	if ctx.IsSet(enableFlag) {
		return EnableThreeg(ctx)
	}
	if ctx.IsSet(disableFlag) {
		return DisableThreeg(ctx)
	}
	if ctx.IsSet(removeFlag) {
		return RemoveThreeg(ctx)
	}
	if ctx.IsSet(configFlag) {
		return configThreegCMD(ctx)
	}
	return nil
}

func configThreegCMD(ctx *cli.Context) error {
	base := ctx.String("dir")
	name := ctx.String("name")
	src := ctx.String("config")
	if src == "" {
		return errors.New("fconf: missing configuration source file")
	}
	var b []byte
	var err error
	if src == "stdin" {
		b, err = ReadFromStdin()
		if err != nil {
			return err
		}
	} else {
		b, err = ioutil.ReadFile(src)
		if err != nil {
			return err
		}
	}
	e := ThreeG{}
	err = json.Unmarshal(b, &e)
	if err != nil {
		return err
	}
	e.Prepare()
	err = checkDir(base)
	if err != nil {
		return err
	}
	if strings.Contains(name, "%s") {
		name = fmt.Sprintf(name, e.IMEI)
	}
	filename := filepath.Join(base, name)
	var buf bytes.Buffer
	err = e.WriteTo(&buf)
	if err != nil {
		return err
	}
	err = ioutil.WriteFile(filename, buf.Bytes(), 0644)
	if err != nil {
		return err
	}
	fmt.Printf("successful written 3G configuration to %s \n", filename)
	state := &ThreeGState{Configg: &e}
	ms, err := threeGState(e.IMEI)
	if err == nil {
		state.Enabled = ms.Enabled
	}
	b, _ = json.Marshal(state)
	setInterface(ctx, e.IMEI)
	return keepState(
		fmt.Sprintf(defaultThreeGGConfig, e.IMEI), b)
}

func threeGState(i string) (*ThreeGState, error) {
	dir := os.Getenv("FCONF_CONFIGDIR")
	if dir == "" {
		dir = fconfConfigDir
	}
	b, err := ioutil.ReadFile(filepath.Join(dir,
		fmt.Sprintf(defaultThreeGGConfig, i)))
	if err != nil {
		return nil, err
	}
	f := &ThreeGState{}
	err = json.Unmarshal(b, f)
	if err != nil {
		return nil, err
	}
	if f.Configg == nil {
		return nil, ErrWrongStateFile
	}
	return f, nil
}

func EnableThreeg(ctx *cli.Context) error {
	if ctx.IsSet(configFlag) {
		err := configThreegCMD(ctx)
		if err != nil {
			return err
		}
	}
	i := getInterface(ctx)
	if i == "" {
		return errors.New("missing imei , you must specify imei")
	}
	e, err := threeGState(i)
	if err != nil {
		return err
	}
	service := "wvdial"
	err = restartService(service)
	if err != nil {
		return fmt.Errorf("ERROR: restarting systemd %v ", err)
	}
	err = enableService(service)
	if err != nil {
		return fmt.Errorf("ERROR: enabling systemd %v ", err)
	}
	e.Enabled = true
	data, err := json.Marshal(e)
	if err != nil {
		return err
	}
	fmt.Printf("successfully enabled 3g for %s \n", i)
	return keepState(
		fmt.Sprintf(defaultThreeGGConfig, i), data)
}

func DisableThreeg(ctx *cli.Context) error {
	if ctx.IsSet(configFlag) {
		fmt.Println("WARN: config flag will be ignored when diable flag is used")
	}
	i := getInterface(ctx)
	if i == "" {
		return errors.New("missing imei, you must specify imei")
	}
	e, err := threeGState(i)
	if err != nil {
		return err
	}
	e.Enabled = false
	data, err := json.Marshal(e)
	if err != nil {
		return err
	}
	service := "wvdial"
	err = stopService(service)
	if err != nil {
		return err
	}
	err = disableService(service)
	if err != nil {
		return err
	}
	fmt.Println("successfully disabled 3G for ", i)
	return keepState(
		fmt.Sprintf(defaultThreeGGConfig, i), data)
}

func RemoveThreeg(ctx *cli.Context) error {
	err := DisableThreeg(ctx)
	if err != nil {
		return err
	}
	i := getInterface(ctx)
	if i == "" {
		return errors.New("missing imei, you must specify imei")
	}

	// removestate file
	stateFile := filepath.Join(stateDir(),
		fmt.Sprintf(defaultThreeGGConfig, i))
	err = removeFile(stateFile)
	if err != nil {
		return err
	}

	// remove config
	unit := filepath.Join(apConfigBase, threeGService)
	err = removeFile(unit)
	if err != nil {
		return err
	}
	return nil
}
<|endoftext|>


<commit_before>package main

import (
	"time"

	"labix.org/v2/mgo/bson"
)

type ThriftMessage struct {
	Ts time.Time

	Stream_id    uint32
	Tuple        *IpPortTuple
	CmdlineTuple *CmdlineTuple
	Direction    uint8

	start int
	end   int

	IsRequest bool
	Version   uint32
	Type      uint32
	Method    string
	SeqId     uint32
}

type ThriftStream struct {
	tcpStream *TcpStream

	data []byte

	parseOffset   int
	parseState    int
	bytesReceived int

	message *ThriftMessage
}

type ThriftTransaction struct {
	Type         string
	tuple        TcpTuple
	Src          Endpoint
	Dst          Endpoint
	ResponseTime int32
	Ts           int64
	JsTs         time.Time
	ts           time.Time
	cmdline      *CmdlineTuple

	Thrift bson.M

	Request_raw  string
	Response_raw string

	timer *time.Timer
}

const (
	ThriftStartState = iota
	ThriftReadFields
)

const (
	ThriftVersionMask = 0xffff0000
	ThriftVersion1    = 0x80010000
	ThriftTypeMask    = 0x000000ff
)

const (
	_ = iota
	ThriftTypeCall
	ThriftTypeReply
	ThriftTypeException
	ThriftTypeOneway
)

func (m *ThriftMessage) readMessageBegin(s *ThriftStream) (bool, bool) {
	var ok, complete bool
	var offset, off int

	if len(s.data[s.parseOffset:]) < 9 {
		return true, false // ok, not complete
	}

	sz := Bytes_Ntohl(s.data[s.parseOffset : s.parseOffset+4])
	if int32(sz) < 0 {
		m.Version = sz & ThriftVersionMask
		if m.Version != ThriftVersion1 {
			DEBUG("thrift", "Unexpected version: %d", m.Version)
		}

		DEBUG("thriftdetailed", "version = %d", m.Version)

		offset = s.parseOffset + 4

		DEBUG("thriftdetailed", "offset = %d", offset)

		m.Type = sz & ThriftTypeMask
		m.Method, ok, complete, off = thriftReadString(s.data[offset:])
		if !ok {
			return false, false // not ok, not complete
		}
		if !complete {
			DEBUG("thriftdetailed", "Method name not complete")
			return true, false // ok, not complete
		}
		offset += off

		DEBUG("thriftdetailed", "method = %s", m.Method)
		DEBUG("thriftdetailed", "offset = %d", offset)

		if len(s.data[offset:]) < 4 {
			return true, false // ok, not complete
		}
		m.SeqId = Bytes_Ntohl(s.data[offset : offset+4])
		s.parseOffset = offset + 4
	} else {
		// no version mode
		offset = s.parseOffset

		m.Method, ok, complete, off = thriftReadString(s.data[offset:])
		if !ok {
			return false, false // not ok, not complete
		}
		if !complete {
			DEBUG("thriftdetailed", "Method name not complete")
			return true, false // ok, not complete
		}
		offset += off

		DEBUG("thriftdetailed", "method = %s", m.Method)
		DEBUG("thriftdetailed", "offset = %d", offset)

		if len(s.data[offset:]) < 5 {
			return true, false // ok, not complete
		}

		m.Type = uint32(s.data[offset])
		offset += 1
		m.SeqId = Bytes_Ntohl(s.data[offset : offset+4])
		s.parseOffset = offset + 4
	}

	return true, true
}

func thriftReadString(data []byte) (str string, ok bool, complete bool, off int) {
	if len(data) < 4 {
		return "", true, false, 0 // ok, not complete
	}
	sz := int(Bytes_Ntohl(data[:4]))
	if int32(sz) < 0 {
		return "", false, false, 0 // not ok
	}
	if len(data[4:]) < sz {
		return "", true, false, 0 // ok, not complete
	}

	str = string(data[4 : 4+sz])
	off = 4 + sz

	return str, true, true, off // all good
}

func thriftMessageParser(s *ThriftStream) (bool, bool) {
	var ok, complete bool
	var m = s.message

	for s.parseOffset < len(s.data) {
		switch s.parseState {
		case ThriftStartState:
			m.start = s.parseOffset

			ok, complete = m.readMessageBegin(s)
			if !ok {
				return false, false
			}
			if !complete {
				return true, false
			}

		}
	}

	return true, false
}

func (stream *ThriftStream) PrepareForNewMessage() {
	stream.data = stream.data[stream.parseOffset:]
	stream.parseOffset = 0
	stream.message.IsRequest = false
}

func ParseThrift(pkt *Packet, tcp *TcpStream, dir uint8) {
	defer RECOVER("ParseThrift exception")

	if tcp.thriftData[dir] == nil {
		tcp.thriftData[dir] = &ThriftStream{
			tcpStream: tcp,
			data:      pkt.payload,
			message:   &ThriftMessage{Ts: pkt.ts},
		}
	} else {
		// concatenate bytes
		tcp.thriftData[dir].data = append(tcp.thriftData[dir].data, pkt.payload...)
		if len(tcp.thriftData[dir].data) > TCP_MAX_DATA_IN_STREAM {
			DEBUG("thrift", "Stream data too large, dropping TCP stream")
			tcp.thriftData[dir] = nil
			return
		}
	}

	stream := tcp.thriftData[dir]
	for len(stream.data) > 0 {
		if stream.message == nil {
			stream.message = &ThriftMessage{Ts: pkt.ts}
		}

		ok, complete := thriftMessageParser(tcp.thriftData[dir])

		if !ok {
			// drop this tcp stream. Will retry parsing with the next
			// segment in it
			tcp.thriftData[dir] = nil
			DEBUG("thrift", "Ignore Thrift message. Drop tcp stream. Try parsing with the next segment")
			return
		}

		if complete {

			if stream.message.IsRequest {
				DEBUG("thrift", "Thrift request message: %s", stream.message.Method)
			} else {
				DEBUG("thrift", "Thrift response message: %s", stream.message.Method)
			}

			// all ok, go to next level
			//handleThrift(stream.message, tcp, dir)

			// and reset message
			stream.PrepareForNewMessage()
		} else {
			// wait for more data
			break
		}
	}

}
<commit_msg>Started fields decoding<commit_after>package main

import (
	"encoding/binary"
	"math"
	"time"
	"strconv"

	"labix.org/v2/mgo/bson"
)

type ThriftMessage struct {
	Ts time.Time

	Stream_id    uint32
	Tuple        *IpPortTuple
	CmdlineTuple *CmdlineTuple
	Direction    uint8

	start int
	end   int

	IsRequest bool
	Version   uint32
	Type      uint32
	Method    string
	SeqId     uint32
	Fields    []*ThriftField
}

type ThriftField struct {
	Type byte
	Id uint16

	Value string
}

type ThriftStream struct {
	tcpStream *TcpStream

	data []byte

	parseOffset   int
	parseState    int
	bytesReceived int

	message *ThriftMessage
}

type ThriftTransaction struct {
	Type         string
	tuple        TcpTuple
	Src          Endpoint
	Dst          Endpoint
	ResponseTime int32
	Ts           int64
	JsTs         time.Time
	ts           time.Time
	cmdline      *CmdlineTuple

	Thrift bson.M

	Request_raw  string
	Response_raw string

	timer *time.Timer
}

const (
	ThriftStartState = iota
	ThriftFieldState
)

const (
	ThriftVersionMask = 0xffff0000
	ThriftVersion1    = 0x80010000
	ThriftTypeMask    = 0x000000ff
)

// Thrift types
const (
	ThriftTypeStop = iota
	ThriftTypeVoid
	ThriftTypeBool
	ThriftTypeByte
	ThriftTypeDouble
	ThriftTypeI16 = 6
	ThriftTypeI32 = 8
	ThriftTypeI64 = 10
	ThriftTypeString = 11
	ThriftTypeStruct = 12
	ThriftTypeMap = 13
	ThriftTypeSet = 14
	ThriftTypeList = 15
	ThriftTypeUtf8 = 16
	ThriftTypeUtf16 = 17
)

// Thrift message types -- TODO: rename to ThriftTypeMsg..
const (
	_ = iota
	ThriftTypeCall
	ThriftTypeReply
	ThriftTypeException
	ThriftTypeOneway
)

func (m *ThriftMessage) readMessageBegin(s *ThriftStream) (bool, bool) {
	var ok, complete bool
	var offset, off int

	if len(s.data[s.parseOffset:]) < 9 {
		return true, false // ok, not complete
	}

	sz := Bytes_Ntohl(s.data[s.parseOffset : s.parseOffset+4])
	if int32(sz) < 0 {
		m.Version = sz & ThriftVersionMask
		if m.Version != ThriftVersion1 {
			DEBUG("thrift", "Unexpected version: %d", m.Version)
		}

		DEBUG("thriftdetailed", "version = %d", m.Version)

		offset = s.parseOffset + 4

		DEBUG("thriftdetailed", "offset = %d", offset)

		m.Type = sz & ThriftTypeMask
		m.Method, ok, complete, off = thriftReadString(s.data[offset:])
		if !ok {
			return false, false // not ok, not complete
		}
		if !complete {
			DEBUG("thriftdetailed", "Method name not complete")
			return true, false // ok, not complete
		}
		offset += off

		DEBUG("thriftdetailed", "method = %s", m.Method)
		DEBUG("thriftdetailed", "offset = %d", offset)

		if len(s.data[offset:]) < 4 {
			return true, false // ok, not complete
		}
		m.SeqId = Bytes_Ntohl(s.data[offset : offset+4])
		s.parseOffset = offset + 4
	} else {
		// no version mode
		offset = s.parseOffset

		m.Method, ok, complete, off = thriftReadString(s.data[offset:])
		if !ok {
			return false, false // not ok, not complete
		}
		if !complete {
			DEBUG("thriftdetailed", "Method name not complete")
			return true, false // ok, not complete
		}
		offset += off

		DEBUG("thriftdetailed", "method = %s", m.Method)
		DEBUG("thriftdetailed", "offset = %d", offset)

		if len(s.data[offset:]) < 5 {
			return true, false // ok, not complete
		}

		m.Type = uint32(s.data[offset])
		offset += 1
		m.SeqId = Bytes_Ntohl(s.data[offset : offset+4])
		s.parseOffset = offset + 4
	}

	if m.Type == ThriftTypeCall || m.Type == ThriftTypeOneway {
		m.IsRequest = true
	}

	return true, true
}

func thriftReadString(data []byte) (str string, ok bool, complete bool, off int) {
	if len(data) < 4 {
		return "", true, false, 0 // ok, not complete
	}
	sz := int(Bytes_Ntohl(data[:4]))
	if int32(sz) < 0 {
		return "", false, false, 0 // not ok
	}
	if len(data[4:]) < sz {
		return "", true, false, 0 // ok, not complete
	}

	str = string(data[4 : 4+sz])
	off = 4 + sz

	return str, true, true, off // all good
}

func thriftReadField(s *ThriftStream) (ok bool, complete bool, field *ThriftField) {

	field = new(ThriftField)

	if len(s.data) == 0 {
		return true, false, nil // ok, not complete
	}
	field.Type = byte(s.data[s.parseOffset])
	offset := s.parseOffset + 1
	if field.Type == ThriftTypeStop {
		s.parseOffset = offset
		return true, true, nil	// done
	}

	if len(s.data[offset:]) < 2 {
		return true, false, nil // ok, not complete
	}
	field.Id = Bytes_Ntohs(s.data[offset:offset+2])
	offset += 2

	switch field.Type {
		case ThriftTypeBool:
			if len(s.data[offset:]) < 1 {
				return true, false, nil
			}
			if s.data[offset] == byte(0) {
				field.Value = "true"
			} else {
				field.Value = "false"
			}
			offset += 1

		case ThriftTypeByte:
			if len(s.data[offset:]) < 1 {
				return true, false, nil
			}
			field.Value = strconv.Itoa(int(s.data[offset]))
			offset += 1

		case ThriftTypeDouble:
			if len(s.data[offset:]) < 8 {
				return true, false, nil
			}
			bits := binary.BigEndian.Uint64(s.data[offset:offset+8])
			double := math.Float64frombits(bits)
			field.Value = strconv.FormatFloat(double, 'f', -1, 64)
			offset += 8
	}

	s.parseOffset = offset
	return true, false, field
}

func thriftMessageParser(s *ThriftStream) (bool, bool) {
	var ok, complete bool
	var m = s.message

	for s.parseOffset < len(s.data) {
		switch s.parseState {
		case ThriftStartState:
			m.start = s.parseOffset

			ok, complete = m.readMessageBegin(s)
			if !ok {
				return false, false
			}
			if !complete {
				return true, false
			}

			s.parseState = ThriftFieldState
		case ThriftFieldState:
			ok, complete, field := thriftReadField(s)
			if !ok {
				return false, false
			}
			if complete {
				// done
				return true, true
			}
			if field == nil {
				return true, false // ok, not complete
			}

			m.Fields = append(m.Fields, field)
		}
	}

	return true, false
}

func (stream *ThriftStream) PrepareForNewMessage() {
	stream.data = stream.data[stream.parseOffset:]
	stream.parseOffset = 0
	stream.message.IsRequest = false
}

func ParseThrift(pkt *Packet, tcp *TcpStream, dir uint8) {
	defer RECOVER("ParseThrift exception")

	if tcp.thriftData[dir] == nil {
		tcp.thriftData[dir] = &ThriftStream{
			tcpStream: tcp,
			data:      pkt.payload,
			message:   &ThriftMessage{Ts: pkt.ts},
		}
	} else {
		// concatenate bytes
		tcp.thriftData[dir].data = append(tcp.thriftData[dir].data, pkt.payload...)
		if len(tcp.thriftData[dir].data) > TCP_MAX_DATA_IN_STREAM {
			DEBUG("thrift", "Stream data too large, dropping TCP stream")
			tcp.thriftData[dir] = nil
			return
		}
	}

	stream := tcp.thriftData[dir]
	for len(stream.data) > 0 {
		if stream.message == nil {
			stream.message = &ThriftMessage{Ts: pkt.ts}
		}

		ok, complete := thriftMessageParser(tcp.thriftData[dir])

		if !ok {
			// drop this tcp stream. Will retry parsing with the next
			// segment in it
			tcp.thriftData[dir] = nil
			DEBUG("thrift", "Ignore Thrift message. Drop tcp stream. Try parsing with the next segment")
			return
		}

		if complete {

			if stream.message.IsRequest {
				DEBUG("thrift", "Thrift request message: %s", stream.message.Method)
			} else {
				DEBUG("thrift", "Thrift response message: %s", stream.message.Method)
			}

			// all ok, go to next level
			//handleThrift(stream.message, tcp, dir)

			// and reset message
			stream.PrepareForNewMessage()
		} else {
			// wait for more data
			break
		}
	}

}
<|endoftext|>


<commit_before>package backoff

import (
	"runtime"
	"sync"
	"time"
)

// Ticker holds a channel that delivers `ticks' of a clock at times reported by a BackOff.
//
// Ticks will continue to arrive when the previous operation is still running,
// so operations that take a while to fail could run in quick succession.
type Ticker struct {
	C        <-chan time.Time
	c        chan time.Time
	b        BackOffContext
	stop     chan struct{}
	stopOnce sync.Once
}

// NewTicker returns a new Ticker containing a channel that will send
// the time at times specified by the BackOff argument. Ticker is
// guaranteed to tick at least once.  The channel is closed when Stop
// method is called or BackOff stops. It is not safe to manipulate the
// provided backoff policy (notably calling NextBackOff or Reset)
// while the ticker is running.
func NewTicker(b BackOff) *Ticker {
	c := make(chan time.Time)
	t := &Ticker{
		C:    c,
		c:    c,
		b:    ensureContext(b),
		stop: make(chan struct{}),
	}
	t.b.Reset()
	go t.run()
	return t
}

// Stop turns off a ticker. After Stop, no more ticks will be sent.
func (t *Ticker) Stop() {
	t.stopOnce.Do(func() { close(t.stop) })
}

func (t *Ticker) run() {
	c := t.c
	defer close(c)

	// Ticker is guaranteed to tick at least once.
	afterC := t.send(time.Now())

	for {
		if afterC == nil {
			return
		}

		select {
		case tick := <-afterC:
			afterC = t.send(tick)
		case <-t.stop:
			t.c = nil // Prevent future ticks from being sent to the channel.
			return
		case <-t.b.Context().Done():
			return
		}
	}
}

func (t *Ticker) send(tick time.Time) <-chan time.Time {
	select {
	case t.c <- tick:
	case <-t.stop:
		return nil
	}

	next := t.b.NextBackOff()
	if next == Stop {
		t.Stop()
		return nil
	}

	return time.After(next)
}
<commit_msg>remove unused import<commit_after>package backoff

import (
	"sync"
	"time"
)

// Ticker holds a channel that delivers `ticks' of a clock at times reported by a BackOff.
//
// Ticks will continue to arrive when the previous operation is still running,
// so operations that take a while to fail could run in quick succession.
type Ticker struct {
	C        <-chan time.Time
	c        chan time.Time
	b        BackOffContext
	stop     chan struct{}
	stopOnce sync.Once
}

// NewTicker returns a new Ticker containing a channel that will send
// the time at times specified by the BackOff argument. Ticker is
// guaranteed to tick at least once.  The channel is closed when Stop
// method is called or BackOff stops. It is not safe to manipulate the
// provided backoff policy (notably calling NextBackOff or Reset)
// while the ticker is running.
func NewTicker(b BackOff) *Ticker {
	c := make(chan time.Time)
	t := &Ticker{
		C:    c,
		c:    c,
		b:    ensureContext(b),
		stop: make(chan struct{}),
	}
	t.b.Reset()
	go t.run()
	return t
}

// Stop turns off a ticker. After Stop, no more ticks will be sent.
func (t *Ticker) Stop() {
	t.stopOnce.Do(func() { close(t.stop) })
}

func (t *Ticker) run() {
	c := t.c
	defer close(c)

	// Ticker is guaranteed to tick at least once.
	afterC := t.send(time.Now())

	for {
		if afterC == nil {
			return
		}

		select {
		case tick := <-afterC:
			afterC = t.send(tick)
		case <-t.stop:
			t.c = nil // Prevent future ticks from being sent to the channel.
			return
		case <-t.b.Context().Done():
			return
		}
	}
}

func (t *Ticker) send(tick time.Time) <-chan time.Time {
	select {
	case t.c <- tick:
	case <-t.stop:
		return nil
	}

	next := t.b.NextBackOff()
	if next == Stop {
		t.Stop()
		return nil
	}

	return time.After(next)
}
<|endoftext|>