/
connections.py
158 lines (102 loc) · 4.41 KB
/
connections.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
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# MAILnetD.py
#This file is part of MAILNETd.
#MAILNETd is free software: you can redistribute it and/or modify
#it under the terms of the GNU General Public License as published by
#the Free Software Foundation, either version 3 of the License, or
#(at your option) any later version.
#MAILNETd is distributed in the hope that it will be useful,
#but WITHOUT ANY WARRANTY; without even the implied warranty of
#MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
#GNU General Public License for more details.
#You should have received a copy of the GNU General Public License
#along with MAILNETd. If not, see <http://www.gnu.org/licenses/>.
import asyncore
import asynchat
import socket
from users import Users
class Connection_manager(asyncore.dispatcher):
all_conn_count = 0 # Class variable. Contains count of all connections from every instance of this class.
def __init__(self, type, port):
asyncore.dispatcher.__init__(self)
self.port = port
self.create_socket(socket.AF_INET, socket.SOCK_STREAM)
# This allows to reuse the port which we are listening
self.socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
self.type = type
self.connections = []
self.bind(("", port))
self.listen(5)
self.dmesg( self.type.__name__, "listening on port", self.port )
def __str__(self):
"""equivalent to java's toString()"""
return "%s clients connected to %s. Overall %s connections" % (len(self.connections), self.type.__name__, Connection_manager.all_conn_count)
def handle_accept(self):
conn, addr = self.accept()
Connection_manager.all_conn_count += 1
self.connections.append( self.type(conn, addr, self) )
self.dmesg( str(addr[0]) + ":" + str(addr[1]), "connected to", self.type.__name__ )
self.dmesg( self )
def remove_conn(self, conn):
self.connections.remove(conn)
Connection_manager.all_conn_count -= 1
self.dmesg( conn.addr[0], "disconnected from", self.type.__name__ )
self.dmesg( self )
def dmesg(self, *msgs):
msg = "%s> %s" % (self.__class__.__name__, " ".join(str(v) for v in msgs) )
# light blue
print("\033[01;34m" + msg + "\033[00m" )
class Connection_handler(asynchat.async_chat):
"""Abstract class for connection handling.
Subclass with implementation of the protocol"""
users = Users()
def __init__(self, sock, addr, manager):
asynchat.async_chat.__init__(self, sock)
# TODO: Make sure this is really the right one
# btw, is this exactly same with pop3 and smpt?
#self.set_terminator("\n") # netcat
self.set_terminator("\r\n")
self.users = Connection_handler.users
self.addr = addr
self.buffer = ""
self.manager = manager
def handle_command(self, data):
raise NotImplementedError, "must be implemented in subclass"
def found_terminator(self):
"""Fired when full line is recieved"""
self.handle_command(self.buffer)
self.buffer = ""
def handle_close(self):
"""Fired when client closes connection.
Can be also called by this class."""
self.close()
self.manager.remove_conn(self)
def __del__(self):
"""just testing"""
self.dmesg( "deleting object", self.addr )
def pushln(self, data=""):
"""use this method to send data to client"""
self.push(data + self.get_terminator())
def collect_incoming_data(self, data):
"""This is fired always when recieving data."""
self.buffer += str(data)
def handle_command(self, data):
raise NotImplementedError, "must be implemented in subclass"
def found_terminator(self):
"""Fired when full line is recieved"""
self.handle_command(self.buffer)
self.buffer = ""
def handle_close(self):
"""Fired when client closes connection.
Can be also called by this class."""
self.close()
self.manager.remove_conn(self)
def __del__(self):
"""just testing"""
self.dmesg( "deleting object", self.addr )
def dmesg(self, *msgs):
"""http://hacktux.com/bash/colors"""
msg = "%s> %s" % (self.__class__.__name__, " ".join(str(v) for v in msgs) )
# yellow
print( "\033[01;33m" + msg + "\033[00m" )