Advertisement
Guest User

serv

a guest
Nov 21st, 2017
84
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 17.26 KB | None | 0 0
  1. from multiprocessing import Process
  2. import socket,time,sqlite3,time,os,random
  3. try:
  4.     import serv_settings
  5. except:
  6.     f = open("serv_settings.py","w")
  7.     t = '''
  8. IP_ADDRESS = ""
  9.  
  10. PORT = 9090
  11.  
  12. KEY_DECAY_TIME = 3600
  13.  
  14. ONLINE_CONFIRM_TIME = 600
  15.  
  16. LOGGING = 1
  17.  
  18. LOGFOLDER = "logs"
  19.  
  20. MAX_CLIENTS = 100
  21.        '''
  22.     f.write(t)
  23.     f.close()
  24.     import serv_settings
  25.  
  26.  
  27.  
  28. def error_p(errmsg):
  29.     print("Error: "+errmsg)
  30.  
  31. def logmsg(logmsg):
  32.     a = time.strftime("%H-%M %d %h %Y")
  33.     print(a+": "+logmsg)
  34.  
  35. def add_nulls(dlen,data):
  36.     to_ret = data
  37.     if(len(data)<dlen):
  38.         dif = dlen-len(data)
  39.         to_ret = "0"*dif+to_ret
  40.     return to_ret
  41.  
  42. class logging_db:
  43.     def __init__(self):
  44.         cur,connection = self.connect_to_db()
  45.         cur.execute('''
  46.            CREATE TABLE IF NOT EXISTS errlogs(
  47.                ADDR TEXT,
  48.                DATE TEXT,
  49.                ERROR TEXT)
  50.            ''')
  51.         cur.execute('''
  52.            CREATE TABLE IF NOT EXISTS traffics(
  53.                ADDR TEXT,
  54.                TYPE TEXT,
  55.                AMOUNT INTEGER)
  56.            ''')#amount in bytes
  57.         connection.commit()
  58.         connection.close()
  59.         #todo
  60.         #make traffic counting
  61.         #make error logging here
  62.         #traffic counted by dates and users
  63.         #tables must be wiped sometimes))))00000
  64.  
  65.     def add_traffic(self,addr,ttype,amount):
  66.         cur,connection = self.connect_to_db()
  67.         cur.execute("SELECT AMOUNT FROM traffics WHERE ADDR = ? AND TYPE = ?",(addr,ttype))
  68.         d = cur.fetchone()
  69.         if(d!=None):
  70.             num = d[0]
  71.             num+=amount
  72.             cur.execute("UPDATE traffics SET AMOUNT = ? WHERE ADDR = ? AND TYPE = ?",(num,addr,ttype))
  73.         else:
  74.             cur.execute("INSERT INTO traffics VALUES (?,?,?)",(addr,ttype,amount))
  75.         connection.commit()
  76.         connection.close()
  77.  
  78.     def add_error(self,addr,error):
  79.         date = time.time()
  80.         cur,connection = self.connect_to_db()
  81.         cur.execute("INSERT INTO errlogs VALUES (?,?,?)",(addr,str(date),error))
  82.         connection.commit()
  83.         connection.close()
  84.    
  85.     def connect_to_db(self):
  86.         try:
  87.             connection = sqlite3.connect(serv_settings.LOGFOLDER+"/"+"log.db")
  88.         except:
  89.             os.mkdir(serv_settings.LOGFOLDER)
  90.             connection = sqlite3.connect(serv_settings.LOGFOLDER+"/"+"log.db")
  91.         cur = connection.cursor()
  92.         return(cur,connection)
  93.    
  94.        
  95.    
  96.  
  97. class dbwork:
  98.     #1)login,password,id - logindata
  99.     #2)id,key,time_to_change_key - keys
  100.     #3)id,time_to_offline - onlines
  101.     #4)id,unread_messages - messages
  102.     def __init__(self):
  103.         cur,connection = self.connect_to_db()
  104.         #creating tables
  105.         cur.execute('''
  106.            CREATE TABLE IF NOT EXISTS logindata(
  107.                ID INTEGER PRIMARY KEY,
  108.                LOGIN TEXT,
  109.                PASSWORD TEXT)
  110.            ''')
  111.         cur.execute('''
  112.            CREATE TABLE IF NOT EXISTS keys(
  113.                ID INTEGER,
  114.                KEY INTEGER,
  115.                DTIME INTEGER)
  116.            ''')
  117.         cur.execute('''
  118.            CREATE TABLE IF NOT EXISTS onlines(
  119.                ID INTEGER PRIMARY KEY,
  120.                OTIME INTEGER)
  121.            ''')
  122.         cur.execute('''
  123.            CREATE TABLE IF NOT EXISTS messages(
  124.                ID INTEGER,
  125.                MESSAGE BLOB)
  126.            ''')#ID of the user to recive message
  127.         connection.commit()
  128.         connection.close()
  129.  
  130.     def connect_to_db(self):
  131.         connection = sqlite3.connect("chatdb.db")
  132.         cur = connection.cursor()
  133.         return(cur,connection)
  134.  
  135.     def generate_key(self,ID): #generates a new key for given ID
  136.         random.seed()
  137.         cur,connection = self.connect_to_db()
  138.         key = random.randint(10000000,99999999)
  139.         ok = 0
  140.         while(ok==0): #generating a unique key for messaging
  141.             cur.execute("SELECT * FROM keys WHERE KEY = ?",(key,))
  142.             if(cur.fetchone()==None):
  143.                 ok = 1
  144.                 break
  145.             else:
  146.                 key = random.randint(10000000,99999999)
  147.         cur.execute("SELECT * FROM keys WHERE ID = ?",(ID,)) #checking if the
  148.         dtime = time.time()+serv_settings.KEY_DECAY_TIME                   #ID in table
  149.         if(cur.fetchone()==None):
  150.             cur.execute("INSERT INTO keys VALUES (?,?,?)",(ID,key,dtime))
  151.         else:
  152.             cur.execute("UPDATE keys SET KEY = ?, DTIME = ? WHERE ID = ?",(key,dtime,ID))
  153.         connection.commit()
  154.         connection.close()
  155.         return(key)
  156.  
  157.     def get_messages(self,ID):
  158.         cur,connection = self.connect_to_db()
  159.         cur.execute("SELECT MESSAGE FROM messages WHERE ID = ?",(ID,))
  160.         msgs = cur.fetchall()
  161.         msgdata = b""
  162.         if(msgs==[]):
  163.             connection.close()
  164.             return(0)
  165.         else:
  166.             for msg in msgs:
  167.                 message = msg[0]
  168.                 msgdata+=message
  169.             cur.execute("DELETE FROM messages WHERE ID = ?",(ID,))
  170.             connection.commit()
  171.             connection.close()
  172.             return(msgdata)
  173.  
  174.     def get_ID_by_login(self,login):
  175.         cur,connection = self.connect_to_db()
  176.         cur.execute("SELECT ID FROM logindata WHERE LOGIN = ?",(login,))
  177.         ID = cur.fetchone()[0]
  178.         connection.close()
  179.         return(ID)
  180.    
  181.     def get_key(self,ID): #returns a key for given ID
  182.         cur,connection = self.connect_to_db()
  183.         cur.execute("SELECT KEY FROM keys WHERE ID = ?",(ID,))
  184.         key = cur.fetchone()
  185.         if(key!=None):
  186.             key=key[0]
  187.         connection.close()
  188.         return(key)
  189.  
  190.     def get_key_dtime(self,ID):
  191.         cur,connection = self.connect_to_db()
  192.         cur.execute("SELECT DTIME FROM keys WHERE ID = ?",(ID,))
  193.         dtime = cur.fetchone()
  194.         if(dtime!=None):
  195.             dtime=dtime[0]
  196.         connection.close()
  197.         return(dtime)
  198.    
  199.     def get_ID_by_key(self,key):
  200.         cur,connection = self.connect_to_db()
  201.         cur.execute("SELECT ID, DTIME FROM keys WHERE key = ?",(key,))
  202.         uid = cur.fetchone()
  203.         connection.close()
  204.         if(uid==None):
  205.             return(-1)#no such key
  206.         else:
  207.             dtime = uid[1]
  208.             uid = uid[0]
  209.             if(dtime<time.time()):
  210.                 return(-2)#timed out key
  211.             else:
  212.                 return(uid)
  213.        
  214.     def update_user_online(self,ID):
  215.         otime = time.time()+serv_settings.ONLINE_CONFIRM_TIME
  216.         cur,connection = self.connect_to_db()
  217.         cur.execute("REPLACE INTO onlines VALUES(?,?)",(ID,otime))
  218.         connection.commit()
  219.         connection.close()
  220.  
  221.     def get_users_online(self):
  222.         ctime = time.time()
  223.         cur,connection = self.connect_to_db()
  224.         cur.execute("SELECT ID FROM onlines WHERE OTIME > ?",(ctime,))
  225.         onlineIDs = cur.fetchall()
  226.         onlines = []
  227.         if(onlineIDs == []):
  228.             return([])
  229.         else:
  230.             for oid in onlineIDs:
  231.                 onlines.append(oid[0])
  232.             return(onlines)
  233.  
  234.     def add_message(self,ID,msg):
  235.         cur,connection = self.connect_to_db()
  236.         cur.execute("INSERT INTO messages VALUES(?,?)",(ID,msg))
  237.         connection.commit()
  238.         connection.close()
  239.    
  240.     def login(self,login,password):
  241.         cur,connection = self.connect_to_db()
  242.         cur.execute("SELECT * FROM logindata WHERE LOGIN = ?",(login,))
  243.         udata = cur.fetchone()
  244.         if(udata==None):
  245.             cur.execute("INSERT INTO logindata VALUES (NULL,?,?)",(login,password))
  246.             connection.commit()
  247.             connection.close()
  248.             ID = self.get_ID_by_login(login)
  249.             key = self.generate_key(ID)
  250.             self.update_user_online(ID)
  251.             return([0,key]) #OK - new registered
  252.         else:
  253.             if(udata[2]==password):
  254.                 connection.close()
  255.                 ID = self.get_ID_by_login(login)
  256.                 key = self.generate_key(ID)
  257.                 self.update_user_online(ID)
  258.                 return([0,key]) #OK - ok login&pwd
  259.             else:
  260.                 connection.close()
  261.                 return([1,0]) #login already exists(it means - password incorrect)
  262.  
  263.  
  264. class client_job:
  265.  
  266.     def send_close(self,data):
  267.         self.send_msg(data)
  268.         self.conn.close()
  269.     def send_msg(self,data):
  270.         count = 0
  271.         try:
  272.             try:
  273.                 self.conn.send(data.encode("utf-8"))
  274.                 count = len(data.encode("utf-8"))
  275.             except:
  276.                 self.conn.send(data)
  277.                 count = len(data)
  278.         except:
  279.             self.write_log("error sending to: "+str(self.addr))
  280.             return
  281.         self.count_traffic(count,"out")
  282.    
  283.     def answer_ask_chk(self):
  284.         self.ID = self.database.get_ID_by_key(self.key)
  285.         if(self.ID>0):
  286.             dtime = self.database.get_key_dtime(self.ID)
  287.             dtime-=time.time()
  288.             dtime = add_nulls(4,str(dtime))
  289.             self.database.update_user_online(self.ID)
  290.             self.send_msg("OK"+dtime)
  291.             return(-1)
  292.         else:
  293.             if(self.ID==-1):
  294.                 self.error = 5 #wrong key
  295.             else:
  296.                 self.error = 6 #key timed out
  297.             return(0)
  298.  
  299.     def read_ask_msg(self,data):
  300.         try:
  301.             ask_m = data.decode("utf-8")
  302.         except:
  303.             self.error = 1 #encoding failure
  304.             return(0)
  305.         if(len(ask_m)!=11):
  306.             self.error = 3 #message badly structured
  307.             return(0)
  308.         mtype = ask_m[:3]
  309.         if(mtype=="CHK"):
  310.             try:
  311.                 self.key = int(ask_m[3:])
  312.             except:
  313.                 self.error = 5
  314.                 return(0)
  315.             return self.answer_ask_chk()
  316.         if(mtype=="MES"):
  317.             try:
  318.                 self.protocol = int(ask_m[3:7])
  319.                 ret_bytes = int(ask_m[7:])
  320.             except:
  321.                 self.error = 1
  322.                 return(0)
  323.             return ret_bytes
  324.         else:
  325.             self.error = 2 #unknown initiation
  326.             return(0)
  327.  
  328.     def check_key_ID(self):
  329.         realID = self.database.get_ID_by_key(self.key)
  330.         if(realID==self.ID):
  331.             return(1)
  332.         else:
  333.             if(realID==-1):
  334.                 self.error = 5
  335.                 return(0)
  336.             else:
  337.                 self.error = 6
  338.                 return(0)
  339.            
  340.    
  341.     def process_message(self,trg_ID,message):
  342.         if(self.check_key_ID()==1):
  343.             if(self.database.get_key(trg_ID)==None):
  344.                 self.error = 9
  345.                 return(0)
  346.             else:
  347.                 msglen = str(add_nulls(4,str(len(message)))).encode("utf-8")
  348.                 sender = str(add_nulls(8,str(self.ID))).encode("utf-8")
  349.                 dbmsg = sender+msglen+message #add a sender's ID and msglen
  350.                 self.database.add_message(trg_ID,dbmsg)
  351.                 self.database.update_user_online(self.ID)
  352.                 msg = "OK"+add_nulls(16,"")
  353.                 self.send_msg(msg)
  354.                 return(-1)
  355.         else:
  356.             self.error = 5
  357.             return(0)
  358.    
  359.     def read_msg(self,data,len_m):
  360.         if(len(data)!=len_m):
  361.             self.error = 3
  362.             return(0)
  363.         try:
  364.             mtype = data[:3].decode("utf-8")
  365.         except:
  366.             self.error = 1
  367.             return(0)
  368.         if(data[-3:].decode("utf-8")!="FIN"):
  369.             self.error = 3
  370.             return(0)
  371.         if(mtype=="MSG"):#messages can be not a unicode str
  372.             if(self.protocol==1):
  373.                 try:
  374.                     self.ID = int(data[3:11].decode("utf-8"))
  375.                     self.key = int(data[11:19].decode("utf-8"))
  376.                     trg_ID = int(data[19:27].decode("utf-8"))
  377.                 except:
  378.                     self.error = 3
  379.                     return(0)
  380.                 msg = data[27:-3]
  381.                 return(self.process_message(trg_ID,msg))
  382.             else:
  383.                 self.error = 4 #protocol mismatch
  384.                 return(0)
  385.         try:
  386.             cl_data = data.decode("utf-8")
  387.         except:
  388.             self.error = 1
  389.             return(0)
  390.         if(cl_data[-3:]!="FIN"):
  391.             self.error = 3
  392.             return(0)
  393.         mtype = cl_data[:3]
  394.         if(mtype=="LOG"):
  395.             if(self.protocol==1):
  396.                 try:
  397.                     llen = int(cl_data[3:7])
  398.                     plen = int(cl_data[7:11])
  399.                 except:
  400.                     self.error = 3
  401.                     return(0)
  402.                 self.login = cl_data[11:11+llen]
  403.                 self.password = cl_data[11+llen:11+llen+plen]
  404.                 result = self.database.login(self.login,self.password)
  405.                 if(result[0]==0):
  406.                     self.key = result[1]
  407.                     self.ID = self.database.get_ID_by_key(self.key)
  408.                     if(self.ID<0):
  409.                         self.error = 7 #internal error???? must not happen
  410.                         return(0)
  411.                     else:
  412.                         msg = "OK"+add_nulls(8,str(self.key))+add_nulls(8,str(self.ID))
  413.                         self.send_msg(msg)
  414.                         return(-1)
  415.                 else:
  416.                     self.error = 8 #wrong password for existing login
  417.                     return(0)
  418.             else:
  419.                 self.error = 4
  420.                 return(0)
  421.         if(mtype=="UPD"):
  422.             if(self.protocol==1):
  423.                 try:
  424.                     self.key = int(cl_data[3:11])
  425.                 except:
  426.                     self.error = 5
  427.                     return(0)
  428.                 self.ID = self.database.get_ID_by_key(self.key)
  429.                 if(self.ID>0):
  430.                     msgdata = self.database.get_messages(self.ID)
  431.                     if(msgdata==0):
  432.                         self.error = 10
  433.                         return(0)
  434.                     else:
  435.                         msgdata = msgdata
  436.                         msg = "OK"+add_nulls(16,str(len(msgdata)))
  437.                         self.database.update_user_online(self.ID)
  438.                         self.send_msg(msg)
  439.                         self.send_msg(msgdata)
  440.                         return(-1)
  441.                 else:
  442.                     self.error = 5
  443.                     return(0)
  444.             else:
  445.                 self.error = 4
  446.                 return(0)
  447.         if(mtype=="WOL"):
  448.             if(self.protocol==1):
  449.                 onlines = self.database.get_users_online()
  450.                 if(onlines==[]):
  451.                     self.error = 11
  452.                     return(0)
  453.                 outmsg = ""
  454.                 for oid in onlines:
  455.                     outmsg+=add_nulls(8,str(oid))
  456.                 outmsg = outmsg.encode("utf-8")
  457.                 lenmsg = len(outmsg)
  458.                 msg = "OK"+add_nulls(16,str(lenmsg))
  459.                 self.send_msg(msg)
  460.                 self.send_msg(outmsg)
  461.                 return(-1)
  462.             else:
  463.                 self.error = 4
  464.                 return(0)
  465.  
  466.     def write_log(self,errtext):
  467.         if(serv_settings.LOGGING==1 and self.error!=10 and self.error!=11):
  468.             self.log.add_error(self.addr[0],errtext)
  469.             outstr="Error ID: "+str(self.error)+" "
  470.             outstr+="Error text: "+errtext+"\n"
  471.             print(outstr)
  472.  
  473.     def count_traffic(self,num,traffic_type):
  474.         if(serv_settings.LOGGING==1):
  475.             self.log.add_traffic(self.addr[0],traffic_type,num)
  476.            
  477.    
  478.     def work_with_client(self,conn,addr):
  479.         self.log = logging_db()
  480.         self.database = dbwork()
  481.         self.conn = conn
  482.         self.addr = addr
  483.         self.ID = ""
  484.         self.key = ""
  485.         self.login = ""
  486.         self.password = ""
  487.         self.protocol = 0
  488.         self.error = 0 #zero is for unknown error
  489.         try:
  490.             data = self.conn.recv(11)
  491.         except:
  492.             print(1)
  493.         to_recieve = self.read_ask_msg(data)
  494.         if(to_recieve==0):
  495.             bmsg = "BA"+add_nulls(4,str(self.error))
  496.             self.send_close(bmsg.encode("utf-8"))
  497.             self.write_log("initiation bad from: "+str(self.addr))
  498.             return
  499.         elif(to_recieve==-1):
  500.             self.conn.close()
  501.             return
  502.         else:
  503.             self.send_msg("OK0000".encode("utf-8"))
  504.             data = conn.recv(to_recieve)
  505.             to_recieve = self.read_msg(data,to_recieve)
  506.             if(to_recieve==0):
  507.                 bmsg = "BA"+add_nulls(16,str(self.error))
  508.                 self.send_close(bmsg.encode("utf-8"))
  509.                 self.write_log("shit with message from: "+str(self.addr))
  510.             else:
  511.                 self.conn.close()
  512.  
  513. #KEEP IN MIND THAT MULTIPROCESS DOES NOT WORK IN IDLE, START THE SERVER
  514. #USING A DOUBLECLICK ON PY FILE
  515.  
  516. def start_process(conne,addre):
  517.     job = client_job()
  518.     job.work_with_client(conne,addre)
  519.  
  520. if(__name__=="__main__"):
  521.     sock = socket.socket()
  522.     sock.bind((serv_settings.IP_ADDRESS, serv_settings.PORT))
  523.     sock.listen(serv_settings.MAX_CLIENTS)
  524.     while True:
  525.         conn, addr = sock.accept()
  526.         answ = Process(target=start_process,args=(conn,addr))
  527.         answ.start()
  528.         answ.join()
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement