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 setSocket(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, socket):
68 Handle client connection.
70 if self.hasPendingConnections():
71 connectingClient = self.server.nextPendingConnection()
72 connectingClient.readyRead.connect(self.receiveData)
74 def receiveData(self, socket):
75 while socket.canReadLine():
76 line = socket.readLine().strip()
79 class HttpParseError(Exception):
81 Error parsing HTTP request.
85 class HttpRequestParser(object):
87 A simple state machine for parsing HTTP requests.
89 HTTP_NONE, HTTP_REQUEST, HTTP_HEADERS, HTTP_EMPTY, HTTP_MESSAGE = range(5)
90 HTTP_STATES = ['NONE', 'REQUEST', 'HEADERS', 'EMPTY', 'MESSAGE']
93 super(HttpParser, self).__init__()
97 Reset parser to initial state.
99 # Initial values for request data.
101 self.request_path = None
102 self.http_version = None
106 self.state = HTTP_NONE
108 def handle(self, line):
110 Dispatch line to current state handler.
112 for state in HTTP_STATES:
113 if getattr(self, 'HTTP_%s' % state) == self.state:
114 getattr(self, 'handle%s' % state.title()).(line)
117 raise HttpParseError('Unknown HTTP state')
119 def handleNone(self, line):
121 Pass line to next state.
126 def handleRequest(self, line):
128 Retrieve HTTP method, request path and HTTP version from request.
130 self.method, self.request_path, self.http_version = line.split(' ')
133 def handleHeaders(self, line):
135 Parse headers while not found an empty line.
138 key, value = line.split(': ')
139 self.headers[key] = value
143 def handleEmpty(self, line):
145 Empty line separator is found - proceed to next state.
149 def handleMessage(self, line):
151 Append to message body.