Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
U
uva
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Taddeüs Kroes
uva
Commits
b6fb2278
Commit
b6fb2278
authored
Feb 13, 2011
by
Sander Mathijs van Veen
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Improved CLI and chat connection.
parent
5fafb3dc
Changes
7
Hide whitespace changes
Inline
Side-by-side
Showing
7 changed files
with
144 additions
and
31 deletions
+144
-31
telematica/ass1/async.py
telematica/ass1/async.py
+57
-12
telematica/ass1/base_bar.py
telematica/ass1/base_bar.py
+24
-0
telematica/ass1/base_window.py
telematica/ass1/base_window.py
+14
-5
telematica/ass1/cli.py
telematica/ass1/cli.py
+39
-7
telematica/ass1/command_bar.py
telematica/ass1/command_bar.py
+6
-0
telematica/ass1/info_bar.py
telematica/ass1/info_bar.py
+0
-7
telematica/ass1/main.py
telematica/ass1/main.py
+4
-0
No files found.
telematica/ass1/async.py
View file @
b6fb2278
import
asyncore
,
socket
import
asyncore
,
socket
from
Queue
import
Queue
from
Queue
import
Queue
import
re
import
re
import
random
class
ClientConnection
(
object
,
asyncore
.
dispatcher
):
class
ClientConnection
(
object
,
asyncore
.
dispatcher
):
...
@@ -12,7 +13,11 @@ class ClientConnection(object, asyncore.dispatcher):
...
@@ -12,7 +13,11 @@ class ClientConnection(object, asyncore.dispatcher):
self
.
authenticated
=
False
self
.
authenticated
=
False
self
.
authentification_sent
=
False
self
.
authentification_sent
=
False
self
.
user
=
'Anonymous'
self
.
retrieved_user_list
=
False
self
.
request_user_list_sent
=
False
# Generate a random user name
self
.
user
=
'Anonymous'
+
str
(
int
(
random
.
random
()
*
10000
))
# Connection/chat event callbacks
# Connection/chat event callbacks
self
.
event_list
=
{
}
self
.
event_list
=
{
}
...
@@ -20,9 +25,14 @@ class ClientConnection(object, asyncore.dispatcher):
...
@@ -20,9 +25,14 @@ class ClientConnection(object, asyncore.dispatcher):
self
.
send_queue
=
Queue
()
self
.
send_queue
=
Queue
()
self
.
send_buffer
=
''
self
.
send_buffer
=
''
def
init_loop
(
self
):
"""Initialise the asyncore loop (blocking)."""
# Set a timeout of 0.1 seconds and use poll() when available.
asyncore
.
loop
(.
1
,
True
)
def
debug_log
(
self
,
msg
):
def
debug_log
(
self
,
msg
):
if
'debug'
in
self
.
event_list
:
if
'debug'
in
self
.
event_list
:
self
.
event_list
[
'debug'
](
msg
)
self
.
event_list
[
'debug'
](
self
,
msg
)
else
:
else
:
print
msg
print
msg
...
@@ -31,14 +41,25 @@ class ClientConnection(object, asyncore.dispatcher):
...
@@ -31,14 +41,25 @@ class ClientConnection(object, asyncore.dispatcher):
self
.
port
=
addr
[
1
]
self
.
port
=
addr
[
1
]
super
(
ClientConnection
,
self
).
connect
(
addr
)
super
(
ClientConnection
,
self
).
connect
(
addr
)
def
retrieve_users
(
self
):
"""
Retreive list of users active at the chat server.
"""
self
.
send_queue
.
put
(
'NAMES'
)
def
username
(
self
,
name
=
''
):
def
username
(
self
,
name
=
''
):
if
not
user
:
if
not
name
:
return
self
.
user
return
self
.
user
self
.
user
=
name
self
.
user
=
name
self
.
authenticated
=
False
self
.
authentification_sent
=
True
self
.
send_queue
.
put
(
'USER %s'
%
name
)
def
handle_connect
(
self
):
def
handle_connect
(
self
):
"""Called when a connection is established."""
"""Called when a connection is established."""
pass
if
'connect'
in
self
.
event_list
:
self
.
event_list
[
'connect'
](
self
)
def
handle_close
(
self
):
def
handle_close
(
self
):
self
.
close
()
self
.
close
()
...
@@ -48,16 +69,21 @@ class ClientConnection(object, asyncore.dispatcher):
...
@@ -48,16 +69,21 @@ class ClientConnection(object, asyncore.dispatcher):
multi_line
=
False
multi_line
=
False
response_format
=
False
response_format
=
False
# Receive a (multiline) message.
while
True
:
while
True
:
chunk
=
self
.
recv
(
1
)
chunk
=
self
.
recv
(
1
)
if
not
chunk
:
if
not
chunk
:
raise
RuntimeError
(
"socket connection broken"
)
raise
RuntimeError
(
'socket connection broken'
)
if
chunk
in
[
'-'
,
'+'
]:
if
chunk
in
[
'-'
,
'+'
]:
response_format
=
True
response_format
=
True
elif
chunk
==
':'
:
elif
chunk
==
':'
:
multi_line
=
True
multi_line
=
True
elif
chunk
==
'
\
n
'
and
buf
[
-
1
]
==
'
\
r
'
:
elif
chunk
==
'
\
n
'
and
buf
[
-
1
]
==
'
\
r
'
:
if
not
multi_line
or
buf
[
-
3
:]
==
'
\
r
\
n
\
r
'
:
if
not
multi_line
:
break
if
buf
[
-
3
:]
==
'
\
r
\
n
\
r
'
:
# Remove trailing '\n\r' from multi line response
buf
=
buf
[:
-
2
]
break
break
multi_line
=
False
multi_line
=
False
buf
+=
chunk
buf
+=
chunk
...
@@ -65,6 +91,7 @@ class ClientConnection(object, asyncore.dispatcher):
...
@@ -65,6 +91,7 @@ class ClientConnection(object, asyncore.dispatcher):
buf
=
buf
[:
-
1
]
buf
=
buf
[:
-
1
]
self
.
debug_log
(
'< %s'
%
buf
)
self
.
debug_log
(
'< %s'
%
buf
)
# Invoke the proper callback function.
if
not
self
.
verified
:
if
not
self
.
verified
:
self
.
verify_server
(
buf
)
self
.
verify_server
(
buf
)
elif
response_format
:
elif
response_format
:
...
@@ -86,28 +113,46 @@ class ClientConnection(object, asyncore.dispatcher):
...
@@ -86,28 +113,46 @@ class ClientConnection(object, asyncore.dispatcher):
self
.
debug_log
(
'Failed to verify connection'
)
self
.
debug_log
(
'Failed to verify connection'
)
sys
.
exit
(
-
1
)
sys
.
exit
(
-
1
)
self
.
debug_log
(
'Server version is %s'
%
match
.
group
(
1
))
if
'verify'
in
self
.
event_list
:
if
'verify'
in
self
.
event_list
:
self
.
event_list
[
'verify'
](
buf
,
match
.
group
(
1
))
self
.
event_list
[
'verify'
](
self
,
buf
,
match
.
group
(
1
))
else
:
self
.
debug_log
(
'Server version is %s'
%
match
.
group
(
1
))
self
.
verified
=
True
self
.
verified
=
True
self
.
send_queue
.
put
(
'CHAT'
)
self
.
send_queue
.
put
(
'CHAT'
)
def
parse_response
(
self
,
buf
):
def
parse_response
(
self
,
buf
):
if
'response'
in
self
.
event_list
:
self
.
event_list
[
'response'
](
self
,
buf
)
if
not
self
.
authenticated
:
if
not
self
.
authenticated
:
if
not
self
.
authentification_sent
:
if
not
self
.
authentification_sent
:
self
.
send_queue
.
put
(
'USER %s'
%
self
.
user
)
self
.
send_queue
.
put
(
'USER %s'
%
self
.
user
)
self
.
authentification_sent
=
True
self
.
authentification_sent
=
True
elif
buf
[
1
:
10
]
==
'Username'
:
# TODO: handle 'username is taken'.
self
.
authenticated
=
True
if
'authenticated'
in
self
.
event_list
:
self
.
event_list
[
'authenticated'
](
self
,
self
.
user
)
#if not self.retrieved_user_list:
# if not self.request_user_list_sent:
# self.request_user_list_sent = True
# self.retrieve_users()
# else:
# # TODO: process user list
# self.retrieved_user_list = True
# #self.debug_log('i Users: %s' % str(buf.split('\r\n')[:-1]))
def
parse_notification
(
self
,
buf
):
def
parse_notification
(
self
,
buf
):
if
'notify'
in
self
.
event_list
:
if
'notify'
in
self
.
event_list
:
self
.
event_list
[
'notify'
](
msg
)
self
.
event_list
[
'notify'
](
self
,
buf
)
def
writable
(
self
):
def
writable
(
self
):
return
not
self
.
send_queue
.
empty
()
or
len
(
self
.
send_buffer
)
write
=
not
self
.
send_queue
.
empty
()
or
len
(
self
.
send_buffer
)
return
write
if
__name__
==
'__main__'
:
if
__name__
==
'__main__'
:
client
=
ClientConnection
()
client
=
ClientConnection
()
client
.
connect
((
'ow150.science.uva.nl'
,
16897
))
client
.
connect
((
'ow150.science.uva.nl'
,
16897
))
asyncore
.
loop
()
client
.
init_
loop
()
telematica/ass1/base_bar.py
View file @
b6fb2278
...
@@ -13,4 +13,28 @@ class BaseBar(object):
...
@@ -13,4 +13,28 @@ class BaseBar(object):
# Initialise bar
# Initialise bar
self
.
bar
=
curses
.
newwin
(
1
,
width
,
top
,
left
)
self
.
bar
=
curses
.
newwin
(
1
,
width
,
top
,
left
)
self
.
color_pair
=
curses
.
color_pair
(
0
)
self
.
_prefix
=
''
def
prefix
(
self
,
value
=
''
):
if
not
value
:
return
self
.
_prefix
self
.
_prefix
=
value
self
.
display
(
self
.
_msg
)
def
display
(
self
,
msg
):
self
.
_msg
=
msg
if
self
.
prefix
:
msg
=
self
.
prefix
()
+
' '
+
msg
# Curses will raise a 'curses.error' when the last possible character is
# written. This exception should therefore always be catched. The raised
# exception truncates the message to the width of the bar.
try
:
self
.
bar
.
addstr
(
0
,
0
,
msg
.
ljust
(
self
.
width
),
self
.
color_pair
)
except
curses
.
error
:
pass
self
.
refresh
()
def
refresh
(
self
):
self
.
bar
.
refresh
()
telematica/ass1/base_window.py
View file @
b6fb2278
import
curses
import
curses
from
Queue
import
Queue
class
BaseWindow
(
object
):
class
BaseWindow
(
object
):
def
__init__
(
self
,
main
,
top
,
left
,
height
,
width
):
def
__init__
(
self
,
main
,
top
,
left
,
height
,
width
):
...
@@ -12,29 +13,37 @@ class BaseWindow(object):
...
@@ -12,29 +13,37 @@ class BaseWindow(object):
self
.
width
=
width
self
.
width
=
width
self
.
lines
=
[]
self
.
lines
=
[]
self
.
line_queue
=
Queue
()
# Initialise window
# Initialise window
self
.
window
=
curses
.
newwin
(
height
,
width
,
top
,
left
)
self
.
window
=
curses
.
newwin
(
height
,
width
,
top
,
left
)
def
clear
(
self
):
def
clear
(
self
):
self
.
lines
=
[]
self
.
window
.
clear
()
self
.
window
.
clear
()
self
.
window
.
refresh
()
self
.
refresh
()
def
redraw
(
self
):
def
redraw
(
self
):
for
y
in
range
(
self
.
height
):
self
.
window
.
clear
()
self
.
window
.
move
(
y
,
0
)
while
not
self
.
line_queue
.
empty
():
self
.
lines
.
append
(
self
.
line_queue
.
get
())
if
self
.
displayed_help
:
return
for
y
,
line
in
enumerate
(
self
.
lines
[
-
self
.
height
:]):
for
y
,
line
in
enumerate
(
self
.
lines
[
-
self
.
height
:]):
try
:
try
:
self
.
window
.
addstr
(
y
,
0
,
line
.
ljust
(
self
.
width
))
self
.
window
.
addstr
(
y
,
0
,
line
.
ljust
(
self
.
width
))
except
curses
.
error
:
except
curses
.
error
:
pass
pass
self
.
refresh
()
def
refresh
(
self
):
self
.
window
.
refresh
()
self
.
window
.
refresh
()
def
append
(
self
,
msg
):
def
append
(
self
,
msg
):
while
msg
:
while
msg
:
self
.
line
s
+=
[
msg
[:
self
.
width
]]
self
.
line
_queue
.
put
(
msg
[:
self
.
width
])
msg
=
msg
[
self
.
width
:]
msg
=
msg
[
self
.
width
:]
self
.
redraw
()
self
.
redraw
()
telematica/ass1/cli.py
View file @
b6fb2278
...
@@ -111,7 +111,7 @@ class CLI:
...
@@ -111,7 +111,7 @@ class CLI:
# If the help screen is currently displayed, hide it.
# If the help screen is currently displayed, hide it.
if
main
.
chat_window
.
displayed_help
:
if
main
.
chat_window
.
displayed_help
:
main
.
chat_window
.
displayed_help
=
False
main
.
chat_window
.
displayed_help
=
False
main
.
chat_window
.
clear
()
main
.
chat_window
.
redraw
()
else
:
else
:
# Stop user input handler (which will exit the application).
# Stop user input handler (which will exit the application).
main
.
execute
(
'quit'
)
main
.
execute
(
'quit'
)
...
@@ -130,13 +130,16 @@ class CLI:
...
@@ -130,13 +130,16 @@ class CLI:
# Initialise the connection and bind event handlers.
# Initialise the connection and bind event handlers.
main
.
connection
=
ClientConnection
()
main
.
connection
=
ClientConnection
()
main
.
connection
.
main
=
main
main
.
connection
.
main
=
main
main
.
connection
.
event_list
[
'debug'
]
=
main
.
debug_log
main
.
connection
.
event_list
[
'debug'
]
=
main
.
debug_event
main
.
connection
.
event_list
[
'connect'
]
=
main
.
connect_event
main
.
connection
.
event_list
[
'notify'
]
=
main
.
notify_event
main
.
connection
.
event_list
[
'authenticated'
]
=
\
main
.
authenticated_event
main
.
connection
.
connect
((
host
,
port
))
main
.
connection
.
connect
((
host
,
port
))
# The chat connection is ran in a separate thread.
# The chat connection is ran in a separate thread.
import
asyncore
self
.
connection_thread
=
threading
.
Thread
()
self
.
connection_thread
=
threading
.
Thread
()
self
.
connection_thread
.
run
=
asyncore
.
loop
self
.
connection_thread
.
run
=
main
.
connection
.
init_
loop
self
.
connection_thread
.
start
()
self
.
connection_thread
.
start
()
def
disconnect
(
main
):
def
disconnect
(
main
):
...
@@ -183,6 +186,8 @@ All commands listed below should be preceded by a slash:
...
@@ -183,6 +186,8 @@ All commands listed below should be preceded by a slash:
help This help page.
help This help page.
quit Quit this chat application (shortcut: ^c).
quit Quit this chat application (shortcut: ^c).
user Change your username to USER.
"""
"""
for
i
,
line
in
enumerate
(
help_text
.
split
(
'
\
n
'
)):
for
i
,
line
in
enumerate
(
help_text
.
split
(
'
\
n
'
)):
...
@@ -203,6 +208,9 @@ All commands listed below should be preceded by a slash:
...
@@ -203,6 +208,9 @@ All commands listed below should be preceded by a slash:
sys
.
exit
(
0
)
sys
.
exit
(
0
)
def
user
(
main
,
name
):
main
.
connection
.
username
(
name
)
def
_exec
(
main
,
cmd
):
def
_exec
(
main
,
cmd
):
# Skip the leading "/exec " of the command
# Skip the leading "/exec " of the command
exec
cmd
[
6
:]
exec
cmd
[
6
:]
...
@@ -214,11 +222,34 @@ All commands listed below should be preceded by a slash:
...
@@ -214,11 +222,34 @@ All commands listed below should be preceded by a slash:
'disconnect'
:
disconnect
,
'disconnect'
:
disconnect
,
'exec'
:
_exec
,
'exec'
:
_exec
,
'help'
:
help
,
'help'
:
help
,
'quit'
:
quit
'quit'
:
quit
,
'user'
:
user
,
}
}
def
debug_log
(
self
,
msg
):
def
refresh
(
self
):
self
.
debug_window
.
append
(
msg
)
self
.
chat_window
.
refresh
()
self
.
debug_window
.
refresh
()
self
.
info_bar
.
refresh
()
self
.
command_bar
.
refresh
()
self
.
command_bar
.
focus
()
self
.
stdscr
.
refresh
()
def
authenticated_event
(
self
,
conn
,
username
):
self
.
info_bar
.
prefix
(
'[%s @ %s]'
%
(
username
,
conn
.
host
))
self
.
refresh
()
def
connect_event
(
self
,
conn
):
self
.
info_bar
.
prefix
(
'[%s]'
%
conn
.
host
)
self
.
display_info
(
''
)
self
.
refresh
()
def
debug_event
(
self
,
conn
,
msg
):
self
.
chat_window
.
append
(
msg
)
self
.
refresh
()
def
notify_event
(
self
,
conn
,
msg
):
self
.
chat_window
.
append
(
msg
)
self
.
refresh
()
def
display_info
(
self
,
msg
):
def
display_info
(
self
,
msg
):
"""
"""
...
@@ -227,6 +258,7 @@ All commands listed below should be preceded by a slash:
...
@@ -227,6 +258,7 @@ All commands listed below should be preceded by a slash:
"""
"""
self
.
info_bar
.
display
(
msg
)
self
.
info_bar
.
display
(
msg
)
self
.
refresh
()
def
execute
(
self
,
cmd
,
args
=
[],
raw_command
=
''
):
def
execute
(
self
,
cmd
,
args
=
[],
raw_command
=
''
):
...
...
telematica/ass1/command_bar.py
View file @
b6fb2278
...
@@ -16,6 +16,12 @@ class CommandBar(BaseBar):
...
@@ -16,6 +16,12 @@ class CommandBar(BaseBar):
# Initialise textbox
# Initialise textbox
self
.
textbox
=
Textbox
(
self
.
bar
)
self
.
textbox
=
Textbox
(
self
.
bar
)
def
focus
(
self
):
"""
Set the cursor to the current positon of this bar.
"""
self
.
bar
.
move
(
*
self
.
bar
.
getyx
())
def
handle_input
(
self
,
c
):
def
handle_input
(
self
,
c
):
#if c == curses.KEY_HOME:
#if c == curses.KEY_HOME:
# self.x = self.y = 0
# self.x = self.y = 0
...
...
telematica/ass1/info_bar.py
View file @
b6fb2278
...
@@ -13,10 +13,3 @@ class InfoBar(BaseBar):
...
@@ -13,10 +13,3 @@ class InfoBar(BaseBar):
+
' or "/help" for help.'
+
' or "/help" for help.'
self
.
display
(
start_message
)
self
.
display
(
start_message
)
def
display
(
self
,
msg
):
try
:
self
.
bar
.
addstr
(
0
,
0
,
msg
.
ljust
(
self
.
width
),
self
.
color_pair
)
except
curses
.
error
:
pass
self
.
bar
.
refresh
()
telematica/ass1/main.py
View file @
b6fb2278
...
@@ -10,4 +10,8 @@ except Exception, e:
...
@@ -10,4 +10,8 @@ except Exception, e:
curses
.
echo
()
curses
.
echo
()
curses
.
endwin
()
curses
.
endwin
()
print
'Error:'
,
e
print
'Error:'
,
e
#finally:
# curses.nocbreak();
# curses.echo()
# curses.endwin()
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment