Skip to content

Commit

Permalink
Merge pull request #53 from rahimklaber/master
Browse files Browse the repository at this point in the history
Add Group 3 Peerson implementation
  • Loading branch information
rellermeyer authored Apr 4, 2022
2 parents 0149a49 + d0d45c5 commit bb0862b
Show file tree
Hide file tree
Showing 26 changed files with 1,338 additions and 0 deletions.
64 changes: 64 additions & 0 deletions PeerSoN/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
# PeerSon - P2P Online social network

## IN4391 Distributed Systems Group 3

### Authors:

- Klabér, Rahim
- Morstøl, Hallvard Molin
- Qiu, Jason
- Samardžić, Mariana

## About PeerSoN

PeerSoN is a distributed Online Social Network (OSN). It is using the all-peers decentralized system architecture. PeerSoN is doing this by combining peer-to-peer (P2P) infrastructure, encryption and a distributed hash table (DHT).

## Requirements

These are the versions of tools we used. We have not tested if the system works on earlier or later versions.

- Open JDK: 17.0.2
- Scala version: 2.13.8
- SBT: 1.6.2

## Running the project

### Running with Intellij

In IntelliJ, the `src/main/resources` folder needs to be marked as a resource folder. To do this, right-click
the folder and at the bottom there should be an option called "Mark directory as" and then "Resources root" should be selected.

### Running the project

Two environment variables need to be set. First `HOST` which is the computer's IP or the router's IP in the case that you are behind a NAT and want to use the application over the internet (This can be found by running `curl ifconfig.me`) .

Second `BOOTSTRAP` needs to be set to the IP of a TOMP2P DHT which will bootstrap our DHT.

To run a bootstrap node, use a dummy `HOST` value and set `BOOTSTRAP` to the computer's IP. Then login with a dummy name such as `BOOTSTRAPNODE`. The bootstrap node should now be ready.


Depending on your system build/compile:

- `sbt compile` or build from inside your IDE.

After building the project.
Run the main object in ./src/main/scala/main.scala.

- `sbt run` or run from inside your IDE.

You can then run some possible commands to send to the guardian, which works as the interface for the application:

- `login`
- Guardian asks for mail and location to log user in. User gets any messages he received while offline.
- `logout`
- Guardian logs user out by asking for mail and location.
- `send-message`
- Guardian asks for sender, receiver and text to send and sends the message.
- `add-to-wall`
- Guardian asks for sender, receiver and text to send and adds the text to the users wall.
- `request-wall`
- Guardian asks for the user requesting, the file name and sends the file back.
- To be able to fetch entries of some user's wall, a user should first request the wall index file of that user which contains all the file names of the individual entries.
- The file name of a user's wall index is in the form email@wi.
- `exit`
- Exit the interface
20 changes: 20 additions & 0 deletions PeerSoN/build.sbt
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
name := "in4391_peerson"

version := "0.1"

scalaVersion := "2.13.8"

//resolvers += "Typesafe Repository" at "http://repo.typesafe.com/typesafe/releases/"


val AkkaVersion = "2.6.18"
libraryDependencies ++= Seq(
"com.typesafe.akka" %% "akka-actor-typed" % AkkaVersion,
"com.typesafe.akka" %% "akka-actor-testkit-typed" % AkkaVersion % Test,
"com.typesafe.akka" %% "akka-remote" % AkkaVersion,
"ch.qos.logback" % "logback-classic" % "1.2.10",
"net.tomp2p" % "tomp2p-all" % "5.0-Beta8",
"com.simtechdata" % "WaifUPnP" % "1.0"
)

resolvers += ("tomp2p.net" at "http://tomp2p.net/dev/mvn/").withAllowInsecureProtocol(true)
103 changes: 103 additions & 0 deletions PeerSoN/experiments/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
#
# Scala and sbt Dockerfile
#
# Based on https://github.com/hseeberger/scala-sbt/blob/master/debian/Dockerfile
# Based on https://jrtechs.net/java/running-scala-code-in-docker

# Pull base image
ARG BASE_IMAGE_TAG
FROM openjdk:${BASE_IMAGE_TAG:-17.0.2-jdk-bullseye}

