Commit 63e76482 authored by Jeffrey Wilcke's avatar Jeffrey Wilcke

Merge pull request #2140 from obscuren/rpc2-console

Rpc2 console
parents f2ab351e 19b2640e
{
"ImportPath": "github.com/ethereum/go-ethereum",
"GoVersion": "go1.4",
"GoVersion": "go1.5.2",
"Packages": [
"./..."
],
......@@ -40,10 +40,6 @@
"ImportPath": "github.com/jackpal/go-nat-pmp",
"Rev": "a45aa3d54aef73b504e15eb71bea0e5565b5e6e1"
},
{
"ImportPath": "github.com/kardianos/osext",
"Rev": "ccfcd0245381f0c94c68f50626665eed3c6b726a"
},
{
"ImportPath": "github.com/mattn/go-isatty",
"Rev": "7fcbc72f853b92b5720db4a6b8482be612daef24"
......@@ -73,10 +69,6 @@
"ImportPath": "github.com/robertkrimen/otto",
"Rev": "dea31a3d392779af358ec41f77a07fcc7e9d04ba"
},
{
"ImportPath": "github.com/rs/cors",
"Rev": "6e0c3cb65fc0fdb064c743d176a620e3ca446dfb"
},
{
"ImportPath": "github.com/shiena/ansicolor",
"Rev": "a5e2b567a4dd6cc74545b8a4f27c9d63b9e7735b"
......@@ -109,6 +101,10 @@
"ImportPath": "golang.org/x/net/html",
"Rev": "e0403b4e005737430c05a57aac078479844f919c"
},
{
"ImportPath": "golang.org/x/net/websocket",
"Rev": "e0403b4e005737430c05a57aac078479844f919c"
},
{
"ImportPath": "golang.org/x/text/encoding",
"Rev": "c93e7c9fff19fb9139b5ab04ce041833add0134e"
......
Copyright (c) 2012 The Go Authors. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the following disclaimer
in the documentation and/or other materials provided with the
distribution.
* Neither the name of Google Inc. nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
### Extensions to the "os" package.
## Find the current Executable and ExecutableFolder.
There is sometimes utility in finding the current executable file
that is running. This can be used for upgrading the current executable
or finding resources located relative to the executable file.
Multi-platform and supports:
* Linux
* OS X
* Windows
* Plan 9
* BSDs.
// Copyright 2012 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// Extensions to the standard "os" package.
package osext
import "path/filepath"
// Executable returns an absolute path that can be used to
// re-invoke the current program.
// It may not be valid after the current program exits.
func Executable() (string, error) {
p, err := executable()
return filepath.Clean(p), err
}
// Returns same path as Executable, returns just the folder
// path. Excludes the executable name.
func ExecutableFolder() (string, error) {
p, err := Executable()
if err != nil {
return "", err
}
folder, _ := filepath.Split(p)
return folder, nil
}
// Copyright 2012 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// +build linux netbsd openbsd solaris dragonfly
package osext
import (
"errors"
"fmt"
"os"
"runtime"
)
func executable() (string, error) {
switch runtime.GOOS {
case "linux":
return os.Readlink("/proc/self/exe")
case "netbsd":
return os.Readlink("/proc/curproc/exe")
case "openbsd", "dragonfly":
return os.Readlink("/proc/curproc/file")
case "solaris":
return os.Readlink(fmt.Sprintf("/proc/%d/path/a.out", os.Getpid()))
}
return "", errors.New("ExecPath not implemented for " + runtime.GOOS)
}
// Copyright 2012 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// +build darwin freebsd
package osext
import (
"os"
"path/filepath"
"runtime"
"syscall"
"unsafe"
)
var initCwd, initCwdErr = os.Getwd()
func executable() (string, error) {
var mib [4]int32
switch runtime.GOOS {
case "freebsd":
mib = [4]int32{1 /* CTL_KERN */, 14 /* KERN_PROC */, 12 /* KERN_PROC_PATHNAME */, -1}
case "darwin":
mib = [4]int32{1 /* CTL_KERN */, 38 /* KERN_PROCARGS */, int32(os.Getpid()), -1}
}
n := uintptr(0)
// Get length.
_, _, errNum := syscall.Syscall6(syscall.SYS___SYSCTL, uintptr(unsafe.Pointer(&mib[0])), 4, 0, uintptr(unsafe.Pointer(&n)), 0, 0)
if errNum != 0 {
return "", errNum
}
if n == 0 { // This shouldn't happen.
return "", nil
}
buf := make([]byte, n)
_, _, errNum = syscall.Syscall6(syscall.SYS___SYSCTL, uintptr(unsafe.Pointer(&mib[0])), 4, uintptr(unsafe.Pointer(&buf[0])), uintptr(unsafe.Pointer(&n)), 0, 0)
if errNum != 0 {
return "", errNum
}
if n == 0 { // This shouldn't happen.
return "", nil
}
for i, v := range buf {
if v == 0 {
buf = buf[:i]
break
}
}
var err error
execPath := string(buf)
// execPath will not be empty due to above checks.
// Try to get the absolute path if the execPath is not rooted.
if execPath[0] != '/' {
execPath, err = getAbs(execPath)
if err != nil {
return execPath, err
}
}
// For darwin KERN_PROCARGS may return the path to a symlink rather than the
// actual executable.
if runtime.GOOS == "darwin" {
if execPath, err = filepath.EvalSymlinks(execPath); err != nil {
return execPath, err
}
}
return execPath, nil
}
func getAbs(execPath string) (string, error) {
if initCwdErr != nil {
return execPath, initCwdErr
}
// The execPath may begin with a "../" or a "./" so clean it first.
// Join the two paths, trailing and starting slashes undetermined, so use
// the generic Join function.
return filepath.Join(initCwd, filepath.Clean(execPath)), nil
}
// Copyright 2012 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// +build darwin linux freebsd netbsd windows
package osext
import (
"fmt"
"os"
oexec "os/exec"
"path/filepath"
"runtime"
"testing"
)
const execPath_EnvVar = "OSTEST_OUTPUT_EXECPATH"
func TestExecPath(t *testing.T) {
ep, err := Executable()
if err != nil {
t.Fatalf("ExecPath failed: %v", err)
}
// we want fn to be of the form "dir/prog"
dir := filepath.Dir(filepath.Dir(ep))
fn, err := filepath.Rel(dir, ep)
if err != nil {
t.Fatalf("filepath.Rel: %v", err)
}
cmd := &oexec.Cmd{}
// make child start with a relative program path
cmd.Dir = dir
cmd.Path = fn
// forge argv[0] for child, so that we can verify we could correctly
// get real path of the executable without influenced by argv[0].
cmd.Args = []string{"-", "-test.run=XXXX"}
cmd.Env = []string{fmt.Sprintf("%s=1", execPath_EnvVar)}
out, err := cmd.CombinedOutput()
if err != nil {
t.Fatalf("exec(self) failed: %v", err)
}
outs := string(out)
if !filepath.IsAbs(outs) {
t.Fatalf("Child returned %q, want an absolute path", out)
}
if !sameFile(outs, ep) {
t.Fatalf("Child returned %q, not the same file as %q", out, ep)
}
}
func sameFile(fn1, fn2 string) bool {
fi1, err := os.Stat(fn1)
if err != nil {
return false
}
fi2, err := os.Stat(fn2)
if err != nil {
return false
}
return os.SameFile(fi1, fi2)
}
func init() {
if e := os.Getenv(execPath_EnvVar); e != "" {
// first chdir to another path
dir := "/"
if runtime.GOOS == "windows" {
dir = filepath.VolumeName(".")
}
os.Chdir(dir)
if ep, err := Executable(); err != nil {
fmt.Fprint(os.Stderr, "ERROR: ", err)
} else {
fmt.Fprint(os.Stderr, ep)
}
os.Exit(0)
}
}
// Copyright 2012 The Go 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 osext
import (
"syscall"
"unicode/utf16"
"unsafe"
)
var (
kernel = syscall.MustLoadDLL("kernel32.dll")
getModuleFileNameProc = kernel.MustFindProc("GetModuleFileNameW")
)
// GetModuleFileName() with hModule = NULL
func executable() (exePath string, err error) {
return getModuleFileName()
}
func getModuleFileName() (string, error) {
var n uint32
b := make([]uint16, syscall.MAX_PATH)
size := uint32(len(b))
r0, _, e1 := getModuleFileNameProc.Call(0, uintptr(unsafe.Pointer(&b[0])), uintptr(size))
n = uint32(r0)
if n == 0 {
return "", e1
}
return string(utf16.Decode(b[0:n])), nil
}
language: go
go:
- 1.3
- 1.4
Copyright (c) 2014 Olivier Poitrey <rs@dailymotion.com>
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is furnished
to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
# Go CORS handler [![godoc](http://img.shields.io/badge/godoc-reference-blue.svg?style=flat)](https://godoc.org/github.com/rs/cors) [![license](http://img.shields.io/badge/license-MIT-red.svg?style=flat)](https://raw.githubusercontent.com/rs/cors/master/LICENSE) [![build](https://img.shields.io/travis/rs/cors.svg?style=flat)](https://travis-ci.org/rs/cors)
CORS is a `net/http` handler implementing [Cross Origin Resource Sharing W3 specification](http://www.w3.org/TR/cors/) in Golang.
## Getting Started
After installing Go and setting up your [GOPATH](http://golang.org/doc/code.html#GOPATH), create your first `.go` file. We'll call it `server.go`.
```go
package main
import (
"net/http"
"github.com/rs/cors"
)
func main() {
h := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "application/json")
w.Write([]byte("{\"hello\": \"world\"}"))
})
// cors.Default() setup the middleware with default options being
// all origins accepted with simple methods (GET, POST). See
// documentation below for more options.
handler = cors.Default().Handler(h)
http.ListenAndServe(":8080", handler)
}
```
Install `cors`:
go get github.com/rs/cors
Then run your server:
go run server.go
The server now runs on `localhost:8080`:
$ curl -D - -H 'Origin: http://foo.com' http://localhost:8080/
HTTP/1.1 200 OK
Access-Control-Allow-Origin: foo.com
Content-Type: application/json
Date: Sat, 25 Oct 2014 03:43:57 GMT
Content-Length: 18
{"hello": "world"}
### More Examples
* `net/http`: [examples/nethttp/server.go](https://github.com/rs/cors/blob/master/examples/nethttp/server.go)
* [Goji](https://goji.io): [examples/goji/server.go](https://github.com/rs/cors/blob/master/examples/goji/server.go)
* [Martini](http://martini.codegangsta.io): [examples/martini/server.go](https://github.com/rs/cors/blob/master/examples/martini/server.go)
* [Negroni](https://github.com/codegangsta/negroni): [examples/negroni/server.go](https://github.com/rs/cors/blob/master/examples/negroni/server.go)
* [Alice](https://github.com/justinas/alice): [examples/alice/server.go](https://github.com/rs/cors/blob/master/examples/alice/server.go)
## Parameters
Parameters are passed to the middleware thru the `cors.New` method as follow:
```go
c := cors.New(cors.Options{
AllowedOrigins: []string{"http://foo.com"},
AllowCredentials: true,
})
// Insert the middleware
handler = c.Handler(handler)
```
* **AllowedOrigins** `[]string`: A list of origins a cross-domain request can be executed from. If the special `*` value is present in the list, all origins will be allowed. The default value is `*`.
* **AllowedMethods** `[]string`: A list of methods the client is allowed to use with cross-domain requests.
* **AllowedHeaders** `[]string`: A list of non simple headers the client is allowed to use with cross-domain requests. Default value is simple methods (`GET` and `POST`)
* **ExposedHeaders** `[]string`: Indicates which headers are safe to expose to the API of a CORS API specification
* **AllowCredentials** `bool`: Indicates whether the request can include user credentials like cookies, HTTP authentication or client side SSL certificates. The default is `false`.
* **MaxAge** `int`: Indicates how long (in seconds) the results of a preflight request can be cached. The default is `0` which stands for no max age.
See [API documentation](http://godoc.org/github.com/rs/cors) for more info.
## Licenses
All source code is licensed under the [MIT License](https://raw.github.com/rs/cors/master/LICENSE).
package cors
import (
"net/http"
"net/http/httptest"
"testing"
)
func BenchmarkWithout(b *testing.B) {
res := httptest.NewRecorder()
req, _ := http.NewRequest("GET", "http://example.com/foo", nil)
for i := 0; i < b.N; i++ {
testHandler.ServeHTTP(res, req)
}
}
func BenchmarkDefault(b *testing.B) {
res := httptest.NewRecorder()
req, _ := http.NewRequest("GET", "http://example.com/foo", nil)
handler := Default()
for i := 0; i < b.N; i++ {
handler.Handler(testHandler).ServeHTTP(res, req)
}
}
func BenchmarkPreflight(b *testing.B) {
res := httptest.NewRecorder()
req, _ := http.NewRequest("OPTIONS", "http://example.com/foo", nil)
req.Header.Add("Access-Control-Request-Method", "GET")
handler := Default()
for i := 0; i < b.N; i++ {
handler.Handler(testHandler).ServeHTTP(res, req)
}
}
This diff is collapsed.
package cors
import (
"net/http"
"net/http/httptest"
"testing"
)
var testHandler = http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.Write([]byte("bar"))
})
func assertHeaders(t *testing.T, resHeaders http.Header, reqHeaders map[string]string) {
for name, value := range reqHeaders {
if resHeaders.Get(name) != value {
t.Errorf("Invalid header `%s', wanted `%s', got `%s'", name, value, resHeaders.Get(name))
}
}
}
func TestNoConfig(t *testing.T) {
s := New(Options{
// Intentionally left blank.
})
res := httptest.NewRecorder()
req, _ := http.NewRequest("GET", "http://example.com/foo", nil)
s.Handler(testHandler).ServeHTTP(res, req)
assertHeaders(t, res.Header(), map[string]string{
"Access-Control-Allow-Origin": "",
"Access-Control-Allow-Methods": "",
"Access-Control-Allow-Headers": "",
"Access-Control-Allow-Credentials": "",
"Access-Control-Max-Age": "",
"Access-Control-Expose-Headers": "",
})
}
func TestWildcardOrigin(t *testing.T) {
s := New(Options{
AllowedOrigins: []string{"*"},
})
res := httptest.NewRecorder()
req, _ := http.NewRequest("GET", "http://example.com/foo", nil)
req.Header.Add("Origin", "http://foobar.com")
s.Handler(testHandler).ServeHTTP(res, req)
assertHeaders(t, res.Header(), map[string]string{
"Access-Control-Allow-Origin": "http://foobar.com",
"Access-Control-Allow-Methods": "",
"Access-Control-Allow-Headers": "",
"Access-Control-Allow-Credentials": "",
"Access-Control-Max-Age": "",
"Access-Control-Expose-Headers": "",
})
}
func TestAllowedOrigin(t *testing.T) {
s := New(Options{
AllowedOrigins: []string{"http://foobar.com"},
})
res := httptest.NewRecorder()
req, _ := http.NewRequest("GET", "http://example.com/foo", nil)
req.Header.Add("Origin", "http://foobar.com")
s.Handler(testHandler).ServeHTTP(res, req)
assertHeaders(t, res.Header(), map[string]string{
"Access-Control-Allow-Origin": "http://foobar.com",
"Access-Control-Allow-Methods": "",
"Access-Control-Allow-Headers": "",
"Access-Control-Allow-Credentials": "",
"Access-Control-Max-Age": "",
"Access-Control-Expose-Headers": "",
})
}
func TestDisallowedOrigin(t *testing.T) {
s := New(Options{
AllowedOrigins: []string{"http://foobar.com"},
})
res := httptest.NewRecorder()
req, _ := http.NewRequest("GET", "http://example.com/foo", nil)
req.Header.Add("Origin", "http://barbaz.com")
s.Handler(testHandler).ServeHTTP(res, req)
assertHeaders(t, res.Header(), map[string]string{
"Access-Control-Allow-Origin": "",
"Access-Control-Allow-Methods": "",
"Access-Control-Allow-Headers": "",
"Access-Control-Allow-Credentials": "",
"Access-Control-Max-Age": "",
"Access-Control-Expose-Headers": "",
})
}
func TestAllowedMethod(t *testing.T) {
s := New(Options{
AllowedOrigins: []string{"http://foobar.com"},
AllowedMethods: []string{"PUT", "DELETE"},
})
res := httptest.NewRecorder()
req, _ := http.NewRequest("OPTIONS", "http://example.com/foo", nil)
req.Header.Add("Origin", "http://foobar.com")
req.Header.Add("Access-Control-Request-Method", "PUT")
s.Handler(testHandler).ServeHTTP(res, req)
assertHeaders(t, res.Header(), map[string]string{
"Access-Control-Allow-Origin": "http://foobar.com",
"Access-Control-Allow-Methods": "PUT",
"Access-Control-Allow-Headers": "",
"Access-Control-Allow-Credentials": "",
"Access-Control-Max-Age": "",
"Access-Control-Expose-Headers": "",
})
}
func TestDisallowedMethod(t *testing.T) {
s := New(Options{
AllowedOrigins: []string{"http://foobar.com"},
AllowedMethods: []string{"PUT", "DELETE"},
})
res := httptest.NewRecorder()
req, _ := http.NewRequest("OPTIONS", "http://example.com/foo", nil)
req.Header.Add("Origin", "http://foobar.com")
req.Header.Add("Access-Control-Request-Method", "PATCH")
s.Handler(testHandler).ServeHTTP(res, req)
assertHeaders(t, res.Header(), map[string]string{
"Access-Control-Allow-Origin": "",
"Access-Control-Allow-Methods": "",
"Access-Control-Allow-Headers": "",
"Access-Control-Allow-Credentials": "",
"Access-Control-Max-Age": "",
"Access-Control-Expose-Headers": "",
})
}
func TestAllowedHeader(t *testing.T) {
s := New(Options{
AllowedOrigins: []string{"http://foobar.com"},
AllowedHeaders: []string{"X-Header-1", "x-header-2"},
})
res := httptest.NewRecorder()
req, _ := http.NewRequest("OPTIONS", "http://example.com/foo", nil)
req.Header.Add("Origin", "http://foobar.com")
req.Header.Add("Access-Control-Request-Method", "GET")
req.Header.Add("Access-Control-Request-Headers", "X-Header-2, X-HEADER-1")
s.Handler(testHandler).ServeHTTP(res, req)
assertHeaders(t, res.Header(), map[string]string{
"Access-Control-Allow-Origin": "http://foobar.com",
"Access-Control-Allow-Methods": "GET",
"Access-Control-Allow-Headers": "X-Header-2, X-Header-1",
"Access-Control-Allow-Credentials": "",
"Access-Control-Max-Age": "",
"Access-Control-Expose-Headers": "",
})
}
func TestAllowedWildcardHeader(t *testing.T) {
s := New(Options{
AllowedOrigins: []string{"http://foobar.com"},
AllowedHeaders: []string{"*"},
})
res := httptest.NewRecorder()
req, _ := http.NewRequest("OPTIONS", "http://example.com/foo", nil)
req.Header.Add("Origin", "http://foobar.com")
req.Header.Add("Access-Control-Request-Method", "GET")
req.Header.Add("Access-Control-Request-Headers", "X-Header-2, X-HEADER-1")
s.Handler(testHandler).ServeHTTP(res, req)
assertHeaders(t, res.Header(), map[string]string{
"Access-Control-Allow-Origin": "http://foobar.com",
"Access-Control-Allow-Methods": "GET",
"Access-Control-Allow-Headers": "X-Header-2, X-Header-1",
"Access-Control-Allow-Credentials": "",
"Access-Control-Max-Age": "",
"Access-Control-Expose-Headers": "",
})
}
func TestDisallowedHeader(t *testing.T) {
s := New(Options{
AllowedOrigins: []string{"http://foobar.com"},
AllowedHeaders: []string{"X-Header-1", "x-header-2"},
})
res := httptest.NewRecorder()
req, _ := http.NewRequest("OPTIONS", "http://example.com/foo", nil)
req.Header.Add("Origin", "http://foobar.com")
req.Header.Add("Access-Control-Request-Method", "GET")
req.Header.Add("Access-Control-Request-Headers", "X-Header-3, X-Header-1")
s.Handler(testHandler).ServeHTTP(res, req)
assertHeaders(t, res.Header(), map[string]string{
"Access-Control-Allow-Origin": "",
"Access-Control-Allow-Methods": "",
"Access-Control-Allow-Headers": "",
"Access-Control-Allow-Credentials": "",
"Access-Control-Max-Age": "",
"Access-Control-Expose-Headers": "",
})
}
func TestOriginHeader(t *testing.T) {
s := New(Options{
AllowedOrigins: []string{"http://foobar.com"},
})
res := httptest.NewRecorder()
req, _ := http.NewRequest("OPTIONS", "http://example.com/foo", nil)
req.Header.Add("Origin", "http://foobar.com")
req.Header.Add("Access-Control-Request-Method", "GET")
req.Header.Add("Access-Control-Request-Headers", "origin")
s.Handler(testHandler).ServeHTTP(res, req)
assertHeaders(t, res.Header(), map[string]string{
"Access-Control-Allow-Origin": "http://foobar.com",
"Access-Control-Allow-Methods": "GET",
"Access-Control-Allow-Headers": "Origin",
"Access-Control-Allow-Credentials": "",
"Access-Control-Max-Age": "",
"Access-Control-Expose-Headers": "",
})
}
func TestExposedHeader(t *testing.T) {
s := New(Options{
AllowedOrigins: []string{"http://foobar.com"},
ExposedHeaders: []string{"X-Header-1", "x-header-2"},
})
res := httptest.NewRecorder()
req, _ := http.NewRequest("GET", "http://example.com/foo", nil)
req.Header.Add("Origin", "http://foobar.com")
s.Handler(testHandler).ServeHTTP(res, req)
assertHeaders(t, res.Header(), map[string]string{
"Access-Control-Allow-Origin": "http://foobar.com",
"Access-Control-Allow-Methods": "",
"Access-Control-Allow-Headers": "",
"Access-Control-Allow-Credentials": "",
"Access-Control-Max-Age": "",
"Access-Control-Expose-Headers": "X-Header-1, X-Header-2",
})
}
func TestAllowedCredentials(t *testing.T) {
s := New(Options{
AllowedOrigins: []string{"http://foobar.com"},
AllowCredentials: true,
})
res := httptest.NewRecorder()
req, _ := http.NewRequest("OPTIONS", "http://example.com/foo", nil)
req.Header.Add("Origin", "http://foobar.com")
req.Header.Add("Access-Control-Request-Method", "GET")
s.Handler(testHandler).ServeHTTP(res, req)
assertHeaders(t, res.Header(), map[string]string{
"Access-Control-Allow-Origin": "http://foobar.com",
"Access-Control-Allow-Methods": "GET",
"Access-Control-Allow-Headers": "",
"Access-Control-Allow-Credentials": "true",
"Access-Control-Max-Age": "",
"Access-Control-Expose-Headers": "",
})
}
package main
import (
"net/http"
"github.com/justinas/alice"
"github.com/rs/cors"
)
func main() {
c := cors.New(cors.Options{
AllowedOrigins: []string{"http://foo.com"},
})
mux := http.NewServeMux()
mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "application/json")
w.Write([]byte("{\"hello\": \"world\"}"))
})
chain := alice.New(c.Handler).Then(mux)
http.ListenAndServe(":8080", chain)
}
package main
import (
"net/http"
"github.com/rs/cors"
)
func main() {
h := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "application/json")
w.Write([]byte("{\"hello\": \"world\"}"))
})
// Use default options
handler := cors.Default().Handler(h)
http.ListenAndServe(":8080", handler)
}
package main
import (
"net/http"
"github.com/rs/cors"
"github.com/zenazn/goji"
)
func main() {
c := cors.New(cors.Options{
AllowedOrigins: []string{"http://foo.com"},
})
goji.Use(c.Handler)
goji.Get("/", func(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "application/json")
w.Write([]byte("{\"hello\": \"world\"}"))
})
goji.Serve()
}
package main
import (
"github.com/go-martini/martini"
"github.com/martini-contrib/render"
"github.com/rs/cors"
)
func main() {
c := cors.New(cors.Options{
AllowedOrigins: []string{"http://foo.com"},
})
m := martini.Classic()
m.Use(render.Renderer())
m.Use(c.HandlerFunc)
m.Get("/", func(r render.Render) {
r.JSON(200, map[string]interface{}{"hello": "world"})
})
m.Run()
}
package main
import (
"net/http"
"github.com/codegangsta/negroni"
"github.com/rs/cors"
)
func main() {
c := cors.New(cors.Options{
AllowedOrigins: []string{"http://foo.com"},
})
mux := http.NewServeMux()
mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "application/json")
w.Write([]byte("{\"hello\": \"world\"}"))
})
n := negroni.Classic()
n.Use(c)
n.UseHandler(mux)
n.Run(":3000")
}
package main
import (
"net/http"
"github.com/rs/cors"
)
func main() {
c := cors.New(cors.Options{
AllowedOrigins: []string{"http://foo.com"},
})
handler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "application/json")
w.Write([]byte("{\"hello\": \"world\"}"))
})
http.ListenAndServe(":8080", c.Handler(handler))
}
package main
import (
"net/http"
"github.com/rs/cors"
)
func main() {
c := cors.New(cors.Options{
AllowedOrigins: []string{"*"},
AllowedMethods: []string{"GET", "POST", "PUT", "DELETE"},
AllowCredentials: true,
})
h := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "application/json")
w.Write([]byte("{\"hello\": \"world\"}"))
})
http.ListenAndServe(":8080", c.Handler(h))
}
package cors
import (
"net/http"
"strings"
)
type converter func(string) string
// convert converts a list of string using the passed converter function
func convert(s []string, c converter) []string {
out := []string{}
for _, i := range s {
out = append(out, c(i))
}
return out
}
func parseHeaderList(headerList string) (headers []string) {
for _, header := range strings.Split(headerList, ",") {
header = http.CanonicalHeaderKey(strings.TrimSpace(header))
if header != "" {
headers = append(headers, header)
}
}
return headers
}
package cors
import (
"strings"
"testing"
)
func TestConvert(t *testing.T) {
s := convert([]string{"A", "b", "C"}, strings.ToLower)
e := []string{"a", "b", "c"}
if s[0] != e[0] || s[1] != e[1] || s[2] != e[2] {
t.Errorf("%v != %v", s, e)
}
}
func TestParseHeaderList(t *testing.T) {
h := parseHeaderList("header, second-header, THIRD-HEADER")
e := []string{"Header", "Second-Header", "Third-Header"}
if h[0] != e[0] || h[1] != e[1] || h[2] != e[2] {
t.Errorf("%v != %v", h, e)
}
}
func TestParseHeaderListEmpty(t *testing.T) {
if len(parseHeaderList("")) != 0 {
t.Error("should be empty sclice")
}
}
// Copyright 2009 The Go 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 websocket
import (
"bufio"
"crypto/tls"
"io"
"net"
"net/http"
"net/url"
)
// DialError is an error that occurs while dialling a websocket server.
type DialError struct {
*Config
Err error
}
func (e *DialError) Error() string {
return "websocket.Dial " + e.Config.Location.String() + ": " + e.Err.Error()
}
// NewConfig creates a new WebSocket config for client connection.
func NewConfig(server, origin string) (config *Config, err error) {
config = new(Config)
config.Version = ProtocolVersionHybi13
config.Location, err = url.ParseRequestURI(server)
if err != nil {
return
}
config.Origin, err = url.ParseRequestURI(origin)
if err != nil {
return
}
config.Header = http.Header(make(map[string][]string))
return
}
// NewClient creates a new WebSocket client connection over rwc.
func NewClient(config *Config, rwc io.ReadWriteCloser) (ws *Conn, err error) {
br := bufio.NewReader(rwc)
bw := bufio.NewWriter(rwc)
err = hybiClientHandshake(config, br, bw)
if err != nil {
return
}
buf := bufio.NewReadWriter(br, bw)
ws = newHybiClientConn(config, buf, rwc)
return
}
// Dial opens a new client connection to a WebSocket.
func Dial(url_, protocol, origin string) (ws *Conn, err error) {
config, err := NewConfig(url_, origin)
if err != nil {
return nil, err
}
if protocol != "" {
config.Protocol = []string{protocol}
}
return DialConfig(config)
}
var portMap = map[string]string{
"ws": "80",
"wss": "443",
}
func parseAuthority(location *url.URL) string {
if _, ok := portMap[location.Scheme]; ok {
if _, _, err := net.SplitHostPort(location.Host); err != nil {
return net.JoinHostPort(location.Host, portMap[location.Scheme])
}
}
return location.Host
}
// DialConfig opens a new client connection to a WebSocket with a config.
func DialConfig(config *Config) (ws *Conn, err error) {
var client net.Conn
if config.Location == nil {
return nil, &DialError{config, ErrBadWebSocketLocation}
}
if config.Origin == nil {
return nil, &DialError{config, ErrBadWebSocketOrigin}
}
switch config.Location.Scheme {
case "ws":
client, err = net.Dial("tcp", parseAuthority(config.Location))
case "wss":
client, err = tls.Dial("tcp", parseAuthority(config.Location), config.TlsConfig)
default:
err = ErrBadScheme
}
if err != nil {
goto Error
}
ws, err = NewClient(config, client)
if err != nil {
client.Close()
goto Error
}
return
Error:
return nil, &DialError{config, err}
}
// Copyright 2012 The Go 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 websocket_test
import (
"fmt"
"log"
"golang.org/x/net/websocket"
)
// This example demonstrates a trivial client.
func ExampleDial() {
origin := "http://localhost/"
url := "ws://localhost:12345/ws"
ws, err := websocket.Dial(url, "", origin)
if err != nil {
log.Fatal(err)
}
if _, err := ws.Write([]byte("hello, world!\n")); err != nil {
log.Fatal(err)
}
var msg = make([]byte, 512)
var n int
if n, err = ws.Read(msg); err != nil {
log.Fatal(err)
}
fmt.Printf("Received: %s.\n", msg[:n])
}
......@@ -2,19 +2,25 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package osext
package websocket_test
import (
"os"
"strconv"
"syscall"
"io"
"net/http"
"golang.org/x/net/websocket"
)
func executable() (string, error) {
f, err := os.Open("/proc/" + strconv.Itoa(os.Getpid()) + "/text")
// Echo the data received on the WebSocket.
func EchoServer(ws *websocket.Conn) {
io.Copy(ws, ws)
}
// This example demonstrates a trivial echo server.
func ExampleHandler() {
http.Handle("/echo", websocket.Handler(EchoServer))
err := http.ListenAndServe(":12345", nil)
if err != nil {
return "", err
panic("ListenAndServe: " + err.Error())
}
defer f.Close()
return syscall.Fd2path(int(f.Fd()))
}
This diff is collapsed.
This diff is collapsed.
// Copyright 2009 The Go 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 websocket
import (
"bufio"
"fmt"
"io"
"net/http"
)
func newServerConn(rwc io.ReadWriteCloser, buf *bufio.ReadWriter, req *http.Request, config *Config, handshake func(*Config, *http.Request) error) (conn *Conn, err error) {
var hs serverHandshaker = &hybiServerHandshaker{Config: config}
code, err := hs.ReadHandshake(buf.Reader, req)
if err == ErrBadWebSocketVersion {
fmt.Fprintf(buf, "HTTP/1.1 %03d %s\r\n", code, http.StatusText(code))
fmt.Fprintf(buf, "Sec-WebSocket-Version: %s\r\n", SupportedProtocolVersion)
buf.WriteString("\r\n")
buf.WriteString(err.Error())
buf.Flush()
return
}
if err != nil {
fmt.Fprintf(buf, "HTTP/1.1 %03d %s\r\n", code, http.StatusText(code))
buf.WriteString("\r\n")
buf.WriteString(err.Error())
buf.Flush()
return
}
if handshake != nil {
err = handshake(config, req)
if err != nil {
code = http.StatusForbidden
fmt.Fprintf(buf, "HTTP/1.1 %03d %s\r\n", code, http.StatusText(code))
buf.WriteString("\r\n")
buf.Flush()
return
}
}
err = hs.AcceptHandshake(buf.Writer)
if err != nil {
code = http.StatusBadRequest
fmt.Fprintf(buf, "HTTP/1.1 %03d %s\r\n", code, http.StatusText(code))
buf.WriteString("\r\n")
buf.Flush()
return
}
conn = hs.NewServerConn(buf, rwc, req)
return
}
// Server represents a server of a WebSocket.
type Server struct {
// Config is a WebSocket configuration for new WebSocket connection.
Config
// Handshake is an optional function in WebSocket handshake.
// For example, you can check, or don't check Origin header.
// Another example, you can select config.Protocol.
Handshake func(*Config, *http.Request) error
// Handler handles a WebSocket connection.
Handler
}
// ServeHTTP implements the http.Handler interface for a WebSocket
func (s Server) ServeHTTP(w http.ResponseWriter, req *http.Request) {
s.serveWebSocket(w, req)
}
func (s Server) serveWebSocket(w http.ResponseWriter, req *http.Request) {
rwc, buf, err := w.(http.Hijacker).Hijack()
if err != nil {
panic("Hijack failed: " + err.Error())
return
}
// The server should abort the WebSocket connection if it finds
// the client did not send a handshake that matches with protocol
// specification.
defer rwc.Close()
conn, err := newServerConn(rwc, buf, req, &s.Config, s.Handshake)
if err != nil {
return
}
if conn == nil {
panic("unexpected nil conn")
}
s.Handler(conn)
}
// Handler is a simple interface to a WebSocket browser client.
// It checks if Origin header is valid URL by default.
// You might want to verify websocket.Conn.Config().Origin in the func.
// If you use Server instead of Handler, you could call websocket.Origin and
// check the origin in your Handshake func. So, if you want to accept
// non-browser client, which doesn't send Origin header, you could use Server
//. that doesn't check origin in its Handshake.
type Handler func(*Conn)
func checkOrigin(config *Config, req *http.Request) (err error) {
config.Origin, err = Origin(config, req)
if err == nil && config.Origin == nil {
return fmt.Errorf("null origin")
}
return err
}
// ServeHTTP implements the http.Handler interface for a WebSocket
func (h Handler) ServeHTTP(w http.ResponseWriter, req *http.Request) {
s := Server{Handler: h, Handshake: checkOrigin}
s.serveWebSocket(w, req)
}
This diff is collapsed.
// Copyright 2009 The Go 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 websocket
import (
"bytes"
"fmt"
"io"
"log"
"net"
"net/http"
"net/http/httptest"
"net/url"
"strings"
"sync"
"testing"
)
var serverAddr string
var once sync.Once
func echoServer(ws *Conn) { io.Copy(ws, ws) }
type Count struct {
S string
N int
}
func countServer(ws *Conn) {
for {
var count Count
err := JSON.Receive(ws, &count)
if err != nil {
return
}
count.N++
count.S = strings.Repeat(count.S, count.N)
err = JSON.Send(ws, count)
if err != nil {
return
}
}
}
func subProtocolHandshake(config *Config, req *http.Request) error {
for _, proto := range config.Protocol {
if proto == "chat" {
config.Protocol = []string{proto}
return nil
}
}
return ErrBadWebSocketProtocol
}
func subProtoServer(ws *Conn) {
for _, proto := range ws.Config().Protocol {
io.WriteString(ws, proto)
}
}
func startServer() {
http.Handle("/echo", Handler(echoServer))
http.Handle("/count", Handler(countServer))
subproto := Server{
Handshake: subProtocolHandshake,
Handler: Handler(subProtoServer),
}
http.Handle("/subproto", subproto)
server := httptest.NewServer(nil)
serverAddr = server.Listener.Addr().String()
log.Print("Test WebSocket server listening on ", serverAddr)
}
func newConfig(t *testing.T, path string) *Config {
config, _ := NewConfig(fmt.Sprintf("ws://%s%s", serverAddr, path), "http://localhost")
return config
}
func TestEcho(t *testing.T) {
once.Do(startServer)
// websocket.Dial()
client, err := net.Dial("tcp", serverAddr)
if err != nil {
t.Fatal("dialing", err)
}
conn, err := NewClient(newConfig(t, "/echo"), client)
if err != nil {
t.Errorf("WebSocket handshake error: %v", err)
return
}
msg := []byte("hello, world\n")
if _, err := conn.Write(msg); err != nil {
t.Errorf("Write: %v", err)
}
var actual_msg = make([]byte, 512)
n, err := conn.Read(actual_msg)
if err != nil {
t.Errorf("Read: %v", err)
}
actual_msg = actual_msg[0:n]
if !bytes.Equal(msg, actual_msg) {
t.Errorf("Echo: expected %q got %q", msg, actual_msg)
}
conn.Close()
}
func TestAddr(t *testing.T) {
once.Do(startServer)
// websocket.Dial()
client, err := net.Dial("tcp", serverAddr)
if err != nil {
t.Fatal("dialing", err)
}
conn, err := NewClient(newConfig(t, "/echo"), client)
if err != nil {
t.Errorf("WebSocket handshake error: %v", err)
return
}
ra := conn.RemoteAddr().String()
if !strings.HasPrefix(ra, "ws://") || !strings.HasSuffix(ra, "/echo") {
t.Errorf("Bad remote addr: %v", ra)
}
la := conn.LocalAddr().String()
if !strings.HasPrefix(la, "http://") {
t.Errorf("Bad local addr: %v", la)
}
conn.Close()
}
func TestCount(t *testing.T) {
once.Do(startServer)
// websocket.Dial()
client, err := net.Dial("tcp", serverAddr)
if err != nil {
t.Fatal("dialing", err)
}
conn, err := NewClient(newConfig(t, "/count"), client)
if err != nil {
t.Errorf("WebSocket handshake error: %v", err)
return
}
var count Count
count.S = "hello"
if err := JSON.Send(conn, count); err != nil {
t.Errorf("Write: %v", err)
}
if err := JSON.Receive(conn, &count); err != nil {
t.Errorf("Read: %v", err)
}
if count.N != 1 {
t.Errorf("count: expected %d got %d", 1, count.N)
}
if count.S != "hello" {
t.Errorf("count: expected %q got %q", "hello", count.S)
}
if err := JSON.Send(conn, count); err != nil {
t.Errorf("Write: %v", err)
}
if err := JSON.Receive(conn, &count); err != nil {
t.Errorf("Read: %v", err)
}
if count.N != 2 {
t.Errorf("count: expected %d got %d", 2, count.N)
}
if count.S != "hellohello" {
t.Errorf("count: expected %q got %q", "hellohello", count.S)
}
conn.Close()
}
func TestWithQuery(t *testing.T) {
once.Do(startServer)
client, err := net.Dial("tcp", serverAddr)
if err != nil {
t.Fatal("dialing", err)
}
config := newConfig(t, "/echo")
config.Location, err = url.ParseRequestURI(fmt.Sprintf("ws://%s/echo?q=v", serverAddr))
if err != nil {
t.Fatal("location url", err)
}
ws, err := NewClient(config, client)
if err != nil {
t.Errorf("WebSocket handshake: %v", err)
return
}
ws.Close()
}
func testWithProtocol(t *testing.T, subproto []string) (string, error) {
once.Do(startServer)
client, err := net.Dial("tcp", serverAddr)
if err != nil {
t.Fatal("dialing", err)
}
config := newConfig(t, "/subproto")
config.Protocol = subproto
ws, err := NewClient(config, client)
if err != nil {
return "", err
}
msg := make([]byte, 16)
n, err := ws.Read(msg)
if err != nil {
return "", err
}
ws.Close()
return string(msg[:n]), nil
}
func TestWithProtocol(t *testing.T) {
proto, err := testWithProtocol(t, []string{"chat"})
if err != nil {
t.Errorf("SubProto: unexpected error: %v", err)
}
if proto != "chat" {
t.Errorf("SubProto: expected %q, got %q", "chat", proto)
}
}
func TestWithTwoProtocol(t *testing.T) {
proto, err := testWithProtocol(t, []string{"test", "chat"})
if err != nil {
t.Errorf("SubProto: unexpected error: %v", err)
}
if proto != "chat" {
t.Errorf("SubProto: expected %q, got %q", "chat", proto)
}
}
func TestWithBadProtocol(t *testing.T) {
_, err := testWithProtocol(t, []string{"test"})
if err != ErrBadStatus {
t.Errorf("SubProto: expected %v, got %v", ErrBadStatus, err)
}
}
func TestHTTP(t *testing.T) {
once.Do(startServer)
// If the client did not send a handshake that matches the protocol
// specification, the server MUST return an HTTP response with an
// appropriate error code (such as 400 Bad Request)
resp, err := http.Get(fmt.Sprintf("http://%s/echo", serverAddr))
if err != nil {
t.Errorf("Get: error %#v", err)
return
}
if resp == nil {
t.Error("Get: resp is null")
return
}
if resp.StatusCode != http.StatusBadRequest {
t.Errorf("Get: expected %q got %q", http.StatusBadRequest, resp.StatusCode)
}
}
func TestTrailingSpaces(t *testing.T) {
// http://code.google.com/p/go/issues/detail?id=955
// The last runs of this create keys with trailing spaces that should not be
// generated by the client.
once.Do(startServer)
config := newConfig(t, "/echo")
for i := 0; i < 30; i++ {
// body
ws, err := DialConfig(config)
if err != nil {
t.Errorf("Dial #%d failed: %v", i, err)
break
}
ws.Close()
}
}
func TestDialConfigBadVersion(t *testing.T) {
once.Do(startServer)
config := newConfig(t, "/echo")
config.Version = 1234
_, err := DialConfig(config)
if dialerr, ok := err.(*DialError); ok {
if dialerr.Err != ErrBadProtocolVersion {
t.Errorf("dial expected err %q but got %q", ErrBadProtocolVersion, dialerr.Err)
}
}
}
func TestSmallBuffer(t *testing.T) {
// http://code.google.com/p/go/issues/detail?id=1145
// Read should be able to handle reading a fragment of a frame.
once.Do(startServer)
// websocket.Dial()
client, err := net.Dial("tcp", serverAddr)
if err != nil {
t.Fatal("dialing", err)
}
conn, err := NewClient(newConfig(t, "/echo"), client)
if err != nil {
t.Errorf("WebSocket handshake error: %v", err)
return
}
msg := []byte("hello, world\n")
if _, err := conn.Write(msg); err != nil {
t.Errorf("Write: %v", err)
}
var small_msg = make([]byte, 8)
n, err := conn.Read(small_msg)
if err != nil {
t.Errorf("Read: %v", err)
}
if !bytes.Equal(msg[:len(small_msg)], small_msg) {
t.Errorf("Echo: expected %q got %q", msg[:len(small_msg)], small_msg)
}
var second_msg = make([]byte, len(msg))
n, err = conn.Read(second_msg)
if err != nil {
t.Errorf("Read: %v", err)
}
second_msg = second_msg[0:n]
if !bytes.Equal(msg[len(small_msg):], second_msg) {
t.Errorf("Echo: expected %q got %q", msg[len(small_msg):], second_msg)
}
conn.Close()
}
var parseAuthorityTests = []struct {
in *url.URL
out string
}{
{
&url.URL{
Scheme: "ws",
Host: "www.google.com",
},
"www.google.com:80",
},
{
&url.URL{
Scheme: "wss",
Host: "www.google.com",
},
"www.google.com:443",
},
{
&url.URL{
Scheme: "ws",
Host: "www.google.com:80",
},
"www.google.com:80",
},
{
&url.URL{
Scheme: "wss",
Host: "www.google.com:443",
},
"www.google.com:443",
},
// some invalid ones for parseAuthority. parseAuthority doesn't
// concern itself with the scheme unless it actually knows about it
{
&url.URL{
Scheme: "http",
Host: "www.google.com",
},
"www.google.com",
},
{
&url.URL{
Scheme: "http",
Host: "www.google.com:80",
},
"www.google.com:80",
},
{
&url.URL{
Scheme: "asdf",
Host: "127.0.0.1",
},
"127.0.0.1",
},
{
&url.URL{
Scheme: "asdf",
Host: "www.google.com",
},
"www.google.com",
},
}
func TestParseAuthority(t *testing.T) {
for _, tt := range parseAuthorityTests {
out := parseAuthority(tt.in)
if out != tt.out {
t.Errorf("got %v; want %v", out, tt.out)
}
}
}
......@@ -100,7 +100,7 @@ func (am *Manager) Lock(addr common.Address) error {
am.mutex.Lock()
if unl, found := am.unlocked[addr]; found {
am.mutex.Unlock()
am.expire(addr, unl, time.Duration(0) * time.Nanosecond)
am.expire(addr, unl, time.Duration(0)*time.Nanosecond)
} else {
am.mutex.Unlock()
}
......
......@@ -24,23 +24,16 @@ import (
"os/signal"
"path/filepath"
"regexp"
"strings"
"sort"
"strings"
"github.com/ethereum/go-ethereum/cmd/utils"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/natspec"
"github.com/ethereum/go-ethereum/common/registrar"
"github.com/ethereum/go-ethereum/eth"
re "github.com/ethereum/go-ethereum/jsre"
"github.com/ethereum/go-ethereum/node"
"github.com/ethereum/go-ethereum/rpc"
"github.com/ethereum/go-ethereum/rpc/api"
"github.com/ethereum/go-ethereum/rpc/codec"
"github.com/ethereum/go-ethereum/rpc/comms"
"github.com/ethereum/go-ethereum/rpc/shared"
"github.com/ethereum/go-ethereum/xeth"
"github.com/peterh/liner"
"github.com/robertkrimen/otto"
)
......@@ -79,82 +72,90 @@ func (r dumbterm) AppendHistory(string) {}
type jsre struct {
re *re.JSRE
stack *node.Node
xeth *xeth.XEth
wait chan *big.Int
ps1 string
atexit func()
corsDomain string
client comms.EthereumClient
client rpc.Client
prompter
}
var (
loadedModulesMethods map[string][]string
loadedModulesMethods map[string][]string
autoCompleteStatement = "function _autocomplete(obj) {var results = []; for (var e in obj) { results.push(e); }; return results; }; _autocomplete(%s)"
)
func keywordCompleter(line string) []string {
results := make([]string, 0)
if strings.Contains(line, ".") {
elements := strings.Split(line, ".")
if len(elements) == 2 {
module := elements[0]
partialMethod := elements[1]
if methods, found := loadedModulesMethods[module]; found {
for _, method := range methods {
if strings.HasPrefix(method, partialMethod) { // e.g. debug.se
results = append(results, module+"."+method)
}
}
}
}
} else {
for module, methods := range loadedModulesMethods {
if line == module { // user typed in full module name, show all methods
for _, method := range methods {
results = append(results, module+"."+method)
func keywordCompleter(jsre *jsre, line string) []string {
var results []string
parts := strings.Split(line, ".")
objRef := "this"
prefix := line
if len(parts) > 1 {
objRef = strings.Join(parts[0:len(parts) - 1], ".")
prefix = parts[len(parts) - 1]
}
result, _ := jsre.re.Run(fmt.Sprintf(autoCompleteStatement, objRef))
raw, _ := result.Export()
if keys, ok := raw.([]interface{}); ok {
for _, k := range keys {
if strings.HasPrefix(fmt.Sprintf("%s", k), prefix) {
if objRef == "this" {
results = append(results, fmt.Sprintf("%s", k))
} else {
results = append(results, fmt.Sprintf("%s.%s", strings.Join(parts[:len(parts) - 1], "."), k))
}
} else if strings.HasPrefix(module, line) { // partial method name, e.g. admi
results = append(results, module)
}
}
}
return results
}
func apiWordCompleter(line string, pos int) (head string, completions []string, tail string) {
if len(line) == 0 || pos == 0 {
return "", nil, ""
// e.g. web3<tab><tab> append dot since its an object
isObj, _ := jsre.re.Run(fmt.Sprintf("typeof(%s) === 'object'", line))
if isObject, _ := isObj.ToBoolean(); isObject {
results = append(results, line + ".")
}
i := 0
for i = pos - 1; i > 0; i-- {
if line[i] == '.' || (line[i] >= 'a' && line[i] <= 'z') || (line[i] >= 'A' && line[i] <= 'Z') {
continue
sort.Strings(results)
return results
}
func apiWordCompleterWithContext(jsre *jsre) liner.WordCompleter {
completer := func(line string, pos int) (head string, completions []string, tail string) {
if len(line) == 0 || pos == 0 {
return "", nil, ""
}
if i >= 3 && line[i] == '3' && line[i-3] == 'w' && line[i-2] == 'e' && line[i-1] == 'b' {
continue
// chuck data to relevant part for autocompletion, e.g. in case of nested lines eth.getBalance(eth.coinb<tab><tab>
i := 0
for i = pos - 1; i > 0; i-- {
if line[i] == '.' || (line[i] >= 'a' && line[i] <= 'z') || (line[i] >= 'A' && line[i] <= 'Z') {
continue
}
if i >= 3 && line[i] == '3' && line[i - 3] == 'w' && line[i - 2] == 'e' && line[i - 1] == 'b' {
continue
}
i += 1
break
}
i += 1
break
}
begin := line[:i]
keyword := line[i:pos]
end := line[pos:]
begin := line[:i]
keyword := line[i:pos]
end := line[pos:]
completionWords := keywordCompleter(jsre, keyword)
return begin, completionWords, end
}
completionWords := keywordCompleter(keyword)
return begin, completionWords, end
return completer
}
func newLightweightJSRE(docRoot string, client comms.EthereumClient, datadir string, interactive bool) *jsre {
func newLightweightJSRE(docRoot string, client rpc.Client, datadir string, interactive bool) *jsre {
js := &jsre{ps1: "> "}
js.wait = make(chan *big.Int)
js.client = client
// update state in separare forever blocks
js.re = re.New(docRoot)
if err := js.apiBindings(js); err != nil {
if err := js.apiBindings(); err != nil {
utils.Fatalf("Unable to initialize console - %v", err)
}
......@@ -165,7 +166,7 @@ func newLightweightJSRE(docRoot string, client comms.EthereumClient, datadir str
js.withHistory(datadir, func(hist *os.File) { lr.ReadHistory(hist) })
lr.SetCtrlCAborts(true)
js.loadAutoCompletion()
lr.SetWordCompleter(apiWordCompleter)
lr.SetWordCompleter(apiWordCompleterWithContext(js))
lr.SetTabCompletionStyle(liner.TabPrints)
js.prompter = lr
js.atexit = func() {
......@@ -177,25 +178,15 @@ func newLightweightJSRE(docRoot string, client comms.EthereumClient, datadir str
return js
}
func newJSRE(stack *node.Node, docRoot, corsDomain string, client comms.EthereumClient, interactive bool, f xeth.Frontend) *jsre {
func newJSRE(stack *node.Node, docRoot, corsDomain string, client rpc.Client, interactive bool) *jsre {
js := &jsre{stack: stack, ps1: "> "}
// set default cors domain used by startRpc from CLI flag
js.corsDomain = corsDomain
if f == nil {
f = js
}
js.xeth = xeth.New(stack, f)
js.wait = js.xeth.UpdateState()
js.wait = make(chan *big.Int)
js.client = client
if clt, ok := js.client.(*comms.InProcClient); ok {
if offeredApis, err := api.ParseApiString(shared.AllApis, codec.JSON, js.xeth, stack); err == nil {
clt.Initialize(api.Merge(offeredApis...))
}
}
// update state in separare forever blocks
js.re = re.New(docRoot)
if err := js.apiBindings(f); err != nil {
if err := js.apiBindings(); err != nil {
utils.Fatalf("Unable to connect - %v", err)
}
......@@ -206,7 +197,7 @@ func newJSRE(stack *node.Node, docRoot, corsDomain string, client comms.Ethereum
js.withHistory(stack.DataDir(), func(hist *os.File) { lr.ReadHistory(hist) })
lr.SetCtrlCAborts(true)
js.loadAutoCompletion()
lr.SetWordCompleter(apiWordCompleter)
lr.SetWordCompleter(apiWordCompleterWithContext(js))
lr.SetTabCompletionStyle(liner.TabPrints)
js.prompter = lr
js.atexit = func() {
......@@ -222,7 +213,7 @@ func (self *jsre) loadAutoCompletion() {
if modules, err := self.supportedApis(); err == nil {
loadedModulesMethods = make(map[string][]string)
for module, _ := range modules {
loadedModulesMethods[module] = api.AutoCompletion[module]
loadedModulesMethods[module] = rpc.AutoCompletion[module]
}
}
}
......@@ -258,7 +249,6 @@ func (self *jsre) welcome() {
loadedModules = append(loadedModules, fmt.Sprintf("%s:%s", api, version))
}
sort.Strings(loadedModules)
}
}
......@@ -266,7 +256,7 @@ func (self *jsre) supportedApis() (map[string]string, error) {
return self.client.SupportedModules()
}
func (js *jsre) apiBindings(f xeth.Frontend) error {
func (js *jsre) apiBindings() error {
apis, err := js.supportedApis()
if err != nil {
return err
......@@ -277,12 +267,7 @@ func (js *jsre) apiBindings(f xeth.Frontend) error {
apiNames = append(apiNames, a)
}
apiImpl, err := api.ParseApiString(strings.Join(apiNames, ","), codec.JSON, js.xeth, js.stack)
if err != nil {
utils.Fatalf("Unable to determine supported api's: %v", err)
}
jeth := rpc.NewJeth(api.Merge(apiImpl...), js.re, js.client, f)
jeth := utils.NewJeth(js.re, js.client)
js.re.Set("jeth", struct{}{})
t, _ := js.re.Get("jeth")
jethObj := t.Object()
......@@ -313,14 +298,16 @@ func (js *jsre) apiBindings(f xeth.Frontend) error {
// load only supported API's in javascript runtime
shortcuts := "var eth = web3.eth; "
for _, apiName := range apiNames {
if apiName == shared.Web3ApiName {
continue // manually mapped
if apiName == "web3" || apiName == "rpc" {
continue // manually mapped or ignore
}
if err = js.re.Compile(fmt.Sprintf("%s.js", apiName), api.Javascript(apiName)); err == nil {
shortcuts += fmt.Sprintf("var %s = web3.%s; ", apiName, apiName)
} else {
utils.Fatalf("Error loading %s.js: %v", apiName, err)
if jsFile, ok := rpc.WEB3Extensions[apiName]; ok {
if err = js.re.Compile(fmt.Sprintf("%s.js", apiName), jsFile); err == nil {
shortcuts += fmt.Sprintf("var %s = web3.%s; ", apiName, apiName)
} else {
utils.Fatalf("Error loading %s.js: %v", apiName, err)
}
}
}
......@@ -375,14 +362,13 @@ func (self *jsre) ConfirmTransaction(tx string) bool {
return false
}
// If natspec is enabled, ask for permission
if ethereum.NatSpec {
notice := natspec.GetNotice(self.xeth, tx, ethereum.HTTPClient())
fmt.Println(notice)
answer, _ := self.Prompt("Confirm Transaction [y/n]")
return strings.HasPrefix(strings.Trim(answer, " "), "y")
} else {
return true
if ethereum.NatSpec && false /* disabled for now */ {
// notice := natspec.GetNotice(self.xeth, tx, ethereum.HTTPClient())
// fmt.Println(notice)
// answer, _ := self.Prompt("Confirm Transaction [y/n]")
// return strings.HasPrefix(strings.Trim(answer, " "), "y")
}
return true
}
func (self *jsre) UnlockAccount(addr []byte) bool {
......
......@@ -32,30 +32,27 @@ import (
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/compiler"
"github.com/ethereum/go-ethereum/common/httpclient"
"github.com/ethereum/go-ethereum/common/natspec"
"github.com/ethereum/go-ethereum/common/registrar"
"github.com/ethereum/go-ethereum/core"
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/eth"
"github.com/ethereum/go-ethereum/ethdb"
"github.com/ethereum/go-ethereum/node"
"github.com/ethereum/go-ethereum/rpc/codec"
"github.com/ethereum/go-ethereum/rpc/comms"
"github.com/ethereum/go-ethereum/cmd/utils"
)
const (
testSolcPath = ""
solcVersion = "0.9.23"
solcVersion = "0.9.23"
testKey = "e6fab74a43941f82d89cb7faa408e227cdad3153c4720e540e855c19b15e6674"
testKey = "e6fab74a43941f82d89cb7faa408e227cdad3153c4720e540e855c19b15e6674"
testAddress = "0x8605cdbbdb6d264aa742e77020dcbc58fcdce182"
testBalance = "10000000000000000000"
// of empty string
// of empty string
testHash = "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470"
)
var (
versionRE = regexp.MustCompile(strconv.Quote(`"compilerVersion":"` + solcVersion + `"`))
versionRE = regexp.MustCompile(strconv.Quote(`"compilerVersion":"` + solcVersion + `"`))
testNodeKey = crypto.ToECDSA(common.Hex2Bytes("4b50fa71f5c3eeb8fdc452224b2395af2fcc3d125e06c32c82e048c0559db03f"))
testGenesis = `{"` + testAddress[2:] + `": {"balance": "` + testBalance + `"}}`
)
......@@ -77,15 +74,16 @@ func (self *testjethre) UnlockAccount(acc []byte) bool {
return true
}
func (self *testjethre) ConfirmTransaction(tx string) bool {
var ethereum *eth.Ethereum
self.stack.Service(&ethereum)
if ethereum.NatSpec {
self.lastConfirm = natspec.GetNotice(self.xeth, tx, self.client)
}
return true
}
// Temporary disabled while natspec hasn't been migrated
//func (self *testjethre) ConfirmTransaction(tx string) bool {
// var ethereum *eth.Ethereum
// self.stack.Service(&ethereum)
//
// if ethereum.NatSpec {
// self.lastConfirm = natspec.GetNotice(self.xeth, tx, self.client)
// }
// return true
//}
func testJEthRE(t *testing.T) (string, *testjethre, *node.Node) {
return testREPL(t, nil)
......@@ -118,7 +116,9 @@ func testREPL(t *testing.T, config func(*eth.Config)) (string, *testjethre, *nod
if config != nil {
config(ethConf)
}
if err := stack.Register(func(ctx *node.ServiceContext) (node.Service, error) { return eth.New(ctx, ethConf) }); err != nil {
if err := stack.Register(func(ctx *node.ServiceContext) (node.Service, error) {
return eth.New(ctx, ethConf)
}); err != nil {
t.Fatalf("failed to register ethereum protocol: %v", err)
}
// Initialize all the keys for testing
......@@ -141,9 +141,10 @@ func testREPL(t *testing.T, config func(*eth.Config)) (string, *testjethre, *nod
stack.Service(&ethereum)
assetPath := filepath.Join(os.Getenv("GOPATH"), "src", "github.com", "ethereum", "go-ethereum", "cmd", "mist", "assets", "ext")
client := comms.NewInProcClient(codec.JSON)
//client := comms.NewInProcClient(codec.JSON)
client := utils.NewInProcRPCClient(stack)
tf := &testjethre{client: ethereum.HTTPClient()}
repl := newJSRE(stack, assetPath, "", client, false, tf)
repl := newJSRE(stack, assetPath, "", client, false)
tf.jsre = repl
return tmp, tf, stack
}
......@@ -166,8 +167,8 @@ func TestAccounts(t *testing.T) {
defer node.Stop()
defer os.RemoveAll(tmp)
checkEvalJSON(t, repl, `eth.accounts`, `["`+testAddress+`"]`)
checkEvalJSON(t, repl, `eth.coinbase`, `"`+testAddress+`"`)
checkEvalJSON(t, repl, `eth.accounts`, `["` + testAddress + `"]`)
checkEvalJSON(t, repl, `eth.coinbase`, `"` + testAddress + `"`)
val, err := repl.re.Run(`jeth.newAccount("password")`)
if err != nil {
t.Errorf("expected no error, got %v", err)
......@@ -177,7 +178,7 @@ func TestAccounts(t *testing.T) {
t.Errorf("address not hex: %q", addr)
}
checkEvalJSON(t, repl, `eth.accounts`, `["`+testAddress+`","`+addr+`"]`)
checkEvalJSON(t, repl, `eth.accounts`, `["` + testAddress + `","` + addr + `"]`)
}
......@@ -205,13 +206,13 @@ func TestBlockChain(t *testing.T) {
node.Service(&ethereum)
ethereum.BlockChain().Reset()
checkEvalJSON(t, repl, `admin.exportChain(`+tmpfileq+`)`, `true`)
checkEvalJSON(t, repl, `admin.exportChain(` + tmpfileq + `)`, `true`)
if _, err := os.Stat(tmpfile); err != nil {
t.Fatal(err)
}
// check import, verify that dumpBlock gives the same result.
checkEvalJSON(t, repl, `admin.importChain(`+tmpfileq+`)`, `true`)
checkEvalJSON(t, repl, `admin.importChain(` + tmpfileq + `)`, `true`)
checkEvalJSON(t, repl, `debug.dumpBlock(eth.blockNumber)`, beforeExport)
}
......@@ -239,7 +240,7 @@ func TestCheckTestAccountBalance(t *testing.T) {
defer os.RemoveAll(tmp)
repl.re.Run(`primary = "` + testAddress + `"`)
checkEvalJSON(t, repl, `eth.getBalance(primary)`, `"`+testBalance+`"`)
checkEvalJSON(t, repl, `eth.getBalance(primary)`, `"` + testBalance + `"`)
}
func TestSignature(t *testing.T) {
......@@ -278,19 +279,20 @@ func TestContract(t *testing.T) {
defer ethereum.Stop()
defer os.RemoveAll(tmp)
reg := registrar.New(repl.xeth)
_, err := reg.SetGlobalRegistrar("", coinbase)
if err != nil {
t.Errorf("error setting HashReg: %v", err)
}
_, err = reg.SetHashReg("", coinbase)
if err != nil {
t.Errorf("error setting HashReg: %v", err)
}
_, err = reg.SetUrlHint("", coinbase)
if err != nil {
t.Errorf("error setting HashReg: %v", err)
}
// Temporary disabled while registrar isn't migrated
//reg := registrar.New(repl.xeth)
//_, err := reg.SetGlobalRegistrar("", coinbase)
//if err != nil {
// t.Errorf("error setting HashReg: %v", err)
//}
//_, err = reg.SetHashReg("", coinbase)
//if err != nil {
// t.Errorf("error setting HashReg: %v", err)
//}
//_, err = reg.SetUrlHint("", coinbase)
//if err != nil {
// t.Errorf("error setting HashReg: %v", err)
//}
/* TODO:
* lookup receipt and contract addresses by tx hash
* name registration for HashReg and UrlHint addresses
......@@ -299,11 +301,11 @@ func TestContract(t *testing.T) {
*/
source := `contract test {\n` +
" /// @notice Will multiply `a` by 7." + `\n` +
` function multiply(uint a) returns(uint d) {\n` +
` return a * 7;\n` +
` }\n` +
`}\n`
" /// @notice Will multiply `a` by 7." + `\n` +
` function multiply(uint a) returns(uint d) {\n` +
` return a * 7;\n` +
` }\n` +
`}\n`
if checkEvalJSON(t, repl, `admin.stopNatSpec()`, `true`) != nil {
return
......@@ -313,10 +315,10 @@ func TestContract(t *testing.T) {
if err != nil {
t.Fatalf("%v", err)
}
if checkEvalJSON(t, repl, `primary = eth.accounts[0]`, `"`+testAddress+`"`) != nil {
if checkEvalJSON(t, repl, `primary = eth.accounts[0]`, `"` + testAddress + `"`) != nil {
return
}
if checkEvalJSON(t, repl, `source = "`+source+`"`, `"`+source+`"`) != nil {
if checkEvalJSON(t, repl, `source = "` + source + `"`, `"` + source + `"`) != nil {
return
}
......@@ -394,7 +396,7 @@ multiply7 = Multiply7.at(contractaddress);
var contentHash = `"0x86d2b7cf1e72e9a7a3f8d96601f0151742a2f780f1526414304fbe413dc7f9bd"`
if sol != nil && solcVersion != sol.Version() {
modContractInfo := versionRE.ReplaceAll(contractInfo, []byte(`"compilerVersion":"`+sol.Version()+`"`))
modContractInfo := versionRE.ReplaceAll(contractInfo, []byte(`"compilerVersion":"` + sol.Version() + `"`))
fmt.Printf("modified contractinfo:\n%s\n", modContractInfo)
contentHash = `"` + common.ToHex(crypto.Sha3([]byte(modContractInfo))) + `"`
}
......@@ -474,11 +476,12 @@ func processTxs(repl *testjethre, t *testing.T, expTxc int) bool {
defer ethereum.StopMining()
timer := time.NewTimer(100 * time.Second)
height := new(big.Int).Add(repl.xeth.CurrentBlock().Number(), big.NewInt(1))
blockNr := ethereum.BlockChain().CurrentBlock().Number()
height := new(big.Int).Add(blockNr, big.NewInt(1))
repl.wait <- height
select {
case <-timer.C:
// if times out make sure the xeth loop does not block
// if times out make sure the xeth loop does not block
go func() {
select {
case repl.wait <- nil:
......
......@@ -40,8 +40,6 @@ import (
"github.com/ethereum/go-ethereum/node"
"github.com/ethereum/go-ethereum/params"
"github.com/ethereum/go-ethereum/rlp"
"github.com/ethereum/go-ethereum/rpc/codec"
"github.com/ethereum/go-ethereum/rpc/comms"
)
const (
......@@ -263,11 +261,11 @@ See https://github.com/ethereum/go-ethereum/wiki/Javascipt-Console
Name: "attach",
Usage: `Geth Console: interactive JavaScript environment (connect to node)`,
Description: `
The Geth console is an interactive shell for the JavaScript runtime environment
which exposes a node admin interface as well as the Ðapp JavaScript API.
See https://github.com/ethereum/go-ethereum/wiki/Javascipt-Console.
This command allows to open a console on a running geth node.
`,
The Geth console is an interactive shell for the JavaScript runtime environment
which exposes a node admin interface as well as the Ðapp JavaScript API.
See https://github.com/ethereum/go-ethereum/wiki/Javascipt-Console.
This command allows to open a console on a running geth node.
`,
},
{
Action: execScripts,
......@@ -309,11 +307,15 @@ JavaScript API. See https://github.com/ethereum/go-ethereum/wiki/Javascipt-Conso
utils.RPCEnabledFlag,
utils.RPCListenAddrFlag,
utils.RPCPortFlag,
utils.RpcApiFlag,
utils.RPCApiFlag,
utils.WSEnabledFlag,
utils.WSListenAddrFlag,
utils.WSPortFlag,
utils.WSApiFlag,
utils.WSAllowedDomainsFlag,
utils.IPCDisabledFlag,
utils.IPCApiFlag,
utils.IPCPathFlag,
utils.IPCExperimental,
utils.ExecFlag,
utils.WhisperEnabledFlag,
utils.DevModeFlag,
......@@ -392,20 +394,12 @@ func geth(ctx *cli.Context) {
node.Wait()
}
// attach will connect to a running geth instance attaching a JavaScript console and to it.
func attach(ctx *cli.Context) {
var client comms.EthereumClient
var err error
if ctx.Args().Present() {
client, err = comms.ClientFromEndpoint(ctx.Args().First(), codec.JSON)
} else {
cfg := comms.IpcConfig{
Endpoint: utils.IpcSocketPath(ctx),
}
client, err = comms.NewIpcClient(cfg, codec.JSON)
}
// attach to a running geth instance
client, err := utils.NewRemoteRPCClient(ctx)
if err != nil {
utils.Fatalf("Unable to attach to geth node - %v", err)
utils.Fatalf("Unable to attach to geth - %v", err)
}
repl := newLightweightJSRE(
......@@ -431,11 +425,12 @@ func console(ctx *cli.Context) {
startNode(ctx, node)
// Attach to the newly started node, and either execute script or become interactive
client := comms.NewInProcClient(codec.JSON)
client := utils.NewInProcRPCClient(node)
repl := newJSRE(node,
ctx.GlobalString(utils.JSpathFlag.Name),
ctx.GlobalString(utils.RPCCORSDomainFlag.Name),
client, true, nil)
client, true)
if script := ctx.GlobalString(utils.ExecFlag.Name); script != "" {
repl.batch(script)
......@@ -454,11 +449,12 @@ func execScripts(ctx *cli.Context) {
startNode(ctx, node)
// Attach to the newly started node and execute the given scripts
client := comms.NewInProcClient(codec.JSON)
client := utils.NewInProcRPCClient(node)
repl := newJSRE(node,
ctx.GlobalString(utils.JSpathFlag.Name),
ctx.GlobalString(utils.RPCCORSDomainFlag.Name),
client, false, nil)
client, false)
for _, file := range ctx.Args() {
repl.exec(file)
......@@ -517,6 +513,11 @@ func startNode(ctx *cli.Context, stack *node.Node) {
utils.Fatalf("Failed to start RPC: %v", err)
}
}
if ctx.GlobalBool(utils.WSEnabledFlag.Name) {
if err := utils.StartWS(stack, ctx); err != nil {
utils.Fatalf("Failed to start WS: %v", err)
}
}
if ctx.GlobalBool(utils.MiningEnabledFlag.Name) {
if err := ethereum.StartMining(ctx.GlobalInt(utils.MinerThreadsFlag.Name), ctx.GlobalString(utils.MiningGPUFlag.Name)); err != nil {
utils.Fatalf("Failed to start mining: %v", err)
......
......@@ -21,16 +21,15 @@ import (
"math"
"reflect"
"runtime"
"sort"
"strings"
"time"
"sort"
"github.com/codegangsta/cli"
"github.com/ethereum/go-ethereum/cmd/utils"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/rpc"
"github.com/ethereum/go-ethereum/rpc/codec"
"github.com/ethereum/go-ethereum/rpc/comms"
"github.com/gizak/termui"
)
......@@ -70,20 +69,18 @@ to display multiple metrics simultaneously.
// monitor starts a terminal UI based monitoring tool for the requested metrics.
func monitor(ctx *cli.Context) {
var (
client comms.EthereumClient
client rpc.Client
err error
)
// Attach to an Ethereum node over IPC or RPC
endpoint := ctx.String(monitorCommandAttachFlag.Name)
if client, err = comms.ClientFromEndpoint(endpoint, codec.JSON); err != nil {
if client, err = utils.NewRemoteRPCClientFromString(endpoint); err != nil {
utils.Fatalf("Unable to attach to geth node: %v", err)
}
defer client.Close()
xeth := rpc.NewXeth(client)
// Retrieve all the available metrics and resolve the user pattens
metrics, err := retrieveMetrics(xeth)
metrics, err := retrieveMetrics(client)
if err != nil {
utils.Fatalf("Failed to retrieve system metrics: %v", err)
}
......@@ -133,7 +130,7 @@ func monitor(ctx *cli.Context) {
}
termui.Body.AddRows(termui.NewRow(termui.NewCol(12, 0, footer)))
refreshCharts(xeth, monitored, data, units, charts, ctx, footer)
refreshCharts(client, monitored, data, units, charts, ctx, footer)
termui.Body.Align()
termui.Render(termui.Body)
......@@ -154,7 +151,7 @@ func monitor(ctx *cli.Context) {
termui.Render(termui.Body)
}
case <-refresh:
if refreshCharts(xeth, monitored, data, units, charts, ctx, footer) {
if refreshCharts(client, monitored, data, units, charts, ctx, footer) {
termui.Body.Align()
}
termui.Render(termui.Body)
......@@ -164,8 +161,30 @@ func monitor(ctx *cli.Context) {
// retrieveMetrics contacts the attached geth node and retrieves the entire set
// of collected system metrics.
func retrieveMetrics(xeth *rpc.Xeth) (map[string]interface{}, error) {
return xeth.Call("debug_metrics", []interface{}{true})
func retrieveMetrics(client rpc.Client) (map[string]interface{}, error) {
req := map[string]interface{}{
"id": new(int64),
"method": "debug_metrics",
"jsonrpc": "2.0",
"params": []interface{}{true},
}
if err := client.Send(req); err != nil {
return nil, err
}
var res rpc.JSONSuccessResponse
if err := client.Recv(&res); err != nil {
return nil, err
}
if res.Result != nil {
if mets, ok := res.Result.(map[string]interface{}); ok {
return mets, nil
}
}
return nil, fmt.Errorf("unable to retrieve metrics")
}
// resolveMetrics takes a list of input metric patterns, and resolves each to one
......@@ -253,8 +272,8 @@ func fetchMetric(metrics map[string]interface{}, metric string) float64 {
// refreshCharts retrieves a next batch of metrics, and inserts all the new
// values into the active datasets and charts
func refreshCharts(xeth *rpc.Xeth, metrics []string, data [][]float64, units []int, charts []*termui.LineChart, ctx *cli.Context, footer *termui.Par) (realign bool) {
values, err := retrieveMetrics(xeth)
func refreshCharts(client rpc.Client, metrics []string, data [][]float64, units []int, charts []*termui.LineChart, ctx *cli.Context, footer *termui.Par) (realign bool) {
values, err := retrieveMetrics(client)
for i, metric := range metrics {
if len(data) < 512 {
data[i] = append([]float64{fetchMetric(values, metric)}, data[i]...)
......
......@@ -87,7 +87,12 @@ var AppHelpFlagGroups = []flagGroup{
utils.RPCEnabledFlag,
utils.RPCListenAddrFlag,
utils.RPCPortFlag,
utils.RpcApiFlag,
utils.RPCApiFlag,
utils.WSEnabledFlag,
utils.WSListenAddrFlag,
utils.WSPortFlag,
utils.WSApiFlag,
utils.WSAllowedDomainsFlag,
utils.IPCDisabledFlag,
utils.IPCApiFlag,
utils.IPCPathFlag,
......@@ -158,7 +163,6 @@ var AppHelpFlagGroups = []flagGroup{
Flags: []cli.Flag{
utils.WhisperEnabledFlag,
utils.NatspecEnabledFlag,
utils.IPCExperimental,
},
},
{
......
......@@ -26,8 +26,9 @@ import (
"path/filepath"
"runtime"
"errors"
"github.com/ethereum/go-ethereum/accounts"
"github.com/ethereum/go-ethereum/cmd/utils"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/eth"
......@@ -35,13 +36,9 @@ import (
"github.com/ethereum/go-ethereum/logger"
"github.com/ethereum/go-ethereum/logger/glog"
"github.com/ethereum/go-ethereum/node"
"github.com/ethereum/go-ethereum/rpc/api"
"github.com/ethereum/go-ethereum/rpc/codec"
"github.com/ethereum/go-ethereum/rpc/comms"
rpc "github.com/ethereum/go-ethereum/rpc/v2"
"github.com/ethereum/go-ethereum/rpc"
"github.com/ethereum/go-ethereum/tests"
"github.com/ethereum/go-ethereum/whisper"
"github.com/ethereum/go-ethereum/xeth"
)
const defaultTestKey = "b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291"
......@@ -176,21 +173,25 @@ func RunTest(stack *node.Node, test *tests.BlockTest) error {
// StartRPC initializes an RPC interface to the given protocol stack.
func StartRPC(stack *node.Node) error {
config := comms.HttpConfig{
ListenAddress: "127.0.0.1",
ListenPort: 8545,
/*
web3 := NewPublicWeb3API(stack)
server.RegisterName("web3", web3)
net := NewPublicNetAPI(stack.Server(), ethereum.NetVersion())
server.RegisterName("net", net)
*/
for _, api := range stack.APIs() {
if adminApi, ok := api.Service.(*node.PrivateAdminAPI); ok {
_, err := adminApi.StartRPC("127.0.0.1", 8545, "", "admin,db,eth,debug,miner,net,shh,txpool,personal,web3")
return err
}
}
xeth := xeth.New(stack, nil)
codec := codec.JSON
apis, err := api.ParseApiString(comms.DefaultHttpRpcApis, codec, xeth, stack)
if err != nil {
return err
}
return comms.StartHttp(config, codec, api.Merge(apis...))
glog.V(logger.Error).Infof("Unable to start RPC-HTTP interface, could not find admin API")
return errors.New("Unable to start RPC-HTTP interface")
}
// StartRPC initializes an IPC interface to the given protocol stack.
// StartIPC initializes an IPC interface to the given protocol stack.
func StartIPC(stack *node.Node) error {
var ethereum *eth.Ethereum
if err := stack.Service(&ethereum); err != nil {
......@@ -202,11 +203,7 @@ func StartIPC(stack *node.Node) error {
endpoint = filepath.Join(common.DefaultDataDir(), "geth.ipc")
}
config := comms.IpcConfig{
Endpoint: endpoint,
}
listener, err := comms.CreateListener(config)
listener, err := rpc.CreateIPCListener(endpoint)
if err != nil {
return err
}
......@@ -217,16 +214,16 @@ func StartIPC(stack *node.Node) error {
offered := stack.APIs()
for _, api := range offered {
server.RegisterName(api.Namespace, api.Service)
glog.V(logger.Debug).Infof("Register %T@%s for IPC service\n", api.Service, api.Namespace)
glog.V(logger.Debug).Infof("Register %T under namespace '%s' for IPC service\n", api.Service, api.Namespace)
}
web3 := utils.NewPublicWeb3API(stack)
server.RegisterName("web3", web3)
net := utils.NewPublicNetAPI(stack.Server(), ethereum.NetVersion())
server.RegisterName("net", net)
//var ethereum *eth.Ethereum
//if err := stack.Service(&ethereum); err != nil {
// return err
//}
go func() {
glog.V(logger.Info).Infof("Start IPC server on %s\n", config.Endpoint)
glog.V(logger.Info).Infof("Start IPC server on %s\n", endpoint)
for {
conn, err := listener.Accept()
if err != nil {
......
// Copyright 2015 The go-ethereum Authors
// This file is part of the go-ethereum library.
//
// The go-ethereum library is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// The go-ethereum library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
package utils
import (
"fmt"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/node"
"github.com/ethereum/go-ethereum/p2p"
rpc "github.com/ethereum/go-ethereum/rpc/v2"
)
// PublicWeb3API offers helper utils
type PublicWeb3API struct {
stack *node.Node
}
// NewPublicWeb3API creates a new Web3Service instance
func NewPublicWeb3API(stack *node.Node) *PublicWeb3API {
return &PublicWeb3API{stack}
}
// ClientVersion returns the node name
func (s *PublicWeb3API) ClientVersion() string {
return s.stack.Server().Name
}
// Sha3 applies the ethereum sha3 implementation on the input.
// It assumes the input is hex encoded.
func (s *PublicWeb3API) Sha3(input string) string {
return common.ToHex(crypto.Sha3(common.FromHex(input)))
}
// PublicNetAPI offers network related RPC methods
type PublicNetAPI struct {
net *p2p.Server
networkVersion int
}
// NewPublicNetAPI creates a new net api instance.
func NewPublicNetAPI(net *p2p.Server, networkVersion int) *PublicNetAPI {
return &PublicNetAPI{net, networkVersion}
}
// Listening returns an indication if the node is listening for network connections.
func (s *PublicNetAPI) Listening() bool {
return true // always listening
}
// Peercount returns the number of connected peers
func (s *PublicNetAPI) PeerCount() *rpc.HexNumber {
return rpc.NewHexNumber(s.net.PeerCount())
}
// ProtocolVersion returns the current ethereum protocol version.
func (s *PublicNetAPI) Version() string {
return fmt.Sprintf("%d", s.networkVersion)
}
// Copyright 2015 The go-ethereum Authors
// This file is part of the go-ethereum library.
//
// The go-ethereum library is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// The go-ethereum library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
package utils
import (
"encoding/json"
"fmt"
"strings"
"github.com/codegangsta/cli"
"github.com/ethereum/go-ethereum/eth"
"github.com/ethereum/go-ethereum/logger"
"github.com/ethereum/go-ethereum/logger/glog"
"github.com/ethereum/go-ethereum/node"
"github.com/ethereum/go-ethereum/rpc"
)
// NewInProcRPCClient will start a new RPC server for the given node and returns a client to interact with it.
func NewInProcRPCClient(stack *node.Node) *inProcClient {
server := rpc.NewServer()
offered := stack.APIs()
for _, api := range offered {
server.RegisterName(api.Namespace, api.Service)
}
web3 := node.NewPublicWeb3API(stack)
server.RegisterName("web3", web3)
var ethereum *eth.Ethereum
if err := stack.Service(&ethereum); err == nil {
net := eth.NewPublicNetAPI(stack.Server(), ethereum.NetVersion())
server.RegisterName("net", net)
} else {
glog.V(logger.Warn).Infof("%v\n", err)
}
buf := &buf{
requests: make(chan []byte),
responses: make(chan []byte),
}
client := &inProcClient{
server: server,
buf: buf,
}
go func() {
server.ServeCodec(rpc.NewJSONCodec(client.buf))
}()
return client
}
// buf represents the connection between the RPC server and console
type buf struct {
readBuf []byte // store remaining request bytes after a partial read
requests chan []byte // list with raw serialized requests
responses chan []byte // list with raw serialized responses
}
// will read the next request in json format
func (b *buf) Read(p []byte) (int, error) {
// last read didn't read entire request, return remaining bytes
if len(b.readBuf) > 0 {
n := copy(p, b.readBuf)
if n < len(b.readBuf) {
b.readBuf = b.readBuf[:n]
} else {
b.readBuf = b.readBuf[:0]
}
return n, nil
}
// read next request
req := <-b.requests
n := copy(p, req)
if n < len(req) {
// buf too small, store remaining chunk for next read
b.readBuf = req[n:]
}
return n, nil
}
// Write send the given buffer to the backend
func (b *buf) Write(p []byte) (n int, err error) {
b.responses <- p
return len(p), nil
}
// Close cleans up obtained resources.
func (b *buf) Close() error {
close(b.requests)
close(b.responses)
return nil
}
// inProcClient starts a RPC server and uses buf to communicate with it.
type inProcClient struct {
server *rpc.Server
buf *buf
}
// Close will stop the RPC server
func (c *inProcClient) Close() {
c.server.Stop()
}
// Send a msg to the endpoint
func (c *inProcClient) Send(msg interface{}) error {
d, err := json.Marshal(msg)
if err != nil {
return err
}
c.buf.requests <- d
return nil
}
// Recv reads a message and tries to parse it into the given msg
func (c *inProcClient) Recv(msg interface{}) error {
data := <-c.buf.responses
return json.Unmarshal(data, &msg)
}
// Returns the collection of modules the RPC server offers.
func (c *inProcClient) SupportedModules() (map[string]string, error) {
return rpc.SupportedModules(c)
}
// NewRemoteRPCClient returns a RPC client which connects to a running geth instance.
// Depending on the given context this can either be a IPC or a HTTP client.
func NewRemoteRPCClient(ctx *cli.Context) (rpc.Client, error) {
if ctx.Args().Present() {
endpoint := ctx.Args().First()
return NewRemoteRPCClientFromString(endpoint)
}
// use IPC by default
endpoint := IPCSocketPath(ctx)
return rpc.NewIPCClient(endpoint)
}
// NewRemoteRPCClientFromString returns a RPC client which connects to the given
// endpoint. It must start with either `ipc:` or `rpc:` (HTTP).
func NewRemoteRPCClientFromString(endpoint string) (rpc.Client, error) {
if strings.HasPrefix(endpoint, "ipc:") {
return rpc.NewIPCClient(endpoint[4:])
}
if strings.HasPrefix(endpoint, "rpc:") {
return rpc.NewHTTPClient(endpoint[4:])
}
if strings.HasPrefix(endpoint, "http://") {
return rpc.NewHTTPClient(endpoint)
}
if strings.HasPrefix(endpoint, "ws:") {
return rpc.NewWSClient(endpoint)
}
return nil, fmt.Errorf("invalid endpoint")
}
......@@ -23,7 +23,6 @@ import (
"log"
"math"
"math/big"
"net"
"net/http"
"os"
"path/filepath"
......@@ -31,6 +30,8 @@ import (
"strconv"
"strings"
"errors"
"github.com/codegangsta/cli"
"github.com/ethereum/ethash"
"github.com/ethereum/go-ethereum/accounts"
......@@ -49,14 +50,8 @@ import (
"github.com/ethereum/go-ethereum/p2p/discover"
"github.com/ethereum/go-ethereum/p2p/nat"
"github.com/ethereum/go-ethereum/params"
"github.com/ethereum/go-ethereum/rpc/api"
"github.com/ethereum/go-ethereum/rpc/codec"
"github.com/ethereum/go-ethereum/rpc/comms"
"github.com/ethereum/go-ethereum/rpc/shared"
"github.com/ethereum/go-ethereum/rpc/useragent"
rpc "github.com/ethereum/go-ethereum/rpc/v2"
"github.com/ethereum/go-ethereum/rpc"
"github.com/ethereum/go-ethereum/whisper"
"github.com/ethereum/go-ethereum/xeth"
)
func init() {
......@@ -282,10 +277,10 @@ var (
Usage: "Domains from which to accept cross origin requests (browser enforced)",
Value: "",
}
RpcApiFlag = cli.StringFlag{
RPCApiFlag = cli.StringFlag{
Name: "rpcapi",
Usage: "API's offered over the HTTP-RPC interface",
Value: comms.DefaultHttpRpcApis,
Value: rpc.DefaultHttpRpcApis,
}
IPCDisabledFlag = cli.BoolFlag{
Name: "ipcdisable",
......@@ -294,16 +289,36 @@ var (
IPCApiFlag = cli.StringFlag{
Name: "ipcapi",
Usage: "API's offered over the IPC-RPC interface",
Value: comms.DefaultIpcApis,
Value: rpc.DefaultIpcApis,
}
IPCPathFlag = DirectoryFlag{
Name: "ipcpath",
Usage: "Filename for IPC socket/pipe",
Value: DirectoryString{common.DefaultIpcPath()},
}
IPCExperimental = cli.BoolFlag{
Name: "ipcexp",
Usage: "Enable the new RPC implementation",
WSEnabledFlag = cli.BoolFlag{
Name: "ws",
Usage: "Enable the WS-RPC server",
}
WSListenAddrFlag = cli.StringFlag{
Name: "wsaddr",
Usage: "WS-RPC server listening interface",
Value: "127.0.0.1",
}
WSPortFlag = cli.IntFlag{
Name: "wsport",
Usage: "WS-RPC server listening port",
Value: 8546,
}
WSApiFlag = cli.StringFlag{
Name: "wsapi",
Usage: "API's offered over the WS-RPC interface",
Value: rpc.DefaultHttpRpcApis,
}
WSAllowedDomainsFlag = cli.StringFlag{
Name: "wsdomains",
Usage: "Domains from which to accept websockets requests",
Value: "",
}
ExecFlag = cli.StringFlag{
Name: "exec",
......@@ -760,7 +775,7 @@ func MakeChain(ctx *cli.Context) (chain *core.BlockChain, chainDb ethdb.Database
return chain, chainDb
}
func IpcSocketPath(ctx *cli.Context) (ipcpath string) {
func IPCSocketPath(ctx *cli.Context) (ipcpath string) {
if runtime.GOOS == "windows" {
ipcpath = common.DefaultIpcPath()
if ctx.GlobalIsSet(IPCPathFlag.Name) {
......@@ -780,79 +795,83 @@ func IpcSocketPath(ctx *cli.Context) (ipcpath string) {
}
func StartIPC(stack *node.Node, ctx *cli.Context) error {
config := comms.IpcConfig{
Endpoint: IpcSocketPath(ctx),
}
var ethereum *eth.Ethereum
if err := stack.Service(&ethereum); err != nil {
return err
}
if ctx.GlobalIsSet(IPCExperimental.Name) {
listener, err := comms.CreateListener(config)
if err != nil {
return err
}
endpoint := IPCSocketPath(ctx)
listener, err := rpc.CreateIPCListener(endpoint)
if err != nil {
return err
}
server := rpc.NewServer()
server := rpc.NewServer()
// register package API's this node provides
offered := stack.APIs()
for _, api := range offered {
server.RegisterName(api.Namespace, api.Service)
glog.V(logger.Debug).Infof("Register %T under namespace '%s' for IPC service\n", api.Service, api.Namespace)
}
// register package API's this node provides
offered := stack.APIs()
for _, api := range offered {
server.RegisterName(api.Namespace, api.Service)
glog.V(logger.Debug).Infof("Register %T under namespace '%s' for IPC service\n", api.Service, api.Namespace)
}
web3 := NewPublicWeb3API(stack)
server.RegisterName("web3", web3)
net := NewPublicNetAPI(stack.Server(), ethereum.NetVersion())
server.RegisterName("net", net)
go func() {
glog.V(logger.Info).Infof("Start IPC server on %s\n", config.Endpoint)
for {
conn, err := listener.Accept()
if err != nil {
glog.V(logger.Error).Infof("Unable to accept connection - %v\n", err)
}
codec := rpc.NewJSONCodec(conn)
go server.ServeCodec(codec)
go func() {
glog.V(logger.Info).Infof("Start IPC server on %s\n", endpoint)
for {
conn, err := listener.Accept()
if err != nil {
glog.V(logger.Error).Infof("Unable to accept connection - %v\n", err)
}
}()
return nil
}
initializer := func(conn net.Conn) (comms.Stopper, shared.EthereumApi, error) {
fe := useragent.NewRemoteFrontend(conn, ethereum.AccountManager())
xeth := xeth.New(stack, fe)
apis, err := api.ParseApiString(ctx.GlobalString(IPCApiFlag.Name), codec.JSON, xeth, stack)
if err != nil {
return nil, nil, err
codec := rpc.NewJSONCodec(conn)
go server.ServeCodec(codec)
}
return xeth, api.Merge(apis...), nil
}
return comms.StartIpc(config, codec.JSON, initializer)
}()
return nil
}
// StartRPC starts a HTTP JSON-RPC API server.
func StartRPC(stack *node.Node, ctx *cli.Context) error {
config := comms.HttpConfig{
ListenAddress: ctx.GlobalString(RPCListenAddrFlag.Name),
ListenPort: uint(ctx.GlobalInt(RPCPortFlag.Name)),
CorsDomain: ctx.GlobalString(RPCCORSDomainFlag.Name),
for _, api := range stack.APIs() {
if adminApi, ok := api.Service.(*node.PrivateAdminAPI); ok {
address := ctx.GlobalString(RPCListenAddrFlag.Name)
port := ctx.GlobalInt(RPCPortFlag.Name)
cors := ctx.GlobalString(RPCCORSDomainFlag.Name)
apiStr := ""
if ctx.GlobalIsSet(RPCApiFlag.Name) {
apiStr = ctx.GlobalString(RPCApiFlag.Name)
}
_, err := adminApi.StartRPC(address, port, cors, apiStr)
return err
}
}
xeth := xeth.New(stack, nil)
codec := codec.JSON
glog.V(logger.Error).Infof("Unable to start RPC-HTTP interface, could not find admin API")
return errors.New("Unable to start RPC-HTTP interface")
}
apis, err := api.ParseApiString(ctx.GlobalString(RpcApiFlag.Name), codec, xeth, stack)
if err != nil {
return err
// StartWS starts a websocket JSON-RPC API server.
func StartWS(stack *node.Node, ctx *cli.Context) error {
for _, api := range stack.APIs() {
if adminApi, ok := api.Service.(*node.PrivateAdminAPI); ok {
address := ctx.GlobalString(WSListenAddrFlag.Name)
port := ctx.GlobalInt(WSAllowedDomainsFlag.Name)
allowedDomains := ctx.GlobalString(WSAllowedDomainsFlag.Name)
apiStr := ""
if ctx.GlobalIsSet(WSApiFlag.Name) {
apiStr = ctx.GlobalString(WSApiFlag.Name)
}
_, err := adminApi.StartWS(address, port, allowedDomains, apiStr)
return err
}
}
return comms.StartHttp(config, codec, api.Merge(apis...))
glog.V(logger.Error).Infof("Unable to start RPC-WS interface, could not find admin API")
return errors.New("Unable to start RPC-WS interface")
}
func StartPProf(ctx *cli.Context) {
......
This diff is collapsed.
......@@ -13,6 +13,8 @@
//
// You should have received a copy of the GNU Lesser General Public License
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
//
// +build ignore
package natspec
......
......@@ -13,6 +13,8 @@
//
// You should have received a copy of the GNU Lesser General Public License
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
//
// +build ignore
package natspec
......
......@@ -13,6 +13,8 @@
//
// You should have received a copy of the GNU Lesser General Public License
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
//
// +build ignore
package natspec
......
This diff is collapsed.
// Copyright 2015 The go-ethereum Authors
// This file is part of the go-ethereum library.
//
// The go-ethereum library is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// The go-ethereum library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
package ethreg
import (
"math/big"
"github.com/ethereum/go-ethereum/common/registrar"
"github.com/ethereum/go-ethereum/xeth"
)
// implements a versioned Registrar on an archiving full node
type EthReg struct {
backend *xeth.XEth
registry *registrar.Registrar
}
func New(xe *xeth.XEth) (self *EthReg) {
self = &EthReg{backend: xe}
self.registry = registrar.New(xe)
return
}
func (self *EthReg) Registry() *registrar.Registrar {
return self.registry
}
func (self *EthReg) Resolver(n *big.Int) *registrar.Registrar {
xe := self.backend
if n != nil {
xe = self.backend.AtStateNum(n.Int64())
}
return registrar.New(xe)
}
This diff is collapsed.
......@@ -32,6 +32,7 @@ import (
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/compiler"
"github.com/ethereum/go-ethereum/common/httpclient"
"github.com/ethereum/go-ethereum/common/registrar/ethreg"
"github.com/ethereum/go-ethereum/core"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/eth/downloader"
......@@ -44,7 +45,7 @@ import (
"github.com/ethereum/go-ethereum/node"
"github.com/ethereum/go-ethereum/p2p"
"github.com/ethereum/go-ethereum/rlp"
rpc "github.com/ethereum/go-ethereum/rpc/v2"
"github.com/ethereum/go-ethereum/rpc"
)
const (
......@@ -121,14 +122,15 @@ type Ethereum struct {
eventMux *event.TypeMux
miner *miner.Miner
Mining bool
MinerThreads int
NatSpec bool
AutoDAG bool
PowTest bool
autodagquit chan bool
etherbase common.Address
netVersionId int
Mining bool
MinerThreads int
NatSpec bool
AutoDAG bool
PowTest bool
autodagquit chan bool
etherbase common.Address
netVersionId int
netRPCService *PublicNetAPI
}
func New(ctx *node.ServiceContext, config *Config) (*Ethereum, error) {
......@@ -262,12 +264,12 @@ func (s *Ethereum) APIs() []rpc.API {
}, {
Namespace: "eth",
Version: "1.0",
Service: NewPublicBlockChainAPI(s.BlockChain(), s.ChainDb(), s.EventMux(), s.AccountManager()),
Service: NewPublicBlockChainAPI(s.BlockChain(), s.Miner(), s.ChainDb(), s.EventMux(), s.AccountManager()),
Public: true,
}, {
Namespace: "eth",
Version: "1.0",
Service: NewPublicTransactionPoolAPI(s.TxPool(), s.ChainDb(), s.EventMux(), s.BlockChain(), s.AccountManager()),
Service: NewPublicTransactionPoolAPI(s.TxPool(), s.Miner(), s.ChainDb(), s.EventMux(), s.BlockChain(), s.AccountManager()),
Public: true,
}, {
Namespace: "eth",
......@@ -307,6 +309,15 @@ func (s *Ethereum) APIs() []rpc.API {
Namespace: "debug",
Version: "1.0",
Service: NewPrivateDebugAPI(s),
}, {
Namespace: "net",
Version: "1.0",
Service: s.netRPCService,
Public: true,
}, {
Namespace: "admin",
Version: "1.0",
Service: ethreg.NewPrivateRegistarAPI(s.BlockChain(), s.ChainDb(), s.TxPool(), s.AccountManager()),
},
}
}
......@@ -356,11 +367,12 @@ func (s *Ethereum) Protocols() []p2p.Protocol {
// Start implements node.Service, starting all internal goroutines needed by the
// Ethereum protocol implementation.
func (s *Ethereum) Start(*p2p.Server) error {
func (s *Ethereum) Start(srvr *p2p.Server) error {
if s.AutoDAG {
s.StartAutoDAG()
}
s.protocolManager.Start()
s.netRPCService = NewPublicNetAPI(srvr, s.NetVersion())
return nil
}
......
......@@ -17,7 +17,7 @@
package downloader
import (
rpc "github.com/ethereum/go-ethereum/rpc/v2"
"github.com/ethereum/go-ethereum/rpc"
)
// PublicDownloaderAPI provides an API which gives informatoin about the current synchronisation status.
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment