#include "utils.hpp" #define PORT "4444" int main(int argc, char** argv); int connect_to_server(Options* options); void* packet_recieveing_thread(void* poptions); void* ping_thread(void* poptions); int parse_arguments(int argc, char** argv, Options* options); int print_help(); Options options {}; int main(int argc, char** argv) { int status; char player_name[20] = "Anonymous"; char num[5]; sprintf(num, "%d", (int)(time(0) % 9999)); strncat(player_name, num, sizeof(player_name)); options.server = false; strncpy(options.port, PORT, sizeof(options.port)); strncpy(options.name, player_name, sizeof(options.name)); options.encryption = false; strncpy(options.password, DEFAULT_PASS, sizeof(options.password)); status = parse_arguments(argc, argv, &options); if(status) { print_help(); goto end; } status = connect_to_server(&options); if(status) { ERROR_LOG("Failed to connect to the server.\n"); goto end; } INFO_LOG("Succesfully connected to server.\n"); pthread_t packet_recieveing_thread_id; pthread_create(&packet_recieveing_thread_id, NULL, packet_recieveing_thread, (void*)&options); start_client(NULL, &options); end: return status; } int connect_to_server(Options* options) { options->sockfd = socket(AF_INET, SOCK_STREAM, 0); if(options->sockfd < 0) return 1; struct sockaddr_in sockaddr; sockaddr.sin_family = AF_INET; sockaddr.sin_addr.s_addr = inet_addr(options->ip); sockaddr.sin_port = htons(atoi(options->port)); if(connect(options->sockfd, (struct sockaddr*)&sockaddr, sizeof(sockaddr))) return 2; Packet packet {}; packet.type = PacketType::packet_connect; strncpy(packet.data.packet_connect.name, options->name, sizeof(packet.data.packet_connect.name)); packet.data.packet_connect.pass = options->pass; strncpy(packet.data.packet_connect.password, options->password, sizeof(packet.data.packet_connect.password)); if(send_packet(&packet, &options->sockfd, options, NULL)) return 3; pthread_t ping_thread_id; pthread_create(&ping_thread_id, NULL, ping_thread, (void*)options); return 0; } void* packet_recieveing_thread(void* poptions) { Options* opt = (Options*)poptions; Packet incoming_packet {}; int read_size = 0; while((read_size = recv(opt->sockfd, &incoming_packet, sizeof(incoming_packet), 0)) > 0) { int result = handle_incoming_packet(&incoming_packet, &opt->sockfd, NULL, &options); if(result) { ERROR_LOG("Invalid packet recieved.\n"); exit(1); } } return 0; } void* ping_thread(void* poptions) { Options* opt = (Options*)poptions; while(1) { Packet ping {}; ping.type = PacketType::packet_ping; strncpy(ping.data.packet_ping.name, opt->name, sizeof(ping.data.packet_ping.name)); if(send_packet(&ping, &opt->sockfd, opt, NULL)) { ERROR_LOG("Lost connection to server.\n"); exit(1); } sleep(2); } } int parse_arguments(int argc, char** argv, Options* options) { extern char* optarg; int status = 0; bool mand_flag = false; int option; while((option = getopt(argc, argv, "i:p:en:x:h")) != -1) switch(option) { case 'i': strncpy(options->ip, optarg, sizeof(options->ip)); mand_flag = true; break; case 'p': strncpy(options->port, optarg, sizeof(options->port)); break; case 'e': options->encryption = true; break; case 'n': strncpy(options->name, optarg, sizeof(options->name)); break; case 'x': options->pass = true; strncpy(options->password, optarg, sizeof(options->password)); break; case 'h': print_help(); break; case ':': status = 1; break; case '?': status = 1; break; } if(!mand_flag) { status = 1; ERROR_LOG("Needs ip argument (-i IP)\n"); } return status; } int print_help() { printf( "Usage:\n" "\t./client\n" "\t\t-i (IP) [ip address]\n" "\t\t-p (PORT) [port number]\n" "\t\t-e [encryption]\n" "\t\t-n (NAME) [username]\n" "\t\t-x (PASS) [password]\n" "\t\t-h [show help]\n" ); return 0; }