# Env variables
ARG SCALA_VERSION
ENV SCALA_VERSION ${SCALA_VERSION:-2.13.8}
ARG SBT_VERSION
ENV SBT_VERSION ${SBT_VERSION:-1.6.2}
ARG USER_ID
ENV USER_ID ${USER_ID:-1001}
ARG GROUP_ID
ENV GROUP_ID ${GROUP_ID:-1001}

ARG buildtime_host=80.114.141.221
ENV HOST=$buildtime_host

ARG buildtime_bootstrap=150.230.20.128
ENV BOOTSTRAP=$buildtime_bootstrap

# Install sbt
RUN \
curl -fsL "https://github.com/sbt/sbt/releases/download/v$SBT_VERSION/sbt-$SBT_VERSION.tgz" | tar xfz - -C /usr/share && \
chown -R root:root /usr/share/sbt && \
chmod -R 755 /usr/share/sbt && \
ln -s /usr/share/sbt/bin/sbt /usr/local/bin/sbt

# Install Scala
RUN \
case $SCALA_VERSION in \
"3"*) URL=https://github.com/lampepfl/dotty/releases/download/$SCALA_VERSION/scala3-$SCALA_VERSION.tar.gz SCALA_DIR=/usr/share/scala3-$SCALA_VERSION ;; \
*) URL=https://downloads.typesafe.com/scala/$SCALA_VERSION/scala-$SCALA_VERSION.tgz SCALA_DIR=/usr/share/scala-$SCALA_VERSION ;; \
esac && \
curl -fsL $URL | tar xfz - -C /usr/share && \
mv $SCALA_DIR /usr/share/scala && \
chown -R root:root /usr/share/scala && \
chmod -R 755 /usr/share/scala && \
ln -s /usr/share/scala/bin/* /usr/local/bin && \
case $SCALA_VERSION in \
"3"*) echo "@main def main = println(util.Properties.versionMsg)" > test.scala ;; \
*) echo "println(util.Properties.versionMsg)" > test.scala ;; \
esac && \
scala -nocompdaemon test.scala && rm test.scala

# Install rpm for sbt-native-packager
# see https://github.com/hseeberger/scala-sbt/pull/114
RUN apt-get update && \
apt-get install rpm -y && \
rm -rf /var/lib/apt/lists/*

# Add and use user sbtuser
RUN groupadd --gid $GROUP_ID sbtuser && useradd -m --gid $GROUP_ID --uid $USER_ID sbtuser --shell /bin/bash
USER sbtuser

# Switch working directory
WORKDIR /home/sbtuser

# Prepare sbt (warm cache)
RUN \
sbt sbtVersion && \
mkdir -p project && \
echo "scalaVersion := \"${SCALA_VERSION}\"" > build.sbt && \
echo "sbt.version=${SBT_VERSION}" > project/build.properties && \
echo "// force sbt compiler-bridge download" > project/Dependencies.scala && \
echo "case object Temp" > Temp.scala && \
sbt compile && \
rm -r project && rm build.sbt && rm Temp.scala && rm -r target

# Link everything into root as well
# This allows users of this container to choose, whether they want to run the container as sbtuser (non-root) or as root
USER root
RUN \
ln -s /home/sbtuser/.cache /root/.cache && \
ln -s /home/sbtuser/.sbt /root/.sbt && \
if [ -d "/home/sbtuser/.ivy2" ]; then ln -s /home/sbtuser/.ivy2 /root/.ivy2; fi

# Switch working directory back to root
## Users wanting to use this container as non-root should combine the two following arguments
## -u sbtuser
## -w /home/sbtuser
WORKDIR /root

EXPOSE 6122/udp
EXPOSE 6122/tcp
EXPOSE 5001/udp
EXPOSE 5001/tcp
EXPOSE 5000/tcp

WORKDIR /home/sbtuser/project

RUN git clone https://github.com/rahimklaber/in4391_peerson.git

WORKDIR /home/sbtuser/project/in4391_peerson

RUN sbt compile

CMD ["bash"]
28 changes: 28 additions & 0 deletions PeerSoN/experiments/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
! This does not work, you can start the system but, it throws an error when trying to send messages !

Prerequisite:

- Docker

To start the application run in this folder the command:

Find your ip with: `curl ifconfig.me`

The first node created will have the bootstrap ip with: `curl ifconfig.me`

`docker build -t peerson .\ --build-arg buildtime_bootstrap=your_ip --build-arg buildtime_bootstrap=bootstrap_ip`

`docker run -it peerson /bin/bash`

Check that the addresses are set correctly `echo host:$HOST bootstrap:$BOOTSTRAP`

`sbt run`

Possible commands for the guardian:

- `login`
- `logout`
- `send-message`
- `add-to-wall`
- `request-wall`
- `exit`
6 changes: 6 additions & 0 deletions PeerSoN/experiments/Results/time.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
Time measured in seconds when performing different actions.
Login: 10.20, 10.169, 10.163, 10.191, 10.186, 10.176, 10.166, 10.182, 10.172, 10.182
Login w/notifications: 10.105, 10.087, 10.098, 10.181, 10.072, 10.127, 10.212, 10.134, 10.111, 10.206
Logout: 5.097, 5.074, 5.097, 5.077, 5.076, 5.082, 5.085, 5.090, 5.080, 5.090
sync-message: 0.096, 0.062, 0.055, 0.052, 0.051, 0.054, 0.053, 0.054, 0.058, 0.054
Request-wall: 10.082, 10.091, 10.121, 10.101, 10.065, 10.082, 10.091, 10.012, 10.099, 10.105
22 changes: 22 additions & 0 deletions PeerSoN/src/main/resources/application.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
akka {
loglevel = "INFO"

actor {
allow-java-serialization = true
provider = remote
}
remote {
enabled-transports = ["akka.remote.netty.tcp"]

artery {
transport = tcp # See Selecting a transport below
bind.hostname = "0.0.0.0" # internal (bind) hostname
bind.port = 6122 # internal (bind) port

canonical.hostname = ${HOST} # external (logical) hostname
canonical.port = 6122 # external (logical) port
}
log-sent-messages = on
log-received-messages = on
}
}
13 changes: 13 additions & 0 deletions PeerSoN/src/main/resources/logback.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<configuration>
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>%d{HH:mm:ss} [%thread] %-5level %logger{1000} - %msg%n</pattern>
</encoder>
</appender>

<logger name="net.tomp2p" level="OFF"/>

<root level="info">
<appender-ref ref="STDOUT" />
</root>
</configuration>
45 changes: 45 additions & 0 deletions PeerSoN/src/main/scala/REPLCommand.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
/**
* a file for REPLCommand trait and child case classes
*/

