diff options
Diffstat (limited to 'bittorrent')
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(©); + 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 |
