Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- from multiprocessing import Process
- import socket,time,sqlite3,time,os,random
- try:
- import serv_settings
- except:
- f = open("serv_settings.py","w")
- t = '''
- IP_ADDRESS = ""
- PORT = 9090
- KEY_DECAY_TIME = 3600
- ONLINE_CONFIRM_TIME = 600
- LOGGING = 1
- LOGFOLDER = "logs"
- MAX_CLIENTS = 100
- '''
- f.write(t)
- f.close()
- import serv_settings
- def error_p(errmsg):
- print("Error: "+errmsg)
- def logmsg(logmsg):
- a = time.strftime("%H-%M %d %h %Y")
- print(a+": "+logmsg)
- def add_nulls(dlen,data):
- to_ret = data
- if(len(data)<dlen):
- dif = dlen-len(data)
- to_ret = "0"*dif+to_ret
- return to_ret
- class logging_db:
- def __init__(self):
- cur,connection = self.connect_to_db()
- cur.execute('''
- CREATE TABLE IF NOT EXISTS errlogs(
- ADDR TEXT,
- DATE TEXT,
- ERROR TEXT)
- ''')
- cur.execute('''
- CREATE TABLE IF NOT EXISTS traffics(
- ADDR TEXT,
- TYPE TEXT,
- AMOUNT INTEGER)
- ''')#amount in bytes
- connection.commit()
- connection.close()
- #todo
- #make traffic counting
- #make error logging here
- #traffic counted by dates and users
- #tables must be wiped sometimes))))00000
- def add_traffic(self,addr,ttype,amount):
- cur,connection = self.connect_to_db()
- cur.execute("SELECT AMOUNT FROM traffics WHERE ADDR = ? AND TYPE = ?",(addr,ttype))
- d = cur.fetchone()
- if(d!=None):
- num = d[0]
- num+=amount
- cur.execute("UPDATE traffics SET AMOUNT = ? WHERE ADDR = ? AND TYPE = ?",(num,addr,ttype))
- else:
- cur.execute("INSERT INTO traffics VALUES (?,?,?)",(addr,ttype,amount))
- connection.commit()
- connection.close()
- def add_error(self,addr,error):
- date = time.time()
- cur,connection = self.connect_to_db()
- cur.execute("INSERT INTO errlogs VALUES (?,?,?)",(addr,str(date),error))
- connection.commit()
- connection.close()
- def connect_to_db(self):
- try:
- connection = sqlite3.connect(serv_settings.LOGFOLDER+"/"+"log.db")
- except:
- os.mkdir(serv_settings.LOGFOLDER)
- connection = sqlite3.connect(serv_settings.LOGFOLDER+"/"+"log.db")
- cur = connection.cursor()
- return(cur,connection)
- class dbwork:
- #1)login,password,id - logindata
- #2)id,key,time_to_change_key - keys
- #3)id,time_to_offline - onlines
- #4)id,unread_messages - messages
- def __init__(self):
- cur,connection = self.connect_to_db()
- #creating tables
- cur.execute('''
- CREATE TABLE IF NOT EXISTS logindata(
- ID INTEGER PRIMARY KEY,
- LOGIN TEXT,
- PASSWORD TEXT)
- ''')
- cur.execute('''
- CREATE TABLE IF NOT EXISTS keys(
- ID INTEGER,
- KEY INTEGER,
- DTIME INTEGER)
- ''')
- cur.execute('''
- CREATE TABLE IF NOT EXISTS onlines(
- ID INTEGER PRIMARY KEY,
- OTIME INTEGER)
- ''')
- cur.execute('''
- CREATE TABLE IF NOT EXISTS messages(
- ID INTEGER,
- MESSAGE BLOB)
- ''')#ID of the user to recive message
- connection.commit()
- connection.close()
- def connect_to_db(self):
- connection = sqlite3.connect("chatdb.db")
- cur = connection.cursor()
- return(cur,connection)
- def generate_key(self,ID): #generates a new key for given ID
- random.seed()
- cur,connection = self.connect_to_db()
- key = random.randint(10000000,99999999)
- ok = 0
- while(ok==0): #generating a unique key for messaging
- cur.execute("SELECT * FROM keys WHERE KEY = ?",(key,))
- if(cur.fetchone()==None):
- ok = 1
- break
- else:
- key = random.randint(10000000,99999999)
- cur.execute("SELECT * FROM keys WHERE ID = ?",(ID,)) #checking if the
- dtime = time.time()+serv_settings.KEY_DECAY_TIME #ID in table
- if(cur.fetchone()==None):
- cur.execute("INSERT INTO keys VALUES (?,?,?)",(ID,key,dtime))
- else:
- cur.execute("UPDATE keys SET KEY = ?, DTIME = ? WHERE ID = ?",(key,dtime,ID))
- connection.commit()
- connection.close()
- return(key)
- def get_messages(self,ID):
- cur,connection = self.connect_to_db()
- cur.execute("SELECT MESSAGE FROM messages WHERE ID = ?",(ID,))
- msgs = cur.fetchall()
- msgdata = b""
- if(msgs==[]):
- connection.close()
- return(0)
- else:
- for msg in msgs:
- message = msg[0]
- msgdata+=message
- cur.execute("DELETE FROM messages WHERE ID = ?",(ID,))
- connection.commit()
- connection.close()
- return(msgdata)
- def get_ID_by_login(self,login):
- cur,connection = self.connect_to_db()
- cur.execute("SELECT ID FROM logindata WHERE LOGIN = ?",(login,))
- ID = cur.fetchone()[0]
- connection.close()
- return(ID)
- def get_key(self,ID): #returns a key for given ID
- cur,connection = self.connect_to_db()
- cur.execute("SELECT KEY FROM keys WHERE ID = ?",(ID,))
- key = cur.fetchone()
- if(key!=None):
- key=key[0]
- connection.close()
- return(key)
- def get_key_dtime(self,ID):
- cur,connection = self.connect_to_db()
- cur.execute("SELECT DTIME FROM keys WHERE ID = ?",(ID,))
- dtime = cur.fetchone()
- if(dtime!=None):
- dtime=dtime[0]
- connection.close()
- return(dtime)
- def get_ID_by_key(self,key):
- cur,connection = self.connect_to_db()
- cur.execute("SELECT ID, DTIME FROM keys WHERE key = ?",(key,))
- uid = cur.fetchone()
- connection.close()
- if(uid==None):
- return(-1)#no such key
- else:
- dtime = uid[1]
- uid = uid[0]
- if(dtime<time.time()):
- return(-2)#timed out key
- else:
- return(uid)
- def update_user_online(self,ID):
- otime = time.time()+serv_settings.ONLINE_CONFIRM_TIME
- cur,connection = self.connect_to_db()
- cur.execute("REPLACE INTO onlines VALUES(?,?)",(ID,otime))
- connection.commit()
- connection.close()
- def get_users_online(self):
- ctime = time.time()
- cur,connection = self.connect_to_db()
- cur.execute("SELECT ID FROM onlines WHERE OTIME > ?",(ctime,))
- onlineIDs = cur.fetchall()
- onlines = []
- if(onlineIDs == []):
- return([])
- else:
- for oid in onlineIDs:
- onlines.append(oid[0])
- return(onlines)
- def add_message(self,ID,msg):
- cur,connection = self.connect_to_db()
- cur.execute("INSERT INTO messages VALUES(?,?)",(ID,msg))
- connection.commit()
- connection.close()
- def login(self,login,password):
- cur,connection = self.connect_to_db()
- cur.execute("SELECT * FROM logindata WHERE LOGIN = ?",(login,))
- udata = cur.fetchone()
- if(udata==None):
- cur.execute("INSERT INTO logindata VALUES (NULL,?,?)",(login,password))
- connection.commit()
- connection.close()
- ID = self.get_ID_by_login(login)
- key = self.generate_key(ID)
- self.update_user_online(ID)
- return([0,key]) #OK - new registered
- else:
- if(udata[2]==password):
- connection.close()
- ID = self.get_ID_by_login(login)
- key = self.generate_key(ID)
- self.update_user_online(ID)
- return([0,key]) #OK - ok login&pwd
- else:
- connection.close()
- return([1,0]) #login already exists(it means - password incorrect)
- class client_job:
- def send_close(self,data):
- self.send_msg(data)
- self.conn.close()
- def send_msg(self,data):
- count = 0
- try:
- try:
- self.conn.send(data.encode("utf-8"))
- count = len(data.encode("utf-8"))
- except:
- self.conn.send(data)
- count = len(data)
- except:
- self.write_log("error sending to: "+str(self.addr))
- return
- self.count_traffic(count,"out")
- def answer_ask_chk(self):
- self.ID = self.database.get_ID_by_key(self.key)
- if(self.ID>0):
- dtime = self.database.get_key_dtime(self.ID)
- dtime-=time.time()
- dtime = add_nulls(4,str(dtime))
- self.database.update_user_online(self.ID)
- self.send_msg("OK"+dtime)
- return(-1)
- else:
- if(self.ID==-1):
- self.error = 5 #wrong key
- else:
- self.error = 6 #key timed out
- return(0)
- def read_ask_msg(self,data):
- try:
- ask_m = data.decode("utf-8")
- except:
- self.error = 1 #encoding failure
- return(0)
- if(len(ask_m)!=11):
- self.error = 3 #message badly structured
- return(0)
- mtype = ask_m[:3]
- if(mtype=="CHK"):
- try:
- self.key = int(ask_m[3:])
- except:
- self.error = 5
- return(0)
- return self.answer_ask_chk()
- if(mtype=="MES"):
- try:
- self.protocol = int(ask_m[3:7])
- ret_bytes = int(ask_m[7:])
- except:
- self.error = 1
- return(0)
- return ret_bytes
- else:
- self.error = 2 #unknown initiation
- return(0)
- def check_key_ID(self):
- realID = self.database.get_ID_by_key(self.key)
- if(realID==self.ID):
- return(1)
- else:
- if(realID==-1):
- self.error = 5
- return(0)
- else:
- self.error = 6
- return(0)
- def process_message(self,trg_ID,message):
- if(self.check_key_ID()==1):
- if(self.database.get_key(trg_ID)==None):
- self.error = 9
- return(0)
- else:
- msglen = str(add_nulls(4,str(len(message)))).encode("utf-8")
- sender = str(add_nulls(8,str(self.ID))).encode("utf-8")
- dbmsg = sender+msglen+message #add a sender's ID and msglen
- self.database.add_message(trg_ID,dbmsg)
- self.database.update_user_online(self.ID)
- msg = "OK"+add_nulls(16,"")
- self.send_msg(msg)
- return(-1)
- else:
- self.error = 5
- return(0)
- def read_msg(self,data,len_m):
- if(len(data)!=len_m):
- self.error = 3
- return(0)
- try:
- mtype = data[:3].decode("utf-8")
- except:
- self.error = 1
- return(0)
- if(data[-3:].decode("utf-8")!="FIN"):
- self.error = 3
- return(0)
- if(mtype=="MSG"):#messages can be not a unicode str
- if(self.protocol==1):
- try:
- self.ID = int(data[3:11].decode("utf-8"))
- self.key = int(data[11:19].decode("utf-8"))
- trg_ID = int(data[19:27].decode("utf-8"))
- except:
- self.error = 3
- return(0)
- msg = data[27:-3]
- return(self.process_message(trg_ID,msg))
- else:
- self.error = 4 #protocol mismatch
- return(0)
- try:
- cl_data = data.decode("utf-8")
- except:
- self.error = 1
- return(0)
- if(cl_data[-3:]!="FIN"):
- self.error = 3
- return(0)
- mtype = cl_data[:3]
- if(mtype=="LOG"):
- if(self.protocol==1):
- try:
- llen = int(cl_data[3:7])
- plen = int(cl_data[7:11])
- except:
- self.error = 3
- return(0)
- self.login = cl_data[11:11+llen]
- self.password = cl_data[11+llen:11+llen+plen]
- result = self.database.login(self.login,self.password)
- if(result[0]==0):
- self.key = result[1]
- self.ID = self.database.get_ID_by_key(self.key)
- if(self.ID<0):
- self.error = 7 #internal error???? must not happen
- return(0)
- else:
- msg = "OK"+add_nulls(8,str(self.key))+add_nulls(8,str(self.ID))
- self.send_msg(msg)
- return(-1)
- else:
- self.error = 8 #wrong password for existing login
- return(0)
- else:
- self.error = 4
- return(0)
- if(mtype=="UPD"):
- if(self.protocol==1):
- try:
- self.key = int(cl_data[3:11])
- except:
- self.error = 5
- return(0)
- self.ID = self.database.get_ID_by_key(self.key)
- if(self.ID>0):
- msgdata = self.database.get_messages(self.ID)
- if(msgdata==0):
- self.error = 10
- return(0)
- else:
- msgdata = msgdata
- msg = "OK"+add_nulls(16,str(len(msgdata)))
- self.database.update_user_online(self.ID)
- self.send_msg(msg)
- self.send_msg(msgdata)
- return(-1)
- else:
- self.error = 5
- return(0)
- else:
- self.error = 4
- return(0)
- if(mtype=="WOL"):
- if(self.protocol==1):
- onlines = self.database.get_users_online()
- if(onlines==[]):
- self.error = 11
- return(0)
- outmsg = ""
- for oid in onlines:
- outmsg+=add_nulls(8,str(oid))
- outmsg = outmsg.encode("utf-8")
- lenmsg = len(outmsg)
- msg = "OK"+add_nulls(16,str(lenmsg))
- self.send_msg(msg)
- self.send_msg(outmsg)
- return(-1)
- else:
- self.error = 4
- return(0)
- def write_log(self,errtext):
- if(serv_settings.LOGGING==1 and self.error!=10 and self.error!=11):
- self.log.add_error(self.addr[0],errtext)
- outstr="Error ID: "+str(self.error)+" "
- outstr+="Error text: "+errtext+"\n"
- print(outstr)
- def count_traffic(self,num,traffic_type):
- if(serv_settings.LOGGING==1):
- self.log.add_traffic(self.addr[0],traffic_type,num)
- def work_with_client(self,conn,addr):
- self.log = logging_db()
- self.database = dbwork()
- self.conn = conn
- self.addr = addr
- self.ID = ""
- self.key = ""
- self.login = ""
- self.password = ""
- self.protocol = 0
- self.error = 0 #zero is for unknown error
- try:
- data = self.conn.recv(11)
- except:
- print(1)
- to_recieve = self.read_ask_msg(data)
- if(to_recieve==0):
- bmsg = "BA"+add_nulls(4,str(self.error))
- self.send_close(bmsg.encode("utf-8"))
- self.write_log("initiation bad from: "+str(self.addr))
- return
- elif(to_recieve==-1):
- self.conn.close()
- return
- else:
- self.send_msg("OK0000".encode("utf-8"))
- data = conn.recv(to_recieve)
- to_recieve = self.read_msg(data,to_recieve)
- if(to_recieve==0):
- bmsg = "BA"+add_nulls(16,str(self.error))
- self.send_close(bmsg.encode("utf-8"))
- self.write_log("shit with message from: "+str(self.addr))
- else:
- self.conn.close()
- #KEEP IN MIND THAT MULTIPROCESS DOES NOT WORK IN IDLE, START THE SERVER
- #USING A DOUBLECLICK ON PY FILE
- def start_process(conne,addre):
- job = client_job()
- job.work_with_client(conne,addre)
- if(__name__=="__main__"):
- sock = socket.socket()
- sock.bind((serv_settings.IP_ADDRESS, serv_settings.PORT))
- sock.listen(serv_settings.MAX_CLIENTS)
- while True:
- conn, addr = sock.accept()
- answ = Process(target=start_process,args=(conn,addr))
- answ.start()
- answ.join()
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement