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
12 changes: 9 additions & 3 deletions Makefile
Original file line number Diff line number Diff line change
@@ -1,7 +1,13 @@
all: kilo
CC = gcc -g -Wall -W -ansi -pedantic -std=c99 -pthread -o
C+ = g++ -g -Wall -pthread -std=c++11 -o

all: kilo server

kilo: kilo.c
$(CC) -o kilo kilo.c -Wall -W -pedantic -std=c99
$(CC) kilo kilo.c

server: server.cpp
$(C+) server server.cpp

clean:
rm kilo
rm -f kilo server transfer
31 changes: 30 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,11 @@ Kilo is a small text editor in less than 1K lines of code (counted with cloc).
A screencast is available here: https://asciinema.org/a/90r2i9bq8po03nazhqtsifksb

Usage: kilo `<filename>`
New Usage: kilo <host> <port>

Keys:
'get' to copy file from server

Editor Keys:

CTRL-S: Save
CTRL-Q: Quit
Expand All @@ -24,3 +27,29 @@ style CLI.

Kilo was written by Salvatore Sanfilippo aka antirez and is released
under the BSD 2 clause license.

# cpd-term-project
Term Project for COP5570
Concurrent Text File Editing (Google Docs redev)

Contributers:
Skylar Scorca,
Tony Drouillard,
Jack Dewey

Project Objectives (intended features)
- Allow users to update a single text file simultaneously
- Allow users to view the updates of other users in real-time
- Handle the movement of a user’s cursor after an update is made
- Handle transactions quickly and efficiently

Optional Objectives: (if time allows)
- Allow users to create and delete text files in a greater system of files
- Allow users to modify the tree structure of the greater system of files
- Allow users to view the updates to the file system in real-time

Due date countdown:
https://www.timeanddate.com/countdown/generic?iso=20230428T2359&p0=856&msg=cpd+term+project+due+date&font=cursive&csz=1

Google Drive Folder:
https://drive.google.com/drive/folders/1sZ5ulUizpBA6Rq9KOYdHxhaF4QC_5UAi?usp=share_link
10 changes: 0 additions & 10 deletions TODO

This file was deleted.

91 changes: 85 additions & 6 deletions kilo.c
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@
#include <stdarg.h>
#include <fcntl.h>
#include <signal.h>
#include <netdb.h>

/* Syntax highlight types */
#define HL_NORMAL 0
Expand Down Expand Up @@ -109,6 +110,8 @@ struct editorConfig {
struct editorSyntax *syntax; /* Current syntax highlight, or NULL. */
};

//Note: we may want to add a few fields to the erow and editorConfig structs

static struct editorConfig E;

enum KEY_ACTION{
Expand Down Expand Up @@ -198,6 +201,7 @@ struct editorSyntax HLDB[] = {
#define HLDB_ENTRIES (sizeof(HLDB)/sizeof(HLDB[0]))

/* ======================= Low level terminal handling ====================== */
//Note: probably don't need to edit these

static struct termios orig_termios; /* In order to restore at exit.*/

Expand All @@ -214,7 +218,7 @@ void editorAtExit(void) {
disableRawMode(STDIN_FILENO);
}

/* Raw mode: 1960 magic shit. */
/* Raw mode: 1960 magic*/
int enableRawMode(int fd) {
struct termios raw;

Expand Down Expand Up @@ -362,6 +366,7 @@ int getWindowSize(int ifd, int ofd, int *rows, int *cols) {
}

/* ====================== Syntax highlight color scheme ==================== */
//Note: probably don't need to edit these

int is_separator(int c) {
return c == '\0' || isspace(c) || strchr(",.()+-/*=~%[];",c) != NULL;
Expand Down Expand Up @@ -551,6 +556,10 @@ void editorSelectSyntaxHighlight(char *filename) {
}

/* ======================= Editor rows implementation ======================= */
//Note: probably want to edit these. perhaps at the end of an update function, we call another
// function to send an update message to the server.
//Note: we can copy the logic from these functions to allow for editing after receuving an
// update message from the server.

/* Update the rendered version and the syntax highlight of a row. */
void editorUpdateRow(erow *row) {
Expand Down Expand Up @@ -616,7 +625,7 @@ void editorFreeRow(erow *row) {
free(row->hl);
}

/* Remove the row at the specified position, shifting the remainign on the
/* Remove the row at the specified position, shifting the remaining on the
* top. */
void editorDelRow(int at) {
erow *row;
Expand Down Expand Up @@ -852,6 +861,7 @@ int editorSave(void) {
}

/* ============================= Terminal update ============================ */
//Note: probably don't need to edit these

/* We define a very simple "append buffer" structure, that is an heap
* allocated string where we can append to. This is useful in order to
Expand Down Expand Up @@ -1008,6 +1018,7 @@ void editorSetStatusMessage(const char *fmt, ...) {
}

/* =============================== Find mode ================================ */
//Note: probably don't need to edit these

#define KILO_QUERY_LEN 256

Expand Down Expand Up @@ -1107,6 +1118,7 @@ void editorFind(int fd) {
}

/* ========================= Editor events handling ======================== */
//Note: we probably don't need to edit these

/* Handle cursor position change because arrow keys were pressed. */
void editorMoveCursor(int key) {
Expand Down Expand Up @@ -1288,14 +1300,81 @@ void initEditor(void) {
signal(SIGWINCH, handleSigWinCh);
}

/* ========================= Communication with Server ======================== */

void receiveFile(int fd){
ssize_t n;
FILE *file = fopen("transfer", "w");
char buffer[1024];

n = read(fd, buffer, 1024);
buffer[n] = '\0';

while (1){
if ((n = read(fd, buffer, 1024)) > 0){
// printf("Line: %s\n", buffer);
buffer[n] = '\0';
if (!strcmp(buffer, "End Transfer")){
// printf("Closing\n");
fclose(file);
return;
}
fprintf(file, "%s\n", buffer);
send(fd, "ACK", 1024, 0); //why are we sending this?
}
}
//editorOpen("test");
}

/* ============================= Main Program ================================== */

//main program of text-editor client
int main(int argc, char **argv) {
if (argc != 2) {
fprintf(stderr,"Usage: kilo <filename>\n");
//check command-line args
if (argc != 3) {
fprintf(stderr,"Usage: kilo <host> <port>\n");
exit(1);
}

initEditor();
editorSelectSyntaxHighlight(argv[1]);
//setup
struct addrinfo hints, *res, *traverser;
memset(&hints, 0, sizeof(struct addrinfo));
hints.ai_family = AF_UNSPEC;
hints.ai_socktype = SOCK_STREAM;
int r = getaddrinfo(argv[1], argv[2], &hints, &res);
if (r != 0){
fprintf(stderr,"Error: Can't find server.\n");
return 1;
}

// Try addresses until one is successful
int serverFd;
for (traverser = res; traverser; traverser = traverser->ai_next){
if ((serverFd = socket(traverser->ai_family, traverser->ai_socktype, traverser->ai_protocol)) != -1){
if ((connect(serverFd, traverser->ai_addr, traverser->ai_addrlen)) == 0){
break;
}
}
}
printf("Connected\n");

char buffer[1024];
while (fgets(buffer, 1024, stdin)){
buffer[strcspn(buffer, "\r\n")] = 0;
if (!strcmp(buffer, "get")){
printf("sending get\n");
send(serverFd, "get", 1024, 0);
receiveFile(serverFd);
}
// printf("%s\n", buffer);
}

close(serverFd);
// exit(0);

//start editor
initEditor();
editorSelectSyntaxHighlight("transfer");
editorOpen(argv[1]);
enableRawMode(STDIN_FILENO);
editorSetStatusMessage(
Expand Down
143 changes: 143 additions & 0 deletions server.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,143 @@
// C Headers
#include <arpa/inet.h>
#include <errno.h>
#include <netdb.h>
#include <netinet/in.h>
#include <pthread.h>
#include <signal.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <unistd.h>
// C++ Headers
#include <fstream>
#include <iostream>
#include <sstream>
#include <map>
#include <string>
#include <vector>
using namespace std;

//readFile - reads lines in file into the data structure lines
vector<string> readFile(){
string line;
vector<string> lines;
ifstream file("test");
while (getline(file, line)){
lines.push_back(line);
}
return lines;
}

//sendFile - send file line-by-line to a client at fd
void sendFile(int fd, vector<string> lines){
vector<string>::iterator i;

send(fd, (void*)"Start Transfer", 1024, 0);

/* for (i = lines.begin(); i != lines.end(); i++){
char buffer[1024];
string msg = *i;
// cout << "Line: " << msg << endl;
send(fd, msg.c_str(), msg.length(), 0);
read(fd, buffer, 1024);
} */

//this is the same as the loop that is commented out
for(string msg : lines){
char buffer[1024];

send(fd, msg.c_str(), msg.length(), 0);
read(fd, buffer, 1024);
}

send(fd, (void*)"End Transfer", 1024, 0);
}

//threadFunc - thread function to read any messages from a client
void *threadFunc(void *args){
ssize_t n;
int clientFd = *(int*)args;
char buffer[1024];
pthread_detach(pthread_self());

// Read until disconnection
while ((n = read(clientFd, buffer, 1024)) > 0){
string line(buffer);

if (line == "exit"){
close(clientFd);
}
else if (line == "get"){
cout << "Get Received" << endl;
sendFile(clientFd, readFile());
}
}
return NULL;
}

//handleSigInt - action performed when user types ctrl-C
void handleSigInt(int unused __attribute__((unused))){
exit(0);
}

//main server program
int main(void){

//setup SIGINT signal handler
signal(SIGINT, handleSigInt);

// Create server socket
int serverFd;
if ((serverFd = socket(AF_INET, SOCK_STREAM, 0)) < 0){
std::cerr << "Error: Can't create socket." << std::endl;
return 1;
}

// Set options for socket
int val;
if (setsockopt(serverFd, SOL_SOCKET, SO_REUSEADDR, &val, sizeof(int))){
std::cerr << "Error: Can't reuse socket." << std::endl;
return 2;
}

// Configure addr and bind
struct sockaddr_in serverAddr;
serverAddr.sin_family = AF_INET;
serverAddr.sin_addr.s_addr = htonl(INADDR_ANY);
serverAddr.sin_port = htons(10001);
if (bind(serverFd, (struct sockaddr *)&serverAddr, sizeof(serverAddr)) == -1){
cerr << "Error: Can't bind socket to port." << endl;
return 3;
}

// Listen for client connections
if (listen(serverFd, 20) < 0){
cerr << "Error: Can't listen for clients." << endl;
return 4;
}

// Get name and port assigned to server
char *name = new char[1024];
struct sockaddr_in infoAddr;
socklen_t len = sizeof(infoAddr);
gethostname(name, 1024);
getsockname(serverFd, (struct sockaddr *)&infoAddr, &len);

// Report name and port
cout << name << ":" << ntohs(serverAddr.sin_port)<< endl;
delete name;

// Connect a client
struct sockaddr_in cliAddr;
len = sizeof(cliAddr);
while (true){
int clientFd = accept(serverFd, (struct sockaddr *)&serverAddr, &len);

// Create thread to deal with client
pthread_t thread;
pthread_create(&thread, NULL, threadFunc, (void *)&clientFd);
}
return 0;
}
4 changes: 4 additions & 0 deletions test
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
this is a test file
these are some words
these are some more
bye!
Empty file added transfer
Empty file.