-
Notifications
You must be signed in to change notification settings - Fork 0
/
udpServer.py
209 lines (185 loc) · 8.72 KB
/
udpServer.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
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
#!/usr/bin/python3
# -*- coding: utf-8 -*-
'''Project:
# # ## ## ## ### ## # # ### ##
# # # # # # # # # # # # # # #
# # # # ## # ## ## # # ## ##
# # # # # # # # # # # # # #
### ## # ## ### # # # ### # #
'''
import socket
import threading
from ipaddress import AddressValueError, IPv4Address
from os import getcwd
'''###################################################################'''
'''############# Defining practical & local functions: ###############'''
def find_iface_ip():
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
s.connect(("8.8.8.8", 80))
iface_ip = s.getsockname()[0]
s.close()
return iface_ip
def find_iface_ip2():
return socket.gethostbyname(socket.gethostname())
def test_conn(Socket=socket.socket()):
''' not useful as a function apart but i must remember this one '''
if Socket._closed == False:
print('connection remains')
return True
else:
print('connection lost')
return False
toHex = lambda x:"".join([hex(ord(c))[2:].zfill(2) for c in x])
'''###################################################################'''
'''################# P2P SERVER CLASS OBJECT DEFINED #################'''
class P2PSocketServer(socket.socket):
def __init__(self, \
IPServer=str('127.0.0.1'), \
PortServer=int(0), \
MaxBuffer=int(0)):
'''#########################################'''
'''UDP Sockets' prototypes are created here:'''
socket.socket.__init__(self, \
family=socket.AF_INET, \
proto=socket.IPPROTO_UDP, \
type=socket.SOCK_DGRAM)
'''#############################################'''
''' Initial Arguments' Values are checked here: '''
try:
isinstance(IPv4Address(IPServer), IPv4Address)
self.P2P_IPServer = IPServer
except AddressValueError as ErrorMessage:
print(ErrorMessage)
try:
isinstance(PortServer, int)
isinstance(MaxBuffer, int)
self.P2P_PortServer = PortServer
self.P2P_SocketServer = (IPv4Address(IPServer).compressed, \
self.P2P_PortServer)
self.P2P_SocketMaxBuffer = MaxBuffer
except TypeError as ErrorMessage:
print(ErrorMessage)
'''#################################################'''
'''A Centralized list of Clients and Exchanged Datas
are stocked in Server's Memory here:'''
self.P2P_Clients = [] # [(self.P2P_IPServer, self.P2P_PortServer)]
self.P2P_AllMemory = [] # a list of bytearrays # 0th would be data sent?
'''#######################'''
'''Setting Default Timeout'''
if socket.getdefaulttimeout() != None:
socket.setdefaulttimeout(None)
'''Binding created sockets:
By precaution, i manually reserved port 14 both tcp/udp
for my_py_server service in /etc/services file.'''
'''Creating bidirectional udp connectors for mutual communication'''
self.bind(self.P2P_SocketServer)
'''#######################################################'''
'''## Once Structure Generated, Connection starts with: ##'''
def startConnection(self,IPClient=str(),PortClient=int()):
try:
isinstance(IPv4Address(IPClient), IPv4Address)
isinstance(PortClient, int)
SocketClient = (IPv4Address(IPClient).compressed, PortClient)
self.connect(SocketClient)
self.P2P_Clients.append(SocketClient)
except AddressValueError as ErrorMessage:
print(ErrorMessage)
'''#################################################'''
'''To Safely Control Interruption of the Connection:'''
def stopConnection(self):
pass
'''#####################################################################'''
'''############### THREADING CLASSES FOR THE SERVER-SIDE ###############'''
'''NOTE: Difference to consider is:
Although Peer2Peer, Server remains central,
and susceptible of having multiple connections,
that's why a different class specifying sendTo/recvFrom
details are needed to be defined.
NOTE2: One could want though clients would be connected too.
That is not my case for now. If so, use only Server Classes
for generating Connections.(cf. further details)'''
class ListenToLocalServer(threading.Thread):
def __init__(self, \
Socket=P2PSocketServer(), \
Data=bytes(), \
Memory=bytearray(), \
MaxBuffer=int()#, \
#LogFile=\
):
threading.Thread.__init__(self)
self.ConnectionSocket = Socket
self.ConnectionData = Data
self.ConnectionMemory = Memory
self.ConnectionMaxBuffer = self.ConnectionSocket.P2P_SocketMaxBuffer
self.HeaderClient = str()
self.ConnectionSocket.P2P_AllMemory.append(self.ConnectionMemory)
self.ConnectionLogFile = str(getcwd()+'/Log'+self.getName()) #enumerate...
#Thread's name has to be fixed for client given..
#otherwise when session changes, buffering changes too.
#self.setName(self.ConnectionSocket.P2P_Clients.index(...))
'''###########################################'''
'''## Automated Threading-Recv Function is: ##'''
def recv(self, \
recvSocket=P2PSocketServer(), \
recvData=bytes(), \
recvMemory=bytearray(), \
recvMaxBuffer=int()):
with open(self.ConnectionLogFile, 'ab', buffering=1) as logFile:
recvData, self.HeaderClient = recvSocket.recvfrom(recvMaxBuffer)
logFile.write(recvData+b'\n')
recvData, self.HeaderClient = bytes(recvData), \
str(self.HeaderClient[0]+': ')
recvMemory.extend(recvData+b'\n')
print(self.HeaderClient+recvData.decode('utf-8'))
'''#############################################'''
'''#### Data recieved is logged into a File ####'''
#generate a logFile for each client
#no i cant make a separate function... recvData's value is lost once recieved
#no it is not. but it is converted before.
#and no need to reopen the file everytime...? no difference.
#i ll see tomorrow.
def logData(self, loggedData=bytes()): # think about buffering =0/1
with open(self.ConnectionLogFile, 'ab', buffering=1) as logFile:
logFile.write(loggedData+b'\n')
'''#############################################'''
'''##### Main Function to begin Threading: #####'''
def run(self):
try:
while self.ConnectionSocket._closed == False:
self.recv(recvSocket=self.ConnectionSocket, \
recvData=self.ConnectionData, \
recvMemory=self.ConnectionMemory, \
recvMaxBuffer=self.ConnectionMaxBuffer)
#self.logData(loggedData=self.ConnectionData)
except KeyboardInterrupt:
self.ConnectionSocket.close()
'''###################################################################'''
'''###################################################################'''
class AnswerToClient(threading.Thread):
def __init__(self, \
Socket=P2PSocketServer(), \
#Client=tuple() # how to know who i am answering?
):
threading.Thread.__init__(self)
self.ConnectionSocket = Socket
self.ConnectionClient = Socket.P2P_Clients[0] # Client
#self.setName(self.ConnectionSocket.P2P_Clients.index(...))
'''###########################################'''
'''## Automated Threading-Send Function is: ##'''
def send(self, \
sendSocket=P2PSocketServer(), \
sendData=str(), \
sendClient=tuple()):
sendSocket.sendto(sendData.encode('utf-8'),sendClient)
'''#############################################'''
'''##### Main Function to begin Threading: #####'''
def run(self):
try:
while self.ConnectionSocket._closed == False:
self.send(sendSocket=self.ConnectionSocket, \
sendData=input(), \
sendClient=self.ConnectionClient)
except KeyboardInterrupt:
self.ConnectionSocket.close()
'''###################################################################'''
'''###################################################################'''