<commit_before>package main

import (
	"fmt"
	"net"
)

type UDP_manager struct {
	ipAddress string
	pl        net.PacketConn
	open      bool
	conn      *IP_Conn
	buff      map[uint16](chan byte)
}

type UDP struct {
	manager   *UDP_manager
	conn      *IP_Conn
	bytes     chan byte
	src, dest uint16
}

func NewUDP_Manager(ip string) (*UDP_manager, error) {
	p, err := net.ListenPacket("ip4:17", ip)
	if err != nil {
		fmt.Println(err)
		return nil, err
	}

	r, err := NewIP_Conn(ip)
	if err != nil {
		fmt.Println(err)
		return nil, err
	}

	x := &UDP_manager{open: true, conn: r, pl: p, buff: make(map[uint16](chan byte)), ipAddress: ip}

	//go x.readAll()

	return x, nil
}

func (x *UDP_manager) readAll() {
	b := make([]byte, 1024)

	for {
		payload, err := x.conn.ReadFrom(b)
		if err != nil {
			continue
		}

		dest := (((uint16)(payload[2])) << 8) + ((uint16)(payload[3]))
		//		fmt.Println(dest)
		//		fmt.Println(payload)
		//
		//		fmt.Println(x.buff)
		c, ok := x.buff[dest]
		//fmt.Println(ok)
		payload = payload[8:]
		if ok {
			go func() {
				for _, elem := range payload {
					//fmt.Println("Writing")
					c <- elem
				}
			}()
		}
	}
}

func (x *UDP_manager) NewUDP(src, dest uint16) (*UDP, error) {
	x.buff[src] = make(chan byte, 1024)
	return &UDP{src: src, dest: dest, conn: x.conn, bytes: x.buff[src], manager: x}, nil
}

func (c *UDP) read(size int) ([]byte, error) {
	data := make([]byte, size)
	for i := 0; i < size; i++ {
		//fmt.Println("test")
		data[i] = <-c.bytes
		//fmt.Println(data[i])
	}
	return data, nil
}
func (c *UDP) write(x []byte) error {
	UDPHeader := []byte{
		(byte)(c.src >> 8), (byte)(c.src), // Source port in byte slice
		(byte)(c.dest >> 8), (byte)(c.dest), // Dest port in byte slice
		(byte)((8 + len(x)) >> 8), (byte)(8 + len(x)), // Length in bytes of UDP header + data
		0, 0, // Checksum
	}

	x = append(UDPHeader, x...)

	err := c.conn.WriteTo(x)
	if err != nil {
		fmt.Println(err)
		return err
	}
	return nil
}
func (c *UDP) close() error {
	return c.conn.Close()
}
<commit_msg>Added back the readALL goroutine<commit_after>package main

import (
	"fmt"
	"net"
)

type UDP_manager struct {
	ipAddress string
	pl        net.PacketConn
	open      bool
	conn      *IP_Conn
	buff      map[uint16](chan byte)
}

type UDP struct {
	manager   *UDP_manager
	conn      *IP_Conn
	bytes     chan byte
	src, dest uint16
}

func NewUDP_Manager(ip string) (*UDP_manager, error) {
	p, err := net.ListenPacket("ip4:17", ip)
	if err != nil {
		fmt.Println(err)
		return nil, err
	}

	r, err := NewIP_Conn(ip)
	if err != nil {
		fmt.Println(err)
		return nil, err
	}

	x := &UDP_manager{open: true, conn: r, pl: p, buff: make(map[uint16](chan byte)), ipAddress: ip}

	go x.readAll()

	return x, nil
}

func (x *UDP_manager) readAll() {
	b := make([]byte, 1024)

	for {
		payload, err := x.conn.ReadFrom(b)
		if err != nil {
			continue
		}

		dest := (((uint16)(payload[2])) << 8) + ((uint16)(payload[3]))
		//		fmt.Println(dest)
		//		fmt.Println(payload)
		//
		//		fmt.Println(x.buff)
		c, ok := x.buff[dest]
		//fmt.Println(ok)
		payload = payload[8:]
		if ok {
			go func() {
				for _, elem := range payload {
					//fmt.Println("Writing")
					c <- elem
				}
			}()
		}
	}
}

func (x *UDP_manager) NewUDP(src, dest uint16) (*UDP, error) {
	x.buff[src] = make(chan byte, 1024)
	return &UDP{src: src, dest: dest, conn: x.conn, bytes: x.buff[src], manager: x}, nil
}

func (c *UDP) read(size int) ([]byte, error) {
	data := make([]byte, size)
	for i := 0; i < size; i++ {
		//fmt.Println("test")
		data[i] = <-c.bytes
		//fmt.Println(data[i])
	}
	return data, nil
}
func (c *UDP) write(x []byte) error {
	UDPHeader := []byte{
		(byte)(c.src >> 8), (byte)(c.src), // Source port in byte slice
		(byte)(c.dest >> 8), (byte)(c.dest), // Dest port in byte slice
		(byte)((8 + len(x)) >> 8), (byte)(8 + len(x)), // Length in bytes of UDP header + data
		0, 0, // Checksum
	}

	x = append(UDPHeader, x...)

	err := c.conn.WriteTo(x)
	if err != nil {
		fmt.Println(err)
		return err
	}
	return nil
}
func (c *UDP) close() error {
	return c.conn.Close()
}
<|endoftext|>


<commit_before>package rainforest

import (
	"errors"
	"fmt"
	"net/url"
	"regexp"
	"strconv"
)

const uploadableRegex = `{{ *file\.(download|screenshot)\(([^\)]+)\) *}}`

// TestIDMap is a type representing RF tests that contain the test definitions.
type TestIDMap struct {
	ID     int    `json:"id"`
	RFMLID string `json:"rfml_id"`
}

// TestIDMappings is a slice of all the mapping pairs.
// And has a set of functions defined to get map of one to the other.
type TestIDMappings []TestIDMap

// MapIDtoRFMLID creates a map from test IDs to RFML IDs
func (s TestIDMappings) MapIDtoRFMLID() map[int]string {
	resultMap := make(map[int]string)
	for _, mapping := range s {
		resultMap[mapping.ID] = mapping.RFMLID
	}
	return resultMap
}

// MapRFMLIDtoID creates a map from RFML IDs to IDs
func (s TestIDMappings) MapRFMLIDtoID() map[string]int {
	resultMap := make(map[string]int)
	for _, mapping := range s {
		resultMap[mapping.RFMLID] = mapping.ID
	}
	return resultMap
}

// RFTest is a struct representing the Rainforest Test with its settings and steps
type RFTest struct {
	TestID      int                      `json:"id"`
	RFMLID      string                   `json:"rfml_id"`
	Source      string                   `json:"source"`
	Title       string                   `json:"title,omitempty"`
	StartURI    string                   `json:"start_uri,omitempty"`
	SiteID      int                      `json:"site_id,omitempty"`
	Description string                   `json:"description,omitempty"`
	Tags        []string                 `json:"tags,omitempty"`
	BrowsersMap []map[string]interface{} `json:"browsers,omitempty"`
	Elements    []testElement            `json:"elements,omitempty"`

	// Browsers and Steps are helper fields
	Browsers []string      `json:"-"`
	Steps    []interface{} `json:"-"`
	// RFMLPath is a helper field for keeping track of the filepath to the
	// test's RFML file.
	RFMLPath string `json:"-"`
}

// testElement is one of the helpers to construct the proper JSON test sturcture
type testElement struct {
	Redirect bool               `json:"redirection"`
	Type     string             `json:"type"`
	Details  testElementDetails `json:"element"`
}

// testElementDetails is one of the helpers to construct the proper JSON test sturcture
type testElementDetails struct {
	ID       int    `json:"id,omitempty"`
	Action   string `json:"action,omitempty"`
	Response string `json:"response,omitempty"`
}

// mapBrowsers fills the browsers field with format recognized by the API
func (t *RFTest) mapBrowsers() {
	// if there are no browsers skip mapping
	if len(t.Browsers) == 0 {
		return
	}
	t.BrowsersMap = make([]map[string]interface{}, len(t.Browsers))
	for i, browser := range t.Browsers {
		mappedBrowser := map[string]interface{}{
			"state": "enabled",
			"name":  browser,
		}
		t.BrowsersMap[i] = mappedBrowser
	}
}

// unmapBrowsers parses browsers from the API format to internal go one
func (t *RFTest) unmapBrowsers() {
	// if there are no browsers skip unmapping
	if len(t.BrowsersMap) == 0 {
		return
	}

	for _, browserMap := range t.BrowsersMap {
		if browserMap["state"] == "enabled" {
			t.Browsers = append(t.Browsers, browserMap["name"].(string))
		}
	}
}

// marshallElements converts go rfml structs into format understood by the API
func (t *RFTest) marshallElements(mappings TestIDMappings) error {
	// if there are no steps skip marshalling
	if len(t.Steps) == 0 {
		return nil
	}
	t.Elements = make([]testElement, len(t.Steps))
	rfmlidToID := mappings.MapRFMLIDtoID()
	for i, step := range t.Steps {
		switch castStep := step.(type) {
		case RFTestStep:
			stepElementDetails := testElementDetails{Action: castStep.Action, Response: castStep.Response}
			stepElement := testElement{Redirect: castStep.Redirect, Type: "step", Details: stepElementDetails}
			t.Elements[i] = stepElement
		case RFEmbeddedTest:
			embeddedID, ok := rfmlidToID[castStep.RFMLID]
			if !ok {
				return errors.New("Couldn't convert RFML ID to test ID")
			}
			embeddedElementDetails := testElementDetails{ID: embeddedID}
			embeddedElement := testElement{Redirect: castStep.Redirect, Type: "test", Details: embeddedElementDetails}
			t.Elements[i] = embeddedElement
		}
	}
	return nil
}

// unmarshalElements converts API elements format into RFML go structs
func (t *RFTest) unmarshalElements(mappings TestIDMappings) error {
	if len(t.Elements) == 0 {
		return nil
	}
	t.Steps = make([]interface{}, len(t.Elements))
	idToRFMLID := mappings.MapIDtoRFMLID()

	for i, element := range t.Elements {
		switch element.Type {
		case "step":
			step := RFTestStep{Action: element.Details.Action, Response: element.Details.Response, Redirect: element.Redirect}
			t.Steps[i] = step
		case "test":
			rfmlID, ok := idToRFMLID[element.Details.ID]
			if !ok {
				return errors.New("Couldn't convert test ID to RFML ID")
			}
			embedd := RFEmbeddedTest{RFMLID: rfmlID, Redirect: element.Redirect}
			t.Steps[i] = embedd
		}
	}
	return nil
}

// PrepareToUploadFromRFML uses different helper methods to prepare struct for API upload
func (t *RFTest) PrepareToUploadFromRFML(mappings TestIDMappings) error {
	t.Source = "rainforest-cli"
	if t.StartURI == "" {
		t.StartURI = "/"
	}
	t.mapBrowsers()
	err := t.marshallElements(mappings)
	if err != nil {
		return err
	}
	return nil
}

// PrepareToWriteAsRFML uses different helper methods to prepare struct for translation to RFML
func (t *RFTest) PrepareToWriteAsRFML(mappings TestIDMappings) error {
	err := t.unmarshalElements(mappings)
	if err != nil {
		return err
	}
	t.unmapBrowsers()
	return nil
}

// HasUploadableFiles returns true if test has embedded files in the format {{ file.screenshot(path/to/file) }}
// or {{ file.download(path/to/file) }}. It returns false otherwise.
func (t *RFTest) HasUploadableFiles() bool {
	for _, step := range t.Steps {
		s, ok := step.(RFTestStep)
		if ok && s.hasUploadableFiles() {
			return true
		}
	}

	return false
}

// RFTestStep contains single Rainforest step
type RFTestStep struct {
	Action   string
	Response string
	Redirect bool
}

func (s *RFTestStep) hasUploadableFiles() bool {
	return len(s.embeddedFilesInAction()) > 0 || len(s.embeddedFilesInResponse()) > 0
}

func (s *RFTestStep) embeddedFilesInAction() []embeddedFile {
	return findEmbeddedFiles(s.Action)
}

func (s *RFTestStep) embeddedFilesInResponse() []embeddedFile {
	return findEmbeddedFiles(s.Response)
}

// uploadable contains the information of an embedded step variables
type embeddedFile struct {
	// text is the entire step variable text. eg: "{{ file.screenshot(path/to/file) }}"
	text string
	// the step variable used. Either "screenshot" or "download"
	stepVar string
	// the path argument to the step variable
	path string
}

// findEmbeddedFiles looks through a string and parses out embedded step variables
// and returns a slice of uploadables
func findEmbeddedFiles(s string) []embeddedFile {
	// Shouldn't fail compilation unless uploadableRegex is incorrect
	reg := regexp.MustCompile(uploadableRegex)
	matches := reg.FindAllStringSubmatch(s, -1)

	uploadables := make([]embeddedFile, len(matches))

	for idx, match := range matches {
		uploadables[idx] = embeddedFile{
			text:    match[0],
			stepVar: match[1],
			path:    match[2],
		}
	}

	return uploadables
}

// RFEmbeddedTest contains an embedded test details
type RFEmbeddedTest struct {
	RFMLID   string
	Redirect bool
}

// RFTestFilters are used to translate test filters to a proper query string
type RFTestFilters struct {
	Tags          []string
	SiteID        int
	SmartFolderID int
}

func (f *RFTestFilters) toQuery() string {
	v := url.Values{"tags": f.Tags}
	if f.SiteID > 0 {
		v.Add("site_id", strconv.Itoa(f.SiteID))
	}
	if f.SmartFolderID > 0 {
		v.Add("smart_folder_id", strconv.Itoa(f.SmartFolderID))
	}

	return v.Encode()
}

// GetRFMLIDs returns all tests IDs and RFML IDs to properly map tests to their IDs
// for uploading and deleting.
func (c *Client) GetRFMLIDs() (TestIDMappings, error) {
	// Prepare request
	req, err := c.NewRequest("GET", "tests/rfml_ids", nil)
	if err != nil {
		return nil, err
	}

	// Send request and process response
	var testResp TestIDMappings
	_, err = c.Do(req, &testResp)
	if err != nil {
		return nil, err
	}
	return testResp, nil
}

// GetTests returns all tests that are optionally filtered by RFTestFilters
func (c *Client) GetTests(params *RFTestFilters) ([]RFTest, error) {
	testsURL := "tests?" + params.toQuery()
	req, err := c.NewRequest("GET", testsURL, nil)
	if err != nil {
		return nil, err
	}

	var testResp []RFTest
	_, err = c.Do(req, &testResp)
	if err != nil {
		return nil, err
	}

	return testResp, nil
}

