Пример #1
0
    def establish_connection(
            self, ip,
            port):  # attempting to establish connection with other client
        try:
            self.cnct = Client_Connection(
                self.user, self.priv_key,
                self.pub_key)  # creating connection object
            self.cnct.connect(ip,
                              port)  # attempting connection with ip and port

            self.connected = True  # knowing connection is established

            # confirming connection in textbox
            Client.update_text_other(
                self,
                "Connection established with {} on port {}\n".format(ip, port))

            self.menubar.entryconfig(1,
                                     state="disabled")  # make connect unviable
            self.menubar.entryconfig(
                2, state="normal"
            )  # make disconnect viable if connection established
            self.menubar.entryconfig(3,
                                     state="disabled")  # make options unviable

            self.enter_field.configure(state='normal')  # make entry box usable

        except socket_error as e:  # if connection fails
            print("Connection failed.")
            print(e)
Пример #2
0
    def establish_connection(
            self, ip,
            port):  # attempting to establish connection with other client
        # validating connection inputs
        if int(port) < 1024:
            Client.update_message_other(self, "Cannot use port below 1024")
        elif not '.' in ip:
            Client.update_message_other(self, "Invalid IP given")

        else:
            try:  # attempt the connection
                self.cnct = Client_Connection(
                    self.user, self.priv_key,
                    self.pub_key)  # creating connection object
                self.cnct.connect(
                    ip, port)  # attempting connection with ip and port
            except socket_error as e:  # if connection fails
                print("Connection failed.")
                print(e)
                Client.update_message_other(
                    self,
                    "Connection failed.")  # telling user connection failed
            else:  # updating program after successful connection
                self.connected = True  # knowing connection is established

                # confirming connection in textbox
                Client.update_message_other(
                    self, "Connection established with {} on port {}\n".format(
                        ip, port))

                self.menubar.entryconfig(
                    1, state="disabled")  # make connect unviable
                self.menubar.entryconfig(
                    2, state="normal"
                )  # make disconnect viable if connection established
                self.menubar.entryconfig(
                    3, state="disabled")  # make options unviable

                self.enter_field.configure(
                    state='normal')  # make entry box usable
