Skip to content

Simple client mode #17

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 19 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 17 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,23 @@ $ gpg-group-chat --server
$ gpg-group-chat --client
```

## Basic usage flow

1. Server starts with gpg-group-chat --server at 192.168.0.1
2. The client1 starts with gpg-group-chat --client --server-ip=192.168.0.1 --public-key=public-key1
3. The client1 connect to the server and the it stores the public key for client1
4. The server send the current list of keys for client1 (contains public key1)
5. The client2 starts with gpg-group-chat --client --server-ip=192.168.0.1 --public-key=public-key2
6. The client2 connect to the server and the it stores the public key for client2
7. The server send the current list of keys for client1 and client2 (contains public key1 and public key2)
8. The client3 starts with gpg-group-chat --client --server-ip=192.168.0.1 --public-key=public-key3
9. The client3 connect to the server and the it stores the public key for client3
10. The server send the current list of keys for client1, client2 and client3 (contains public key1, public key2 and public key3)
11. The client2 disconnects from the server
12. the server delete the public key from client 2 from the storage
13. The server send the current list of keys for client1 and client3 (contains public key1 and public key3)
...

# Issue board

[Waffle.io/bahackers/gpg-group-chat](https://waffle.io/bahackers/gpg-group-chat)
54 changes: 52 additions & 2 deletions gpg_group_chat/client/client.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,54 @@
import select
import socket
import sys


class Client():

def start(self, port, host):
print('Hello friend!')
def __init__(self):
self._socket = None
self._working = True

def start(self, server_port, server_ip):
print('Hello friend')
dest = (server_ip, server_port)

try:
self._socket = socket.create_connection(dest)
except ConnectionRefusedError as err:
print('Connection refused')
sys.exit(1)

self._handle_messages()

def _handle_messages(self):
input_list = [sys.stdin, self._socket]
self._prompt()
while self._working:
ready_to_read, _, _ = select.select(input_list, [], [])
self._handle_input_channel(ready_to_read)

def _handle_input_channel(self, ready_to_read):
for input_channel in ready_to_read:
if input_channel is self._socket:
self._receive_data_from_server()
else:
self._send_message_to_server()

def _receive_data_from_server(self):
data = self._socket.recv(4096)
if not data:
print('\nDisconnected from chat server')
sys.exit(0)
else:
print(data.decode('utf-8'))
self._prompt()

def _send_message_to_server(self):
msg = '[*] %s' % input()
self._socket.send(msg.encode('utf-8'))
self._prompt()

def _prompt(self):
print('[Me] ', end='')
sys.stdout.flush()
3 changes: 2 additions & 1 deletion gpg_group_chat/server/server.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ def __init__(self):
self._working = False

def start(self, port, target):
print('Server listening on %s:%d' % (target, port))
print('Server is not done yet!')
self._working = True
try:
self._socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
Expand Down Expand Up @@ -49,3 +49,4 @@ def _client_handler(client_socket, thread_event):
break
else:
print('[INFO] Received: %s' % data)
client_socket.sendall(b'\rACK{}\n')
2 changes: 2 additions & 0 deletions gpg_group_chat/utils.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
def show_help():
print('Helper will be available soon!')
89 changes: 86 additions & 3 deletions test/client/client_test.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,88 @@
import gpg_group_chat.client
from gpg_group_chat.client.client import Client
from socket import socket as SocketType
from unittest import TestCase
from unittest.mock import Mock
from unittest.mock import patch
import sys


def test_start_gpg_groupd_chat():
assert True
class ClientTest(TestCase):

def setUp(self):
self.create_connection = patch('socket.create_connection').start()
self.exit = patch('sys.exit').start()
self.readline = patch('sys.stdin.readline').start()
self.select = patch('select.select').start()
self.print_stdout = patch('sys.stdout.write').start()

self.socket = Mock(SocketType)
self.create_connection.return_value = self.socket

self.client = Client()

def test_connect_to_a_server(self):
def _handle_messages():
pass

self.client._handle_messages = _handle_messages
self.client.start(9999, '127.0.0.1')

self.create_connection.assert_called_once_with(('127.0.0.1', 9999))

def test_to_connect_to_unexist_server(self):
def side_effect(dest):
raise ConnectionRefusedError(111, 'connection refused')

def _handle_messages():
pass

self.create_connection.side_effect = side_effect
self.client._handle_messages = _handle_messages

self.client.start(9999, 'server.runkown')

self.exit.assert_called_once_with(1)

def test_send_a_message_to_the_server(self):
def side_effect(msg):
self.client._working = False

self.socket.send.side_effect = side_effect
self.readline.return_value = 'message'
self.select.return_value = ([sys.stdin], None, None)

self.client.start(9999, '127.0.0.1')

self.socket.send.assert_called_once_with(b'[*] message')

def test_receive_a_message_from_the_server(self):
def side_effect(size):
self.client._working = False
return b'message from server'

self.socket.recv.side_effect = side_effect
self.select.return_value = ([self.socket], None, None)

self.client.start(9999, '127.0.0.1')

self.print_stdout.assert_any_call('message from server')

def test_exit_when_disconnect_with_the_server(self):
def side_effect(size):
self.client._working = False
return None

self.socket.recv.side_effect = side_effect
self.select.return_value = ([self.socket], None, None)

self.client.start(9999, '127.0.0.1')

self.print_stdout.assert_any_call('\nDisconnected from chat server')
self.exit.assert_called_once_with(0)

def test_the_prompt_meyhod_does_not_print_with_break_line_char(self):
def side_effect(txt):
assert not txt.endswith('\n')

self.print_stdout.side_effect = side_effect
self.client._prompt()