// GetTest gets a test from RF specified by the given test ID
func (c *Client) GetTest(testID int) (*RFTest, error) {
	req, err := c.NewRequest("GET", "tests/"+strconv.Itoa(testID), nil)
	if err != nil {
		return nil, err
	}

	var testResp RFTest
	_, err = c.Do(req, &testResp)
	if err != nil {
		return nil, err
	}

	testResp.TestID = testID
	return &testResp, nil
}

// DeleteTest deletes test with a specified ID from the RF test suite
func (c *Client) DeleteTest(testID int) error {
	// Prepare request
	req, err := c.NewRequest("DELETE", "tests/"+strconv.Itoa(testID), nil)
	if err != nil {
		return err
	}

	// Send request and process response
	_, err = c.Do(req, nil)
	if err != nil {
		return err
	}
	return nil
}

// DeleteTestByRFMLID deletes test with a specified RFMLID from the RF test suite
func (c *Client) DeleteTestByRFMLID(testRFMLID string) error {
	testMappings, err := c.GetRFMLIDs()
	if err != nil {
		return err
	}
	rfmlMap := testMappings.MapRFMLIDtoID()
	testID, ok := rfmlMap[testRFMLID]
	if !ok {
		return fmt.Errorf("RFML ID: %v doesn't exist in Rainforest", testRFMLID)
	}
	return c.DeleteTest(testID)
}

// CreateTest creates new test on RF, requires RFTest struct to be prepared to upload using helpers
func (c *Client) CreateTest(test *RFTest) error {
	// Prepare request
	req, err := c.NewRequest("POST", "tests", test)
	if err != nil {
		return err
	}

	// Send request and process response
	_, err = c.Do(req, nil)
	if err != nil {
		return err
	}
	return nil
}

// UpdateTest updates existing test on RF, requires RFTest struct to be prepared to upload using helpers
func (c *Client) UpdateTest(test *RFTest) error {
	if test.TestID == 0 {
		return errors.New("Couldn't update the test TestID not specified in RFTest")
	}

	// Prepare request
	req, err := c.NewRequest("PUT", "tests/"+strconv.Itoa(test.TestID), test)
	if err != nil {
		return err
	}

	// Send request and process response
	_, err = c.Do(req, nil)
	if err != nil {
		return err
	}
	return nil
}
<commit_msg>don't omit a required parameter, even if its an empty string<commit_after>package rainforest

import (
	"errors"
	"fmt"
	"net/url"
	"regexp"
	"strconv"
)

const uploadableRegex = `{{ *file\.(download|screenshot)\(([^\)]+)\) *}}`

// TestIDMap is a type representing RF tests that contain the test definitions.
type TestIDMap struct {
	ID     int    `json:"id"`
	RFMLID string `json:"rfml_id"`
}

// TestIDMappings is a slice of all the mapping pairs.
// And has a set of functions defined to get map of one to the other.
type TestIDMappings []TestIDMap

// MapIDtoRFMLID creates a map from test IDs to RFML IDs
func (s TestIDMappings) MapIDtoRFMLID() map[int]string {
	resultMap := make(map[int]string)
	for _, mapping := range s {
		resultMap[mapping.ID] = mapping.RFMLID
	}
	return resultMap
}

// MapRFMLIDtoID creates a map from RFML IDs to IDs
func (s TestIDMappings) MapRFMLIDtoID() map[string]int {
	resultMap := make(map[string]int)
	for _, mapping := range s {
		resultMap[mapping.RFMLID] = mapping.ID
	}
	return resultMap
}

// RFTest is a struct representing the Rainforest Test with its settings and steps
type RFTest struct {
	TestID      int                      `json:"id"`
	RFMLID      string                   `json:"rfml_id"`
	Source      string                   `json:"source"`
	Title       string                   `json:"title,omitempty"`
	StartURI    string                   `json:"start_uri"`
	SiteID      int                      `json:"site_id,omitempty"`
	Description string                   `json:"description,omitempty"`
	Tags        []string                 `json:"tags,omitempty"`
	BrowsersMap []map[string]interface{} `json:"browsers,omitempty"`
	Elements    []testElement            `json:"elements,omitempty"`

	// Browsers and Steps are helper fields
	Browsers []string      `json:"-"`
	Steps    []interface{} `json:"-"`
	// RFMLPath is a helper field for keeping track of the filepath to the
	// test's RFML file.
	RFMLPath string `json:"-"`
}

// testElement is one of the helpers to construct the proper JSON test sturcture
type testElement struct {
	Redirect bool               `json:"redirection"`
	Type     string             `json:"type"`
	Details  testElementDetails `json:"element"`
}

// testElementDetails is one of the helpers to construct the proper JSON test sturcture
type testElementDetails struct {
	ID       int    `json:"id,omitempty"`
	Action   string `json:"action,omitempty"`
	Response string `json:"response,omitempty"`
}

// mapBrowsers fills the browsers field with format recognized by the API
func (t *RFTest) mapBrowsers() {
	// if there are no browsers skip mapping
	if len(t.Browsers) == 0 {
		return
	}
	t.BrowsersMap = make([]map[string]interface{}, len(t.Browsers))
	for i, browser := range t.Browsers {
		mappedBrowser := map[string]interface{}{
			"state": "enabled",
			"name":  browser,
		}
		t.BrowsersMap[i] = mappedBrowser
	}
}

// unmapBrowsers parses browsers from the API format to internal go one
func (t *RFTest) unmapBrowsers() {
	// if there are no browsers skip unmapping
	if len(t.BrowsersMap) == 0 {
		return
	}

	for _, browserMap := range t.BrowsersMap {
		if browserMap["state"] == "enabled" {
			t.Browsers = append(t.Browsers, browserMap["name"].(string))
		}
	}
}

// marshallElements converts go rfml structs into format understood by the API
func (t *RFTest) marshallElements(mappings TestIDMappings) error {
	// if there are no steps skip marshalling
	if len(t.Steps) == 0 {
		return nil
	}
	t.Elements = make([]testElement, len(t.Steps))
	rfmlidToID := mappings.MapRFMLIDtoID()
	for i, step := range t.Steps {
		switch castStep := step.(type) {
		case RFTestStep:
			stepElementDetails := testElementDetails{Action: castStep.Action, Response: castStep.Response}
			stepElement := testElement{Redirect: castStep.Redirect, Type: "step", Details: stepElementDetails}
			t.Elements[i] = stepElement
		case RFEmbeddedTest:
			embeddedID, ok := rfmlidToID[castStep.RFMLID]
			if !ok {
				return errors.New("Couldn't convert RFML ID to test ID")
			}
			embeddedElementDetails := testElementDetails{ID: embeddedID}
			embeddedElement := testElement{Redirect: castStep.Redirect, Type: "test", Details: embeddedElementDetails}
			t.Elements[i] = embeddedElement
		}
	}
	return nil
}

// unmarshalElements converts API elements format into RFML go structs
func (t *RFTest) unmarshalElements(mappings TestIDMappings) error {
	if len(t.Elements) == 0 {
		return nil
	}
	t.Steps = make([]interface{}, len(t.Elements))
	idToRFMLID := mappings.MapIDtoRFMLID()

	for i, element := range t.Elements {
		switch element.Type {
		case "step":
			step := RFTestStep{Action: element.Details.Action, Response: element.Details.Response, Redirect: element.Redirect}
			t.Steps[i] = step
		case "test":
			rfmlID, ok := idToRFMLID[element.Details.ID]
			if !ok {
				return errors.New("Couldn't convert test ID to RFML ID")
			}
			embedd := RFEmbeddedTest{RFMLID: rfmlID, Redirect: element.Redirect}
			t.Steps[i] = embedd
		}
	}
	return nil
}

// PrepareToUploadFromRFML uses different helper methods to prepare struct for API upload
func (t *RFTest) PrepareToUploadFromRFML(mappings TestIDMappings) error {
	t.Source = "rainforest-cli"
	if t.StartURI == "" {
		t.StartURI = "/"
	}
	t.mapBrowsers()
	err := t.marshallElements(mappings)
	if err != nil {
		return err
	}
	return nil
}

// PrepareToWriteAsRFML uses different helper methods to prepare struct for translation to RFML
func (t *RFTest) PrepareToWriteAsRFML(mappings TestIDMappings) error {
	err := t.unmarshalElements(mappings)
	if err != nil {
		return err
	}
	t.unmapBrowsers()
	return nil
}

// HasUploadableFiles returns true if test has embedded files in the format {{ file.screenshot(path/to/file) }}
// or {{ file.download(path/to/file) }}. It returns false otherwise.
func (t *RFTest) HasUploadableFiles() bool {
	for _, step := range t.Steps {
		s, ok := step.(RFTestStep)
		if ok && s.hasUploadableFiles() {
			return true
		}
	}

	return false
}

// RFTestStep contains single Rainforest step
type RFTestStep struct {
	Action   string
	Response string
	Redirect bool
}

func (s *RFTestStep) hasUploadableFiles() bool {
	return len(s.embeddedFilesInAction()) > 0 || len(s.embeddedFilesInResponse()) > 0
}

func (s *RFTestStep) embeddedFilesInAction() []embeddedFile {
	return findEmbeddedFiles(s.Action)
}

func (s *RFTestStep) embeddedFilesInResponse() []embeddedFile {
	return findEmbeddedFiles(s.Response)
}

// uploadable contains the information of an embedded step variables
type embeddedFile struct {
	// text is the entire step variable text. eg: "{{ file.screenshot(path/to/file) }}"
	text string
	// the step variable used. Either "screenshot" or "download"
	stepVar string
	// the path argument to the step variable
	path string
}

// findEmbeddedFiles looks through a string and parses out embedded step variables
// and returns a slice of uploadables
func findEmbeddedFiles(s string) []embeddedFile {
	// Shouldn't fail compilation unless uploadableRegex is incorrect
	reg := regexp.MustCompile(uploadableRegex)
	matches := reg.FindAllStringSubmatch(s, -1)

	uploadables := make([]embeddedFile, len(matches))

	for idx, match := range matches {
		uploadables[idx] = embeddedFile{
			text:    match[0],
			stepVar: match[1],
			path:    match[2],
		}
	}

	return uploadables
}

// RFEmbeddedTest contains an embedded test details
type RFEmbeddedTest struct {
	RFMLID   string
	Redirect bool
}

// RFTestFilters are used to translate test filters to a proper query string
type RFTestFilters struct {
	Tags          []string
	SiteID        int
	SmartFolderID int
}

func (f *RFTestFilters) toQuery() string {
	v := url.Values{"tags": f.Tags}
	if f.SiteID > 0 {
		v.Add("site_id", strconv.Itoa(f.SiteID))
	}
	if f.SmartFolderID > 0 {
		v.Add("smart_folder_id", strconv.Itoa(f.SmartFolderID))
	}

	return v.Encode()
}

// GetRFMLIDs returns all tests IDs and RFML IDs to properly map tests to their IDs
// for uploading and deleting.
func (c *Client) GetRFMLIDs() (TestIDMappings, error) {
	// Prepare request
	req, err := c.NewRequest("GET", "tests/rfml_ids", nil)
	if err != nil {
		return nil, err
	}

	// Send request and process response
	var testResp TestIDMappings
	_, err = c.Do(req, &testResp)
	if err != nil {
		return nil, err
	}
	return testResp, nil
}

// GetTests returns all tests that are optionally filtered by RFTestFilters
func (c *Client) GetTests(params *RFTestFilters) ([]RFTest, error) {
	testsURL := "tests?" + params.toQuery()
	req, err := c.NewRequest("GET", testsURL, nil)
	if err != nil {
		return nil, err
	}

	var testResp []RFTest
	_, err = c.Do(req, &testResp)
	if err != nil {
		return nil, err
	}

	return testResp, nil
}

// GetTest gets a test from RF specified by the given test ID
func (c *Client) GetTest(testID int) (*RFTest, error) {
	req, err := c.NewRequest("GET", "tests/"+strconv.Itoa(testID), nil)
	if err != nil {
		return nil, err
	}

	var testResp RFTest
	_, err = c.Do(req, &testResp)
	if err != nil {
		return nil, err
	}

	testResp.TestID = testID
	return &testResp, nil
}

// DeleteTest deletes test with a specified ID from the RF test suite
func (c *Client) DeleteTest(testID int) error {
	// Prepare request
	req, err := c.NewRequest("DELETE", "tests/"+strconv.Itoa(testID), nil)
	if err != nil {
		return err
	}

	// Send request and process response
	_, err = c.Do(req, nil)
	if err != nil {
		return err
	}
	return nil
}

// DeleteTestByRFMLID deletes test with a specified RFMLID from the RF test suite
func (c *Client) DeleteTestByRFMLID(testRFMLID string) error {
	testMappings, err := c.GetRFMLIDs()
	if err != nil {
		return err
	}
	rfmlMap := testMappings.MapRFMLIDtoID()
	testID, ok := rfmlMap[testRFMLID]
	if !ok {
		return fmt.Errorf("RFML ID: %v doesn't exist in Rainforest", testRFMLID)
	}
	return c.DeleteTest(testID)
}

// CreateTest creates new test on RF, requires RFTest struct to be prepared to upload using helpers
func (c *Client) CreateTest(test *RFTest) error {
	// Prepare request
	req, err := c.NewRequest("POST", "tests", test)
	if err != nil {
		return err
	}

	// Send request and process response
	_, err = c.Do(req, nil)
	if err != nil {
		return err
	}
	return nil
}

// UpdateTest updates existing test on RF, requires RFTest struct to be prepared to upload using helpers
func (c *Client) UpdateTest(test *RFTest) error {
	if test.TestID == 0 {
		return errors.New("Couldn't update the test TestID not specified in RFTest")
	}

	// Prepare request
	req, err := c.NewRequest("PUT", "tests/"+strconv.Itoa(test.TestID), test)
	if err != nil {
		return err
	}

	// Send request and process response
	_, err = c.Do(req, nil)
	if err != nil {
		return err
	}
	return nil
}
<|endoftext|>


<commit_before>package mvc

import (
	"bytes"
	"fmt"
	"net/http"
	"net/url"
	"net/http/httptest"
	"strings"
	"encoding/json"

	"gopkg.in/gin-gonic/gin.v1"
	ogin "github.com/Cepave/open-falcon-backend/common/gin"
)

