<commit_before>package sql

import (
	"bytes"
	"io"
	"strings"
	"testing"
)

func Test_stackEmpty(t *testing.T) {
	s := newStack()
	if !s.empty() {
		t.Fatal("new stack is not empty")
	}

	if s.peek() != rune(0) {
		t.Fatal("peek of empty stack does not return correct value")
	}
}

func Test_stackSingle(t *testing.T) {
	s := newStack()
	s.push('x')
	if s.empty() {
		t.Fatal("non-empty stack marked as empty")
	}

	if s.peek() != 'x' {
		t.Fatal("peek of stack with single entry does not return correct value")
	}

	if s.pop() != 'x' {
		t.Fatal("pop of stack with single entry does not return correct value")
	}

	if !s.empty() {
		t.Fatal("popped stack is not empty")
	}
}

func Test_stackMulti(t *testing.T) {
	s := newStack()
	s.push('x')
	s.push('y')
	s.push('z')

	if s.pop() != 'z' {
		t.Fatal("pop of 1st multi stack does not return correct value")
	}
	if s.pop() != 'y' {
		t.Fatal("pop of 2nd multi stack does not return correct value")
	}
	if s.pop() != 'x' {
		t.Fatal("pop of 3rd multi stack does not return correct value")
	}

	if !s.empty() {
		t.Fatal("popped mstack is not empty")
	}
}

func Test_ScannerNew(t *testing.T) {
	s := NewScanner(nil)
	if s == nil {
		t.Fatalf("failed to create basic Scanner")
	}
}

func Test_ScannerEmpty(t *testing.T) {
	r := bytes.NewBufferString("")
	s := NewScanner(r)

	_, err := s.Scan()
	if err != io.EOF {
		t.Fatal("Scan of empty string did not return EOF")
	}
}

func Test_ScannerSemi(t *testing.T) {
	r := bytes.NewBufferString(";")
	s := NewScanner(r)

	l, err := s.Scan()
	if err != nil {
		t.Fatal("Scan of single semicolon failed")
	}
	if l != ";" {
		t.Fatal("Scan of single semicolon returned incorrect value")
	}
	_, err = s.Scan()
	if err != io.EOF {
		t.Fatal("Scan of empty string after semicolon did not return EOF")
	}
}

func Test_ScannerSingleStatement(t *testing.T) {
	r := bytes.NewBufferString("SELECT * FROM foo;")
	s := NewScanner(r)

	l, err := s.Scan()
	if err != nil {
		t.Fatal("Scan of single statement failed")
	}
	if l != "SELECT * FROM foo;" {
		t.Fatal("Scan of single statement returned incorrect value")
	}
	_, err = s.Scan()
	if err != io.EOF {
		t.Fatal("Scan of empty string after statement did not return EOF")
	}
}

func Test_ScannerSingleStatementQuotes(t *testing.T) {
	r := bytes.NewBufferString(`SELECT * FROM "foo";`)
	s := NewScanner(r)

	l, err := s.Scan()
	if err != nil {
		t.Fatal("Scan of single statement failed")
	}
	if l != `SELECT * FROM "foo";` {
		t.Fatal("Scan of single statement returned incorrect value")
	}
	_, err = s.Scan()
	if err != io.EOF {
		t.Fatal("Scan of empty string after statement did not return EOF")
	}
}

func Test_ScannerSingleStatementQuotesEmbedded(t *testing.T) {
	r := bytes.NewBufferString(`SELECT * FROM ";SELECT * FROM '"foo"'";`)
	s := NewScanner(r)

	l, err := s.Scan()
	if err != nil {
		t.Fatal("Scan of single statement failed")
	}
	if l != `SELECT * FROM ";SELECT * FROM '"foo"'";` {
		t.Fatal("Scan of single statement returned incorrect value")
	}
	_, err = s.Scan()
	if err != io.EOF {
		t.Fatal("Scan of empty string after statement did not return EOF")
	}
}

func Test_ScannerMultiStatement(t *testing.T) {
	e := []string{`SELECT * FROM foo;`, `SELECT * FROM bar;`}
	r := bytes.NewBufferString(strings.Join(e, ""))
	s := NewScanner(r)

	for i := range e {
		l, err := s.Scan()
		if err != nil {
			t.Fatal("Scan of multi statement failed")
		}

		if l != e[i] {
			t.Fatalf("Scan of multi statement returned incorrect value, exp %s, got %s", e[i], l)
		}
	}
}

func Test_ScannerMultiStatementQuotesEmbedded(t *testing.T) {
	e := []string{`SELECT * FROM "foo;barx";`, `SELECT * FROM bar;`}
	r := bytes.NewBufferString(strings.Join(e, ""))
	s := NewScanner(r)

	for i := range e {
		l, err := s.Scan()
		if err != nil {
			t.Fatal("Scan of multi statement failed")
		}

		if l != e[i] {
			t.Fatalf("Scan of multi statement returned incorrect value, exp %s, got %s", e[i], l)
		}
	}
}

// XX I am missing this case: '"' ????
<commit_msg>Add test of multiline parsing<commit_after>package sql

import (
	"bytes"
	"io"
	"strings"
	"testing"
)

func Test_stackEmpty(t *testing.T) {
	s := newStack()
	if !s.empty() {
		t.Fatal("new stack is not empty")
	}

	if s.peek() != rune(0) {
		t.Fatal("peek of empty stack does not return correct value")
	}
}

func Test_stackSingle(t *testing.T) {
	s := newStack()
	s.push('x')
	if s.empty() {
		t.Fatal("non-empty stack marked as empty")
	}

	if s.peek() != 'x' {
		t.Fatal("peek of stack with single entry does not return correct value")
	}

	if s.pop() != 'x' {
		t.Fatal("pop of stack with single entry does not return correct value")
	}

	if !s.empty() {
		t.Fatal("popped stack is not empty")
	}
}

func Test_stackMulti(t *testing.T) {
	s := newStack()
	s.push('x')
	s.push('y')
	s.push('z')

	if s.pop() != 'z' {
		t.Fatal("pop of 1st multi stack does not return correct value")
	}
	if s.pop() != 'y' {
		t.Fatal("pop of 2nd multi stack does not return correct value")
	}
	if s.pop() != 'x' {
		t.Fatal("pop of 3rd multi stack does not return correct value")
	}

	if !s.empty() {
		t.Fatal("popped mstack is not empty")
	}
}

func Test_ScannerNew(t *testing.T) {
	s := NewScanner(nil)
	if s == nil {
		t.Fatalf("failed to create basic Scanner")
	}
}

func Test_ScannerEmpty(t *testing.T) {
	r := bytes.NewBufferString("")
	s := NewScanner(r)

	_, err := s.Scan()
	if err != io.EOF {
		t.Fatal("Scan of empty string did not return EOF")
	}
}

func Test_ScannerSemi(t *testing.T) {
	r := bytes.NewBufferString(";")
	s := NewScanner(r)

	l, err := s.Scan()
	if err != nil {
		t.Fatal("Scan of single semicolon failed")
	}
	if l != ";" {
		t.Fatal("Scan of single semicolon returned incorrect value")
	}
	_, err = s.Scan()
	if err != io.EOF {
		t.Fatal("Scan of empty string after semicolon did not return EOF")
	}
}

func Test_ScannerSingleStatement(t *testing.T) {
	r := bytes.NewBufferString("SELECT * FROM foo;")
	s := NewScanner(r)

	l, err := s.Scan()
	if err != nil {
		t.Fatal("Scan of single statement failed")
	}
	if l != "SELECT * FROM foo;" {
		t.Fatal("Scan of single statement returned incorrect value")
	}
	_, err = s.Scan()
	if err != io.EOF {
		t.Fatal("Scan of empty string after statement did not return EOF")
	}
}

func Test_ScannerSingleStatementQuotes(t *testing.T) {
	r := bytes.NewBufferString(`SELECT * FROM "foo";`)
	s := NewScanner(r)

	l, err := s.Scan()
	if err != nil {
		t.Fatal("Scan of single statement failed")
	}
	if l != `SELECT * FROM "foo";` {
		t.Fatal("Scan of single statement returned incorrect value")
	}
	_, err = s.Scan()
	if err != io.EOF {
		t.Fatal("Scan of empty string after statement did not return EOF")
	}
}

func Test_ScannerSingleStatementQuotesEmbedded(t *testing.T) {
	r := bytes.NewBufferString(`SELECT * FROM ";SELECT * FROM '"foo"'";`)
	s := NewScanner(r)

	l, err := s.Scan()
	if err != nil {
		t.Fatal("Scan of single statement failed")
	}
	if l != `SELECT * FROM ";SELECT * FROM '"foo"'";` {
		t.Fatal("Scan of single statement returned incorrect value")
	}
	_, err = s.Scan()
	if err != io.EOF {
		t.Fatal("Scan of empty string after statement did not return EOF")
	}
}

func Test_ScannerMultiStatement(t *testing.T) {
	e := []string{`SELECT * FROM foo;`, `SELECT * FROM bar;`}
	r := bytes.NewBufferString(strings.Join(e, ""))
	s := NewScanner(r)

	for i := range e {
		l, err := s.Scan()
		if err != nil {
			t.Fatal("Scan of multi statement failed")
		}

		if l != e[i] {
			t.Fatalf("Scan of multi statement returned incorrect value, exp %s, got %s", e[i], l)
		}
	}
}

func Test_ScannerMultiStatementQuotesEmbedded(t *testing.T) {
	e := []string{`SELECT * FROM "foo;barx";`, `SELECT * FROM bar;`}
	r := bytes.NewBufferString(strings.Join(e, ""))
	s := NewScanner(r)

	for i := range e {
		l, err := s.Scan()
		if err != nil {
			t.Fatal("Scan of multi statement failed")
		}

		if l != e[i] {
			t.Fatalf("Scan of multi statement returned incorrect value, exp %s, got %s", e[i], l)
		}
	}
}

// XX I am missing this case: '"' ????

func Test_ScannerMultiLine(t *testing.T) {
	stmt := `CREATE TABLE [Customer]
(
    [CustomerId] INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,
    [FirstName] NVARCHAR(40)  NOT NULL,
    [LastName] NVARCHAR(20)  NOT NULL,
    [Company] NVARCHAR(80),
    [Address] NVARCHAR(70),
    [City] NVARCHAR(40),
    [State] NVARCHAR(40),
    [Country] NVARCHAR(40),
    [PostalCode] NVARCHAR(10),
    [Phone] NVARCHAR(24),
    [Fax] NVARCHAR(24),
    [Email] NVARCHAR(60)  NOT NULL,
    [SupportRepId] INTEGER,
    FOREIGN KEY ([SupportRepId]) REFERENCES [Employee] ([EmployeeId])
                ON DELETE NO ACTION ON UPDATE NO ACTION
);`
	r := bytes.NewBufferString(stmt)
	s := NewScanner(r)

	l, err := s.Scan()
	if err != nil {
		t.Fatal("Scan of multiline statement failed")
	}
	if l != stmt {
		t.Fatal("Scan of multiline statement returned incorrect value")
	}
	_, err = s.Scan()
	if err != io.EOF {
		t.Fatal("Scan of empty string after statement did not return EOF")
	}
}
<|endoftext|>


<commit_before>package server

import (
    "github.com/gorilla/mux"
    "net/http"
)

// Setup the routes for the server and any static assets
func SetupRoutes() {
    router := mux.NewRouter()

    // Define error'd route handler
    router.NotFoundHandler = http.HandlerFunc(Render404)

    // Define various application routes here
    router.HandleFunc("/", RenderIndex).Methods("GET")

    // Serve any app related static content
    http.Handle("/static/", http.StripPrefix("/static/", http.FileServer(http.Dir("go-meeting/static"))))

    // Use the above router for all routes
    http.Handle("/", router)
}

// Render 404 page
func Render404(response http.ResponseWriter, request *http.Request) {
    response.Write([]byte("Hmm looks like we 404'd trying to find: " + request.URL.Path))
}

// Render Home page
func RenderIndex(response http.ResponseWriter, request *http.Request) {
    response.Write([]byte("Hello world!"))
}

<commit_msg>Wired up server and external client resources<commit_after>package server

import (
    "github.com/gorilla/mux"
    "net/http"
    "fmt"
)

// Setup the routes for the server and any static assets
func SetupRoutes() {
    router := mux.NewRouter()

    // Define error'd route handler
    router.NotFoundHandler = http.HandlerFunc(Render404)

    // Define various application routes here
    router.HandleFunc("/api/add/{a:[0-9]+}/{b:[0-9]+}", AddHandler).Methods("GET")

    // Serve any app related static content
    router.PathPrefix("/").Handler(http.FileServer(http.Dir("server/static")))

    // Use the above router for all routes
    http.Handle("/", router)
}

// Render 404 page
func Render404(response http.ResponseWriter, request *http.Request) {
    response.Write([]byte("Hmm looks like we 404'd trying to find: " + request.URL.Path))
}

// Add Handler (POC entrypoint - just adds two numbers)
func AddHandler(response http.ResponseWriter, request *http.Request) {
    fmt.Printf("Add handler invoked: %v\n", mux.Vars(request))
    vars := mux.Vars(request)
    a, b := vars["a"], vars["b"]
    response.Write([]byte(a + b))
}

<|endoftext|>


<commit_before>package main

import (
	"bufio"
	"github.com/gophergala2016/3wordgame/validation"
	"net"
)

// Client struct
type Client struct {
	incoming chan string
	outgoing chan string
	reader   *bufio.Reader
	writer   *bufio.Writer
}

// Read line by line into the client.incoming
func (client *Client) Read() {
	for {
		line, _ := client.reader.ReadString('\n')
		client.incoming <- line
	}
}

// Write client outgoing data to the client writer
func (client *Client) Write() {
	for data := range client.outgoing {
		client.writer.WriteString(data)
		client.writer.Flush()
	}
}

