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 # TODO: read in chunks.
76 for line in str(self.socket.readAll()).split('\r\n'):
77 self.httpRequestParser.handle(line)
80 class HttpParseError(Exception):
82 Error parsing HTTP request.
86 class HttpRequestParser(object):
88 A simple state machine for parsing HTTP requests.
90 HTTP_NONE, HTTP_REQUEST, HTTP_HEADERS, HTTP_EMPTY, HTTP_MESSAGE = range(5)
91 HTTP_STATES = ['NONE', 'REQUEST', 'HEADERS', 'EMPTY', 'MESSAGE']
94 super(HttpRequestParser, self).__init__()
99 Reset parser to initial state.
101 # Initial values for request data.
103 self.request_path = None
104 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 print self.state, line
118 getattr(self, 'handle%s' % state.title())(line)
121 raise HttpParseError('Unknown HTTP state')
123 def handleNone(self, line):
125 Pass line to next state.
130 def handleRequest(self, line):
132 Retrieve HTTP method, request path and HTTP version from request.
134 self.method, self.request_path, self.http_version = line.split(' ')
137 def handleHeaders(self, line):
139 Parse headers while not found an empty line.
142 key, value = line.split(': ')
143 self.headers[key] = value
148 def handleEmpty(self, line):
150 Empty line separator is found - proceed to next state.
154 def handleMessage(self, line):
156 Append to message body.
158 self.data = dict(pair.split('=', 2) for pair in line.split('&'))