server.go 2.37 KB
Newer Older
1 2 3
package main

import (
obscuren's avatar
obscuren committed
4 5 6
	"container/list"
	"github.com/ethereum/ethdb-go"
	"github.com/ethereum/ethutil-go"
obscuren's avatar
obscuren committed
7
	"github.com/ethereum/ethwire-go"
obscuren's avatar
obscuren committed
8 9
	"log"
	"net"
obscuren's avatar
obscuren committed
10
	"time"
11 12 13
)

type Server struct {
obscuren's avatar
obscuren committed
14 15 16
	// Channel for shutting down the server
	shutdownChan chan bool
	// DB interface
obscuren's avatar
obscuren committed
17 18
	//db *ethdb.LDBDatabase
	db *ethdb.MemDatabase
obscuren's avatar
obscuren committed
19 20 21 22
	// Block manager for processing new blocks and managing the block chain
	blockManager *BlockManager
	// Peers (NYI)
	peers *list.List
obscuren's avatar
obscuren committed
23 24
	// Nonce
	Nonce uint64
25 26 27
}

func NewServer() (*Server, error) {
obscuren's avatar
obscuren committed
28 29
	//db, err := ethdb.NewLDBDatabase()
	db, err := ethdb.NewMemDatabase()
obscuren's avatar
obscuren committed
30 31 32
	if err != nil {
		return nil, err
	}
33

obscuren's avatar
obscuren committed
34
	ethutil.SetConfig(db)
obscuren's avatar
obscuren committed
35

obscuren's avatar
obscuren committed
36
	nonce, _ := ethutil.RandomUint64()
obscuren's avatar
obscuren committed
37 38 39 40 41
	server := &Server{
		shutdownChan: make(chan bool),
		blockManager: NewBlockManager(),
		db:           db,
		peers:        list.New(),
obscuren's avatar
obscuren committed
42
		Nonce:        nonce,
obscuren's avatar
obscuren committed
43
	}
44

obscuren's avatar
obscuren committed
45
	return server, nil
46 47
}

obscuren's avatar
obscuren committed
48
func (s *Server) AddPeer(conn net.Conn) {
obscuren's avatar
obscuren committed
49 50 51 52 53
	peer := NewPeer(conn, s, true)

	if peer != nil {
		s.peers.PushBack(peer)
		peer.Start()
54

obscuren's avatar
obscuren committed
55 56
		log.Println("Peer connected ::", conn.RemoteAddr())
	}
57 58 59
}

func (s *Server) ConnectToPeer(addr string) error {
obscuren's avatar
obscuren committed
60
	conn, err := net.Dial("tcp", addr)
61

obscuren's avatar
obscuren committed
62 63 64
	if err != nil {
		return err
	}
65

obscuren's avatar
obscuren committed
66
	peer := NewPeer(conn, s, false)
obscuren's avatar
obscuren committed
67 68
	s.peers.PushBack(peer)
	peer.Start()
69

obscuren's avatar
obscuren committed
70
	log.Println("Connected to peer ::", conn.RemoteAddr())
71

obscuren's avatar
obscuren committed
72
	return nil
73 74 75
}

func (s *Server) Broadcast(msgType string, data []byte) {
obscuren's avatar
obscuren committed
76 77
	for e := s.peers.Front(); e != nil; e = e.Next() {
		if peer, ok := e.Value.(*Peer); ok {
obscuren's avatar
obscuren committed
78
			peer.QueueMessage(ethwire.NewMessage(msgType, 0, data))
obscuren's avatar
obscuren committed
79 80
		}
	}
obscuren's avatar
obscuren committed
81 82
}

83 84
// Start the server
func (s *Server) Start() {
obscuren's avatar
obscuren committed
85 86 87 88 89 90 91 92 93 94 95
	// For now this function just blocks the main thread
	ln, err := net.Listen("tcp", ":12345")
	if err != nil {
		log.Fatal(err)
	}

	go func() {
		for {
			conn, err := ln.Accept()
			if err != nil {
				log.Println(err)
obscuren's avatar
obscuren committed
96

obscuren's avatar
obscuren committed
97 98 99 100 101 102 103 104
				continue
			}

			go s.AddPeer(conn)
		}
	}()

	// TMP
obscuren's avatar
obscuren committed
105 106 107 108 109 110 111
	go func() {
		for {
			s.Broadcast("block", s.blockManager.bc.GenesisBlock().MarshalRlp())

			time.Sleep(1000 * time.Millisecond)
		}
	}()
112 113 114
}

func (s *Server) Stop() {
obscuren's avatar
obscuren committed
115 116
	// Close the database
	defer s.db.Close()
117

obscuren's avatar
obscuren committed
118 119 120 121 122 123
	// Loop thru the peers and close them (if we had them)
	for e := s.peers.Front(); e != nil; e = e.Next() {
		if peer, ok := e.Value.(*Peer); ok {
			peer.Stop()
		}
	}
124

obscuren's avatar
obscuren committed
125
	s.shutdownChan <- true
126 127 128 129
}

// This function will wait for a shutdown and resumes main thread execution
func (s *Server) WaitForShutdown() {
obscuren's avatar
obscuren committed
130
	<-s.shutdownChan
131
}