// Listen for reads and writes on the client
func (client *Client) Listen() {
	go client.Read()
	go client.Write()
}

// NewClient returns new instance of client.
func NewClient(connection net.Conn) *Client {
	writer := bufio.NewWriter(connection)
	reader := bufio.NewReader(connection)

	client := &Client{
		incoming: make(chan string),
		outgoing: make(chan string),
		reader:   reader,
		writer:   writer,
	}

	client.Listen()

	return client
}

// ChatRoom struct
type ChatRoom struct {
	clients  []*Client
	joins    chan net.Conn
	incoming chan string
	outgoing chan string
}

// Broadcast data to all connected chatRoom.clients
func (chatRoom *ChatRoom) Broadcast(data string) {
	for _, client := range chatRoom.clients {
		client.outgoing <- data
	}
}

// Join attaches a new client to the chatRoom clients
func (chatRoom *ChatRoom) Join(connection net.Conn) {
	client := NewClient(connection)
	chatRoom.clients = append(chatRoom.clients, client)
	go func() {
		for {
			chatRoom.incoming <- <-client.incoming
		}
	}()
}

// Listen to all incoming messages for the chatRoom
func (chatRoom *ChatRoom) Listen() {
	go func() {
		for {
			select {
			case data := <-chatRoom.incoming:
				msg, err := validation.ValidateMsg(data)
				if err == nil {
					chatRoom.Broadcast(msg)
				}
			case conn := <-chatRoom.joins:
				chatRoom.Join(conn)
			}
		}
	}()
}

// NewChatRoom factories a ChatRoom instance
func NewChatRoom() *ChatRoom {
	chatRoom := &ChatRoom{
		clients:  make([]*Client, 0),
		joins:    make(chan net.Conn),
		incoming: make(chan string),
		outgoing: make(chan string),
	}

	chatRoom.Listen()

	return chatRoom
}

func main() {
	chatRoom := NewChatRoom()

	listener, _ := net.Listen("tcp", ":6666")

	for {
		conn, _ := listener.Accept()
		chatRoom.joins <- conn
	}
}
<commit_msg>Make the server host:port configurable.<commit_after>package main

import (
	"bufio"
	"flag"
	"fmt"
	"github.com/gophergala2016/3wordgame/validation"
	"net"
)

// Client struct
type Client struct {
	incoming chan string
	outgoing chan string
	reader   *bufio.Reader
	writer   *bufio.Writer
}

// Read line by line into the client.incoming
func (client *Client) Read() {
	for {
		line, _ := client.reader.ReadString('\n')
		client.incoming <- line
	}
}

// Write client outgoing data to the client writer
func (client *Client) Write() {
	for data := range client.outgoing {
		client.writer.WriteString(data)
		client.writer.Flush()
	}
}

// Listen for reads and writes on the client
func (client *Client) Listen() {
	go client.Read()
	go client.Write()
}

// NewClient returns new instance of client.
func NewClient(connection net.Conn) *Client {
	writer := bufio.NewWriter(connection)
	reader := bufio.NewReader(connection)

	client := &Client{
		incoming: make(chan string),
		outgoing: make(chan string),
		reader:   reader,
		writer:   writer,
	}

	client.Listen()

	return client
}

// ChatRoom struct
type ChatRoom struct {
	clients  []*Client
	joins    chan net.Conn
	incoming chan string
	outgoing chan string
}

// Broadcast data to all connected chatRoom.clients
func (chatRoom *ChatRoom) Broadcast(data string) {
	for _, client := range chatRoom.clients {
		client.outgoing <- data
	}
}

// Join attaches a new client to the chatRoom clients
func (chatRoom *ChatRoom) Join(connection net.Conn) {
	client := NewClient(connection)
	chatRoom.clients = append(chatRoom.clients, client)
	go func() {
		for {
			chatRoom.incoming <- <-client.incoming
		}
	}()
}

// Listen to all incoming messages for the chatRoom
func (chatRoom *ChatRoom) Listen() {
	go func() {
		for {
			select {
			case data := <-chatRoom.incoming:
				msg, err := validation.ValidateMsg(data)
				if err == nil {
					chatRoom.Broadcast(msg)
				}
			case conn := <-chatRoom.joins:
				chatRoom.Join(conn)
			}
		}
	}()
}

// NewChatRoom factories a ChatRoom instance
func NewChatRoom() *ChatRoom {
	chatRoom := &ChatRoom{
		clients:  make([]*Client, 0),
		joins:    make(chan net.Conn),
		incoming: make(chan string),
		outgoing: make(chan string),
	}

	chatRoom.Listen()

	return chatRoom
}

func main() {
	var server string
	var port int

	flag.StringVar(&server, "server", "127.0.0.1", "Server host")
	flag.IntVar(&port, "port", 6666, "Server port")
	flag.Parse()

	listener, _ := net.Listen("tcp", fmt.Sprintf("%s:%d", server, port))

	chatRoom := NewChatRoom()

	for {
		conn, _ := listener.Accept()
		chatRoom.joins <- conn
	}
}
<|endoftext|>


<commit_before>package server

import (
	"crypto/sha256"
	"errors"
	"github.com/andres-erbsen/chatterbox/proto"
	"github.com/andres-erbsen/chatterbox/transport"
	"github.com/syndtr/goleveldb/leveldb"
	"github.com/syndtr/goleveldb/leveldb/opt"
	"github.com/syndtr/goleveldb/leveldb/util"
	"net"
	"sync"
)

const MAX_MESSAGE_SIZE = 16 * 1024

var WO_sync = &opt.WriteOptions{Sync: true}

type Server struct {
	database *leveldb.DB
	shutdown chan struct{}
	listener net.Listener
	notifier Notifier
	wg       sync.WaitGroup
	pk       *[32]byte
	sk       *[32]byte
	keyMutex sync.Mutex
}

func StartServer(db *leveldb.DB, shutdown chan struct{}, pk *[32]byte, sk *[32]byte, listenAddr string) (*Server, error) {
	listener, err := net.Listen("tcp", listenAddr)
	if err != nil {
		return nil, err
	}
	server := &Server{
		database: db,
		shutdown: shutdown,
		listener: listener,
		notifier: Notifier{waiters: make(map[[32]byte][]chan []byte)},
		pk:       pk,
		sk:       sk,
	}
	server.wg.Add(1)
	go server.RunServer()
	return server, nil
}

func (server *Server) StopServer() {
	close(server.shutdown)
	server.listener.Close()
	server.wg.Wait()
}

func (server *Server) RunServer() error {
	defer server.wg.Done()
	for {
		select {
		case <-server.shutdown:
			return nil
		default: //
		}
		conn, err := server.listener.Accept()
		if err != nil {
			return err
		}

		server.wg.Add(1)
		go server.handleClient(conn)
	}
	return nil
}

func (server *Server) handleClientShutdown(connection *transport.Conn) {
	defer server.wg.Done()
	<-server.shutdown
	(*connection).Close()
	return
}

// readClientCommands reads client commands from a connnection and sends them
// to channel commands. On error, the error is sent to channel disconnect and
// both channels (but not the connection are closed).
// commands is a TWO-WAY channel! the reader must reach return each cmd after
// interpreting it, readClientCommands will call cmd.Reset() and reuse it.
func (server *Server) readClientCommands(conn *transport.Conn,
	commands chan *proto.ClientToServer, disconnected chan error) {
	defer server.wg.Done()
	defer close(commands)
	defer close(disconnected)
	inBuf := make([]byte, MAX_MESSAGE_SIZE)
	cmd := new(proto.ClientToServer)
	for {
		num, err := conn.ReadFrame(inBuf)
		if err != nil {
			disconnected <- err
			return
		}
		if err := cmd.Unmarshal(inBuf[:num]); err != nil {
			disconnected <- err
			return
		}
		commands <- cmd
		cmd = <-commands
		cmd.Reset()
	}
}

// readClientNotifications is a for loop of blocking reads on notificationsIn
// and non-blocking sends on notificationsOut. If the input channel is closed
// or a send would block, the output channel is closed.
func (server *Server) readClientNotifications(notificationsIn chan []byte, notificationsOut chan []byte) {
	var hasOverflowed bool
	defer server.wg.Done()
	for n := range notificationsIn {
		if !hasOverflowed {
			select {
			case notificationsOut <- n:
			default:
				hasOverflowed = true
				close(notificationsOut)
			}
		}
	}
}

func toProtoByte32List(list *[][32]byte) *[]proto.Byte32 {
	newList := make([]proto.Byte32, 0)
	for _, element := range *list {
		newList = append(newList, (proto.Byte32)(element))
	}
	return &newList
}

func to32ByteList(list *[]proto.Byte32) *[][32]byte {
	newList := make([][32]byte, 0, 0)
	for _, element := range *list {
		newList = append(newList, ([32]byte)(element))
	}
	return &newList
}

//for each client, listen for commands
func (server *Server) handleClient(connection net.Conn) error {
	defer server.wg.Done()
	newConnection, uid, err := transport.Handshake(connection, server.pk, server.sk, nil, MAX_MESSAGE_SIZE) //TODO: Decide on this bound
	if err != nil {
		return err
	}

	commands := make(chan *proto.ClientToServer)
	disconnected := make(chan error)
	server.wg.Add(2)
	go server.readClientCommands(newConnection, commands, disconnected)
	go server.handleClientShutdown(newConnection)

	var notificationsUnbuffered, notifications chan []byte
	var notifyEnabled bool
	defer func() {
		if notifyEnabled {
			server.notifier.StopWaitingSync(uid, notificationsUnbuffered)
		}
	}()

	outBuf := make([]byte, MAX_MESSAGE_SIZE)
	response := new(proto.ServerToClient)
	for {
		select {
		case err := <-disconnected:
			return err
		case cmd := <-commands:
			if cmd.CreateAccount != nil && *cmd.CreateAccount {
				err = server.newUser(uid)
			} else if cmd.DeliverEnvelope != nil {
				err = server.newMessage((*[32]byte)(cmd.DeliverEnvelope.User),
					cmd.DeliverEnvelope.Envelope)
			} else if cmd.ListMessages != nil && *cmd.ListMessages {
				var messageList *[][32]byte
				messageList, err = server.getMessageList(uid)
				response.MessageList = *toProtoByte32List(messageList)
			} else if cmd.DownloadEnvelope != nil {
				response.Envelope, err = server.getEnvelope(uid, (*[32]byte)(cmd.DownloadEnvelope))
			} else if cmd.DeleteMessages != nil {
				messageList := cmd.DeleteMessages
				err = server.deleteMessages(uid, to32ByteList(&messageList))
			} else if cmd.UploadSignedKeys != nil {
				err = server.newKeys(uid, cmd.UploadSignedKeys)
			} else if cmd.GetSignedKey != nil {
				response.SignedKey, err = server.getKey((*[32]byte)(cmd.GetSignedKey))
			} else if cmd.GetNumKeys != nil {
				response.NumKeys, err = server.getNumKeys(uid)
			} else if cmd.ReceiveEnvelopes != nil {
				if *cmd.ReceiveEnvelopes && !notifyEnabled {
					notifyEnabled = true
					notificationsUnbuffered = server.notifier.StartWaiting(uid)
					notifications = make(chan []byte)
					server.wg.Add(1)
					go server.readClientNotifications(notificationsUnbuffered, notifications)
				} else if !*cmd.ReceiveEnvelopes && notifyEnabled {
					server.notifier.StopWaitingSync(uid, notificationsUnbuffered)
					notifyEnabled = false
				}
			}
			if err != nil {
				response.Status = proto.ServerToClient_PARSE_ERROR.Enum()
			} else {
				response.Status = proto.ServerToClient_OK.Enum()
			}
			if err = server.writeProtobuf(newConnection, outBuf, response); err != nil {
				return err
			}
			commands <- cmd
		case notification, ok := <-notifications:
			if !notifyEnabled {
				continue
			}
			if !ok {
				notifyEnabled = false
				go server.notifier.StopWaitingSync(uid, notificationsUnbuffered)
				continue
			}
			response.Envelope = notification
			response.Status = proto.ServerToClient_OK.Enum()
			if err = server.writeProtobuf(newConnection, outBuf, response); err != nil {
				return err
			}
		}
		response.Reset()
	}
	return nil
}

func (server *Server) getNumKeys(user *[32]byte) (*int64, error) { //TODO: Batch read of some kind?
	prefix := append([]byte{'k'}, (*user)[:]...)
	server.keyMutex.Lock()
	snapshot, err := server.database.GetSnapshot()
	if err != nil {
		server.keyMutex.Unlock()
		return nil, err
	}
	server.keyMutex.Unlock()
	defer snapshot.Release()
	keyRange := util.BytesPrefix(prefix)
	iter := snapshot.NewIterator(keyRange, nil)
	defer iter.Release()
	var numRecords int64
	for iter.Next() {
		numRecords = numRecords + 1
	}
	return &numRecords, iter.Error()
}

func (server *Server) deleteKey(uid *[32]byte, key []byte) error {
	keyHash := sha256.Sum256((key))
	dbKey := append(append([]byte{'k'}, uid[:]...), keyHash[:]...)
	return server.database.Delete(dbKey, WO_sync)
}

func (server *Server) getKey(user *[32]byte) ([]byte, error) {
	prefix := append([]byte{'k'}, (*user)[:]...)
	server.keyMutex.Lock()
	defer server.keyMutex.Unlock()
	snapshot, err := server.database.GetSnapshot()
	if err != nil {
		return nil, err
	}
	defer snapshot.Release()
	keyRange := util.BytesPrefix(prefix)
	iter := snapshot.NewIterator(keyRange, nil)
	defer iter.Release()
	if iter.First() == false {
		return nil, errors.New("No keys left in database")
	}
	err = iter.Error()
	server.deleteKey(user, iter.Value())
	return append([]byte{}, iter.Value()...), err
}

