'''
The header for each byte stream sent and received is of the following format:
XXXXXXXXXX YYYYY Z* A* BBBB C*
- X represents the 10 character id of the sender
- Y represents the 5 character key of the sender
- Z represents any number of characters representing the ip address of the sender
- A represents any number of characters representing the port number of the sender
- B represents the uppercase 4 character command
- C represents the any number of characters making up the message sent
MACHINE_ID-MACHINE_KEY-IP_ADDRESS-PORT_NUMBER-COMMAND-MESSAGE
'''
import sched, time
import socket
import threading
from tkinter import *
import tkinter.messagebox
import gui_header
import VotingContainer
import SQLVoterTable
import blockchain
import os
import queue
import pickle
# ----------------------------------------------------------------------------------------------------------------------#
#-------------------------------------------GUI Variables--------------------------------------------------------------#
ballot = gui_header.LoadCSV('Ballot.csv')
votes = []
WriteInEntries = []
limitations = []
all_frames = []
compiledBallot = []
frameCount = 1
block = VotingContainer.Vote
stationId = 1234 # Station ID
blockToAdd = None
ballotQueue = queue.Queue(maxsize=0)
#----------------------------------------------------------------------------------------------------------------------#
#----------------------------- These identifiers will be hard coded onto each machine ---------------------------------#
MACHINE_ID = "Machine002"
MACHINE_KEY = "23456"
LEADER = False
#MAX_NUMBER_OF PEERS = 10
HOST = "146.95.43.141"
SERVER_PORT = "999"
SERVER_MACHINE_ID = "Server0001"
SERVER_KEY = "10101"
IP_ADDRESS = "146.95.41.248"# socket.gethostbyname(socket.getfqdn())
PORT_NUMBER = "1000"
#-- This message header will be used to send every message for verification purposes --#
MESSAGE_HEADER = MACHINE_ID + "|" + MACHINE_KEY + "|" + IP_ADDRESS + "|" + PORT_NUMBER
#----------------------------------------------------------------------------------------------------------------------#
#------------------------------List of peer info and list of peer socket connections-----------------------------------#
peers = []
registered_peers = []
#---------------------------------------- Block Chain will replace this list ------------------------------------------#
block_chain = []
#----------------------------------------------------------------------------------------------------------------------#
#----------------------------------------- Lock to prevent race conditions --------------------------------------------#
lock = threading.Lock()
#----------------------------------------------------------------------------------------------------------------------#
#----------------------------------------------------------------------------------------------------------------------#
#----------------------------------------------------------------------------------------------------------------------#
#------------------------------------------ Class for holding client info ---------------------------------------------#
class Peer_Info:
#-- Constructor --#
def __init__(self, machineID, privateKey, ipAddress, portNumber):
self.machineID = machineID
self.privateKey = privateKey
self.ipAddress = ipAddress
self.portNumber = portNumber
def change_ip_address(self, ipAddress):
self.ipAddress = ipAddress
def change_port_number(self, portNumber):
self.portNumber = portNumber
#----------------------------------------------------------------------------------------------------------------------#
#----------------------------------------------------------------------------------------------------------------------#
#----------------------------------------------------------------------------------------------------------------------#
#----------------- This function creates a server socket, binds it and returns the object -----------------------------#
def makeserversocket(portNumber, backlog=5):
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
#-- allows us to reuse socket immediately after it is closed --#
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
#-- binds to whatever IP Address the peer is assigne --#
s.bind(("", int(portNumber)))
s.listen(backlog)
s.setblocking(0)
print("binding peer server socket to port " + PORT_NUMBER)
print("Listening for connections...")
return s
#----------------------------------------------------------------------------------------------------------------------#
# --------------------------------------------- Authentication Function -----------------------------------------------#
'''Function takes the machineID and key that have been extracted from the parse_incoming_message function, and checks
the list of peers to make sure the connecting peer is authorized to connect. If it is the function returns true, if not
returns false'''
#----------------------------------------------------------------------------------------------------------------------#
def verify_incoming_peer(connection, machineID, key, ip_address, port_number):
found_match = False
print("Machine login info is: " + machineID + " " + key + "" + ip_address + "" + port_number)
# -------------------------------------------------------------------------------------------------------------#
# -------------- Loop through list of clients and see if a match with login info is found -------------------#
for x in peers:
# -- Client's machine id and private key match so it is confirmed to connect --#
if (x.machineID == machineID) and (x.privateKey == key):
print("match found!")
# -- Client's IP address does not match so we update it in the Client list --#
if (x.ipAddress != ip_address):
x.change_ip_address(ip_address)
print("Updated IP Address: " + ip_address)
# -- Client's port number does not match so we update it in the Client list --#
if (x.portNumber != port_number):
x.change_port_number(port_number)
print("Updated Port Number: " + str(port_number))
# -- Match found so update variable --#
found_match = True
break
# ------------------------------------------------------------------------------------------------------------#
# ------------------------------------------- Peer failed to connect to ----------------------------------------#
if found_match is False:
print("Peer failed to provide a valid machine name and/or key.")
return False
# -----------------------------------------------------------------------------------------------------------------#
# -------------------------------------- Client successfully connected --------------------------------------------#
else:
already_exist = False
# -- Add socket to list of connections --#
for p in registered_peers:
if p.machineID == machineID:
p.ipAddress = ip_address
p.portNumber = port_number
already_exist = True
break
if already_exist is False:
with lock:
registered_peers.append(Peer_Info(machineID, key, ip_address, port_number))
print("Added to list of registered peers.")
return True
# ---------------------------------------------------------------------------------------------------------------------#
# ------------------------------------------------- Handle connection -------------------------------------------------#
def handle_incoming_peer(connection):
incoming_message = connection.recv(2048)
incoming_message = incoming_message.decode()
machine_id, key, ip_address, port_number, command, message = incoming_message.