613 lines
21 KiB
Text
613 lines
21 KiB
Text
|
|
#!/usr/bin/python3
|
||
|
|
# -*- coding: utf-8 -*-
|
||
|
|
#import sys first so that if we bale in the following try we can still exit clean.
|
||
|
|
import sys
|
||
|
|
|
||
|
|
try:
|
||
|
|
# twisted imports
|
||
|
|
from twisted.internet.protocol import DatagramProtocol
|
||
|
|
from twisted.internet import reactor
|
||
|
|
|
||
|
|
# system imports
|
||
|
|
import codecs
|
||
|
|
import os
|
||
|
|
import re
|
||
|
|
import signal
|
||
|
|
import socket
|
||
|
|
import syslog
|
||
|
|
import time
|
||
|
|
except ImportError:
|
||
|
|
print("Some modules missing: requires Twisted among others.\n")
|
||
|
|
sys.exit(1)
|
||
|
|
|
||
|
|
##################################################################
|
||
|
|
os.chdir(os.path.dirname(__file__))
|
||
|
|
BaseDir = os.getcwd()
|
||
|
|
CRLF = "\r\n"
|
||
|
|
confdir = "conf"
|
||
|
|
conffile = "config.conf"
|
||
|
|
config = "/" + confdir + "/" + conffile
|
||
|
|
phonebookfile = BaseDir + "/" + confdir + "/addressbook.conf"
|
||
|
|
ITSP = "127.0.0.1"
|
||
|
|
##################################################################
|
||
|
|
|
||
|
|
def ReadConfig():
|
||
|
|
print("Read config")
|
||
|
|
try:
|
||
|
|
with codecs.open(BaseDir + config, 'r', encoding='utf-8') as configfile:
|
||
|
|
for line in configfile:
|
||
|
|
preconf(line)
|
||
|
|
except:
|
||
|
|
print("Error reading " + BaseDir + config + "\nAborting")
|
||
|
|
|
||
|
|
|
||
|
|
def CreateConfig():
|
||
|
|
print("Not found.\n")
|
||
|
|
print("Checking that " + BaseDir + "/" + confdir + " exists")
|
||
|
|
if (os.path.isdir(BaseDir + "/" + confdir) == False):
|
||
|
|
print("No. Attempting to create " + BaseDir + "/" + confdir)
|
||
|
|
try:
|
||
|
|
os.mkdir(BaseDir + "/" + confdir)
|
||
|
|
print("Success\n")
|
||
|
|
except OSError as e:
|
||
|
|
print("Can\'t create " + BaseDir + "/" + confdir)
|
||
|
|
print(e)
|
||
|
|
sys.exit(1)
|
||
|
|
except IOError as e:
|
||
|
|
print("Can\'t create " + BaseDir + "/" + confdir)
|
||
|
|
print(e)
|
||
|
|
sys.exit(1)
|
||
|
|
|
||
|
|
else:
|
||
|
|
print("Yes.")
|
||
|
|
print("Attempting to write configuration file " + BaseDir + config)
|
||
|
|
try:
|
||
|
|
fh = codecs.open(BaseDir + config, 'w', encoding='utf-8')
|
||
|
|
fh.write('\n')
|
||
|
|
except IOError as e:
|
||
|
|
print("Error: can\'t write file - " + BaseDir + config)
|
||
|
|
print(e)
|
||
|
|
sys.exit(1)
|
||
|
|
except OSError as e:
|
||
|
|
print("Error: can\'t write file - " + BaseDir + config)
|
||
|
|
print(e)
|
||
|
|
sys.exit(1)
|
||
|
|
else:
|
||
|
|
fh.close()
|
||
|
|
with codecs.open(BaseDir + config, 'w', encoding='utf-8') as configfile:
|
||
|
|
configfile.write("# This software was written as a shim for a Grandstream Budget One VOIP telephone\r")
|
||
|
|
configfile.write(" operating on an ipv4 lan, to add a phone book and get around the UDP NAT problem.\r")
|
||
|
|
configfile.write(" consequently it does not require a stun server or other black magic to operate.\r")
|
||
|
|
configfile.write(" It will probably work with other VOIP telephones\n")
|
||
|
|
configfile.write("# Prerequisites.\r")
|
||
|
|
configfile.write(" A VOIP telephone\r")
|
||
|
|
configfile.write(" A computer on which to run, that has either direct access to the Internet, or has\r")
|
||
|
|
configfile.write(" the following 3 UDP ports portforwarded from something that does.\r")
|
||
|
|
configfile.write(" 5060, 11110, and 11111\n")
|
||
|
|
configfile.write("# The important settings in your VOIP telephone are :- \n")
|
||
|
|
configfile.write(" IP address:\r")
|
||
|
|
configfile.write(" SIP Server:\r")
|
||
|
|
configfile.write(" Outbound Proxy:\r")
|
||
|
|
configfile.write(" local RTP port:\r")
|
||
|
|
configfile.write("# These must match up with the settings below or it just won\'t work \n")
|
||
|
|
configfile.write("# In this configuration file, there are no defaults,\r")
|
||
|
|
configfile.write("# lines beginning with white space are comments\r")
|
||
|
|
configfile.write(" Anything after a # is a comment\n")
|
||
|
|
configfile.write(" The configuration lines must begin in column 1\r")
|
||
|
|
configfile.write(" so each of the following lines needs a value.\n\n")
|
||
|
|
configfile.write("LocalPhoneIP = 192.168.0.42 # ip address of the VOIP telephone\n")
|
||
|
|
configfile.write("LocalPhonePort = 5004 # local RTP port: in the telephone's setup menu\n")
|
||
|
|
configfile.write("ThisBoxIP = 192.168.0.69 # the Internet connected box I am running on\r")
|
||
|
|
configfile.write(" this is also the Outbound Proxy: in your telephone's setup.\n")
|
||
|
|
configfile.write("PublicIP = 127.0.0.1 # Where the sip provider will send your incoming calls\n")
|
||
|
|
configfile.write("ITSP = sip.sipdiscount.com # (Internet Telephone Service Provider)\r")
|
||
|
|
configfile.write(" this the same as SIP Server: in your telephone\'s setup.\n")
|
||
|
|
configfile.write("UserID = bob_smith # SIP User ID: in your telephone\'s setup. This is used to \r")
|
||
|
|
configfile.write(" prevent random idiots making your phone ring whilst unsuccessfully\r")
|
||
|
|
configfile.write(" trying to steal your bandwidth/services.\n")
|
||
|
|
configfile.write("logfile = /var/log/phone.log # needs root to write to /var/log so use a file you have actual\r")
|
||
|
|
configfile.write(" permission to write to.\n")
|
||
|
|
configfile.write(" \n")
|
||
|
|
configfile.write(" \n")
|
||
|
|
print("Config file " + BaseDir + config + " successfully written.")
|
||
|
|
print("Additionally, " + BaseDir + config + " will require editing before you can continue.")
|
||
|
|
|
||
|
|
def preconf(line):
|
||
|
|
global LocalPhoneIP
|
||
|
|
global LocalPhonePort
|
||
|
|
global ThisBoxIP
|
||
|
|
global PublicIP
|
||
|
|
global ITSP
|
||
|
|
global UserID
|
||
|
|
global logfile
|
||
|
|
|
||
|
|
if(line[:12] == u"LocalPhoneIP"):
|
||
|
|
LocalPhoneIP = line.split("=")[1].strip()
|
||
|
|
LocalPhoneIP = LocalPhoneIP.split("#")[0].strip()
|
||
|
|
print("LocalPhoneIP = " + LocalPhoneIP)
|
||
|
|
|
||
|
|
if(line[:14] == u"LocalPhonePort"):
|
||
|
|
LocalPhonePort = line.split("=")[1].strip()
|
||
|
|
LocalPhonePort = LocalPhonePort.split("#")[0].strip()
|
||
|
|
print("LocalPhonePort = " + LocalPhonePort)
|
||
|
|
|
||
|
|
if(line[:9] == u"ThisBoxIP"):
|
||
|
|
ThisBoxIP = line.split("=")[1].strip()
|
||
|
|
ThisBoxIP = ThisBoxIP.split("#")[0].strip()
|
||
|
|
print("ThisBoxIP = " + ThisBoxIP)
|
||
|
|
|
||
|
|
if(line[:8] == u"PublicIP"):
|
||
|
|
PublicIP = line.split("=")[1].strip()
|
||
|
|
PublicIP = PublicIP.split("#")[0].strip()
|
||
|
|
print("PublicIP = " + PublicIP)
|
||
|
|
|
||
|
|
if(line[:4] == u"ITSP"):
|
||
|
|
ITSP = line.split("=")[1].strip()
|
||
|
|
ITSP = ITSP.split("#")[0].strip()
|
||
|
|
print("ITSP = " + ITSP)
|
||
|
|
|
||
|
|
if(line[:6] == u"UserID"):
|
||
|
|
UserID = line.split("=")[1].strip()
|
||
|
|
UserID = UserID.split("#")[0].strip()
|
||
|
|
print("UserID = " + UserID)
|
||
|
|
|
||
|
|
if(line[:7] == u"logfile"):
|
||
|
|
logfile = line.split("=")[1].strip()
|
||
|
|
logfile = logfile.split("#")[0].strip()
|
||
|
|
print("logfile = " + logfile)
|
||
|
|
|
||
|
|
def isip(addr):
|
||
|
|
try:
|
||
|
|
socket.inet_aton(addr)
|
||
|
|
return True
|
||
|
|
except socket.error:
|
||
|
|
return False
|
||
|
|
|
||
|
|
##################################################################
|
||
|
|
#variable
|
||
|
|
BookList = []
|
||
|
|
Destination = "127.0.0.1"
|
||
|
|
Remote_Audio_IP = "127.0.0.1"
|
||
|
|
Remote_Audio_Port = "61110"
|
||
|
|
Local_Audio_IP = "127.0.0.1"
|
||
|
|
Local_Audio_Port = "61110"
|
||
|
|
register_regex = 'CSeq: (.+?) REGISTER'
|
||
|
|
inviteSD_regex = 'INVITE sip:(.+?)@sipdiscount.com SIP/2'
|
||
|
|
register_pattern=re.compile(register_regex, flags=re.IGNORECASE)
|
||
|
|
inviteSD_pattern=re.compile(inviteSD_regex, flags=re.IGNORECASE)
|
||
|
|
##################################################################
|
||
|
|
class Sip(DatagramProtocol):
|
||
|
|
def datagramReceived(self, data, addr):
|
||
|
|
global Destination
|
||
|
|
try:
|
||
|
|
data = data.decode()
|
||
|
|
except UnicodeDecodeError as e:
|
||
|
|
print("random shite detected from " + addr[0])
|
||
|
|
print(e)
|
||
|
|
return
|
||
|
|
|
||
|
|
Time = time.strftime("%Y-%m-%d %H:%M:%S")
|
||
|
|
reg = re.findall(register_pattern,data)
|
||
|
|
if reg:
|
||
|
|
Destination = ITSP # Registration always with ITSP
|
||
|
|
print(Time, "From:", addr[0])
|
||
|
|
print(data[:12])
|
||
|
|
else:
|
||
|
|
try:
|
||
|
|
syslog.syslog("From " + addr[0])
|
||
|
|
syslog.syslog(data)
|
||
|
|
print(Time, "From:", addr[0])
|
||
|
|
print(data)
|
||
|
|
except TypeError:
|
||
|
|
syslog.syslog("TypeError")
|
||
|
|
print(Time, "TypeError:")
|
||
|
|
|
||
|
|
tdata = Proxy(data, addr)
|
||
|
|
|
||
|
|
if (addr[0] == LocalPhoneIP):
|
||
|
|
reg = re.findall(register_pattern,tdata)
|
||
|
|
if reg:
|
||
|
|
Destination = ITSP # Registration always with ITSP
|
||
|
|
self.transport.write(tdata.encode(), (Destination, 5060))
|
||
|
|
print(tdata[:12])
|
||
|
|
else:
|
||
|
|
syslog.syslog("To " + Destination)
|
||
|
|
syslog.syslog(tdata)
|
||
|
|
print(Time, "To:", Destination)
|
||
|
|
self.transport.write(tdata.encode(), (Destination, 5060))
|
||
|
|
print(tdata)
|
||
|
|
else:
|
||
|
|
if (addr[0] != LocalPhoneIP):
|
||
|
|
Logit(Time + " From ip: " + addr[0] + " " + data)
|
||
|
|
if (UserID in data):
|
||
|
|
Destination = addr[0]
|
||
|
|
reg = re.findall(register_pattern,tdata)
|
||
|
|
if reg:
|
||
|
|
self.transport.write(tdata.encode(), (LocalPhoneIP, 5060))
|
||
|
|
print(tdata[:12])
|
||
|
|
else:
|
||
|
|
syslog.syslog("To " + LocalPhoneIP)
|
||
|
|
syslog.syslog(tdata)
|
||
|
|
print(Time, "To:", LocalPhoneIP)
|
||
|
|
self.transport.write(tdata.encode(), (LocalPhoneIP, 5060))
|
||
|
|
print(tdata)
|
||
|
|
|
||
|
|
else:
|
||
|
|
Logit(Time + " From ip: " + addr[0] + " " + tdata)
|
||
|
|
|
||
|
|
##################################################################
|
||
|
|
|
||
|
|
def Proxy(data, addr):
|
||
|
|
if (addr[0] == LocalPhoneIP):
|
||
|
|
tdata = FromLocal(data, addr)
|
||
|
|
else:
|
||
|
|
tdata = FromRemote(data, addr)
|
||
|
|
if ("m=audio" in tdata):
|
||
|
|
return(tdata.strip() + CRLF)
|
||
|
|
else:
|
||
|
|
return(tdata.strip() + CRLF + CRLF)
|
||
|
|
|
||
|
|
##################################################################
|
||
|
|
|
||
|
|
def FromRemote(data, addr):
|
||
|
|
global Remote_Audio_IP # spurious, probably unneeded
|
||
|
|
|
||
|
|
data = data.replace(PublicIP, LocalPhoneIP)
|
||
|
|
data = data.replace(addr[0], ThisBoxIP)
|
||
|
|
data = Remote_SDP_Edit(data)
|
||
|
|
return data
|
||
|
|
|
||
|
|
##################################################################
|
||
|
|
|
||
|
|
def FromLocal(data, addr):
|
||
|
|
global Destination
|
||
|
|
data = FoneBook(data)
|
||
|
|
# Too many bugs, needs thinking about.
|
||
|
|
# reg = re.findall(register_pattern,data)
|
||
|
|
# if reg:
|
||
|
|
# Destination = ITSP
|
||
|
|
# print("Destination is " + Destination)
|
||
|
|
# data = data.replace(addr[0], PublicIP)
|
||
|
|
# data = Local_SDP_Edit(data)
|
||
|
|
# return data
|
||
|
|
#
|
||
|
|
# sd = re.findall(inviteSD_pattern,data)
|
||
|
|
# if sd:
|
||
|
|
# Destination = ITSP
|
||
|
|
# print("Destination is " + Destination)
|
||
|
|
# else:
|
||
|
|
# if ("INVITE sip:" in data):
|
||
|
|
# begin = data.find("@")
|
||
|
|
# begin = begin + 1
|
||
|
|
# nigeb = data.find(" ", begin)
|
||
|
|
# Destination = data[begin:nigeb]
|
||
|
|
# Destination = Destination.split(':')[0]
|
||
|
|
# print("Destination is " + Destination)
|
||
|
|
#
|
||
|
|
# if isip(Destination) == False:
|
||
|
|
# Destination = socket.gethostbyname(Destination)
|
||
|
|
#
|
||
|
|
# print("Destination is " + Destination)
|
||
|
|
data = data.replace(addr[0], PublicIP)
|
||
|
|
data = Local_SDP_Edit(data)
|
||
|
|
# print(data)
|
||
|
|
return data
|
||
|
|
|
||
|
|
##################################################################
|
||
|
|
|
||
|
|
class OutRTP(DatagramProtocol):
|
||
|
|
def datagramReceived(self, data, addr):
|
||
|
|
global Remote_Audio_IP
|
||
|
|
global Remote_Audio_Port
|
||
|
|
if (addr[0] == LocalPhoneIP):
|
||
|
|
dst = ((Remote_Audio_IP, int(Remote_Audio_Port)))
|
||
|
|
else:
|
||
|
|
dst = ((LocalPhoneIP, int(LocalPhonePort)))
|
||
|
|
self.transport.write(data, dst)
|
||
|
|
|
||
|
|
##################################################################
|
||
|
|
|
||
|
|
class OutRTCP(DatagramProtocol):
|
||
|
|
def datagramReceived(self, data, addr):
|
||
|
|
global Remote_Audio_IP
|
||
|
|
global Remote_Audio_Port
|
||
|
|
if (addr[0] == LocalPhoneIP):
|
||
|
|
dst = ((Remote_Audio_IP, int(Remote_Audio_Port) + 1))
|
||
|
|
else:
|
||
|
|
dst = ((LocalPhoneIP, (int(LocalPhonePort) + 1)))
|
||
|
|
self.transport.write(data, dst)
|
||
|
|
|
||
|
|
##################################################################
|
||
|
|
|
||
|
|
def FoneBook(data):
|
||
|
|
for line in BookList:
|
||
|
|
if (line.split("=")[0] in data):
|
||
|
|
data = data.replace(line.split("=")[0],line.split("=")[1])
|
||
|
|
return data
|
||
|
|
|
||
|
|
##################################################################
|
||
|
|
|
||
|
|
def Local_SDP_Edit(data): #fiddle with data from localphone
|
||
|
|
global Local_Audio_IP
|
||
|
|
global Local_Audio_Port
|
||
|
|
if ("m=audio" in data):
|
||
|
|
PortA = data.split("m=audio ")[1]
|
||
|
|
Local_Audio_Port = PortA.split()[0]
|
||
|
|
IPA = data.split("c=IN IP4 ")[1]
|
||
|
|
Local_Audio_IP = IPA.split()[0]
|
||
|
|
data = data.replace("m=audio " + Local_Audio_Port, "m=audio 11110")
|
||
|
|
data = data.replace("IN IP4 " + Local_Audio_IP, "IN IP4 " + PublicIP)
|
||
|
|
First = data.split("Content-Length: ")[0] + "Content-Length: "
|
||
|
|
Second = data.split(CRLF + CRLF)[1]
|
||
|
|
ilength = len(Second)
|
||
|
|
return First + str(ilength) + CRLF + CRLF + Second
|
||
|
|
else:
|
||
|
|
return data
|
||
|
|
|
||
|
|
##################################################################
|
||
|
|
|
||
|
|
def Remote_SDP_Edit(data): #fiddle with data from remotephone
|
||
|
|
global Remote_Audio_IP
|
||
|
|
global Remote_Audio_Port
|
||
|
|
if ("m=audio" in data):
|
||
|
|
PortA = data.split("m=audio ")[1]
|
||
|
|
Remote_Audio_Port = PortA.split()[0]
|
||
|
|
IPA = data.split("c=IN IP4 ")[1]
|
||
|
|
Remote_Audio_IP= IPA.split()[0]
|
||
|
|
data = data.replace("m=audio " + Remote_Audio_Port, "m=audio 11110")
|
||
|
|
data = data.replace("IN IP4 " + Remote_Audio_IP, "IN IP4 " + ThisBoxIP)
|
||
|
|
First = data.split("Content-Length: ")[0] + "Content-Length: "
|
||
|
|
Second = data.split(CRLF + CRLF)[1]
|
||
|
|
ilength = len(Second)
|
||
|
|
return First + str(ilength) + CRLF + CRLF + Second
|
||
|
|
else:
|
||
|
|
return data
|
||
|
|
|
||
|
|
##################################################################
|
||
|
|
|
||
|
|
def signal_handler(sig, frame):
|
||
|
|
print
|
||
|
|
print("signal", sig)
|
||
|
|
Time = time.strftime("%Y-%m-%d %H:%M:%S")
|
||
|
|
print(Time, "Shutting down")
|
||
|
|
reactor.stop()
|
||
|
|
print('reactor stopped')
|
||
|
|
syslog.syslog("SIGINT - Shutting Down!")
|
||
|
|
os._exit(0)
|
||
|
|
syslog.syslog("Not Visible in syslog.")
|
||
|
|
quit()
|
||
|
|
|
||
|
|
|
||
|
|
##################################################################
|
||
|
|
def MkFoneBook():
|
||
|
|
Blurb001 = "# This fonebook is crude, the error checking is minimal, so if you screw it up, then it wont work.\n"
|
||
|
|
Blurb002 = "# However, if you delete the screwed up copy, the basic file will be recreated by SipProxy.\n\n"
|
||
|
|
Blurb003 = "# Lines beginning with # are ignored, as are lines consisting solely of whitespace and blank lines.\n#\n"
|
||
|
|
Blurb004 = "#Replace=With\n"
|
||
|
|
|
||
|
|
Blurb005 = "#01* Geographic area codes.\n"
|
||
|
|
Blurb006 = "INVITE sip:01=INVITE sip:00441\n"
|
||
|
|
Blurb007 = "ACK sip:01=ACK sip:00441\n"
|
||
|
|
Blurb008 = "BYE sip:01=BYE sip:00441\n"
|
||
|
|
Blurb009 = "CANCEL sip:01=CANCEL sip:00441\n\n"
|
||
|
|
|
||
|
|
Blurb010 = "#02* Geographic area codes (introduced in 2000).\n"
|
||
|
|
Blurb011 = "INVITE sip:02=INVITE sip:00442\n"
|
||
|
|
Blurb012 = "ACK sip:02=ACK sip:00442\n"
|
||
|
|
Blurb013 = "BYE sip:02=BYE sip:00442\n"
|
||
|
|
Blurb014 = "CANCEL sip:02=CANCEL sip:00442\n\n"
|
||
|
|
|
||
|
|
Blurb015 = "#03* Nationwide non-geographic code, charged to caller at geographic area code rates (introduced 2007).\n"
|
||
|
|
Blurb016 = "INVITE sip:03=INVITE sip:00443\n"
|
||
|
|
Blurb017 = "ACK sip:03=ACK sip:00443\n"
|
||
|
|
Blurb018 = "BYE sip:03=BYE sip:00443\n"
|
||
|
|
Blurb019 = "CANCEL sip:03=CANCEL sip:00443\n\n"
|
||
|
|
|
||
|
|
Blurb020 = "#05* Corporate numbering and VoIP services\n"
|
||
|
|
Blurb021 = "INVITE sip:05=INVITE sip:00445\n"
|
||
|
|
Blurb022 = "ACK sip:05=ACK sip:00445\n"
|
||
|
|
Blurb023 = "BYE sip:05=BYE sip:00445\n"
|
||
|
|
Blurb024 = "CANCEL sip:05=CANCEL sip:00445\n\n"
|
||
|
|
|
||
|
|
Blurb025 = "#07* Mostly for mobile phones\n"
|
||
|
|
Blurb026 = "INVITE sip:07=INVITE sip:00447\n"
|
||
|
|
Blurb027 = "ACK sip:07=ACK sip:00447\n"
|
||
|
|
Blurb028 = "BYE sip:07=BYE sip:00447\n"
|
||
|
|
Blurb029 = "CANCEL sip:07=CANCEL sip:00447\n\n"
|
||
|
|
|
||
|
|
Blurb030 = "#08* Freephone (toll free) on 080, and Special Services (formerly known as local and national rate) on 084 and 087.\n"
|
||
|
|
Blurb031 = "INVITE sip:08=INVITE sip:00448\n"
|
||
|
|
Blurb032 = "ACK sip:08=ACK sip:00448\n"
|
||
|
|
Blurb033 = "BYE sip:08=BYE sip:00448\n"
|
||
|
|
Blurb034 = "CANCEL sip:08=CANCEL sip:00448\n\n"
|
||
|
|
|
||
|
|
Blurb035 = "#The following numbers are for Scunthorpe (01724) local numbers.\n"
|
||
|
|
Blurb036 = "INVITE sip:2=INVITE sip:004417242\n"
|
||
|
|
Blurb037 = "ACK sip:2=ACK sip:004417242\n"
|
||
|
|
Blurb038 = "BYE sip:2=BYE sip:004417242\n"
|
||
|
|
Blurb039 = "CANCEL sip:2=CANCEL sip:004417242\n\n"
|
||
|
|
|
||
|
|
Blurb040 = "INVITE sip:3=INVITE sip:004417243\n"
|
||
|
|
Blurb041 = "ACK sip:3=ACK sip:004417243\n"
|
||
|
|
Blurb042 = "BYE sip:3=BYE sip:004417243\n"
|
||
|
|
Blurb043 = "CANCEL sip:3=CANCEL sip:004417243\n\n"
|
||
|
|
|
||
|
|
Blurb044 = "INVITE sip:7=INVITE sip:004417247\n"
|
||
|
|
Blurb045 = "ACK sip:7=ACK sip:004417247\n"
|
||
|
|
Blurb046 = "BYE sip:7=BYE sip:004417247\n"
|
||
|
|
Blurb047 = "CANCEL sip:7=CANCEL sip:004417247\n\n"
|
||
|
|
|
||
|
|
Blurb048 = "INVITE sip:8=INVITE sip:004417248\n"
|
||
|
|
Blurb049 = "ACK sip:8=ACK sip:004417248\n"
|
||
|
|
Blurb050 = "BYE sip:8=BYE sip:004417248\n"
|
||
|
|
Blurb051 = "CANCEL sip:8=CANCEL sip:004417248\n\n"
|
||
|
|
|
||
|
|
Blurb052 = "# Here can be placed upto 100, 3 digit, speed dial shortcuts, from 100 to 199.\n"
|
||
|
|
Blurb053 = "# Each entry is a pair of lines, firstly the #speed dial number and description.\n"
|
||
|
|
Blurb054 = "# Secondly the 'Replace=With' for the preceeding line.\n\n"
|
||
|
|
|
||
|
|
Blurb0541 = "# As far as the telephone is concerned, all traffic goes to sipdiscount.com\n"
|
||
|
|
Blurb0542 = "# so if we want it go elsewhere we need to check the destination after the phonebook\n"
|
||
|
|
Blurb0543 = "# has fiddled with it and set the destination accordingly.\n\n"
|
||
|
|
|
||
|
|
Blurb055 = "#100 Example speed dial 1\n"
|
||
|
|
Blurb056 = "INVITE sip:100@sip.sipdiscount.com=INVITE sip:00441724280280@sip.sipdiscount.com\n"
|
||
|
|
Blurb057 = "ACK sip:100@sip.sipdiscount.com=ACK sip:00441724280280@sip.sipdiscount.com\n"
|
||
|
|
Blurb058 = "BYE sip:100@sip.sipdiscount.com=BYE sip:00441724280280@sip.sipdiscount.com\n"
|
||
|
|
Blurb059 = "CANCEL sip:100@sip.sipdiscount.com=CANCEL sip:00441724280280@sip.sipdiscount.com\n\n"
|
||
|
|
|
||
|
|
Blurb060 = "#101 Example speed dial 2\n"
|
||
|
|
Blurb061 = "INVITE sip:101@sip.sipdiscount.com=INVITE sip:00441724855555@sip.sipdiscount.com\n"
|
||
|
|
Blurb062 = "ACK sip:101@sip.sipdiscount.com=ACK sip:00441724855555@sip.sipdiscount.com\n"
|
||
|
|
Blurb063 = "BYE sip:101@sip.sipdiscount.com=BYE sip:00441724855555@sip.sipdiscount.com\n"
|
||
|
|
Blurb064 = "CANCEL sip:101@sip.sipdiscount.com=CANCEL sip:00441724855555@sip.sipdiscount.com\n"
|
||
|
|
|
||
|
|
try:
|
||
|
|
fh = codecs.open(phonebookfile, 'w', encoding='utf-8')
|
||
|
|
fh.write(Blurb001)
|
||
|
|
fh.write(Blurb002)
|
||
|
|
fh.write(Blurb003)
|
||
|
|
fh.write(Blurb004)
|
||
|
|
fh.write(Blurb005)
|
||
|
|
fh.write(Blurb006)
|
||
|
|
fh.write(Blurb007)
|
||
|
|
fh.write(Blurb008)
|
||
|
|
fh.write(Blurb009)
|
||
|
|
fh.write(Blurb010)
|
||
|
|
fh.write(Blurb011)
|
||
|
|
fh.write(Blurb012)
|
||
|
|
fh.write(Blurb013)
|
||
|
|
fh.write(Blurb014)
|
||
|
|
fh.write(Blurb015)
|
||
|
|
fh.write(Blurb016)
|
||
|
|
fh.write(Blurb017)
|
||
|
|
fh.write(Blurb018)
|
||
|
|
fh.write(Blurb019)
|
||
|
|
fh.write(Blurb020)
|
||
|
|
fh.write(Blurb021)
|
||
|
|
fh.write(Blurb022)
|
||
|
|
fh.write(Blurb023)
|
||
|
|
fh.write(Blurb024)
|
||
|
|
fh.write(Blurb025)
|
||
|
|
fh.write(Blurb026)
|
||
|
|
fh.write(Blurb027)
|
||
|
|
fh.write(Blurb028)
|
||
|
|
fh.write(Blurb029)
|
||
|
|
fh.write(Blurb030)
|
||
|
|
fh.write(Blurb031)
|
||
|
|
fh.write(Blurb032)
|
||
|
|
fh.write(Blurb033)
|
||
|
|
fh.write(Blurb034)
|
||
|
|
fh.write(Blurb035)
|
||
|
|
fh.write(Blurb036)
|
||
|
|
fh.write(Blurb037)
|
||
|
|
fh.write(Blurb038)
|
||
|
|
fh.write(Blurb039)
|
||
|
|
fh.write(Blurb040)
|
||
|
|
fh.write(Blurb041)
|
||
|
|
fh.write(Blurb042)
|
||
|
|
fh.write(Blurb043)
|
||
|
|
fh.write(Blurb044)
|
||
|
|
fh.write(Blurb045)
|
||
|
|
fh.write(Blurb046)
|
||
|
|
fh.write(Blurb047)
|
||
|
|
fh.write(Blurb048)
|
||
|
|
fh.write(Blurb049)
|
||
|
|
fh.write(Blurb050)
|
||
|
|
fh.write(Blurb051)
|
||
|
|
fh.write(Blurb052)
|
||
|
|
fh.write(Blurb053)
|
||
|
|
fh.write(Blurb054)
|
||
|
|
fh.write(Blurb0541)
|
||
|
|
fh.write(Blurb0542)
|
||
|
|
fh.write(Blurb0543)
|
||
|
|
fh.write(Blurb055)
|
||
|
|
fh.write(Blurb056)
|
||
|
|
fh.write(Blurb057)
|
||
|
|
fh.write(Blurb058)
|
||
|
|
fh.write(Blurb059)
|
||
|
|
fh.write(Blurb060)
|
||
|
|
fh.write(Blurb061)
|
||
|
|
fh.write(Blurb062)
|
||
|
|
fh.write(Blurb063)
|
||
|
|
fh.write(Blurb064)
|
||
|
|
except IOError:
|
||
|
|
pass
|
||
|
|
else:
|
||
|
|
print("Phone book written")
|
||
|
|
print("The phone book will need to be edited to create your speed dial")
|
||
|
|
print("shortcuts and to map your local exchange. This is not absolutely")
|
||
|
|
print("necessary immediately, and sipproxy will still function regardless.")
|
||
|
|
fh.close()
|
||
|
|
##################################################################
|
||
|
|
def Logit(Blurb):
|
||
|
|
try:
|
||
|
|
fh = codecs.open(logfile, 'a', encoding='utf-8')
|
||
|
|
Blurb = Blurb.replace("\n","\\n")
|
||
|
|
Blurb = Blurb.replace("\r","\\r")
|
||
|
|
fh.write(Blurb)
|
||
|
|
fh.write("\n")
|
||
|
|
except IOError:
|
||
|
|
pass
|
||
|
|
else:
|
||
|
|
fh.close()
|
||
|
|
|
||
|
|
##################################################################
|
||
|
|
|
||
|
|
def ReadFoneBook():
|
||
|
|
global BookList
|
||
|
|
try:
|
||
|
|
with codecs.open(phonebookfile, 'r', encoding='utf-8') as config:
|
||
|
|
for line in config:
|
||
|
|
if line[:1] != "#" and line.strip() != "":
|
||
|
|
BookList.append(line.strip())
|
||
|
|
|
||
|
|
except IOError:
|
||
|
|
pass
|
||
|
|
|
||
|
|
##################################################################
|
||
|
|
print("\n\n\n\n\n\n")
|
||
|
|
print(" ____ ____")
|
||
|
|
print(" / ___) _ ____ | _ \\")
|
||
|
|
print("( (___ (_)| _ \| |_) )_ __ ___ __ ____ __")
|
||
|
|
print(" \__ \| || |_) | __/| '__/ _ \\\ \/ /\ \/ /")
|
||
|
|
print(" ___) | || __/| | | | ( (_) )> < \ / ")
|
||
|
|
print("(_____/|_||_| |_| |_| \___//_/\_\ /_/ ")
|
||
|
|
print("\n\n\n\n\n\n")
|
||
|
|
print("The all new and improved sipproxy running under Python " + (sys.version))
|
||
|
|
print("Initialising " + __file__)
|
||
|
|
print("Looking for " + BaseDir + config)
|
||
|
|
if os.path.isfile(BaseDir + config):
|
||
|
|
result = ReadConfig()
|
||
|
|
else:
|
||
|
|
result = CreateConfig()
|
||
|
|
if os.path.isfile(phonebookfile):
|
||
|
|
print("Phone book already exists, not overwriting")
|
||
|
|
sys.exit(0)
|
||
|
|
else:
|
||
|
|
result = MkFoneBook()
|
||
|
|
sys.exit(0)
|
||
|
|
|
||
|
|
if isip(ITSP) == False:
|
||
|
|
Destination = socket.gethostbyname(ITSP)
|
||
|
|
ITSP = Destination
|
||
|
|
print("ITSP = " + Destination)
|
||
|
|
else:
|
||
|
|
Destination = ITSP
|
||
|
|
|
||
|
|
if os.path.isfile(phonebookfile):
|
||
|
|
result = ReadFoneBook()
|
||
|
|
else:
|
||
|
|
result = MkFoneBook()
|
||
|
|
|
||
|
|
signal.signal(signal.SIGINT, signal_handler)
|
||
|
|
Time = time.strftime("%Y-%m-%d %H:%M:%S")
|
||
|
|
print(Time, "Everything started up")
|
||
|
|
Logit(Time + "Started up OK")
|
||
|
|
syslog.syslog("Everything started up")
|
||
|
|
reactor.listenUDP(5060, Sip())
|
||
|
|
reactor.listenUDP(11110, OutRTP())
|
||
|
|
reactor.listenUDP(11111, OutRTCP())
|
||
|
|
reactor.run()
|
||
|
|
|