func (server *Server) newKeys(uid *[32]byte, keyList [][]byte) error {
	batch := new(leveldb.Batch)
	for _, key := range keyList {
		keyHash := sha256.Sum256(key)
		dbKey := append(append([]byte{'k'}, uid[:]...), keyHash[:]...)
		batch.Put(dbKey, key)
	}
	return server.database.Write(batch, WO_sync)
}
func (server *Server) deleteMessages(uid *[32]byte, messageList *[][32]byte) error {
	batch := new(leveldb.Batch)
	for _, messageHash := range *messageList {
		key := append(append([]byte{'m'}, uid[:]...), messageHash[:]...)
		batch.Delete(key)
	}
	return server.database.Write(batch, WO_sync)
}

func (server *Server) getEnvelope(uid *[32]byte, messageHash *[32]byte) ([]byte, error) {
	key := append(append([]byte{'m'}, uid[:]...), (messageHash)[:]...)
	envelope, err := server.database.Get(key, nil)
	return envelope, err
}

func (server *Server) writeProtobuf(conn *transport.Conn, outBuf []byte, message *proto.ServerToClient) error {
	size, err := message.MarshalTo(outBuf)
	if err != nil {
		return err
	}
	conn.WriteFrame(outBuf[:size])
	return nil
}

func (server *Server) getMessageList(user *[32]byte) (*[][32]byte, error) {
	messages := make([][32]byte, 0)
	prefix := append([]byte{'m'}, (*user)[:]...)
	messageRange := util.BytesPrefix(prefix)
	snapshot, err := server.database.GetSnapshot()
	if err != nil {
		return nil, err
	}
	defer snapshot.Release()
	iter := snapshot.NewIterator(messageRange, nil)
	defer iter.Release()
	for iter.Next() {
		var message [32]byte
		copy(message[:], iter.Key()[len(prefix):len(prefix)+32])
		messages = append(messages, message)
	}
	err = iter.Error()
	return &messages, err
}

func (server *Server) newMessage(uid *[32]byte, envelope []byte) error {
	// TODO: check that user exists
	messageHash := sha256.Sum256(envelope)
	key := append(append([]byte{'m'}, uid[:]...), messageHash[:]...)
	err := server.database.Put(key, (envelope)[:], WO_sync)
	if err != nil {
		return err
	}
	server.notifier.Notify(uid, append([]byte{}, envelope...))
	return nil
}

func (server *Server) newUser(uid *[32]byte) error {
	return server.database.Put(append([]byte{'u'}, uid[:]...), []byte(""), WO_sync)
}
<commit_msg>remove redundant locking from server<commit_after>package server

import (
	"crypto/sha256"
	"errors"
	"github.com/andres-erbsen/chatterbox/proto"
	"github.com/andres-erbsen/chatterbox/transport"
	"github.com/syndtr/goleveldb/leveldb"
	"github.com/syndtr/goleveldb/leveldb/opt"
	"github.com/syndtr/goleveldb/leveldb/util"
	"net"
	"sync"
)

const MAX_MESSAGE_SIZE = 16 * 1024

var WO_sync = &opt.WriteOptions{Sync: true}

type Server struct {
	database *leveldb.DB
	shutdown chan struct{}
	listener net.Listener
	notifier Notifier
	wg       sync.WaitGroup
	pk       *[32]byte
	sk       *[32]byte
	keyMutex sync.Mutex
}

func StartServer(db *leveldb.DB, shutdown chan struct{}, pk *[32]byte, sk *[32]byte, listenAddr string) (*Server, error) {
	listener, err := net.Listen("tcp", listenAddr)
	if err != nil {
		return nil, err
	}
	server := &Server{
		database: db,
		shutdown: shutdown,
		listener: listener,
		notifier: Notifier{waiters: make(map[[32]byte][]chan []byte)},
		pk:       pk,
		sk:       sk,
	}
	server.wg.Add(1)
	go server.RunServer()
	return server, nil
}

func (server *Server) StopServer() {
	close(server.shutdown)
	server.listener.Close()
	server.wg.Wait()
}

func (server *Server) RunServer() error {
	defer server.wg.Done()
	for {
		select {
		case <-server.shutdown:
			return nil
		default: //
		}
		conn, err := server.listener.Accept()
		if err != nil {
			return err
		}

		server.wg.Add(1)
		go server.handleClient(conn)
	}
	return nil
}

func (server *Server) handleClientShutdown(connection *transport.Conn) {
	defer server.wg.Done()
	<-server.shutdown
	(*connection).Close()
	return
}

// readClientCommands reads client commands from a connnection and sends them
// to channel commands. On error, the error is sent to channel disconnect and
// both channels (but not the connection are closed).
// commands is a TWO-WAY channel! the reader must reach return each cmd after
// interpreting it, readClientCommands will call cmd.Reset() and reuse it.
func (server *Server) readClientCommands(conn *transport.Conn,
	commands chan *proto.ClientToServer, disconnected chan error) {
	defer server.wg.Done()
	defer close(commands)
	defer close(disconnected)
	inBuf := make([]byte, MAX_MESSAGE_SIZE)
	cmd := new(proto.ClientToServer)
	for {
		num, err := conn.ReadFrame(inBuf)
		if err != nil {
			disconnected <- err
			return
		}
		if err := cmd.Unmarshal(inBuf[:num]); err != nil {
			disconnected <- err
			return
		}
		commands <- cmd
		cmd = <-commands
		cmd.Reset()
	}
}

// readClientNotifications is a for loop of blocking reads on notificationsIn
// and non-blocking sends on notificationsOut. If the input channel is closed
// or a send would block, the output channel is closed.
func (server *Server) readClientNotifications(notificationsIn chan []byte, notificationsOut chan []byte) {
	var hasOverflowed bool
	defer server.wg.Done()
	for n := range notificationsIn {
		if !hasOverflowed {
			select {
			case notificationsOut <- n:
			default:
				hasOverflowed = true
				close(notificationsOut)
			}
		}
	}
}

func toProtoByte32List(list *[][32]byte) *[]proto.Byte32 {
	newList := make([]proto.Byte32, 0)
	for _, element := range *list {
		newList = append(newList, (proto.Byte32)(element))
	}
	return &newList
}

func to32ByteList(list *[]proto.Byte32) *[][32]byte {
	newList := make([][32]byte, 0, 0)
	for _, element := range *list {
		newList = append(newList, ([32]byte)(element))
	}
	return &newList
}

//for each client, listen for commands
func (server *Server) handleClient(connection net.Conn) error {
	defer server.wg.Done()
	newConnection, uid, err := transport.Handshake(connection, server.pk, server.sk, nil, MAX_MESSAGE_SIZE) //TODO: Decide on this bound
	if err != nil {
		return err
	}

	commands := make(chan *proto.ClientToServer)
	disconnected := make(chan error)
	server.wg.Add(2)
	go server.readClientCommands(newConnection, commands, disconnected)
	go server.handleClientShutdown(newConnection)

	var notificationsUnbuffered, notifications chan []byte
	var notifyEnabled bool
	defer func() {
		if notifyEnabled {
			server.notifier.StopWaitingSync(uid, notificationsUnbuffered)
		}
	}()

	outBuf := make([]byte, MAX_MESSAGE_SIZE)
	response := new(proto.ServerToClient)
	for {
		select {
		case err := <-disconnected:
			return err
		case cmd := <-commands:
			if cmd.CreateAccount != nil && *cmd.CreateAccount {
				err = server.newUser(uid)
			} else if cmd.DeliverEnvelope != nil {
				err = server.newMessage((*[32]byte)(cmd.DeliverEnvelope.User),
					cmd.DeliverEnvelope.Envelope)
			} else if cmd.ListMessages != nil && *cmd.ListMessages {
				var messageList *[][32]byte
				messageList, err = server.getMessageList(uid)
				response.MessageList = *toProtoByte32List(messageList)
			} else if cmd.DownloadEnvelope != nil {
				response.Envelope, err = server.getEnvelope(uid, (*[32]byte)(cmd.DownloadEnvelope))
			} else if cmd.DeleteMessages != nil {
				messageList := cmd.DeleteMessages
				err = server.deleteMessages(uid, to32ByteList(&messageList))
			} else if cmd.UploadSignedKeys != nil {
				err = server.newKeys(uid, cmd.UploadSignedKeys)
			} else if cmd.GetSignedKey != nil {
				response.SignedKey, err = server.getKey((*[32]byte)(cmd.GetSignedKey))
			} else if cmd.GetNumKeys != nil {
				response.NumKeys, err = server.getNumKeys(uid)
			} else if cmd.ReceiveEnvelopes != nil {
				if *cmd.ReceiveEnvelopes && !notifyEnabled {
					notifyEnabled = true
					notificationsUnbuffered = server.notifier.StartWaiting(uid)
					notifications = make(chan []byte)
					server.wg.Add(1)
					go server.readClientNotifications(notificationsUnbuffered, notifications)
				} else if !*cmd.ReceiveEnvelopes && notifyEnabled {
					server.notifier.StopWaitingSync(uid, notificationsUnbuffered)
					notifyEnabled = false
				}
			}
			if err != nil {
				response.Status = proto.ServerToClient_PARSE_ERROR.Enum()
			} else {
				response.Status = proto.ServerToClient_OK.Enum()
			}
			if err = server.writeProtobuf(newConnection, outBuf, response); err != nil {
				return err
			}
			commands <- cmd
		case notification, ok := <-notifications:
			if !notifyEnabled {
				continue
			}
			if !ok {
				notifyEnabled = false
				go server.notifier.StopWaitingSync(uid, notificationsUnbuffered)
				continue
			}
			response.Envelope = notification
			response.Status = proto.ServerToClient_OK.Enum()
			if err = server.writeProtobuf(newConnection, outBuf, response); err != nil {
				return err
			}
		}
		response.Reset()
	}
	return nil
}

func (server *Server) getNumKeys(user *[32]byte) (*int64, error) { //TODO: Batch read of some kind?
	prefix := append([]byte{'k'}, (*user)[:]...)
	snapshot, err := server.database.GetSnapshot()
	if err != nil {
		return nil, err
	}
	defer snapshot.Release()
	keyRange := util.BytesPrefix(prefix)
	iter := snapshot.NewIterator(keyRange, nil)
	defer iter.Release()
	var numRecords int64
	for iter.Next() {
		numRecords = numRecords + 1
	}
	return &numRecords, iter.Error()
}

func (server *Server) deleteKey(uid *[32]byte, key []byte) error {
	keyHash := sha256.Sum256((key))
	dbKey := append(append([]byte{'k'}, uid[:]...), keyHash[:]...)
	return server.database.Delete(dbKey, WO_sync)
}

func (server *Server) getKey(user *[32]byte) ([]byte, error) {
	prefix := append([]byte{'k'}, (*user)[:]...)
	server.keyMutex.Lock()
	defer server.keyMutex.Unlock()
	snapshot, err := server.database.GetSnapshot()
	if err != nil {
		return nil, err
	}
	defer snapshot.Release()
	keyRange := util.BytesPrefix(prefix)
	iter := snapshot.NewIterator(keyRange, nil)
	defer iter.Release()
	if iter.First() == false {
		return nil, errors.New("No keys left in database")
	}
	err = iter.Error()
	server.deleteKey(user, iter.Value())
	return append([]byte{}, iter.Value()...), err
}

func (server *Server) newKeys(uid *[32]byte, keyList [][]byte) error {
	batch := new(leveldb.Batch)
	for _, key := range keyList {
		keyHash := sha256.Sum256(key)
		dbKey := append(append([]byte{'k'}, uid[:]...), keyHash[:]...)
		batch.Put(dbKey, key)
	}
	return server.database.Write(batch, WO_sync)
}
func (server *Server) deleteMessages(uid *[32]byte, messageList *[][32]byte) error {
	batch := new(leveldb.Batch)
	for _, messageHash := range *messageList {
		key := append(append([]byte{'m'}, uid[:]...), messageHash[:]...)
		batch.Delete(key)
	}
	return server.database.Write(batch, WO_sync)
}

func (server *Server) getEnvelope(uid *[32]byte, messageHash *[32]byte) ([]byte, error) {
	key := append(append([]byte{'m'}, uid[:]...), (messageHash)[:]...)
	envelope, err := server.database.Get(key, nil)
	return envelope, err
}

func (server *Server) writeProtobuf(conn *transport.Conn, outBuf []byte, message *proto.ServerToClient) error {
	size, err := message.MarshalTo(outBuf)
	if err != nil {
		return err
	}
	conn.WriteFrame(outBuf[:size])
	return nil
}

func (server *Server) getMessageList(user *[32]byte) (*[][32]byte, error) {
	messages := make([][32]byte, 0)
	prefix := append([]byte{'m'}, (*user)[:]...)
	messageRange := util.BytesPrefix(prefix)
	snapshot, err := server.database.GetSnapshot()
	if err != nil {
		return nil, err
	}
	defer snapshot.Release()
	iter := snapshot.NewIterator(messageRange, nil)
	defer iter.Release()
	for iter.Next() {
		var message [32]byte
		copy(message[:], iter.Key()[len(prefix):len(prefix)+32])
		messages = append(messages, message)
	}
	err = iter.Error()
	return &messages, err
}

func (server *Server) newMessage(uid *[32]byte, envelope []byte) error {
	// TODO: check that user exists
	messageHash := sha256.Sum256(envelope)
	key := append(append([]byte{'m'}, uid[:]...), messageHash[:]...)
	err := server.database.Put(key, (envelope)[:], WO_sync)
	if err != nil {
		return err
	}
	server.notifier.Notify(uid, append([]byte{}, envelope...))
	return nil
}

func (server *Server) newUser(uid *[32]byte) error {
	return server.database.Put(append([]byte{'u'}, uid[:]...), []byte(""), WO_sync)
}
<|endoftext|>


<commit_before>package server

import (
	"log"
	"net/http"
	"os"

	"github.com/julienschmidt/httprouter"

	kitlog "github.com/go-kit/kit/log"
	kitprometheus "github.com/go-kit/kit/metrics/prometheus"
	httptransport "github.com/go-kit/kit/transport/http"
	stdprometheus "github.com/prometheus/client_golang/prometheus"
)