Пример #3
0
class Client(tk.Frame):
    def __init__(self, parent, width=400, height=500):  # init app
        # creating parent
        tk.Frame.__init__(self, parent)
        self.parent = parent
        parent.title("Client-side")

        Client.get_config(self)

        self.connected = False  # connection identifier

        self.w = width
        self.h = height

        Client.toplevel_menu(self)  # creating chat window

        Client.bind_events(self)  # event binding, such as <enter_pressed>

        update_incoming_msg_thread = Thread(
            target=Client.handle_incoming_msg, args=(
                self, )).start()  # thread to handle received message updating

    def bind_events(self):
        self.enter_field.bind('<Return>',
                              lambda event, a=self: Client.enter_pressed(a))

    def combine_funcs(*funcs):  # function for combining functions
        def combined_func(*args, **kwargs):
            for f in funcs:
                f(*args, **kwargs)

        return combined_func

    def toplevel_menu(self):  # creation of the main window and its widgets
        self.parent.resizable(False, False)  # stop the window being resized

        self.menubar = tk.Menu(self.parent)  # create menubar object

        # adding menubar options "Connect", "Disconnect, "Options", and "Quit"
        self.menubar.add_command(
            label="Connect", command=lambda: Client.connection_window(self))
        self.menubar.add_command(label="Disconnect",
                                 command=lambda: Client.break_connection(self))
        self.menubar.add_command(label="Options",
                                 command=lambda: Client.options(self))
        self.menubar.add_command(label="Quit",
                                 command=Client.combine_funcs(
                                     self.parent.destroy, Client.quit_prog))

        # default disconnect bar as disabled
        self.menubar.entryconfig(2, state="disabled")

        # main chat window that can't be edited
        self.messages = tk.Text(self.parent)
        self.messages.config(state='disabled')
        self.messages.grid(row=0, column=0)

        # actual scrollbar
        scrollbar = tk.Scrollbar(self.parent, command=self.messages.yview)
        scrollbar.grid(row=0, column=2, sticky="nsew", padx=2, pady=2)
        self.messages['yscrollcommand'] = scrollbar.set
        """
        #stupid joke scroll window and scrollbar
        scrollW = tk.Toplevel(self.parent)
        scrollW.protocol('WM_DELETE_WINDOW', False)
        scrollb = tk.Scrollbar(scrollW, command=self.messages.yview)
        scrollb.grid(sticky="nsew", padx=2, pady=2)
        self.messages['yscrollcommand'] = scrollb.set
        """

        # user input field for chat window
        self.input_user = tk.StringVar()  # make variable for text entry box
        self.enter_field = tk.Entry(self.parent, text=self.input_user)
        self.enter_field.grid(row=20, column=0,
                              sticky='W,E,S,N')  # create entry field
        #self.enter_field.configure(state='readonly') # start the entry box as disabled until connection

        self.parent.config(menu=self.menubar)  # place menubar on window

    def enter_pressed(self):  # called if enter is pressed
        input_get = self.enter_field.get()  # getting input from enter box
        self.input_user.set('')  # make entry text box blank

        # checking if the box contained text, and then acting on that
        if len(input_get) > 0:
            Client.update_text(self, self.user,
                               input_get)  # adding the text to the chat window
            if self.connected:
                self.cnct.send_message(
                    input_get)  # sending the message to the other client

    def update_text(self, name, text):  # updating chat window
        self.messages.config(state='normal')  # make text box configurable

        self.messages.insert('end', '{}: {}\n'.format(name,
                                                      text))  # insert message

        self.messages.see(tk.END)  # put message box at the end

        self.messages.config(state='disabled')  # make text box unconfigurable

    def update_text_other(self, text):
        self.messages.config(state='normal')  # make text box configurable

        self.messages.insert('end', "\n{}\n".format(text))  # insert message

        self.messages.see(tk.END)  # put message box at the end

        self.messages.config(state='disabled')  # make text box unconfigurable

    def handle_incoming_msg(
        self
    ):  # checking to update text inside gui as opposed to in connection class
        while True:
            try:
                if self.cnct:
                    if self.cnct.incoming_msg:
                        if self.cnct.incoming_msg != None:
                            Client.update_text(self, self.cnct.other_name,
                                               self.cnct.incoming_msg)
                            self.cnct.incoming_msg = None
            except AttributeError:
                continue

    def connection_window(self):  # window to connect to individual
        top = tk.Toplevel(self.parent)
        tk.Label(top, text="IP:").pack()  # place to enter IP address

        e = tk.Entry(top)  # entry box for IP
        e.pack(padx=5)

        tk.Label(top, text="Port:").pack()  # place to enter port

        e2 = tk.Entry(top)  # entry box for port
        e2.insert(0, 4030)  # defaulted at 4030 to make it easy
        e2.pack(padx=5)

        b = tk.Button(top,
                      text="Enter",
                      command=lambda: Client.combine_funcs(
                          Client.establish_connection(self, e.get(), e2.get()),
                          top.destroy()))
        b.pack(pady=5)  # create and pack confirmation button

    def establish_connection(
            self, ip,
            port):  # attempting to establish connection with other client
        try:
            self.cnct = Client_Connection(
                self.user, self.priv_key,
                self.pub_key)  # creating connection object
            self.cnct.connect(ip,
                              port)  # attempting connection with ip and port

            self.connected = True  # knowing connection is established

            # confirming connection in textbox
            Client.update_text_other(
                self,
                "Connection established with {} on port {}\n".format(ip, port))

            self.menubar.entryconfig(1,
                                     state="disabled")  # make connect unviable
            self.menubar.entryconfig(
                2, state="normal"
            )  # make disconnect viable if connection established
            self.menubar.entryconfig(3,
                                     state="disabled")  # make options unviable

            self.enter_field.configure(state='normal')  # make entry box usable

        except socket_error as e:  # if connection fails
            print("Connection failed.")
            print(e)

    def break_connection(self):  # function to break connection
        self.cnct.disconnect()  # call object's disconnect function

        self.connected = False  # show connection has been dropped

        self.menubar.entryconfig(1, state="normal")  # make connect unviable
        self.menubar.entryconfig(
            2, state="disabled"
        )  # make disconnect unviable if connection established
        self.menubar.entryconfig(3, state="normal")  # make options viable

        self.enter_field.configure(state='readonly')  # make entry box unusable
        #print("Passed")

    def get_config(
        self
    ):  # retrieving config from local files, creating one if it doesn't exist
        config = ConfigParser()
        if os.path.isfile('config.ini'):  # checking file exists
            config.read('config.ini')  # reading file

            # getting username, private key, and public key from config
            self.user = config['CONFIG']['user']
            self.priv_key = literal_eval(
                config['CONFIG']
                ['private_key'])  # getting private key as tuple
            self.pub_key = literal_eval(
                config['CONFIG']['public_key'])  # getting public key as tuple

        else:  # if no config file exists, create one
            self.priv_key, self.pub_key = gen_keys()  # generating keys
            config['CONFIG'] = {
                'user': '******',
                'private_key': str(self.priv_key),
                'public_key': str(self.pub_key)
            }

            self.user = "******"

            with open('config.ini', 'w') as configfile:  # writing to config
                config.write(configfile)
            configfile.close()

    def generate_new_keys(self):
        self.priv_key, self.pub_key = gen_keys()  # generating new keys
        Client.update_cfg(self)  # updating config to apply new keys

        Client.update_text_other(self, "Generated new keys")

    def update_cfg(self):  # updating the config after changes have been made
        config = ConfigParser()
        config.read('config.ini')

        config['CONFIG']['user'] = self.user  # username
        config['CONFIG']['private_key'] = str(self.priv_key)  # private key
        config['CONFIG']['public_key'] = str(self.pub_key)  # public key

        with open('config.ini', 'w') as configfile:  # writing to file
            config.write(configfile)
        configfile.close()

    def options(self):  # allow user to set options, such as name
        window = tk.Toplevel(self.parent)

        tk.Label(window, text="User").grid(row=0)

        e1 = tk.Entry(window)
        e1.grid(row=0, column=1)

        def get_entries(self, *args):  # get the entries the user has input
            ent1 = e1.get()

            if len(ent1) > 0:  # making sure something has been input
                self.user = ent1

            Client.update_cfg(self)

            e1.delete(0, 'end')  # deleting options window

            window.destroy()

        tk.Button(window,
                  text="Confirm",
                  command=lambda: get_entries(self, window, e1)).grid(
                      row=3, column=0)  # button to get username update

        tk.Button(window,
                  text="Generate New Keys",
                  command=lambda: Client.generate_new_keys(self)).grid(
                      row=4, column=0)  # button to generate new keys

    def quit_prog():  # QUITTING
        sys.exit(0)