5
\$\begingroup\$

I'm looking for a code review and code improvement for my own small server. The server accepts the requests: User Join,User Leave,User Text Notify Group Join, Group Leave, Group Notify Request Time. The syntax for User Join/Left Group Join/Left: **

DSLP-3.0
User Join
NameOfUser
DSLP-Body

** The syntax for Group Notify: **

DSLP-3.0
Group Notify
NameOfGroup
1(<--number of lines you want to send)
DSLP-Body
LineYouWantSend

** The syntax for User Text Notify: **

DSLP-3.0
User Text Notify
User1
User2
1(<---number of lines you want to send)
DSLP-Body
LineYouWantSend

**

The syntax for Request Time:

DSLP-3.0
Request Time
DSLP-Body

This is the code:

import socket
from socket import *
from threading import Thread
from datetime import datetime





host="localhost"
port=44444
s = socket(AF_INET, SOCK_STREAM)
SOCK_STREAM
s.bind((host, port))
s.listen(5)

trash=[]
user=["foobar"]
group=["foobar"]
def clientHandler():
    platz=""
    conn, addr = s.accept()
    print ("Connected with", addr)
    while True:
        data = conn.recv(4096)

        #error
        if repr(data)!="b'dslp-3.0'":
            print(error_firstline())
        else:
            while True:

                data = conn.recv(4096)
                platz+=repr(data)
                platz+="\r\n"
                trash.append(platz)

                if len(trash)==2 and platz.count("\r\n")==2:
                    if "b'dslp-3.0'" in platz:
                        continue
                    else:
                        print(error_search_2nd_line(platz))

                if len(trash)>4 and "b'dslp-3.0'" in platz:
                    pp=platz.rsplit("b'dslp-3.0'\r\n")
                    trash.clear()
                    print(error_search_2nd_line(pp[1]))

                if len(trash)>6:
                    trash.clear()


                if "request time" in platz:
                    if "dslp-body" in platz:
                        platz=check_dslp(platz)
                        print(response_time())
                        platz=""
                    if len(platz)>31:
                        print(error_forthline())

                if "group join" in platz:

                    if "dslp-body" in platz:
                        platz=check_dslp(platz)
                        so=platz.split(("b'group join'"))
                        soo=so[1].split(("\r\nb'dslp-body'\r\n"))
                        sooo=soo[0].split(("\r\nb'"))
                        zahl=len(platz)-len(sooo[1])

                        if zahl>33:
                            print(error_forthline())
                            platz=""
                        else:
                            print(group_join(platz))
                            platz=""


                if "group leave" in platz:

                    if "dslp-body" in platz:
                        platz=check_dslp(platz)
                        so=platz.split(("b'group leave'"))
                        soo=so[1].split(("\r\nb'dslp-body'\r\n"))
                        sooo=soo[0].split(("\r\nb'"))
                        zahl=len(platz)-len(sooo[1])

                        if zahl>34:
                            print(error_forthline())
                            platz=""
                        else:
                            print(group_leave(platz))
                            platz=""

                if "user join" in platz:
                    if len(trash)>4:
                        trash.clear()
                    if "dslp-body" in platz:
                        platz=check_dslp(platz)
                        so=platz.split(("b'user join'"))
                        soo=so[1].split(("\r\nb'dslp-body'\r\n"))
                        sooo=soo[0].split(("\r\nb'"))
                        zahl=len(platz)-len(sooo[1])

                        if zahl>32:
                            print(error_forthline())
                            platz=""
                        else:
                            print(user_join(platz))
                            platz=""

                if "user leave" in platz:
                    if "dslp-body" in platz:
                        platz=check_dslp(platz)
                        so=platz.split(("b'user leave'"))
                        soo=so[1].split(("\r\nb'dslp-body'\r\n"))
                        sooo=soo[0].split(("\r\nb'"))
                        zahl=len(platz)-len(sooo[1])
                        if zahl>33:
                            print(error_forthline())
                            platz=""
                        else:
                            print(user_leave(platz))
                            platz=""

                if "group notify" in platz:
                    platz=check_dslp(platz)
                    for i in range(5):
                        if str(i) in platz:

                            if i==1:
                                if platz.count("\r\n")==5:

                                    print(group_notify(platz))
                                    platz=""
                            if i==2:
                                if platz.count("\r\n")==6:
                                    print(group_notify(platz))
                                    platz=""
                            if i==3:
                                if platz.count("\r\n")==7:
                                    print(group_notify(platz))
                                    platz=""
                            if i==4:
                                if platz.count("\r\n")==8:
                                    print(group_notify(platz))
                                    platz=""
                            if i==5:
                                if platz.count("\r\n")==9:
                                    print(group_notify(platz))
                                    platz=""

                if "user text notify" in platz:
                    platz=check_dslp(platz)
                    for i in range(5):
                        if str(i) in platz:

                            if i==1:
                                if platz.count("\r\n")==6:
                                    print(user_notify(platz))
                                    platz=""
                            if i==2:
                                if platz.count("\r\n")==7:
                                    print(user_notify(platz))
                                    platz=""
                            if i==3:
                                if platz.count("\r\n")==8:
                                    print(user_notify(platz))
                                    platz=""
                            if i==4:
                                if platz.count("\r\n")==9:
                                    print(user_notify(platz))
                                    platz=""
                            if i==5:
                                if platz.count("\r\n")==10:
                                    print(user_notify(platz))
                                    platz=""

                if "user list" in platz:
                    if "dslp-body" in platz:
                        print(user_list())
                        platz=""
                if "group list" in platz:
                    if "dslp-body" in platz:
                        print(group_list())
                        platz=""








