Page MenuHomePhabricator

No OneTemporary

diff --git a/sockpy.py b/sockpy.py
--- a/sockpy.py
+++ b/sockpy.py
@@ -1,128 +1,245 @@
#!/usr/bin/env python2
import requests
import simplejson as json
import threading
from optparse import OptionParser
import socket
import select
import uuid
import time
+import base64
import sys
MAXLEN = 16384
parser = OptionParser()
parser.add_option("-c", "--connect", dest="connect", help="connect local port to remote host and port, use localPort:remoteHost:remotePort; separate multiple hosts by \",\"", default="")
parser.add_option("-s", "--server", dest="host", help="the host running the sockpy server application", default="http://127.0.0.1:8051")
parser.add_option("-u", "--user", dest="user", help="the username for logging into the remote sockpy server", default="admin")
parser.add_option("-p", "--password", dest="password", help="the password for logging into the remote sockpy server", default="admin")
+parser.add_option("-v", "--verbose", action="store_true", dest="verbose", help="enable verbose output", default=False)
(opts, args) = parser.parse_args()
-class SocketWrapper(threading.Thread):
- def __init__(self, host, user, password, connStr):
+class SocketServerWrapper(threading.Thread):
+ def __init__(self, host, user, password, connStr, verbose):
self.url = host
self.user = user
self.password = password
+ self.connStr = connStr
connArr = connStr.split(":")
self.localPort = int(connArr[0])
+ self.error = False
+ self.verbose = verbose
+ self.running = True
+ self.sock = None
+ self.socketThreads = []
+ threading.Thread.__init__(self)
+ self.setDaemon(True)
+
+ def close(self):
+ for thread in self.socketThreads:
+ thread.close()
+
+ def run(self):
+ print "Spawning socket and waiting for connections on port: " + str(self.localPort)
+ self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
+ self.sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 5)
+ self.sock.bind(('', self.localPort))
+ self.sock.listen(1)
+ while self.running:
+ clientSocket, addr = self.sock.accept()
+ self.socketThreads.append(SocketWrapper(self.url, self.user, self.password, self.connStr, clientSocket, self.verbose))
+ self.socketThreads[-1].start()
+ print "ThreadedSocketServer exit."
+
+class SocketWrapper(threading.Thread):
+ def __init__(self, host, user, password, connStr, clientSocket, verbose):
+ self.url = host
+ self.user = user
+ self.verbose = verbose
+ self.password = password
+ connArr = connStr.split(":")
self.remotePort = connArr[-1]
self.error = False
self.connected = False
- self.sock = None
+ self.running = True
self.uid = str(uuid.uuid4())
- self.clientSocket = None
+ self.clientSocket = clientSocket
if len(connArr) == 3:
self.remoteHost = connArr[1]
else:
self.remoteHost = "127.0.0.1"
threading.Thread.__init__(self)
+ self.setDaemon(True)
def run(self):
- self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
- self.sock.bind(('', self.localPort))
- self.sock.listen(5)
- self.clientSocket, addr = self.sock.accept()
if self.connect():
if self.login():
self.connectRemote()
while self.connected:
self.sendRemote(self.recvLocal())
self.sendLocal(self.recvRemote())
+ self.disconnectRemote()
+ self.disconnectLocal()
+ print "Thread exit"
+
+ def close(self):
+ print "Closing Thread..."
+ if self.connected:
+ self.disconnectRemote()
+ self.disconnectLocal()
+ self.connected = False
+ self.running = False
+
+ def disconnectRemote(self):
+ if self.verbose:
+ print "Disconnecting Remote..."
+ payload = {}
+ payload["command"] = "quit"
+ payload["uid"] = self.uid
+ payload["payload"] = json.dumps({})
+ self.connected = False
+ try:
+ r = requests.post(self.url, data=payload)
+ except:
+ return False
+ return True
+
+ def disconnectLocal(self):
+ if self.verbose:
+ print "Disconnecting Local..."
+ try:
+ self.clientSocket.shutdown(socket.SHUT_RDWR)
+ self.clientSocket.close()
+ except:
+ pass
def connect(self):
+ if self.verbose:
+ print "Connecting..."
payload = {}
payload["command"] = "status"
payload["payload"] = json.dumps({})
payload["uid"] = self.uid
- r = requests.post(self.url, data=payload)
+ try:
+ r = requests.post(self.url, data=payload)
+ except:
+ return False
reply = json.loads(r.content)
- return True # FIXME: requests will fail if connect is unsuccessful
+ return True
def login(self):
+ if self.verbose:
+ print "Logging in..."
payload = {}
payload["command"] = "login"
payload["uid"] = self.uid
payload["payload"] = json.dumps({"username" : self.user, "password" : self.password})
- r = requests.post(self.url, data=payload)
+ try:
+ r = requests.post(self.url, data=payload)
+ except:
+ return False
reply = json.loads(r.content)
if reply["status"]:
return True
else:
return False
def connectRemote(self):
+ if self.verbose:
+ print "Connecting Remote..."
payload = {}
payload["command"] = "connect"
payload["payload"] = json.dumps({"host" : self.remoteHost, "port" : self.remotePort})
payload["uid"] = self.uid
r = requests.post(self.url, data=payload)
reply = json.loads(r.content)
if reply["connected"]:
self.connected = True
return True
else:
self.connected = False
return False
def recvLocal(self):
- readable, writable, errored = select.select([self.clientSocket], [], [], 0)
+ readable, writable, errored = select.select([self.clientSocket], [], [self.clientSocket], 0)
if self.clientSocket in readable:
data = self.clientSocket.recv(MAXLEN)
+ if len(data) == 0:
+ self.connected = False
+ print "Local disconnect, closing socket..."
+ elif self.clientSocket in errored:
+ self.connected = False
else:
data = ""
return data
def sendLocal(self, data):
- read, writable, errored = select.select([], [self.clientSocket], [], 0)
+ read, writable, errored = select.select([], [self.clientSocket], [self.clientSocket], 0)
if self.clientSocket in writable and data != "":
- self.clientSocket.sendall(data)
+ sent = self.clientSocket.sendall(data)
+ if sent is not None:
+ self.connected = False
+ print "Error sending to local socket, disconnecting..."
+ elif self.clientSocket in errored:
+ self.connected = False
def recvRemote(self):
payload = {}
payload["command"] = "recv"
payload["payload"] = json.dumps({})
payload["uid"] = self.uid
- r = requests.post(self.url, data=payload)
+ try:
+ r = requests.post(self.url, data=payload)
+ except:
+ self.connected = False
+ return ""
reply = json.loads(r.content)
- return reply["data"]
+ if reply["status"] == False:
+ self.connected = False
+ if reply["connected"] == False:
+ self.connected = False
+ print "Remote disconnect, closing socket..."
+ data = base64.b64decode(reply["data"])
+ if self.verbose:
+ print "Got from Remote: " + data
+ return data
def sendRemote(self, data):
if data != "":
+ if self.verbose:
+ print "Sending to Remote: " + data
payload = {}
payload["command"] = "send"
- payload["payload"] = json.dumps({"data" : data})
+ payload["payload"] = json.dumps({"data" : base64.b64encode(data)})
payload["uid"] = self.uid
- r = requests.post(self.url, data=payload)
+ try:
+ r = requests.post(self.url, data=payload)
+ except:
+ self.connected = False
+ return
+ reply = json.loads(r.content)
+ if reply["status"] == False:
+ self.connected = False
+ if reply["connected"] == False:
+ print "Remote disconnect, closing socket..."
+ self.connected = False
if __name__ == "__main__":
if opts.connect == "":
sys.exit()
hostList = opts.connect.split(",")
sockConns = []
for connStr in hostList:
- sockConns.append(SocketWrapper(opts.host, opts.user, opts.password, connStr))
+ sockConns.append(SocketServerWrapper(opts.host, opts.user, opts.password, connStr, opts.verbose))
sockConns[-1].start()
- while True:
- time.sleep(1)
+ try:
+ while True:
+ time.sleep(1)
+ finally:
+ for conn in sockConns:
+ conn.close()
+ print "done"
+ sys.exit(1)
diff --git a/sockpy.wsgi b/sockpy.wsgi
--- a/sockpy.wsgi
+++ b/sockpy.wsgi
@@ -1,135 +1,155 @@
#!/usr/bin/env python2
from cgi import parse_qs, escape
import simplejson as json
import socket
import select
import time
+import base64
MAXLEN = 16348
gbl_keys = {}
def ExpireOldUIDs():
currTime = time.time()
for uid in gbl_keys.keys():
if gbl_keys[uid].has_key("timeStamp"):
if currTime - gbl_keys[uid]["timeStamp"] > 3600:
del gbl_keys[uid]
def GetValueForUID(uid, key):
if gbl_keys.has_key(uid):
if gbl_keys[uid].has_key(key):
gbl_keys[uid]["timeStamp"] = time.time()
return gbl_keys[uid][key]
return False
def SetValueForUID(uid, key, val):
if not gbl_keys.has_key(uid):
gbl_keys[uid] = {}
gbl_keys[uid][key] = val
gbl_keys[uid]["timeStamp"] = time.time()
def application(environ, start_response):
# the environment variable CONTENT_LENGTH may be empty or missing
try:
request_body_size = int(environ.get('CONTENT_LENGTH', 0))
except (ValueError):
request_body_size = 0
# When the method is POST the query string will be sent
# in the HTTP request body which is passed by the WSGI server
# in the file like wsgi.input environment variable.
request_body = environ['wsgi.input'].read(request_body_size)
d = parse_qs(request_body)
command = escape(d.get('command', [''])[0])
uid = escape(d.get('uid', [''])[0])
- payload = json.loads(d.get('payload', [''])[0])
+ if command != "" and uid != "":
+ payload = json.loads(d.get('payload', [''])[0])
response_array = {}
if command == 'status':
print "status"
response_array['status'] = GetValueForUID(uid, 'status')
elif command == 'login':
print "login"
if payload['username'] == "admin" and payload['password'] == "admin":
print "success"
response_array['status'] = True
SetValueForUID(uid, 'status', True)
else:
print "fail"
response_array['status'] = False
+ SetValueForUID(uid, 'status', False)
elif command == 'send':
print "send"
if GetValueForUID(uid, 'connected') and GetValueForUID(uid, 'status'):
- data = payload['data']
+ data = base64.b64decode(payload['data'])
sock = GetValueForUID(uid, 'socket')
readable, writable, errored = select.select([], [sock], [sock], 0)
if sock in writable:
sock.sendall(data)
response_array['status'] = True
+ response_array['connected'] = True
elif sock in errored:
+ SetValueForUID(uid, 'connected', False)
response_array['status'] = False
+ response_array['connected'] = False
+ sock.close()
else:
response_array['status'] = False
elif command == 'connect':
print "connect"
if GetValueForUID(uid, 'status') and not GetValueForUID(uid, 'connected'):
host = payload['host']
port = payload['port']
print "host: " + host
print "port: " + port
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((host, int(port)))
#s.setblocking(0)
SetValueForUID(uid, 'socket', s)
SetValueForUID(uid, 'connected', True)
response_array['status'] = True
response_array['connected'] = True
else:
response_array['status'] = False
response_array['connected'] = False
elif command == 'quit':
print "quit"
if GetValueForUID(uid, 'connected') and GetValueForUID(uid, 'status'):
- s.close()
+ sock = GetValueForUID(uid, 'socket')
+ sock.close()
SetValueForUID(uid, 'connected', False)
response_array['status'] = True
+ response_array['connected'] = False
elif command == 'recv':
print "recv"
if GetValueForUID(uid, 'connected') and GetValueForUID(uid, 'status'):
sock = GetValueForUID(uid, 'socket')
readable, writable, errored = select.select([sock], [], [sock], 0)
if sock in readable:
data = sock.recv(MAXLEN)
- response_array['status'] = True
+ if len(data) == 0:
+ response_array["status"] = True
+ response_array["connected"] = False
+ sock.close()
+ else:
+ response_array['status'] = True
+ response_array['connected'] = True
elif sock in errored:
+ response_array['connected'] = False
response_array['status'] = False
data = ""
+ sock = GetValueForUID(uid, 'socket')
+ sock.close()
else:
data = ""
response_array['status'] = True
- response_array['data'] = data
+ response_array['connected'] = True
+ response_array['data'] = base64.b64encode(data)
else:
response_array['status'] = False
+ response_array['connected'] = False
response_body = json.dumps(response_array)
print response_body
status = '200 OK'
response_headers = [('Content-Type', 'text/html'),
('Content-Length', str(len(response_body)))]
start_response(status, response_headers)
ExpireOldUIDs()
return [response_body]
if __name__ == "__main__":
from wsgiref.simple_server import make_server
httpd = make_server('localhost', 8051, application)
httpd.serve_forever()

File Metadata

Mime Type
text/x-diff
Expires
Fri, Nov 22, 9:00 PM (12 h, 8 m ago)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
530070
Default Alt Text
(15 KB)

Event Timeline