1 # Copyright (c) Stas Shtin, 2010
3 # This file is part of IPyPBX.
5 # IPyPBX is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU General Public License as published by
7 # the Free Software Foundation, either version 3 of the License, or
8 # (at your option) any later version.
10 # IPyPBX is distributed in the hope that it will be useful,
11 # but WITHOUT ANY WARRANTY; without even the implied warranty of
12 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 # GNU General Public License for more details.
15 # You should have received a copy of the GNU General Public License
16 # along with IPyPBX. If not, see <http://www.gnu.org/licenses/>.
18 from PyQt4 import QtCore, QtNetwork
21 class FreeswitchConfigServer(QtNetwork.QTcpServer):
23 TCP server that receives config requests from freeswitch.
25 def __init__(self, parent=None):
26 super(FreeswitchConfigServer, self).__init__(parent)
30 self.is_running = False
32 self.httpRequestParser = HttpRequestParser()
34 def setSocketData(self, host, port):
36 Set host and port for socket to listen on.
41 def startServer(self):
43 Start listening on our socket.
45 if not self.is_running:
46 if self.host and self.port:
47 self.newConnection.connect(self.clientConnecting)
48 self.listen(QtNetwork.QHostAddress(self.host), self.port)
49 self.is_running = True
53 Stop listening on our socket.
57 self.is_running = False
59 def restartServer(self):
66 def clientConnecting(self):
68 Handle client connection.
70 if self.hasPendingConnections():
71 self.socket = self.nextPendingConnection()
72 self.socket.readyRead.connect(self.receiveData)
74 def receiveData(self):
75 while self.socket.canReadLine():
76 line = str(self.socket.readLine()).strip()
78 self.httpRequestParser.handle(line)
81 class HttpParseError(Exception):
83 Error parsing HTTP request.
87 class HttpRequestParser(object):
89 A simple state machine for parsing HTTP requests.
91 HTTP_NONE, HTTP_REQUEST, HTTP_HEADERS, HTTP_EMPTY, HTTP_MESSAGE = range(5)
92 HTTP_STATES = ['NONE', 'REQUEST', 'HEADERS', 'EMPTY', 'MESSAGE']
95 super(HttpRequestParser, self).__init__()
100 Reset parser to initial state.
102 # Initial values for request data.
104 self.request_path = None
105 self.http_version = None
109 self.state = self.HTTP_NONE
111 def handle(self, line):
113 Dispatch line to current state handler.
115 for state in self.HTTP_STATES:
116 if getattr(self, 'HTTP_%s' % state) == self.state:
117 getattr(self, 'handle%s' % state.title())(line)
120 raise HttpParseError('Unknown HTTP state')
122 def handleNone(self, line):
124 Pass line to next state.
129 def handleRequest(self, line):
131 Retrieve HTTP method, request path and HTTP version from request.
133 self.method, self.request_path, self.http_version = line.split(' ')
136 def handleHeaders(self, line):
138 Parse headers while not found an empty line.
141 key, value = line.split(': ')
142 self.headers[key] = value
146 def handleEmpty(self, line):
148 Empty line separator is found - proceed to next state.
152 def handleMessage(self, line):
154 Append to message body.