func ExampleMvcBuilder_BuildHandler_httpGet() {
	mvcBuilder := NewMvcBuilder(NewDefaultMvcConfig())

	gin.SetMode(gin.ReleaseMode)
	engine := gin.New()
	engine.GET(
		"/get-1",
		mvcBuilder.BuildHandler(
			func(
				data *struct {
					V1 int8 `mvc:"query[v1]"`
					V2 int32 `mvc:"query[v2]"`
				},
			) string {
				return fmt.Sprintf("V1: %d. V2: %d", data.V1, data.V2)
			},
		),
	)

	req := httptest.NewRequest(http.MethodGet, "/get-1?v1=20&v2=40", nil)
	resp := httptest.NewRecorder()
	engine.ServeHTTP(resp, req)

	fmt.Println(resp.Body.String())

	// Output:
	// V1: 20. V2: 40
}
func ExampleMvcBuilder_BuildHandler_httpPost() {
	mvcBuilder := NewMvcBuilder(NewDefaultMvcConfig())

	gin.SetMode(gin.ReleaseMode)
	engine := gin.New()
	engine.POST(
		"/post-1",
		mvcBuilder.BuildHandler(
			func(
				data *struct {
					V1 int8 `mvc:"form[v1]"`
					V2 []int32 `mvc:"form[v2]"`
				},
			) string {
				return fmt.Sprintf("v1: %d. v2: %d,%d", data.V1, data.V2[0], data.V2[1])
			},
		),
	)

	/**
	 * Form data
	 */
	form := url.Values {
		"v1": []string { "17" },
		"v2": []string { "230", "232" },
	}
	// :~)

	req := httptest.NewRequest(http.MethodPost, "/post-1", strings.NewReader(form.Encode()))
	req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
	resp := httptest.NewRecorder()
	engine.ServeHTTP(resp, req)

	fmt.Println(resp.Body.String())

	// Output:
	// v1: 17. v2: 230,232
}

type sampleCar struct {
	Name string `json:"name"`
	Age int `json:"age"`
}
func (car *sampleCar) Bind(c *gin.Context) {
	ogin.BindJson(c, car)
}
func ExampleMvcBuilder_BuildHandler_json() {
	/*
	type sampleCar struct {
		Name string `json:"name"`
		Age int `json:"age"`
	}
	func (car *sampleCar) Bind(c *gin.Context) {
		ogin.BindJson(c, car)
	}
	*/

	mvcBuilder := NewMvcBuilder(NewDefaultMvcConfig())

	gin.SetMode(gin.ReleaseMode)
	engine := gin.New()
	engine.POST(
		"/json-1",
		mvcBuilder.BuildHandler(
			func(car *sampleCar) OutputBody {
				return JsonOutputBody(car)
			},
		),
	)

	rawJson, _ := json.Marshal(&sampleCar{ "GTA-99", 3 })

	req := httptest.NewRequest(http.MethodPost, "/json-1", bytes.NewReader(rawJson))
	req.Header.Set("Content-Type", "application/json")
	resp := httptest.NewRecorder()
	engine.ServeHTTP(resp, req)

	fmt.Println(resp.Body.String())

	// Output:
	// {"name":"GTA-99","age":3}
}
<commit_msg>[OWL-1418] Add example for paging<commit_after>package mvc

import (
	"bytes"
	"fmt"
	"net/http"
	"net/url"
	"net/http/httptest"
	"strings"
	"encoding/json"

	"github.com/Cepave/open-falcon-backend/common/model"
	"gopkg.in/gin-gonic/gin.v1"
	ogin "github.com/Cepave/open-falcon-backend/common/gin"
)

func ExampleMvcBuilder_BuildHandler_httpGet() {
	mvcBuilder := NewMvcBuilder(NewDefaultMvcConfig())

	gin.SetMode(gin.ReleaseMode)
	engine := gin.New()
	engine.GET(
		"/get-1",
		mvcBuilder.BuildHandler(
			func(
				data *struct {
					V1 int8 `mvc:"query[v1]"`
					V2 int32 `mvc:"query[v2]"`
				},
			) string {
				return fmt.Sprintf("V1: %d. V2: %d", data.V1, data.V2)
			},
		),
	)

	req := httptest.NewRequest(http.MethodGet, "/get-1?v1=20&v2=40", nil)
	resp := httptest.NewRecorder()
	engine.ServeHTTP(resp, req)

	fmt.Println(resp.Body.String())

	// Output:
	// V1: 20. V2: 40
}
func ExampleMvcBuilder_BuildHandler_httpPost() {
	mvcBuilder := NewMvcBuilder(NewDefaultMvcConfig())

	gin.SetMode(gin.ReleaseMode)
	engine := gin.New()
	engine.POST(
		"/post-1",
		mvcBuilder.BuildHandler(
			func(
				data *struct {
					V1 int8 `mvc:"form[v1]"`
					V2 []int32 `mvc:"form[v2]"`
				},
			) string {
				return fmt.Sprintf("v1: %d. v2: %d,%d", data.V1, data.V2[0], data.V2[1])
			},
		),
	)

	/**
	 * Form data
	 */
	form := url.Values {
		"v1": []string { "17" },
		"v2": []string { "230", "232" },
	}
	// :~)

	req := httptest.NewRequest(http.MethodPost, "/post-1", strings.NewReader(form.Encode()))
	req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
	resp := httptest.NewRecorder()
	engine.ServeHTTP(resp, req)

	fmt.Println(resp.Body.String())

	// Output:
	// v1: 17. v2: 230,232
}

type sampleCar struct {
	Name string `json:"name"`
	Age int `json:"age"`
}
func (car *sampleCar) Bind(c *gin.Context) {
	ogin.BindJson(c, car)
}
func ExampleMvcBuilder_BuildHandler_json() {
	/*
	type sampleCar struct {
		Name string `json:"name"`
		Age int `json:"age"`
	}
	func (car *sampleCar) Bind(c *gin.Context) {
		ogin.BindJson(c, car)
	}
	*/

	mvcBuilder := NewMvcBuilder(NewDefaultMvcConfig())

	gin.SetMode(gin.ReleaseMode)
	engine := gin.New()
	engine.POST(
		"/json-1",
		mvcBuilder.BuildHandler(
			func(car *sampleCar) OutputBody {
				return JsonOutputBody(car)
			},
		),
	)

	rawJson, _ := json.Marshal(&sampleCar{ "GTA-99", 3 })

	req := httptest.NewRequest(http.MethodPost, "/json-1", bytes.NewReader(rawJson))
	req.Header.Set("Content-Type", "application/json")
	resp := httptest.NewRecorder()
	engine.ServeHTTP(resp, req)

	fmt.Println(resp.Body.String())

	// Output:
	// {"name":"GTA-99","age":3}
}

func ExampleMvcBuilder_BuildHandler_paging() {
	mvcBuilder := NewMvcBuilder(NewDefaultMvcConfig())

	gin.SetMode(gin.ReleaseMode)
	engine := gin.New()
	engine.GET(
		"/paging-1",
		mvcBuilder.BuildHandler(
			func(
				p *struct {
					// Loads paging from header
					Paging *model.Paging
				},
			) (*model.Paging, string) {
				p.Paging.TotalCount = 980

				// Output paging in header
				return p.Paging, fmt.Sprintf("Position: %d", p.Paging.Position)
			},
		),
	)

	req := httptest.NewRequest(http.MethodGet, "/paging-1", nil)
	// Ask for page of 4th
	req.Header.Set("page-pos", "4")
	resp := httptest.NewRecorder()
	engine.ServeHTTP(resp, req)

	fmt.Println(resp.Body.String())
	fmt.Printf("total-count: %s", resp.Header().Get("total-count"))

	// Output:
	// Position: 4
	// total-count: 980
}
<|endoftext|>


<commit_before>package syslog

import (
	"fmt"
	"io"
	"math/rand"
	"net"
	"testing"
	"time"
)

const clienthost = "clienthost"

func panicf(s string, i ...interface{}) { panic(fmt.Sprintf(s, i)) }

type testServer struct {
	Addr     string
	Close    chan bool
	Messages chan string
}

func newTestServer(network string) *testServer {
	server := testServer{
		Close:    make(chan bool, 1),
		Messages: make(chan string, 20),
	}
	switch network {
	case "tcp":
		ln := server.listenTCP()
		go server.serveTCP(ln)
	case "udp":
		conn := server.listenUDP()
		go server.serveUDP(conn)
	}
	return &server
}

func (s *testServer) listenTCP() net.Listener {
	addr := s.Addr
	if addr == "" {
		addr = "127.0.0.1:0"
	}
	ln, err := net.Listen("tcp", addr)
	if err != nil {
		panicf("listen error %v", err)
	}
	if s.Addr == "" {
		s.Addr = ln.Addr().String()
	}
	return ln
}

func (s *testServer) serveTCP(ln net.Listener) {
	for {
		select {
		case <-s.Close:
			ln.Close()
			return
		default:
			conn, err := ln.Accept()
			if err != nil {
				panicf("Accept error: %v", err)
			}
			go handle(conn, s.Messages)
		}
	}
}

func (s *testServer) listenUDP() *net.UDPConn {
	addr := s.Addr
	if addr == "" {
		addr = "127.0.0.1:0"
	}
	udpAddr, err := net.ResolveUDPAddr("udp", addr)
	if err != nil {
		panicf("unexpected error %v", err)
	}

	conn, err := net.ListenUDP("udp", udpAddr)
	if err != nil {
		panicf("listen error %v", err)
	}
	if s.Addr == "" {
		s.Addr = conn.LocalAddr().String()
	}
	return conn
}

func (s *testServer) serveUDP(conn *net.UDPConn) {
	for {
		handle(conn, s.Messages)
		conn = s.listenUDP()
	}
}

func handle(conn io.ReadCloser, messages chan string) {
	for {
		fmt.Println("handle")
		buf := make([]byte, 1024)
		n, err := conn.Read(buf)
		if err != nil {
			panicf("Read error")
		} else {
			fmt.Println("handle", string(buf[0:n]))
			messages <- string(buf[0:n])
		}
		// todo: make configurable
		if 0 == (rand.Int() % 2) {
			fmt.Println("closing")
			conn.Close()
			return
		}
	}
}

func generatePackets() []Packet {
	packets := make([]Packet, 10)
	for i, _ := range packets {
		t, _ := time.Parse(time.RFC3339, "2006-01-02T15:04:05Z07:00")
		packets[i] = Packet{
			Severity: SevInfo,
			Facility: LogLocal1,
			Time:     t,
			Hostname: clienthost,
			Tag:      "test",
			Message:  fmt.Sprintf("message %d", i),
		}
	}
	return packets
}

func TestSyslog(t *testing.T) {
	for _, network := range []string{"tcp", "udp"} {
		s := newTestServer(network)

		logger, err := Dial(clienthost, network, s.Addr, nil)
		if err != nil {
			t.Errorf("unexpected dial error %v", err)
		}
		packets := generatePackets()
		for _, p := range packets {
			logger.writePacket(p)
			time.Sleep(100 * time.Millisecond)
		}
		s.Close <- true

		for _, p := range packets {
			expected := p.Generate(0)
			if network == "tcp" {
				expected = expected + "\n"
			}
			select {
			case got := <-s.Messages:
				if got != expected {
					t.Errorf("expected %s, got %s", expected, got)
				}
			default:
				t.Errorf("expected %s, got nothing", expected)
				break
			}
		}
		if l := len(s.Messages); l != 0 {
			t.Errorf("found %d extra messages", l)
		}
	}
}
<commit_msg>Test TCP slow reconnection<commit_after>package syslog

import (
	"fmt"
	"io"
	"net"
	"testing"
	"time"
)

const clienthost = "clienthost"

func panicf(s string, i ...interface{}) { panic(fmt.Sprintf(s, i)) }

type testServer struct {
	Addr     string
	Close    chan bool
	Messages chan string
}

func newTestServer(network string) *testServer {
	server := testServer{
		Close:    make(chan bool, 1),
		Messages: make(chan string, 20),
	}
	switch network {
	case "tcp":
		ln := server.listenTCP()
		go server.serveTCP(ln)
	case "udp":
		conn := server.listenUDP()
		go server.serveUDP(conn)
	}
	return &server
}

func (s *testServer) listenTCP() net.Listener {
	addr := s.Addr
	if addr == "" {
		addr = "127.0.0.1:0"
	}
	ln, err := net.Listen("tcp", addr)
	if err != nil {
		panicf("listen error %v", err)
	}
	if s.Addr == "" {
		s.Addr = ln.Addr().String()
	}
	return ln
}

func (s *testServer) serveTCP(ln net.Listener) {
	for i := 0; ; i++ {
		select {
		case <-s.Close:
			ln.Close()
			return
		default:
			conn, err := ln.Accept()
			if err != nil {
				panicf("Accept error: %v", err)
			}
			go handle(conn, s.Messages)
			if !testing.Short() && 0 == i%5 {
				ln.Close()
				time.Sleep(time.Second * 6)
				ln = s.listenTCP()
			}
		}
	}
}

func (s *testServer) listenUDP() *net.UDPConn {
	addr := s.Addr
	if addr == "" {
		addr = "127.0.0.1:0"
	}
	udpAddr, err := net.ResolveUDPAddr("udp", addr)
	if err != nil {
		panicf("unexpected error %v", err)
	}

	conn, err := net.ListenUDP("udp", udpAddr)
	if err != nil {
		panicf("listen error %v", err)
	}
	if s.Addr == "" {
		s.Addr = conn.LocalAddr().String()
	}
	return conn
}

func (s *testServer) serveUDP(conn *net.UDPConn) {
	for {
		handle(conn, s.Messages)
		conn = s.listenUDP()
	}
}

func handle(conn io.ReadCloser, messages chan string) {

	for i := 0; ; i++ {
		fmt.Println("handle")
		buf := make([]byte, 1024)
		n, err := conn.Read(buf)
		if err != nil {
			panicf("Read error")
		} else {
			fmt.Println("handle", string(buf[0:n]))
			messages <- string(buf[0:n])
		}
		if i % 2 == 0 {
			fmt.Println("closing")
			conn.Close()
			return
		}
	}
}

func generatePackets() []Packet {
	packets := make([]Packet, 10)
	for i, _ := range packets {
		t, _ := time.Parse(time.RFC3339, "2006-01-02T15:04:05Z07:00")
		packets[i] = Packet{
			Severity: SevInfo,
			Facility: LogLocal1,
			Time:     t,
			Hostname: clienthost,
			Tag:      "test",
			Message:  fmt.Sprintf("message %d", i),
		}
	}
	return packets
}

func TestSyslog(t *testing.T) {
	for _, network := range []string{"tcp", "udp"} {
		s := newTestServer(network)

		logger, err := Dial(clienthost, network, s.Addr, nil)
		if err != nil {
			t.Errorf("unexpected dial error %v", err)
		}
		packets := generatePackets()
		for _, p := range packets {
			logger.writePacket(p)
			time.Sleep(100 * time.Millisecond)
		}
		s.Close <- true

		for _, p := range packets {
			expected := p.Generate(0)
			if network == "tcp" {
				expected = expected + "\n"
			}
			select {
			case got := <-s.Messages:
				if got != expected {
					t.Errorf("expected %s, got %s", expected, got)
				}
			default:
				t.Errorf("expected %s, got nothing", expected)
				break
			}
		}
		if l := len(s.Messages); l != 0 {
			t.Errorf("found %d extra messages", l)
		}
	}
}
<|endoftext|>


<commit_before>// Copyright 2015 Google Inc. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package fuseutil

import (
	"flag"
	"io"
	"math/rand"
	"time"

	"github.com/jacobsa/fuse"
	"github.com/jacobsa/fuse/fuseops"
)