for i in range(5):
    Thread(target=clientHandler).start()

s.close()

def error_search_2nd_line(platzhalter):

    bb=platzhalter.rsplit("b'")
    b=bb[1].rsplit("'\r\n")
    platzhalter=b[0]
    print (platzhalter)
    liste=["group join", "group leave", "user join", "user leave", "group notify", "user text notify","user list","group list"]
    bedingung=""
    for x in range(len(liste)):
        bedingung+=liste[x]
        if x+1==len(liste):
            if platzhalter not in bedingung:
                trash.clear()
                print(error_secondline())
            else:
                trash.clear()



def error_firstline():
    print("dslp-3.0\r\nerror\r\n1\r\ndslp-body\r\nReceived unexpected text as first line.\r\nConnection closed by foreign host.")

def error_secondline():
    print("error")
    print("1")
    print("dslp-body")
    print("Received unexpected message type in second line.")
    print("Connection closed by foreign host.")

def error_forthline():
    print("dslp-3.0")
    print("error")
    print("1")
    print("dslp-body")
    print("Unexpected state while analyzing line 4.")
    print("Connection closed by foreign host.")

def group_error():
    print("Group is unknown.")

def user_error():
    print("Source user is unknown.")

def check_dslp(platz):
    if "b'dslp-3.0'\r\n" in platz:
        pp=platz.rsplit("b'dslp-3.0'\r\n")
        platz=pp[1]
        return platz
    else:
        return platz





def group_join(platzhalter):
    print("dslp-3.0")
    print("group join ack")
    y=platzhalter.split("b'group join'\r\nb'")
    y=y[1].split("'")
    group.append(y[0])
    print(y[0])
    print("dslp-body")


def group_notify(platzhalter):
    if len(group)==1:
        print(group_error())
    for x in group:
        if x in platzhalter:
            pp=platzhalter.rsplit("dslp-body'\r\nb'")
            ppp=pp[1].rsplit("'\r\n")
            for i in ppp:
                print (i)
            break
        if x=="foobar":
            continue
        elif x not in platzhalter:
            print(group_error())




def group_leave(platzhalter):
    y=platzhalter.split("b'group leave'\r\nb'")
    y=y[1].split("'")
    for x in group:
        if y[0] in group:
            print("dslp-3.0")
            print("group leave ack")
            print(y[0])
            print("dslp-body")
            group.remove(y[0])
            break
        else:
            print(group_error())

def group_list():
    print("Groups: ")
    for i in group:
        print(i)

def user_join(platzhalter):
    if "b'dslp-3.0'\r\n" in platzhalter:
        z=platzhalter.split("b'dslp-3.0'\r\n")
        y=z[1]
        y=platzhalter.split("b'user join'\r\nb'")
        y=y[1].split("\r\nb'dslp-body'\r\n")
        y=y[0].split("'")
        user.append(y[0])
        print("dslp-3.0")
        print("user join ack")
        print(y[0])
        print("dslp-body")
    else:
        y=platzhalter.split("b'user join'\r\nb'")
        y=y[1].split("\r\nb'dslp-body'\r\n")
        y=y[0].split("'")
        user.append(y[0])
        print("dslp-3.0")
        print("user join ack")
        print(y[0])
        print("dslp-body")

def user_notify(platzhalter):
    if len(user)==1:
        print(user_error())
    for x in user:
        if x in platzhalter:
            pp=platzhalter.rsplit("dslp-body'\r\nb'")
            ppp=pp[1].rsplit("'\r\n")
            for i in ppp:
                print(i)
            break

        if x not in platzhalter:
            print(user_error())


def user_leave(platzhalter):
    y=platzhalter.split("b'user leave'\r\nb'")
    y=y[1].split("\r\nb'dslp-body'\r\n")
    y=y[0].split("'")
    user.remove(y[0])
    print("dslp-3.0")
    print("user leave ack")
    print(y[0])
    print("dslp-body")

def user_list():
    print("Users are: ")
    for i in user:
        print(i)
\$\endgroup\$
0

1 Answer 1

3
\$\begingroup\$

Packet fragmentation

    data = conn.recv(4096)

    #error
    if repr(data)!="b'dslp-3.0'":

To quote the documentation for recv,

The maximum amount of data to be received at once is specified by bufsize.

Emphasis mine. This is a common pitfall that beginners encounter when attempting low-level socket programming. The socket library gives you no guarantee that you will actually get 4096 bytes, or even a complete message. You need to iterate until you think you have enough bytes or a valid message, however you define that.

Put another way, it would be trivially easy to write a client that sends fragmented data to your server that should be valid but will in fact be erroneously rejected.

Though I haven't tried it, socketserver seems like its rfile should be able to abstract this away for you since it handles buffering. In other words, you don't need to worry about packets or buffer sizes; you can ask for rfile.readline(), which is what you actually want given your protocol.

If you do not want the abstraction of socketserver, you can also use makefile - which is called by socketserver anyway.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.