#!/usr/bin/env python3
import argparse
import traceback
import socket
import ssl
import sys
import re
import json
import random
wordlist = []
# First, store the wordlist for guessing
with open('words.txt','r') as file:
# read each line
for line in file:
# read each word
for word in line.split():
# append the words
wordlist.append(word)
notInWord = []
inWord = []
inPlace = ['']*5
def attempt_guess(id, guesses):
if guesses is not None:
for i in range(0, 5):
if (guesses['marks'][i] == 0):
notInWord.append(guesses['word'][i])
elif (guesses['marks'][i] == 1):
inWord.append(guesses['word'][i])
elif (guesses['marks'][i] == 2):
inPlace[i] = guesses['word'][i]
else:
raise Exception('Invalid mark')
guess = ''
while guess == '':
guess = random.choice(wordlist)
wordlist.remove(guess)
for c in notInWord:
if c in guess:
guess = ''
break
for c in inWord:
if c not in guess:
guess = ''
break
if guess == '':
continue
for i in range(len(inPlace)):
if inPlace[i] != '' and guess[i] != inPlace[i]:
guess = ''
break
guess_message = {'type': 'guess', 'id': id, 'word': guess}
return guess_message
def get_flag(sockt, username):
hello = {'type': 'hello', 'northeastern_username': username} # C -> S interaction
sockt.sendall((json.dumps(hello) + '\n').encode('ascii'))
# Keeps asking for guesses of the word
while True:
# Processes the entire line
data = sockt.recv(10000).decode('ascii')
while not data.endswith('\n'):
data += sockt.recv(10000).decode('ascii')
message = json.loads(data)
if re.match('start', message['type']):
id = message['id']
sockt.sendall((json.dumps(attempt_guess(id, None)) + '\n').encode('ascii'))
elif re.match('retry', message['type']): # C -> S interaction
sockt.sendall((json.dumps(attempt_guess(id, message['guesses'][-1])) + '\n').encode('ascii'))
elif re.match('bye', message['type']):
return message['flag']
else:
raise Exception('Could not understand message: {}'.format(message))
if __name__ == '__main__':
# Start to parse necessary arguments
parser = argparse.ArgumentParser(usage='./client <-p port> <-s> <hostname> <Northeastern-username>')
parser.add_argument('-p', type=int, help='optional TCP port', required = False, dest = 'port')
parser.add_argument('-s', action='store_true',
help='determines whether or not to use TLS encrypted socket',
required = False, dest='use_tls')
parser.add_argument('hostname', type=str, help='name of the server', nargs='?', default='proj1.3700.network')
parser.add_argument('Northeastern_username', type=str, help = 'Northeastern username', nargs='?', default='zinger.m')
args = parser.parse_args()
sockt = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
if args.use_tls:
sockt = ssl.wrap_socket(sockt)
# Here, we use the given port if specified,
# otherwise, assume the port is 27993
# but if given -s flag, we use TLS encryption
# and assume port is 27994
port = args.port if args.port is not None else (
27994 if args.use_tls else 27993)
try:
sockt.connect((args.hostname, port))
except socket.error as error_message:
print('Could not connect to server: {}'.format(error_message))
sys.exit(1)
try:
flag = get_flag(sockt, args.Northeastern_username)
sockt.close()
except Exception as error_message:
print(traceback.format_exc())
print('Could not retrieve secret flag: {}'.format(error_message))
sys.exit(1)
print(flag)