mirror of
https://github.com/FlipsideCrypto/web3.py.git
synced 2026-02-06 10:56:47 +00:00
116 lines
3.0 KiB
Python
Executable File
116 lines
3.0 KiB
Python
Executable File
from __future__ import absolute_import
|
|
|
|
import sys
|
|
import os
|
|
import contextlib
|
|
import json
|
|
|
|
try:
|
|
from json import JSONDecodeError
|
|
except ImportError:
|
|
JSONDecodeError = ValueError
|
|
|
|
from ..eth_utils import (
|
|
force_text,
|
|
)
|
|
|
|
from ..utils.compat import (
|
|
Timeout,
|
|
threading,
|
|
socket,
|
|
)
|
|
|
|
from .base import JSONBaseProvider
|
|
|
|
|
|
@contextlib.contextmanager
|
|
def get_ipc_socket(ipc_path, timeout=0.1):
|
|
if sys.platform == 'win32':
|
|
# On Windows named pipe is used. Simulate socket with it.
|
|
from ..utils.windows import NamedPipe
|
|
|
|
pipe = NamedPipe(ipc_path)
|
|
with contextlib.closing(pipe):
|
|
yield pipe
|
|
else:
|
|
sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
|
|
sock.connect(ipc_path)
|
|
sock.settimeout(timeout)
|
|
with contextlib.closing(sock):
|
|
yield sock
|
|
|
|
|
|
def get_default_ipc_path(testnet=False):
|
|
if testnet:
|
|
testnet = "testnet"
|
|
else:
|
|
testnet = ""
|
|
|
|
if sys.platform == 'darwin':
|
|
return os.path.expanduser(os.path.join(
|
|
"~",
|
|
"Library",
|
|
"Ethereum",
|
|
testnet,
|
|
"geth.ipc",
|
|
))
|
|
elif sys.platform.startswith('linux'):
|
|
return os.path.expanduser(os.path.join(
|
|
"~",
|
|
".ethereum",
|
|
testnet,
|
|
"geth.ipc",
|
|
))
|
|
elif sys.platform == 'win32':
|
|
return "\\\\.\\pipe\\geth.ipc"
|
|
else:
|
|
raise ValueError(
|
|
"Unsupported platform '{0}'. Only darwin/linux2/win32 are "
|
|
"supported. You must specify the ipc_path".format(sys.platform)
|
|
)
|
|
|
|
|
|
class IPCProvider(JSONBaseProvider):
|
|
def __init__(self, ipc_path=None, testnet=False, *args, **kwargs):
|
|
if ipc_path is None:
|
|
self.ipc_path = get_default_ipc_path(testnet)
|
|
else:
|
|
self.ipc_path = ipc_path
|
|
|
|
self._lock = threading.Lock()
|
|
super(IPCProvider, self).__init__(*args, **kwargs)
|
|
|
|
def make_request(self, method, params):
|
|
request = self.encode_rpc_request(method, params)
|
|
|
|
self._lock.acquire()
|
|
|
|
try:
|
|
with get_ipc_socket(self.ipc_path) as sock:
|
|
sock.sendall(request)
|
|
# TODO: use a BytesIO object here
|
|
response_raw = b""
|
|
|
|
with Timeout(10) as timeout:
|
|
while True:
|
|
try:
|
|
response_raw += sock.recv(4096)
|
|
except socket.timeout:
|
|
timeout.sleep(0)
|
|
continue
|
|
|
|
if response_raw == b"":
|
|
timeout.sleep(0)
|
|
else:
|
|
try:
|
|
json.loads(force_text(response_raw))
|
|
except JSONDecodeError:
|
|
timeout.sleep(0)
|
|
continue
|
|
else:
|
|
break
|
|
finally:
|
|
self._lock.release()
|
|
|
|
return response_raw
|