Skip to content
GitLab
Explore
Sign in
Primary navigation
Search or go to…
Project
U
uva
Manage
Activity
Members
Labels
Plan
Issues
Issue boards
Milestones
Wiki
Code
Merge requests
Repository
Branches
Commits
Tags
Repository graph
Compare revisions
Build
Pipelines
Jobs
Pipeline schedules
Artifacts
Deploy
Releases
Model registry
Operate
Environments
Monitor
Incidents
Analyze
Value stream analytics
Contributor analytics
CI/CD analytics
Repository analytics
Model experiments
Help
Help
Support
GitLab documentation
Compare GitLab plans
Community forum
Contribute to GitLab
Provide feedback
Keyboard shortcuts
?
Snippets
Groups
Projects
Show more breadcrumbs
Taddeüs Kroes
uva
Commits
692d3737
Commit
692d3737
authored
14 years ago
by
Sander Mathijs van Veen
Browse files
Options
Downloads
Patches
Plain Diff
Implemented begin of client handling.
parent
77cb903f
No related branches found
Branches containing commit
No related tags found
No related merge requests found
Changes
2
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
telematica/ass1/cli.py
+7
-10
7 additions, 10 deletions
telematica/ass1/cli.py
telematica/ass1/server.py
+76
-16
76 additions, 16 deletions
telematica/ass1/server.py
with
83 additions
and
26 deletions
telematica/ass1/cli.py
+
7
−
10
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
):
...
...
This diff is collapsed.
Click to expand it.
telematica/ass1/server.py
+
76
−
16
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
:
...
...
This diff is collapsed.
Click to expand it.
Preview
0%
Loading
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Save comment
Cancel
Please
register
or
sign in
to comment