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
692d3737
Commit
692d3737
authored
Mar 10, 2011
by
Sander Mathijs van Veen
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Implemented begin of client handling.
parent
77cb903f
Changes
2
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
83 additions
and
26 deletions
+83
-26
telematica/ass1/cli.py
telematica/ass1/cli.py
+7
-10
telematica/ass1/server.py
telematica/ass1/server.py
+76
-16
No files found.
telematica/ass1/cli.py
View file @
692d3737
...
...
@@ -141,6 +141,7 @@ class CLI:
# The chat connection is ran in a separate thread.
self
.
connection_thread
=
threading
.
Thread
()
self
.
connection_thread
.
daemon
=
True
self
.
connection_thread
.
run
=
main
.
connection
.
init_loop
self
.
connection_thread
.
start
()
...
...
@@ -152,6 +153,8 @@ class CLI:
and the 'Offline' message is set to the info bar.
"""
self
.
connection
.
close
()
del
self
.
connection_thread
self
.
connection
=
None
self
.
display_info
(
'Offline. Type "/connect HOST" to connect'
\
+
' to another chat server.'
)
...
...
@@ -204,13 +207,6 @@ All commands listed below should be preceded by a slash:
main
.
chat_window
.
window
.
refresh
()
def
quit
(
main
):
# Disconnect the connection
e
=
None
try
:
del
self
.
connection
except
Exception
,
e
:
pass
# Reverse the curses-friendly terminal settings.
curses
.
nocbreak
();
self
.
stdscr
.
keypad
(
0
);
...
...
@@ -219,9 +215,10 @@ All commands listed below should be preceded by a slash:
# Restore the terminal to its original operating mode.
curses
.
endwin
()
if
e
:
raise
e
# Disconnect the connection
if
hasattr
(
self
,
'connection_thread'
):
del
self
.
connection_thread
self
.
connection
=
None
sys
.
exit
(
0
)
def
raw
(
main
,
cmd
):
...
...
telematica/ass1/server.py
View file @
692d3737
...
...
@@ -4,6 +4,7 @@ import asyncore
import
logging
import
logging.config
import
os
import
re
import
socket
import
sys
...
...
@@ -14,6 +15,12 @@ GREETING_MSG = 'Hi there!'
MAJOR_VERSION
=
1
MINOR_VERSION
=
0
class
SocketError
(
RuntimeError
):
pass
class
ClientData
(
object
):
pass
class
Server
(
asyncore
.
dispatcher
):
"""
Basic server which will listen on an host address and port. The given
...
...
@@ -29,16 +36,17 @@ class Server(asyncore.dispatcher):
self
.
create_socket
(
socket
.
AF_INET
,
socket
.
SOCK_STREAM
)
self
.
set_reuse_addr
()
self
.
bind
((
ip
,
port
))
logging
.
config
.
fileConfig
(
'logging.conf'
)
self
.
log
=
logging
.
getLogger
(
'Server'
)
self
.
set_reuse_addr
()
self
.
bind
((
ip
,
port
))
self
.
log
.
info
(
'waiting for incoming connections on port %s.'
%
port
)
self
.
listen
(
5
)
self
.
active_clients
=
{}
# Dictonary which maps ip/port tuple to client data object.
self
.
clients
=
{}
def
handle_accept
(
self
):
"""
...
...
@@ -48,6 +56,7 @@ class Server(asyncore.dispatcher):
try
:
conn
,
addr
=
self
.
accept
()
self
.
log
.
info
(
'accepted client %s:%d'
%
addr
)
client
=
self
.
connect_client
(
addr
)
except
socket
.
error
:
self
.
log
.
warning
(
'warning: server accept() threw an exception.'
)
return
...
...
@@ -56,14 +65,26 @@ class Server(asyncore.dispatcher):
return
# creates an instance of the handler class to handle the
# request/response on the incoming connection.
self
.
handler
(
conn
,
addr
,
self
)
self
.
handler
(
conn
,
addr
,
client
,
self
)
def
connect_client
(
self
,
addr
):
self
.
clients
[
'%s:%d'
%
addr
]
=
ClientData
()
return
self
.
clients
[
'%s:%d'
%
addr
]
def
disconnect_client
(
self
,
addr
):
del
self
.
clients
[
'%s:%d'
%
addr
]
def
change_username
(
self
,
addr
,
username
):
self
.
clients
[
'%s:%d'
%
addr
].
username
=
username
# TODO: notify other clients of changed username
class
RequestHandler
(
AsyncBase
,
asyncore
.
dispatcher
):
def
__init__
(
self
,
conn
,
address
,
server
):
def
__init__
(
self
,
conn
,
address
,
client
,
server
):
AsyncBase
.
__init__
(
self
)
asyncore
.
dispatcher
.
__init__
(
self
,
conn
)
self
.
address
=
address
self
.
client
=
client
self
.
server
=
server
self
.
log
=
self
.
server
.
log
...
...
@@ -75,26 +96,65 @@ class RequestHandler(AsyncBase, asyncore.dispatcher):
def
handle_read
(
self
):
buf
=
''
# Receive a message from the client.
while
True
:
chunk
=
self
.
recv
(
1
)
if
not
chunk
:
raise
RuntimeError
(
'socket connection broken'
)
elif
chunk
==
'
\
n
'
and
buf
[
-
1
]
==
'
\
r
'
:
break
buf
+=
chunk
# Receive a message from the client. If the connection is somehow
# broken, disconnect the client and clean the corresponding data.
try
:
while
True
:
chunk
=
self
.
recv
(
1
)
if
not
chunk
:
raise
SocketError
(
'socket connection broken'
)
elif
chunk
==
'
\
n
'
and
buf
[
-
1
]
==
'
\
r
'
:
break
buf
+=
chunk
except
SocketError
:
self
.
log
.
info
(
'client %s:%d disconnected or socket is broken.'
\
%
self
.
address
)
self
.
server
.
disconnect_client
(
self
.
address
)
return
# Received a message, so it's time to parse the message.
buf
=
buf
[:
-
1
]
self
.
debug_log
(
'< %s'
%
buf
)
self
.
send_positive
(
'Ok'
)
#self.send_negative('Ok')
self
.
parse_response
(
buf
)
def
parse_response
(
self
,
buf
):
"""
>>> class DummyServer(object):
... def __init__(self): self.log = None
... def change_username(self, addr, username): pass
>>> req = RequestHandler(None, None, None, DummyServer())
>>> assert req.parse_response('CHAT')
>>> assert req.parse_response('USER foo')
>>> # Some error handling
>>> assert not req.parse_response('CHAT ') # Client must send CHAT
>>> assert not req.parse_response('USER') # No username given.
>>> assert not req.parse_response('USER j/k') # username has a /
"""
cmd
=
buf
.
split
(
' '
)[
0
]
if
buf
==
'CHAT'
:
# Client wants to chat.
return
self
.
send_positive
(
'Ok'
)
if
cmd
==
'USER'
:
# User changes/sets its username.
if
re
.
match
(
ur'^[^\u0000-\u001f\u007f-\u009f/:]+$'
,
buf
[
5
:]):
self
.
set_username
(
buf
[
5
:])
return
self
.
send_positive
(
'Ok'
)
return
self
.
send_negative
(
'Invalid username.'
)
return
self
.
send_negative
(
'Unsupported command.'
)
def
send_positive
(
self
,
msg
):
self
.
send_raw
(
'+%s'
%
msg
)
return
True
def
send_negative
(
self
,
msg
):
self
.
send_raw
(
'-%s'
%
msg
)
return
False
def
set_username
(
self
,
username
):
self
.
server
.
change_username
(
self
.
address
,
username
)
if
__name__
==
'__main__'
:
if
len
(
sys
.
argv
)
!=
3
:
...
...
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