var logger *log.Logger

func init() {
	logger = log.New(os.Stdout, "server: ", log.Lshortfile)
}

func Init(port string) {

	var serverLogger kitlog.Logger
	serverLogger = kitlog.NewLogfmtLogger(os.Stderr)
	serverLogger = kitlog.With(serverLogger, "listen", port, "caller", kitlog.DefaultCaller)

	fieldKeys := []string{"method", "error"}

	requestCount := kitprometheus.NewCounterFrom(stdprometheus.CounterOpts{
		Namespace: "dfk",
		Subsystem: "parse_service",
		Name:      "request_count",
		Help:      "Number of requests received.",
	}, fieldKeys)
	requestLatency := kitprometheus.NewSummaryFrom(stdprometheus.SummaryOpts{
		Namespace: "dfk",
		Subsystem: "parse_service",
		Name:      "request_latency_microseconds",
		Help:      "Total duration of requests in microseconds.",
	}, fieldKeys)
	countResult := kitprometheus.NewSummaryFrom(stdprometheus.SummaryOpts{
		Namespace: "dfk",
		Subsystem: "parse_service",
		Name:      "count_result",
		Help:      "The result of each count method.",
	}, []string{})

	var svc ParseService
	svc = parseService{}
	//	svc = proxyingMiddleware(context.Background(), proxy, serverLogger)(svc)
	svc = statsMiddleware("18")(svc)
	svc = cachingMiddleware()(svc)
	//	svc = resultCachingMiddleware()(svc)
	svc = loggingMiddleware(serverLogger)(svc)
	svc = robotsTxtMiddleware()(svc)
	svc = instrumentingMiddleware(requestCount, requestLatency, countResult)(svc)

	getHTMLHandler := httptransport.NewServer(
		makeGetHTMLEndpoint(svc),
		decodeGetHTMLRequest,
		encodeResponse,
	)

	marshalDataHandler := httptransport.NewServer(
		makeMarshalDataEndpoint(svc),
		decodeMarshalDataRequest,
		encodeResponse,
	)

	/*
	checkServicesHandler := httptransport.NewServer(
		makeCheckServicesEndpoint(svc),
		decodeCheckServicesRequest,
		encodeCheckServicesResponse,
	)
	*/

	router := httprouter.New()
	router.Handler("POST", "/app/gethtml", getHTMLHandler)
	router.Handler("POST", "/app/marshaldata", marshalDataHandler)
	//router.Handler("POST", "/app/chkservices", checkServicesHandler)
	//router.ServeFiles("/static/*filepath", http.Dir("web/static"))
	//router.HandlerFunc("GET", "/", func(w http.ResponseWriter, r *http.Request) {
	//	http.ServeFile(w, r, "web/index.html")
	//})

	router.Handler("GET", "/metrics", stdprometheus.Handler())

	serverLogger.Log("msg", "HTTP", "addr", port)
	serverLogger.Log("err", http.ListenAndServe(port, router))
}
<commit_msg>reverted server changes temporarily<commit_after>package server

import (
	"log"
	"net/http"
	"os"

	"github.com/julienschmidt/httprouter"

	kitlog "github.com/go-kit/kit/log"
	kitprometheus "github.com/go-kit/kit/metrics/prometheus"
	httptransport "github.com/go-kit/kit/transport/http"
	stdprometheus "github.com/prometheus/client_golang/prometheus"
)

var logger *log.Logger

func init() {
	logger = log.New(os.Stdout, "server: ", log.Lshortfile)
}

func Init(port string) {

	var serverLogger kitlog.Logger
	serverLogger = kitlog.NewLogfmtLogger(os.Stderr)
	serverLogger = kitlog.With(serverLogger, "listen", port, "caller", kitlog.DefaultCaller)

	fieldKeys := []string{"method", "error"}

	requestCount := kitprometheus.NewCounterFrom(stdprometheus.CounterOpts{
		Namespace: "dfk",
		Subsystem: "parse_service",
		Name:      "request_count",
		Help:      "Number of requests received.",
	}, fieldKeys)
	requestLatency := kitprometheus.NewSummaryFrom(stdprometheus.SummaryOpts{
		Namespace: "dfk",
		Subsystem: "parse_service",
		Name:      "request_latency_microseconds",
		Help:      "Total duration of requests in microseconds.",
	}, fieldKeys)
	countResult := kitprometheus.NewSummaryFrom(stdprometheus.SummaryOpts{
		Namespace: "dfk",
		Subsystem: "parse_service",
		Name:      "count_result",
		Help:      "The result of each count method.",
	}, []string{})

	var svc ParseService
	svc = parseService{}
	//	svc = proxyingMiddleware(context.Background(), proxy, serverLogger)(svc)
	svc = statsMiddleware("18")(svc)
	svc = cachingMiddleware()(svc)
	//	svc = resultCachingMiddleware()(svc)
	svc = loggingMiddleware(serverLogger)(svc)
	svc = robotsTxtMiddleware()(svc)
	svc = instrumentingMiddleware(requestCount, requestLatency, countResult)(svc)

	getHTMLHandler := httptransport.NewServer(
		makeGetHTMLEndpoint(svc),
		decodeGetHTMLRequest,
		encodeResponse,
	)

	marshalDataHandler := httptransport.NewServer(
		makeMarshalDataEndpoint(svc),
		decodeMarshalDataRequest,
		encodeResponse,
	)

	/*
	checkServicesHandler := httptransport.NewServer(
		makeCheckServicesEndpoint(svc),
		decodeCheckServicesRequest,
		encodeCheckServicesResponse,
	)
	*/

	router := httprouter.New()
	router.Handler("POST", "/app/gethtml", getHTMLHandler)
	router.Handler("POST", "/app/marshaldata", marshalDataHandler)
	//router.Handler("POST", "/app/chkservices", checkServicesHandler)
	router.ServeFiles("/static/*filepath", http.Dir("web/static"))
	router.HandlerFunc("GET", "/", func(w http.ResponseWriter, r *http.Request) {
		http.ServeFile(w, r, "web/index.html")
	})

	router.Handler("GET", "/metrics", stdprometheus.Handler())

	serverLogger.Log("msg", "HTTP", "addr", port)
	serverLogger.Log("err", http.ListenAndServe(port, router))
}
<|endoftext|>


<commit_before>// Copyright 2018-2022 the u-root Authors. All rights reserved
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package server

import (
	"fmt"
	"io"
	"io/ioutil"
	"log"
	"os"
	"strings"
	"syscall"
	"unsafe"

	// We use this ssh because it implements port redirection.
	// It can not, however, unpack password-protected keys yet.
	"github.com/gliderlabs/ssh"
	"github.com/kr/pty" // TODO: get rid of krpty
)

const (
	defaultPort = "23"
)

var (
	v = log.Printf // func(string, ...interface{}) {}
)

func verbose(f string, a ...interface{}) {
	v("\r\nCPUD:"+f+"\r\n", a...)
}

func setWinsize(f *os.File, w, h int) {
	syscall.Syscall(syscall.SYS_IOCTL, f.Fd(), uintptr(syscall.TIOCSWINSZ), //nolint
		uintptr(unsafe.Pointer(&struct{ h, w, x, y uint16 }{uint16(h), uint16(w), 0, 0})))
}

// errval can be used to examine errors that we don't consider errors
func errval(err error) error {
	if err == nil {
		return err
	}
	// Our zombie reaper is occasionally sneaking in and grabbing the
	// child's exit state. Looks like our process code still sux.
	if strings.Contains(err.Error(), "no child process") {
		return nil
	}
	return err
}

func handler(s ssh.Session) {
	a := s.Command()
	v("handler: cmd is %q", a)
	cmd := command(a[0], a[1:]...)
	cmd.Env = append(cmd.Env, s.Environ()...)
	ptyReq, winCh, isPty := s.Pty()
	if isPty {
		cmd.Env = append(cmd.Env, fmt.Sprintf("TERM=%s", ptyReq.Term))
		f, err := pty.Start(cmd)
		v("command started with pty")
		if err != nil {
			v("CPUD:err %v", err)
			return
		}
		go func() {
			for win := range winCh {
				setWinsize(f, win.Width, win.Height)
			}
		}()
		go func() {
			io.Copy(f, s) //nolint stdin
		}()
		io.Copy(s, f) //nolint stdout
		// Stdout is closed, "there's no more to the show/
		// If you all want to breath right/you all better go"
		// This is going to seem a bit odd, but it is important to
		// only wait for the process started here, not any orphans.
		// In most cases, that process is either a singleton (so the wait
		// will be all we need); a shell (which does all the waiting for
		// its children); or the rare case of a detached process (in which
		// case the reaper will get it).
		// Seen in the wild: were this code to wait for orphans,
		// and the main loop to wait for orphans, they end up
		// competing with each other and the results are odd to say the least.
		// If the command exits, leaving orphans behind, it is the job
		// of the reaper to get them.
		v("wait for %q", cmd)
		err = cmd.Wait()
		v("cmd %q returns with %v %v", cmd, err, cmd.ProcessState)
		if errval(err) != nil {
			v("CPUD:child exited with  %v", err)
			s.Exit(cmd.ProcessState.ExitCode()) //nolint
		}

	} else {
		cmd.Stdin, cmd.Stdout, cmd.Stderr = s, s, s
		v("running command without pty")
		if err := cmd.Run(); errval(err) != nil {
			v("CPUD:err %v", err)
			s.Exit(1) //nolint
		}
	}
	verbose("handler exits")
}

// New sets up a cpud. cpud is really just an SSH server with a special
// handler and support for port forwarding for the 9p port.
func New(publicKeyFile, hostKeyFile string) (*ssh.Server, error) {
	v("configure SSH server")
	publicKeyOption := func(ctx ssh.Context, key ssh.PublicKey) bool {
		data, err := ioutil.ReadFile(publicKeyFile)
		if err != nil {
			fmt.Print(err)
			return false
		}
		allowed, _, _, _, err := ssh.ParseAuthorizedKey(data)
		if err != nil {
			fmt.Print(err)
			return false
		}
		return ssh.KeysEqual(key, allowed)
	}

	// Now we run as an ssh server, and each time we get a connection,
	// we run that command after setting things up for it.
	forwardHandler := &ssh.ForwardedTCPHandler{}
	server := &ssh.Server{
		LocalPortForwardingCallback: ssh.LocalPortForwardingCallback(func(ctx ssh.Context, dhost string, dport uint32) bool {
			log.Println("CPUD:Accepted forward", dhost, dport)
			return true
		}),
		// Pick a reasonable default, which can be used for a call to listen and which
		// will be overridden later from a listen.Addr
		Addr:             ":" + defaultPort,
		PublicKeyHandler: publicKeyOption,
		ReversePortForwardingCallback: ssh.ReversePortForwardingCallback(func(ctx ssh.Context, host string, port uint32) bool {
			v("CPUD:attempt to bind", host, port, "granted")
			return true
		}),
		RequestHandlers: map[string]ssh.RequestHandler{
			"tcpip-forward":        forwardHandler.HandleSSHRequest,
			"cancel-tcpip-forward": forwardHandler.HandleSSHRequest,
		},
		Handler: handler,
	}

	// we ignore the SetOption error; if it does not work out, we
	// actually don't care.
	server.SetOption(ssh.HostKeyFile(hostKeyFile))
	return server, nil
}
<commit_msg>server: turn off debug prints<commit_after>// Copyright 2018-2022 the u-root Authors. All rights reserved
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package server

import (
	"fmt"
	"io"
	"io/ioutil"
	"log"
	"os"
	"strings"
	"syscall"
	"unsafe"

	// We use this ssh because it implements port redirection.
	// It can not, however, unpack password-protected keys yet.
	"github.com/gliderlabs/ssh"
	"github.com/kr/pty" // TODO: get rid of krpty
)

const (
	defaultPort = "23"
)

var (
	v = func(string, ...interface{}) {}
)

func verbose(f string, a ...interface{}) {
	v("\r\nCPUD:"+f+"\r\n", a...)
}

func setWinsize(f *os.File, w, h int) {
	syscall.Syscall(syscall.SYS_IOCTL, f.Fd(), uintptr(syscall.TIOCSWINSZ), //nolint
		uintptr(unsafe.Pointer(&struct{ h, w, x, y uint16 }{uint16(h), uint16(w), 0, 0})))
}

// errval can be used to examine errors that we don't consider errors
func errval(err error) error {
	if err == nil {
		return err
	}
	// Our zombie reaper is occasionally sneaking in and grabbing the
	// child's exit state. Looks like our process code still sux.
	if strings.Contains(err.Error(), "no child process") {
		return nil
	}
	return err
}

func handler(s ssh.Session) {
	a := s.Command()
	v("handler: cmd is %q", a)
	cmd := command(a[0], a[1:]...)
	cmd.Env = append(cmd.Env, s.Environ()...)
	ptyReq, winCh, isPty := s.Pty()
	if isPty {
		cmd.Env = append(cmd.Env, fmt.Sprintf("TERM=%s", ptyReq.Term))
		f, err := pty.Start(cmd)
		v("command started with pty")
		if err != nil {
			v("CPUD:err %v", err)
			return
		}
		go func() {
			for win := range winCh {
				setWinsize(f, win.Width, win.Height)
			}
		}()
		go func() {
			io.Copy(f, s) //nolint stdin
		}()
		io.Copy(s, f) //nolint stdout
		// Stdout is closed, "there's no more to the show/
		// If you all want to breath right/you all better go"
		// This is going to seem a bit odd, but it is important to
		// only wait for the process started here, not any orphans.
		// In most cases, that process is either a singleton (so the wait
		// will be all we need); a shell (which does all the waiting for
		// its children); or the rare case of a detached process (in which
		// case the reaper will get it).
		// Seen in the wild: were this code to wait for orphans,
		// and the main loop to wait for orphans, they end up
		// competing with each other and the results are odd to say the least.
		// If the command exits, leaving orphans behind, it is the job
		// of the reaper to get them.
		v("wait for %q", cmd)
		err = cmd.Wait()
		v("cmd %q returns with %v %v", cmd, err, cmd.ProcessState)
		if errval(err) != nil {
			v("CPUD:child exited with  %v", err)
			s.Exit(cmd.ProcessState.ExitCode()) //nolint
		}

	} else {
		cmd.Stdin, cmd.Stdout, cmd.Stderr = s, s, s
		v("running command without pty")
		if err := cmd.Run(); errval(err) != nil {
			v("CPUD:err %v", err)
			s.Exit(1) //nolint
		}
	}
	verbose("handler exits")
}