var fRandomDelays = flag.Bool(
	"fuseutil.random_delays", false,
	"If set, randomly delay each op received, to help expose concurrency issues.")

// An interface with a method for each op type in the fuseops package. This can
// be used in conjunction with NewFileSystemServer to avoid writing a "dispatch
// loop" that switches on op types, instead receiving typed method calls
// directly.
//
// The FileSystem implementation should not call Op.Respond, instead returning
// the error with which the caller should respond.
//
// See NotImplementedFileSystem for a convenient way to embed default
// implementations for methods you don't care about.
type FileSystem interface {
	Init(*fuseops.InitOp) error
	LookUpInode(*fuseops.LookUpInodeOp) error
	GetInodeAttributes(*fuseops.GetInodeAttributesOp) error
	SetInodeAttributes(*fuseops.SetInodeAttributesOp) error
	ForgetInode(*fuseops.ForgetInodeOp) error
	MkDir(*fuseops.MkDirOp) error
	CreateFile(*fuseops.CreateFileOp) error
	CreateSymlink(*fuseops.CreateSymlinkOp) error
	RmDir(*fuseops.RmDirOp) error
	Unlink(*fuseops.UnlinkOp) error
	OpenDir(*fuseops.OpenDirOp) error
	ReadDir(*fuseops.ReadDirOp) error
	ReleaseDirHandle(*fuseops.ReleaseDirHandleOp) error
	OpenFile(*fuseops.OpenFileOp) error
	ReadFile(*fuseops.ReadFileOp) error
	WriteFile(*fuseops.WriteFileOp) error
	SyncFile(*fuseops.SyncFileOp) error
	FlushFile(*fuseops.FlushFileOp) error
	ReleaseFileHandle(*fuseops.ReleaseFileHandleOp) error
	ReadSymlink(*fuseops.ReadSymlinkOp) error
}

// Create a fuse.Server that handles ops by calling the associated FileSystem
// method.Respond with the resulting error. Unsupported ops are responded to
// directly with ENOSYS.
//
// Each call to a FileSystem method is made on its own goroutine, and is free
// to block.
//
// (It is safe to naively process ops concurrently because the kernel
// guarantees to serialize operations that the user expects to happen in order,
// cf. http://goo.gl/jnkHPO, fuse-devel thread "Fuse guarantees on concurrent
// requests").
func NewFileSystemServer(fs FileSystem) fuse.Server {
	return fileSystemServer{fs}
}

type fileSystemServer struct {
	fs FileSystem
}

func (s fileSystemServer) ServeOps(c *fuse.Connection) {
	for {
		op, err := c.ReadOp()
		if err == io.EOF {
			break
		}

		if err != nil {
			panic(err)
		}

		go s.handleOp(op)
	}
}

func (s fileSystemServer) handleOp(op fuseops.Op) {
	// Delay if requested.
	if *fRandomDelays {
		const delayLimit = 100 * time.Microsecond
		delay := time.Duration(rand.Int63n(int64(delayLimit)))
		time.Sleep(delay)
	}

	// Dispatch to the appropriate method.
	switch typed := op.(type) {
	default:
		op.Respond(fuse.ENOSYS)

	case *fuseops.InitOp:
		s.fs.Init(typed)

	case *fuseops.LookUpInodeOp:
		s.fs.LookUpInode(typed)

	case *fuseops.GetInodeAttributesOp:
		s.fs.GetInodeAttributes(typed)

	case *fuseops.SetInodeAttributesOp:
		s.fs.SetInodeAttributes(typed)

	case *fuseops.ForgetInodeOp:
		s.fs.ForgetInode(typed)

	case *fuseops.MkDirOp:
		s.fs.MkDir(typed)

	case *fuseops.CreateFileOp:
		s.fs.CreateFile(typed)

	case *fuseops.CreateSymlinkOp:
		s.fs.CreateSymlink(typed)

	case *fuseops.RmDirOp:
		s.fs.RmDir(typed)

	case *fuseops.UnlinkOp:
		s.fs.Unlink(typed)

	case *fuseops.OpenDirOp:
		s.fs.OpenDir(typed)

	case *fuseops.ReadDirOp:
		s.fs.ReadDir(typed)

	case *fuseops.ReleaseDirHandleOp:
		s.fs.ReleaseDirHandle(typed)

	case *fuseops.OpenFileOp:
		s.fs.OpenFile(typed)

	case *fuseops.ReadFileOp:
		s.fs.ReadFile(typed)

	case *fuseops.WriteFileOp:
		s.fs.WriteFile(typed)

	case *fuseops.SyncFileOp:
		s.fs.SyncFile(typed)

	case *fuseops.FlushFileOp:
		s.fs.FlushFile(typed)

	case *fuseops.ReleaseFileHandleOp:
		s.fs.ReleaseFileHandle(typed)

	case *fuseops.ReadSymlinkOp:
		s.fs.ReadSymlink(typed)
	}
}
<commit_msg>Fixed fileSystemServer.handleOp.<commit_after>// Copyright 2015 Google Inc. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package fuseutil

import (
	"flag"
	"io"
	"math/rand"
	"time"

	"github.com/jacobsa/fuse"
	"github.com/jacobsa/fuse/fuseops"
)

var fRandomDelays = flag.Bool(
	"fuseutil.random_delays", false,
	"If set, randomly delay each op received, to help expose concurrency issues.")

// An interface with a method for each op type in the fuseops package. This can
// be used in conjunction with NewFileSystemServer to avoid writing a "dispatch
// loop" that switches on op types, instead receiving typed method calls
// directly.
//
// The FileSystem implementation should not call Op.Respond, instead returning
// the error with which the caller should respond.
//
// See NotImplementedFileSystem for a convenient way to embed default
// implementations for methods you don't care about.
type FileSystem interface {
	Init(*fuseops.InitOp) error
	LookUpInode(*fuseops.LookUpInodeOp) error
	GetInodeAttributes(*fuseops.GetInodeAttributesOp) error
	SetInodeAttributes(*fuseops.SetInodeAttributesOp) error
	ForgetInode(*fuseops.ForgetInodeOp) error
	MkDir(*fuseops.MkDirOp) error
	CreateFile(*fuseops.CreateFileOp) error
	CreateSymlink(*fuseops.CreateSymlinkOp) error
	RmDir(*fuseops.RmDirOp) error
	Unlink(*fuseops.UnlinkOp) error
	OpenDir(*fuseops.OpenDirOp) error
	ReadDir(*fuseops.ReadDirOp) error
	ReleaseDirHandle(*fuseops.ReleaseDirHandleOp) error
	OpenFile(*fuseops.OpenFileOp) error
	ReadFile(*fuseops.ReadFileOp) error
	WriteFile(*fuseops.WriteFileOp) error
	SyncFile(*fuseops.SyncFileOp) error
	FlushFile(*fuseops.FlushFileOp) error
	ReleaseFileHandle(*fuseops.ReleaseFileHandleOp) error
	ReadSymlink(*fuseops.ReadSymlinkOp) error
}

// Create a fuse.Server that handles ops by calling the associated FileSystem
// method.Respond with the resulting error. Unsupported ops are responded to
// directly with ENOSYS.
//
// Each call to a FileSystem method is made on its own goroutine, and is free
// to block.
//
// (It is safe to naively process ops concurrently because the kernel
// guarantees to serialize operations that the user expects to happen in order,
// cf. http://goo.gl/jnkHPO, fuse-devel thread "Fuse guarantees on concurrent
// requests").
func NewFileSystemServer(fs FileSystem) fuse.Server {
	return fileSystemServer{fs}
}

type fileSystemServer struct {
	fs FileSystem
}

func (s fileSystemServer) ServeOps(c *fuse.Connection) {
	for {
		op, err := c.ReadOp()
		if err == io.EOF {
			break
		}

		if err != nil {
			panic(err)
		}

		go s.handleOp(op)
	}
}

func (s fileSystemServer) handleOp(op fuseops.Op) {
	// Delay if requested.
	if *fRandomDelays {
		const delayLimit = 100 * time.Microsecond
		delay := time.Duration(rand.Int63n(int64(delayLimit)))
		time.Sleep(delay)
	}

	// Dispatch to the appropriate method.
	var err error
	switch typed := op.(type) {
	default:
		err = fuse.ENOSYS

	case *fuseops.InitOp:
		err = s.fs.Init(typed)

	case *fuseops.LookUpInodeOp:
		err = s.fs.LookUpInode(typed)

	case *fuseops.GetInodeAttributesOp:
		err = s.fs.GetInodeAttributes(typed)

	case *fuseops.SetInodeAttributesOp:
		err = s.fs.SetInodeAttributes(typed)

	case *fuseops.ForgetInodeOp:
		err = s.fs.ForgetInode(typed)

	case *fuseops.MkDirOp:
		err = s.fs.MkDir(typed)

	case *fuseops.CreateFileOp:
		err = s.fs.CreateFile(typed)

	case *fuseops.CreateSymlinkOp:
		err = s.fs.CreateSymlink(typed)

	case *fuseops.RmDirOp:
		err = s.fs.RmDir(typed)

	case *fuseops.UnlinkOp:
		err = s.fs.Unlink(typed)

	case *fuseops.OpenDirOp:
		err = s.fs.OpenDir(typed)

	case *fuseops.ReadDirOp:
		err = s.fs.ReadDir(typed)

	case *fuseops.ReleaseDirHandleOp:
		err = s.fs.ReleaseDirHandle(typed)

	case *fuseops.OpenFileOp:
		err = s.fs.OpenFile(typed)

	case *fuseops.ReadFileOp:
		err = s.fs.ReadFile(typed)

	case *fuseops.WriteFileOp:
		err = s.fs.WriteFile(typed)

	case *fuseops.SyncFileOp:
		err = s.fs.SyncFile(typed)

	case *fuseops.FlushFileOp:
		err = s.fs.FlushFile(typed)

	case *fuseops.ReleaseFileHandleOp:
		err = s.fs.ReleaseFileHandle(typed)

	case *fuseops.ReadSymlinkOp:
		err = s.fs.ReadSymlink(typed)
	}

	op.Respond(err)
}
<|endoftext|>


<commit_before>// Copyright 2017 gf Author(https://github.com/gogf/gf). All Rights Reserved.
//
// This Source Code Form is subject to the terms of the MIT License.
// If a copy of the MIT was not distributed with this file,
// You can obtain one at https://github.com/gogf/gf.

// Package gxml provides accessing and converting for XML content.
//
// XML数据格式解析。
package gxml

import (
	"fmt"
	"github.com/gogf/gf/g/text/gregex"
	"github.com/gogf/gf/third/github.com/axgle/mahonia"
	"github.com/gogf/gf/third/github.com/clbanning/mxj"
	"strings"
)

// 将XML内容解析为map变量
func Decode(content []byte) (map[string]interface{}, error) {
	res, err := convert(content)
	if err != nil {
		return nil, err
	}
	return mxj.NewMapXml(res)
}

// 将map变量解析为XML格式内容
func Encode(v map[string]interface{}, rootTag ...string) ([]byte, error) {
	return mxj.Map(v).Xml(rootTag...)
}

func EncodeWithIndent(v map[string]interface{}, rootTag ...string) ([]byte, error) {
	return mxj.Map(v).XmlIndent("", "\t", rootTag...)
}

// XML格式内容直接转换为JSON格式内容
func ToJson(content []byte) ([]byte, error) {
	res, err := convert(content)
	if err != nil {
		fmt.Println("convert error. ", err)
		return nil, err
	}

	mv, err := mxj.NewMapXml(res)
	if err == nil {
		return mv.Json()
	} else {
		return nil, err
	}
}

// XML字符集预处理
// @author wenzi1
// @date 20180604  修复并发安全问题,改为如果非UTF8字符集则先做字符集转换
func convert(xmlbyte []byte) (res []byte, err error) {
	patten := `<\?xml.*encoding\s*=\s*['|"](.*?)['|"].*\?>`
	matchStr, err := gregex.MatchString(patten, string(xmlbyte))
	if err != nil {
		return nil, err
	}

	xmlEncode := "UTF-8"
	if len(matchStr) == 2 {
		xmlEncode = matchStr[1]
	}

	s := mahonia.GetCharset(xmlEncode)
	if s == nil {
		return nil, fmt.Errorf("not support charset:%s\n", xmlEncode)
	}
	fmt.Println(s.Name, xmlEncode)
	res, err = gregex.Replace(patten, []byte(""), []byte(xmlbyte))
	if err != nil {
		return nil, err
	}

	if !strings.EqualFold(s.Name, "UTF-8") {
		res = []byte(s.NewDecoder().ConvertString(string(res)))
	}

	return res, nil
}
<commit_msg>修复并发安全问题,改为如果非UTF8字符集则先做字符集转换<commit_after>// Copyright 2017 gf Author(https://github.com/gogf/gf). All Rights Reserved.
//
// This Source Code Form is subject to the terms of the MIT License.
// If a copy of the MIT was not distributed with this file,
// You can obtain one at https://github.com/gogf/gf.

// Package gxml provides accessing and converting for XML content.
//
// XML数据格式解析。
package gxml

import (
	"fmt"
	"github.com/gogf/gf/g/text/gregex"
	"github.com/gogf/gf/third/github.com/axgle/mahonia"
	"github.com/gogf/gf/third/github.com/clbanning/mxj"
	"strings"
)

// 将XML内容解析为map变量
func Decode(content []byte) (map[string]interface{}, error) {
	res, err := convert(content)
	if err != nil {
		return nil, err
	}
	return mxj.NewMapXml(res)
}

// 将map变量解析为XML格式内容
func Encode(v map[string]interface{}, rootTag ...string) ([]byte, error) {
	return mxj.Map(v).Xml(rootTag...)
}

func EncodeWithIndent(v map[string]interface{}, rootTag ...string) ([]byte, error) {
	return mxj.Map(v).XmlIndent("", "\t", rootTag...)
}

// XML格式内容直接转换为JSON格式内容
func ToJson(content []byte) ([]byte, error) {
	res, err := convert(content)
	if err != nil {
		fmt.Println("convert error. ", err)
		return nil, err
	}

	mv, err := mxj.NewMapXml(res)
	if err == nil {
		return mv.Json()
	} else {
		return nil, err
	}
}

// XML字符集预处理
// @author wenzi1
// @date 20180604  修复并发安全问题,改为如果非UTF8字符集则先做字符集转换
func convert(xmlbyte []byte) (res []byte, err error) {
	patten := `<\?xml.*encoding\s*=\s*['|"](.*?)['|"].*\?>`
	matchStr, err := gregex.MatchString(patten, string(xmlbyte))
	if err != nil {
		return nil, err
	}

	xmlEncode := "UTF-8"
	if len(matchStr) == 2 {
		xmlEncode = matchStr[1]
	}

	s := mahonia.GetCharset(xmlEncode)
	if s == nil {
		return nil, fmt.Errorf("not support charset:%s\n", xmlEncode)
	}

	res, err = gregex.Replace(patten, []byte(""), []byte(xmlbyte))
	if err != nil {
		return nil, err
	}

	if !strings.EqualFold(s.Name, "UTF-8") {
		res = []byte(s.NewDecoder().ConvertString(string(res)))
	}

	return res, nil
}
<|endoftext|>


