Skip to content
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
595 changes: 595 additions & 0 deletions .gitignore

Large diffs are not rendered by default.

13 changes: 13 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
cmake_minimum_required(VERSION 3.9)
project(networks)

set(TBB_DIR lib/tbb)
set(CMAKE_CXX_STANDARD 11)

include(cmake/TBBGet.cmake)
tbb_get(TBB_ROOT tbb_root CONFIG_DIR TBB_DIR)
find_package(TBB)

add_subdirectory(server/)
add_subdirectory(client/)
add_subdirectory(common/)
5 changes: 5 additions & 0 deletions client/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
project(client)

set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -pthread")

add_executable(client src/main.cpp ../common/src/Message.cpp ../common/include/Message.h ../common/include/ctpl.h src/ChatClient.cpp include/ChatClient.h include/utils.h)
41 changes: 41 additions & 0 deletions client/include/ChatClient.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
//
// Created by Владислав Калинин on 11/02/2019.
//

#ifndef NETWORKS_CHATCLIENT_H
#define NETWORKS_CHATCLIENT_H


#include "../../common/include/Message.h"

class ChatClient {
public:
ChatClient(const char *hostname, uint16_t port);

void registry(std::string name, std::string password);

void login(std::string name, std::string password);

void sendBroadcastMessage(std::string message);

void sendPrivateMessage(std::string reciever, std::string message);

void kickUser(std::string name);

void close_client();

TextMessage *recieveMessage();

private:
int sockfd;
std::string username = "";

void authorization(std::string msg);

void sendMessage(std::string msg);

char *recvMessage();
};


#endif //NETWORKS_CHATCLIENT_H
30 changes: 30 additions & 0 deletions client/include/utils.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
//
// Created by Владислав Калинин on 11/02/2019.
//

#ifndef NETWORKS_UTILS_H
#define NETWORKS_UTILS_H

#include <string>

void split(const std::string &txt, std::vector<std::string> &strs, char delimetr) {
size_t pos = txt.find(delimetr);
size_t initialPos = 0;
strs.clear();

while (pos != std::string::npos) {
strs.push_back(txt.substr(initialPos, pos - initialPos));
initialPos = pos + 1;

pos = txt.find(delimetr, initialPos);
}

strs.push_back(txt.substr(initialPos, std::min(pos, txt.size()) - initialPos + 1));
}

std::string firstWord(const std::string &txt) {
size_t pos = txt.find(' ');
return txt.substr(0, pos);
}

#endif //NETWORKS_UTILS_H
104 changes: 104 additions & 0 deletions client/src/ChatClient.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
//
// Created by Владислав Калинин on 11/02/2019.
//

#include <netinet/in.h>
#include <netdb.h>
#include <string>
#include <zconf.h>
#include <iostream>
#include "../include/ChatClient.h"
#include "../../common/include/constants.h"
#include "../../common/include/Message.h"

ChatClient::ChatClient(const char *hostname, uint16_t port) {
sockaddr_in serv_addr;
hostent *server;

this->sockfd = socket(AF_INET, SOCK_STREAM, 0);

if (this->sockfd < 0) {
perror("ERROR opening socket");
exit(1);
}

server = gethostbyname(hostname);

if (server == nullptr) {
fprintf(stderr, "ERROR, no such host\n");
exit(0);
}

bzero((char *) &serv_addr, sizeof(serv_addr));
serv_addr.sin_family = AF_INET;
bcopy(server->h_addr, (char *) &serv_addr.sin_addr.s_addr, (size_t) server->h_length);
serv_addr.sin_port = htons(port);

if (connect(this->sockfd, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) < 0) {
perror("ERROR connecting");
exit(1);
}
}

void ChatClient::registry(std::string name, std::string password) {
std::string msg = RegistryMessage(name, password).to_json_format();
authorization(msg);
}

void ChatClient::login(std::string name, std::string password) {
if (this->username == "") {
std::string msg = AuthenticationMessage(name, password).to_json_format();
authorization(msg);
this->username = name;
} else {
throw std::runtime_error("client already authentication");
}
}

void ChatClient::authorization(std::string msg) {
sendMessage(msg);
char *responseBuffer = recvMessage();
json response = json::parse(responseBuffer);
delete[] responseBuffer;
if (response.at(STATUS).get<int>() == STATUS_ERROR) {
throw std::runtime_error(response.at(CAUSE).get<std::string>());
}
}