// New sets up a cpud. cpud is really just an SSH server with a special
// handler and support for port forwarding for the 9p port.
func New(publicKeyFile, hostKeyFile string) (*ssh.Server, error) {
	v("configure SSH server")
	publicKeyOption := func(ctx ssh.Context, key ssh.PublicKey) bool {
		data, err := ioutil.ReadFile(publicKeyFile)
		if err != nil {
			fmt.Print(err)
			return false
		}
		allowed, _, _, _, err := ssh.ParseAuthorizedKey(data)
		if err != nil {
			fmt.Print(err)
			return false
		}
		return ssh.KeysEqual(key, allowed)
	}

	// Now we run as an ssh server, and each time we get a connection,
	// we run that command after setting things up for it.
	forwardHandler := &ssh.ForwardedTCPHandler{}
	server := &ssh.Server{
		LocalPortForwardingCallback: ssh.LocalPortForwardingCallback(func(ctx ssh.Context, dhost string, dport uint32) bool {
			log.Println("CPUD:Accepted forward", dhost, dport)
			return true
		}),
		// Pick a reasonable default, which can be used for a call to listen and which
		// will be overridden later from a listen.Addr
		Addr:             ":" + defaultPort,
		PublicKeyHandler: publicKeyOption,
		ReversePortForwardingCallback: ssh.ReversePortForwardingCallback(func(ctx ssh.Context, host string, port uint32) bool {
			v("CPUD:attempt to bind", host, port, "granted")
			return true
		}),
		RequestHandlers: map[string]ssh.RequestHandler{
			"tcpip-forward":        forwardHandler.HandleSSHRequest,
			"cancel-tcpip-forward": forwardHandler.HandleSSHRequest,
		},
		Handler: handler,
	}

	// we ignore the SetOption error; if it does not work out, we
	// actually don't care.
	server.SetOption(ssh.HostKeyFile(hostKeyFile))
	return server, nil
}
<|endoftext|>


<commit_before>package server

import (
	"context"
	"net/http"

	"github.com/gorilla/mux"
	"github.com/rancher/rancher/pkg/api/customization/clusteregistrationtokens"
	managementapi "github.com/rancher/rancher/pkg/api/server"
	"github.com/rancher/rancher/pkg/auth/providers/publicapi"
	authrequests "github.com/rancher/rancher/pkg/auth/requests"
	"github.com/rancher/rancher/pkg/auth/tokens"
	"github.com/rancher/rancher/pkg/controllers/user/pipeline/hooks"
	rancherdialer "github.com/rancher/rancher/pkg/dialer"
	"github.com/rancher/rancher/pkg/dynamiclistener"
	"github.com/rancher/rancher/pkg/httpproxy"
	k8sProxy "github.com/rancher/rancher/pkg/k8sproxy"
	"github.com/rancher/rancher/pkg/rkenodeconfigserver"
	"github.com/rancher/rancher/server/capabilities"
	"github.com/rancher/rancher/server/ui"
	managementSchema "github.com/rancher/types/apis/management.cattle.io/v3/schema"
	"github.com/rancher/types/config"
	"github.com/rancher/types/config/dialer"
	utilnet "k8s.io/apimachinery/pkg/util/net"
	"k8s.io/kubernetes/cmd/kube-apiserver/app"
)

var (
	whiteList = []string{
		"*.amazonaws.com",
		"*.amazonaws.com.cn",
		"forums.rancher.com",
		"api.exoscale.ch",
		"api.ubiquityhosting.com",
		"api.digitalocean.com",
		"*.otc.t-systems.com",
		"api.profitbricks.com",
		"api.packet.net",
	}
)

func Start(ctx context.Context, httpPort, httpsPort int, apiContext *config.ScaledContext) error {
	tokenAPI, err := tokens.NewAPIHandler(ctx, apiContext)
	if err != nil {
		return err
	}

	publicAPI, err := publicapi.NewHandler(ctx, apiContext)
	if err != nil {
		return err
	}

	managementAPI, err := managementapi.New(ctx, apiContext)
	if err != nil {
		return err
	}

	root := mux.NewRouter()

	app.DefaultProxyDialer = utilnet.DialFunc(apiContext.Dialer.LocalClusterDialer())

	localClusterAuth := k8sProxy.NewLocalProxy(apiContext, apiContext.Dialer, root)

	k8sProxy := k8sProxy.New(apiContext, apiContext.Dialer)

	rawAuthedAPIs := newAuthed(tokenAPI, managementAPI, k8sProxy)

	authedHandler, err := authrequests.NewAuthenticationFilter(ctx, apiContext, rawAuthedAPIs)
	if err != nil {
		return err
	}

	webhookHandler := hooks.New(apiContext)

	connectHandler, connectConfigHandler := connectHandlers(apiContext.Dialer)

	root.Handle("/", ui.UI(managementAPI))
	root.PathPrefix("/v3-public").Handler(publicAPI)
	root.Handle("/v3/import/{token}.yaml", http.HandlerFunc(clusteregistrationtokens.ClusterImportHandler))
	root.Handle("/v3/connect", connectHandler)
	root.Handle("/v3/connect/config", connectConfigHandler)
	root.Handle("/v3/settings/cacerts", rawAuthedAPIs).Methods(http.MethodGet)
	root.PathPrefix("/v3").Handler(authedHandler)
	root.PathPrefix("/hooks").Handler(webhookHandler)
	root.PathPrefix("/k8s/clusters/").Handler(authedHandler)
	root.PathPrefix("/meta").Handler(authedHandler)
	root.NotFoundHandler = ui.UI(http.NotFoundHandler())

	// UI
	uiContent := ui.Content()
	root.PathPrefix("/assets").Handler(uiContent)
	root.PathPrefix("/translations").Handler(uiContent)
	root.Handle("/humans.txt", uiContent)
	root.Handle("/index.html", uiContent)
	root.Handle("/robots.txt", uiContent)
	root.Handle("/VERSION.txt", uiContent)

	registerHealth(root)

	dynamiclistener.Start(ctx, apiContext, httpPort, httpsPort, localClusterAuth)
	return nil
}

func newAuthed(tokenAPI http.Handler, managementAPI http.Handler, k8sproxy http.Handler) *mux.Router {
	authed := mux.NewRouter()
	authed.PathPrefix("/meta/proxy").Handler(newProxy())
	authed.PathPrefix("/meta").Handler(managementAPI)
	authed.PathPrefix("/v3/gkeMachineTypes").Handler(capabilities.NewGKEMachineTypesHandler())
	authed.PathPrefix("/v3/gkeVersions").Handler(capabilities.NewGKEVersionsHandler())
	authed.PathPrefix("/v3/gkeZones").Handler(capabilities.NewGKEZonesHandler())
	authed.PathPrefix("/v3/identit").Handler(tokenAPI)
	authed.PathPrefix("/v3/token").Handler(tokenAPI)
	authed.PathPrefix("/k8s/clusters/").Handler(k8sproxy)
	authed.PathPrefix(managementSchema.Version.Path).Handler(managementAPI)

	return authed
}

func connectHandlers(dialer dialer.Factory) (http.Handler, http.Handler) {
	if f, ok := dialer.(*rancherdialer.Factory); ok {
		return f.TunnelServer, rkenodeconfigserver.Handler(f.TunnelAuthorizer)
	}

	return http.NotFoundHandler(), http.NotFoundHandler()
}

func newProxy() http.Handler {
	return httpproxy.NewProxy("/proxy/", func() []string {
		return whiteList
	})
}
<commit_msg>Use encoded path in router<commit_after>package server

import (
	"context"
	"net/http"

	"github.com/gorilla/mux"
	"github.com/rancher/rancher/pkg/api/customization/clusteregistrationtokens"
	managementapi "github.com/rancher/rancher/pkg/api/server"
	"github.com/rancher/rancher/pkg/auth/providers/publicapi"
	authrequests "github.com/rancher/rancher/pkg/auth/requests"
	"github.com/rancher/rancher/pkg/auth/tokens"
	"github.com/rancher/rancher/pkg/controllers/user/pipeline/hooks"
	rancherdialer "github.com/rancher/rancher/pkg/dialer"
	"github.com/rancher/rancher/pkg/dynamiclistener"
	"github.com/rancher/rancher/pkg/httpproxy"
	k8sProxy "github.com/rancher/rancher/pkg/k8sproxy"
	"github.com/rancher/rancher/pkg/rkenodeconfigserver"
	"github.com/rancher/rancher/server/capabilities"
	"github.com/rancher/rancher/server/ui"
	managementSchema "github.com/rancher/types/apis/management.cattle.io/v3/schema"
	"github.com/rancher/types/config"
	"github.com/rancher/types/config/dialer"
	utilnet "k8s.io/apimachinery/pkg/util/net"
	"k8s.io/kubernetes/cmd/kube-apiserver/app"
)

var (
	whiteList = []string{
		"*.amazonaws.com",
		"*.amazonaws.com.cn",
		"forums.rancher.com",
		"api.exoscale.ch",
		"api.ubiquityhosting.com",
		"api.digitalocean.com",
		"*.otc.t-systems.com",
		"api.profitbricks.com",
		"api.packet.net",
	}
)

func Start(ctx context.Context, httpPort, httpsPort int, apiContext *config.ScaledContext) error {
	tokenAPI, err := tokens.NewAPIHandler(ctx, apiContext)
	if err != nil {
		return err
	}

	publicAPI, err := publicapi.NewHandler(ctx, apiContext)
	if err != nil {
		return err
	}

	managementAPI, err := managementapi.New(ctx, apiContext)
	if err != nil {
		return err
	}

	root := mux.NewRouter()
	root.UseEncodedPath()

	app.DefaultProxyDialer = utilnet.DialFunc(apiContext.Dialer.LocalClusterDialer())

	localClusterAuth := k8sProxy.NewLocalProxy(apiContext, apiContext.Dialer, root)

	k8sProxy := k8sProxy.New(apiContext, apiContext.Dialer)

	rawAuthedAPIs := newAuthed(tokenAPI, managementAPI, k8sProxy)

	authedHandler, err := authrequests.NewAuthenticationFilter(ctx, apiContext, rawAuthedAPIs)
	if err != nil {
		return err
	}

	webhookHandler := hooks.New(apiContext)

	connectHandler, connectConfigHandler := connectHandlers(apiContext.Dialer)

	root.Handle("/", ui.UI(managementAPI))
	root.PathPrefix("/v3-public").Handler(publicAPI)
	root.Handle("/v3/import/{token}.yaml", http.HandlerFunc(clusteregistrationtokens.ClusterImportHandler))
	root.Handle("/v3/connect", connectHandler)
	root.Handle("/v3/connect/config", connectConfigHandler)
	root.Handle("/v3/settings/cacerts", rawAuthedAPIs).Methods(http.MethodGet)
	root.PathPrefix("/v3").Handler(authedHandler)
	root.PathPrefix("/hooks").Handler(webhookHandler)
	root.PathPrefix("/k8s/clusters/").Handler(authedHandler)
	root.PathPrefix("/meta").Handler(authedHandler)
	root.NotFoundHandler = ui.UI(http.NotFoundHandler())

	// UI
	uiContent := ui.Content()
	root.PathPrefix("/assets").Handler(uiContent)
	root.PathPrefix("/translations").Handler(uiContent)
	root.Handle("/humans.txt", uiContent)
	root.Handle("/index.html", uiContent)
	root.Handle("/robots.txt", uiContent)
	root.Handle("/VERSION.txt", uiContent)

	registerHealth(root)

	dynamiclistener.Start(ctx, apiContext, httpPort, httpsPort, localClusterAuth)
	return nil
}

func newAuthed(tokenAPI http.Handler, managementAPI http.Handler, k8sproxy http.Handler) *mux.Router {
	authed := mux.NewRouter()
	authed.UseEncodedPath()
	authed.PathPrefix("/meta/proxy").Handler(newProxy())
	authed.PathPrefix("/meta").Handler(managementAPI)
	authed.PathPrefix("/v3/gkeMachineTypes").Handler(capabilities.NewGKEMachineTypesHandler())
	authed.PathPrefix("/v3/gkeVersions").Handler(capabilities.NewGKEVersionsHandler())
	authed.PathPrefix("/v3/gkeZones").Handler(capabilities.NewGKEZonesHandler())
	authed.PathPrefix("/v3/identit").Handler(tokenAPI)
	authed.PathPrefix("/v3/token").Handler(tokenAPI)
	authed.PathPrefix("/k8s/clusters/").Handler(k8sproxy)
	authed.PathPrefix(managementSchema.Version.Path).Handler(managementAPI)

	return authed
}

func connectHandlers(dialer dialer.Factory) (http.Handler, http.Handler) {
	if f, ok := dialer.(*rancherdialer.Factory); ok {
		return f.TunnelServer, rkenodeconfigserver.Handler(f.TunnelAuthorizer)
	}

	return http.NotFoundHandler(), http.NotFoundHandler()
}

func newProxy() http.Handler {
	return httpproxy.NewProxy("/proxy/", func() []string {
		return whiteList
	})
}
<|endoftext|>


<commit_before>package server