trait REPLCommand

/**
* REPL lets `user` to login
* @param user user email (not hashed)
* @param location location string
*/
case class Login(user: String, location: String) extends REPLCommand

/**
* REPL lets `user` to logout
* @param user user email (not hashed)
* @param location location string
*/
case class Logout(user: String, location: String) extends REPLCommand

/**
* REPL lets user with `mail` to send a message `test`
* @param sender sender mail (not hashed)
* @param receiver receiver mail (not hashed)
* @param text text message
*/
case class SendMessage(sender: String, receiver: String, text: String) extends REPLCommand

/**
* REPL lets `sender` to send a message `text` to `owner`'s wall
* @param sender sender email (not hashed)
* @param owner wall owner, message receiver, email (not hashed)
* @param text message text
*/
case class AddWallByUser(sender: String, owner: String, text: String) extends REPLCommand

/**
* REPL lets `requester` to request a file `fileName` of `version` from responder`
* @param requester file requester, email (not hashed)
* @param responder file responder, email (not hashed)
* @param fileName filename
* @param version version == 0 by default
*/
case class RequestFileByUser(requester: String, responder: String, fileName: String, version: Int) extends REPLCommand

36 changes: 36 additions & 0 deletions PeerSoN/src/main/scala/dht/DHT.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
package dht

trait DHT {
/**
* put a new key on the DHT
* create a data list for this key
* add the data to the list
*/
def put(key: String, data: Any): Unit

/**
* retrieves the head of data list by key
* if key not existed, return None
*/
def get(key: String, callback: Option[Any] => Unit): Unit

/**
* check if the DHT contains a certain key
*/
def contains(key: String, callback: Boolean => Unit): Unit

/**
* update the data list with a new item under a key
*/
def append(key: String, data: Any): Unit

/**
* retrieves all values stored in a data list under a key
*/
def getAll(key: String, callback: Option[List[Any]] => Unit): Unit

/**
* remove a key-value pair
*/
def remove(key: String): Unit
}
Loading

0 comments on commit bb0862b

Please sign in to comment.