<commit_before>package gateway

import (
	"bytes"
	"encoding/json"
	"fmt"
	"io"
	"io/ioutil"
	"net/http"

	"github.com/clbanning/mxj"
	"golang.org/x/net/html/charset"

	"github.com/TykTechnologies/tyk/apidef"
)

func WrappedCharsetReader(s string, i io.Reader) (io.Reader, error) {
	return charset.NewReader(i, s)
}

// TransformMiddleware is a middleware that will apply a template to a request body to transform it's contents ready for an upstream API
type TransformMiddleware struct {
	BaseMiddleware
}

func (t *TransformMiddleware) Name() string {
	return "TransformMiddleware"
}

func (t *TransformMiddleware) EnabledForSpec() bool {
	for _, version := range t.Spec.VersionData.Versions {
		if len(version.ExtendedPaths.Transform) > 0 {
			return true
		}
	}
	return false
}

// ProcessRequest will run any checks on the request on the way through the system, return an error to have the chain fail
func (t *TransformMiddleware) ProcessRequest(w http.ResponseWriter, r *http.Request, _ interface{}) (error, int) {
	_, versionPaths, _, _ := t.Spec.Version(r)
	found, meta := t.Spec.CheckSpecMatchesStatus(r, versionPaths, Transformed)
	if !found {
		return nil, http.StatusOK
	}
	err := transformBody(r, meta.(*TransformSpec), t.Spec.EnableContextVars)
	if err != nil {
		t.Logger().WithError(err).Error("Body transform failure")
	}
	return nil, http.StatusOK
}

