summaryrefslogtreecommitdiff
path: root/bittorrent
diff options
context:
space:
mode:
Diffstat (limited to 'bittorrent')
-rw-r--r--bittorrent/.clang-format79
-rw-r--r--bittorrent/.gitignore10
-rw-r--r--bittorrent/bittorrent/libs/mbtbe/include/mbt/be/bencode.h122
-rw-r--r--bittorrent/bittorrent/libs/mbtbe/include/mbt/be/mytorrent.h87
-rw-r--r--bittorrent/bittorrent/libs/mbtbe/include/mbt/be/torrent.h53
-rw-r--r--bittorrent/bittorrent/libs/mbtbe/include/mbt/be/torrent_files.h35
-rw-r--r--bittorrent/bittorrent/libs/mbtbe/include/mbt/be/torrent_getters.h88
-rw-r--r--bittorrent/bittorrent/libs/mbtbe/meson.build57
-rw-r--r--bittorrent/bittorrent/libs/mbtbe/src/beutils.c107
-rw-r--r--bittorrent/bittorrent/libs/mbtbe/src/decode.c220
-rw-r--r--bittorrent/bittorrent/libs/mbtbe/src/encode.c56
-rw-r--r--bittorrent/bittorrent/libs/mbtbe/src/mygetters.c61
-rw-r--r--bittorrent/bittorrent/libs/mbtbe/src/mygetters2.c10
-rw-r--r--bittorrent/bittorrent/libs/mbtbe/src/mytfiles.c26
-rw-r--r--bittorrent/bittorrent/libs/mbtbe/src/mytorrent.c113
-rw-r--r--bittorrent/bittorrent/libs/mbtbe/src/mytorrentfile.c282
-rw-r--r--bittorrent/bittorrent/libs/mbtbe/src/node.c93
-rw-r--r--bittorrent/bittorrent/libs/mbtfile/include/mbt/file/file_handler.h42
-rw-r--r--bittorrent/bittorrent/libs/mbtfile/include/mbt/file/my_file_handler.h31
-rw-r--r--bittorrent/bittorrent/libs/mbtfile/include/mbt/file/my_piece.h26
-rw-r--r--bittorrent/bittorrent/libs/mbtfile/include/mbt/file/piece.h55
-rw-r--r--bittorrent/bittorrent/libs/mbtfile/meson.build51
-rw-r--r--bittorrent/bittorrent/libs/mbtfile/src/mbt_file_handler.c119
-rw-r--r--bittorrent/bittorrent/libs/mbtfile/src/mbt_piece.c70
-rw-r--r--bittorrent/bittorrent/libs/mbtnet/include/mbt/net/context.h29
-rw-r--r--bittorrent/bittorrent/libs/mbtnet/include/mbt/net/leeching.h15
-rw-r--r--bittorrent/bittorrent/libs/mbtnet/include/mbt/net/peer.h16
-rw-r--r--bittorrent/bittorrent/libs/mbtnet/include/mbt/net/tracker.h12
-rw-r--r--bittorrent/bittorrent/libs/mbtnet/meson.build59
-rw-r--r--bittorrent/bittorrent/libs/mbtnet/src/mbtnet.c1
-rw-r--r--bittorrent/bittorrent/libs/mbtutils/include/mbt/utils/str.h30
-rw-r--r--bittorrent/bittorrent/libs/mbtutils/include/mbt/utils/utils.h17
-rw-r--r--bittorrent/bittorrent/libs/mbtutils/include/mbt/utils/view.h88
-rw-r--r--bittorrent/bittorrent/libs/mbtutils/meson.build29
-rw-r--r--bittorrent/bittorrent/libs/mbtutils/src/cmp.c18
-rw-r--r--bittorrent/bittorrent/libs/mbtutils/src/contains.c15
-rw-r--r--bittorrent/bittorrent/libs/mbtutils/src/ctor.c19
-rw-r--r--bittorrent/bittorrent/libs/mbtutils/src/dtor.c15
-rw-r--r--bittorrent/bittorrent/libs/mbtutils/src/fprint.c16
-rw-r--r--bittorrent/bittorrent/libs/mbtutils/src/free.c10
-rw-r--r--bittorrent/bittorrent/libs/mbtutils/src/init.c12
-rw-r--r--bittorrent/bittorrent/libs/mbtutils/src/pushc.c18
-rw-r--r--bittorrent/bittorrent/libs/mbtutils/src/pushcstr.c11
-rw-r--r--bittorrent/bittorrent/libs/mbtutils/src/pushcv.c10
-rw-r--r--bittorrent/bittorrent/meson.build102
-rw-r--r--bittorrent/bittorrent/src/mbt.c10
-rw-r--r--bittorrent/epoll_server/connection.c58
-rw-r--r--bittorrent/epoll_server/connection.h54
-rw-r--r--bittorrent/epoll_server/epoll_server.c134
-rw-r--r--bittorrent/epoll_server/epoll_server.h58
-rw-r--r--bittorrent/epoll_server/meson.build32
-rw-r--r--bittorrent/epoll_server/utils/xalloc.c31
-rw-r--r--bittorrent/epoll_server/utils/xalloc.h32
-rw-r--r--bittorrent/mbtstr/include/mbtstr/str.h30
-rw-r--r--bittorrent/mbtstr/include/mbtstr/utils.h17
-rw-r--r--bittorrent/mbtstr/include/mbtstr/view.h88
-rw-r--r--bittorrent/mbtstr/meson.build45
-rw-r--r--bittorrent/mbtstr/src/cmp.c18
-rw-r--r--bittorrent/mbtstr/src/contains.c16
-rw-r--r--bittorrent/mbtstr/src/ctor.c19
-rw-r--r--bittorrent/mbtstr/src/dtor.c15
-rw-r--r--bittorrent/mbtstr/src/fprint.c17
-rw-r--r--bittorrent/mbtstr/src/free.c11
-rw-r--r--bittorrent/mbtstr/src/init.c12
-rw-r--r--bittorrent/mbtstr/src/pushc.c18
-rw-r--r--bittorrent/mbtstr/src/pushcstr.c11
-rw-r--r--bittorrent/mbtstr/src/pushcv.c10
-rw-r--r--bittorrent/meson.build15
68 files changed, 3186 insertions, 0 deletions
diff --git a/bittorrent/.clang-format b/bittorrent/.clang-format
new file mode 100644
index 0000000..7ed8115
--- /dev/null
+++ b/bittorrent/.clang-format
@@ -0,0 +1,79 @@
+AccessModifierOffset: -4
+AlignAfterOpenBracket: Align
+AlignConsecutiveAssignments: false
+AlignConsecutiveDeclarations: false
+AlignEscapedNewlines: Right
+AlignOperands: false
+AlignTrailingComments: false
+AllowAllParametersOfDeclarationOnNextLine: false
+AllowShortBlocksOnASingleLine: false
+AllowShortCaseLabelsOnASingleLine: false
+AllowShortFunctionsOnASingleLine: None
+AllowShortIfStatementsOnASingleLine: false
+AlwaysBreakAfterReturnType: None
+AlwaysBreakBeforeMultilineStrings: false
+AlwaysBreakTemplateDeclarations: Yes
+BinPackArguments: true
+BinPackParameters: true
+BreakBeforeBraces: Custom
+BraceWrapping:
+ AfterEnum: true
+ AfterClass: true
+ AfterControlStatement: true
+ AfterFunction: true
+ AfterNamespace: true
+ AfterStruct: true
+ AfterUnion: true
+ AfterExternBlock: true
+ BeforeCatch: true
+ BeforeElse: true
+ IndentBraces: false
+ SplitEmptyFunction: false
+ SplitEmptyRecord: false
+ SplitEmptyNamespace: false
+BreakBeforeBinaryOperators: NonAssignment
+BreakBeforeTernaryOperators: true
+BreakConstructorInitializers: BeforeComma
+BreakInheritanceList: BeforeComma
+BreakStringLiterals: true
+ColumnLimit: 80
+CompactNamespaces: false
+ConstructorInitializerAllOnOneLineOrOnePerLine: false
+ConstructorInitializerIndentWidth: 4
+Cpp11BracedListStyle: false
+DerivePointerAlignment: false
+FixNamespaceComments: true
+ForEachMacros: ['ILIST_FOREACH', 'ILIST_FOREACH_ENTRY']
+IncludeBlocks: Regroup
+IncludeCategories:
+ - Regex: '<.*>'
+ Priority: 1
+ - Regex: '.*'
+ Priority: 2
+IndentCaseLabels: false
+IndentPPDirectives: AfterHash
+IndentWidth: 4
+IndentWrappedFunctionNames: false
+KeepEmptyLinesAtTheStartOfBlocks: false
+Language: Cpp
+NamespaceIndentation: All
+PointerAlignment: Right
+ReflowComments: true
+SortIncludes: true
+SortUsingDeclarations: false
+SpaceAfterCStyleCast: false
+SpaceAfterTemplateKeyword: true
+SpaceBeforeAssignmentOperators: true
+SpaceBeforeCpp11BracedList: false
+SpaceBeforeCtorInitializerColon: true
+SpaceBeforeParens: ControlStatements
+SpaceBeforeRangeBasedForLoopColon: true
+SpaceInEmptyParentheses: false
+SpacesBeforeTrailingComments: 1
+SpacesInAngles: false
+SpacesInCStyleCastParentheses: false
+SpacesInContainerLiterals: false
+SpacesInParentheses: false
+SpacesInSquareBrackets: false
+TabWidth: 4
+UseTab: Never
diff --git a/bittorrent/.gitignore b/bittorrent/.gitignore
new file mode 100644
index 0000000..79d706c
--- /dev/null
+++ b/bittorrent/.gitignore
@@ -0,0 +1,10 @@
+*.swp
+*.swo
+*.swap
+.vs*
+build/
+builddir/
+.cache
+nopush*
+*tests*
+*Identifier
diff --git a/bittorrent/bittorrent/libs/mbtbe/include/mbt/be/bencode.h b/bittorrent/bittorrent/libs/mbtbe/include/mbt/be/bencode.h
new file mode 100644
index 0000000..e9ae123
--- /dev/null
+++ b/bittorrent/bittorrent/libs/mbtbe/include/mbt/be/bencode.h
@@ -0,0 +1,122 @@
+#ifndef MBT_BE_BENCODE_H
+#define MBT_BE_BENCODE_H
+
+////////////////////////////////////////////////////////////////////////////////
+/// THIS FILE WILL BE OVERWRITTEN ///
+////////////////////////////////////////////////////////////////////////////////
+
+// mbtstr
+#include <mbt/utils/str.h>
+// libc
+#include <stddef.h>
+#include <stdint.h>
+
+enum mbt_be_type
+{
+ MBT_BE_NUM,
+ MBT_BE_STR,
+ MBT_BE_LIST,
+ MBT_BE_DICT,
+};
+
+struct mbt_be_pair
+{
+ struct mbt_str key;
+ struct mbt_be_node *val;
+};
+
+struct mbt_be_node
+{
+ enum mbt_be_type type;
+ union mbt_be_value
+ {
+ int64_t nb;
+ struct mbt_str str;
+ /* A `NULL` terminated array of `mbt_be_node`. */
+ struct mbt_be_node **list;
+ /* A `NULL` terminated array of `mbt_be_pair`. */
+ struct mbt_be_pair **dict;
+ } v;
+};
+
+/**
+** @brief Decode a buffer and return it as a `be_node`.
+**
+** @param buf The buffer to decode.
+**
+** @return On success, the `be_node` corresponding to `buf`, `NULL` on failure.
+** A failure can occur if the size is not correct or if the input is
+** ill-formed, in which case `errno` is set to `EINVAL`, or if an
+** allocation error occurs, in which case `errno` is set to `ENOMEM`.
+*/
+struct mbt_be_node *mbt_be_decode(struct mbt_cview *buf) MBT_NONNULL(1);
+
+/**
+** @brief Encode the content of `node` and return it in the allocated buffer.
+**
+** @param node The `mbt_be_node` to encode.
+**
+** @result The allocated buffer filled with the encoded node.
+** Return `NULL` and set `errno` to `ENOMEM` on allocation error.
+*/
+struct mbt_str mbt_be_encode(struct mbt_be_node *node) MBT_NONNULL(1);
+
+/**
+** @brief Allocate and initialize a `mbt_be_node` of type MBT_BE_DICT and set
+*the field.
+**
+** @param d The pairs of the node.
+**
+** @return the initialized `mbt_be_node`, or NULL in case of error.
+*/
+struct mbt_be_node *mbt_be_dict_init(struct mbt_be_pair **d);
+
+/**
+** @brief Allocate and initialize a `mbt_be_node` of type MBT_BE_STR and set the
+*field.
+**
+** @param v The value of the node.
+**
+** @return the initialized `mbt_be_node`, or NULL in case of error.
+*/
+struct mbt_be_node *mbt_be_str_init(struct mbt_cview v);
+
+/**
+** @brief Allocate and initialize a `mbt_be_node` of type MBT_BE_LIST and set
+*the field.
+**
+** @param l The value of the node.
+**
+** @return the initialized `mbt_be_node`, or NULL in case of error.
+*/
+struct mbt_be_node *mbt_be_list_init(struct mbt_be_node **l);
+
+/**
+** @brief Allocate and initialize a `mbt_be_node` of type MBT_BE_NUM and set the
+*field.
+**
+** @param n The value of the node.
+**
+** @return the initialized `mbt_be_node`, or NULL in case of error.
+*/
+struct mbt_be_node *mbt_be_num_init(int64_t n);
+
+/**
+** @brief Allocate and initialize a `mbt_be_pair` set the fields.
+**
+** @param key The key of the pair.
+** @param node The node of the pair.
+**
+** @return the initialized `mbt_be_pair`, or NULL in case of error.
+*/
+struct mbt_be_pair *mbt_be_pair_init(struct mbt_cview key,
+ struct mbt_be_node *node);
+
+/**
+** @brief Free a `mbt_be_node`.
+**
+** @param node The `mbt_be_node` to free.
+*/
+void mbt_be_free(struct mbt_be_node *node);
+
+#endif /* !MBT_BE_BENCODE_H */
diff --git a/bittorrent/bittorrent/libs/mbtbe/include/mbt/be/mytorrent.h b/bittorrent/bittorrent/libs/mbtbe/include/mbt/be/mytorrent.h
new file mode 100644
index 0000000..e0f693e
--- /dev/null
+++ b/bittorrent/bittorrent/libs/mbtbe/include/mbt/be/mytorrent.h
@@ -0,0 +1,87 @@
+#ifndef MYTORRENT_H
+#define MYTORRENT_H
+
+#include <err.h>
+#include <mbt/be/bencode.h>
+#include <mbt/be/torrent.h>
+#include <mbt/be/torrent_files.h>
+#include <mbt/be/torrent_getters.h>
+#include <openssl/sha.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "mbt/utils/str.h"
+
+/**
+** @brief Allows to add or remove const / unsigned qualifiers of string
+**/
+union cast
+{
+ const char *cs;
+ unsigned const char *us;
+ char *s;
+};
+
+/**
+** @brief Structure of a torrent file
+**/
+struct mbt_torrent_file
+{
+ // Nombre de char du fichier
+ size_t length;
+ // NULL-terminated list de string
+ // src/node.c donne ["src","node.c",NULL]
+ struct mbt_str **path;
+};
+
+struct mbt_torrent
+{
+ struct mbt_str announce;
+ size_t creation_date;
+ struct mbt_str created_by;
+ // est un dossier ?
+ bool isDir;
+ // node
+ struct mbt_be_node *node;
+ struct info
+ {
+ struct mbt_str name;
+ size_t piece_length;
+ struct mbt_str pieces;
+ // Si isDir : Liste de fichiers, NULL-terminated
+ struct mbt_torrent_file **files;
+ // Sinon : longueur du fichier
+ size_t length;
+ } info;
+};
+
+struct strlist
+{
+ struct mbt_str *data;
+ size_t size;
+};
+
+// Create an empty torrent struct
+struct mbt_torrent *createTorrent(struct mbt_torrent *m);
+// Trouve une clef d'un dictionnaire
+struct mbt_be_node *findKey(struct mbt_be_pair **d, char *k);
+// Affiche un Node dans la console, en mode JSON
+void debugNode(struct mbt_be_node *n, size_t decal);
+// Crée une view non allouée à partir d'un string
+struct mbt_cview cmstr(char *s);
+// Deep copie un string
+struct mbt_str dc(struct mbt_str s);
+
+// Prend le texte d'un fichier (string), renvoie le hash et le nombre de char
+struct mbt_str *getShaLength(struct mbt_str mf, size_t *length);
+
+// renvoie 1 si path est un dossier
+int isdir(const char *path);
+int isfile(const char *path);
+void fullList(struct mbt_str *path, struct strlist **ls);
+
+struct strlist *strlist_init(void);
+void strlist_append(struct strlist *ls, struct mbt_str *s);
+void strlist_free(struct strlist *ls);
+
+#endif /* ! MYTORRENT_H */ \ No newline at end of file
diff --git a/bittorrent/bittorrent/libs/mbtbe/include/mbt/be/torrent.h b/bittorrent/bittorrent/libs/mbtbe/include/mbt/be/torrent.h
new file mode 100644
index 0000000..9d97ae1
--- /dev/null
+++ b/bittorrent/bittorrent/libs/mbtbe/include/mbt/be/torrent.h
@@ -0,0 +1,53 @@
+#ifndef MBT_BE_TORRENT_H
+#define MBT_BE_TORRENT_H
+
+////////////////////////////////////////////////////////////////////////////////
+/// THIS FILE WILL BE OVERWRITTEN ///
+////////////////////////////////////////////////////////////////////////////////
+
+// mbtbe
+#include <mbt/be/bencode.h>
+// mbtutils
+#include <mbt/utils/view.h>
+// libc
+#include <stdbool.h>
+
+/**
+** @brief Forward declaration of the struct that will contain all the
+** information of the torrent
+**/
+struct mbt_torrent;
+
+/**
+** @brief Parse the file at `path` and put all the information inside `torrent`
+**
+** @param path is the location of the .torrent
+** @param torrent is the output of the function, MUST BE allocated before
+**
+** @return true if success else false
+**/
+bool mbt_be_parse_torrent_file(const char *path, struct mbt_torrent *torrent)
+ MBT_NONNULL(1, 2);
+
+/**
+** @brief Create a .torrent file thanks to a file or a dir
+**
+** @param path is the path to the dir/file
+**
+** @return true if success else false
+**/
+bool mbt_be_make_torrent_file(const char *path) MBT_NONNULL(1);
+
+/**
+** @brief Initialise a mbt_torrent struct
+**
+** @return The newly allocated struct, NULL if any error occured
+**/
+struct mbt_torrent *mbt_torrent_init(void);
+
+/**
+** @brief Free the mbt_torrent struct
+**/
+void mbt_torrent_free(struct mbt_torrent *torrent);
+
+#endif /* !MBT_BE_TORRENT_H */
diff --git a/bittorrent/bittorrent/libs/mbtbe/include/mbt/be/torrent_files.h b/bittorrent/bittorrent/libs/mbtbe/include/mbt/be/torrent_files.h
new file mode 100644
index 0000000..b109a9c
--- /dev/null
+++ b/bittorrent/bittorrent/libs/mbtbe/include/mbt/be/torrent_files.h
@@ -0,0 +1,35 @@
+#ifndef MBT_BE_TORRENT_FILES_H
+#define MBT_BE_TORRENT_FILES_H
+
+////////////////////////////////////////////////////////////////////////////////
+/// THIS FILE WILL BE OVERWRITTEN ///
+////////////////////////////////////////////////////////////////////////////////
+
+// mbtutils
+#include <mbt/utils/str.h>
+
+/**
+** @brief Forward declaration of the struct that will contain all the
+** information of a file inside the field info.files
+**/
+struct mbt_torrent_file;
+
+/**
+** @brief Get the file.path[`idx`] of `file`
+**/
+struct mbt_cview mbt_torrent_file_path_get(const struct mbt_torrent_file *file,
+ size_t idx) MBT_NONNULL(1);
+
+/**
+** @brief Get the size of the path list in `file`
+**/
+size_t mbt_torrent_file_path_size(const struct mbt_torrent_file *file)
+ MBT_NONNULL(1);
+
+/**
+** @brief Get the length of the file
+**/
+size_t mbt_torrent_file_length(const struct mbt_torrent_file *file)
+ MBT_NONNULL(1);
+
+#endif // !MBT_BE_TORRENT_FILES_H
diff --git a/bittorrent/bittorrent/libs/mbtbe/include/mbt/be/torrent_getters.h b/bittorrent/bittorrent/libs/mbtbe/include/mbt/be/torrent_getters.h
new file mode 100644
index 0000000..e519733
--- /dev/null
+++ b/bittorrent/bittorrent/libs/mbtbe/include/mbt/be/torrent_getters.h
@@ -0,0 +1,88 @@
+#ifndef MBT_BE_TORRENT_GETTERS_H
+#define MBT_BE_TORRENT_GETTERS_H
+
+////////////////////////////////////////////////////////////////////////////////
+/// THIS FILE WILL BE OVERWRITTEN ///
+////////////////////////////////////////////////////////////////////////////////
+
+// mbtutils
+#include <mbt/utils/str.h>
+// libc
+#include <stdbool.h>
+
+// Forward decleration
+struct mbt_torrent;
+
+///////////////////////////////////////////////////////////////////////////
+/// This file has all the getters for the mbt_torrent struct
+///////////////////////////////////////////////////////////////////////////
+
+/**
+** @brief Get the announce field of the `torrent`
+**/
+struct mbt_cview mbt_torrent_announce(const struct mbt_torrent *torrent)
+ MBT_NONNULL(1);
+
+/**
+** @brief Get the created_by field of the `torrent`
+**/
+struct mbt_cview mbt_torrent_created_by(const struct mbt_torrent *torrent)
+ MBT_NONNULL(1);
+
+/**
+** @brief Get the creation_date field of the `torrent`
+**/
+size_t mbt_torrent_creation_date(const struct mbt_torrent *torrent)
+ MBT_NONNULL(1);
+
+/**
+** @brief Get the info.piece_length field of the `torrent`
+**/
+size_t mbt_torrent_piece_length(const struct mbt_torrent *torrent)
+ MBT_NONNULL(1);
+
+/**
+** @brief Get the info.name field of the `torrent`
+**/
+struct mbt_cview mbt_torrent_name(const struct mbt_torrent *torrent)
+ MBT_NONNULL(1);
+
+/**
+** @brief Get the info.pieces field of the `torrent`
+**/
+struct mbt_cview mbt_torrent_pieces(const struct mbt_torrent *torrent)
+ MBT_NONNULL(1);
+
+/**
+** @brief Get the info.length field of the `torrent`
+**/
+size_t mbt_torrent_length(const struct mbt_torrent *torrent) MBT_NONNULL(1);
+
+/**
+** @brief Get the info.files[`idx`] of the `torrent`
+**
+** @return NULL if idx is out of bound else the pointer to mbt_torrent_file
+**/
+const struct mbt_torrent_file *
+mbt_torrent_files_get(const struct mbt_torrent *torrent, size_t idx)
+ MBT_NONNULL(1);
+
+/**
+** @brief Get the numbers of files inside info.files field of the `torrent`
+**/
+size_t mbt_torrent_files_size(const struct mbt_torrent *torrent) MBT_NONNULL(1);
+
+/**
+** @brief Get the type of the `torrent`
+**
+** @return true if the torrent download a directory else false
+**/
+bool mbt_torrent_is_dir(const struct mbt_torrent *torrent) MBT_NONNULL(1);
+
+/**
+** @brief Get the main mbt_be_node of the `torrent`
+**/
+const struct mbt_be_node *mbt_torrent_node(const struct mbt_torrent *torrent)
+ MBT_NONNULL(1);
+
+#endif // !MBT_BE_TORRENT_GETTERS_H
diff --git a/bittorrent/bittorrent/libs/mbtbe/meson.build b/bittorrent/bittorrent/libs/mbtbe/meson.build
new file mode 100644
index 0000000..a6bba3f
--- /dev/null
+++ b/bittorrent/bittorrent/libs/mbtbe/meson.build
@@ -0,0 +1,57 @@
+project(
+ 'mbtbe', # project name
+ 'c', # project language
+ meson_version: '>= 1.1.0', # meson minimum version
+ version: '1.0.0', # project version
+ default_options: [
+ 'c_args=-D_GNU_SOURCE',
+ 'c_std=c99', # -std=c99
+ 'debug=true', # -g
+ 'optimization=0', # -O0
+ 'warning_level=2', # -Wall -Wextra
+ 'werror=true', # -Werror
+ 'b_sanitize=address,undefined', # -fsanitize=address,undefined
+ ],
+)
+
+add_project_arguments('-Wvla', language: 'c')
+# Tout les fichiers src/*.c sauf src/tests/*.c
+mbtbe_CFILES = run_command('find', 'src', '!', '-path', '*tests*', '-name', '*.c').stdout().split()
+message(mbtbe_CFILES)
+# Tout les tests src/tests/*.c
+mbtbe_TFILES = run_command('find', 'src/tests/', '-name', '*.c').stdout().split()
+message(mbtbe_TFILES)
+# Tout les includes
+mbtbe_IFILES = [include_directories('include')]
+
+mbtutils_CFILES = run_command('find', '../mbtutils/src', '!', '-path', '*tests*', '-name', '*.c').stdout().split()
+message(mbtutils_CFILES)
+
+mbtutils_IFILES = [include_directories('../mbtutils/include/')]
+
+mbtbe = shared_library(
+ 'mbtbe',
+ sources: mbtbe_CFILES + mbtutils_CFILES,
+ include_directories: mbtbe_IFILES + mbtutils_IFILES,
+ dependencies: [dependency('openssl')],
+)
+
+# test(
+# 'mbtbe_test',
+# executable(
+# 'mbtbe_test',
+# sources: mbtbe_CFILES + mbtbe_TFILES + mbtutils_CFILES,
+# include_directories: mbtbe_IFILES + mbtutils_IFILES,
+# dependencies: [dependency('criterion'), dependency('openssl')],
+# install: false,
+# ),
+# timeout: 15,
+# )
+
+test_exec = executable(
+ 'mbtbe_test',
+ sources: mbtbe_CFILES + mbtbe_TFILES + mbtutils_CFILES,
+ include_directories: mbtbe_IFILES + mbtutils_IFILES,
+ dependencies: [dependency('criterion'), dependency('openssl')],
+ install: false,
+) \ No newline at end of file
diff --git a/bittorrent/bittorrent/libs/mbtbe/src/beutils.c b/bittorrent/bittorrent/libs/mbtbe/src/beutils.c
new file mode 100644
index 0000000..22e8c3d
--- /dev/null
+++ b/bittorrent/bittorrent/libs/mbtbe/src/beutils.c
@@ -0,0 +1,107 @@
+#include <dirent.h>
+#include <openssl/sha.h>
+#include <stdio.h>
+#include <string.h>
+#include <sys/stat.h>
+
+#include "mbt/be/bencode.h"
+#include "mbt/be/mytorrent.h"
+#include "mbt/utils/str.h"
+
+// Read files content mf
+// Returns the SHA hash, and length
+struct mbt_str *getShaLength(struct mbt_str mf, size_t *length)
+{
+ struct mbt_str *hash = mbt_str_init(0);
+ size_t nbPieces = mf.capacity / 262144 + 1;
+ for (size_t i = 0; i < nbPieces; i++)
+ {
+ union cast c;
+ c.s = mf.data + i * 262144;
+
+ unsigned char buf[20];
+ size_t len = i == nbPieces - 1 ? mf.capacity % 262144 : 262144;
+
+ SHA1(c.us, len, buf);
+ for (size_t j = 0; j < 20; j++)
+ {
+ mbt_str_pushc(hash, buf[j]);
+ }
+ }
+ *length = mf.size;
+ free(mf.data);
+ return hash;
+}
+
+int isdir(const char *path)
+{
+ struct stat s;
+ stat(path, &s);
+ return S_ISDIR(s.st_mode);
+}
+
+int isfile(const char *path)
+{
+ struct stat s;
+ stat(path, &s);
+ return S_ISREG(s.st_mode);
+}
+
+struct strlist *strlist_init(void)
+{
+ struct strlist *ls = malloc(sizeof(struct strlist));
+ ls->data = NULL;
+ ls->size = 0;
+ return ls;
+}
+
+void strlist_append(struct strlist *ls, struct mbt_str *s)
+{
+ struct mbt_str s2;
+ mbt_str_ctor(&s2, 0);
+ mbt_str_pushcstr(&s2, s->data);
+ ls->size++;
+ ls->data = realloc(ls->data, ls->size * sizeof(struct mbt_str));
+ ls->data[ls->size - 1] = s2;
+}
+
+void strlist_free(struct strlist *ls)
+{
+ if (ls == NULL)
+ return;
+ for (size_t i = 0; i < ls->size; i++)
+ free(ls->data[i].data);
+ free(ls->data);
+ free(ls);
+}
+
+void fullList(struct mbt_str *path, struct strlist **ls)
+{
+ DIR *dir = opendir(path == NULL ? "." : path->data);
+ if (dir == NULL)
+ return;
+ if (ls == NULL || *ls == NULL)
+ *ls = strlist_init();
+ for (struct dirent *d = readdir(dir); d; d = readdir(dir))
+ {
+ if (!strcmp(d->d_name, ".") || !strcmp(d->d_name, ".."))
+ continue;
+ struct mbt_str *s = mbt_str_init(0);
+ if (path != NULL)
+ {
+ mbt_str_pushcstr(s, path->data);
+ }
+ mbt_str_pushcstr(s, d->d_name);
+ if (d->d_type == DT_DIR)
+ {
+ mbt_str_pushc(s, '/');
+ fullList(s, ls);
+ }
+ else
+ {
+ strlist_append(*ls, s);
+ }
+ mbt_str_free(s);
+ }
+ closedir(dir);
+} \ No newline at end of file
diff --git a/bittorrent/bittorrent/libs/mbtbe/src/decode.c b/bittorrent/bittorrent/libs/mbtbe/src/decode.c
new file mode 100644
index 0000000..875f0db
--- /dev/null
+++ b/bittorrent/bittorrent/libs/mbtbe/src/decode.c
@@ -0,0 +1,220 @@
+#include <mbt/be/bencode.h>
+#include <mbt/utils/utils.h>
+#include <mbt/utils/view.h>
+
+// libc
+#include <ctype.h>
+#include <stdlib.h>
+
+#define MBT_INT64_MAX_ULL 9223372036854775807LLU
+
+static inline bool mbt_be_consume(struct mbt_cview *buf, char expected);
+static inline bool mbt_be_parse_u64(struct mbt_cview *buf, uint64_t *val,
+ char end);
+static inline bool mbt_be_parse_i64(struct mbt_cview *buf, int64_t *val);
+static inline bool mbt_be_parse_str(struct mbt_cview *buf, struct mbt_str *str);
+static inline struct mbt_be_node *mbt_be_decode_rec(struct mbt_cview *buf);
+static inline struct mbt_be_node *mbt_be_decode_num(struct mbt_cview *buf);
+static inline struct mbt_be_node *mbt_be_decode_str(struct mbt_cview *buf);
+static inline struct mbt_be_node *mbt_be_decode_list(struct mbt_cview *buf);
+static inline struct mbt_be_node *mbt_be_decode_dict(struct mbt_cview *buf);
+
+struct mbt_be_node *mbt_be_decode(struct mbt_cview *buf)
+{
+ struct mbt_cview copy = *buf;
+ struct mbt_be_node *res = mbt_be_decode_rec(&copy);
+ if (!res)
+ return NULL;
+ *buf = copy;
+ return res;
+}
+
+static inline bool mbt_be_consume(struct mbt_cview *buf, char expected)
+{
+ if (!buf->size || *buf->data != expected)
+ return false;
+ *buf = MBT_CVIEW_SUB(*buf, 1);
+ return true;
+}
+
+static inline bool mbt_be_parse_u64(struct mbt_cview *buf, uint64_t *val,
+ char end)
+{
+ uint64_t v = 0;
+ if (!buf->size || *buf->data == end
+ || (*buf->data == '0' && (buf->size == 1 || buf->data[1] != end)))
+ return false;
+ for (; !mbt_be_consume(buf, end); *buf = MBT_CVIEW_SUB(*buf, 1))
+ {
+ if (!buf->size || !isdigit(*buf->data))
+ return false;
+ if (__builtin_mul_overflow(v, 10, &v))
+ return false;
+ unsigned char c = *buf->data - '0';
+ if (__builtin_add_overflow(v, c, &v))
+ return false;
+ }
+ *val = v;
+ return true;
+}
+
+static inline bool mbt_be_parse_i64(struct mbt_cview *buf, int64_t *val)
+{
+ bool neg = mbt_be_consume(buf, '-');
+ uint64_t v;
+ if (!mbt_be_parse_u64(buf, &v, 'e'))
+ return false;
+ if ((v == 0 && neg) || v > MBT_INT64_MAX_ULL + (neg ? 1ull : 0ull))
+ return false;
+ if (v == MBT_INT64_MAX_ULL + 1ull)
+ *val = INT64_MIN;
+ else if (neg)
+ *val = -v;
+ else
+ *val = v;
+ return true;
+}
+
+static inline bool mbt_be_parse_str(struct mbt_cview *buf, struct mbt_str *str)
+{
+ uint64_t len;
+ if (!mbt_be_parse_u64(buf, &len, ':'))
+ return false;
+
+ if (!mbt_str_pushcv(str, MBT_CVIEW(buf->data, len)))
+ return false;
+
+ *buf = MBT_CVIEW_SUB(*buf, len);
+ return true;
+}
+
+static inline struct mbt_be_node *mbt_be_decode_rec(struct mbt_cview *buf)
+{
+ if (!buf->size)
+ return NULL;
+ switch (*buf->data)
+ {
+ case 'i':
+ *buf = MBT_CVIEW_SUB(*buf, 1);
+ return mbt_be_decode_num(buf);
+ case 'd':
+ *buf = MBT_CVIEW_SUB(*buf, 1);
+ return mbt_be_decode_dict(buf);
+ case 'l':
+ *buf = MBT_CVIEW_SUB(*buf, 1);
+ return mbt_be_decode_list(buf);
+ default:
+ return mbt_be_decode_str(buf);
+ }
+}
+
+static inline struct mbt_be_node *mbt_be_decode_num(struct mbt_cview *buf)
+{
+ int64_t val;
+ if (!mbt_be_parse_i64(buf, &val))
+ return NULL;
+
+ return mbt_be_num_init(val);
+}
+
+static inline struct mbt_be_node *mbt_be_decode_str(struct mbt_cview *buf)
+{
+ struct mbt_be_node *bn = mbt_be_str_init(MBT_CVIEW(NULL, 0));
+ if (!bn)
+ return NULL;
+
+ if (!mbt_be_parse_str(buf, &bn->v.str))
+ {
+ mbt_be_free(bn);
+ return NULL;
+ }
+
+ return bn;
+}
+
+static inline struct mbt_be_node *mbt_be_decode_list(struct mbt_cview *buf)
+{
+ struct mbt_be_node *bn = mbt_be_list_init(NULL);
+ if (!bn)
+ return NULL;
+ size_t nb_elements = 0;
+ bn->v.list = calloc(1, sizeof(struct mbt_be_node *));
+ if (!bn->v.list)
+ {
+ free(bn);
+ return NULL;
+ }
+
+ for (; !mbt_be_consume(buf, 'e'); ++nb_elements)
+ {
+ struct mbt_be_node **ptr = realloc(
+ bn->v.list, (nb_elements + 2) * sizeof(struct mbt_be_node *));
+ if (!bn->v.list)
+ {
+ mbt_be_free(bn);
+ return NULL;
+ }
+ bn->v.list = ptr;
+ bn->v.list[nb_elements + 1] = NULL;
+
+ bn->v.list[nb_elements] = mbt_be_decode_rec(buf);
+ if (!bn->v.list[nb_elements])
+ {
+ mbt_be_free(bn);
+ return NULL;
+ }
+ }
+
+ bn->v.list[nb_elements] = NULL;
+ return bn;
+}
+
+static inline struct mbt_be_node *mbt_be_decode_dict(struct mbt_cview *buf)
+{
+ struct mbt_be_node *bn = mbt_be_dict_init(NULL);
+ if (!bn)
+ return NULL;
+
+ size_t nb_elements = 0;
+ bn->v.dict = calloc(1, sizeof(struct mbt_be_pair *));
+ if (!bn->v.dict)
+ {
+ free(bn);
+ return NULL;
+ }
+
+ for (; !mbt_be_consume(buf, 'e'); ++nb_elements)
+ {
+ struct mbt_be_pair **ptr = realloc(
+ bn->v.dict, (nb_elements + 2) * sizeof(struct mbt_be_pair *));
+ if (!ptr)
+ {
+ mbt_be_free(bn);
+ return NULL;
+ }
+ bn->v.dict = ptr;
+ bn->v.dict[nb_elements + 1] = NULL;
+
+ bn->v.dict[nb_elements] = calloc(1, sizeof(**ptr));
+ if (!bn->v.dict[nb_elements])
+ {
+ mbt_be_free(bn);
+ return NULL;
+ }
+
+ if (!mbt_be_parse_str(buf, &bn->v.dict[nb_elements]->key))
+ {
+ mbt_be_free(bn);
+ return NULL;
+ }
+
+ bn->v.dict[nb_elements]->val = mbt_be_decode_rec(buf);
+ if (!bn->v.dict[nb_elements]->val)
+ {
+ mbt_be_free(bn);
+ return NULL;
+ }
+ }
+
+ return bn;
+}
diff --git a/bittorrent/bittorrent/libs/mbtbe/src/encode.c b/bittorrent/bittorrent/libs/mbtbe/src/encode.c
new file mode 100644
index 0000000..190def2
--- /dev/null
+++ b/bittorrent/bittorrent/libs/mbtbe/src/encode.c
@@ -0,0 +1,56 @@
+#include <mbt/be/bencode.h>
+#include <mbt/utils/utils.h>
+#include <mbt/utils/view.h>
+
+// libc
+#include <inttypes.h>
+#include <stdio.h>
+
+static inline bool mbt_be_encode_rec(struct mbt_be_node *bn,
+ struct mbt_str *str);
+
+struct mbt_str mbt_be_encode(struct mbt_be_node *node)
+{
+ struct mbt_str str;
+ mbt_str_ctor(&str, 0);
+ if (!mbt_be_encode_rec(node, &str))
+ mbt_str_dtor(&str);
+ return str;
+}
+
+static inline bool mbt_be_encode_rec(struct mbt_be_node *bn,
+ struct mbt_str *str)
+{
+ static char buf[16] = "i";
+ switch (bn->type)
+ {
+ case MBT_BE_NUM:
+ snprintf(buf + 1, sizeof(buf) - 1, "%" PRIi64, bn->v.nb);
+ return mbt_str_pushcstr(str, buf) && mbt_str_pushc(str, 'e');
+ case MBT_BE_STR:
+ snprintf(buf + 1, sizeof(buf) - 1, "%zu", bn->v.str.size);
+ return mbt_str_pushcstr(str, buf + 1) && mbt_str_pushc(str, ':')
+ && mbt_str_pushcv(str, MBT_CVIEW_OF(bn->v.str));
+ case MBT_BE_LIST:
+ if (!mbt_str_pushc(str, 'l'))
+ return false;
+ for (size_t i = 0; bn->v.list[i]; ++i)
+ if (!mbt_be_encode_rec(bn->v.list[i], str))
+ return false;
+ return mbt_str_pushc(str, 'e');
+ case MBT_BE_DICT:
+ if (!mbt_str_pushc(str, 'd'))
+ return false;
+ for (size_t i = 0; bn->v.list[i]; ++i)
+ {
+ struct mbt_be_pair *p = bn->v.dict[i];
+ snprintf(buf + 1, sizeof(buf) - 1, "%zu", p->key.size);
+ if (!mbt_str_pushcstr(str, buf + 1) || !mbt_str_pushc(str, ':')
+ || !mbt_str_pushcv(str, MBT_CVIEW_OF(p->key))
+ || !mbt_be_encode_rec(p->val, str))
+ return false;
+ }
+ return mbt_str_pushc(str, 'e');
+ };
+ __builtin_unreachable();
+}
diff --git a/bittorrent/bittorrent/libs/mbtbe/src/mygetters.c b/bittorrent/bittorrent/libs/mbtbe/src/mygetters.c
new file mode 100644
index 0000000..529b3d1
--- /dev/null
+++ b/bittorrent/bittorrent/libs/mbtbe/src/mygetters.c
@@ -0,0 +1,61 @@
+#include <mbt/be/mytorrent.h>
+#include <stddef.h>
+#include <stdio.h>
+
+#include "mbt/utils/view.h"
+
+struct mbt_cview mbt_torrent_announce(const struct mbt_torrent *torrent)
+{
+ return MBT_CVIEW_OF(torrent->announce);
+}
+
+struct mbt_cview mbt_torrent_created_by(const struct mbt_torrent *torrent)
+{
+ return MBT_CVIEW_OF(torrent->created_by);
+}
+
+size_t mbt_torrent_creation_date(const struct mbt_torrent *torrent)
+{
+ return torrent->creation_date;
+}
+
+size_t mbt_torrent_piece_length(const struct mbt_torrent *torrent)
+{
+ return torrent->info.piece_length;
+}
+
+struct mbt_cview mbt_torrent_name(const struct mbt_torrent *torrent)
+{
+ return MBT_CVIEW_OF(torrent->info.name);
+}
+
+struct mbt_cview mbt_torrent_pieces(const struct mbt_torrent *torrent)
+{
+ return MBT_CVIEW_OF(torrent->info.pieces);
+}
+
+size_t mbt_torrent_length(const struct mbt_torrent *torrent)
+{
+ return torrent->info.length;
+}
+
+const struct mbt_torrent_file *
+mbt_torrent_files_get(const struct mbt_torrent *torrent, size_t idx)
+{
+ return torrent->info.files[idx];
+}
+
+size_t mbt_torrent_files_size(const struct mbt_torrent *torrent)
+{
+ size_t tt = 0;
+ for (size_t i = 0; torrent->info.files && torrent->info.files[i]; i++)
+ {
+ tt += 1;
+ }
+ return tt;
+}
+
+bool mbt_torrent_is_dir(const struct mbt_torrent *torrent)
+{
+ return torrent->isDir;
+} \ No newline at end of file
diff --git a/bittorrent/bittorrent/libs/mbtbe/src/mygetters2.c b/bittorrent/bittorrent/libs/mbtbe/src/mygetters2.c
new file mode 100644
index 0000000..7f58cd2
--- /dev/null
+++ b/bittorrent/bittorrent/libs/mbtbe/src/mygetters2.c
@@ -0,0 +1,10 @@
+#include <mbt/be/mytorrent.h>
+#include <stddef.h>
+#include <stdio.h>
+
+#include "mbt/utils/view.h"
+
+const struct mbt_be_node *mbt_torrent_node(const struct mbt_torrent *torrent)
+{
+ return torrent->node;
+} \ No newline at end of file
diff --git a/bittorrent/bittorrent/libs/mbtbe/src/mytfiles.c b/bittorrent/bittorrent/libs/mbtbe/src/mytfiles.c
new file mode 100644
index 0000000..b019dc9
--- /dev/null
+++ b/bittorrent/bittorrent/libs/mbtbe/src/mytfiles.c
@@ -0,0 +1,26 @@
+#include <mbt/be/mytorrent.h>
+#include <stddef.h>
+#include <stdio.h>
+
+#include "mbt/utils/view.h"
+
+struct mbt_cview mbt_torrent_file_path_get(const struct mbt_torrent_file *file,
+ size_t idx)
+{
+ return MBT_CVIEW_OF(*(file->path[idx]));
+}
+
+size_t mbt_torrent_file_path_size(const struct mbt_torrent_file *file)
+{
+ size_t tt = 0;
+ for (size_t j = 0; file->path[j]; j++)
+ {
+ tt++;
+ }
+ return tt;
+}
+
+size_t mbt_torrent_file_length(const struct mbt_torrent_file *file)
+{
+ return file->length;
+} \ No newline at end of file
diff --git a/bittorrent/bittorrent/libs/mbtbe/src/mytorrent.c b/bittorrent/bittorrent/libs/mbtbe/src/mytorrent.c
new file mode 100644
index 0000000..048cd0b
--- /dev/null
+++ b/bittorrent/bittorrent/libs/mbtbe/src/mytorrent.c
@@ -0,0 +1,113 @@
+#include <mbt/be/mytorrent.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "mbt/be/bencode.h"
+#include "mbt/utils/str.h"
+#include "mbt/utils/view.h"
+
+struct mbt_torrent *createTorrent(struct mbt_torrent *m)
+{
+ mbt_str_ctor(&(m->announce), 0);
+ m->creation_date = 0;
+ mbt_str_ctor(&(m->created_by), 0);
+ mbt_str_ctor(&(m->info.name), 0);
+ m->info.files = NULL;
+ m->info.piece_length = 0;
+ mbt_str_ctor(&(m->info.pieces), 0);
+ m->info.files = NULL;
+ m->info.length = 0;
+ m->isDir = false;
+ m->node = NULL;
+ return m;
+}
+
+struct mbt_be_node *findKey(struct mbt_be_pair **d, char *k)
+{
+ if (d == NULL || d[0] == NULL)
+ return NULL;
+ // errx(1,"Key '%s' not found",k);
+ // puts("PAIR");
+ // mbt_cview_fprint(cmstr(k), stdout);
+ // printf(" - ");
+ // mbt_cview_fprint(MBT_CVIEW_OF(d[0]->key), stdout);
+ // puts("");
+ if (!mbt_cview_cmp(cmstr(k), MBT_CVIEW_OF(d[0]->key)))
+ return d[0]->val;
+ return findKey(d + 1, k);
+}
+
+bool debugNode2(struct mbt_be_node *n, size_t decal)
+{
+ if (n->type == MBT_BE_DICT)
+ {
+ puts("{");
+ for (size_t i = 0; n->v.dict[i]; i++)
+ {
+ for (size_t k = 0; k < decal * 4; k++)
+ putchar(' ');
+ struct mbt_be_pair *p = n->v.dict[i];
+ mbt_cview_fprint(MBT_CVIEW_OF(p->key), stdout);
+ printf(":");
+ debugNode(p->val, decal + 1);
+ puts(",");
+ }
+ for (size_t k = 0; k < decal * 4; k++)
+ putchar(' ');
+ puts("}");
+ return true;
+ }
+ return false;
+}
+
+void debugNode(struct mbt_be_node *n, size_t decal)
+{
+ if (debugNode2(n, decal))
+ return;
+ if (n->type == MBT_BE_LIST)
+ {
+ for (size_t k = 0; k < decal * 4; k++)
+ putchar(' ');
+ puts("[");
+ for (size_t i = 0; n->v.list[i]; i++)
+ {
+ for (size_t k = 0; k < decal * 4; k++)
+ putchar(' ');
+ debugNode(n->v.list[i], decal + 1);
+ puts(",");
+ }
+ for (size_t k = 0; k < decal * 4; k++)
+ putchar(' ');
+ puts("]");
+ }
+ else if (n->type == MBT_BE_STR)
+ {
+ putchar('"');
+ mbt_cview_fprint(MBT_CVIEW_OF(n->v.str), stdout);
+ putchar('"');
+ }
+ else
+ printf("%ld", n->v.nb);
+}
+
+// Creates a non allocated mbt_str, with non allocated string
+struct mbt_cview cmstr(char *s)
+{
+ struct mbt_str ms;
+ ms.data = s;
+ ms.size = strlen(s);
+ ms.capacity = strlen(s);
+ return MBT_CVIEW_OF(ms);
+}
+
+// DeepCopy a string
+struct mbt_str dc(struct mbt_str s)
+{
+ struct mbt_str ms;
+ ms.data = calloc(s.size + 1, 1);
+ memcpy(ms.data, s.data, s.size);
+ ms.size = s.size;
+ ms.capacity = s.capacity;
+ return ms;
+} \ No newline at end of file
diff --git a/bittorrent/bittorrent/libs/mbtbe/src/mytorrentfile.c b/bittorrent/bittorrent/libs/mbtbe/src/mytorrentfile.c
new file mode 100644
index 0000000..ea87fce
--- /dev/null
+++ b/bittorrent/bittorrent/libs/mbtbe/src/mytorrentfile.c
@@ -0,0 +1,282 @@
+#include <dirent.h>
+#include <mbt/be/mytorrent.h>
+#include <openssl/sha.h>
+#include <pwd.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <string.h>
+#include <sys/stat.h>
+#include <unistd.h>
+
+#include "mbt/be/bencode.h"
+#include "mbt/utils/str.h"
+#include "mbt/utils/view.h"
+
+struct mbt_str readfile(FILE *f)
+{
+ if (f == NULL)
+ errx(1, "readfile de NULL");
+
+ fseek(f, 0, SEEK_END);
+ long filesize = ftell(f);
+ fseek(f, 0, SEEK_SET);
+ struct mbt_str s;
+ mbt_str_ctor(&s, filesize);
+ fread(s.data, 1, filesize, f);
+ s.size = filesize;
+ return s;
+}
+
+bool parse_files(struct mbt_be_node *fs, struct mbt_torrent *t)
+{
+ for (size_t i = 0; fs->v.list && fs->v.list[i]; i++)
+ {
+ struct mbt_be_node *li = fs->v.list[i];
+ t->info.files =
+ realloc(t->info.files, (i + 2) * sizeof(struct mbt_torrent_file *));
+ struct mbt_torrent_file **f = t->info.files;
+ f[i] = calloc(1, sizeof(struct mbt_torrent_file));
+ f[i]->length = findKey(li->v.dict, "length")->v.nb;
+ struct mbt_be_node **ls = findKey(li->v.dict, "path")->v.list;
+ f[i]->path = NULL;
+ for (size_t j = 0; ls && ls[j]; j++)
+ {
+ f[i]->path =
+ realloc(f[i]->path, (j + 2) * (sizeof(struct mbt_str *)));
+ f[i]->path[j] = mbt_str_init(ls[j]->v.str.capacity);
+ mbt_str_pushcv(f[i]->path[j], MBT_CVIEW_OF(ls[j]->v.str));
+ f[i]->path[j + 1] = NULL;
+ }
+ f[i + 1] = NULL;
+ t->info.length++;
+ }
+ return true;
+}
+
+bool mbt_be_parse_torrent_file(const char *path, struct mbt_torrent *torrent)
+{
+ FILE *f = fopen(path, "r");
+ if (f == NULL)
+ return false;
+ struct mbt_str s = readfile(f);
+
+ struct mbt_cview v = MBT_CVIEW_OF(s);
+ struct mbt_be_node *m = mbt_be_decode(&v);
+ createTorrent(torrent);
+
+ torrent->announce = dc(findKey(m->v.dict, "announce")->v.str);
+ torrent->created_by = dc(findKey(m->v.dict, "created by")->v.str);
+ torrent->creation_date = findKey(m->v.dict, "creation date")->v.nb;
+ struct mbt_be_node *i = findKey(m->v.dict, "info");
+ torrent->info.name = dc(findKey(i->v.dict, "name")->v.str);
+ torrent->info.piece_length = findKey(i->v.dict, "piece length")->v.nb;
+ torrent->info.pieces = dc(findKey(i->v.dict, "pieces")->v.str);
+
+ struct mbt_be_node *fs = findKey(i->v.dict, "files");
+ if (fs)
+ {
+ torrent->isDir = true;
+ if (!parse_files(fs, torrent))
+ return false;
+ }
+ else
+ {
+ torrent->info.length = findKey(i->v.dict, "length")->v.nb;
+ }
+
+ mbt_str_dtor(&s);
+ torrent->node = m;
+ fclose(f);
+ return true;
+}
+
+void make_filecase(FILE *f, struct mbt_be_pair **pls)
+{
+ struct mbt_str mf = readfile(f);
+ struct mbt_str *hash = mbt_str_init(0);
+ size_t nbPieces = mf.capacity / 262144 + 1;
+ for (size_t i = 0; i < nbPieces; i++)
+ {
+ union cast c;
+ c.s = mf.data + i * 262144;
+
+ unsigned char buf[20];
+ size_t len = i == nbPieces - 1 ? mf.capacity % 262144 : 262144;
+
+ SHA1(c.us, len, buf);
+ for (size_t j = 0; j < 20; j++)
+ {
+ mbt_str_pushc(hash, buf[j]);
+ }
+ }
+ pls[0] = mbt_be_pair_init(cmstr("length"), mbt_be_num_init(mf.size));
+ struct mbt_be_node *pieces = mbt_be_str_init(MBT_CVIEW_OF(*hash));
+ pls[3] = mbt_be_pair_init(cmstr("pieces"), pieces);
+ free(mf.data);
+ mbt_str_free(hash);
+}
+
+void make_foldercaseloop(size_t i, struct strlist *ls,
+ struct mbt_be_node ***files, struct mbt_str *pieces)
+{
+ // files = [ {...} ... NULL ]
+ FILE *f = fopen(ls->data[i].data, "r");
+ if (!isfile(ls->data[i].data) || f == NULL)
+ return;
+ *files = realloc(*files, (i + 2) * sizeof(struct mbt_be_node *));
+ (*files)[i + 1] = NULL;
+
+ struct mbt_be_node **fPathLs = calloc(sizeof(struct mbt_be_node *), 1);
+ char *t = strtok(ls->data[i].data, "/");
+ size_t j = 1;
+ while (t != NULL)
+ {
+ // fPaths = [ ... str NULL ]
+ fPathLs = realloc(fPathLs, ++j * sizeof(struct mbt_be_node *));
+ fPathLs[j - 2] = mbt_be_str_init(cmstr(t));
+ fPathLs[j - 1] = NULL;
+ t = strtok(NULL, "/");
+ }
+ struct mbt_be_node *paths = mbt_be_list_init(fPathLs);
+
+ size_t l;
+ struct mbt_str *sha = getShaLength(readfile(f), &l);
+ fclose(f);
+ for (size_t k = 0; k < sha->size; k++)
+ mbt_str_pushc(pieces, sha->data[k]);
+ mbt_str_free(sha);
+
+ struct mbt_be_pair **dict = calloc(sizeof(struct mbt_be_node *), 3);
+ dict[0] = mbt_be_pair_init(cmstr("length"), mbt_be_num_init(l));
+ dict[1] = mbt_be_pair_init(cmstr("path"), paths);
+ dict[2] = NULL;
+ (*files)[i] = mbt_be_dict_init(dict);
+}
+
+void make_foldercase(const char *path, struct mbt_be_pair **pls)
+{
+ char cwd[1024] = { 0 };
+ getcwd(cwd, 1024);
+ chdir(path);
+ // On parcours le path
+ struct strlist *ls = NULL;
+ fullList(NULL, &ls);
+ // files = [ NULL ]
+ struct mbt_be_node **files = calloc(sizeof(struct mbt_be_node *), 1);
+ struct mbt_str *pieces = mbt_str_init(0);
+ for (size_t i = 0; i < ls->size; i++)
+ {
+ make_foldercaseloop(i, ls, &files, pieces);
+ }
+ pls[0] = mbt_be_pair_init(cmstr("files"), mbt_be_list_init(files));
+ pls[3] = mbt_be_pair_init(cmstr("pieces"),
+ mbt_be_str_init(MBT_CVIEW_OF(*pieces)));
+ mbt_str_free(pieces);
+ chdir(cwd);
+ strlist_free(ls);
+}
+
+bool mbt_be_make_torrent_file2(const char *path, struct mbt_be_pair **pls,
+ struct mbt_be_pair **pl, union cast ca)
+{
+ if (!isdir(path))
+ {
+ FILE *f = fopen(path, "r");
+ make_filecase(f, pls);
+ fclose(f);
+ }
+ else // f == NULL
+ make_foldercase(path, pls);
+
+ struct mbt_be_node *info = mbt_be_dict_init(pls);
+ pl[3] = mbt_be_pair_init(cmstr("info"), info);
+ struct mbt_be_node *d = mbt_be_dict_init(pl);
+
+ struct mbt_str s = mbt_be_encode(d);
+ struct mbt_str *filename = mbt_str_init(0);
+ mbt_str_pushcstr(filename, ca.s);
+ mbt_str_pushcstr(filename, ".torrent");
+ FILE *f2 = fopen(filename->data, "w+");
+ // printf("I will write in f2 : '%s'\n",filename->data);
+ mbt_be_free(d);
+ mbt_str_free(filename);
+ if (f2 == NULL)
+ {
+ perror("jpeux pas f2 wesh");
+ free(s.data);
+ return false;
+ }
+ for (size_t i = 0; i < s.size; i++)
+ putc(s.data[i], f2);
+ free(s.data);
+ fclose(f2);
+ return true;
+}
+
+bool mbt_be_make_torrent_file(const char *path)
+{
+ struct stat st;
+ if (stat(path, &st) == -1)
+ return false;
+ struct mbt_be_node *announce =
+ mbt_be_str_init(cmstr("http://localhost:6969/announce"));
+ struct mbt_be_node *created_by =
+ mbt_be_str_init(cmstr(getpwuid(st.st_uid)->pw_name));
+ struct mbt_be_node *cd = mbt_be_num_init(st.st_mtim.tv_sec);
+
+ union cast ca;
+ ca.s = strrchr(path, '/');
+ if (ca.s == NULL)
+ ca.cs = path;
+ else
+ ca.cs = ca.cs + 1;
+ struct mbt_be_node *iname = mbt_be_str_init(cmstr(ca.s));
+ struct mbt_be_node *ipl = mbt_be_num_init(262144);
+
+ struct mbt_be_pair **pls = malloc(5 * sizeof(struct mbt_be_pair *));
+ pls[1] = mbt_be_pair_init(cmstr("name"), iname);
+ pls[2] = mbt_be_pair_init(cmstr("piece length"), ipl);
+ pls[4] = NULL;
+
+ struct mbt_be_pair **pl = malloc(5 * sizeof(struct mbt_be_pair *));
+ pl[0] = mbt_be_pair_init(cmstr("announce"), announce);
+ pl[1] = mbt_be_pair_init(cmstr("created by"), created_by);
+ pl[2] = mbt_be_pair_init(cmstr("creation date"), cd);
+ pl[4] = NULL;
+
+ return mbt_be_make_torrent_file2(path, pls, pl, ca);
+}
+
+struct mbt_torrent *mbt_torrent_init(void)
+{
+ struct mbt_torrent *m = calloc(sizeof(struct mbt_torrent), 1);
+ if (m == NULL)
+ return NULL;
+ return m;
+}
+
+void mbt_torrent_free(struct mbt_torrent *torrent)
+{
+ mbt_str_dtor(&(torrent->announce));
+ mbt_str_dtor(&(torrent->created_by));
+ mbt_str_dtor(&(torrent->info.name));
+ mbt_str_dtor(&(torrent->info.pieces));
+ if (torrent->info.files != NULL)
+ {
+ for (size_t i = 0; torrent->info.files[i]; i++)
+ {
+ struct mbt_torrent_file *f = torrent->info.files[i];
+ for (size_t j = 0; f->path[j]; j++)
+ {
+ free(f->path[j]->data);
+ free(f->path[j]);
+ }
+ free(f->path);
+ free(f);
+ }
+ free(torrent->info.files);
+ }
+ if (torrent->node)
+ mbt_be_free(torrent->node);
+ free(torrent);
+}
diff --git a/bittorrent/bittorrent/libs/mbtbe/src/node.c b/bittorrent/bittorrent/libs/mbtbe/src/node.c
new file mode 100644
index 0000000..1a6aeec
--- /dev/null
+++ b/bittorrent/bittorrent/libs/mbtbe/src/node.c
@@ -0,0 +1,93 @@
+#include <mbt/be/bencode.h>
+#include <mbt/utils/utils.h>
+#include <mbt/utils/view.h>
+
+// libc
+#include <stdlib.h>
+
+static inline struct mbt_be_node *mbt_be_init(enum mbt_be_type type);
+
+struct mbt_be_node *mbt_be_dict_init(struct mbt_be_pair **d)
+{
+ struct mbt_be_node *bn = mbt_be_init(MBT_BE_DICT);
+ if (bn)
+ bn->v.dict = d;
+ return bn;
+}
+
+struct mbt_be_node *mbt_be_str_init(struct mbt_cview v)
+{
+ struct mbt_be_node *bn = mbt_be_init(MBT_BE_STR);
+ if (bn)
+ {
+ mbt_str_ctor(&bn->v.str, v.size);
+ mbt_str_pushcv(&bn->v.str, v);
+ }
+ return bn;
+}
+
+struct mbt_be_node *mbt_be_list_init(struct mbt_be_node **l)
+{
+ struct mbt_be_node *bn = mbt_be_init(MBT_BE_LIST);
+ if (bn)
+ bn->v.list = l;
+ return bn;
+}
+
+struct mbt_be_node *mbt_be_num_init(int64_t n)
+{
+ struct mbt_be_node *bn = mbt_be_init(MBT_BE_NUM);
+ if (bn)
+ bn->v.nb = n;
+ return bn;
+}
+
+struct mbt_be_pair *mbt_be_pair_init(struct mbt_cview key,
+ struct mbt_be_node *node)
+{
+ struct mbt_be_pair *pair = malloc(sizeof(*pair));
+ if (!pair)
+ return NULL;
+ mbt_str_ctor(&pair->key, key.size);
+ mbt_str_pushcv(&pair->key, key);
+ pair->val = node;
+ return pair;
+}
+
+void mbt_be_free(struct mbt_be_node *bn)
+{
+ if (!bn)
+ return;
+ switch (bn->type)
+ {
+ case MBT_BE_NUM:
+ break;
+ case MBT_BE_STR:
+ mbt_str_dtor(&bn->v.str);
+ break;
+ case MBT_BE_LIST:
+ for (size_t i = 0; bn->v.list[i]; ++i)
+ mbt_be_free(bn->v.list[i]);
+ free(bn->v.list);
+ break;
+ case MBT_BE_DICT:
+ for (size_t i = 0; bn->v.dict[i]; ++i)
+ {
+ mbt_str_dtor(&bn->v.dict[i]->key);
+ mbt_be_free(bn->v.dict[i]->val);
+ free(bn->v.dict[i]);
+ }
+ free(bn->v.dict);
+ break;
+ }
+ free(bn);
+}
+
+static inline struct mbt_be_node *mbt_be_init(enum mbt_be_type type)
+{
+ struct mbt_be_node *bn = calloc(1, sizeof(*bn));
+ if (!bn)
+ return NULL;
+ bn->type = type;
+ return bn;
+}
diff --git a/bittorrent/bittorrent/libs/mbtfile/include/mbt/file/file_handler.h b/bittorrent/bittorrent/libs/mbtfile/include/mbt/file/file_handler.h
new file mode 100644
index 0000000..822831e
--- /dev/null
+++ b/bittorrent/bittorrent/libs/mbtfile/include/mbt/file/file_handler.h
@@ -0,0 +1,42 @@
+#ifndef MBT_FILE_FILE_HANDLER_H
+#define MBT_FILE_FILE_HANDLER_H
+
+////////////////////////////////////////////////////////////////////////////////
+/// THIS FILE WILL BE OVERWRITTEN ///
+////////////////////////////////////////////////////////////////////////////////
+
+// mbtutils
+#include <mbt/utils/str.h>
+
+// mbtbe
+#include <mbt/be/torrent.h>
+
+// mbtfile
+#include <mbt/file/piece.h>
+
+#define MBT_BLOCK_SIZE (1 << 14)
+
+// Forward declaration
+struct mbt_file_handler;
+
+// Forward declaration
+struct mbt_file;
+
+struct mbt_file_handler *mbt_file_handler_init(struct mbt_torrent *torrent)
+ MBT_NONNULL(1);
+
+void mbt_file_handler_free(struct mbt_file_handler *fh);
+
+// getters
+size_t mbt_file_handler_get_nb_pieces(struct mbt_file_handler *fh)
+ MBT_NONNULL(1);
+struct mbt_cview mbt_file_handler_get_name(struct mbt_file_handler *fh)
+ MBT_NONNULL(1);
+size_t mbt_file_handler_get_nb_files(struct mbt_file_handler *fh)
+ MBT_NONNULL(1);
+size_t mbt_file_handler_get_total_size(struct mbt_file_handler *fh)
+ MBT_NONNULL(1);
+const char *mbt_file_handler_get_pieces_hash(struct mbt_file_handler *fh)
+ MBT_NONNULL(1);
+
+#endif /* !MBT_FILE_FILE_HANDLER_H */
diff --git a/bittorrent/bittorrent/libs/mbtfile/include/mbt/file/my_file_handler.h b/bittorrent/bittorrent/libs/mbtfile/include/mbt/file/my_file_handler.h
new file mode 100644
index 0000000..c07c2f7
--- /dev/null
+++ b/bittorrent/bittorrent/libs/mbtfile/include/mbt/file/my_file_handler.h
@@ -0,0 +1,31 @@
+#ifndef MBT_FILE_MY_FILE_HANDLER_H
+#define MBT_FILE_MY_FILE_HANDLER_H
+
+#include "file_handler.h"
+#include "my_piece.h"
+
+struct mbt_file
+{
+ size_t length;
+ struct mbt_str *path;
+};
+
+struct mbt_file_handler
+{
+ // Nom du torrent - free
+ struct mbt_str *torrent_name;
+ // Nombre de files
+ size_t nb_files;
+ // Array de mbt_file (NULL terminated) - deep free + free
+ struct mbt_file *files;
+ // Piece length
+ size_t piece_length;
+ // Array de pieces, free
+ struct mbt_piece **pieces;
+ // Pieces hash
+ const char *p_hash;
+ // Size totale du telechargement
+ size_t size;
+};
+
+#endif // !MBT_FILE_MY_FILE_HANDLER_H
diff --git a/bittorrent/bittorrent/libs/mbtfile/include/mbt/file/my_piece.h b/bittorrent/bittorrent/libs/mbtfile/include/mbt/file/my_piece.h
new file mode 100644
index 0000000..186cc3c
--- /dev/null
+++ b/bittorrent/bittorrent/libs/mbtfile/include/mbt/file/my_piece.h
@@ -0,0 +1,26 @@
+#ifndef MY_FILE_HANDLER
+#define MY_FILE_HANDLER
+
+#include "mbt/file/piece.h"
+#include "my_file_handler.h"
+
+#define BLOCK_SIZE 16384
+
+struct block
+{
+ // Index dans la data
+ size_t index;
+ bool received;
+ struct block *next;
+};
+
+struct mbt_piece
+{
+ // Donnée de tous les blocks, free
+ char *data;
+ // Linked list de blocks, reçus ou pas, free
+ struct block *blocks;
+ size_t nb_blocks;
+ enum mbt_piece_status status;
+};
+#endif // !MY_FILE_HANDLER
diff --git a/bittorrent/bittorrent/libs/mbtfile/include/mbt/file/piece.h b/bittorrent/bittorrent/libs/mbtfile/include/mbt/file/piece.h
new file mode 100644
index 0000000..4c132e7
--- /dev/null
+++ b/bittorrent/bittorrent/libs/mbtfile/include/mbt/file/piece.h
@@ -0,0 +1,55 @@
+#ifndef MBT_FILE_PIECE_H
+#define MBT_FILE_PIECE_H
+
+////////////////////////////////////////////////////////////////////////////////
+/// THIS FILE WILL BE OVERWRITTEN ///
+////////////////////////////////////////////////////////////////////////////////
+
+// mbtutils
+#include <mbt/utils/str.h>
+
+// libc
+#include <stdbool.h>
+#include <stddef.h>
+
+struct mbt_file_handler;
+
+struct mbt_piece;
+
+// Enum for pieces status
+enum mbt_piece_status
+{
+ MBT_PIECE_VALID,
+ MBT_PIECE_DOWNLOADING,
+ MBT_PIECE_INVALID,
+};
+
+void mbt_piece_dtor(struct mbt_piece *p);
+
+size_t mbt_piece_get_nb_blocks(struct mbt_file_handler *fh, size_t piece_index)
+ MBT_NONNULL(1);
+
+const char *mbt_piece_get_data(struct mbt_file_handler *fh, size_t piece_index)
+ MBT_NONNULL(1);
+
+void mbt_piece_set_data(struct mbt_file_handler *fh, size_t piece_index,
+ const char *data, size_t size) MBT_NONNULL(1, 3);
+
+bool mbt_piece_block_is_received(struct mbt_file_handler *fh,
+ size_t piece_index, size_t block_index)
+ MBT_NONNULL(1);
+
+void mbt_piece_block_set_received(struct mbt_file_handler *fh,
+ size_t piece_index, size_t block_index,
+ bool received) MBT_NONNULL(1);
+
+bool mbt_compare_hashes(struct mbt_file_handler *fh, size_t piece_index,
+ const char *received_data) MBT_NONNULL(1);
+
+enum mbt_piece_status mbt_piece_check(struct mbt_file_handler *fh,
+ size_t piece_index) MBT_NONNULL(1);
+
+bool mbt_piece_write(struct mbt_file_handler *fh, size_t piece_index)
+ MBT_NONNULL(1);
+
+#endif /* ! MBT_FILE_PIECE_H */
diff --git a/bittorrent/bittorrent/libs/mbtfile/meson.build b/bittorrent/bittorrent/libs/mbtfile/meson.build
new file mode 100644
index 0000000..db4728b
--- /dev/null
+++ b/bittorrent/bittorrent/libs/mbtfile/meson.build
@@ -0,0 +1,51 @@
+project(
+ 'mbtfile', # project name
+ 'c', # project language
+ meson_version: '>= 1.1.0', # meson minimum version
+ version: '1.0.0', # project version
+ default_options: [
+ 'c_args=-D_GNU_SOURCE',
+ 'c_std=c99', # -std=c99
+ 'debug=true', # -g
+ 'optimization=0', # -O0
+ 'warning_level=2', # -Wall -Wextra
+ 'werror=true', # -Werror
+ 'b_sanitize=address,undefined', # -fsanitize=address,undefined
+ ],
+)
+
+add_project_arguments('-Wvla', language: 'c')
+# Tout les fichiers src/*.c sauf src/tests/*.c
+mbtfile_CFILES = run_command('find', 'src', '-not', '-path', '*tests*', '-name', '*.c').stdout().split()
+# Tout les tests src/tests/*.c
+mbtfile_TFILES = run_command('find', 'src/tests/', '-name', '*.c').stdout().split()
+# Tout les includes
+mbtfile_IFILES = [include_directories('include')]
+
+mbtutils_CFILES = run_command('find', '../mbtutils/src', '-not', '-path', '*tests*', '-name', '*.c').stdout().split()
+
+mbtutils_IFILES = [include_directories('../mbtutils/include/')]
+
+mbtbe_CFILES = run_command('find', '../mbtbe/src', '-not', '-path', '*tests*', '-name', '*.c').stdout().split()
+
+mbtbe_IFILES = [include_directories('../mbtbe/include/')]
+
+mbtfile = shared_library(
+ 'mbtfile',
+ sources: mbtbe_CFILES + mbtutils_CFILES + mbtfile_CFILES,
+ include_directories: mbtbe_IFILES + mbtutils_IFILES + mbtfile_IFILES,
+ dependencies: [dependency('libcurl'), dependency('openssl')],
+ install: true,
+)
+
+test(
+ 'mbtfile_test',
+ executable(
+ 'mbtfile_test',
+ sources: mbtbe_CFILES + mbtutils_CFILES + mbtfile_CFILES + mbtfile_TFILES,
+ include_directories: mbtbe_IFILES + mbtutils_IFILES + mbtfile_IFILES,
+ dependencies: [dependency('criterion'), dependency('libcurl'), dependency('openssl')],
+ install: false,
+ ),
+ timeout: 100,
+) \ No newline at end of file
diff --git a/bittorrent/bittorrent/libs/mbtfile/src/mbt_file_handler.c b/bittorrent/bittorrent/libs/mbtfile/src/mbt_file_handler.c
new file mode 100644
index 0000000..e26a6f1
--- /dev/null
+++ b/bittorrent/bittorrent/libs/mbtfile/src/mbt_file_handler.c
@@ -0,0 +1,119 @@
+#include "mbt/be/mytorrent.h"
+#include "mbt/file/my_file_handler.h"
+
+struct mbt_str *getFullPath(struct mbt_torrent_file *file);
+
+struct mbt_file *fetch_files(struct mbt_torrent *t, size_t nb_files)
+{
+ struct mbt_file *paths = malloc(nb_files * sizeof(struct mbt_file));
+ for (size_t i = 0; i < nb_files; i++)
+ {
+ struct mbt_torrent_file *f =
+ (struct mbt_torrent_file *)mbt_torrent_files_get(t, i);
+ paths[i].length = mbt_torrent_file_length(f);
+ paths[i].path = getFullPath(f);
+ }
+ return paths;
+}
+
+// returns an allocated string for the path of file
+// eg : file.path = [ "src","test.c",NULL ] gives "src/test.c"
+
+struct mbt_str *getFullPath(struct mbt_torrent_file *file)
+{
+ struct mbt_str *s = mbt_str_init(0);
+ size_t l = mbt_torrent_file_path_size(file);
+ for (size_t i = 0; i < l; i++)
+ {
+ if (i != 0)
+ mbt_str_pushc(s, '/');
+ mbt_str_pushcstr(s, mbt_torrent_file_path_get(file, i).data);
+ }
+ return s;
+}
+
+struct mbt_file_handler *mbt_file_handler_init(struct mbt_torrent *torrent)
+{
+ struct mbt_file_handler *fh = malloc(sizeof(struct mbt_file_handler));
+ if (fh == NULL)
+ return NULL;
+ fh->torrent_name = mbt_str_init(10);
+ if (!mbt_str_pushcv(fh->torrent_name,
+ mbt_torrent_name((const struct mbt_torrent *)torrent)))
+ {
+ free(fh);
+ return NULL;
+ }
+ if (mbt_torrent_is_dir((const struct mbt_torrent *)torrent))
+ {
+ fh->size = 0;
+ fh->nb_files =
+ mbt_torrent_files_size((const struct mbt_torrent *)torrent);
+ for (size_t i = 0; i < fh->nb_files; i++)
+ {
+ const struct mbt_torrent_file *f =
+ mbt_torrent_files_get((const struct mbt_torrent *)torrent, i);
+ fh->size += mbt_torrent_file_length(f);
+ }
+ fh->files = fetch_files(torrent, fh->nb_files);
+ }
+ else
+ {
+ fh->size = mbt_torrent_length((const struct mbt_torrent *)torrent);
+ fh->nb_files = 1;
+ fh->files = malloc(sizeof(struct mbt_file));
+ fh->files->path = fh->torrent_name;
+ }
+ fh->piece_length =
+ mbt_torrent_piece_length((const struct mbt_torrent *)torrent);
+ fh->pieces = calloc((mbt_file_handler_get_nb_pieces(fh) + 1),
+ sizeof(struct mbt_piece *));
+ fh->pieces[mbt_file_handler_get_nb_pieces(fh)] = NULL;
+ fh->p_hash = mbt_torrent_pieces((const struct mbt_torrent *)torrent).data;
+ return fh;
+}
+
+struct mbt_cview mbt_file_handler_get_name(struct mbt_file_handler *fh)
+{
+ return MBT_CVIEW_OF(*(fh->torrent_name));
+}
+
+size_t mbt_file_handler_get_nb_files(struct mbt_file_handler *fh)
+{
+ return fh->nb_files;
+}
+
+size_t mbt_file_handler_get_total_size(struct mbt_file_handler *fh)
+{
+ return fh->size;
+}
+
+const char *mbt_file_handler_get_pieces_hash(struct mbt_file_handler *fh)
+{
+ return fh->p_hash;
+}
+
+size_t mbt_file_handler_get_nb_pieces(struct mbt_file_handler *fh)
+{
+ return fh->size / fh->piece_length + (fh->size % fh->piece_length != 0);
+}
+
+void mbt_file_handler_free(struct mbt_file_handler *fh)
+{
+ mbt_str_free(fh->torrent_name);
+ if (fh->nb_files > 1)
+ {
+ for (size_t i = 0; i < fh->nb_files; i++)
+ {
+ mbt_str_free(fh->files[i].path);
+ }
+ }
+ free(fh->files);
+ for (size_t i = 0; fh->pieces[i]; i++)
+ {
+ mbt_piece_dtor(fh->pieces[i]);
+ free(fh->pieces[i]);
+ }
+ free(fh->pieces);
+ free(fh);
+}
diff --git a/bittorrent/bittorrent/libs/mbtfile/src/mbt_piece.c b/bittorrent/bittorrent/libs/mbtfile/src/mbt_piece.c
new file mode 100644
index 0000000..d76db12
--- /dev/null
+++ b/bittorrent/bittorrent/libs/mbtfile/src/mbt_piece.c
@@ -0,0 +1,70 @@
+#include <string.h>
+
+#include "mbt/be/mytorrent.h"
+#include "mbt/file/my_piece.h"
+
+void mbt_piece_dtor(struct mbt_piece *p)
+{
+ free(p->data);
+ for (struct block *b = p->blocks; b;)
+ {
+ struct block *tmp = b->next;
+ free(b);
+ b = tmp;
+ }
+}
+
+size_t mbt_piece_get_nb_blocks(struct mbt_file_handler *fh, size_t piece_index)
+{
+ return fh->pieces[piece_index]->nb_blocks;
+}
+
+const char *mbt_piece_get_data(struct mbt_file_handler *fh, size_t piece_index)
+{
+ return (const char *)fh->pieces[piece_index]->data;
+}
+
+void mbt_piece_set_data(struct mbt_file_handler *fh, size_t piece_index,
+ const char *data, size_t size)
+{
+ char *buf = fh->pieces[piece_index]->data;
+ for (size_t i = 0; i < size; i++)
+ {
+ buf[i] = data[i];
+ }
+}
+
+bool mbt_piece_block_is_received(struct mbt_file_handler *fh,
+ size_t piece_index, size_t block_index)
+{
+ struct block *b = fh->pieces[piece_index]->blocks;
+ for (size_t i = 0; i < block_index; i++)
+ {
+ b = b->next;
+ }
+ return b->received;
+}
+
+void mbt_piece_block_set_received(struct mbt_file_handler *fh,
+ size_t piece_index, size_t block_index,
+ bool received)
+{
+ struct block *b = fh->pieces[piece_index]->blocks;
+ for (size_t i = 0; i < block_index; i++)
+ {
+ b = b->next;
+ }
+ b->received = received;
+}
+
+bool mbt_compare_hashes(struct mbt_file_handler *fh, size_t piece_index,
+ const char *received_data)
+{
+ unsigned char hashbuf[20];
+ const unsigned char *pdata =
+ (const unsigned char *)fh->pieces[piece_index]->data;
+ if (strcmp((char *)SHA1(pdata, fh->piece_length, hashbuf), received_data)
+ == 0)
+ return true;
+ return false;
+}
diff --git a/bittorrent/bittorrent/libs/mbtnet/include/mbt/net/context.h b/bittorrent/bittorrent/libs/mbtnet/include/mbt/net/context.h
new file mode 100644
index 0000000..dc7fe55
--- /dev/null
+++ b/bittorrent/bittorrent/libs/mbtnet/include/mbt/net/context.h
@@ -0,0 +1,29 @@
+#ifndef MBT_NET_CONTEXT_H
+#define MBT_NET_CONTEXT_H
+
+////////////////////////////////////////////////////////////////////////////////
+/// THIS FILE WILL BE OVERWRITTEN ///
+////////////////////////////////////////////////////////////////////////////////
+
+// mbtbe
+#include <mbt/be/torrent.h>
+
+// libc
+#include <arpa/inet.h>
+
+// Forward declaration
+struct mbt_net_context;
+struct mbt_peer;
+
+struct mbt_net_context *mbt_net_context_init(struct mbt_torrent *t,
+ struct in_addr ip, uint16_t port)
+ MBT_NONNULL(1);
+
+void mbt_net_context_free(struct mbt_net_context *ctx);
+
+// getter
+
+struct mbt_peer **mbt_net_context_peers(struct mbt_net_context *ctx)
+ MBT_NONNULL(1);
+
+#endif /* !MBT_NET_CONTEXT_H */
diff --git a/bittorrent/bittorrent/libs/mbtnet/include/mbt/net/leeching.h b/bittorrent/bittorrent/libs/mbtnet/include/mbt/net/leeching.h
new file mode 100644
index 0000000..f5c2d6e
--- /dev/null
+++ b/bittorrent/bittorrent/libs/mbtnet/include/mbt/net/leeching.h
@@ -0,0 +1,15 @@
+#ifndef MBT_NET_LEECHING_H
+#define MBT_NET_LEECHING_H
+
+////////////////////////////////////////////////////////////////////////////////
+/// THIS FILE WILL BE OVERWRITTEN ///
+////////////////////////////////////////////////////////////////////////////////
+
+// mbtnet
+#include <mbt/net/context.h>
+#include <mbt/net/peer_handler.h>
+#include <mbt/net/tracker.h>
+
+void mbt_leech(struct mbt_net_context *ctx);
+
+#endif // !MBT_NET_LEECHING_H
diff --git a/bittorrent/bittorrent/libs/mbtnet/include/mbt/net/peer.h b/bittorrent/bittorrent/libs/mbtnet/include/mbt/net/peer.h
new file mode 100644
index 0000000..2b6c3b1
--- /dev/null
+++ b/bittorrent/bittorrent/libs/mbtnet/include/mbt/net/peer.h
@@ -0,0 +1,16 @@
+#ifndef MBT_NET_PEER_H
+#define MBT_NET_PEER_H
+
+////////////////////////////////////////////////////////////////////////////////
+/// THIS FILE WILL BE OVERWRITTEN ///
+////////////////////////////////////////////////////////////////////////////////
+
+// mbtnet
+#include "context.h"
+
+struct mbt_peer;
+
+void mbt_peer_addr(struct mbt_peer *peer, struct sockaddr_in *addr)
+ MBT_NONNULL(1, 2);
+
+#endif // !MBT_NET_PEER_H
diff --git a/bittorrent/bittorrent/libs/mbtnet/include/mbt/net/tracker.h b/bittorrent/bittorrent/libs/mbtnet/include/mbt/net/tracker.h
new file mode 100644
index 0000000..375e0d6
--- /dev/null
+++ b/bittorrent/bittorrent/libs/mbtnet/include/mbt/net/tracker.h
@@ -0,0 +1,12 @@
+#ifndef MBT_NET_TRACKER_H
+#define MBT_NET_TRACKER_H
+
+////////////////////////////////////////////////////////////////////////////////
+/// THIS FILE WILL BE OVERWRITTEN ///
+////////////////////////////////////////////////////////////////////////////////
+
+#include <mbt/net/context.h>
+
+int mbt_net_contact_tracker(struct mbt_net_context *ctx);
+
+#endif // !MBT_NET_TRACKER_H
diff --git a/bittorrent/bittorrent/libs/mbtnet/meson.build b/bittorrent/bittorrent/libs/mbtnet/meson.build
new file mode 100644
index 0000000..a6379ac
--- /dev/null
+++ b/bittorrent/bittorrent/libs/mbtnet/meson.build
@@ -0,0 +1,59 @@
+project(
+ 'mbtnet', # project name
+ 'c', # project language
+ meson_version: '>= 1.1.0', # meson minimum version
+ version: '1.0.0', # project version
+ default_options: [
+ 'c_args=-D_GNU_SOURCE',
+ 'c_std=c99', # -std=c99
+ 'debug=true', # -g
+ 'optimization=0', # -O0
+ 'warning_level=2', # -Wall -Wextra
+ 'werror=true', # -Werror
+ 'b_sanitize=address,undefined', # -fsanitize=address,undefined
+ ],
+)
+
+add_project_arguments('-Wvla', language: 'c')
+# Tout les fichiers src/*.c sauf src/tests/*.c
+mbtnet_CFILES = run_command('find', 'src', '-not', '-path', '*tests*', '-name', '*.c').stdout().split()
+# Tout les tests src/tests/*.c
+mbtnet_TFILES = run_command('find', 'src/tests/', '-name', '*.c').stdout().split()
+# Tout les includes
+mbtnet_IFILES = [include_directories('include')]
+
+mbtutils_CFILES = run_command('find', '../mbtutils/src', '-not', '-path', '*tests*', '-name', '*.c').stdout().split()
+
+mbtutils_IFILES = [include_directories('../mbtutils/include/')]
+
+mbtbe_CFILES = run_command('find', '../mbtbe/src', '-not', '-path', '*tests*', '-name', '*.c').stdout().split()
+
+mbtbe_IFILES = [include_directories('../mbtbe/include/')]
+
+mbtfile_CFILES = run_command('find', '../mbtfile/src', '-not', '-path', '*tests*', '-name', '*.c').stdout().split()
+
+mbtfile_IFILES = [include_directories('../mbtfile/include/')]
+
+mbtnet = shared_library(
+ 'mbtnet',
+ sources: mbtbe_CFILES + mbtutils_CFILES + mbtfile_CFILES + mbtnet_CFILES,
+ include_directories: mbtbe_IFILES + mbtutils_IFILES + mbtfile_IFILES + mbtnet_IFILES,
+ dependencies: [dependency('libcurl'), dependency('openssl')],
+ install: true,
+)
+
+test(
+ 'mbtnet_test',
+ executable(
+ 'mbtnet_test',
+ sources: mbtbe_CFILES
+ + mbtutils_CFILES
+ + mbtfile_CFILES
+ + mbtnet_CFILES
+ + mbtnet_TFILES,
+ include_directories: mbtbe_IFILES + mbtutils_IFILES + mbtfile_IFILES + mbtnet_IFILES,
+ dependencies: [dependency('criterion'), dependency('libcurl'), dependency('openssl')],
+ install: false,
+ ),
+ timeout: 100,
+) \ No newline at end of file
diff --git a/bittorrent/bittorrent/libs/mbtnet/src/mbtnet.c b/bittorrent/bittorrent/libs/mbtnet/src/mbtnet.c
new file mode 100644
index 0000000..f0a5bcf
--- /dev/null
+++ b/bittorrent/bittorrent/libs/mbtnet/src/mbtnet.c
@@ -0,0 +1 @@
+#include "mbt/be/mytorrent.h"
diff --git a/bittorrent/bittorrent/libs/mbtutils/include/mbt/utils/str.h b/bittorrent/bittorrent/libs/mbtutils/include/mbt/utils/str.h
new file mode 100644
index 0000000..d40e337
--- /dev/null
+++ b/bittorrent/bittorrent/libs/mbtutils/include/mbt/utils/str.h
@@ -0,0 +1,30 @@
+#ifndef MBT_UTILS_STR_H
+#define MBT_UTILS_STR_H
+
+////////////////////////////////////////////////////////////////////////////////
+/// THIS FILE WILL BE OVERWRITTEN ///
+////////////////////////////////////////////////////////////////////////////////
+
+// mbtutils
+#include <mbt/utils/view.h>
+// libc
+#include <stdbool.h>
+
+struct mbt_str
+{
+ char *data;
+ size_t size;
+ size_t capacity;
+};
+
+bool mbt_str_ctor(struct mbt_str *str, size_t capacity) MBT_NONNULL(1);
+void mbt_str_dtor(struct mbt_str *str);
+
+struct mbt_str *mbt_str_init(size_t capacity);
+void mbt_str_free(struct mbt_str *str);
+
+bool mbt_str_pushc(struct mbt_str *str, char c) MBT_NONNULL(1);
+bool mbt_str_pushcstr(struct mbt_str *str, const char *cstr) MBT_NONNULL(1);
+bool mbt_str_pushcv(struct mbt_str *str, struct mbt_cview view) MBT_NONNULL(1);
+
+#endif /* !MBT_UTILS_STR_H */
diff --git a/bittorrent/bittorrent/libs/mbtutils/include/mbt/utils/utils.h b/bittorrent/bittorrent/libs/mbtutils/include/mbt/utils/utils.h
new file mode 100644
index 0000000..4dce96d
--- /dev/null
+++ b/bittorrent/bittorrent/libs/mbtutils/include/mbt/utils/utils.h
@@ -0,0 +1,17 @@
+#ifndef MBT_UTILS_UTILS_H
+#define MBT_UTILS_UTILS_H
+
+////////////////////////////////////////////////////////////////////////////////
+/// THIS FILE WILL BE OVERWRITTEN ///
+////////////////////////////////////////////////////////////////////////////////
+
+// see the Attributes section in the subject
+#define MBT_ATTR(...) __attribute__((__VA_ARGS__))
+#define MBT_UNUSED MBT_ATTR(unused)
+#define MBT_PACKED MBT_ATTR(packed)
+#define MBT_NONNULL(...) MBT_ATTR(nonnull(__VA_ARGS__))
+#define MBT_RET_NONNULL MBT_ATTR(returns_nonnull)
+
+#define MBT_UNREACHABLE() __builtin_unreachable()
+
+#endif /* !MBT_UTILS_UTILS_H */
diff --git a/bittorrent/bittorrent/libs/mbtutils/include/mbt/utils/view.h b/bittorrent/bittorrent/libs/mbtutils/include/mbt/utils/view.h
new file mode 100644
index 0000000..92b002b
--- /dev/null
+++ b/bittorrent/bittorrent/libs/mbtutils/include/mbt/utils/view.h
@@ -0,0 +1,88 @@
+#ifndef MBT_UTILS_VIEW_H
+#define MBT_UTILS_VIEW_H
+
+////////////////////////////////////////////////////////////////////////////////
+/// THIS FILE WILL BE OVERWRITTEN ///
+////////////////////////////////////////////////////////////////////////////////
+
+// mbtutils
+#include <mbt/utils/utils.h>
+// libc
+#include <stdbool.h>
+#include <stdio.h>
+
+struct mbt_cview
+{
+ const char *data;
+ size_t size;
+};
+
+struct mbt_view
+{
+ char *data;
+ size_t size;
+};
+
+#define MBT_VIEW(Data, Size) \
+ ((struct mbt_view){ \
+ .data = (Data), \
+ .size = (Size), \
+ })
+
+// a "View" here is just any struct with a .data and a .size
+#define MBT_VIEW_OF(View) \
+ ((struct mbt_view){ \
+ .data = (View).data, \
+ .size = (View).size, \
+ })
+
+#define MBT_VIEW_ARR(Array) \
+ ((struct mbt_view){ \
+ .data = (Array), \
+ .size = sizeof((Array)), \
+ })
+
+// a "View" here is just any struct with a .data and a .size
+#define MBT_VIEW_SUB(View, Offset) \
+ ((struct mbt_view){ \
+ .data = (View).data + (Offset), \
+ .size = (View).size - (Offset), \
+ })
+
+#define MBT_CVIEW(Data, Size) \
+ ((struct mbt_cview){ \
+ .data = (Data), \
+ .size = (Size), \
+ })
+
+// a "View" here is just any struct with a .data and a .size
+#define MBT_CVIEW_OF(View) \
+ ((struct mbt_cview){ \
+ .data = (View).data, \
+ .size = (View).size, \
+ })
+
+#define MBT_CVIEW_LIT(Lit) \
+ ((struct mbt_cview){ \
+ .data = (Lit), \
+ .size = sizeof((Lit)) - 1, \
+ })
+
+#define MBT_CVIEW_ARR(Array) \
+ ((struct mbt_cview){ \
+ .data = (Array), \
+ .size = sizeof((Array)), \
+ })
+
+// a "View" here is just any struct with a .data and a .size
+#define MBT_CVIEW_SUB(View, Offset) \
+ ((struct mbt_cview){ \
+ .data = (View).data + (Offset), \
+ .size = (View).size - (Offset), \
+ })
+
+int mbt_cview_cmp(struct mbt_cview lhs, struct mbt_cview rhs);
+bool mbt_cview_contains(struct mbt_cview view, char c);
+void mbt_cview_fprint(struct mbt_cview view, FILE *stream) MBT_NONNULL(2);
+
+#endif /* !MBT_UTILS_VIEW_H */
diff --git a/bittorrent/bittorrent/libs/mbtutils/meson.build b/bittorrent/bittorrent/libs/mbtutils/meson.build
new file mode 100644
index 0000000..1e27875
--- /dev/null
+++ b/bittorrent/bittorrent/libs/mbtutils/meson.build
@@ -0,0 +1,29 @@
+mbtutils_CFILES = run_command('find', 'src', '-not', '-path', '*tests*', '-name', '*.c').stdout().split()
+mbtutils_TFILES = run_command('find', 'src/tests/', '-name', '*.c').stdout().split()
+mbtutils_IFILES = [include_directories('include')]
+
+mbtstrlib = shared_library(
+ 'mbtstr',
+ # python c horrible
+ sources: mbtutils_CFILES,
+ include_directories: mbtutils_IFILES,
+)
+
+mbtutils_DEP = declare_dependency(
+ link_with: mbtutils_lib,
+ include_directories: mbtutils_IFILES,
+)
+
+test(
+ 'mbtutils_test',
+ executable(
+ 'mbtutils_test',
+ sources: mbtutils_CFILES + mbtutils_TFILES,
+ include_directories: mbtutils_IFILES,
+ dependencies: [dependency('criterion')],
+ install: false,
+ ),
+ timeout: 100,
+)
+
+mbtutils_DEP \ No newline at end of file
diff --git a/bittorrent/bittorrent/libs/mbtutils/src/cmp.c b/bittorrent/bittorrent/libs/mbtutils/src/cmp.c
new file mode 100644
index 0000000..aab973b
--- /dev/null
+++ b/bittorrent/bittorrent/libs/mbtutils/src/cmp.c
@@ -0,0 +1,18 @@
+#include <complex.h>
+#include <stdbool.h>
+#include <string.h>
+
+#include "mbt/utils/view.h"
+
+int mbt_cview_cmp(struct mbt_cview lhs, struct mbt_cview rhs)
+{
+ size_t min = lhs.size > rhs.size ? rhs.size : lhs.size;
+ for (size_t i = 0; i < min; i++)
+ {
+ if (lhs.data[i] != rhs.data[i])
+ return lhs.data[i] - rhs.data[i];
+ }
+ if (rhs.size == lhs.size)
+ return 0;
+ return lhs.size - rhs.size;
+}
diff --git a/bittorrent/bittorrent/libs/mbtutils/src/contains.c b/bittorrent/bittorrent/libs/mbtutils/src/contains.c
new file mode 100644
index 0000000..5bced99
--- /dev/null
+++ b/bittorrent/bittorrent/libs/mbtutils/src/contains.c
@@ -0,0 +1,15 @@
+#include <complex.h>
+#include <stdbool.h>
+#include <stdlib.h>
+
+#include "mbt/utils/view.h"
+
+bool mbt_cview_contains(struct mbt_cview view, char c)
+{
+ for (size_t i = 0; i < view.size; i++)
+ {
+ if (view.data[i] == c)
+ return true;
+ }
+ return false;
+}
diff --git a/bittorrent/bittorrent/libs/mbtutils/src/ctor.c b/bittorrent/bittorrent/libs/mbtutils/src/ctor.c
new file mode 100644
index 0000000..b28132c
--- /dev/null
+++ b/bittorrent/bittorrent/libs/mbtutils/src/ctor.c
@@ -0,0 +1,19 @@
+#include <stdbool.h>
+#include <stdlib.h>
+
+#include "mbt/utils/str.h"
+
+bool mbt_str_ctor(struct mbt_str *str, size_t capacity)
+{
+ str->size = 0;
+ str->capacity = capacity;
+ if (str->capacity == 0)
+ {
+ str->data = NULL;
+ return true;
+ }
+ str->data = calloc(capacity + 1, 1);
+ if (str->data == NULL)
+ return false;
+ return true;
+}
diff --git a/bittorrent/bittorrent/libs/mbtutils/src/dtor.c b/bittorrent/bittorrent/libs/mbtutils/src/dtor.c
new file mode 100644
index 0000000..dca4706
--- /dev/null
+++ b/bittorrent/bittorrent/libs/mbtutils/src/dtor.c
@@ -0,0 +1,15 @@
+#include <stdbool.h>
+#include <stdlib.h>
+
+#include "mbt/utils/str.h"
+
+void mbt_str_dtor(struct mbt_str *str)
+{
+ if (str->data != NULL)
+ {
+ free(str->data);
+ str->data = NULL;
+ }
+ str->size = 0;
+ str->capacity = 0;
+}
diff --git a/bittorrent/bittorrent/libs/mbtutils/src/fprint.c b/bittorrent/bittorrent/libs/mbtutils/src/fprint.c
new file mode 100644
index 0000000..2600f03
--- /dev/null
+++ b/bittorrent/bittorrent/libs/mbtutils/src/fprint.c
@@ -0,0 +1,16 @@
+#include <complex.h>
+#include <ctype.h>
+#include <stdbool.h>
+
+#include "mbt/utils/view.h"
+
+void mbt_cview_fprint(struct mbt_cview view, FILE *stream)
+{
+ for (size_t i = 0; i < view.size; i++)
+ {
+ if (isprint(view.data[i]))
+ fputc(view.data[i], stream);
+ else
+ fprintf(stream, "U+%04X", (view.data[i] + 256) % 256);
+ }
+}
diff --git a/bittorrent/bittorrent/libs/mbtutils/src/free.c b/bittorrent/bittorrent/libs/mbtutils/src/free.c
new file mode 100644
index 0000000..ae5dbea
--- /dev/null
+++ b/bittorrent/bittorrent/libs/mbtutils/src/free.c
@@ -0,0 +1,10 @@
+#include <stdbool.h>
+#include <stdlib.h>
+
+#include "mbt/utils/str.h"
+
+void mbt_str_free(struct mbt_str *str)
+{
+ mbt_str_dtor(str);
+ free(str);
+}
diff --git a/bittorrent/bittorrent/libs/mbtutils/src/init.c b/bittorrent/bittorrent/libs/mbtutils/src/init.c
new file mode 100644
index 0000000..92fe567
--- /dev/null
+++ b/bittorrent/bittorrent/libs/mbtutils/src/init.c
@@ -0,0 +1,12 @@
+#include <stdbool.h>
+#include <stdlib.h>
+
+#include "mbt/utils/str.h"
+
+struct mbt_str *mbt_str_init(size_t capacity)
+{
+ struct mbt_str *s = calloc(sizeof(struct mbt_str), 1);
+ if (!mbt_str_ctor(s, capacity))
+ return NULL;
+ return s;
+}
diff --git a/bittorrent/bittorrent/libs/mbtutils/src/pushc.c b/bittorrent/bittorrent/libs/mbtutils/src/pushc.c
new file mode 100644
index 0000000..655678f
--- /dev/null
+++ b/bittorrent/bittorrent/libs/mbtutils/src/pushc.c
@@ -0,0 +1,18 @@
+#include <stdlib.h>
+
+#include "mbt/utils/str.h"
+
+bool mbt_str_pushc(struct mbt_str *str, char c)
+{
+ str->size += 1;
+ if (str->size >= str->capacity)
+ {
+ str->capacity = str->size;
+ str->data = realloc(str->data, str->capacity + 1);
+ if (str->data == NULL)
+ return false;
+ }
+ str->data[str->size - 1] = c;
+ str->data[str->size] = 0;
+ return true;
+}
diff --git a/bittorrent/bittorrent/libs/mbtutils/src/pushcstr.c b/bittorrent/bittorrent/libs/mbtutils/src/pushcstr.c
new file mode 100644
index 0000000..4857605
--- /dev/null
+++ b/bittorrent/bittorrent/libs/mbtutils/src/pushcstr.c
@@ -0,0 +1,11 @@
+#include "mbt/utils/str.h"
+
+bool mbt_str_pushcstr(struct mbt_str *str, const char *cstr)
+{
+ if (cstr == NULL)
+ return false;
+ for (size_t i = 0; cstr[i]; i++)
+ if (!mbt_str_pushc(str, cstr[i]))
+ return false;
+ return true;
+}
diff --git a/bittorrent/bittorrent/libs/mbtutils/src/pushcv.c b/bittorrent/bittorrent/libs/mbtutils/src/pushcv.c
new file mode 100644
index 0000000..ac0fbac
--- /dev/null
+++ b/bittorrent/bittorrent/libs/mbtutils/src/pushcv.c
@@ -0,0 +1,10 @@
+#include "mbt/utils/str.h"
+#include "mbt/utils/view.h"
+
+bool mbt_str_pushcv(struct mbt_str *str, struct mbt_cview view)
+{
+ for (size_t i = 0; i < view.size; i++)
+ if (!mbt_str_pushc(str, view.data[i]))
+ return false;
+ return true;
+}
diff --git a/bittorrent/bittorrent/meson.build b/bittorrent/bittorrent/meson.build
new file mode 100644
index 0000000..4353081
--- /dev/null
+++ b/bittorrent/bittorrent/meson.build
@@ -0,0 +1,102 @@
+project(
+ 'bittorrent', # project name
+ 'c', # project language
+ meson_version: '>= 1.1.0', # meson minimum version
+ version: '1.0.0', # project version
+ default_options: [
+ 'c_args=-D_GNU_SOURCE',
+ 'c_std=c99', # -std=c99
+ 'debug=true', # -g
+ 'optimization=0', # -O0
+ 'warning_level=2', # -Wall -Wextra
+ 'werror=true', # -Werror
+ 'b_sanitize=address,undefined', # -fsanitize=address,undefined
+ ],
+)
+
+add_project_arguments('-Wvla', language: 'c')
+
+# all .c files
+mbtbe_CFILES = run_command('find', 'libs/mbtbe/src', '-name', '*.c', '-not', '-path', '*tests*').stdout().split()
+#message(mbtbe_CFILES)
+mbtfile_CFILES = run_command('find', 'libs/mbtfile/src', '-name', '*.c', '-not', '-path', '*tests*').stdout().split()
+#message(mbtfile_CFILES)
+mbtnet_CFILES = run_command('find', 'libs/mbtnet/src', '-name', '*.c', '-not', '-path', '*tests*').stdout().split()
+#message(mbtnet_CFILES)
+mbtutils_CFILES = run_command('find', 'libs/mbtutils/src', '-name', '*.c', '-not', '-path', '*tests*').stdout().split()
+#message(mbtutils_CFILES)
+src_CFILES = run_command('find', 'src', '-name', '*.c', '-not', '-path', '*tests*').stdout().split()
+#message(src_CFILES)
+
+# all includes
+mbtbe_include = [include_directories('libs/mbtbe/include')]
+mbtfile_include = [include_directories('libs/mbtfile/include')]
+mbtnet_include = [include_directories('libs/mbtnet/include')]
+mbtutils_include = [include_directories('libs/mbtutils/include')]
+
+#dependencies
+DEPS = [dependency('libcurl'), dependency('openssl')]
+
+mbtutils_dep = declare_dependency(include_directories: mbtutils_include, dependencies: DEPS)
+
+mbtbe_dep = declare_dependency(include_directories: mbtbe_include + mbtutils_include, dependencies: DEPS)
+
+mbtfile_dep = declare_dependency(
+ include_directories: mbtfile_include + mbtutils_include + mbtbe_include,
+ dependencies: DEPS,
+)
+
+mbtnet_dep = declare_dependency(
+ include_directories: mbtnet_include + mbtutils_include + mbtbe_include + mbtfile_include,
+ dependencies: DEPS,
+)
+
+mbtutils = shared_library(
+ 'mbtutils',
+ sources: mbtutils_CFILES,
+ include_directories: mbtutils_include + [include_directories('libs/mbtutils/src')],
+ dependencies: mbtutils_dep,
+ install: true,
+)
+
+mbtbe = shared_library(
+ 'mbtbe',
+ sources: mbtbe_CFILES + mbtutils_CFILES,
+ include_directories: mbtbe_include + [include_directories('libs/mbtbe/src')] + mbtutils_include,
+ dependencies: mbtbe_dep,
+ install: true,
+)
+
+mbtfile = shared_library(
+ 'mbtfile',
+ sources: mbtfile_CFILES + mbtutils_CFILES + mbtbe_CFILES,
+ include_directories: mbtfile_include
+ + [include_directories('libs/mbtfile/src')]
+ + mbtutils_include
+ + mbtbe_include,
+ dependencies: mbtfile_dep,
+ install: true,
+)
+
+mbtnet = shared_library(
+ 'mbtnet',
+ sources: mbtnet_CFILES + mbtutils_CFILES + mbtbe_CFILES + mbtfile_CFILES,
+ include_directories: mbtnet_include
+ + [include_directories('libs/mbtnet/src')]
+ + mbtutils_include
+ + mbtfile_include
+ + mbtbe_include,
+ dependencies: mbtnet_dep,
+ install: true,
+)
+
+testbe = executable(
+ 'mbt',
+ sources: mbtbe_CFILES + mbtutils_CFILES + mbtnet_CFILES + mbtfile_CFILES + src_CFILES,
+ include_directories: mbtnet_include
+ + mbtutils_include
+ + mbtfile_include
+ + mbtbe_include,
+ dependencies: mbtnet_dep,
+ install: true,
+) \ No newline at end of file
diff --git a/bittorrent/bittorrent/src/mbt.c b/bittorrent/bittorrent/src/mbt.c
new file mode 100644
index 0000000..188ec3f
--- /dev/null
+++ b/bittorrent/bittorrent/src/mbt.c
@@ -0,0 +1,10 @@
+#include <stdio.h>
+
+#include "mbt/be/mytorrent.h"
+
+int main(int argc, char *argv[])
+{
+ if (argc && argv[0])
+ return 0;
+ return 0;
+} \ No newline at end of file
diff --git a/bittorrent/epoll_server/connection.c b/bittorrent/epoll_server/connection.c
new file mode 100644
index 0000000..62560c5
--- /dev/null
+++ b/bittorrent/epoll_server/connection.c
@@ -0,0 +1,58 @@
+#include "connection.h"
+
+#include <err.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+#include "utils/xalloc.h"
+
+struct connection_t *add_client(struct connection_t *head, int client_socket)
+{
+ struct connection_t *new_connection = xmalloc(sizeof(struct connection_t));
+
+ new_connection->client_socket = client_socket;
+ new_connection->buffer = NULL;
+ new_connection->nb_read = 0;
+ new_connection->next = head;
+
+ return new_connection;
+}
+
+struct connection_t *remove_client(struct connection_t *head, int client_socket)
+{
+ if (head && head->client_socket == client_socket)
+ {
+ struct connection_t *client_connection = head->next;
+ if (close(head->client_socket) == -1)
+ err(EXIT_FAILURE, "Failed to close socket");
+ free(head->buffer);
+ free(head);
+ return client_connection;
+ }
+
+ struct connection_t *tmp = head;
+ while (tmp->next)
+ {
+ if (tmp->next->client_socket == client_socket)
+ {
+ struct connection_t *client_connection = tmp->next;
+ tmp->next = client_connection->next;
+ if (close(client_connection->client_socket) == -1)
+ err(EXIT_FAILURE, "Failed to close socket");
+ free(client_connection->buffer);
+ free(client_connection);
+ break;
+ }
+ tmp = tmp->next;
+ }
+
+ return head;
+}
+
+struct connection_t *find_client(struct connection_t *head, int client_socket)
+{
+ while (head != NULL && head->client_socket != client_socket)
+ head = head->next;
+
+ return head;
+}
diff --git a/bittorrent/epoll_server/connection.h b/bittorrent/epoll_server/connection.h
new file mode 100644
index 0000000..40e2370
--- /dev/null
+++ b/bittorrent/epoll_server/connection.h
@@ -0,0 +1,54 @@
+#ifndef CONNECTION_H
+#define CONNECTION_H
+
+#include <sys/types.h>
+
+/**
+ * \brief Contains the information about the clients (linked list)
+ */
+struct connection_t
+{
+ int client_socket; /**< socket fd of the client */
+
+ char *buffer; /**< buffer containing the data received by this client */
+
+ ssize_t nb_read; /**< number of bytes read (also size of the buffer) */
+
+ struct connection_t *next; /**< the next client */
+};
+
+/**
+ * \brief Adds a new client connection_t to the linked list
+ *
+ * \param connection: the connection_t linked list with all the clients
+ *
+ * \param client_socket: the client socket fd to add
+ *
+ * \return The connection_t linked list with the element added
+ */
+struct connection_t *add_client(struct connection_t *head, int client_socket);
+
+/**
+ * \brief Removes the client connection_t from the linked list connection
+ *
+ * \param connection: the connection_t linked list with all the clients
+ *
+ * \param client_socket: the client socket fd to remove
+ *
+ * \return The connection_t linked list with element removed
+ */
+struct connection_t *remove_client(struct connection_t *head,
+ int client_socket);
+
+/**
+ * \brief Find the connection_t element where the socket is equal to client sock
+ *
+ * \param connection: the connection_t linked list with all the clients
+ *
+ * \param client_socket: the client socket to find
+ *
+ * \return The connection_t element of the specific client
+ */
+struct connection_t *find_client(struct connection_t *head, int client_socket);
+
+#endif /* !CONNECTION_H */
diff --git a/bittorrent/epoll_server/epoll_server.c b/bittorrent/epoll_server/epoll_server.c
new file mode 100644
index 0000000..dc010e6
--- /dev/null
+++ b/bittorrent/epoll_server/epoll_server.c
@@ -0,0 +1,134 @@
+#include "epoll_server.h"
+
+#include <netdb.h>
+#include <stdlib.h>
+#include <sys/epoll.h>
+#include <sys/socket.h>
+#include <unistd.h>
+
+#include "connection.h"
+#include "string.h"
+
+int create_and_bind(struct addrinfo *addrinfo)
+{
+ for (struct addrinfo *info = addrinfo; info != NULL; info = info->ai_next)
+ {
+ int sock_fd =
+ socket(info->ai_family, info->ai_socktype, info->ai_protocol);
+ if (sock_fd != -1)
+ {
+ int feur = bind(sock_fd, info->ai_addr, info->ai_addrlen);
+ if (feur != -1)
+ {
+ return sock_fd;
+ }
+ else
+ {
+ close(sock_fd);
+ }
+ }
+ }
+ exit(1);
+}
+
+int prepare_socket(const char *ip, const char *port)
+{
+ struct addrinfo hints;
+ memset(&hints, 0, sizeof(hints));
+ struct addrinfo *addrinfo;
+ int e = getaddrinfo(ip, port, &hints, &addrinfo);
+ if (e != 0)
+ {
+ exit(1);
+ }
+ e = create_and_bind(addrinfo);
+ int e2 = listen(e, 1000);
+ freeaddrinfo(addrinfo);
+ if (e2 == -1)
+ {
+ close(e);
+ exit(1);
+ }
+ return e;
+}
+
+struct connection_t *accept_client(int epoll_instance, int server_socket,
+ struct connection_t *connection)
+{
+ int e = accept(server_socket, NULL, 0);
+ if (e == -1)
+ {
+ close(server_socket);
+ exit(1);
+ }
+ struct epoll_event tmp;
+ tmp.events = EPOLLIN;
+ tmp.data.fd = e;
+ int er = epoll_ctl(epoll_instance, EPOLL_CTL_ADD, e, &tmp);
+ if (er == -1)
+ {
+ close(server_socket);
+ close(e);
+ exit(1);
+ }
+ return add_client(connection, e);
+}
+
+int main(int argc, char **argv)
+{
+ if (argc != 3)
+ {
+ exit(1);
+ }
+ int epoll_instance = epoll_create1(0);
+ if (epoll_instance == -1)
+ {
+ exit(1);
+ }
+ int e = prepare_socket(argv[1], argv[2]);
+ struct connection_t *co = NULL;
+ struct epoll_event tmp;
+ tmp.events = EPOLLIN;
+ tmp.data.fd = e;
+ if (epoll_ctl(epoll_instance, EPOLL_CTL_ADD, e, &tmp) == -1)
+ {
+ close(e);
+ exit(1);
+ }
+ while (1)
+ {
+ struct epoll_event elist[MAX_EVENTS];
+ int info = epoll_wait(epoll_instance, elist, MAX_EVENTS, -1);
+ if (info == -1)
+ {
+ exit(1);
+ }
+ for (int i = 0; i < info; i++)
+ {
+ int fd = elist[i].data.fd;
+ if (fd == e)
+ {
+ co = accept_client(epoll_instance, e, co);
+ }
+ else
+ {
+ char buf[100] = { 0 };
+ int info1 = recv(fd, buf, 100, 0);
+ if (info1 < 1)
+ {
+ co = remove_client(co, fd);
+ close(fd);
+ }
+ else
+ {
+ struct connection_t *tmp = co;
+ while (tmp != NULL)
+ {
+ send(tmp->client_socket, buf, info1, 0);
+ tmp = tmp->next;
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/bittorrent/epoll_server/epoll_server.h b/bittorrent/epoll_server/epoll_server.h
new file mode 100644
index 0000000..ba5de4f
--- /dev/null
+++ b/bittorrent/epoll_server/epoll_server.h
@@ -0,0 +1,58 @@
+#ifndef EPOLL_SERVER_H
+#define EPOLL_SERVER_H
+
+#include <netdb.h>
+#include <sys/socket.h>
+#include <sys/types.h>
+
+#include "connection.h"
+
+/**
+ * \brief The length of the event array, must be greater than zero
+ */
+#define MAX_EVENTS 64
+
+#define DEFAULT_BUFFER_SIZE 2048
+
+/**
+ * \brief Iterate over the struct addrinfo elements to create and bind a socket
+ *
+ * \param addrinfo: struct addrinfo elements
+ *
+ * \return The created socket or exit with 1 if there is an error
+ *
+ * Try to create and connect a socket with every addrinfo element until it
+ * succeeds
+ *
+ */
+int create_and_bind(struct addrinfo *addrinfo);
+
+/**
+ * \brief Initialize the Addrinfo struct and call create_and bind() and
+ * listen(2)
+ *
+ * \param ip: IP address of the server
+ * \param port: Port of the server
+ *
+ * \return The created socket
+ *
+ * Initialize the struct addrinfo needed by create_and_bind() before calling
+ * it. When create_and_bind() returns a valid socket, set the socket to
+ * listening and return it.
+ */
+int prepare_socket(const char *ip, const char *port);
+
+/**
+ * \brief Accept a new client and add it to the connection_t struct
+ *
+ * \param epoll_instance: the epoll instance
+ * \param server_socket: listening socket
+ * \param connection: the connection linked list with all the current
+ * connections
+ *
+ * \return The connection struct with the new client added
+ */
+struct connection_t *accept_client(int epoll_instance, int server_socket,
+ struct connection_t *connection);
+
+#endif /* !EPOLL_SERVER_H */
diff --git a/bittorrent/epoll_server/meson.build b/bittorrent/epoll_server/meson.build
new file mode 100644
index 0000000..de9bba1
--- /dev/null
+++ b/bittorrent/epoll_server/meson.build
@@ -0,0 +1,32 @@
+project(
+ 'epoll_server',
+ 'c',
+ version : '1.0.0',
+ default_options : [
+ 'debug=true',
+ 'c_std=c99',
+ 'buildtype=debug',
+ 'warning_level=2',
+ 'werror=true',
+ 'b_sanitize=address,undefined',
+ 'optimization=plain',
+ ],
+)
+
+deps = []
+pubinc = []
+inc = [include_directories('./')]
+src = files(
+ 'connection.c',
+ 'epoll_server.c',
+ 'utils/xalloc.c'
+)
+
+executable(
+ 'epoll_server',
+ sources : src,
+ include_directories : pubinc + inc,
+ dependencies : deps,
+ c_args : '-D_DEFAULT_SOURCE',
+ install : true,
+)
diff --git a/bittorrent/epoll_server/utils/xalloc.c b/bittorrent/epoll_server/utils/xalloc.c
new file mode 100644
index 0000000..e4dc6b8
--- /dev/null
+++ b/bittorrent/epoll_server/utils/xalloc.c
@@ -0,0 +1,31 @@
+#include "xalloc.h"
+
+#include <err.h>
+#include <stdlib.h>
+
+void *xmalloc(size_t size)
+{
+ void *res = malloc(size);
+ if (!res)
+ err(EXIT_FAILURE, "Impossible to malloc");
+
+ return res;
+}
+
+void *xcalloc(size_t nmemb, size_t size)
+{
+ void *res = calloc(nmemb, size);
+ if (!res)
+ err(EXIT_FAILURE, "Impossible to calloc");
+
+ return res;
+}
+
+void *xrealloc(void *ptr, size_t size)
+{
+ void *res = realloc(ptr, size);
+ if (!res)
+ err(EXIT_FAILURE, "Impossible to realloc");
+
+ return res;
+}
diff --git a/bittorrent/epoll_server/utils/xalloc.h b/bittorrent/epoll_server/utils/xalloc.h
new file mode 100644
index 0000000..e7655b8
--- /dev/null
+++ b/bittorrent/epoll_server/utils/xalloc.h
@@ -0,0 +1,32 @@
+#ifndef XALLOC_H
+#define XALLOC_H
+
+#include <stddef.h>
+
+/**
+** \brief Malloc wrapper that exits on failure.
+**
+** \param size The size to malloc.
+** \return The malloc return.
+*/
+void *xmalloc(size_t size);
+
+/**
+** \brief Calloc wrapper that exits on failure.
+**
+** \param nmemb The number of elements.
+** \param size The size of an element.
+** \return The calloc return.
+*/
+void *xcalloc(size_t nmemb, size_t size);
+
+/**
+** \brief Realloc wrapper that exits on failure.
+**
+** \param ptr The mem pointer.
+** \param size The size to realloc.
+** \return The realloc return.
+*/
+void *xrealloc(void *ptr, size_t size);
+
+#endif /* !XALLOC_H */
diff --git a/bittorrent/mbtstr/include/mbtstr/str.h b/bittorrent/mbtstr/include/mbtstr/str.h
new file mode 100644
index 0000000..aaea5d6
--- /dev/null
+++ b/bittorrent/mbtstr/include/mbtstr/str.h
@@ -0,0 +1,30 @@
+#ifndef MBTSTR_STR_H
+#define MBTSTR_STR_H
+
+////////////////////////////////////////////////////////////////////////////////
+/// THIS FILE WILL BE OVERWRITTEN ///
+////////////////////////////////////////////////////////////////////////////////
+
+// mbtutils
+#include <mbtstr/view.h>
+// libc
+#include <stdbool.h>
+
+struct mbt_str
+{
+ char *data;
+ size_t size;
+ size_t capacity;
+};
+
+bool mbt_str_ctor(struct mbt_str *str, size_t capacity) MBT_NONNULL(1);
+void mbt_str_dtor(struct mbt_str *str);
+
+struct mbt_str *mbt_str_init(size_t capacity);
+void mbt_str_free(struct mbt_str *str);
+
+bool mbt_str_pushc(struct mbt_str *str, char c) MBT_NONNULL(1);
+bool mbt_str_pushcstr(struct mbt_str *str, const char *cstr) MBT_NONNULL(1);
+bool mbt_str_pushcv(struct mbt_str *str, struct mbt_cview view) MBT_NONNULL(1);
+
+#endif /* !MBTSTR_STR_H */
diff --git a/bittorrent/mbtstr/include/mbtstr/utils.h b/bittorrent/mbtstr/include/mbtstr/utils.h
new file mode 100644
index 0000000..0bcbc79
--- /dev/null
+++ b/bittorrent/mbtstr/include/mbtstr/utils.h
@@ -0,0 +1,17 @@
+#ifndef MBTSTR_UTILS_H
+#define MBTSTR_UTILS_H
+
+////////////////////////////////////////////////////////////////////////////////
+/// THIS FILE WILL BE OVERWRITTEN ///
+////////////////////////////////////////////////////////////////////////////////
+
+// see the Attributes section in the subject
+#define MBT_ATTR(...) __attribute__((__VA_ARGS__))
+#define MBT_UNUSED MBT_ATTR(unused)
+#define MBT_PACKED MBT_ATTR(packed)
+#define MBT_NONNULL(...) MBT_ATTR(nonnull(__VA_ARGS__))
+#define MBT_RET_NONNULL MBT_ATTR(returns_nonnull)
+
+#define MBT_UNREACHABLE() __builtin_unreachable()
+
+#endif /* !MBTSTR_UTILS_H */
diff --git a/bittorrent/mbtstr/include/mbtstr/view.h b/bittorrent/mbtstr/include/mbtstr/view.h
new file mode 100644
index 0000000..dd6e196
--- /dev/null
+++ b/bittorrent/mbtstr/include/mbtstr/view.h
@@ -0,0 +1,88 @@
+#ifndef MBTSTR_VIEW_H
+#define MBTSTR_VIEW_H
+
+////////////////////////////////////////////////////////////////////////////////
+/// THIS FILE WILL BE OVERWRITTEN ///
+////////////////////////////////////////////////////////////////////////////////
+
+// mbtutils
+#include <mbtstr/utils.h>
+// libc
+#include <stdbool.h>
+#include <stdio.h>
+
+struct mbt_cview
+{
+ const char *data;
+ size_t size;
+};
+
+struct mbt_view
+{
+ char *data;
+ size_t size;
+};
+
+#define MBT_VIEW(Data, Size) \
+ ((struct mbt_view){ \
+ .data = (Data), \
+ .size = (Size), \
+ })
+
+// a "View" here is just any struct with a .data and a .size
+#define MBT_VIEW_OF(View) \
+ ((struct mbt_view){ \
+ .data = (View).data, \
+ .size = (View).size, \
+ })
+
+#define MBT_VIEW_ARR(Array) \
+ ((struct mbt_view){ \
+ .data = (Array), \
+ .size = sizeof((Array)), \
+ })
+
+// a "View" here is just any struct with a .data and a .size
+#define MBT_VIEW_SUB(View, Offset) \
+ ((struct mbt_view){ \
+ .data = (View).data + (Offset), \
+ .size = (View).size - (Offset), \
+ })
+
+#define MBT_CVIEW(Data, Size) \
+ ((struct mbt_cview){ \
+ .data = (Data), \
+ .size = (Size), \
+ })
+
+// a "View" here is just any struct with a .data and a .size
+#define MBT_CVIEW_OF(View) \
+ ((struct mbt_cview){ \
+ .data = (View).data, \
+ .size = (View).size, \
+ })
+
+#define MBT_CVIEW_LIT(Lit) \
+ ((struct mbt_cview){ \
+ .data = (Lit), \
+ .size = sizeof((Lit)) - 1, \
+ })
+
+#define MBT_CVIEW_ARR(Array) \
+ ((struct mbt_cview){ \
+ .data = (Array), \
+ .size = sizeof((Array)), \
+ })
+
+// a "View" here is just any struct with a .data and a .size
+#define MBT_CVIEW_SUB(View, Offset) \
+ ((struct mbt_cview){ \
+ .data = (View).data + (Offset), \
+ .size = (View).size - (Offset), \
+ })
+
+int mbt_cview_cmp(struct mbt_cview lhs, struct mbt_cview rhs);
+bool mbt_cview_contains(struct mbt_cview view, char c);
+void mbt_cview_fprint(struct mbt_cview view, FILE *stream) MBT_NONNULL(2);
+
+#endif /* !MBTSTR_VIEW_H */
diff --git a/bittorrent/mbtstr/meson.build b/bittorrent/mbtstr/meson.build
new file mode 100644
index 0000000..4565c94
--- /dev/null
+++ b/bittorrent/mbtstr/meson.build
@@ -0,0 +1,45 @@
+project(
+ 'mbtstr', # project name
+ 'c', # project language
+ meson_version: '>= 1.1.0', # meson minimum version
+ version: '1.0.0', # project version
+ default_options: [
+ 'c_args=-D_GNU_SOURCE',
+ 'c_std=c99', # -std=c99
+ 'debug=true', # -g
+ 'optimization=0', # -O0
+ 'warning_level=3', # -Wall -Wextra -Wpedantic
+ 'werror=true', # -Werror
+ 'b_sanitize=address,undefined', # -fsanitize=address,undefined
+ ],
+)
+
+SRCFILES = run_command('find','src -name *.c').stdout().split()
+
+mbtstrlib_inc = [include_directories('include')]
+
+mbtstrlib = shared_library(
+ 'mbtstr',
+ # python c horrible
+ sources: SRCFILES,
+ include_directories: mbtstrlib_inc + [include_directories('src')],
+)
+
+mbtstrlib_dep = declare_dependency(
+ include_directories: mbtstrlib_inc,
+ link_with: mbtstrlib,
+)
+
+mbtstrexe = executable(
+ 'mbtstrexe',
+ sources: SRCFILES,
+ include_directories: [include_directories('src')],
+ dependencies: [mbtstrlib_dep],
+)
+
+
+
+
+
+
+
diff --git a/bittorrent/mbtstr/src/cmp.c b/bittorrent/mbtstr/src/cmp.c
new file mode 100644
index 0000000..58c12d8
--- /dev/null
+++ b/bittorrent/mbtstr/src/cmp.c
@@ -0,0 +1,18 @@
+#include <complex.h>
+#include <stdbool.h>
+#include <string.h>
+
+#include "mbtstr/view.h"
+
+int mbt_cview_cmp(struct mbt_cview lhs, struct mbt_cview rhs)
+{
+ size_t min = lhs.size > rhs.size ? rhs.size : lhs.size;
+ for (size_t i = 0; i < min; i++)
+ {
+ if (lhs.data[i] != rhs.data[i])
+ return lhs.data[i] - rhs.data[i];
+ }
+ if (rhs.size == lhs.size)
+ return 0;
+ return lhs.size - rhs.size;
+}
diff --git a/bittorrent/mbtstr/src/contains.c b/bittorrent/mbtstr/src/contains.c
new file mode 100644
index 0000000..b1bcafc
--- /dev/null
+++ b/bittorrent/mbtstr/src/contains.c
@@ -0,0 +1,16 @@
+#include <complex.h>
+#include <stdbool.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "mbtstr/view.h"
+
+bool mbt_cview_contains(struct mbt_cview view, char c)
+{
+ for (size_t i = 0; i < view.size; i++)
+ {
+ if (view.data[i] == c)
+ return true;
+ }
+ return false;
+}
diff --git a/bittorrent/mbtstr/src/ctor.c b/bittorrent/mbtstr/src/ctor.c
new file mode 100644
index 0000000..5354f88
--- /dev/null
+++ b/bittorrent/mbtstr/src/ctor.c
@@ -0,0 +1,19 @@
+#include <stdbool.h>
+#include <stdlib.h>
+
+#include "mbtstr/str.h"
+
+bool mbt_str_ctor(struct mbt_str *str, size_t capacity)
+{
+ str->size = 0;
+ str->capacity = capacity;
+ if (str->capacity == 0)
+ {
+ str->data = NULL;
+ return true;
+ }
+ str->data = calloc(capacity + 1, 1);
+ if (str->data == NULL)
+ return false;
+ return true;
+}
diff --git a/bittorrent/mbtstr/src/dtor.c b/bittorrent/mbtstr/src/dtor.c
new file mode 100644
index 0000000..af35c9e
--- /dev/null
+++ b/bittorrent/mbtstr/src/dtor.c
@@ -0,0 +1,15 @@
+#include <stdbool.h>
+#include <stdlib.h>
+
+#include "mbtstr/str.h"
+
+void mbt_str_dtor(struct mbt_str *str)
+{
+ if (str->data != NULL)
+ {
+ free(str->data);
+ str->data = NULL;
+ }
+ str->size = 0;
+ str->capacity = 0;
+}
diff --git a/bittorrent/mbtstr/src/fprint.c b/bittorrent/mbtstr/src/fprint.c
new file mode 100644
index 0000000..d0ee309
--- /dev/null
+++ b/bittorrent/mbtstr/src/fprint.c
@@ -0,0 +1,17 @@
+#include <complex.h>
+#include <ctype.h>
+#include <stdbool.h>
+
+#include "mbtstr/utils.h"
+#include "mbtstr/view.h"
+
+void mbt_cview_fprint(struct mbt_cview view, FILE *stream)
+{
+ for (size_t i = 0; i < view.size; i++)
+ {
+ if (isprint(view.data[i]))
+ fputc(view.data[i], stream);
+ else
+ fprintf(stream, "U+%04X", (view.data[i] + 256) % 256);
+ }
+}
diff --git a/bittorrent/mbtstr/src/free.c b/bittorrent/mbtstr/src/free.c
new file mode 100644
index 0000000..fccf803
--- /dev/null
+++ b/bittorrent/mbtstr/src/free.c
@@ -0,0 +1,11 @@
+#include <stdbool.h>
+#include <stdlib.h>
+
+#include "mbtstr/str.h"
+
+void mbt_str_free(struct mbt_str *str)
+{
+ free(str->data);
+ mbt_str_dtor(str);
+ free(str);
+}
diff --git a/bittorrent/mbtstr/src/init.c b/bittorrent/mbtstr/src/init.c
new file mode 100644
index 0000000..bf8a107
--- /dev/null
+++ b/bittorrent/mbtstr/src/init.c
@@ -0,0 +1,12 @@
+#include <stdbool.h>
+#include <stdlib.h>
+
+#include "mbtstr/str.h"
+
+struct mbt_str *mbt_str_init(size_t capacity)
+{
+ struct mbt_str *s = calloc(sizeof(struct mbt_str), 1);
+ if (!mbt_str_ctor(s, capacity))
+ return NULL;
+ return s;
+}
diff --git a/bittorrent/mbtstr/src/pushc.c b/bittorrent/mbtstr/src/pushc.c
new file mode 100644
index 0000000..d63d3d0
--- /dev/null
+++ b/bittorrent/mbtstr/src/pushc.c
@@ -0,0 +1,18 @@
+#include <stdlib.h>
+
+#include "mbtstr/str.h"
+
+bool mbt_str_pushc(struct mbt_str *str, char c)
+{
+ str->size += 1;
+ if (str->size >= str->capacity)
+ {
+ str->capacity = str->size;
+ str->data = realloc(str->data, str->capacity + 1);
+ if (str->data == NULL)
+ return false;
+ }
+ str->data[str->size - 1] = c;
+ str->data[str->size] = 0;
+ return true;
+}
diff --git a/bittorrent/mbtstr/src/pushcstr.c b/bittorrent/mbtstr/src/pushcstr.c
new file mode 100644
index 0000000..d15776e
--- /dev/null
+++ b/bittorrent/mbtstr/src/pushcstr.c
@@ -0,0 +1,11 @@
+#include "mbtstr/str.h"
+
+bool mbt_str_pushcstr(struct mbt_str *str, const char *cstr)
+{
+ if (cstr == NULL)
+ return false;
+ for (size_t i = 0; cstr[i]; i++)
+ if (!mbt_str_pushc(str, cstr[i]))
+ return false;
+ return true;
+}
diff --git a/bittorrent/mbtstr/src/pushcv.c b/bittorrent/mbtstr/src/pushcv.c
new file mode 100644
index 0000000..7f21562
--- /dev/null
+++ b/bittorrent/mbtstr/src/pushcv.c
@@ -0,0 +1,10 @@
+#include "mbtstr/str.h"
+#include "mbtstr/view.h"
+
+bool mbt_str_pushcv(struct mbt_str *str, struct mbt_cview view)
+{
+ for (size_t i = 0; i < view.size; i++)
+ if (!mbt_str_pushc(str, view.data[i]))
+ return false;
+ return true;
+}
diff --git a/bittorrent/meson.build b/bittorrent/meson.build
new file mode 100644
index 0000000..e9dfa6c
--- /dev/null
+++ b/bittorrent/meson.build
@@ -0,0 +1,15 @@
+project(
+ 'bittorrent', # project name
+ 'c', # project language
+ meson_version: '>= 1.1.0', # meson minimum version
+ version: '1.0.0', # project version
+ default_options: [
+ 'c_args=-D_GNU_SOURCE',
+ 'c_std=c99', # -std=c99
+ 'debug=true', # -g
+ 'optimization=0', # -O0
+ 'warning_level=3', # -Wall -Wextra -Wpedantic
+ 'werror=true', # -Werror
+ 'b_sanitize=address,undefined', # -fsanitize=address,undefined
+ ],
+) \ No newline at end of file