status-go/geth/jail/jail_cell.go
Ivan Tomilov ebd77aabe2 Merging bug/whisper-on-geth1.6.1 (#236) which acts like develop
* static: updates Whisper test (to work with Geth 1.6.1)
* jail: VM persistence implemented
* jail: sendMessage/showSuggestions minor fixes (to be squashed)
* node: CHT and boot nodes auto-load implemented
* Replaced CHT data file from farazdagi's to tiabc's
* Rewrote config_test.go using testify having reduced it twice in size
* Increased SyncTime and panic timeout in tests
* Fixed test - remove go default test to testify/suite (#207)
* Add flag setup for RPCEnabled and add comment (#225)
* jail: register method handlers before running initial js in jail (#226)
* Console Jail Mod #179 (#228)
* Added ./statusd-data into .gitignore
* Increased log level for the test node from INFO to ERROR
* Add call to loop.Run to evaluate all setTimeout/setIntervals methods. (#208)
* Rebase onto geth1.6.7 (#232)
* Got back sync duration from 60s to 30s, updated bindata.go
2017-08-04 23:14:17 +07:00

140 lines
3.4 KiB
Go

package jail
import (
"sync"
"fknsrs.biz/p/ottoext/fetch"
"fknsrs.biz/p/ottoext/loop"
"fknsrs.biz/p/ottoext/timers"
"github.com/robertkrimen/otto"
)
const (
// JailCellRequestTimeout seconds before jailed request times out.
JailCellRequestTimeout = 60
)
// JailCell represents single jail cell, which is basically a JavaScript VM.
// TODO(influx6): Rename JailCell to Cell in next refactoring phase.
type JailCell struct {
sync.Mutex
id string
vm *otto.Otto
lo *loop.Loop
}
// newJailCell encapsulates what we need to create a new jailCell from the
// provided vm and eventloop instance.
func newJailCell(id string, vm *otto.Otto, lo *loop.Loop) (*JailCell, error) {
// Register fetch provider from ottoext.
if err := fetch.Define(vm, lo); err != nil {
return nil, err
}
// Register event loop for timers.
if err := timers.Define(vm, lo); err != nil {
return nil, err
}
return &JailCell{
id: id,
vm: vm,
lo: lo,
}, nil
}
// Fetch attempts to call the underline Fetch API added through the
// ottoext package.
func (cell *JailCell) Fetch(url string, callback func(otto.Value)) (otto.Value, error) {
val, err := cell.prepareFetchCall(url, callback)
if err != nil {
return val, err
}
return val, cell.lo.Run()
}
// prepareFetchCall prepares the needed calls to hook into the vm to receive the expected response
// for a call to the FetchAPI. We need this to ensure confidence in mutex locking and unlocking.
func (cell *JailCell) prepareFetchCall(url string, callback func(otto.Value)) (otto.Value, error) {
cell.Lock()
defer cell.Unlock()
if err := cell.vm.Set("__captureFetch", callback); err != nil {
return otto.UndefinedValue(), err
}
return cell.vm.Run(`fetch("` + url + `").then(function(response){
__captureFetch({
"url": response.url,
"type": response.type,
"body": response.text(),
"status": response.status,
"headers": response.headers,
});
});
`)
}
// Set sets the value to be keyed by the provided keyname.
func (cell *JailCell) Set(key string, val interface{}) error {
cell.Lock()
defer cell.Unlock()
return cell.vm.Set(key, val)
}
// Get returns the giving key's otto.Value from the underline otto vm.
func (cell *JailCell) Get(key string) (otto.Value, error) {
cell.Lock()
defer cell.Unlock()
return cell.vm.Get(key)
}
// RunOnLoop evaluates the giving js string on the associated vm loop returning
// an error.
func (cell *JailCell) RunOnLoop(val string) (otto.Value, error) {
cell.Lock()
defer cell.Unlock()
res, err := cell.vm.Run(val)
if err != nil {
return res, err
}
return res, cell.lo.Run()
}
// CallOnLoop attempts to call the internal call function for the giving response associated with the
// proper values.
func (cell *JailCell) CallOnLoop(item string, this interface{}, args ...interface{}) (otto.Value, error) {
cell.Lock()
defer cell.Unlock()
res, err := cell.vm.Call(item, this, args...)
if err != nil {
return res, err
}
return res, cell.lo.Run()
}
// Call attempts to call the internal call function for the giving response associated with the
// proper values.
func (cell *JailCell) Call(item string, this interface{}, args ...interface{}) (otto.Value, error) {
cell.Lock()
defer cell.Unlock()
return cell.vm.Call(item, this, args...)
}
// Run evaluates the giving js string on the associated vm llop.
func (cell *JailCell) Run(val string) (otto.Value, error) {
cell.Lock()
defer cell.Unlock()
return cell.vm.Run(val)
}