void ChatClient::sendMessage(std::string msg) {
std::string size = std::to_string(msg.size());
write(sockfd, msg.c_str(), msg.size());
}

char *ChatClient::recvMessage() {
char *buffer = new char[1024];
int size = read(sockfd, buffer, 1024);
buffer[size] = '\0';
return buffer;
}

void ChatClient::sendBroadcastMessage(std::string message) {
std::string msg = TextMessage(this->username, message).to_json_format();
sendMessage(msg);
}

TextMessage *ChatClient::recieveMessage() {
char *responseBuffer = recvMessage();
json response = json::parse(responseBuffer);
delete[] responseBuffer;
return new TextMessage(response.at(SENDER).get<std::string>(), response.at(MESSAGE).get<std::string>());
}

void ChatClient::sendPrivateMessage(std::string reciever, std::string message) {
std::string msg = PrivateMessage(this->username, reciever, message).to_json_format();
sendMessage(msg);
}

void ChatClient::close_client() {
close(sockfd);
}

void ChatClient::kickUser(std::string name) {
std::string msg = KickMessage(name).to_json_format();
sendMessage(msg);
}
127 changes: 127 additions & 0 deletions client/src/main.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
#include <stdio.h>
#include <stdlib.h>

#include "../../common/include/json.hpp"
#include "../include/ChatClient.h"
#include "../include/utils.h"
#include "../../common/include/ctpl.h"
#include <iostream>

using namespace nlohmann;

std::string register_format = "\tregister format: \\register <username> <password>";
std::string login_format = "\tlogin format: \\login <username> <password>";

void authorization(ChatClient &client);

std::string getUserName(std::string msg);

void receiveResponses(int id, ChatClient &client);

int main(int argc, char *argv[]) {

if (argc < 3) {
fprintf(stderr, "usage %s hostname port\n", argv[0]);
exit(0);
}

ChatClient client(argv[1], atoi(argv[2]));
authorization(client);

ctpl::thread_pool thread_pool(1);
thread_pool.push(receiveResponses, client);
std::string msg;

try {
while (true) {
getline(std::cin, msg);
if (msg == "") {
continue;
}
if (msg == "\\exit") {
break;
}
if (msg == "\\kick") {
std::cout << "please enter username: ";
std::string name;
std::cin >> name;
client.kickUser(name);
continue;
}
std::string username = getUserName(msg);
if (username == "") {
client.sendBroadcastMessage(msg);
} else {
client.sendPrivateMessage(username, msg);
}
}
} catch (std::exception e) {
std::cout << e.what() << std::endl;
}

client.close_client();

return 0;
}

void receiveResponses(int id, ChatClient &client) {
while (true) {
TextMessage *message = client.recieveMessage();
std::cout << message->getSender() << ": " << message->getMessage() << std::endl;
delete message;
}
}

std::string getUserName(std::string msg) {
std::string username = firstWord(msg);
if (username[0] == '@') {
return username.substr(1);
}
return "";
}

void authorization(ChatClient &client) {
std::cout << "please register or enter username and password:" << std::endl;
std::cout << register_format << std::endl;
std::cout << login_format << std::endl;

std::string cmd_line;
std::string param;
std::vector<std::string> params;

while (true) {
getline(std::cin, cmd_line);
split(cmd_line, params, ' ');
if (params[0] == "\\register") {
if (params.size() != 3) {
std::cout << register_format << std::endl;
} else {
try {
client.registry(params[1], params[2]);
std::cout << "registration successfull" << std::endl;
} catch (std::runtime_error e) {
std::cout << e.what() << std::endl;
} catch (std::exception e) {
std::cout << e.what() << std::endl;
}
}
} else if (params[0] == "\\login") {
if (params.size() != 3) {
std::cout << login_format << std::endl;
} else {
try {
client.login(params[1], params[2]);
std::cout << "login successfull" << std::endl;
break;
} catch (std::runtime_error e) {
std::cout << e.what() << std::endl;
} catch (std::exception e) {
std::cout << e.what() << std::endl;
}
}
} else {
std::cout << "unknow command" << std::endl;
}
params.clear();
}
}
Loading