import (
	"encoding/json"
	"fmt"
	"io/ioutil"
	"os"
	"path/filepath"
	"sync"

	"github.com/Sirupsen/logrus"
	"github.com/docker/docker/pkg/registrar"
	"github.com/docker/docker/pkg/truncindex"
	"github.com/kubernetes-incubator/cri-o/oci"
	"github.com/kubernetes-incubator/cri-o/utils"
	"github.com/opencontainers/runc/libcontainer/label"
	rspec "github.com/opencontainers/runtime-spec/specs-go"
	"github.com/rajatchopra/ocicni"
)

const (
	runtimeAPIVersion = "v1alpha1"
	imageStore        = "/var/lib/ocid/images"
)

// Server implements the RuntimeService and ImageService
type Server struct {
	root         string
	runtime      *oci.Runtime
	sandboxDir   string
	pausePath    string
	stateLock    sync.Mutex
	state        *serverState
	netPlugin    ocicni.CNIPlugin
	podNameIndex *registrar.Registrar
	podIDIndex   *truncindex.TruncIndex
	ctrNameIndex *registrar.Registrar
	ctrIDIndex   *truncindex.TruncIndex
}

func (s *Server) loadContainer(id string) error {
	config, err := ioutil.ReadFile(filepath.Join(s.runtime.ContainerDir(), id, "config.json"))
	if err != nil {
		return err
	}
	var m rspec.Spec
	if err = json.Unmarshal(config, &m); err != nil {
		return err
	}
	labels := make(map[string]string)
	if err = json.Unmarshal([]byte(m.Annotations["ocid/labels"]), &labels); err != nil {
		return err
	}
	name := m.Annotations["ocid/name"]
	name, err = s.reserveContainerName(id, name)
	if err != nil {
		return err
	}
	sb := s.getSandbox(m.Annotations["ocid/sandbox_id"])
	if sb == nil {
		logrus.Warnf("could not get sandbox with id %s, skipping", m.Annotations["ocid/sandbox_id"])
	}

	var tty bool
	if v := m.Annotations["ocid/tty"]; v == "true" {
		tty = true
	}
	containerPath := filepath.Join(s.runtime.ContainerDir(), id)

	ctr, err := oci.NewContainer(id, name, containerPath, m.Annotations["ocid/log_path"], labels, sb.id, tty)
	if err != nil {
		return err
	}
	s.addContainer(ctr)
	if err = s.runtime.UpdateStatus(ctr); err != nil {
		logrus.Warnf("error updating status for container %s: %v", ctr.ID(), err)
	}
	if err = s.ctrIDIndex.Add(id); err != nil {
		return err
	}
	return nil
}

func (s *Server) loadSandbox(id string) error {
	config, err := ioutil.ReadFile(filepath.Join(s.sandboxDir, id, "config.json"))
	if err != nil {
		return err
	}
	var m rspec.Spec
	if err = json.Unmarshal(config, &m); err != nil {
		return err
	}
	labels := make(map[string]string)
	if err = json.Unmarshal([]byte(m.Annotations["ocid/labels"]), &labels); err != nil {
		return err
	}
	name := m.Annotations["ocid/name"]
	name, err = s.reservePodName(id, name)
	if err != nil {
		return err
	}

	processLabel, mountLabel, err := label.InitLabels(label.DupSecOpt(m.Process.SelinuxLabel))
	if err != nil {
		return err
	}
	s.addSandbox(&sandbox{
		id:           id,
		name:         name,
		logDir:       m.Annotations["ocid/log_path"],
		labels:       labels,
		containers:   oci.NewMemoryStore(),
		processLabel: processLabel,
		mountLabel:   mountLabel,
	})
	sandboxPath := filepath.Join(s.sandboxDir, id)

	if err := label.ReserveLabel(processLabel); err != nil {
		return err
	}

	cname, err := s.reserveContainerName(m.Annotations["ocid/container_id"], m.Annotations["ocid/container_name"])
	if err != nil {
		return err
	}
	scontainer, err := oci.NewContainer(m.Annotations["ocid/container_id"], cname, sandboxPath, sandboxPath, labels, id, false)
	if err != nil {
		return err
	}
	s.addContainer(scontainer)
	if err = s.runtime.UpdateStatus(scontainer); err != nil {
		logrus.Warnf("error updating status for container %s: %v", scontainer.ID(), err)
	}
	if err = s.ctrIDIndex.Add(scontainer.ID()); err != nil {
		return err
	}
	if err = s.podIDIndex.Add(id); err != nil {
		return err
	}
	return nil
}

func (s *Server) restore() {
	sandboxDir, err := ioutil.ReadDir(s.sandboxDir)
	if err != nil {
		logrus.Warnf("could not read sandbox directory %s: %v", sandboxDir, err)
	}
	for _, v := range sandboxDir {
		if !v.IsDir() {
			continue
		}
		if err = s.loadSandbox(v.Name()); err != nil {
			logrus.Warnf("could not restore sandbox %s: %v", v.Name(), err)
		}
	}
	containerDir, err := ioutil.ReadDir(s.runtime.ContainerDir())
	if err != nil {
		logrus.Warnf("could not read container directory %s: %v", s.runtime.ContainerDir(), err)
	}
	for _, v := range containerDir {
		if !v.IsDir() {
			continue
		}
		if err := s.loadContainer(v.Name()); err != nil {
			logrus.Warnf("could not restore container %s: %v", v.Name(), err)

		}
	}
}

func (s *Server) reservePodName(id, name string) (string, error) {
	if err := s.podNameIndex.Reserve(name, id); err != nil {
		if err == registrar.ErrNameReserved {
			id, err := s.podNameIndex.Get(name)
			if err != nil {
				logrus.Warnf("name %s already reserved for %s", name, id)
				return "", err
			}
			return "", fmt.Errorf("conflict, name %s already reserved", name)
		}
		return "", fmt.Errorf("error reserving name %s", name)
	}
	return name, nil
}

func (s *Server) releasePodName(name string) {
	s.podNameIndex.Release(name)
}

func (s *Server) reserveContainerName(id, name string) (string, error) {
	if err := s.ctrNameIndex.Reserve(name, id); err != nil {
		if err == registrar.ErrNameReserved {
			id, err := s.ctrNameIndex.Get(name)
			if err != nil {
				logrus.Warnf("name %s already reserved for %s", name, id)
				return "", err
			}
			return "", fmt.Errorf("conflict, name %s already reserved", name)
		}
		return "", fmt.Errorf("error reserving name %s", name)
	}
	return name, nil
}

func (s *Server) releaseContainerName(name string) {
	s.ctrNameIndex.Release(name)
}

// New creates a new Server with options provided
func New(runtimePath, root, sandboxDir, containerDir, conmonPath, pausePath string) (*Server, error) {
	// TODO: This will go away later when we have wrapper process or systemd acting as
	// subreaper.
	if err := utils.SetSubreaper(1); err != nil {
		return nil, fmt.Errorf("failed to set server as subreaper: %v", err)
	}

	utils.StartReaper()

	if err := os.MkdirAll(imageStore, 0755); err != nil {
		return nil, err
	}

	if err := os.MkdirAll(sandboxDir, 0755); err != nil {
		return nil, err
	}

	r, err := oci.New(runtimePath, containerDir, conmonPath)
	if err != nil {
		return nil, err
	}
	sandboxes := make(map[string]*sandbox)
	containers := oci.NewMemoryStore()
	netPlugin, err := ocicni.InitCNI("")
	if err != nil {
		return nil, err
	}
	s := &Server{
		root:       root,
		runtime:    r,
		netPlugin:  netPlugin,
		sandboxDir: sandboxDir,
		pausePath:  pausePath,
		state: &serverState{
			sandboxes:  sandboxes,
			containers: containers,
		},
	}

	s.podIDIndex = truncindex.NewTruncIndex([]string{})
	s.podNameIndex = registrar.NewRegistrar()
	s.ctrIDIndex = truncindex.NewTruncIndex([]string{})
	s.ctrNameIndex = registrar.NewRegistrar()

	s.restore()

	logrus.Debugf("sandboxes: %v", s.state.sandboxes)
	logrus.Debugf("containers: %v", s.state.containers)
	return s, nil
}

type serverState struct {
	sandboxes  map[string]*sandbox
	containers oci.Store
}

func (s *Server) addSandbox(sb *sandbox) {
	s.stateLock.Lock()
	s.state.sandboxes[sb.id] = sb
	s.stateLock.Unlock()
}

func (s *Server) getSandbox(id string) *sandbox {
	s.stateLock.Lock()
	sb := s.state.sandboxes[id]
	s.stateLock.Unlock()
	return sb
}

func (s *Server) hasSandbox(id string) bool {
	s.stateLock.Lock()
	_, ok := s.state.sandboxes[id]
	s.stateLock.Unlock()
	return ok
}

func (s *Server) removeSandbox(id string) {
	s.stateLock.Lock()
	delete(s.state.sandboxes, id)
	s.stateLock.Unlock()
}

func (s *Server) addContainer(c *oci.Container) {
	s.stateLock.Lock()
	sandbox := s.state.sandboxes[c.Sandbox()]
	// TODO(runcom): handle !ok above!!! otherwise it panics!
	sandbox.addContainer(c)
	s.state.containers.Add(c.ID(), c)
	s.stateLock.Unlock()
}

func (s *Server) getContainer(id string) *oci.Container {
	s.stateLock.Lock()
	c := s.state.containers.Get(id)
	s.stateLock.Unlock()
	return c
}

func (s *Server) removeContainer(c *oci.Container) {
	s.stateLock.Lock()
	sandbox := s.state.sandboxes[c.Sandbox()]
	sandbox.removeContainer(c)
	s.state.containers.Delete(c.ID())
	s.stateLock.Unlock()
}
<commit_msg>server/server: check pods/ctrs directories before restore<commit_after>package server

import (
	"encoding/json"
	"fmt"
	"io/ioutil"
	"os"
	"path/filepath"
	"sync"

	"github.com/Sirupsen/logrus"
	"github.com/docker/docker/pkg/registrar"
	"github.com/docker/docker/pkg/truncindex"
	"github.com/kubernetes-incubator/cri-o/oci"
	"github.com/kubernetes-incubator/cri-o/utils"
	"github.com/opencontainers/runc/libcontainer/label"
	rspec "github.com/opencontainers/runtime-spec/specs-go"
	"github.com/rajatchopra/ocicni"
)

const (
	runtimeAPIVersion = "v1alpha1"
	imageStore        = "/var/lib/ocid/images"
)

// Server implements the RuntimeService and ImageService
type Server struct {
	root         string
	runtime      *oci.Runtime
	sandboxDir   string
	pausePath    string
	stateLock    sync.Mutex
	state        *serverState
	netPlugin    ocicni.CNIPlugin
	podNameIndex *registrar.Registrar
	podIDIndex   *truncindex.TruncIndex
	ctrNameIndex *registrar.Registrar
	ctrIDIndex   *truncindex.TruncIndex
}

func (s *Server) loadContainer(id string) error {
	config, err := ioutil.ReadFile(filepath.Join(s.runtime.ContainerDir(), id, "config.json"))
	if err != nil {
		return err
	}
	var m rspec.Spec
	if err = json.Unmarshal(config, &m); err != nil {
		return err
	}
	labels := make(map[string]string)
	if err = json.Unmarshal([]byte(m.Annotations["ocid/labels"]), &labels); err != nil {
		return err
	}
	name := m.Annotations["ocid/name"]
	name, err = s.reserveContainerName(id, name)
	if err != nil {
		return err
	}
	sb := s.getSandbox(m.Annotations["ocid/sandbox_id"])
	if sb == nil {
		logrus.Warnf("could not get sandbox with id %s, skipping", m.Annotations["ocid/sandbox_id"])
	}

	var tty bool
	if v := m.Annotations["ocid/tty"]; v == "true" {
		tty = true
	}
	containerPath := filepath.Join(s.runtime.ContainerDir(), id)

	ctr, err := oci.NewContainer(id, name, containerPath, m.Annotations["ocid/log_path"], labels, sb.id, tty)
	if err != nil {
		return err
	}
	s.addContainer(ctr)
	if err = s.runtime.UpdateStatus(ctr); err != nil {
		logrus.Warnf("error updating status for container %s: %v", ctr.ID(), err)
	}
	if err = s.ctrIDIndex.Add(id); err != nil {
		return err
	}
	return nil
}

func (s *Server) loadSandbox(id string) error {
	config, err := ioutil.ReadFile(filepath.Join(s.sandboxDir, id, "config.json"))
	if err != nil {
		return err
	}
	var m rspec.Spec
	if err = json.Unmarshal(config, &m); err != nil {
		return err
	}
	labels := make(map[string]string)
	if err = json.Unmarshal([]byte(m.Annotations["ocid/labels"]), &labels); err != nil {
		return err
	}
	name := m.Annotations["ocid/name"]
	name, err = s.reservePodName(id, name)
	if err != nil {
		return err
	}

	processLabel, mountLabel, err := label.InitLabels(label.DupSecOpt(m.Process.SelinuxLabel))
	if err != nil {
		return err
	}
	s.addSandbox(&sandbox{
		id:           id,
		name:         name,
		logDir:       m.Annotations["ocid/log_path"],
		labels:       labels,
		containers:   oci.NewMemoryStore(),
		processLabel: processLabel,
		mountLabel:   mountLabel,
	})
	sandboxPath := filepath.Join(s.sandboxDir, id)

	if err := label.ReserveLabel(processLabel); err != nil {
		return err
	}

	cname, err := s.reserveContainerName(m.Annotations["ocid/container_id"], m.Annotations["ocid/container_name"])
	if err != nil {
		return err
	}
	scontainer, err := oci.NewContainer(m.Annotations["ocid/container_id"], cname, sandboxPath, sandboxPath, labels, id, false)
	if err != nil {
		return err
	}
	s.addContainer(scontainer)
	if err = s.runtime.UpdateStatus(scontainer); err != nil {
		logrus.Warnf("error updating status for container %s: %v", scontainer.ID(), err)
	}
	if err = s.ctrIDIndex.Add(scontainer.ID()); err != nil {
		return err
	}
	if err = s.podIDIndex.Add(id); err != nil {
		return err
	}
	return nil
}

