good morning!!!!

Skip to content
Snippets Groups Projects
Commit 3af211dd authored by Jeffrey Wilcke's avatar Jeffrey Wilcke
Browse files

Implemented WebSocket package

parent ab6ede51
Branches
Tags
No related merge requests found
......@@ -11,7 +11,6 @@ import (
"github.com/ethereum/eth-go/ethchain"
"github.com/ethereum/eth-go/ethlog"
"github.com/ethereum/eth-go/ethutil"
"github.com/ethereum/eth-go/ethwire"
)
var poollogger = ethlog.NewLogger("BPOOL")
......@@ -99,8 +98,8 @@ func (self *BlockPool) Add(b *ethchain.Block, peer *Peer) {
self.pool[hash] = &block{peer, peer, b, time.Now(), 0}
if !self.eth.BlockChain().HasBlock(b.PrevHash) && !self.fetchingHashes {
poollogger.Infof("Unknown block, requesting parent (%x...)\n", b.PrevHash[0:4])
peer.QueueMessage(ethwire.NewMessage(ethwire.MsgGetBlockHashesTy, []interface{}{b.PrevHash, uint32(256)}))
//poollogger.Infof("Unknown block, requesting parent (%x...)\n", b.PrevHash[0:4])
//peer.QueueMessage(ethwire.NewMessage(ethwire.MsgGetBlockHashesTy, []interface{}{b.PrevHash, uint32(256)}))
}
} else if self.pool[hash] != nil {
self.pool[hash].block = b
......
......@@ -142,14 +142,12 @@ func (self *StateTransition) preCheck() (err error) {
func (self *StateTransition) TransitionState() (err error) {
statelogger.Debugf("(~) %x\n", self.tx.Hash())
/*
defer func() {
if r := recover(); r != nil {
logger.Infoln(r)
statelogger.Infoln(r)
err = fmt.Errorf("state transition err %v", r)
}
}()
*/
// XXX Transactions after this point are considered valid.
if err = self.preCheck(); err != nil {
......
......@@ -320,7 +320,7 @@ out:
case msg := <-p.outputQueue:
if !p.statusKnown {
switch msg.Type {
case ethwire.MsgStatusTy, ethwire.MsgGetTxsTy, ethwire.MsgTxTy, ethwire.MsgGetBlockHashesTy, ethwire.MsgBlockHashesTy, ethwire.MsgGetBlocksTy, ethwire.MsgBlockTy:
case ethwire.MsgGetTxsTy, ethwire.MsgTxTy, ethwire.MsgGetBlockHashesTy, ethwire.MsgBlockHashesTy, ethwire.MsgGetBlocksTy, ethwire.MsgBlockTy:
break skip
}
}
......
package websocket
import (
"fmt"
"io"
ws "code.google.com/p/go.net/websocket"
)
const channelBufSize = 100
var maxId int = 0
type MsgFunc func(c *Client, msg *Message)
// Chat client.
type Client struct {
id int
ws *ws.Conn
server *Server
ch chan *Message
doneCh chan bool
onMessage MsgFunc
}
// Create new chat client.
func NewClient(ws *ws.Conn, server *Server) *Client {
if ws == nil {
panic("ws cannot be nil")
}
if server == nil {
panic("server cannot be nil")
}
maxId++
ch := make(chan *Message, channelBufSize)
doneCh := make(chan bool)
return &Client{maxId, ws, server, ch, doneCh, nil}
}
func (c *Client) Id() int {
return c.id
}
func (c *Client) Conn() *ws.Conn {
return c.ws
}
func (c *Client) Write(data interface{}, seed int) {
msg := &Message{Seed: seed, Data: data}
select {
case c.ch <- msg:
default:
c.server.Del(c)
err := fmt.Errorf("client %d is disconnected.", c.id)
c.server.Err(err)
}
}
func (c *Client) Done() {
c.doneCh <- true
}
// Listen Write and Read request via chanel
func (c *Client) Listen() {
go c.listenWrite()
c.listenRead()
}
// Listen write request via chanel
func (c *Client) listenWrite() {
logger.Debugln("Listening write to client")
for {
select {
// send message to the client
case msg := <-c.ch:
logger.Debugln("Send:", msg)
ws.JSON.Send(c.ws, msg)
// receive done request
case <-c.doneCh:
c.server.Del(c)
c.doneCh <- true // for listenRead method
return
}
}
}
// Listen read request via chanel
func (c *Client) listenRead() {
logger.Debugln("Listening read from client")
for {
select {
// receive done request
case <-c.doneCh:
c.server.Del(c)
c.doneCh <- true // for listenWrite method
return
// read data from ws connection
default:
var msg Message
err := ws.JSON.Receive(c.ws, &msg)
if err == io.EOF {
c.doneCh <- true
} else if err != nil {
c.server.Err(err)
} else {
logger.Debugln(&msg)
if c.onMessage != nil {
c.onMessage(c, &msg)
}
}
}
}
}
package websocket
import "github.com/ethereum/eth-go/ethutil"
type Message struct {
Call string `json:"call"`
Args []interface{} `json:"args"`
Seed int `json:"seed"`
Data interface{} `json:"data"`
}
func (self *Message) Arguments() *ethutil.Value {
return ethutil.NewValue(self.Args)
}
package websocket
import (
"net/http"
"github.com/ethereum/eth-go/ethlog"
ws "code.google.com/p/go.net/websocket"
)
var logger = ethlog.NewLogger("WS")
// Chat server.
type Server struct {
httpServ string
pattern string
messages []*Message
clients map[int]*Client
addCh chan *Client
delCh chan *Client
sendAllCh chan string
doneCh chan bool
errCh chan error
msgFunc MsgFunc
}
// Create new chat server.
func NewServer(pattern, httpServ string) *Server {
clients := make(map[int]*Client)
addCh := make(chan *Client)
delCh := make(chan *Client)
sendAllCh := make(chan string)
doneCh := make(chan bool)
errCh := make(chan error)
return &Server{
httpServ,
pattern,
nil,
clients,
addCh,
delCh,
sendAllCh,
doneCh,
errCh,
nil,
}
}
func (s *Server) Add(c *Client) {
s.addCh <- c
}
func (s *Server) Del(c *Client) {
s.delCh <- c
}
func (s *Server) SendAll(msg string) {
s.sendAllCh <- msg
}
func (s *Server) Done() {
s.doneCh <- true
}
func (s *Server) Err(err error) {
s.errCh <- err
}
func (s *Server) servHTTP() {
logger.Debugln("Serving http", s.httpServ)
err := http.ListenAndServe(s.httpServ, nil)
logger.Warnln(err)
}
func (s *Server) MessageFunc(f MsgFunc) {
s.msgFunc = f
}
// Listen and serve.
// It serves client connection and broadcast request.
func (s *Server) Listen() {
logger.Debugln("Listening server...")
// ws handler
onConnected := func(ws *ws.Conn) {
defer func() {
err := ws.Close()
if err != nil {
s.errCh <- err
}
}()
client := NewClient(ws, s)
client.onMessage = s.msgFunc
s.Add(client)
client.Listen()
}
// Disable Origin check. Request don't need to come necessarily from origin.
http.HandleFunc(s.pattern, func(w http.ResponseWriter, req *http.Request) {
s := ws.Server{Handler: ws.Handler(onConnected)}
s.ServeHTTP(w, req)
})
logger.Debugln("Created handler")
go s.servHTTP()
for {
select {
// Add new a client
case c := <-s.addCh:
s.clients[c.id] = c
// del a client
case c := <-s.delCh:
delete(s.clients, c.id)
case err := <-s.errCh:
logger.Debugln("Error:", err.Error())
case <-s.doneCh:
return
}
}
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment