Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Implemented frame handling (for landslide)

  • Loading branch information...
commit 79b608c6f815b0a53c039c963623c3e12c3992d4 1 parent c342837
@mitotic authored
View
11 graphterm/bin/giframe
@@ -20,6 +20,9 @@ parser = OptionParser(usage=usage)
parser.add_option("", "--opacity", dest="opacity", default=1.0,
help="Feed opacity (default: 1.0)")
+parser.add_option("-n", "--nofooter", action="store_true", dest="nofooter", default=False,
+ help="Suppress footer")
+
(options, args) = parser.parse_args()
if args:
if args[0].startswith("http:") or args[0].startswith("https:"):
@@ -45,9 +48,13 @@ else:
iframe_url = gtermapi.create_blob(content, content_type="text/html")
-IFRAMEFORMAT = '<iframe src="%s" width="100%%" height="95%%"></iframe><pre>Click here and type Control-C to exit</pre>'
+headers = {"opacity": options.opacity}
+
+IFRAMEFORMAT = '<iframe src="%s" width="100%%" height="'+str(100 if options.nofooter else 95)+'%%"></iframe>'
+if not options.nofooter:
+ IFRAMEFORMAT += '<pre class="gterm-frame-footer">Click here and type Control-C to exit</pre>'
-gtermapi.write_html(IFRAMEFORMAT % iframe_url, display="fullscreen", add_headers={"opacity": options.opacity})
+gtermapi.write_html(IFRAMEFORMAT % iframe_url, display="fullscreen", add_headers=headers)
try:
while True:
View
20 graphterm/gtermhost.py
@@ -155,7 +155,7 @@ def shutdown(self):
def handle_connect(self):
normalized_host = get_normalized_host(self.connection_id)
- self.remote_response("", [["term_params", {"version": about.version,
+ self.remote_response("", "", [["term_params", {"version": about.version,
"min_version": about.min_version,
"host_secret": self.host_secret,
"normalized_host": normalized_host,
@@ -219,15 +219,15 @@ def paste_command(self, term_name, command_line):
except Exception, excp:
logging.warning("gtermhost: Error in paste_command: %s", excp)
- def screen_callback(self, term_name, command, arg):
+ def screen_callback(self, term_name, response_id, command, arg):
# Invoked in lineterm thread; schedule callback in ioloop
if command == "create_blob":
self.blob_cache.add_blob(*arg)
else:
- self.send_request_threadsafe("response", term_name, [["terminal", command, arg]])
+ self.send_request_threadsafe("response", term_name, response_id, [["terminal", command, arg]])
- def remote_response(self, term_name, message_list):
- self.send_request_threadsafe("response", term_name, message_list)
+ def remote_response(self, term_name, websocket_id, message_list):
+ self.send_request_threadsafe("response", term_name, websocket_id, message_list)
def remote_request(self, term_name, req_list):
"""
@@ -262,7 +262,7 @@ def remote_request(self, term_name, req_list):
elif action == "reconnect":
if self.lineterm:
- self.lineterm.reconnect(term_name)
+ self.lineterm.reconnect(term_name, cmd[0])
elif action == "set_size":
if term_name != OSHELL_NAME:
@@ -444,12 +444,12 @@ def remote_request(self, term_name, req_list):
logging.warning("remote_request: ERROR %s", cmd[0])
else:
raise Exception("Invalid action: "+action)
- self.remote_response(term_name, resp_list);
+ self.remote_response(term_name, "", resp_list);
except Exception, excp:
import traceback
errmsg = "%s\n%s" % (excp, traceback.format_exc())
print >> sys.stderr, "TerminalClient.remote_request: "+errmsg
- self.remote_response(term_name, [["errmsg", errmsg]])
+ self.remote_response(term_name, "", [["errmsg", errmsg]])
##self.shutdown()
@@ -463,7 +463,7 @@ def set_client(self, oshell_client):
def logmessage(self, log_level, msg, exc_info=None, logtype="", plaintext=""):
# If log_level is None, always display message
if self.oshell_client and (log_level is None or log_level >= self.log_level):
- self.oshell_client.remote_response(OSHELL_NAME, [["log", "", [logtype, log_level, msg]]])
+ self.oshell_client.remote_response(OSHELL_NAME, "", [["log", "", [logtype, log_level, msg]]])
if logtype or log_level is None:
sys.stderr.write((plaintext or msg)+"\n")
@@ -474,7 +474,7 @@ def editback(self, content, filepath="", filetype="", editor="", modify=False):
editor=editor, modify=modify)
params = {"editor": editor, "modify": modify, "command": "edit -f "+filepath if modify else "",
"filepath": filepath, "filetype": filetype}
- self.oshell_client.remote_response(OSHELL_NAME, [["edit", params, base64.b64encode(content) if content else ""]])
+ self.oshell_client.remote_response(OSHELL_NAME, "", [["edit", params, base64.b64encode(content) if content else ""]])
return (None, None)
if otrace:
View
26 graphterm/gtermserver.py
@@ -410,13 +410,9 @@ def open(self):
self._all_users[user][self.websocket_id] = self
display_splash = self.controller and self._counter[0] <= 2
- matchpaths = TerminalConnection.get_matching_paths(self.wildcard) if self.wildcard else [path]
- for matchpath in matchpaths:
- matchhost, matchterm = matchpath.split("/")
- TerminalConnection.send_to_connection(matchhost, "request", matchterm, [["reconnect"]])
-
normalized_host, host_secret = "", ""
if not self.wildcard:
+ TerminalConnection.send_to_connection(host, "request", term_name, [["reconnect", self.websocket_id]])
normalized_host = gtermhost.get_normalized_host(host)
if self.authorized["auth_type"] in ("null_auth", "code_auth"):
host_secret = TerminalConnection.host_secrets.get(normalized_host)
@@ -531,7 +527,7 @@ def on_message(self, message):
if msg[1]:
self._webcast_paths[self.remote_path] = time.time()
- elif msg[0] == "edit_broadcast":
+ elif msg[0] == "broadcast":
if self.wildcard:
continue
ws_list = GTSocket._watch_set.get(self.remote_path)
@@ -539,11 +535,12 @@ def on_message(self, message):
continue
for ws_id in ws_list:
if ws_id != self.websocket_id:
- # Broadcast to all watchers (excluding self)
+ # Broadcast to all watchers (excluding originator)
ws = GTSocket._all_websockets.get(ws_id)
if ws:
try:
- ws.write_message(json.dumps([msg]))
+ # Strip broadcast prefix from message
+ ws.write_message(json.dumps([msg[1:]]))
except Exception, excp:
logging.error("edit_broadcast: ERROR %s", excp)
try:
@@ -638,7 +635,7 @@ def remote_terminal_update(self, term_name=None, add_flag=True):
self.term_set.discard(term_name)
return term_name
- def remote_response(self, term_name, msg_list):
+ def remote_response(self, term_name, websocket_id, msg_list):
fwd_list = []
for msg in msg_list:
if msg[0] == "term_params":
@@ -671,11 +668,14 @@ def remote_response(self, term_name, msg_list):
self.allow_feedback.discard(term_name)
path = self.connection_id + "/" + term_name
- ws_list = GTSocket._watch_set.get(path) or set()
+ if websocket_id:
+ ws_list = [websocket_id]
+ else:
+ ws_list = GTSocket._watch_set.get(path) or set()
- for regexp, ws_id in GTSocket._wildcards.itervalues():
- if regexp.match(path):
- ws_list.add(ws_id)
+ for regexp, ws_id in GTSocket._wildcards.itervalues():
+ if regexp.match(path):
+ ws_list.add(ws_id)
if not ws_list:
return
View
72 graphterm/lineterm.py
@@ -420,10 +420,6 @@ def clear_buf(self):
self.scroll_lines = []
self.full_update = True
- def reconnect(self):
- self.last_scroll_count = self.current_scroll_count - len(self.scroll_lines)
- self.full_update = True
-
def clear_last_entry(self, last_entry_index=None):
if not self.scroll_lines or self.entry_index <= 0:
return
@@ -463,13 +459,12 @@ def scroll_buf_up(self, line, meta, offset=0):
self.scroll_lines.pop(0)
def update(self, active_rows, width, height, cursorx, cursory, main_screen,
- alt_screen=None, prompt=[]):
+ alt_screen=None, prompt=[], reconnecting=False):
""" Returns full_update, update_rows, update_scroll
"""
- full_update = self.full_update
- self.full_update = False
+ full_update = self.full_update or reconnecting
- if width != self.width or height != self.height:
+ if not reconnecting and (width != self.width or height != self.height):
self.width = width
self.height = height
full_update = True
@@ -499,15 +494,21 @@ def update(self, active_rows, width, height, cursorx, cursory, main_screen,
offset = prompt_offset(dump(new_row), prompt, screen.meta[j])
update_rows.append([j, offset, "", None, self.dumprichtext(new_row, trim=True)])
- self.cursorx = cursorx
- self.cursory = cursory
- self.main_screen = main_screen.make_copy() if main_screen else None
- self.alt_screen = alt_screen.make_copy() if alt_screen else None
- if self.last_scroll_count < self.current_scroll_count:
+ if reconnecting:
+ update_scroll = self.scroll_lines[:]
+ elif self.last_scroll_count < self.current_scroll_count:
update_scroll = self.scroll_lines[self.last_scroll_count-self.current_scroll_count:]
else:
update_scroll = []
- self.last_scroll_count = self.current_scroll_count
+
+ if not reconnecting:
+ self.last_scroll_count = self.current_scroll_count
+ self.full_update = False
+ self.cursorx = cursorx
+ self.cursory = cursory
+ self.main_screen = main_screen.make_copy() if main_screen else None
+ self.alt_screen = alt_screen.make_copy() if alt_screen else None
+
return full_update, update_rows, update_scroll
def dumprichtext(self, data, trim=False):
@@ -674,6 +675,7 @@ def reset(self, s=""):
self.gterm_buf_size = 0
self.gterm_entry_index = None
self.gterm_validated = False
+ self.gterm_output_buf = []
def resize(self, height, width):
reset_flag = (self.width != width or self.height != height)
@@ -704,9 +706,9 @@ def clear(self):
self.screen_buf.clear_buf()
self.needs_updating = True
- def reconnect(self):
- self.screen_buf.reconnect()
- self.needs_updating = True
+ def reconnect(self, response_id=""):
+ self.update_callback(response_id=response_id)
+ self.graphterm_output(response_id=response_id, from_buffer=True)
def clear_last_entry(self, last_entry_index=None):
self.screen_buf.clear_last_entry(last_entry_index=last_entry_index)
@@ -753,21 +755,27 @@ def update(self):
self.update_time = time.time()
self.needs_updating = False
- alt_screen = self.alt_screen if self.alt_mode else None
if not self.alt_mode:
self.scroll_screen()
+ self.update_callback()
+
+ def update_callback(self, response_id=""):
+ alt_screen = self.alt_screen if self.alt_mode else None
full_update, update_rows, update_scroll = self.screen_buf.update(self.active_rows, self.width, self.height,
self.cursor_x, self.cursor_y,
self.main_screen,
alt_screen=alt_screen,
- prompt=self.prompt)
+ prompt=self.prompt,
+ reconnecting=bool(response_id))
pre_offset = len(self.prompt[0]) if self.prompt else 0
- self.screen_callback(self.term_name, "row_update",
+ self.screen_callback(self.term_name, response_id, "row_update",
[self.alt_mode, full_update, self.active_rows,
self.width, self.height,
self.cursor_x, self.cursor_y, pre_offset,
update_rows, update_scroll])
+ if not response_id and (update_rows or update_scroll):
+ self.gterm_output_buf = []
def zero(self, y1, x1, y2, x2, screen=None):
if screen is None: screen = self.screen
@@ -1285,13 +1293,12 @@ def gterm_append(self, s):
logging.warning("No content_length specified for create_blob")
else:
# Note: blob content should be Base64 encoded
- self.screen_callback(self.term_name, "create_blob",
+ self.screen_callback(self.term_name, "", "create_blob",
[blob_id, headers, content])
elif self.gterm_validated or plain_text:
headers["content_length"] = len(content)
params = {"validated": self.gterm_validated, "headers": headers}
- self.screen_callback(self.term_name, "graphterm_output", [params,
- base64.b64encode(content) if content else ""])
+ self.graphterm_output(params, content)
self.gterm_code = None
self.gterm_buf = None
self.gterm_buf_size = 0
@@ -1299,6 +1306,13 @@ def gterm_append(self, s):
self.gterm_entry_index = None
return retval
+ def graphterm_output(self, params={}, content="", response_id="", from_buffer=False):
+ if not from_buffer:
+ self.gterm_output_buf = [params, base64.b64encode(content) if content else ""]
+ elif not self.gterm_output_buf:
+ return
+ self.screen_callback(self.term_name, response_id, "graphterm_output", self.gterm_output_buf)
+
def save_file(self, filepath, filedata):
status = ""
try:
@@ -1306,7 +1320,7 @@ def save_file(self, filepath, filedata):
f.write(base64.b64decode(filedata))
except Exception, excp:
status = str(excp)
- self.screen_callback(self.term_name, "save_status", [filepath, status])
+ self.screen_callback(self.term_name, "", "save_status", [filepath, status])
def get_finder(self, kind, directory=""):
test_finder_head = """<table frame=none border=0>
@@ -1337,7 +1351,7 @@ def get_finder(self, kind, directory=""):
"x_gterm_response": "display_finder",
"x_gterm_parameters": {"finder_type": kind, "current_directory": ""}}
params = {"validated": self.gterm_validated, "headers": headers}
- self.screen_callback(self.term_name, "graphterm_output", [params, content])
+ self.graphterm_output(params, content)
def click_paste(self, text, file_url="", options={}):
"""Return text or filename (and command) for pasting into command line.
@@ -1593,7 +1607,7 @@ def terminal(self, term_name=None, command="", height=25, width=80):
self.set_size(term_name, height, width)
if not is_executable(Gls_path) and not Exec_errmsg:
Exec_errmsg = True
- self.screen_callback(term_name, "alert", ["File %s is not executable. Did you 'sudo gterm_setup' after 'sudo easy_install graphterm'?" % Gls_path])
+ self.screen_callback(term_name, "", "alert", ["File %s is not executable. Did you 'sudo gterm_setup' after 'sudo easy_install graphterm'?" % Gls_path])
return term_name, cookie
def term_env(self, term_name, cookie, export=False):
@@ -1769,12 +1783,12 @@ def click_paste(self, term_name, text, file_url="", options={}):
return ""
return term.click_paste(text, file_url=file_url, options=options)
- def reconnect(self, term_name):
+ def reconnect(self, term_name, response_id=""):
with self.lock:
term = self.proc.get(term_name)
if not term:
return
- term.reconnect()
+ term.reconnect(response_id=response_id)
def clear(self, term_name):
with self.lock:
@@ -1844,7 +1858,7 @@ def loop(self):
Prompt = "> "
Log_file = "term.log"
Log_file = ""
- def screen_callback(term_name, command, arg):
+ def screen_callback(term_name, response_id, command, arg):
if command == "row_update":
alt_mode, reset, active_rows, width, height, cursorx, cursory, pre_offset, update_rows, update_scroll = arg
for row_num, row_offset, row_dir, row_markup, row_span in update_rows:
Please sign in to comment.
Something went wrong with that request. Please try again.