func (s *Server) restore() {
	sandboxDir, err := ioutil.ReadDir(s.sandboxDir)
	if err != nil && !os.IsNotExist(err) {
		logrus.Warnf("could not read sandbox directory %s: %v", sandboxDir, err)
	}
	for _, v := range sandboxDir {
		if !v.IsDir() {
			continue
		}
		if err = s.loadSandbox(v.Name()); err != nil {
			logrus.Warnf("could not restore sandbox %s: %v", v.Name(), err)
		}
	}
	containerDir, err := ioutil.ReadDir(s.runtime.ContainerDir())
	if err != nil && !os.IsNotExist(err) {
		logrus.Warnf("could not read container directory %s: %v", s.runtime.ContainerDir(), err)
	}
	for _, v := range containerDir {
		if !v.IsDir() {
			continue
		}
		if err := s.loadContainer(v.Name()); err != nil {
			logrus.Warnf("could not restore container %s: %v", v.Name(), err)

		}
	}
}

func (s *Server) reservePodName(id, name string) (string, error) {
	if err := s.podNameIndex.Reserve(name, id); err != nil {
		if err == registrar.ErrNameReserved {
			id, err := s.podNameIndex.Get(name)
			if err != nil {
				logrus.Warnf("name %s already reserved for %s", name, id)
				return "", err
			}
			return "", fmt.Errorf("conflict, name %s already reserved", name)
		}
		return "", fmt.Errorf("error reserving name %s", name)
	}
	return name, nil
}

func (s *Server) releasePodName(name string) {
	s.podNameIndex.Release(name)
}

func (s *Server) reserveContainerName(id, name string) (string, error) {
	if err := s.ctrNameIndex.Reserve(name, id); err != nil {
		if err == registrar.ErrNameReserved {
			id, err := s.ctrNameIndex.Get(name)
			if err != nil {
				logrus.Warnf("name %s already reserved for %s", name, id)
				return "", err
			}
			return "", fmt.Errorf("conflict, name %s already reserved", name)
		}
		return "", fmt.Errorf("error reserving name %s", name)
	}
	return name, nil
}

func (s *Server) releaseContainerName(name string) {
	s.ctrNameIndex.Release(name)
}

// New creates a new Server with options provided
func New(runtimePath, root, sandboxDir, containerDir, conmonPath, pausePath string) (*Server, error) {
	// TODO: This will go away later when we have wrapper process or systemd acting as
	// subreaper.
	if err := utils.SetSubreaper(1); err != nil {
		return nil, fmt.Errorf("failed to set server as subreaper: %v", err)
	}

	utils.StartReaper()

	if err := os.MkdirAll(imageStore, 0755); err != nil {
		return nil, err
	}

	if err := os.MkdirAll(sandboxDir, 0755); err != nil {
		return nil, err
	}

	r, err := oci.New(runtimePath, containerDir, conmonPath)
	if err != nil {
		return nil, err
	}
	sandboxes := make(map[string]*sandbox)
	containers := oci.NewMemoryStore()
	netPlugin, err := ocicni.InitCNI("")
	if err != nil {
		return nil, err
	}
	s := &Server{
		root:       root,
		runtime:    r,
		netPlugin:  netPlugin,
		sandboxDir: sandboxDir,
		pausePath:  pausePath,
		state: &serverState{
			sandboxes:  sandboxes,
			containers: containers,
		},
	}

	s.podIDIndex = truncindex.NewTruncIndex([]string{})
	s.podNameIndex = registrar.NewRegistrar()
	s.ctrIDIndex = truncindex.NewTruncIndex([]string{})
	s.ctrNameIndex = registrar.NewRegistrar()

	s.restore()

	logrus.Debugf("sandboxes: %v", s.state.sandboxes)
	logrus.Debugf("containers: %v", s.state.containers)
	return s, nil
}

type serverState struct {
	sandboxes  map[string]*sandbox
	containers oci.Store
}

func (s *Server) addSandbox(sb *sandbox) {
	s.stateLock.Lock()
	s.state.sandboxes[sb.id] = sb
	s.stateLock.Unlock()
}

func (s *Server) getSandbox(id string) *sandbox {
	s.stateLock.Lock()
	sb := s.state.sandboxes[id]
	s.stateLock.Unlock()
	return sb
}

func (s *Server) hasSandbox(id string) bool {
	s.stateLock.Lock()
	_, ok := s.state.sandboxes[id]
	s.stateLock.Unlock()
	return ok
}

func (s *Server) removeSandbox(id string) {
	s.stateLock.Lock()
	delete(s.state.sandboxes, id)
	s.stateLock.Unlock()
}

func (s *Server) addContainer(c *oci.Container) {
	s.stateLock.Lock()
	sandbox := s.state.sandboxes[c.Sandbox()]
	// TODO(runcom): handle !ok above!!! otherwise it panics!
	sandbox.addContainer(c)
	s.state.containers.Add(c.ID(), c)
	s.stateLock.Unlock()
}

func (s *Server) getContainer(id string) *oci.Container {
	s.stateLock.Lock()
	c := s.state.containers.Get(id)
	s.stateLock.Unlock()
	return c
}

func (s *Server) removeContainer(c *oci.Container) {
	s.stateLock.Lock()
	sandbox := s.state.sandboxes[c.Sandbox()]
	sandbox.removeContainer(c)
	s.state.containers.Delete(c.ID())
	s.stateLock.Unlock()
}
<|endoftext|>


<commit_before>//   Copyright 2017 MSolution.IO
//
//   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 main

import (
	"context"
	"fmt"
	"net/http"
	"os"
	"regexp"
	"time"

	uuid "github.com/satori/go.uuid"
	"github.com/trackit/jsonlog"

	_ "github.com/trackit/trackit/aws"
	_ "github.com/trackit/trackit/aws/routes"
	_ "github.com/trackit/trackit/aws/s3"
	"github.com/trackit/trackit/config"
	_ "github.com/trackit/trackit/costs"
	_ "github.com/trackit/trackit/costs/anomalies"
	_ "github.com/trackit/trackit/costs/diff"
	_ "github.com/trackit/trackit/costs/tags"
	"github.com/trackit/trackit/periodic"
	_ "github.com/trackit/trackit/plugins"
	_ "github.com/trackit/trackit/reports"
	_ "github.com/trackit/trackit/resourcesTagging"
	"github.com/trackit/trackit/routes"
	_ "github.com/trackit/trackit/s3/costs"
	_ "github.com/trackit/trackit/tagging/routes"
	_ "github.com/trackit/trackit/usageReports/ec2"
	_ "github.com/trackit/trackit/usageReports/ec2Coverage"
	_ "github.com/trackit/trackit/usageReports/elasticache"
	_ "github.com/trackit/trackit/usageReports/es"
	_ "github.com/trackit/trackit/usageReports/lambda"
	_ "github.com/trackit/trackit/usageReports/rds"
	_ "github.com/trackit/trackit/usageReports/riEc2"
	_ "github.com/trackit/trackit/usageReports/riRds"
	_ "github.com/trackit/trackit/users"
	_ "github.com/trackit/trackit/users/shared_account"
)

var buildNumber string = "unknown-build"
var backendId = getBackendId()

func init() {
	jsonlog.DefaultLogger = jsonlog.DefaultLogger.WithLogLevel(jsonlog.LogLevelDebug)
}

var tasks = map[string]func(context.Context) error{
	"server":                      taskServer,
	"ingest":                      taskIngest,
	"ingest-due":                  taskIngestDue,
	"process-account":             taskProcessAccount,
	"process-account-plugins":     taskProcessAccountPlugins,
	"anomalies-detection":         taskAnomaliesDetection,
	"check-user-entitlement":      taskCheckEntitlement,
	"generate-spreadsheet":        taskSpreadsheet,
	"generate-tags-spreadsheet":   taskTagsSpreadsheet,
	"generate-master-spreadsheet": taskMasterSpreadsheet,
	"update-aws-identity":         taskUpdateAwsIdentity,
	"check-cost":                  taskCheckCost,
	"fetch-pricings":              taskFetchPricings,
	"ingest-limit":                taskIngestLimit,
	"update-tags":                 taskUpdateTags,
	"update-most-used-tags":       taskUpdateMostUsedTags,
	"update-tagging-compliance":   taskUpdateTaggingCompliance,
}

// dockerHostnameRe matches the value of the HOSTNAME environment variable when
// generated by Docker from the container ID.
var dockerHostnameRe = regexp.MustCompile(`[0-9a-z]{12}`)

func main() {
	ctx := context.Background()
	logger := jsonlog.DefaultLogger
	logger.Info("Started.", struct {
		BackendId string `json:"backendId"`
	}{backendId})
	if task, ok := tasks[config.Task]; ok {
		task(ctx)
	} else {
		knownTasks := make([]string, 0, len(tasks))
		for k := range tasks {
			knownTasks = append(knownTasks, k)
		}
		logger.Error("Unknown task.", map[string]interface{}{
			"knownTasks": knownTasks,
			"chosen":     config.Task,
		})
	}
}

var sched periodic.Scheduler

func schedulePeriodicTasks() {
	sched.Register(taskIngestDue, 10*time.Minute, "ingest-due-updates")
	sched.Start()
}

func taskServer(ctx context.Context) error {
	logger := jsonlog.LoggerFromContextOrDefault(ctx)
	initializeHandlers()
	if config.Periodics {
		schedulePeriodicTasks()
		logger.Info("Scheduled periodic tasks.", nil)
	}
	logger.Info(fmt.Sprintf("Listening on %s.", config.HttpAddress), nil)
	err := http.ListenAndServe(config.HttpAddress, nil)
	logger.Error("Server stopped.", err.Error())
	return err
}

// initializeHandlers sets the HTTP server up with handler functions.
func initializeHandlers() {
	globalDecorators := []routes.Decorator{
		routes.RequestId{},
		routes.RouteLog{},
		routes.BackendId{backendId},
		routes.ErrorBody{},
		//routes.PanicAsError{},
		routes.Cors{
			AllowCredentials: true,
			AllowHeaders:     []string{"Content-Type", "Accept", "Authorization", "Cache-Status", "Cache-Error"},
			AllowOrigin:      []string{"*"},
		},
	}
	logger := jsonlog.DefaultLogger
	routes.DocumentationHandler().Register("/docs")
	for _, rh := range routes.RegisteredHandlers {
		applyDecoratorsAndHandle(rh.Pattern, rh.Handler, globalDecorators)
		logger.Info(fmt.Sprintf("Registered route %s.", rh.Pattern), nil)
	}
}

// applyDecoratorsAndHandle applies a list of decorators to a handler and
// registers it.
func applyDecoratorsAndHandle(p string, h routes.Handler, ds []routes.Decorator) {
	h = h.With(ds...)
	http.Handle(p, h)
}

// getBackendId returns an ID unique to the current process. It can also be set
// in the config to a determined string. It contains the build number.
func getBackendId() string {
	if config.BackendId != "" {
		return config.BackendId
	} else if hostname := os.Getenv("HOSTNAME"); dockerHostnameRe.Match([]byte(hostname)) {
		return fmt.Sprintf("%s-%s", hostname, buildNumber)
	} else {
		return fmt.Sprintf("%s-%s", uuid.NewV1().String(), buildNumber)
	}
}
<commit_msg>Removing resourcesTagging to server.go import<commit_after>//   Copyright 2017 MSolution.IO
//
//   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 main

import (
	"context"
	"fmt"
	"net/http"
	"os"
	"regexp"
	"time"

	uuid "github.com/satori/go.uuid"
	"github.com/trackit/jsonlog"

	_ "github.com/trackit/trackit/aws"
	_ "github.com/trackit/trackit/aws/routes"
	_ "github.com/trackit/trackit/aws/s3"
	"github.com/trackit/trackit/config"
	_ "github.com/trackit/trackit/costs"
	_ "github.com/trackit/trackit/costs/anomalies"
	_ "github.com/trackit/trackit/costs/diff"
	_ "github.com/trackit/trackit/costs/tags"
	"github.com/trackit/trackit/periodic"
	_ "github.com/trackit/trackit/plugins"
	_ "github.com/trackit/trackit/reports"
	"github.com/trackit/trackit/routes"
	_ "github.com/trackit/trackit/s3/costs"
	_ "github.com/trackit/trackit/tagging/routes"
	_ "github.com/trackit/trackit/usageReports/ec2"
	_ "github.com/trackit/trackit/usageReports/ec2Coverage"
	_ "github.com/trackit/trackit/usageReports/elasticache"
	_ "github.com/trackit/trackit/usageReports/es"
	_ "github.com/trackit/trackit/usageReports/lambda"
	_ "github.com/trackit/trackit/usageReports/rds"
	_ "github.com/trackit/trackit/usageReports/riEc2"
	_ "github.com/trackit/trackit/usageReports/riRds"
	_ "github.com/trackit/trackit/users"
	_ "github.com/trackit/trackit/users/shared_account"
)

var buildNumber string = "unknown-build"
var backendId = getBackendId()

func init() {
	jsonlog.DefaultLogger = jsonlog.DefaultLogger.WithLogLevel(jsonlog.LogLevelDebug)
}

var tasks = map[string]func(context.Context) error{
	"server":                      taskServer,
	"ingest":                      taskIngest,
	"ingest-due":                  taskIngestDue,
	"process-account":             taskProcessAccount,
	"process-account-plugins":     taskProcessAccountPlugins,
	"anomalies-detection":         taskAnomaliesDetection,
	"check-user-entitlement":      taskCheckEntitlement,
	"generate-spreadsheet":        taskSpreadsheet,
	"generate-tags-spreadsheet":   taskTagsSpreadsheet,
	"generate-master-spreadsheet": taskMasterSpreadsheet,
	"update-aws-identity":         taskUpdateAwsIdentity,
	"check-cost":                  taskCheckCost,
	"fetch-pricings":              taskFetchPricings,
	"ingest-limit":                taskIngestLimit,
	"update-tags":                 taskUpdateTags,
	"update-most-used-tags":       taskUpdateMostUsedTags,
	"update-tagging-compliance":   taskUpdateTaggingCompliance,
}

