forked from gregoriorobles/ptavi-p4
-
Notifications
You must be signed in to change notification settings - Fork 0
/
server.py
executable file
·138 lines (104 loc) · 4.12 KB
/
server.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
#!/usr/bin/python3
# -*- coding: utf-8 -*-
"""Main class and program for a simple SIP server."""
import socketserver
import json
import time
import sched
import _thread
import sys
scheduler = sched.scheduler(time.time, time.sleep)
def deleteUser(usersDict, user):
"""DeleteUser method deletes an user from the dictionary.
Arguments needed are (dictionary, userToDelete).
"""
try:
del usersDict[user]
print("User", user, "deleted", "because its entry expired")
SIPRegisterHandler.register2json(usersDict)
except KeyError:
print("No entry for", user)
def schedDelete(usersDict, user):
"""schedDelete method schedules an user deletion when his expire time arrives.
Arguments needed are (dictionary, userToDelete).
"""
try:
scheduler.enterabs(usersDict[user]["fromEpoch"], 1, deleteUser,
(usersDict, user))
scheduler.run()
except KeyError:
pass
def registerUser(stringInfo, usersDict, handler):
"""registerUser method manages user registration and deletion.
Arguments needed are (stringReceived, dictionary).
This method also contains a thread call. For each user in your user
dictionary, it call the second thread and schedules an user deletion
with schedDelete function.
"""
addrStart = stringInfo[1].find(":") + 1
user = stringInfo[1][addrStart:]
expire_time = time.strftime('%Y-%m-%d %H:%M:%S',
time.gmtime(time.time() + int(stringInfo[3])))
tagsDictionary = {"address": handler.client_address,
"expires": expire_time,
"fromEpoch": time.time() + int(stringInfo[3])}
usersDict[user] = tagsDictionary
if int(stringInfo[3]) == 0:
deleteUser(usersDict, user)
else:
print("client", user, "registered", "for",
int(stringInfo[3]), "seconds")
_thread.start_new_thread(schedDelete, (usersDict, user))
SIPRegisterHandler.register2json(usersDict)
class SIPRegisterHandler(socketserver.DatagramRequestHandler):
"""Echo server class."""
usersDict = {}
def handle(self):
"""Handle method of the server class.
(all requests will be handled by this method).
"""
stringMsg = self.rfile.read().decode('utf-8')
stringInfo = stringMsg.split(" ")
try:
if stringInfo[0] == 'REGISTER':
registerUser(stringInfo, SIPRegisterHandler.usersDict, self)
self.wfile.write(b"SIP/2.0 200 OK\r\n\r\n")
else:
self.wfile.write(b"SIP/2.0 400 Bad Request\r\n\r\n")
except Exception as e:
self.wfile.write(b"SIP/2.0 500 Server Internal Error\r\n\r\n")
print("Server error:", e)
@classmethod
def register2json(self, usersDict):
"""register2json method prints user dictionary to json file.
Arguments needed are (dictionary).
"""
fileName = "registered.json"
with open(fileName, "w+") as f:
json.dump(usersDict, f, sort_keys=True, indent=4)
@classmethod
def json2registered(self):
"""json2registered method reads a json file and saves its content.
Arguments needed are ().
"""
try:
with open("registered.json", "r+") as f:
print("Reading json file")
initDict = json.load(f)
self.usersDict = initDict
for user in self.usersDict:
_thread.start_new_thread(schedDelete,
(self.usersDict, user))
except FileNotFoundError:
print("json file not found")
if __name__ == "__main__":
# Listens at localhost ('') port 6001
# and calls the EchoHandler class to manage the request
print("Lanzando servidor UDP de eco...")
try:
serv = socketserver.UDPServer(('', int(sys.argv[1])),
SIPRegisterHandler)
SIPRegisterHandler.json2registered()
serv.serve_forever()
except(KeyboardInterrupt, IndexError):
print("Ending server. Usage: port")