func transformBody(r *http.Request, tmeta *TransformSpec, contextVars bool) error {
	body, _ := ioutil.ReadAll(r.Body)
	defer r.Body.Close()

	// Put into an interface:
	bodyData := make(map[string]interface{})

	switch tmeta.TemplateData.Input {
	case apidef.RequestXML:
		if len(body) == 0 {
			body = []byte("<_/>")
		}
		mxj.XmlCharsetReader = WrappedCharsetReader
		var err error
		bodyData, err = mxj.NewMapXml(body) // unmarshal
		if err != nil {
			return fmt.Errorf("error unmarshalling XML: %v", err)
		}
	case apidef.RequestJSON:
		if len(body) == 0 {
			body = []byte("{}")
		}
		var tempBody interface{}
		if err := json.Unmarshal(body, &tempBody); err != nil {
			return err
		}

		switch tempBody.(type) {
		case []interface{}:
			bodyData["array"] = tempBody
		case map[string]interface{}:
			bodyData = tempBody.(map[string]interface{})
		}
	default:
		return fmt.Errorf("unsupported request input type: %v", tmeta.TemplateData.Input)
	}

	if tmeta.TemplateData.EnableSession {
		if session := ctxGetSession(r); session != nil {
			bodyData["_tyk_meta"] = session.MetaData
		} else {
			log.Error("Session context was enabled but not found.")
		}
	}

	if contextVars {
		bodyData["_tyk_context"] = ctxGetData(r)
	}

	// Apply to template
	var bodyBuffer bytes.Buffer
	if err := tmeta.Template.Execute(&bodyBuffer, bodyData); err != nil {
		return fmt.Errorf("failed to apply template to request: %v", err)
	}
	r.Body = ioutil.NopCloser(&bodyBuffer)
	r.ContentLength = int64(bodyBuffer.Len())

	return nil
}
<commit_msg>Fix Body Transform with Validate JSON plugin (#2446)<commit_after>package gateway

import (
	"bytes"
	"encoding/json"
	"fmt"
	"io"
	"io/ioutil"
	"net/http"

	"github.com/clbanning/mxj"
	"golang.org/x/net/html/charset"

	"github.com/TykTechnologies/tyk/apidef"
)

func WrappedCharsetReader(s string, i io.Reader) (io.Reader, error) {
	return charset.NewReader(i, s)
}

// TransformMiddleware is a middleware that will apply a template to a request body to transform it's contents ready for an upstream API
type TransformMiddleware struct {
	BaseMiddleware
}

func (t *TransformMiddleware) Name() string {
	return "TransformMiddleware"
}

func (t *TransformMiddleware) EnabledForSpec() bool {
	for _, version := range t.Spec.VersionData.Versions {
		if len(version.ExtendedPaths.Transform) > 0 {
			return true
		}
	}
	return false
}

// ProcessRequest will run any checks on the request on the way through the system, return an error to have the chain fail
func (t *TransformMiddleware) ProcessRequest(w http.ResponseWriter, r *http.Request, _ interface{}) (error, int) {
	_, versionPaths, _, _ := t.Spec.Version(r)
	found, meta := t.Spec.CheckSpecMatchesStatus(r, versionPaths, Transformed)
	if !found {
		return nil, http.StatusOK
	}
	err := transformBody(r, meta.(*TransformSpec), t.Spec.EnableContextVars)
	if err != nil {
		t.Logger().WithError(err).Error("Body transform failure")
	}
	return nil, http.StatusOK
}

func transformBody(r *http.Request, tmeta *TransformSpec, contextVars bool) error {
	body, _ := ioutil.ReadAll(r.Body)
	defer r.Body.Close()

	// Put into an interface:
	bodyData := make(map[string]interface{})

	switch tmeta.TemplateData.Input {
	case apidef.RequestXML:
		if len(body) == 0 {
			body = []byte("<_/>")
		}
		mxj.XmlCharsetReader = WrappedCharsetReader
		var err error
		bodyData, err = mxj.NewMapXml(body) // unmarshal
		if err != nil {
			return fmt.Errorf("error unmarshalling XML: %v", err)
		}
	case apidef.RequestJSON:
		if len(body) == 0 {
			body = []byte("{}")
		}

		var tempBody interface{}
		if err := json.Unmarshal(body, &tempBody); err != nil {
			return err
		}

		switch tempBody.(type) {
		case []interface{}:
			bodyData["array"] = tempBody
		case map[string]interface{}:
			bodyData = tempBody.(map[string]interface{})
		}
	default:
		return fmt.Errorf("unsupported request input type: %v", tmeta.TemplateData.Input)
	}

	if tmeta.TemplateData.EnableSession {
		if session := ctxGetSession(r); session != nil {
			bodyData["_tyk_meta"] = session.MetaData
		} else {
			log.Error("Session context was enabled but not found.")
		}
	}

	if contextVars {
		bodyData["_tyk_context"] = ctxGetData(r)
	}

	// Apply to template
	var bodyBuffer bytes.Buffer
	if err := tmeta.Template.Execute(&bodyBuffer, bodyData); err != nil {
		return fmt.Errorf("failed to apply template to request: %v", err)
	}
	r.Body = ioutil.NopCloser(&bodyBuffer)
	r.ContentLength = int64(bodyBuffer.Len())
	nopCloseRequestBody(r)

	return nil
}
<|endoftext|>


<commit_before>package generator

import (
	"fmt"
	"io"
	"strings"

	tl "github.com/xlab/cgogen/translator"
)

var (
	skipName    = []byte("_")
	skipNameStr = "_"
)

func (gen *Generator) writeStructMembers(wr io.Writer, structName string, spec tl.CType) {
	structSpec := spec.(*tl.CStructSpec)
	ptrTipRx, typeTipRx, memTipRx := gen.tr.TipRxsForSpec(tl.TipScopeType, structName, structSpec)
	const public = true
	for i, member := range structSpec.Members {
		ptrTip := ptrTipRx.TipAt(i)
		if !ptrTip.IsValid() {
			ptrTip = tl.TipPtrArr
		}
		typeTip := typeTipRx.TipAt(i)
		if !typeTip.IsValid() {
			typeTip = tl.TipTypeNamed
		}
		memTip := memTipRx.TipAt(i)
		if !memTip.IsValid() {
			memTip = gen.MemTipOf(member)
		}
		if memTip == tl.TipMemRaw {
			ptrTip = tl.TipPtrSRef
		}
		declName := checkName(gen.tr.TransformName(tl.TargetType, member.Name, public))
		switch member.Spec.Kind() {
		case tl.TypeKind:
			goSpec := gen.tr.TranslateSpec(member.Spec, ptrTip, typeTip)
			fmt.Fprintf(wr, "%s %s", declName, goSpec)
		case tl.StructKind, tl.OpaqueStructKind, tl.UnionKind:
			if !gen.tr.IsAcceptableName(tl.TargetType, member.Spec.GetBase()) {
				continue
			}
			goSpec := gen.tr.TranslateSpec(member.Spec, ptrTip, typeTip)
			fmt.Fprintf(wr, "%s %s", declName, goSpec)
		case tl.EnumKind:
			if !gen.tr.IsAcceptableName(tl.TargetType, member.Spec.GetBase()) {
				continue
			}
			typeRef := gen.tr.TranslateSpec(member.Spec, ptrTip, typeTip).String()
			fmt.Fprintf(wr, "%s %s", declName, typeRef)
		case tl.FunctionKind:
			gen.writeFunctionAsArg(wr, member, ptrTip, typeTip, public)
		}
		writeSpace(wr, 1)
	}

	if memTipRx.Self() == tl.TipMemRaw {
		return
	}

	crc := getRefCRC(structSpec)
	cgoSpec := gen.tr.CGoSpec(structSpec, false)
	if len(cgoSpec.Base) == 0 {
		return
	}
	fmt.Fprintf(wr, "ref%2x *%s\n", crc, cgoSpec)
	fmt.Fprintf(wr, "allocs%2x interface{}\n", crc)
}

func (gen *Generator) writeFunctionParams(wr io.Writer, funcName string, funcSpec tl.CType) {
	spec := funcSpec.(*tl.CFunctionSpec)
	ptrTipSpecRx, _ := gen.tr.PtrTipRx(tl.TipScopeFunction, funcName)
	typeTipSpecRx, _ := gen.tr.TypeTipRx(tl.TipScopeFunction, funcName)
	const public = false

	writeStartParams(wr)
	for i, param := range spec.Params {
		ptrTip := ptrTipSpecRx.TipAt(i)
		if !ptrTip.IsValid() {
			ptrTip = tl.TipPtrArr
		}
		typeTip := typeTipSpecRx.TipAt(i)
		declName := checkName(gen.tr.TransformName(tl.TargetType, param.Name, public))
		switch param.Spec.Kind() {
		case tl.TypeKind:
			goSpec := gen.tr.TranslateSpec(param.Spec, ptrTip, typeTip)
			if len(goSpec.OuterArr) > 0 {
				fmt.Fprintf(wr, "%s *%s", declName, goSpec)
			} else {
				fmt.Fprintf(wr, "%s %s", declName, goSpec)
			}
		case tl.StructKind, tl.OpaqueStructKind, tl.UnionKind:
			goSpec := gen.tr.TranslateSpec(param.Spec, ptrTip, typeTip)
			if len(goSpec.OuterArr) > 0 {
				fmt.Fprintf(wr, "%s *%s", declName, goSpec)
			} else {
				fmt.Fprintf(wr, "%s %s", declName, goSpec)
			}
		case tl.EnumKind:
			typeRef := gen.tr.TranslateSpec(param.Spec, ptrTip, typeTip).String()
			fmt.Fprintf(wr, "%s %s", declName, typeRef)
		case tl.FunctionKind:
			gen.writeFunctionAsArg(wr, param, ptrTip, typeTip, public)
		}
		if i < len(spec.Params)-1 {
			fmt.Fprintf(wr, ", ")
		}
	}
	writeEndParams(wr)
}

func writeStartParams(wr io.Writer) {
	fmt.Fprint(wr, "(")
}

func writeEndParams(wr io.Writer) {
	fmt.Fprint(wr, ")")
}

func writeEndStruct(wr io.Writer) {
	fmt.Fprint(wr, "}")
}

func writeStartFuncBody(wr io.Writer) {
	fmt.Fprintln(wr, "{")
}

func writeEndFuncBody(wr io.Writer) {
	fmt.Fprintln(wr, "}")
}

func writeSpace(wr io.Writer, n int) {
	fmt.Fprint(wr, strings.Repeat("\n", n))
}

func writeError(wr io.Writer, err error) {
	fmt.Fprintf(wr, "// error: %v\n", err)
}
<commit_msg>Use self type tips in func args.<commit_after>package generator

import (
	"fmt"
	"io"
	"strings"

	tl "github.com/xlab/cgogen/translator"
)

var (
	skipName    = []byte("_")
	skipNameStr = "_"
)

func (gen *Generator) writeStructMembers(wr io.Writer, structName string, spec tl.CType) {
	structSpec := spec.(*tl.CStructSpec)
	ptrTipRx, typeTipRx, memTipRx := gen.tr.TipRxsForSpec(tl.TipScopeType, structName, structSpec)
	const public = true
	for i, member := range structSpec.Members {
		ptrTip := ptrTipRx.TipAt(i)
		if !ptrTip.IsValid() {
			ptrTip = tl.TipPtrArr
		}
		typeTip := typeTipRx.TipAt(i)
		if !typeTip.IsValid() {
			typeTip = tl.TipTypeNamed
		}
		memTip := memTipRx.TipAt(i)
		if !memTip.IsValid() {
			memTip = gen.MemTipOf(member)
		}
		if memTip == tl.TipMemRaw {
			ptrTip = tl.TipPtrSRef
		}
		declName := checkName(gen.tr.TransformName(tl.TargetType, member.Name, public))
		switch member.Spec.Kind() {
		case tl.TypeKind:
			goSpec := gen.tr.TranslateSpec(member.Spec, ptrTip, typeTip)
			fmt.Fprintf(wr, "%s %s", declName, goSpec)
		case tl.StructKind, tl.OpaqueStructKind, tl.UnionKind:
			if !gen.tr.IsAcceptableName(tl.TargetType, member.Spec.GetBase()) {
				continue
			}
			goSpec := gen.tr.TranslateSpec(member.Spec, ptrTip, typeTip)
			fmt.Fprintf(wr, "%s %s", declName, goSpec)
		case tl.EnumKind:
			if !gen.tr.IsAcceptableName(tl.TargetType, member.Spec.GetBase()) {
				continue
			}
			typeRef := gen.tr.TranslateSpec(member.Spec, ptrTip, typeTip).String()
			fmt.Fprintf(wr, "%s %s", declName, typeRef)
		case tl.FunctionKind:
			gen.writeFunctionAsArg(wr, member, ptrTip, typeTip, public)
		}
		writeSpace(wr, 1)
	}

	if memTipRx.Self() == tl.TipMemRaw {
		return
	}

	crc := getRefCRC(structSpec)
	cgoSpec := gen.tr.CGoSpec(structSpec, false)
	if len(cgoSpec.Base) == 0 {
		return
	}
	fmt.Fprintf(wr, "ref%2x *%s\n", crc, cgoSpec)
	fmt.Fprintf(wr, "allocs%2x interface{}\n", crc)
}

func (gen *Generator) writeFunctionParams(wr io.Writer, funcName string, funcSpec tl.CType) {
	spec := funcSpec.(*tl.CFunctionSpec)
	ptrTipSpecRx, _ := gen.tr.PtrTipRx(tl.TipScopeFunction, funcName)
	typeTipSpecRx, _ := gen.tr.TypeTipRx(tl.TipScopeFunction, funcName)
	const public = false

	writeStartParams(wr)
	for i, param := range spec.Params {
		ptrTip := ptrTipSpecRx.TipAt(i)
		if !ptrTip.IsValid() {
			ptrTip = tl.TipPtrArr
		}
		typeTip := typeTipSpecRx.TipAt(i)
		if !typeTip.IsValid() {
			// try to use type tip for the type itself
			if tip, ok := gen.tr.TypeTipRx(tl.TipScopeType, param.Spec.CGoName()); ok {
				if tip := tip.Self(); tip.IsValid() {
					typeTip = tip
				}
			}
		}
		declName := checkName(gen.tr.TransformName(tl.TargetType, param.Name, public))
		switch param.Spec.Kind() {
		case tl.TypeKind:
			goSpec := gen.tr.TranslateSpec(param.Spec, ptrTip, typeTip)
			if len(goSpec.OuterArr) > 0 {
				fmt.Fprintf(wr, "%s *%s", declName, goSpec)
			} else {
				fmt.Fprintf(wr, "%s %s", declName, goSpec)
			}
		case tl.StructKind, tl.OpaqueStructKind, tl.UnionKind:
			goSpec := gen.tr.TranslateSpec(param.Spec, ptrTip, typeTip)
			if len(goSpec.OuterArr) > 0 {
				fmt.Fprintf(wr, "%s *%s", declName, goSpec)
			} else {
				fmt.Fprintf(wr, "%s %s", declName, goSpec)
			}
		case tl.EnumKind:
			typeRef := gen.tr.TranslateSpec(param.Spec, ptrTip, typeTip).String()
			fmt.Fprintf(wr, "%s %s", declName, typeRef)
		case tl.FunctionKind:
			gen.writeFunctionAsArg(wr, param, ptrTip, typeTip, public)
		}
		if i < len(spec.Params)-1 {
			fmt.Fprintf(wr, ", ")
		}
	}
	writeEndParams(wr)
}

func writeStartParams(wr io.Writer) {
	fmt.Fprint(wr, "(")
}

func writeEndParams(wr io.Writer) {
	fmt.Fprint(wr, ")")
}

func writeEndStruct(wr io.Writer) {
	fmt.Fprint(wr, "}")
}

func writeStartFuncBody(wr io.Writer) {
	fmt.Fprintln(wr, "{")
}

func writeEndFuncBody(wr io.Writer) {
	fmt.Fprintln(wr, "}")
}

func writeSpace(wr io.Writer, n int) {
	fmt.Fprint(wr, strings.Repeat("\n", n))
}

func writeError(wr io.Writer, err error) {
	fmt.Fprintf(wr, "// error: %v\n", err)
}
<|endoftext|>


<commit_before>// Copyright 2016 Mesosphere, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package http

import (
	"fmt"
	"net/http"
	"time"

	log "github.com/Sirupsen/logrus"
	"github.com/dcos/dcos-go/store"
	"github.com/dcos/dcos-metrics/producers"
)

// Config for the HTTP producer
type Config struct {
	Port        int           `yaml:"port"`
	CacheExpiry time.Duration // ideally this is a multiple of the collector's PollingPeriod
}

type producerImpl struct {
	config      Config
	store       store.Store
	metricsChan chan producers.MetricsMessage
}

// New creates a new instance of the HTTP producer with the provided configuration.
func New(cfg Config) (producers.MetricsProducer, chan producers.MetricsMessage) {
	p := producerImpl{
		config:      cfg,
		store:       store.New(),
		metricsChan: make(chan producers.MetricsMessage),
	}
	return &p, p.metricsChan
}

// Run a HTTP server and serve the various metrics API endpoints.
// This function should be run in its own goroutine.
func (p *producerImpl) Run() error {
	r := newRouter(p)
	if err := http.ListenAndServe(fmt.Sprintf(":%d", p.config.Port), r); err != nil {
		log.Fatalf("error: http producer: %s", err)
	}
	log.Infof("The HTTP producer is serving requests on port %d", p.config.Port)
	log.Info("Starting janitor for in-memory data store")
	go p.janitor()

	for {
		message := <-p.metricsChan         // read messages off the channel
		p.store.Set(message.Name, message) // overwrite existing object with the same message.Name
	}
}

// janitor analyzes the objects in the store and removes stale objects. An
// object is considered stale when the top-level timestamp of its MetricsMessage
// has exceeded the CacheExpiry, which is calculated as a multiple of the
// collector's polling period. This function should be run in its own goroutine.
func (p *producerImpl) janitor() {
	ticker := time.NewTicker(time.Duration(60 * time.Second))
	for {
		select {
		case _ = <-ticker.C:
			for _, obj := range p.store.Objects() {
				o := obj.(producers.MetricsMessage)

				lastUpdated := time.Since(o.Timestamp)
				if lastUpdated > p.config.CacheExpiry {
					log.Debugf("Removing stale object %s; last updated %d seconds ago", o.Name, lastUpdated*time.Second)
					p.store.Delete(o.Name)
				}
			}
		}
	}
}
<commit_msg>run http.ListenAndServe in a goroutine (it blocks)<commit_after>// Copyright 2016 Mesosphere, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package http

import (
	"fmt"
	"net/http"
	"time"

	log "github.com/Sirupsen/logrus"
	"github.com/dcos/dcos-go/store"
	"github.com/dcos/dcos-metrics/producers"
)

// Config for the HTTP producer
type Config struct {
	Port        int           `yaml:"port"`
	CacheExpiry time.Duration // ideally this is a multiple of the collector's PollingPeriod
}

type producerImpl struct {
	config      Config
	store       store.Store
	metricsChan chan producers.MetricsMessage
}

// New creates a new instance of the HTTP producer with the provided configuration.
func New(cfg Config) (producers.MetricsProducer, chan producers.MetricsMessage) {
	p := producerImpl{
		config:      cfg,
		store:       store.New(),
		metricsChan: make(chan producers.MetricsMessage),
	}
	return &p, p.metricsChan
}

// Run a HTTP server and serve the various metrics API endpoints.
// This function should be run in its own goroutine.
func (p *producerImpl) Run() error {
	r := newRouter(p)
	go func() {
		log.Fatal(http.ListenAndServe(fmt.Sprintf(":%d", p.config.Port), r)) // http.ListenAndServe blocks
	}()

	log.Infof("The HTTP producer is serving requests on port %d", p.config.Port)
	log.Info("Starting janitor for in-memory data store")
	go p.janitor()

	for {
		message := <-p.metricsChan         // read messages off the channel
		p.store.Set(message.Name, message) // overwrite existing object with the same message.Name
	}
}

// janitor analyzes the objects in the store and removes stale objects. An
// object is considered stale when the top-level timestamp of its MetricsMessage
// has exceeded the CacheExpiry, which is calculated as a multiple of the
// collector's polling period. This function should be run in its own goroutine.
func (p *producerImpl) janitor() {
	ticker := time.NewTicker(time.Duration(60 * time.Second))
	for {
		select {
		case _ = <-ticker.C:
			for _, obj := range p.store.Objects() {
				o := obj.(producers.MetricsMessage)

				lastUpdated := time.Since(o.Timestamp)
				if lastUpdated > p.config.CacheExpiry {
					log.Debugf("Removing stale object %s; last updated %d seconds ago", o.Name, lastUpdated*time.Second)
					p.store.Delete(o.Name)
				}
			}
		}
	}
}
<|endoftext|>


<commit_before>// Copyright 2017 Jeff Foley. All rights reserved.
// Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file.

package utils

import (
	"fmt"
	"strconv"
	"strings"

	"github.com/OWASP/Amass/requests"
	"github.com/fatih/color"
)

// Banner is the ASCII art logo used within help output.
const Banner = `

        .+++:.            :                             .+++.
      +W@@@@@@8        &+W@#               o8W8:      +W@@@@@@#.   oW@@@W#+
     &@#+   .o@##.    .@@@o@W.o@@o       :@@#&W8o    .@#:  .:oW+  .@#+++&#&
    +@&        &@&     #@8 +@W@&8@+     :@W.   +@8   +@:          .@8
    8@          @@     8@o  8@8  WW    .@W      W@+  .@W.          o@#:
    WW          &@o    &@:  o@+  o@+   #@.      8@o   +W@#+.        +W@8:
    #@          :@W    &@+  &@+   @8  :@o       o@o     oW@@W+        oW@8
    o@+          @@&   &@+  &@+   #@  &@.      .W@W       .+#@&         o@W.
     WW         +@W@8. &@+  :&    o@+ #@      :@W&@&         &@:  ..     :@o
     :@W:      o@# +Wo &@+        :W: +@W&o++o@W. &@&  8@#o+&@W.  #@:    o@+
      :W@@WWWW@@8       +              :&W@@@@&    &W  .o#@@W&.   :W@WWW@@&
        +o&&&&+.                                                    +oooo.

`

const (
	// Version is used to display the current version of Amass.
	Version = "v3.0.21"

	// Author is used to display the Amass Project Team.
	Author = "OWASP Amass Project - @owaspamass"
)

var (
	// Colors used to ease the reading of program output
	y      = color.New(color.FgHiYellow)
	g      = color.New(color.FgHiGreen)
	r      = color.New(color.FgHiRed)
	b      = color.New(color.FgHiBlue)
	fgR    = color.New(color.FgRed)
	fgY    = color.New(color.FgYellow)
	yellow = color.New(color.FgHiYellow).SprintFunc()
	green  = color.New(color.FgHiGreen).SprintFunc()
	blue   = color.New(color.FgHiBlue).SprintFunc()
)

// ASNSummaryData stores information related to discovered ASs and netblocks.
type ASNSummaryData struct {
	Name      string
	Netblocks map[string]int
}

// UpdateSummaryData updates the summary maps using the provided requests.Output data.
func UpdateSummaryData(output *requests.Output, tags map[string]int, asns map[int]*ASNSummaryData) {
	tags[output.Tag]++

	for _, addr := range output.Addresses {
		data, found := asns[addr.ASN]
		if !found {
			asns[addr.ASN] = &ASNSummaryData{
				Name:      addr.Description,
				Netblocks: make(map[string]int),
			}
			data = asns[addr.ASN]
		}
		// Increment how many IPs were in this netblock
		data.Netblocks[addr.Netblock.String()]++
	}
}

// PrintEnumerationSummary outputs the summary information utilized by the command-line tools.
func PrintEnumerationSummary(total int, tags map[string]int, asns map[int]*ASNSummaryData, demo bool) {
	pad := func(num int, chr string) {
		for i := 0; i < num; i++ {
			b.Fprint(color.Error, chr)
		}
	}

	fmt.Fprintln(color.Error)
	// Print the header information
	title := "OWASP Amass v"
	site := "https://github.com/OWASP/Amass"
	b.Fprint(color.Error, title+Version)
	num := 80 - (len(title) + len(Version) + len(site))
	pad(num, " ")
	b.Fprintf(color.Error, "%s\n", site)
	pad(8, "----------")
	fmt.Fprintf(color.Error, "\n%s%s", yellow(strconv.Itoa(total)), green(" names discovered - "))
	// Print the stats using tag information
	num, length := 1, len(tags)
	for k, v := range tags {
		fmt.Fprintf(color.Error, "%s: %s", green(k), yellow(strconv.Itoa(v)))
		if num < length {
			g.Fprint(color.Error, ", ")
		}
		num++
	}
	fmt.Fprintln(color.Error)

	if len(asns) == 0 {
		return
	}
	// Another line gets printed
	pad(8, "----------")
	fmt.Fprintln(color.Error)
	// Print the ASN and netblock information
	for asn, data := range asns {
		asnstr := strconv.Itoa(asn)
		datastr := data.Name

		if demo && asn > 0 {
			asnstr = censorString(asnstr, 0, len(asnstr))
			datastr = censorString(datastr, 0, len(datastr))
		}

		fmt.Fprintf(color.Error, "%s%s %s %s\n",
			blue("ASN: "), yellow(asnstr), green("-"), green(datastr))

		for cidr, ips := range data.Netblocks {
			countstr := strconv.Itoa(ips)
			cidrstr := cidr

			if demo {
				cidrstr = censorNetBlock(cidrstr)
			}

			countstr = fmt.Sprintf("\t%-4s", countstr)
			cidrstr = fmt.Sprintf("\t%-18s", cidrstr)

			fmt.Fprintf(color.Error, "%s%s %s\n",
				yellow(cidrstr), yellow(countstr), blue("Subdomain Name(s)"))
		}
	}
}

// PrintBanner outputs the Amass banner the same for all tools.
func PrintBanner() {
	y := color.New(color.FgHiYellow)
	r := color.New(color.FgHiRed)
	rightmost := 76
	version := "Version " + Version
	desc := "In-depth DNS Enumeration and Network Mapping"

	pad := func(num int) {
		for i := 0; i < num; i++ {
			fmt.Fprint(color.Error, " ")
		}
	}
	r.Fprintln(color.Error, Banner)
	pad(rightmost - len(version))
	y.Fprintln(color.Error, version)
	pad(rightmost - len(Author))
	y.Fprintln(color.Error, Author)
	pad(rightmost - len(desc))
	y.Fprintf(color.Error, "%s\n\n\n", desc)
}

func censorDomain(input string) string {
	return censorString(input, strings.Index(input, "."), len(input))
}

func censorIP(input string) string {
	return censorString(input, 0, strings.LastIndex(input, "."))
}

func censorNetBlock(input string) string {
	return censorString(input, 0, strings.Index(input, "/"))
}

func censorString(input string, start, end int) string {
	runes := []rune(input)
	for i := start; i < end; i++ {
		if runes[i] == '.' ||
			runes[i] == '/' ||
			runes[i] == '-' ||
			runes[i] == ' ' {
			continue
		}
		runes[i] = 'x'
	}
	return string(runes)
}

// OutputLineParts returns the parts of a line to be printed for a requests.Output.
func OutputLineParts(out *requests.Output, src, addrs, demo bool) (source, name, ips string) {
	if src {
		source = fmt.Sprintf("%-18s", "["+out.Source+"] ")
	}
	if addrs {
		for i, a := range out.Addresses {
			if i != 0 {
				ips += ","
			}
			if demo {
				ips += censorIP(a.Address.String())
			} else {
				ips += a.Address.String()
			}
		}
		if ips == "" {
			ips = "N/A"
		}
	}
	name = out.Name
	if demo {
		name = censorDomain(name)
	}
	return
}

// DesiredAddrTypes removes undesired address types from the AddressInfo slice.
func DesiredAddrTypes(addrs []requests.AddressInfo, ipv4, ipv6 bool) []requests.AddressInfo {
	if !ipv4 && !ipv6 {
		return addrs
	}

	var keep []requests.AddressInfo
	for _, addr := range addrs {
		if IsIPv4(addr.Address) && !ipv4 {
			continue
		} else if IsIPv6(addr.Address) && !ipv6 {
			continue
		}
		keep = append(keep, addr)
	}
	return keep
}
<commit_msg>v3.0.22 release<commit_after>// Copyright 2017 Jeff Foley. All rights reserved.
// Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file.

package utils

import (
	"fmt"
	"strconv"
	"strings"

	"github.com/OWASP/Amass/requests"
	"github.com/fatih/color"
)

// Banner is the ASCII art logo used within help output.
const Banner = `

        .+++:.            :                             .+++.
      +W@@@@@@8        &+W@#               o8W8:      +W@@@@@@#.   oW@@@W#+
     &@#+   .o@##.    .@@@o@W.o@@o       :@@#&W8o    .@#:  .:oW+  .@#+++&#&
    +@&        &@&     #@8 +@W@&8@+     :@W.   +@8   +@:          .@8
    8@          @@     8@o  8@8  WW    .@W      W@+  .@W.          o@#:
    WW          &@o    &@:  o@+  o@+   #@.      8@o   +W@#+.        +W@8:
    #@          :@W    &@+  &@+   @8  :@o       o@o     oW@@W+        oW@8
    o@+          @@&   &@+  &@+   #@  &@.      .W@W       .+#@&         o@W.
     WW         +@W@8. &@+  :&    o@+ #@      :@W&@&         &@:  ..     :@o
     :@W:      o@# +Wo &@+        :W: +@W&o++o@W. &@&  8@#o+&@W.  #@:    o@+
      :W@@WWWW@@8       +              :&W@@@@&    &W  .o#@@W&.   :W@WWW@@&
        +o&&&&+.                                                    +oooo.

`

const (
	// Version is used to display the current version of Amass.
	Version = "v3.0.22"

	// Author is used to display the Amass Project Team.
	Author = "OWASP Amass Project - @owaspamass"
)

var (
	// Colors used to ease the reading of program output
	y      = color.New(color.FgHiYellow)
	g      = color.New(color.FgHiGreen)
	r      = color.New(color.FgHiRed)
	b      = color.New(color.FgHiBlue)
	fgR    = color.New(color.FgRed)
	fgY    = color.New(color.FgYellow)
	yellow = color.New(color.FgHiYellow).SprintFunc()
	green  = color.New(color.FgHiGreen).SprintFunc()
	blue   = color.New(color.FgHiBlue).SprintFunc()
)

// ASNSummaryData stores information related to discovered ASs and netblocks.
type ASNSummaryData struct {
	Name      string
	Netblocks map[string]int
}

// UpdateSummaryData updates the summary maps using the provided requests.Output data.
func UpdateSummaryData(output *requests.Output, tags map[string]int, asns map[int]*ASNSummaryData) {
	tags[output.Tag]++

	for _, addr := range output.Addresses {
		data, found := asns[addr.ASN]
		if !found {
			asns[addr.ASN] = &ASNSummaryData{
				Name:      addr.Description,
				Netblocks: make(map[string]int),
			}
			data = asns[addr.ASN]
		}
		// Increment how many IPs were in this netblock
		data.Netblocks[addr.Netblock.String()]++
	}
}

// PrintEnumerationSummary outputs the summary information utilized by the command-line tools.
func PrintEnumerationSummary(total int, tags map[string]int, asns map[int]*ASNSummaryData, demo bool) {
	pad := func(num int, chr string) {
		for i := 0; i < num; i++ {
			b.Fprint(color.Error, chr)
		}
	}

	fmt.Fprintln(color.Error)
	// Print the header information
	title := "OWASP Amass v"
	site := "https://github.com/OWASP/Amass"
	b.Fprint(color.Error, title+Version)
	num := 80 - (len(title) + len(Version) + len(site))
	pad(num, " ")
	b.Fprintf(color.Error, "%s\n", site)
	pad(8, "----------")
	fmt.Fprintf(color.Error, "\n%s%s", yellow(strconv.Itoa(total)), green(" names discovered - "))
	// Print the stats using tag information
	num, length := 1, len(tags)
	for k, v := range tags {
		fmt.Fprintf(color.Error, "%s: %s", green(k), yellow(strconv.Itoa(v)))
		if num < length {
			g.Fprint(color.Error, ", ")
		}
		num++
	}
	fmt.Fprintln(color.Error)

	if len(asns) == 0 {
		return
	}
	// Another line gets printed
	pad(8, "----------")
	fmt.Fprintln(color.Error)
	// Print the ASN and netblock information
	for asn, data := range asns {
		asnstr := strconv.Itoa(asn)
		datastr := data.Name

		if demo && asn > 0 {
			asnstr = censorString(asnstr, 0, len(asnstr))
			datastr = censorString(datastr, 0, len(datastr))
		}

		fmt.Fprintf(color.Error, "%s%s %s %s\n",
			blue("ASN: "), yellow(asnstr), green("-"), green(datastr))

		for cidr, ips := range data.Netblocks {
			countstr := strconv.Itoa(ips)
			cidrstr := cidr

			if demo {
				cidrstr = censorNetBlock(cidrstr)
			}

			countstr = fmt.Sprintf("\t%-4s", countstr)
			cidrstr = fmt.Sprintf("\t%-18s", cidrstr)

			fmt.Fprintf(color.Error, "%s%s %s\n",
				yellow(cidrstr), yellow(countstr), blue("Subdomain Name(s)"))
		}
	}
}

// PrintBanner outputs the Amass banner the same for all tools.
func PrintBanner() {
	y := color.New(color.FgHiYellow)
	r := color.New(color.FgHiRed)
	rightmost := 76
	version := "Version " + Version
	desc := "In-depth DNS Enumeration and Network Mapping"

	pad := func(num int) {
		for i := 0; i < num; i++ {
			fmt.Fprint(color.Error, " ")
		}
	}
	r.Fprintln(color.Error, Banner)
	pad(rightmost - len(version))
	y.Fprintln(color.Error, version)
	pad(rightmost - len(Author))
	y.Fprintln(color.Error, Author)
	pad(rightmost - len(desc))
	y.Fprintf(color.Error, "%s\n\n\n", desc)
}

func censorDomain(input string) string {
	return censorString(input, strings.Index(input, "."), len(input))
}

func censorIP(input string) string {
	return censorString(input, 0, strings.LastIndex(input, "."))
}

func censorNetBlock(input string) string {
	return censorString(input, 0, strings.Index(input, "/"))
}

func censorString(input string, start, end int) string {
	runes := []rune(input)
	for i := start; i < end; i++ {
		if runes[i] == '.' ||
			runes[i] == '/' ||
			runes[i] == '-' ||
			runes[i] == ' ' {
			continue
		}
		runes[i] = 'x'
	}
	return string(runes)
}

// OutputLineParts returns the parts of a line to be printed for a requests.Output.
func OutputLineParts(out *requests.Output, src, addrs, demo bool) (source, name, ips string) {
	if src {
		source = fmt.Sprintf("%-18s", "["+out.Source+"] ")
	}
	if addrs {
		for i, a := range out.Addresses {
			if i != 0 {
				ips += ","
			}
			if demo {
				ips += censorIP(a.Address.String())
			} else {
				ips += a.Address.String()
			}
		}
		if ips == "" {
			ips = "N/A"
		}
	}
	name = out.Name
	if demo {
		name = censorDomain(name)
	}
	return
}

// DesiredAddrTypes removes undesired address types from the AddressInfo slice.
func DesiredAddrTypes(addrs []requests.AddressInfo, ipv4, ipv6 bool) []requests.AddressInfo {
	if !ipv4 && !ipv6 {
		return addrs
	}

	var keep []requests.AddressInfo
	for _, addr := range addrs {
		if IsIPv4(addr.Address) && !ipv4 {
			continue
		} else if IsIPv6(addr.Address) && !ipv6 {
			continue
		}
		keep = append(keep, addr)
	}
	return keep
}
<|endoftext|>


<commit_before>package utils

import (
	"strings"
)

func parseURL(url string) (string, string) {
	arr := strings.Split(url, "://")

	if len(arr) == 1 {
		return "unix", arr[0]
	}

	proto := arr[0]
	if proto == "http" {
		proto = "tcp"
	}

	return proto, arr[1]
}

func SplitPort(portSetting string) (string, string) {
	arr := strings.Split(portSetting, "/")
	return arr[0], arr[1]
}
<commit_msg>Export parse method<commit_after>package utils

import (
	"strings"
)

func ParseURL(url string) (string, string) {
	arr := strings.Split(url, "://")

	if len(arr) == 1 {
		return "unix", arr[0]
	}

	proto := arr[0]
	if proto == "http" {
		proto = "tcp"
	}

	return proto, arr[1]
}

func SplitPort(portSetting string) (string, string) {
	arr := strings.Split(portSetting, "/")
	return arr[0], arr[1]
}
<|endoftext|>


<commit_before>package git_test

import (
	"io"
	"io/ioutil"
	"net"
	"os"
	"os/exec"
	"strings"

	"github.com/bargez/pktline"
	"github.com/lucas-clemente/git-cr/backends/fixture"
	"github.com/lucas-clemente/git-cr/git"
	. "github.com/onsi/ginkgo"
	. "github.com/onsi/gomega"
)

type pktlineDecoderWrapper struct {
	*pktline.Decoder
	io.Reader
}

func fillBackend(b *fixture.FixtureBackend) {
	b.CurrentRefs = git.Refs{
		"HEAD":              "f84b0d7375bcb16dd2742344e6af173aeebfcfd6",
		"refs/heads/master": "f84b0d7375bcb16dd2742344e6af173aeebfcfd6",
	}
	b.AddPackfile("", "f84b0d7375bcb16dd2742344e6af173aeebfcfd6", "UEFDSwAAAAIAAAADlwt4nJ3MQQrCMBBA0X1OMXtBJk7SdEBEcOslJmGCgaSFdnp/ET2By7f43zZVmAS5RC46a/Y55lBnDhE9kk6pVs4klL2ok8Ne6wbPo8gOj65DF1O49o/v5edzW2/gAxEnShzghBdEV9Yxmpn+V7u2NGvS4btxb5cEOSI0eJxLSiziAgADnQFArwF4nDM0MDAzMVFIy89nCBc7Fdl++mdt9lZPhX3L1t5T0W1/BgCtgg0ijmEEgEsIHYPJopDmNYTk3nR5stM=")
}

var _ = Describe("integration with git", func() {
	var (
		tempDir  string
		backend  *fixture.FixtureBackend
		server   *git.GitRequestHandler
		listener net.Listener
		port     string
	)

	BeforeEach(func() {
		var err error

		tempDir, err = ioutil.TempDir("", "io.clemente.git-cr.test")
		Ω(err).ShouldNot(HaveOccurred())

		backend = fixture.NewFixtureBackend()

		listener, err = net.Listen("tcp", "localhost:0")
		Ω(err).ShouldNot(HaveOccurred())
		port = strings.Split(listener.Addr().String(), ":")[1]

		go func() {
			defer GinkgoRecover()

			for {
				conn, err := listener.Accept()
				if err != nil {
					return
				}
				defer conn.Close()

				encoder := pktline.NewEncoder(conn)
				decoder := &pktlineDecoderWrapper{Decoder: pktline.NewDecoder(conn), Reader: conn}

				server = git.NewGitRequestHandler(encoder, decoder, backend)
				err = server.ServeRequest()
				Ω(err).ShouldNot(HaveOccurred())
				conn.Close()
			}
		}()

	})

	AfterEach(func() {
		listener.Close()
		os.RemoveAll(tempDir)
	})

	Context("cloning", func() {
		It("clones using git", func() {
			fillBackend(backend)
			err := exec.Command("git", "clone", "git://localhost:"+port+"/repo", tempDir).Run()
			Ω(err).ShouldNot(HaveOccurred())
			contents, err := ioutil.ReadFile(tempDir + "/foo")
			Ω(err).ShouldNot(HaveOccurred())
			Ω(contents).Should(Equal([]byte("bar\n")))
		})
	})

	Context("pulling", func() {
		BeforeEach(func() {
			fillBackend(backend)
			err := exec.Command("git", "clone", "git://localhost:"+port+"/repo", tempDir).Run()
			Ω(err).ShouldNot(HaveOccurred())
		})

		It("pulls updates", func() {
			backend.CurrentRefs["HEAD"] = "1a6d946069d483225913cf3b8ba8eae4c894c322"
			backend.CurrentRefs["refs/heads/master"] = "1a6d946069d483225913cf3b8ba8eae4c894c322"
			backend.AddPackfile("f84b0d7375bcb16dd2742344e6af173aeebfcfd6", "1a6d946069d483225913cf3b8ba8eae4c894c322", "UEFDSwAAAAIAAAADlgx4nJXLSwrCMBRG4XlWkbkgSe5NbgpS3Eoef1QwtrQRXL51CU7O4MA3NkDnmqgFT0CSBhIGI0RhmeBCCb5Mk2cbWa1pw2voFjmbKiQ+l2xDrU7YER8oNSuUgNxKq0Gl97gvmx7Yh778esUn9fWJc1n6rC0TG0suOn0yzhh13P4YA38Q1feb+gIlsDr0M3icS0qsAgACZQE+rwF4nDM0MDAzMVFIy89nsJ9qkZYUaGwfv1Tygdym9MuFp+ZUAACUGAuBskz7fFz81Do1iG8hcUrj/ncK63Q=")
			cmd := exec.Command("git", "pull")
			cmd.Dir = tempDir
			err := cmd.Run()
			Ω(err).ShouldNot(HaveOccurred())
			contents, err := ioutil.ReadFile(tempDir + "/foo")
			Ω(err).ShouldNot(HaveOccurred())
			Ω(contents).Should(Equal([]byte("baz")))
		})
	})

	Context("pushing changes", func() {
		BeforeEach(func() {
			fillBackend(backend)
			err := exec.Command("git", "clone", "git://localhost:"+port+"/repo", tempDir).Run()
			Ω(err).ShouldNot(HaveOccurred())
		})

		It("pushes updates", func() {
			// Modify file
			err := ioutil.WriteFile(tempDir+"/foo", []byte("baz"), 0644)
			Ω(err).ShouldNot(HaveOccurred())
			// Add
			cmd := exec.Command("git", "add", "foo")
			cmd.Dir = tempDir
			err = cmd.Run()
			Ω(err).ShouldNot(HaveOccurred())
			// Settings
			cmd = exec.Command("git", "config", "user.name", "test")
			cmd.Dir = tempDir
			err = cmd.Run()
			Ω(err).ShouldNot(HaveOccurred())
			cmd = exec.Command("git", "config", "user.email", "test@example.com")
			cmd.Dir = tempDir
			err = cmd.Run()
			Ω(err).ShouldNot(HaveOccurred())
			// Commit
			cmd = exec.Command("git", "commit", "--message=msg")
			cmd.Dir = tempDir
			cmd.Env = []string{
				"GIT_COMMITTER_DATE=Thu Jun 11 11:01:22 2015 +0200",
				"GIT_AUTHOR_DATE=Thu Jun 11 11:01:22 2015 +0200",
			}
			err = cmd.Run()
			Ω(err).ShouldNot(HaveOccurred())
			// Push
			cmd = exec.Command("git", "push")
			cmd.Dir = tempDir
			err = cmd.Run()
			Ω(err).ShouldNot(HaveOccurred())
			// Verify
			Ω(backend.PackfilesFromTo["f84b0d7375bcb16dd2742344e6af173aeebfcfd6"]["1a6d946069d483225913cf3b8ba8eae4c894c322"]).ShouldNot(HaveLen(0))
			Ω(backend.CurrentRefs).Should(HaveLen(2))
			Ω(backend.CurrentRefs["refs/heads/master"]).Should(Equal("1a6d946069d483225913cf3b8ba8eae4c894c322"))
		})

		It("pushes deletes", func() {
			// Push
			cmd := exec.Command("git", "push", "origin", ":master")
			cmd.Dir = tempDir
			err := cmd.Run()
			Ω(err).ShouldNot(HaveOccurred())
			// Verify
			Ω(backend.CurrentRefs).Should(HaveLen(1))
		})

		It("pushes new branches", func() {
			// Push
			cmd := exec.Command("git", "push", "origin", "master:foobar")
			cmd.Dir = tempDir
			err := cmd.Run()
			Ω(err).ShouldNot(HaveOccurred())
			// Verify
			Ω(backend.CurrentRefs).Should(HaveLen(3))
			Ω(backend.CurrentRefs["refs/heads/foobar"]).Should(Equal("f84b0d7375bcb16dd2742344e6af173aeebfcfd6"))
		})
	})

	Context("pushing into empty repos", func() {
		It("works", func() {
			cmd := exec.Command("git", "init")
			cmd.Dir = tempDir
			err := cmd.Run()
			Ω(err).ShouldNot(HaveOccurred())

			err = ioutil.WriteFile(tempDir+"/foo", []byte("foobar"), 0644)
			Ω(err).ShouldNot(HaveOccurred())

			cmd = exec.Command("git", "add", "foo")
			cmd.Dir = tempDir
			err = cmd.Run()
			Ω(err).ShouldNot(HaveOccurred())

			// Settings
			cmd = exec.Command("git", "config", "user.name", "test")
			cmd.Dir = tempDir
			err = cmd.Run()
			Ω(err).ShouldNot(HaveOccurred())
			cmd = exec.Command("git", "config", "user.email", "test@example.com")
			cmd.Dir = tempDir
			err = cmd.Run()
			Ω(err).ShouldNot(HaveOccurred())

			cmd = exec.Command("git", "commit", "-m", "test")
			cmd.Dir = tempDir
			err = cmd.Run()
			Ω(err).ShouldNot(HaveOccurred())

			cmd = exec.Command("git", "remote", "add", "origin", "git://localhost:"+port+"/repo")
			cmd.Dir = tempDir
			err = cmd.Run()
			Ω(err).ShouldNot(HaveOccurred())

			cmd = exec.Command("git", "push", "origin", "master")
			cmd.Dir = tempDir
			out, err := cmd.CombinedOutput()
			println(string(out))
			Ω(err).ShouldNot(HaveOccurred())

			// Clone into second dir
			tempDir2, err := ioutil.TempDir("", "io.clemente.git-cr.test")
			Ω(err).ShouldNot(HaveOccurred())
			defer os.RemoveAll(tempDir2)

			err = exec.Command("git", "clone", "git://localhost:"+port+"/repo", tempDir2).Run()
			Ω(err).ShouldNot(HaveOccurred())
			contents, err := ioutil.ReadFile(tempDir2 + "/foo")
			Ω(err).ShouldNot(HaveOccurred())
			Ω(contents).Should(Equal([]byte("foobar")))
		})
	})
})
<commit_msg>try to fix race on travis with mutex<commit_after>package git_test

import (
	"io"
	"io/ioutil"
	"net"
	"os"
	"os/exec"
	"strings"
	"sync"

	"github.com/bargez/pktline"
	"github.com/lucas-clemente/git-cr/backends/fixture"
	"github.com/lucas-clemente/git-cr/git"
	. "github.com/onsi/ginkgo"
	. "github.com/onsi/gomega"
)

type pktlineDecoderWrapper struct {
	*pktline.Decoder
	io.Reader
}

func fillBackend(b *fixture.FixtureBackend) {
	b.CurrentRefs = git.Refs{
		"HEAD":              "f84b0d7375bcb16dd2742344e6af173aeebfcfd6",
		"refs/heads/master": "f84b0d7375bcb16dd2742344e6af173aeebfcfd6",
	}
	b.AddPackfile("", "f84b0d7375bcb16dd2742344e6af173aeebfcfd6", "UEFDSwAAAAIAAAADlwt4nJ3MQQrCMBBA0X1OMXtBJk7SdEBEcOslJmGCgaSFdnp/ET2By7f43zZVmAS5RC46a/Y55lBnDhE9kk6pVs4klL2ok8Ne6wbPo8gOj65DF1O49o/v5edzW2/gAxEnShzghBdEV9Yxmpn+V7u2NGvS4btxb5cEOSI0eJxLSiziAgADnQFArwF4nDM0MDAzMVFIy89nCBc7Fdl++mdt9lZPhX3L1t5T0W1/BgCtgg0ijmEEgEsIHYPJopDmNYTk3nR5stM=")
}

var _ = Describe("integration with git", func() {
	var (
		tempDir  string
		backend  *fixture.FixtureBackend
		server   *git.GitRequestHandler
		listener net.Listener
		port     string
		mutex    sync.Mutex
	)

	BeforeEach(func() {
		var err error

		mutex = sync.Mutex{}

		tempDir, err = ioutil.TempDir("", "io.clemente.git-cr.test")
		Ω(err).ShouldNot(HaveOccurred())

		backend = fixture.NewFixtureBackend()

		listener, err = net.Listen("tcp", "localhost:0")
		Ω(err).ShouldNot(HaveOccurred())
		port = strings.Split(listener.Addr().String(), ":")[1]

		go func() {
			defer GinkgoRecover()

			for {
				conn, err := listener.Accept()
				if err != nil {
					return
				}
				defer conn.Close()

				mutex.Lock()

				encoder := pktline.NewEncoder(conn)
				decoder := &pktlineDecoderWrapper{Decoder: pktline.NewDecoder(conn), Reader: conn}

				server = git.NewGitRequestHandler(encoder, decoder, backend)
				err = server.ServeRequest()
				Ω(err).ShouldNot(HaveOccurred())
				conn.Close()

				mutex.Unlock()
			}
		}()

	})

	AfterEach(func() {
		listener.Close()
		mutex.Lock()
		mutex.Unlock()
		os.RemoveAll(tempDir)
	})

	Context("cloning", func() {
		It("clones using git", func() {
			fillBackend(backend)
			err := exec.Command("git", "clone", "git://localhost:"+port+"/repo", tempDir).Run()
			Ω(err).ShouldNot(HaveOccurred())
			contents, err := ioutil.ReadFile(tempDir + "/foo")
			Ω(err).ShouldNot(HaveOccurred())
			Ω(contents).Should(Equal([]byte("bar\n")))

			mutex.Lock()
			mutex.Unlock()
		})
	})

	Context("pulling", func() {
		BeforeEach(func() {
			fillBackend(backend)
			err := exec.Command("git", "clone", "git://localhost:"+port+"/repo", tempDir).Run()
			Ω(err).ShouldNot(HaveOccurred())
		})

		It("pulls updates", func() {
			backend.CurrentRefs["HEAD"] = "1a6d946069d483225913cf3b8ba8eae4c894c322"
			backend.CurrentRefs["refs/heads/master"] = "1a6d946069d483225913cf3b8ba8eae4c894c322"
			backend.AddPackfile("f84b0d7375bcb16dd2742344e6af173aeebfcfd6", "1a6d946069d483225913cf3b8ba8eae4c894c322", "UEFDSwAAAAIAAAADlgx4nJXLSwrCMBRG4XlWkbkgSe5NbgpS3Eoef1QwtrQRXL51CU7O4MA3NkDnmqgFT0CSBhIGI0RhmeBCCb5Mk2cbWa1pw2voFjmbKiQ+l2xDrU7YER8oNSuUgNxKq0Gl97gvmx7Yh778esUn9fWJc1n6rC0TG0suOn0yzhh13P4YA38Q1feb+gIlsDr0M3icS0qsAgACZQE+rwF4nDM0MDAzMVFIy89nsJ9qkZYUaGwfv1Tygdym9MuFp+ZUAACUGAuBskz7fFz81Do1iG8hcUrj/ncK63Q=")
			cmd := exec.Command("git", "pull")
			cmd.Dir = tempDir
			err := cmd.Run()
			Ω(err).ShouldNot(HaveOccurred())
			contents, err := ioutil.ReadFile(tempDir + "/foo")
			Ω(err).ShouldNot(HaveOccurred())
			Ω(contents).Should(Equal([]byte("baz")))
		})
	})

	Context("pushing changes", func() {
		BeforeEach(func() {
			fillBackend(backend)
			err := exec.Command("git", "clone", "git://localhost:"+port+"/repo", tempDir).Run()
			Ω(err).ShouldNot(HaveOccurred())
		})

		It("pushes updates", func() {
			// Modify file
			err := ioutil.WriteFile(tempDir+"/foo", []byte("baz"), 0644)
			Ω(err).ShouldNot(HaveOccurred())
			// Add
			cmd := exec.Command("git", "add", "foo")
			cmd.Dir = tempDir
			err = cmd.Run()
			Ω(err).ShouldNot(HaveOccurred())
			// Settings
			cmd = exec.Command("git", "config", "user.name", "test")
			cmd.Dir = tempDir
			err = cmd.Run()
			Ω(err).ShouldNot(HaveOccurred())
			cmd = exec.Command("git", "config", "user.email", "test@example.com")
			cmd.Dir = tempDir
			err = cmd.Run()
			Ω(err).ShouldNot(HaveOccurred())
			// Commit
			cmd = exec.Command("git", "commit", "--message=msg")
			cmd.Dir = tempDir
			cmd.Env = []string{
				"GIT_COMMITTER_DATE=Thu Jun 11 11:01:22 2015 +0200",
				"GIT_AUTHOR_DATE=Thu Jun 11 11:01:22 2015 +0200",
			}
			err = cmd.Run()
			Ω(err).ShouldNot(HaveOccurred())
			// Push
			cmd = exec.Command("git", "push")
			cmd.Dir = tempDir
			err = cmd.Run()
			Ω(err).ShouldNot(HaveOccurred())
			// Verify
			mutex.Lock()
			mutex.Unlock()
			Ω(backend.PackfilesFromTo["f84b0d7375bcb16dd2742344e6af173aeebfcfd6"]["1a6d946069d483225913cf3b8ba8eae4c894c322"]).ShouldNot(HaveLen(0))
			Ω(backend.CurrentRefs).Should(HaveLen(2))
			Ω(backend.CurrentRefs["refs/heads/master"]).Should(Equal("1a6d946069d483225913cf3b8ba8eae4c894c322"))
		})

		It("pushes deletes", func() {
			// Push
			cmd := exec.Command("git", "push", "origin", ":master")
			cmd.Dir = tempDir
			err := cmd.Run()
			Ω(err).ShouldNot(HaveOccurred())
			// Verify
			mutex.Lock()
			mutex.Unlock()
			Ω(backend.CurrentRefs).Should(HaveLen(1))
		})

		It("pushes new branches", func() {
			// Push
			cmd := exec.Command("git", "push", "origin", "master:foobar")
			cmd.Dir = tempDir
			err := cmd.Run()
			Ω(err).ShouldNot(HaveOccurred())
			// Verify
			mutex.Lock()
			mutex.Unlock()
			Ω(backend.CurrentRefs).Should(HaveLen(3))
			Ω(backend.CurrentRefs["refs/heads/foobar"]).Should(Equal("f84b0d7375bcb16dd2742344e6af173aeebfcfd6"))
		})
	})

	Context("pushing into empty repos", func() {
		It("works", func() {
			cmd := exec.Command("git", "init")
			cmd.Dir = tempDir
			err := cmd.Run()
			Ω(err).ShouldNot(HaveOccurred())

			err = ioutil.WriteFile(tempDir+"/foo", []byte("foobar"), 0644)
			Ω(err).ShouldNot(HaveOccurred())

			cmd = exec.Command("git", "add", "foo")
			cmd.Dir = tempDir
			err = cmd.Run()
			Ω(err).ShouldNot(HaveOccurred())

			// Settings
			cmd = exec.Command("git", "config", "user.name", "test")
			cmd.Dir = tempDir
			err = cmd.Run()
			Ω(err).ShouldNot(HaveOccurred())
			cmd = exec.Command("git", "config", "user.email", "test@example.com")
			cmd.Dir = tempDir
			err = cmd.Run()
			Ω(err).ShouldNot(HaveOccurred())

			cmd = exec.Command("git", "commit", "-m", "test")
			cmd.Dir = tempDir
			err = cmd.Run()
			Ω(err).ShouldNot(HaveOccurred())

			cmd = exec.Command("git", "remote", "add", "origin", "git://localhost:"+port+"/repo")
			cmd.Dir = tempDir
			err = cmd.Run()
			Ω(err).ShouldNot(HaveOccurred())

			cmd = exec.Command("git", "push", "origin", "master")
			cmd.Dir = tempDir
			err = cmd.Run()
			Ω(err).ShouldNot(HaveOccurred())

			mutex.Lock()
			mutex.Unlock()

			// Clone into second dir
			tempDir2, err := ioutil.TempDir("", "io.clemente.git-cr.test")
			Ω(err).ShouldNot(HaveOccurred())
			defer os.RemoveAll(tempDir2)

			err = exec.Command("git", "clone", "git://localhost:"+port+"/repo", tempDir2).Run()
			Ω(err).ShouldNot(HaveOccurred())
			contents, err := ioutil.ReadFile(tempDir2 + "/foo")
			Ω(err).ShouldNot(HaveOccurred())
			Ω(contents).Should(Equal([]byte("foobar")))
		})
	})
})
<|endoftext|>