// dockerHostnameRe matches the value of the HOSTNAME environment variable when
// generated by Docker from the container ID.
var dockerHostnameRe = regexp.MustCompile(`[0-9a-z]{12}`)

func main() {
	ctx := context.Background()
	logger := jsonlog.DefaultLogger
	logger.Info("Started.", struct {
		BackendId string `json:"backendId"`
	}{backendId})
	if task, ok := tasks[config.Task]; ok {
		task(ctx)
	} else {
		knownTasks := make([]string, 0, len(tasks))
		for k := range tasks {
			knownTasks = append(knownTasks, k)
		}
		logger.Error("Unknown task.", map[string]interface{}{
			"knownTasks": knownTasks,
			"chosen":     config.Task,
		})
	}
}

var sched periodic.Scheduler

func schedulePeriodicTasks() {
	sched.Register(taskIngestDue, 10*time.Minute, "ingest-due-updates")
	sched.Start()
}

func taskServer(ctx context.Context) error {
	logger := jsonlog.LoggerFromContextOrDefault(ctx)
	initializeHandlers()
	if config.Periodics {
		schedulePeriodicTasks()
		logger.Info("Scheduled periodic tasks.", nil)
	}
	logger.Info(fmt.Sprintf("Listening on %s.", config.HttpAddress), nil)
	err := http.ListenAndServe(config.HttpAddress, nil)
	logger.Error("Server stopped.", err.Error())
	return err
}

// initializeHandlers sets the HTTP server up with handler functions.
func initializeHandlers() {
	globalDecorators := []routes.Decorator{
		routes.RequestId{},
		routes.RouteLog{},
		routes.BackendId{backendId},
		routes.ErrorBody{},
		//routes.PanicAsError{},
		routes.Cors{
			AllowCredentials: true,
			AllowHeaders:     []string{"Content-Type", "Accept", "Authorization", "Cache-Status", "Cache-Error"},
			AllowOrigin:      []string{"*"},
		},
	}
	logger := jsonlog.DefaultLogger
	routes.DocumentationHandler().Register("/docs")
	for _, rh := range routes.RegisteredHandlers {
		applyDecoratorsAndHandle(rh.Pattern, rh.Handler, globalDecorators)
		logger.Info(fmt.Sprintf("Registered route %s.", rh.Pattern), nil)
	}
}

// applyDecoratorsAndHandle applies a list of decorators to a handler and
// registers it.
func applyDecoratorsAndHandle(p string, h routes.Handler, ds []routes.Decorator) {
	h = h.With(ds...)
	http.Handle(p, h)
}

// getBackendId returns an ID unique to the current process. It can also be set
// in the config to a determined string. It contains the build number.
func getBackendId() string {
	if config.BackendId != "" {
		return config.BackendId
	} else if hostname := os.Getenv("HOSTNAME"); dockerHostnameRe.Match([]byte(hostname)) {
		return fmt.Sprintf("%s-%s", hostname, buildNumber)
	} else {
		return fmt.Sprintf("%s-%s", uuid.NewV1().String(), buildNumber)
	}
}
<|endoftext|>


<commit_before>package server

import (
    "strconv"
    "time"
    "github.com/kataras/iris"
    "github.com/BluePecker/JwtAuth/server/router"
    "github.com/Sirupsen/logrus"
    "github.com/kataras/iris/context"
)

type (
    Server struct {
        App *iris.Application
    }
)

func (Api *Server) AddRouter(routers... router.Router) {
    for _, route := range routers {
        route.Routes(Api.App)
    }
}

func (Api *Server) Run(runner iris.Runner) error {
    Api.App = iris.New()
    Options := iris.WithConfiguration(iris.Configuration{
        DisableStartupLog: true,
    })
    Api.App.Use(func(ctx context.Context) {
        start := time.Now()
        ctx.Next()
        logrus.Infof("%v %4v %s %s %s", strconv.Itoa(ctx.GetStatusCode()), time.Now().Sub(start), ctx.RemoteAddr(), ctx.Method(), ctx.Path())
    })
    return Api.App.Run(runner, Options)
}<commit_msg>debug<commit_after>package server

import (
    "strconv"
    "time"
    "github.com/kataras/iris"
    "github.com/BluePecker/JwtAuth/server/router"
    "github.com/Sirupsen/logrus"
    "github.com/kataras/iris/context"
)

type (
    Server struct {
        App *iris.Application
    }
)

func (Api *Server) AddRouter(routers... router.Router) {
    for _, route := range routers {
        route.Routes(Api.App)
    }
}

func (Api *Server) Run(runner iris.Runner) error {
    Api.App = iris.New()
    Options := iris.WithConfiguration(iris.Configuration{
        //DisableStartupLog: true,
    })
    Api.App.Use(func(ctx context.Context) {
        start := time.Now()
        ctx.Next()
        logrus.Infof("%v %4v %s %s %s", strconv.Itoa(ctx.GetStatusCode()), time.Now().Sub(start), ctx.RemoteAddr(), ctx.Method(), ctx.Path())
    })
    return Api.App.Run(runner, Options)
}<|endoftext|>


<commit_before>package main

import (
	"crypto/rand"
	"crypto/rsa"
	"crypto/x509"
	"encoding/pem"
	"fmt"
	"os"
	"strings"
	"time"

	"github.com/blackjack/syslog"
	"golang.org/x/crypto/ssh"
)

var (
	AUTHKEYSFILE string = os.Getenv("HOME") + "/.ssh/authorized_keys"
	CLIENT       string = os.Getenv("SSH_CLIENT")
)

func Debug(format string, a ...interface{}) {
	syslog.Syslogf(syslog.LOG_NOTICE, format, a...)
}

func Log(format string, a ...interface{}) {
	syslog.Syslogf(syslog.LOG_NOTICE, format, a...)
}

func Warn(format string, a ...interface{}) {
	syslog.Syslogf(syslog.LOG_WARNING, format, a...)
}

func syntaxError() {
	fmt.Println("ERROR")
	os.Exit(1)
}

func netskelDB() {
	fmt.Println("Moo")
	os.Exit(0)
}

func fingerprint(method, filename string) {
	hash := "THISISAHASH"

	fmt.Println(hash)
}

func addKey(hostname string) {
	servername, err := os.Hostname()
	now := time.Now().Format("Mon Jan _2 15:04:05 2006")

	privateKey, err := rsa.GenerateKey(rand.Reader, 2048)
	if err != nil {
		Warn("Error generating private key: %v", err)
		os.Exit(1)
	}
	privateKeyPEM := &pem.Block{Type: "RSA PRIVATE KEY", Bytes: x509.MarshalPKCS1PrivateKey(privateKey)}
	pemdata := pem.EncodeToMemory(privateKeyPEM)

	pub, err := ssh.NewPublicKey(&privateKey.PublicKey)
	if err != nil {
		Warn("Error constructing public key: %v", err)
		os.Exit(1)
	}
	pubdata := strings.TrimSpace(string(ssh.MarshalAuthorizedKey(pub)))

	Debug("Appending %d byte public key to %s for %s (%v)", len(pubdata), AUTHKEYSFILE, hostname, CLIENT)

	f, err := os.OpenFile(AUTHKEYSFILE, os.O_APPEND|os.O_WRONLY, 0600)
	if err != nil {
		Warn("Error writing public key: %v", err)
		os.Exit(1)
	}

	defer f.Close()

	if _, err = f.WriteString("restrict " + pubdata + " " + hostname + " " + now + "\n"); err != nil {
		panic(err)
	}

	fmt.Printf("#\n# Netskel private key generated by %v for %v (%v)\n#\n", servername, hostname, CLIENT)
	fmt.Println(string(pemdata))
	//fmt.Println("-- ")
	//fmt.Println(string(pubdata))

	os.Exit(0)
}

func main() {
	syslog.Openlog("netskel-server", syslog.LOG_PID, syslog.LOG_USER)

	if os.Args[0] != "server" {
		syntaxError()
	}

	nsCommand := strings.Split(os.Args[2], " ")
	command := nsCommand[0]

	Log("netskel-server launched for %v with %v", CLIENT, nsCommand)

	//for index, arg := range nsCommand {
	//	fmt.Printf("%2d: %v\n", index, arg)
	//}

	switch command {
	case "netskeldb":
		netskelDB()

	case "sha1":
		filename := nsCommand[1]
		fingerprint("sha1", filename)

	case "addkey":
		key := nsCommand[1]
		addKey(key)

	default:
		syntaxError()
	}

	os.Exit(0)
}
<commit_msg>First pass at netskeldb production<commit_after>package main

import (
	"crypto/md5"
	"crypto/rand"
	"crypto/rsa"
	"crypto/x509"
	"encoding/pem"
	"fmt"
	"io"
	"io/ioutil"
	"os"
	"strings"
	"time"

	"github.com/blackjack/syslog"
	"golang.org/x/crypto/ssh"
)

var (
	AUTHKEYSFILE string = os.Getenv("HOME") + "/.ssh/authorized_keys"
	CLIENT       string = os.Getenv("SSH_CLIENT")
)

func Debug(format string, a ...interface{}) {
	syslog.Syslogf(syslog.LOG_NOTICE, format, a...)
}

func Log(format string, a ...interface{}) {
	syslog.Syslogf(syslog.LOG_NOTICE, format, a...)
}

func Warn(format string, a ...interface{}) {
	syslog.Syslogf(syslog.LOG_WARNING, format, a...)
}

func syntaxError() {
	fmt.Println("ERROR")
	os.Exit(1)
}

func dbFileLine(filename string) {
	file, err := os.Stat(filename)
	if err != nil {
		Warn("Error Stat %v: %v", filename, err)
		return
	}

	trimmed := strings.TrimPrefix(filename, "./")

	hash, _ := fingerprint(filename)

	fmt.Printf("%s\t%o\t*\t%d\t%x\n", trimmed, file.Mode(), file.Size(), hash)
}

func listDir(dirname string) {
	files, err := ioutil.ReadDir(dirname)
	if err != nil {
		Warn("Error reading directory %v", dirname)
		return
	}

	for _, file := range files {
		if file.Name() == ".git" {
			continue
		}

		fullname := dirname + "/" + file.Name()

		switch mode := file.Mode(); {
		case mode.IsDir():
			trimmed := strings.TrimPrefix(fullname, "./")
			fmt.Printf("%s\t%d\t*\n", trimmed, 700)
			listDir(fullname)
		case mode.IsRegular():
			dbFileLine(fullname)
		}
	}
}

func netskelDB() {
	servername, _ := os.Hostname()
	now := time.Now().Format("Mon, 2 Jan 2006 15:04:05 UTC")

	os.Chdir("db")

	fmt.Printf("#\n# .netskeldb for %v\n#\n# Generated %v by %v\n#\n", CLIENT, now, servername)

	listDir(".")

	os.Exit(0)
}

func fingerprint(filename string) ([]byte, error) {
	var result []byte

	file, err := os.Open(filename)
	if err != nil {
		return result, err
	}
	defer file.Close()

	hash := md5.New()
	if _, err := io.Copy(hash, file); err != nil {
		return result, err
	}

	return hash.Sum(result), nil
}

func addKey(hostname string) {
	servername, err := os.Hostname()
	now := time.Now().Format("Mon Jan _2 15:04:05 2006")

	privateKey, err := rsa.GenerateKey(rand.Reader, 2048)
	if err != nil {
		Warn("Error generating private key: %v", err)
		os.Exit(1)
	}
	privateKeyPEM := &pem.Block{Type: "RSA PRIVATE KEY", Bytes: x509.MarshalPKCS1PrivateKey(privateKey)}
	pemdata := pem.EncodeToMemory(privateKeyPEM)

	pub, err := ssh.NewPublicKey(&privateKey.PublicKey)
	if err != nil {
		Warn("Error constructing public key: %v", err)
		os.Exit(1)
	}
	pubdata := strings.TrimSpace(string(ssh.MarshalAuthorizedKey(pub)))

	Debug("Appending %d byte public key to %s for %s (%v)", len(pubdata), AUTHKEYSFILE, hostname, CLIENT)

	f, err := os.OpenFile(AUTHKEYSFILE, os.O_APPEND|os.O_WRONLY, 0600)
	if err != nil {
		Warn("Error writing public key: %v", err)
		os.Exit(1)
	}

	defer f.Close()

	if _, err = f.WriteString("restrict " + pubdata + " " + hostname + " " + now + "\n"); err != nil {
		panic(err)
	}

	fmt.Printf("#\n# Netskel private key generated by %v for %v (%v)\n#\n", servername, hostname, CLIENT)
	fmt.Println(string(pemdata))
	//fmt.Println("-- ")
	//fmt.Println(string(pubdata))

	os.Exit(0)
}

func main() {
	syslog.Openlog("netskel-server", syslog.LOG_PID, syslog.LOG_USER)

	if os.Args[0] != "server" {
		syntaxError()
	}

	nsCommand := strings.Split(os.Args[2], " ")
	command := nsCommand[0]

	Log("netskel-server launched for %v with %v", CLIENT, nsCommand)

	//for index, arg := range nsCommand {
	//	fmt.Printf("%2d: %v\n", index, arg)
	//}

	switch command {
	case "netskeldb":
		netskelDB()

	case "sha1":
		filename := nsCommand[1]
		hash, _ := fingerprint(filename)
		fmt.Println(hash)

	case "addkey":
		key := nsCommand[1]
		addKey(key)

	default:
		syntaxError()
	}

	os.Exit(0)
}
<|endoftext|>