From a6fb61ffe4cf17b2147bdc15bbc2252a12b37fb1 Mon Sep 17 00:00:00 2001 From: Samih Date: Mon, 1 Jan 2024 04:23:00 +0400 Subject: [PATCH 001/215] first commit - Initial setup of Server and Socket classes --- ver-01.1/includes/Server.hpp | 10 ++--- ver-01.1/includes/Socket.hpp | 38 ++++++++++++++++++ ver-01.1/srcs/Server.cpp | 54 +++++++++++++------------ ver-01.1/srcs/Socket.cpp | 76 ++++++++++++++++++++++++++++++++++++ 4 files changed, 147 insertions(+), 31 deletions(-) create mode 100644 ver-01.1/includes/Socket.hpp create mode 100644 ver-01.1/srcs/Socket.cpp diff --git a/ver-01.1/includes/Server.hpp b/ver-01.1/includes/Server.hpp index 7aae40d..75084d7 100644 --- a/ver-01.1/includes/Server.hpp +++ b/ver-01.1/includes/Server.hpp @@ -1,9 +1,8 @@ +#include + #ifndef SERVER_HPP #define SERVER_HPP -// group up in errors struct or enum something -#include -#define SOCKET_ERR "failed to initiate listener" // simple singleton implementation class Server @@ -18,12 +17,13 @@ class Server // this function needs to be static, as there won't be an instance of a Server // when its first created static Server &getInstance(); - void start(); // !! work on start + void start(); + static WS_CODE bind(int sockfd); ~Server(); private: int listener; - int nConn; + int status; std::vector conn; }; diff --git a/ver-01.1/includes/Socket.hpp b/ver-01.1/includes/Socket.hpp new file mode 100644 index 0000000..b11302a --- /dev/null +++ b/ver-01.1/includes/Socket.hpp @@ -0,0 +1,38 @@ +#ifndef SOCKET_HPP +#define SOCKET_HPP + +// error messages +#define SOCKET_ERR "socket failed" + +// error codes +enum WS_CODE +{ + WS_OK = 0, + WS_LISTEN_FAIL, + WS_TOTAL +}; + +// socket_descriptor type +// cant use alias +typedef int file_descriptor; + +class Socket +{ + + public: + Socket(int domain, int type, int protocol); + ~Socket(); + // member functions + WS_CODE bind(); + WS_CODE listen(int backlog); + + private: + static const int invalid_file_descriptor = -1; + file_descriptor socket_descriptor; + + // deleted but can't cause is 98 maguy + Socket(const Socket &); + Socket &operator=(const Socket &); +}; + +#endif // SOCKET_HPP diff --git a/ver-01.1/srcs/Server.cpp b/ver-01.1/srcs/Server.cpp index aebbb4d..51256b7 100644 --- a/ver-01.1/srcs/Server.cpp +++ b/ver-01.1/srcs/Server.cpp @@ -24,21 +24,8 @@ Server &Server::getInstance() Server::Server() : listener( socket(AF_INET, SOCK_STREAM, IPPROTO_TCP | SOCK_NONBLOCK)) // start the listener - , nConn(0) -{ - // On success, a file descriptor for the new socket is returned. On error, -1 is - // returned, and errno is set - if (listener == -1) - { - std::stringstream errorMessage; - errorMessage << SOCKET_ERR << ": " << strerror(errno); - throw std::runtime_error(errorMessage.str()); - } -#ifdef __DEBUG // if needed - else - std::cout << "Listener was created successfully fd[" << listener << "]\n"; -#endif // __DEBUG -} + , status(WS_OK) +{} Server::~Server() { @@ -53,21 +40,36 @@ Server &Server::operator=(const __attribute__((unused)) Server &other) return *this; } -// member functions + void Server::start() { + int backlog = 0; + int status = 0; + + // bind the socket while (true) { - // int select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, - // struct timeval *timeout); - // - // void FD_CLR(int fd, fd_set *set); - // int FD_ISSET(int fd, fd_set *set); - // void FD_SET(int fd, fd_set *set); - // void FD_ZERO(fd_set * set); + if (status) // an error has occured + { + // If a connection request arrives when the queue is full + std::stringstream errorMessage; + errorMessage << SOCKET_ERR << ": " << strerror(errno); + throw std::runtime_error(errorMessage.str()); + } + + // accept a connection on a socket + struct sockaddr_storage clientAddr; + socklen_t clientAddrSize = sizeof(clientAddr); + int clientSocket = + accept(listener, (struct sockaddr *)&clientAddr, &clientAddrSize); + if (clientSocket == -1) + { + std::stringstream errorMessage; + errorMessage << SOCKET_ERR << ": " << strerror(errno); + throw std::runtime_error(errorMessage.str()); + } - // !! work on select - // if (select(nConn, )) - std::cout << "server is live boy!" << std::endl; + // handle the connection + handleConnection(clientSocket); } } diff --git a/ver-01.1/srcs/Socket.cpp b/ver-01.1/srcs/Socket.cpp new file mode 100644 index 0000000..0a7b6dd --- /dev/null +++ b/ver-01.1/srcs/Socket.cpp @@ -0,0 +1,76 @@ +#include "Socket.hpp" +#include +#include +#include +#include +#include /* See NOTES */ +#include + +Socket::Socket(int domain, int type, int protocol) + : socket_descriptor(invalid_file_descriptor) +{ + socket_descriptor = socket(domain, type, protocol); + // On success, a file descriptor for the new socket is returned. On error, -1 is + // returned, and errno is set + if (socket_descriptor == invalid_file_descriptor) + { + std::stringstream errorMessage; + errorMessage << SOCKET_ERR << ": " << strerror(errno); + throw std::runtime_error(errorMessage.str()); + } +#ifdef __DEBUG__ // if needed + else + std::cout << "Listener was created successfully fd[" << listener << "]\n"; +#endif // __DEBUG__ +} + +Socket::~Socket() +{ + if (socket_descriptor != invalid_file_descriptor) + { + close(socket_descriptor); + socket_descriptor = invalid_file_descriptor; // invalidate the filedescriptor + } +} + + +// member functions + +/** + * Listens for a connection on a socket and marks the socket referred to by + * socket_descriptor as a passive socket. + * + * @param backlog The maximum length to which the queue of pending connections for sockfd + * may grow. + * + * @return WS_CODE The status code indicating the result of the listen operation. + * + * @throws None + * + * @note The listen operation is typically used on server sockets after the socket has + * been bound to a specific address and port using the bind function. Once the listen + * operation is successful, the server socket can accept incoming connections using the + * accept function. + */ +WS_CODE Socket::listen(int backlog) +{ + // global namespace to avoid conflict + int status = ::listen(socket_descriptor, backlog); + if (status == -1) + return WS_LISTEN_FAIL; + return WS_OK; +} + +// deleted but can't cause is 98 maguy +Socket::Socket(const Socket &other) + : socket_descriptor(0) +{ + (void)other; +} + +Socket &Socket::operator=(const Socket &other) +{ + + (void)other; + return *this; +} From c0943a782d165b5fb56765304515aa828b7c8fee Mon Sep 17 00:00:00 2001 From: Samih Date: Tue, 2 Jan 2024 05:14:01 +0400 Subject: [PATCH 002/215] feat(Socket.cpp): Add the `bind` function. - Please note that this implementation of the Socket class is still very basic. It has been done solely to ensure the server is operational. The design may undergo significant changes in the future. --- ver-01.1/includes/Socket.hpp | 9 ++++++++- ver-01.1/srcs/Socket.cpp | 14 ++++++++++++++ 2 files changed, 22 insertions(+), 1 deletion(-) diff --git a/ver-01.1/includes/Socket.hpp b/ver-01.1/includes/Socket.hpp index b11302a..90ca8da 100644 --- a/ver-01.1/includes/Socket.hpp +++ b/ver-01.1/includes/Socket.hpp @@ -1,3 +1,6 @@ +#include +#include /* superset of previous */ + #ifndef SOCKET_HPP #define SOCKET_HPP @@ -9,6 +12,7 @@ enum WS_CODE { WS_OK = 0, WS_LISTEN_FAIL, + WS_BIND_FAIL, WS_TOTAL }; @@ -16,6 +20,9 @@ enum WS_CODE // cant use alias typedef int file_descriptor; +// ports +#define PORT_HTTP 80 + class Socket { @@ -23,7 +30,7 @@ class Socket Socket(int domain, int type, int protocol); ~Socket(); // member functions - WS_CODE bind(); + WS_CODE bind(int family, int port, int address = INADDR_ANY); WS_CODE listen(int backlog); private: diff --git a/ver-01.1/srcs/Socket.cpp b/ver-01.1/srcs/Socket.cpp index 0a7b6dd..1a4f645 100644 --- a/ver-01.1/srcs/Socket.cpp +++ b/ver-01.1/srcs/Socket.cpp @@ -1,5 +1,7 @@ #include "Socket.hpp" #include +#include +#include /* superset of previous */ #include #include #include @@ -36,6 +38,18 @@ Socket::~Socket() // member functions +WS_CODE Socket::bind(int family, int port, int address) +{ + // int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen); + struct sockaddr_in addr; + addr.sin_addr.s_addr = htonl(address); + addr.sin_family = family; + addr.sin_port = port; + if (::bind(socket_descriptor, (struct sockaddr *)&addr, sizeof(addr))) + return WS_BIND_FAIL; + return WS_OK; +} + /** * Listens for a connection on a socket and marks the socket referred to by * socket_descriptor as a passive socket. From 786efcad5dc71096bc19095781394d8fc6d341b7 Mon Sep 17 00:00:00 2001 From: Samih Date: Tue, 2 Jan 2024 17:05:06 +0400 Subject: [PATCH 003/215] chore(clang-format): Add clang-format file --- ver-01.1/.clang-format | 223 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 223 insertions(+) create mode 100644 ver-01.1/.clang-format diff --git a/ver-01.1/.clang-format b/ver-01.1/.clang-format new file mode 100644 index 0000000..7e0af3d --- /dev/null +++ b/ver-01.1/.clang-format @@ -0,0 +1,223 @@ +--- +BasedOnStyle: Mozilla +AccessModifierOffset: -2 +AlignAfterOpenBracket: Align +AlignArrayOfStructures: None +AlignConsecutiveAssignments: + Enabled: false + AcrossEmptyLines: false + AcrossComments: false + AlignCompound: false + PadOperators: true +AlignConsecutiveBitFields: + Enabled: false + AcrossEmptyLines: false + AcrossComments: false + AlignCompound: false + PadOperators: false +AlignConsecutiveDeclarations: + Enabled: true + AcrossEmptyLines: false + AcrossComments: false + AlignCompound: false + PadOperators: false +AlignConsecutiveMacros: + Enabled: true + AcrossEmptyLines: false + AcrossComments: false + AlignCompound: false + PadOperators: false +AlignEscapedNewlines: Right +AlignOperands: Align +AlignTrailingComments: + Kind: Always + OverEmptyLines: 0 +AllowAllArgumentsOnNextLine: false +AllowAllParametersOfDeclarationOnNextLine: false +AllowShortBlocksOnASingleLine: Never +AllowShortCaseLabelsOnASingleLine: true +AllowShortEnumsOnASingleLine: false +AllowShortFunctionsOnASingleLine: None +AllowShortIfStatementsOnASingleLine: Never +AllowShortLambdasOnASingleLine: All +AllowShortLoopsOnASingleLine: false +AlwaysBreakAfterDefinitionReturnType: None +AlwaysBreakAfterReturnType: None +AlwaysBreakBeforeMultilineStrings: false +AlwaysBreakTemplateDeclarations: Yes +AttributeMacros: + - __capability +BinPackArguments: true +BinPackParameters: false +BitFieldColonSpacing: Both +BraceWrapping: + AfterCaseLabel: true + AfterClass: true + AfterControlStatement: Always + AfterEnum: true + AfterFunction: true + AfterNamespace: true + AfterObjCDeclaration: false + AfterStruct: true + AfterUnion: true + AfterExternBlock: true + BeforeCatch: true + BeforeElse: true + BeforeLambdaBody: false + BeforeWhile: false + IndentBraces: false + SplitEmptyFunction: false + SplitEmptyRecord: false + SplitEmptyNamespace: false +BreakAfterAttributes: Never +BreakAfterJavaFieldAnnotations: false +BreakArrays: true +BreakBeforeBinaryOperators: None +BreakBeforeBraces: Custom +BreakBeforeConceptDeclarations: Always +BreakBeforeInlineASMColon: OnlyMultiline +BreakBeforeTernaryOperators: true +BreakConstructorInitializers: BeforeComma +BreakInheritanceList: BeforeComma +BreakStringLiterals: true +ColumnLimit: 90 +CommentPragmas: "^ IWYU pragma:" +CompactNamespaces: false +ConstructorInitializerIndentWidth: 4 +ContinuationIndentWidth: 4 +Cpp11BracedListStyle: false +DerivePointerAlignment: false +DisableFormat: false +EmptyLineAfterAccessModifier: Never +EmptyLineBeforeAccessModifier: Always +ExperimentalAutoDetectBinPacking: false +FixNamespaceComments: false +ForEachMacros: + - foreach + - Q_FOREACH + - BOOST_FOREACH +IfMacros: + - KJ_IF_MAYBE +IncludeBlocks: Preserve +IncludeCategories: + - Regex: ^"(llvm|llvm-c|clang|clang-c)/ + Priority: 2 + SortPriority: 0 + CaseSensitive: false + - Regex: ^(<|"(gtest|gmock|isl|json)/) + Priority: 3 + SortPriority: 0 + CaseSensitive: false + - Regex: .* + Priority: 1 + SortPriority: 0 + CaseSensitive: false +IncludeIsMainRegex: (Test)?$ +IncludeIsMainSourceRegex: "" +IndentAccessModifiers: true +IndentCaseBlocks: false +IndentCaseLabels: true +IndentExternBlock: AfterExternBlock +IndentGotoLabels: true +IndentPPDirectives: None +IndentRequiresClause: true +IndentWidth: 4 +IndentWrappedFunctionNames: false +InsertBraces: false +InsertNewlineAtEOF: true +InsertTrailingCommas: None +IntegerLiteralSeparator: + Binary: 0 + BinaryMinDigits: 0 + Decimal: 0 + DecimalMinDigits: 0 + Hex: 0 + HexMinDigits: 0 +JavaScriptQuotes: Leave +JavaScriptWrapImports: true +KeepEmptyLinesAtTheStartOfBlocks: true +LambdaBodyIndentation: Signature +Language: Cpp +LineEnding: DeriveLF +MacroBlockBegin: "" +MacroBlockEnd: "" +MaxEmptyLinesToKeep: 2 +NamespaceIndentation: None +ObjCBinPackProtocolList: Auto +ObjCBlockIndentWidth: 2 +ObjCBreakBeforeNestedBlockParam: true +ObjCSpaceAfterProperty: true +ObjCSpaceBeforeProtocolList: false +PPIndentWidth: -1 +PackConstructorInitializers: BinPack +PenaltyBreakAssignment: 4 +PenaltyBreakBeforeFirstCallParameter: 19 +PenaltyBreakComment: 300 +PenaltyBreakFirstLessLess: 120 +PenaltyBreakOpenParenthesis: 0 +PenaltyBreakString: 1000 +PenaltyBreakTemplateDeclaration: 10 +PenaltyExcessCharacter: 1000000 +PenaltyIndentedWhitespace: 0 +PenaltyReturnTypeOnItsOwnLine: 200 +PointerAlignment: Right +QualifierAlignment: Leave +ReferenceAlignment: Pointer +ReflowComments: true +RemoveBracesLLVM: false +RemoveSemicolon: false +RequiresClausePosition: OwnLine +RequiresExpressionIndentation: OuterScope +SeparateDefinitionBlocks: Leave +ShortNamespaceLines: 1 +SortIncludes: CaseSensitive +SortJavaStaticImport: Before +SortUsingDeclarations: LexicographicNumeric +SpaceAfterCStyleCast: false +SpaceAfterLogicalNot: false +SpaceAfterTemplateKeyword: false +SpaceAroundPointerQualifiers: Default +SpaceBeforeAssignmentOperators: true +SpaceBeforeCaseColon: false +SpaceBeforeCpp11BracedList: false +SpaceBeforeCtorInitializerColon: true +SpaceBeforeInheritanceColon: true +SpaceBeforeParens: ControlStatements +SpaceBeforeParensOptions: + AfterControlStatements: true + AfterForeachMacros: true + AfterFunctionDeclarationName: false + AfterFunctionDefinitionName: false + AfterIfMacros: true + AfterOverloadedOperator: false + AfterRequiresInClause: false + AfterRequiresInExpression: false + BeforeNonEmptyParentheses: false +SpaceBeforeRangeBasedForLoopColon: true +SpaceBeforeSquareBrackets: false +SpaceInEmptyBlock: false +SpaceInEmptyParentheses: false +SpacesBeforeTrailingComments: 1 +SpacesInAngles: Never +SpacesInCStyleCastParentheses: false +SpacesInConditionalStatement: false +SpacesInContainerLiterals: true +SpacesInLineCommentPrefix: + Minimum: 1 + Maximum: -1 +SpacesInParentheses: false +SpacesInSquareBrackets: false +Standard: Latest +StatementAttributeLikeMacros: + - Q_EMIT +StatementMacros: + - Q_UNUSED + - QT_REQUIRE_VERSION +TabWidth: 4 +UseTab: Never +WhitespaceSensitiveMacros: + - BOOST_PP_STRINGIZE + - CF_SWIFT_NAME + - NS_SWIFT_NAME + - PP_STRINGIZE + - STRINGIZE From afdf09b80aaf349991136d078f64f77640f9488d Mon Sep 17 00:00:00 2001 From: Samih Date: Tue, 2 Jan 2024 22:27:48 +0400 Subject: [PATCH 004/215] chore(Socket.hpp): Add TO-DO list - To improve class design --- ver-01.1/includes/Socket.hpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/ver-01.1/includes/Socket.hpp b/ver-01.1/includes/Socket.hpp index 90ca8da..f436bff 100644 --- a/ver-01.1/includes/Socket.hpp +++ b/ver-01.1/includes/Socket.hpp @@ -1,6 +1,11 @@ #include #include /* superset of previous */ +// TODO +// [ ] error checking functions for domain, type, protocol ... etc +// [ ] custom exception class for error handling +// [ ] better error messages + #ifndef SOCKET_HPP #define SOCKET_HPP From c15685d1d2a7b9f1a39c7b3b13f9db2daea63695 Mon Sep 17 00:00:00 2001 From: Samih Date: Wed, 3 Jan 2024 00:49:47 +0400 Subject: [PATCH 005/215] build(Makefile): Refactor to compile into lib - Add Socket test target `test_socket` that links the library with SOCKET_main.cpp --- ver-01.1/Makefile | 32 +++++++++++++++++++------------- 1 file changed, 19 insertions(+), 13 deletions(-) diff --git a/ver-01.1/Makefile b/ver-01.1/Makefile index 6bc5c7f..84d92b1 100644 --- a/ver-01.1/Makefile +++ b/ver-01.1/Makefile @@ -1,45 +1,51 @@ CXX:= c++ -CXXFLAGS:= -Wall -Werror -Wextra -std=c++98 +CXXFLAGS:= -Wall -Werror -Wextra -std=c++98 +DEBUGFLAGS:= -ggdb3 -fsanitize=address -D__DEBUG__ RM:= rm -rf INCLUDES:= -I./includes -SRCS_DIR:= srcs/ -SRCS:= Server.cpp +SRCS_DIR:= srcs +SRCS:= Socket.cpp Server.cpp + +# tester mains +TEST_SOCK:= $(SRCS_DIR)/SOCKET_main.cpp OBJS_DIR:= objs OBJS:= $(SRCS:%.cpp=$(OBJS_DIR)/%.o) -NAME:= webserv +NAME:= libwebserv.a all: $(NAME) run: re ./$(NAME) -ndebug: CXXFLAGS += -DNDEBUG -ndebug: run - -debug: CXXFLAGS += -DDEBUG -ggdb3 -debug: run +debug: CXXFLAGS += $(DEBUGFLAGS) +debug: all -$(NAME): $(OBJS) - $(CXX) $(CXXFLAGS) $(INCLUDES) -o $@ $^ +$(NAME): $(OBJS) + ar rcs $(NAME) $(OBJS) -$(OBJS_DIR)/%.o: $(SRCS_DIR)%.cpp | $(OBJS_DIR) +$(OBJS_DIR)/%.o: $(SRCS_DIR)/%.cpp | $(OBJS_DIR) $(CXX) $(CXXFLAGS) $(INCLUDES) -c $^ -o $@ $(OBJS_DIR): @mkdir -p objs +# tests +test_socket: $(TEST_SOCK) debug + $(CXX) $(CXXFLAGS) $(INCLUDES) -fsanitize=address $(TEST_SOCK) $(NAME) -o $@ + clean: $(RM) $(OBJS_DIR) fclean: clean $(RM) $(NAME) + $(RM) test_socket re: fclean all -.PHONY: clean fclean all re +.PHONY: clean fclean all re test_socket From 20c6cd5c063b2d02a7a389121d026eafc4098be3 Mon Sep 17 00:00:00 2001 From: Samih Date: Wed, 3 Jan 2024 01:01:26 +0400 Subject: [PATCH 006/215] chore(.gitignore): add objs/ to .gitignore - removed /objs/Server.o from remote repo --- .gitignore | 3 ++- ver-01.1/objs/Server.o | Bin 1704 -> 0 bytes 2 files changed, 2 insertions(+), 1 deletion(-) delete mode 100644 ver-01.1/objs/Server.o diff --git a/.gitignore b/.gitignore index b6f95b6..9d4a0a3 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ -.clang-format .vscode/ +*/objs/ +*/.cache/ diff --git a/ver-01.1/objs/Server.o b/ver-01.1/objs/Server.o deleted file mode 100644 index cf5fcf4e885303156316ddd8a517f938afa66613..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1704 zcmbtUOKTHR6h4#I)0J6#6Gzx^Z7|Q{3n|Gv_upH)$7o;LJJa`_6Y?b7$T-j}|h90n!Y30E0@R z0G}oXxt*joWZ@M2nz{13;`V;Hz1REw>Tdt2+U>=AdJkdl2WP*!3yY=FJ@a~{5x1k* zv@B5+`8g|2N^7T35c%Q_hH?H$^c?yz^u^^0WB|SrCYN~ub28)Q3K&~CV>UZ|ypJ2Z zj2JoD3_YAPxp$e;>8S;5z>>K8grgnCKTT;kPf_ZZ2KrabUsU$c#G=l(YtIK!NvQ%(3)zTU&=ZD$(VHUM356iV-xrTViT8u<$bs3M zNnGx~uHh!vZ#7)*6GV5r6?qMeQJBVcnMM9q1mc+&c_13yE{JBQ)$-ejwL6h7@Y>FG zBd_^_>$P?)g0K_#VYCe*^fx@=uh*W3Ud!jn|0B@7pgT6DjbU@Wq~YpW5p@-v^z!>6 zjO=|HMxNBG+BGcb`}$Y?E!5JOd34p}{KTs!=a=y|k}_BOKC6Y2>%9(g)9CuSd|{2r zQ3l$pYE>*~OkMwtn?9<|nCto{h|&MeMpx}S4_IgL1V&n?)L&wJ+}uP3ywN@GJBg9r hk*=q4^>;^-I?umDg<|^ookeb(-ez!3(Ne1G{{r~-p`QQ% From 5e878db86207fd3f298b92a72d7bea1feaccd270 Mon Sep 17 00:00:00 2001 From: Samih Date: Wed, 3 Jan 2024 04:47:52 +0400 Subject: [PATCH 007/215] feat(Socket): Initial Socket class implementation - still a `WIP` constructors and destructors are implemented - full set of methods to be implemented --- ver-01.1/includes/Socket.hpp | 45 ++++++++++--- ver-01.1/srcs/Socket.cpp | 127 +++++++++++++++++++++++++++-------- 2 files changed, 133 insertions(+), 39 deletions(-) diff --git a/ver-01.1/includes/Socket.hpp b/ver-01.1/includes/Socket.hpp index f436bff..350fac5 100644 --- a/ver-01.1/includes/Socket.hpp +++ b/ver-01.1/includes/Socket.hpp @@ -1,16 +1,23 @@ #include #include /* superset of previous */ +#include // TODO +// [ ] split-up function implementations into their own files // [ ] error checking functions for domain, type, protocol ... etc // [ ] custom exception class for error handling // [ ] better error messages +// [ ] make a unit-tester main +// [ ] add shutdown functionality (block recv, block send, close()) #ifndef SOCKET_HPP #define SOCKET_HPP // error messages -#define SOCKET_ERR "socket failed" +#define ERR_NULL_MSG "Null ptr!!" // make more verbose +#define ERR_STRT_MSG "Socket creation failed" +#define ERR_BIND_MSG "Socket binding failed" +#define ERR_LIST_MSG "Socket binding failed" // error codes enum WS_CODE @@ -22,29 +29,45 @@ enum WS_CODE }; // socket_descriptor type -// cant use alias typedef int file_descriptor; -// ports -#define PORT_HTTP 80 - class Socket { public: - Socket(int domain, int type, int protocol); - ~Socket(); - // member functions - WS_CODE bind(int family, int port, int address = INADDR_ANY); + // constructors + Socket(int domain, int type, int protocol = 0, int flags = SOCK_NONBLOCK); + Socket(int domain, + int type, + const char *protocol_name, + int flags = SOCK_NONBLOCK); + + // destructor + ~Socket(); // close vs shutdown + + // member functions (API) + WS_CODE bind(int port); + // WS_CODE connect(); WS_CODE listen(int backlog); + // WS_CODE accept(); + // WS_CODE send(const char *msg); + // WS_CODE recv(const char *buff); + // WS_CODE getpeer(struct sockaddr &address); + // WS_CODE shutdown(int option); private: static const int invalid_file_descriptor = -1; file_descriptor socket_descriptor; + int family; // domain of communicatoin + int type; // type of socket + // deleted but can't cause is 98 maguy - Socket(const Socket &); - Socket &operator=(const Socket &); + Socket(const Socket &){}; + Socket &operator=(const Socket &) + { + return *this; + }; }; #endif // SOCKET_HPP diff --git a/ver-01.1/srcs/Socket.cpp b/ver-01.1/srcs/Socket.cpp index 1a4f645..5b38abf 100644 --- a/ver-01.1/srcs/Socket.cpp +++ b/ver-01.1/srcs/Socket.cpp @@ -1,5 +1,6 @@ #include "Socket.hpp" #include +#include #include #include /* superset of previous */ #include @@ -8,24 +9,98 @@ #include /* See NOTES */ #include -Socket::Socket(int domain, int type, int protocol) +#ifdef __DEBUG__ +#include +#include +#define DEBUGASSERT(x) assert(x) +#else +#define DEBUGASSERT(x) \ + do \ + { \ + } while (0) +#endif // __DEBUG__ + +/** + * Creates a new socket with the specified domain, type, protocol, and flags. + * + * @param domain The communication domain for the socket. This selects the protocol + * family. + * @param type The type of socket to be created. + * @param protocol The protocol to be used. By default, the protocol is set to 0. + * @param flags The flags to be set for the socket. By default, the flags are set to + * SOCK_NONBLOCK. + * + * @throws std::runtime_error if the socket creation fails. + * + * @note Normally, only one protocol exists to support a specific socket type within a + * particular protocol family. + */ +Socket::Socket(int domain, int type, int protocol, int flags) + : socket_descriptor(invalid_file_descriptor) + , family(domain) + , type(type) +{ + DEBUGASSERT(domain > 0); + DEBUGASSERT(protocol >= 0); + + socket_descriptor = socket(domain, type | flags, protocol); + + // On success, a file descriptor for the new socket is returned. + // On error, -1 is returned, and errno is set + if (socket_descriptor == invalid_file_descriptor) + { + std::stringstream errorMessage; + errorMessage << ERR_STRT_MSG << ": " << strerror(errno); + throw std::runtime_error(errorMessage.str()); + } +#ifdef __DEBUG__ + else + std::cout << "Socket was created successfully fd[" << socket_descriptor << "]\n"; +#endif // __DEBUG__ +} + +// can call protocol by name +Socket::Socket(int domain, int type, const char *protocol_name, int flags) : socket_descriptor(invalid_file_descriptor) { - socket_descriptor = socket(domain, type, protocol); + if (!protocol_name) + throw std::runtime_error(ERR_NULL_MSG); + + DEBUGASSERT(domain > 0); + + // identify the protocol name + std::string proto_name(protocol_name); + for (size_t i = 0; i < proto_name.length(); i++) + proto_name[i] = std::tolower(proto_name[i]); + + // continue with the rest of the code + struct protoent *protocol = getprotobyname(proto_name.c_str()); + // check getprotobyname return + if (!protocol) + throw std::runtime_error(ERR_NULL_MSG); + +#ifdef __DEBUG__ + std::cout << "protocol official name is [" << protocol->p_name << "]\n"; +#endif // __DEBUG__ + + + socket_descriptor = socket(domain, type | flags, protocol->p_proto); + // On success, a file descriptor for the new socket is returned. On error, -1 is // returned, and errno is set if (socket_descriptor == invalid_file_descriptor) { std::stringstream errorMessage; - errorMessage << SOCKET_ERR << ": " << strerror(errno); + errorMessage << ERR_STRT_MSG << ": " << strerror(errno); throw std::runtime_error(errorMessage.str()); } #ifdef __DEBUG__ // if needed else - std::cout << "Listener was created successfully fd[" << listener << "]\n"; + std::cout << "Socket was created successfully fd[" << socket_descriptor << "]\n"; #endif // __DEBUG__ } +// destructor Socket::~Socket() { if (socket_descriptor != invalid_file_descriptor) @@ -33,20 +108,29 @@ Socket::~Socket() close(socket_descriptor); socket_descriptor = invalid_file_descriptor; // invalidate the filedescriptor } +#ifdef __DEBUG__ + else + std::cerr << "socket fd[" << socket_descriptor << "] closed!!\n"; +#endif // __DEBUG__ } // member functions - -WS_CODE Socket::bind(int family, int port, int address) +WS_CODE Socket::bind(int port) { - // int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen); + // this has to be created based on the type of socket struct sockaddr_in addr; - addr.sin_addr.s_addr = htonl(address); + + memset(&addr, 0, sizeof(addr)); + // same for these filled they are determined based on the family type + addr.sin_addr.s_addr = htonl(INADDR_ANY); addr.sin_family = family; - addr.sin_port = port; - if (::bind(socket_descriptor, (struct sockaddr *)&addr, sizeof(addr))) + addr.sin_port = htons(port); + + int status = ::bind(socket_descriptor, (struct sockaddr *)&addr, sizeof(addr)); + if (status == -1) return WS_BIND_FAIL; + return WS_OK; } @@ -54,8 +138,8 @@ WS_CODE Socket::bind(int family, int port, int address) * Listens for a connection on a socket and marks the socket referred to by * socket_descriptor as a passive socket. * - * @param backlog The maximum length to which the queue of pending connections for sockfd - * may grow. + * @param backlog The maximum length to which the queue of pending connections for + * sockfd may grow. * * @return WS_CODE The status code indicating the result of the listen operation. * @@ -63,8 +147,8 @@ WS_CODE Socket::bind(int family, int port, int address) * * @note The listen operation is typically used on server sockets after the socket has * been bound to a specific address and port using the bind function. Once the listen - * operation is successful, the server socket can accept incoming connections using the - * accept function. + * operation is successful, the server socket can accept incoming connections using + * the accept function. */ WS_CODE Socket::listen(int backlog) { @@ -72,19 +156,6 @@ WS_CODE Socket::listen(int backlog) int status = ::listen(socket_descriptor, backlog); if (status == -1) return WS_LISTEN_FAIL; - return WS_OK; -} - -// deleted but can't cause is 98 maguy -Socket::Socket(const Socket &other) - : socket_descriptor(0) -{ - (void)other; -} -Socket &Socket::operator=(const Socket &other) -{ - - (void)other; - return *this; + return WS_OK; } From 05a9e58bfe4b055ac4dc017c9354161dd4ea74a2 Mon Sep 17 00:00:00 2001 From: Samih Date: Wed, 3 Jan 2024 04:50:32 +0400 Subject: [PATCH 008/215] chore: Remove .cache/* --- .../clangd/index/Server.cpp.D633944E783E62FE.idx | Bin 1654 -> 0 bytes .../clangd/index/Server.hpp.9E005926D78734D6.idx | Bin 964 -> 0 bytes 2 files changed, 0 insertions(+), 0 deletions(-) delete mode 100644 ver-01.1/.cache/clangd/index/Server.cpp.D633944E783E62FE.idx delete mode 100644 ver-01.1/.cache/clangd/index/Server.hpp.9E005926D78734D6.idx diff --git a/ver-01.1/.cache/clangd/index/Server.cpp.D633944E783E62FE.idx b/ver-01.1/.cache/clangd/index/Server.cpp.D633944E783E62FE.idx deleted file mode 100644 index 103f0ac12dca63a8e3797913d7fc17ad93686eba..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1654 zcmWIYbaTsNV_Z&?5kz{_EhTmeF~?R`1;5O32C4E{(s|~hM)x@N4Kem`L0;8 zBHcJ(H_ux0b*nub_GUf5RSi+Uq5BCUm@~H z?tJR`&pPv20&Z~ZTOv}Jc1vu7@Ucr(KH>*d?c3gp-CMI*_tBDnp& zKMNVN)qk^A&iQ(GLDv0+b68qsW>!pBnxTAmX~*(uDx6te*7||f&H|^tzu(Rw5S1j$ zEIy&n^3d}iw)+^0y?AnqD|3@}0mJn|Pa0pC*D(eGCRu(4K_dYp2?0IzmJ2{b+kw;LHOHu%4 zn4gZzwtamLoIqhk2}LD{FA@G^W(J6V1A%#H)A(*n18P9W%qwWgnY7+C}rq!iR( zsy(i(mdgEcIT|Re#HS<(6J~bZBzEc?YZ;pG%CmecQ(_iXK+T4!_LkQO`Jl0<7V2)8 z@I&r<=V!YzHUNcnSadjHajQ0sMd3NC%p{O%bx9+b15JLss1oncSp*bTG*`5N3Bz;& z;}Vn{V4jE3d_02u4E$`c00r_m`1ue#A#Nc-1W%knoDJqU9zjs@ff>UisKubg2D1yu zK>^U=!pah!)A554>P>w?mo*{tI#ib(z3yi4`wGKG!Tk;BMk^--SButBy z+{aVdY>6M4Sp*eD6~$q~K%TOqDiTjyQ5VKzC`!#q1jTD{QF3uJh#?6gAV3txU|Jg&7<^m?xN z9u4VaReLs1f#tHB*IbRV)5mUdiU=rAQaydC`r7{s!EqXgckSYfNoiZne?{?;gt}8y z&Si-^TPqfC7UARGnd_5#VKevVR+jL+a>2iDPkpm*-tUiTC+F{fVfJ<*k5sVDa>K(8 zRY`%T`xGhy9|_ItKYzh6a9ium<{z4@tB!mY@K6q4U#%3j+RjMCUi;4dtMZlY5yr)p zxk(m4mtN>e;|udT#vs7N#l*mBBw!@L!Y9Bd!N39Z2@ps#o}HHYelMpO6C+SspF^LI zg_nbu4<>EtG-H2g%N`{@CQc>>7D-7-IWPf}cDmXp-QmljF2uwR)XguzFU=w>F02HT zcH>YE`LVjpK!Aw{C~d)OA;cmgE+PYyUa}>1&hj(eetb;KK*OaZrDVYbOuA-O%<|*i ziD$%_c!9dLIJ7ufL^(t`VbZ2sW---x*qvo(0{W7LgN=g+OfYaVFmN+4FtV_EOqww1 zag@m=h}Xn9#Q9iwIC$V*tGM}Oy;Ik-=X^{YK-(oGB^1E~%=n_zwBlZ*@MB~Iha1e+ z5I-UH7ZYt*8F^Twc%_74Uh&g$*|x9Gfs>Jog_VO9lxn~L7RrpA;LwE`0t;QBYEaO^ zgkhlyR1FGEm~gzfh|U5N2W_BgMh-@}*|0zcss;rvOf}3!K-Hj-g$cs~73dvMV8Vo9 zGzS+X5TWko0f!h&k_W}{K%OYCG|Xo_EPNb%e6Yj@=z37hz=Ro!QgaePZYwTIE*1wd*gymrFtG?`-&=mecZDA#8v_9J C*!=DQ From a494f888a015243729e182027c372de932a34544 Mon Sep 17 00:00:00 2001 From: Samih Date: Wed, 3 Jan 2024 04:51:26 +0400 Subject: [PATCH 009/215] chore(SOCKET_main.cpp): Add tester main for Socket class --- ver-01.1/srcs/SOCKET_main.cpp | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) create mode 100644 ver-01.1/srcs/SOCKET_main.cpp diff --git a/ver-01.1/srcs/SOCKET_main.cpp b/ver-01.1/srcs/SOCKET_main.cpp new file mode 100644 index 0000000..99982fd --- /dev/null +++ b/ver-01.1/srcs/SOCKET_main.cpp @@ -0,0 +1,18 @@ +#include "Socket.hpp" +#include +#include +#include + + +int main() +{ + + try + { + Socket a(PF_INET, SOCK_STREAM, "UDP"); + } + catch (std::exception &e) + { + std::cerr << e.what(); + } +} From b631a79cdda33c5ca68271ae4b12f6b6f3dc04d4 Mon Sep 17 00:00:00 2001 From: Samih Date: Wed, 3 Jan 2024 04:56:31 +0400 Subject: [PATCH 010/215] chore(Socket.cpp): Add a comment to `bind()` - comment to explain why memset 0 structaddr struct --- ver-01.1/srcs/Socket.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/ver-01.1/srcs/Socket.cpp b/ver-01.1/srcs/Socket.cpp index 5b38abf..7c29da9 100644 --- a/ver-01.1/srcs/Socket.cpp +++ b/ver-01.1/srcs/Socket.cpp @@ -121,6 +121,7 @@ WS_CODE Socket::bind(int port) // this has to be created based on the type of socket struct sockaddr_in addr; + // zero out the sockaddr struct memset(&addr, 0, sizeof(addr)); // same for these filled they are determined based on the family type addr.sin_addr.s_addr = htonl(INADDR_ANY); From 568a96d34e68c949590e82c54b4ed8ebf397d586 Mon Sep 17 00:00:00 2001 From: Samih Date: Wed, 3 Jan 2024 04:57:49 +0400 Subject: [PATCH 011/215] chore(Socket.hpp): Change error messages --- ver-01.1/includes/Socket.hpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/ver-01.1/includes/Socket.hpp b/ver-01.1/includes/Socket.hpp index 350fac5..aca95a7 100644 --- a/ver-01.1/includes/Socket.hpp +++ b/ver-01.1/includes/Socket.hpp @@ -9,15 +9,16 @@ // [ ] better error messages // [ ] make a unit-tester main // [ ] add shutdown functionality (block recv, block send, close()) +// [ ] improve error messages #ifndef SOCKET_HPP #define SOCKET_HPP // error messages #define ERR_NULL_MSG "Null ptr!!" // make more verbose -#define ERR_STRT_MSG "Socket creation failed" -#define ERR_BIND_MSG "Socket binding failed" -#define ERR_LIST_MSG "Socket binding failed" +#define ERR_STRT_MSG "Socket: creation failed" +#define ERR_BIND_MSG "Socket: binding failed" +#define ERR_LIST_MSG "Socket: listen failed" // error codes enum WS_CODE From afcaf03180f9a5935943f13901b54bc58233cd8e Mon Sep 17 00:00:00 2001 From: Samih Date: Wed, 3 Jan 2024 04:59:24 +0400 Subject: [PATCH 012/215] chore(main.cpp): Delete main.cpp. - This action was taken because of the design change to a library. --- ver-01.1/srcs/main.cpp | 0 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 ver-01.1/srcs/main.cpp diff --git a/ver-01.1/srcs/main.cpp b/ver-01.1/srcs/main.cpp deleted file mode 100644 index e69de29..0000000 From bbb72d6f9d538907397bd6f391c171d4ca32fc6e Mon Sep 17 00:00:00 2001 From: Samih Date: Thu, 4 Jan 2024 03:42:14 +0400 Subject: [PATCH 013/215] chore(Makefile): Add `TCPSocket` class file --- ver-01.1/Makefile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ver-01.1/Makefile b/ver-01.1/Makefile index 84d92b1..bfea5ae 100644 --- a/ver-01.1/Makefile +++ b/ver-01.1/Makefile @@ -1,5 +1,5 @@ CXX:= c++ -CXXFLAGS:= -Wall -Werror -Wextra -std=c++98 +CXXFLAGS:= -Wall -Werror -Wextra -std=c++98 DEBUGFLAGS:= -ggdb3 -fsanitize=address -D__DEBUG__ RM:= rm -rf @@ -7,7 +7,7 @@ RM:= rm -rf INCLUDES:= -I./includes SRCS_DIR:= srcs -SRCS:= Socket.cpp Server.cpp +SRCS:= Socket.cpp TCPSocket.cpp Server.cpp # tester mains TEST_SOCK:= $(SRCS_DIR)/SOCKET_main.cpp From c3ffe69a0bceb9504e542dfe090367d9721bcc5a Mon Sep 17 00:00:00 2001 From: Samih Date: Thu, 4 Jan 2024 03:43:07 +0400 Subject: [PATCH 014/215] feat(TCPSocket): Adding a new inherited class called TCPSocket. - This was done in order to conceal the complexity of the implementation of the Socket class. - The primary objective of the inherited Socket classes is to restrict the combinations of protocol, family, and socket type to valid combinations. --- ver-01.1/includes/TCPSocket.hpp | 19 +++++++++++++++++++ ver-01.1/srcs/TCPSocket.cpp | 10 ++++++++++ 2 files changed, 29 insertions(+) create mode 100644 ver-01.1/includes/TCPSocket.hpp create mode 100644 ver-01.1/srcs/TCPSocket.cpp diff --git a/ver-01.1/includes/TCPSocket.hpp b/ver-01.1/includes/TCPSocket.hpp new file mode 100644 index 0000000..7ab4bdc --- /dev/null +++ b/ver-01.1/includes/TCPSocket.hpp @@ -0,0 +1,19 @@ +#include +#include + +#ifndef TCPSOCKET_HPP +#define TCPSOCKET_HPP + +class TCPSocket : public Socket +{ + + public: + TCPSocket(); + ~TCPSocket(); + + private: + TCPSocket(const TCPSocket &); + TCPSocket &operator=(const TCPSocket &); +}; + +#endif // TCPSOCKET_HPP diff --git a/ver-01.1/srcs/TCPSocket.cpp b/ver-01.1/srcs/TCPSocket.cpp new file mode 100644 index 0000000..803f471 --- /dev/null +++ b/ver-01.1/srcs/TCPSocket.cpp @@ -0,0 +1,10 @@ +#include "TCPSocket.hpp" + +TCPSocket::TCPSocket() + : Socket(AF_INET, SOCK_STREAM, 0, SOCK_NONBLOCK) +{} + +TCPSocket::~TCPSocket() +{ + // destructor code +} From 8db4053b8bc3d00d8394127bb06f12980bcbc895 Mon Sep 17 00:00:00 2001 From: Samih Date: Thu, 4 Jan 2024 03:47:21 +0400 Subject: [PATCH 015/215] chore(Socket.hpp): Modified TODO, and error handling - Added static error messages, and assert macro for error handling - Updated TODO list --- ver-01.1/includes/Socket.hpp | 43 +++++++++++++++++++----------------- 1 file changed, 23 insertions(+), 20 deletions(-) diff --git a/ver-01.1/includes/Socket.hpp b/ver-01.1/includes/Socket.hpp index aca95a7..c7ae111 100644 --- a/ver-01.1/includes/Socket.hpp +++ b/ver-01.1/includes/Socket.hpp @@ -2,32 +2,35 @@ #include /* superset of previous */ #include -// TODO +// TODO // [P]artially implemented, needs [I]mprovement, [X] done +// +// [ ] Derived TCP class to lock domain, type .. combinations // [ ] split-up function implementations into their own files -// [ ] error checking functions for domain, type, protocol ... etc -// [ ] custom exception class for error handling -// [ ] better error messages -// [ ] make a unit-tester main // [ ] add shutdown functionality (block recv, block send, close()) -// [ ] improve error messages +// [P] make a unit-tester main +// [X] error checking functions for domain, type, protocol ... etc +// [X] better error messages, and error handling,custom exception class #ifndef SOCKET_HPP #define SOCKET_HPP +// DEBUG BUILD +#ifdef __DEBUG__ +#include +#include +#define DEBUGASSERT(x) assert(x) +#else +#define DEBUGASSERT(x) \ + do \ + { \ + } while (0) +#endif // __DEBUG__ +// DEBUG BUILD -// error messages -#define ERR_NULL_MSG "Null ptr!!" // make more verbose -#define ERR_STRT_MSG "Socket: creation failed" -#define ERR_BIND_MSG "Socket: binding failed" -#define ERR_LIST_MSG "Socket: listen failed" - -// error codes -enum WS_CODE -{ - WS_OK = 0, - WS_LISTEN_FAIL, - WS_BIND_FAIL, - WS_TOTAL -}; +// [ERROR MESSAGES] +static std::string ERR_NULL("Socket: null ptr error"); +static std::string ERR_CREAT("Socket: creation failed"); +static std::string ERR_BIND("Socket: binding failed"); +static std::string ERR_LIST("Socket: listen failed"); // socket_descriptor type typedef int file_descriptor; From 5eac525b76ecb033537b6ca8d6f6152e915eda76 Mon Sep 17 00:00:00 2001 From: Samih Date: Thu, 4 Jan 2024 03:50:08 +0400 Subject: [PATCH 016/215] feat(Socket.hpp): Make constructors protected. - This change was made to improve and enforce inheritance by restricting the creation of base Socket to only the derived Socket classes. --- ver-01.1/includes/Socket.hpp | 64 +++++++++++++++++++++++++----------- 1 file changed, 45 insertions(+), 19 deletions(-) diff --git a/ver-01.1/includes/Socket.hpp b/ver-01.1/includes/Socket.hpp index c7ae111..6c37d24 100644 --- a/ver-01.1/includes/Socket.hpp +++ b/ver-01.1/includes/Socket.hpp @@ -1,6 +1,12 @@ +#include +#include +#include #include #include /* superset of previous */ +#include +#include #include +#include // TODO // [P]artially implemented, needs [I]mprovement, [X] done // @@ -39,25 +45,45 @@ class Socket { public: - // constructors - Socket(int domain, int type, int protocol = 0, int flags = SOCK_NONBLOCK); - Socket(int domain, - int type, - const char *protocol_name, - int flags = SOCK_NONBLOCK); - - // destructor - ~Socket(); // close vs shutdown - - // member functions (API) - WS_CODE bind(int port); - // WS_CODE connect(); - WS_CODE listen(int backlog); - // WS_CODE accept(); - // WS_CODE send(const char *msg); - // WS_CODE recv(const char *buff); - // WS_CODE getpeer(struct sockaddr &address); - // WS_CODE shutdown(int option); + /* [DESTRUCTOR] */ + virtual ~Socket(); + + /* [INTERFACE] */ + + void bind(int port); + // void connect(); + void listen(int backlog); + // void accept(); + // void send(const char *msg); + // void recv(const char *buff); + // void getpeer(struct sockaddr &address); + // void shutdown(int option); + + /* [ERROR HANDLING] */ + + struct Exception : public std::exception + { + private: + std::string error_message; + + public: + explicit Exception(const std::string &error_message) + : error_message(error_message){}; + ~Exception() throw(){}; + + /* [COMPOSE MESSAGE] */ + static std::string compose_msg(const std::string &message) + { + std::stringstream _msg; + _msg << message << (errno ? std::strerror(errno) : ""); + return _msg.str(); + } + const char *what() const throw() + { + return error_message.c_str(); + } + }; + ; private: static const int invalid_file_descriptor = -1; From 320e46c26c6d306081b0cefa6a9397f4becda050 Mon Sep 17 00:00:00 2001 From: Samih Date: Thu, 4 Jan 2024 03:57:15 +0400 Subject: [PATCH 017/215] chore(Refactor): Refactor to accomodate design changes - I lied this is a big ass commit :) --- ver-01.1/includes/Server.hpp | 15 +++-- ver-01.1/includes/Socket.hpp | 8 +++ ver-01.1/srcs/SOCKET_main.cpp | 8 +-- ver-01.1/srcs/Server.cpp | 107 ++++++++++++++++----------------- ver-01.1/srcs/Socket.cpp | 109 ++++++++-------------------------- 5 files changed, 100 insertions(+), 147 deletions(-) diff --git a/ver-01.1/includes/Server.hpp b/ver-01.1/includes/Server.hpp index 75084d7..3d2baf0 100644 --- a/ver-01.1/includes/Server.hpp +++ b/ver-01.1/includes/Server.hpp @@ -1,3 +1,4 @@ +#include #include #ifndef SERVER_HPP @@ -9,20 +10,22 @@ class Server { protected: - Server(); - Server(const Server &); - Server &operator=(const Server &); + Server(){}; + Server(const Server &){}; + Server &operator=(const Server &) + { + return *this; + }; public: // this function needs to be static, as there won't be an instance of a Server // when its first created static Server &getInstance(); - void start(); - static WS_CODE bind(int sockfd); + // void start(); ~Server(); private: - int listener; + // Socket listener; int status; std::vector conn; }; diff --git a/ver-01.1/includes/Socket.hpp b/ver-01.1/includes/Socket.hpp index 6c37d24..34dd3f9 100644 --- a/ver-01.1/includes/Socket.hpp +++ b/ver-01.1/includes/Socket.hpp @@ -44,6 +44,14 @@ typedef int file_descriptor; class Socket { + protected: // protected constructors only in derived classes + /* [CONSTRUCTORS] */ + + Socket(int domain, int type, int protocol, int flags); + // maybe not necessary + Socket(int domain, int type, const char *protocol_name, int flags); + + public: /* [DESTRUCTOR] */ virtual ~Socket(); diff --git a/ver-01.1/srcs/SOCKET_main.cpp b/ver-01.1/srcs/SOCKET_main.cpp index 99982fd..69bc284 100644 --- a/ver-01.1/srcs/SOCKET_main.cpp +++ b/ver-01.1/srcs/SOCKET_main.cpp @@ -1,15 +1,15 @@ -#include "Socket.hpp" +#include "TCPSocket.hpp" #include #include #include - +// Socket tester main add test cases here to test the behaviour of the +// class int main() { - try { - Socket a(PF_INET, SOCK_STREAM, "UDP"); + TCPSocket a; } catch (std::exception &e) { diff --git a/ver-01.1/srcs/Server.cpp b/ver-01.1/srcs/Server.cpp index 51256b7..2332be1 100644 --- a/ver-01.1/srcs/Server.cpp +++ b/ver-01.1/srcs/Server.cpp @@ -20,56 +20,57 @@ Server &Server::getInstance() return instance; } -// default constructor -Server::Server() - : listener( - socket(AF_INET, SOCK_STREAM, IPPROTO_TCP | SOCK_NONBLOCK)) // start the listener - , status(WS_OK) -{} - -Server::~Server() -{ - close(listener); -} - -Server::Server(const __attribute__((unused)) Server &other) -{} - -Server &Server::operator=(const __attribute__((unused)) Server &other) -{ - return *this; -} - - -void Server::start() -{ - int backlog = 0; - int status = 0; - - // bind the socket - while (true) - { - if (status) // an error has occured - { - // If a connection request arrives when the queue is full - std::stringstream errorMessage; - errorMessage << SOCKET_ERR << ": " << strerror(errno); - throw std::runtime_error(errorMessage.str()); - } - - // accept a connection on a socket - struct sockaddr_storage clientAddr; - socklen_t clientAddrSize = sizeof(clientAddr); - int clientSocket = - accept(listener, (struct sockaddr *)&clientAddr, &clientAddrSize); - if (clientSocket == -1) - { - std::stringstream errorMessage; - errorMessage << SOCKET_ERR << ": " << strerror(errno); - throw std::runtime_error(errorMessage.str()); - } - - // handle the connection - handleConnection(clientSocket); - } -} +// // default constructor +// Server::Server() +// : listener{ +// Socket(AF_INET, SOCK_STREAM, IPPROTO_TCP, SOCK_NONBLOCK)) // start the +// listener +// , status(WS_OK) +// {} +// +// Server::~Server() +// { +// close(listener); +// } +// +// Server::Server(const __attribute__((unused)) Server &other) +// {} +// +// Server &Server::operator=(const __attribute__((unused)) Server &other) +// { +// return *this; +// } +// +// +// void Server::start() +// { +// int backlog = 0; +// int status = 0; +// +// // bind the socket +// while (true) +// { +// if (status) // an error has occured +// { +// // If a connection request arrives when the queue is full +// std::stringstream errorMessage; +// errorMessage << SOCKET_ERR << ": " << strerror(errno); +// throw std::runtime_error(errorMessage.str()); +// } +// +// // accept a connection on a socket +// struct sockaddr_storage clientAddr; +// socklen_t clientAddrSize = sizeof(clientAddr); +// int clientSocket = +// accept(listener, (struct sockaddr *)&clientAddr, &clientAddrSize); +// if (clientSocket == -1) +// { +// std::stringstream errorMessage; +// errorMessage << SOCKET_ERR << ": " << strerror(errno); +// throw std::runtime_error(errorMessage.str()); +// } +// +// // handle the connection +// handleConnection(clientSocket); +// } +// } diff --git a/ver-01.1/srcs/Socket.cpp b/ver-01.1/srcs/Socket.cpp index 7c29da9..01f2215 100644 --- a/ver-01.1/srcs/Socket.cpp +++ b/ver-01.1/srcs/Socket.cpp @@ -1,72 +1,35 @@ #include "Socket.hpp" -#include #include #include #include /* superset of previous */ -#include -#include #include #include /* See NOTES */ -#include -#ifdef __DEBUG__ -#include -#include -#define DEBUGASSERT(x) assert(x) -#else -#define DEBUGASSERT(x) \ - do \ - { \ - } while (0) -#endif // __DEBUG__ -/** - * Creates a new socket with the specified domain, type, protocol, and flags. - * - * @param domain The communication domain for the socket. This selects the protocol - * family. - * @param type The type of socket to be created. - * @param protocol The protocol to be used. By default, the protocol is set to 0. - * @param flags The flags to be set for the socket. By default, the flags are set to - * SOCK_NONBLOCK. - * - * @throws std::runtime_error if the socket creation fails. - * - * @note Normally, only one protocol exists to support a specific socket type within a - * particular protocol family. - */ -Socket::Socket(int domain, int type, int protocol, int flags) +/* [CONSTRUCTORS] */ + +Socket::Socket(int family, int type, int protocol, int flags) : socket_descriptor(invalid_file_descriptor) - , family(domain) + , family(family) , type(type) { - DEBUGASSERT(domain > 0); - DEBUGASSERT(protocol >= 0); - - socket_descriptor = socket(domain, type | flags, protocol); + socket_descriptor = socket(family, type | flags, protocol); // On success, a file descriptor for the new socket is returned. - // On error, -1 is returned, and errno is set if (socket_descriptor == invalid_file_descriptor) - { - std::stringstream errorMessage; - errorMessage << ERR_STRT_MSG << ": " << strerror(errno); - throw std::runtime_error(errorMessage.str()); - } + throw Socket::Exception(Exception::compose_msg(ERR_CREAT)); #ifdef __DEBUG__ else std::cout << "Socket was created successfully fd[" << socket_descriptor << "]\n"; #endif // __DEBUG__ } -// can call protocol by name -Socket::Socket(int domain, int type, const char *protocol_name, int flags) +/* Call protocol by name */ +Socket::Socket(int family, int type, const char *protocol_name, int flags) : socket_descriptor(invalid_file_descriptor) { if (!protocol_name) - throw std::runtime_error(ERR_NULL_MSG); - - DEBUGASSERT(domain > 0); + throw Socket::Exception(Exception::compose_msg(ERR_NULL)); // identify the protocol name std::string proto_name(protocol_name); @@ -77,36 +40,33 @@ Socket::Socket(int domain, int type, const char *protocol_name, int flags) struct protoent *protocol = getprotobyname(proto_name.c_str()); // check getprotobyname return if (!protocol) - throw std::runtime_error(ERR_NULL_MSG); + throw Socket::Exception(Exception::compose_msg(ERR_NULL)); #ifdef __DEBUG__ std::cout << "protocol official name is [" << protocol->p_name << "]\n"; #endif // __DEBUG__ + socket_descriptor = socket(family, type | flags, protocol->p_proto); - socket_descriptor = socket(domain, type | flags, protocol->p_proto); - - // On success, a file descriptor for the new socket is returned. On error, -1 is - // returned, and errno is set + // On success, a file descriptor for the new socket is returned. if (socket_descriptor == invalid_file_descriptor) - { - std::stringstream errorMessage; - errorMessage << ERR_STRT_MSG << ": " << strerror(errno); - throw std::runtime_error(errorMessage.str()); - } -#ifdef __DEBUG__ // if needed + throw Socket::Exception(Exception::compose_msg(ERR_CREAT)); + +#ifdef __DEBUG__ else std::cout << "Socket was created successfully fd[" << socket_descriptor << "]\n"; #endif // __DEBUG__ } -// destructor +/* [DESTRUCTOR] */ + Socket::~Socket() { if (socket_descriptor != invalid_file_descriptor) { close(socket_descriptor); - socket_descriptor = invalid_file_descriptor; // invalidate the filedescriptor + // invalidate the filedescriptor + socket_descriptor = invalid_file_descriptor; } #ifdef __DEBUG__ else @@ -115,8 +75,9 @@ Socket::~Socket() } -// member functions -WS_CODE Socket::bind(int port) +/* [INTERFACE] */ + +void Socket::bind(int port) { // this has to be created based on the type of socket struct sockaddr_in addr; @@ -130,33 +91,13 @@ WS_CODE Socket::bind(int port) int status = ::bind(socket_descriptor, (struct sockaddr *)&addr, sizeof(addr)); if (status == -1) - return WS_BIND_FAIL; - - return WS_OK; + throw Socket::Exception(Exception::compose_msg(ERR_BIND)); } -/** - * Listens for a connection on a socket and marks the socket referred to by - * socket_descriptor as a passive socket. - * - * @param backlog The maximum length to which the queue of pending connections for - * sockfd may grow. - * - * @return WS_CODE The status code indicating the result of the listen operation. - * - * @throws None - * - * @note The listen operation is typically used on server sockets after the socket has - * been bound to a specific address and port using the bind function. Once the listen - * operation is successful, the server socket can accept incoming connections using - * the accept function. - */ -WS_CODE Socket::listen(int backlog) +void Socket::listen(int backlog) { // global namespace to avoid conflict int status = ::listen(socket_descriptor, backlog); if (status == -1) - return WS_LISTEN_FAIL; - - return WS_OK; + throw Socket::Exception(Exception::compose_msg(ERR_LIST)); } From 4974d52c9c8573346fe1e68388abd1702e3c5e27 Mon Sep 17 00:00:00 2001 From: Samih Date: Thu, 4 Jan 2024 03:59:11 +0400 Subject: [PATCH 018/215] chore(ver-01): Delete unused directory --- ver-01/client | Bin 16352 -> 0 bytes ver-01/client.c | 54 -------------------------------------------- ver-01/server | Bin 16472 -> 0 bytes ver-01/server.c | 59 ------------------------------------------------ 4 files changed, 113 deletions(-) delete mode 100755 ver-01/client delete mode 100644 ver-01/client.c delete mode 100755 ver-01/server delete mode 100644 ver-01/server.c diff --git a/ver-01/client b/ver-01/client deleted file mode 100755 index e0fa7c30bac4e50c4276c3b2170f86e595e2de23..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 16352 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 za; -#include -#include -#include -#include -#include -#include - -#define PORT 8080 - -// GET /hello.txt HTTP/1.1 -// User-Agent: curl/7.16.3 libcurl/7.16.3 OpenSSL/0.9.7l zlib/1.2.3 -// Host: www.example.com -// Accept-Language: en, mi -struct get_request -{}; - -int main(int argc, char const *argv[]) -{ - int sock = 0;: - long valread; - struct sockaddr_in serv_addr; - char *hello = "Hello from client"; - char buffer[1024] = { 0 }; - if ((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0) - { - printf("\n Socket creation error \n"); - return -1; - } - - memset(&serv_addr, 0, sizeof(serv_addr)); - - serv_addr.sin_family = AF_INET; - serv_addr.sin_port = htons(PORT); - - // Convert IPv4 and IPv6 addresses from text to binary form - if (inet_pton(AF_INET, "127.0.0.1", &serv_addr.sin_addr) <= 0) - { - printf("\nInvalid address/ Address not supported \n"); - return -1; - } - - if (connect(sock, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) < 0) - { - printf("\nConnection Failed \n"); - return -1; - } - send(sock, hello, strlen(hello), 0); - printf("Hello message sent\n"); - valread = read(sock, buffer, 1024); - printf("%s\n", buffer); - return 0; -} diff --git a/ver-01/server b/ver-01/server deleted file mode 100755 index 3ea256076796781490446b6bba6b9a61137d5826..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 16472 zcmeHOeQX@X6(2h>7)W9VNJ+v+mNZZx^2H8L2%&DyNt~=(2SPqXB1)IDZ*8A?ALeea zv1vt(%vEt6OGdOMf6yw3N?1Z_(~43W3Alt7hgPLdtE%az+^Ug$6%=zVZD>obzc({) zv$we`sO>+kcC5YMyx)6oX7=sudS-X#vmIUAYHMl)r+MNdf~1+niV17Q;SD+i2#XD3 zA%0hg>%>Kn=SxoM!wR5P>2z&5)@yzqko=ZXrUG80Xu-%WBqYCT>7=fJQ8X$`@~fk) zmi@R)DurNVy<49_&Pay*b@3n>ATfIVC^q|=q+0B2E63+`T=E*(k3{n8*M9xlk8w`d z$H?)dn9#97$J39^&{1Oa`}J!-KW#KGhCUyK7b$G>^c&vMU>za79DIQB^2b%^rtZ!Q18p@DW(i>G;hvU;f#y6W5RpwVQm% zh7y&>U4&%HUyg%pR6HI=PH}{%?AH>6)zZ~akiS1Y2Ey=@kng}z$$m){ep?lOR~4SF zbEWdbRd|X|CHt>~H*omVJ`k1ccU0l6DtvDho`PMe{1?F+IQ)rj>q_=D;8*&MNw%z> z!HCrxOGe_c2W^qIBT;c69dm4G&_{c$j1x&aRw5EhicG5KleQxgb|M29$T}I(6HjGq zk#W*-J1M$j$*AaeQpt>n$1)C>0Xv;erA4Ht#~yHmJs5MK>F%L^zFuta>fF4=S{qs$ zTIc3(Z53AMo*h=yPTPG{MtaYVE%8*+-V^DLQ=9q{siba`rA#XtQctcy@Am$AWtFFX zUMtcF1K-ct<*`fXuK0}Ro_+L7xD9H>L5dX;KWF**me;|)Uq45gAJ%+*Sh@-3Sw6i< z@pO;Twc#}5;l20etcSmpje&C>p3i~QXFa^PKMZL8V%YGrgzN`BJUu5k4SRU~FHEWq zdU!eqP7@xU>fm(P!*eW1cf`XZ@NSy)@Rzx)5Jx@y0uTSZhhOO7^B#VYhd=4z8$A59 zhu1?Ck2c5#5eOm>L?DPj5P={9?y=2+d&*9c+e@=k4O+8p_A{mat5 zv~DBlV(ErE01Yby+4qyCSom$JRGN@74Ume3Q?5({qhjH>E7L%xSonr3(*UMec+!<= z;8H9+>dG`=DHa}fWg4gy3lF$54N!`Oh%3{;q*%Dym1zK0EVR2a4N!`O7FVW$NwIJ} z%Q(9?LUeXpg*-pVdwuc_pWNY-+kEmmpWNh=Z}7?2`s5`(d7)3P^U3dGUg2&3+g`cl zjn2_ipD;&%XO8@SZs(qkmVC>r=6Kup5rxu{pTP3Zy`hE`k3d8R7;k$Aj5%IcB)I*o zvjkn^Im)AJTvD28STRg?FKdMTtI~em34)u?nWJ;&@jq@dkDr}q*1Te#I_F%80&=>5 z`qE6VY$y9u{~2y0waBjCYmT&aQ`Q_k<18@8+Ik_(?mt&5%|>ytUa7kea?O44b?Ybp z!T~5Lvlo6{<4>#-6Qz>*@ar^bFh>@w5?#0dD*GmgVRW?77Y=-8*?OIe~kJzO&(GA)a=(_ zV~&qg0b{bhW3q9huR-@?=yLfXs`*}B^N&EOn$IAoJYJ-m0p^dLH*eMEM_lvgkV82i z(u%+SgTyaVFv@B-WyM1<9?d-g<;V;4D`Xp%Y2S~zg+{2*sa&2+=zOMfCpkNwn@0AS zk@cMG30dhlnUBfRk2OQBs(giXqq#}w5GyjF=MBx7?0`z@_ zl4-}|DWf-?N*EbC{V6*wI+KR}o`jtIaswOeKsmjIv1EUHHn(5=iNcy3h7nB;G3lqy@S{{ zhZhjQe&8fL?DPj5P|=(2=KZy zUS~$%gDBBjHcI$fqLQ9GEY#uxT3Cs+Oo6+ejn-{aqR&H=mMajvu8r48v;OUKr4*SQ z)r-h@ZP*c=;d#ett>-msr**l!rinnhv`rcadSL6mrn*;Psu z6PjRtS~rB-o!54}){N`FPV;Q{_mVn4R3|BXX_M!BM3;vTI#TAiW11)BL9KsB%X}WX z`2QO4dToD!&H8$WHSW}Szs3QL!x|?v9?^JIV_xI5#u<%s8vXUYms}rK7TdRM*=XFf zw>z73vPMfws5R8w)RL8A%R_6|hMHS%*7UzFk>WmIyd}T)AKg7M$zb9Bni&YeAvg|s(HTeAj;H<-x}OCjbSBozt}7J54iV{(h9l0l&O+dqv=rS?}lucNY@E5#$%a|!3MQaSWVxJFzh{QYW5x?SO}qvuk7A?=sC_b2mn z$oNi4sum(31{-RO9$_X}ih3cCp~+9`pOFloPMQ zKU9T(v#uN1cu_(t^4 zrD192{v4C`jqZM&8?|OW9=K%hk7pzJ%b|HyS0djv!Dor&-D2I$jaB&DtMFY_`1`<9 z9Q^Hxfj8XR&SyrzuRJfhxvzk~ycYi*eb2G467O1hGP`@yPD?0-mFJP}nB_$J1c;22 z?d=Wqi1Vw|Ehk}NEqv0>z%rV$`r@hXNZg7#sdUDQWCul0DlrhZ9XlFou53YT@MBga zosJAycuAQa620k2!nUH>L}Cao9?62GQ)a5(siH-ewQX1Xjt;Bi&aD>K$8X(#XZw!M zEugXC!|E`#*4(;FSlheq+T7k{-L-Ao?v6dyp7zaM9q{lk`VaFe{r6azPrCtJTUyaC zHxZOEmK}{a5g|`hZy6}l%bf#djM`~XM#&8aWejauC?jwIP>v8!T0gpw)84)rCop@DP? zC*TZusP1eGTa#i@O|@_CY@)6&&HE#nei4ceB~gV!C#^Jit)Ib*`7*(RE^WsnyW?_}*CXTg z_wTEt?+o6={~ws6@ru`<$4iU`8*23X-vjs)deoc#UWGJTW&+`<=5o0G1h#`urQ&PvbN@YGgmg z@A&+AKQiMjzKI+Aaj`G?{CRxI$n$Ns_s8#h+Mln#Ftnw{Ni8z)^<(*m$WZ**f6`DI z##SY|zyA7v360l(#!#k=?^XX9m@mS?Vd8ypybspjUX~f(f^UPzpWidw-vkng?UZz0 zX8v6$sPA(9Ja6HB&Afk^o*$IhkFVo1;OP9>pWid=TSL}DOe%1H*`M(uID7p?SerI0 z -#include -#include -#include -#include -#include - -#define PORT 8080 -int main(int argc, char const *argv[]) -{ - int server_fd, new_socket; - long valread; - struct sockaddr_in address; - int addrlen = sizeof(address); - - char *hello = "Hello from server"; - - // Creating socket file descriptor - if ((server_fd = socket(AF_INET, SOCK_STREAM, 0)) == 0) - { - perror("In socket"); - exit(EXIT_FAILURE); - } - - address.sin_family = AF_INET; - address.sin_addr.s_addr = INADDR_ANY; - address.sin_port = htons(PORT); - - memset(address.sin_zero, '\0', sizeof address.sin_zero); - - if (bind(server_fd, (struct sockaddr *)&address, sizeof(address)) < 0) - { - perror("In bind"); - exit(EXIT_FAILURE); - } - if (listen(server_fd, 10) < 0) - { - perror("In listen"); - exit(EXIT_FAILURE); - } - while (1) - { - printf("\n+++++++ Waiting for new connection ++++++++\n\n"); - if ((new_socket = accept(server_fd, (struct sockaddr *)&address, - (socklen_t *)&addrlen)) < 0) - { - perror("In accept"); - exit(EXIT_FAILURE); - } - - char buffer[30000] = { 0 }; - valread = read(new_socket, buffer, 30000); - printf("%s\n", buffer); - write(new_socket, hello, strlen(hello)); - printf("------------------Hello message sent-------------------\n"); - close(new_socket); - } - return 0; -} From b5dba5047746e096901fbc33599e94a5302cfb5d Mon Sep 17 00:00:00 2001 From: Samih Date: Sat, 6 Jan 2024 04:05:54 +0400 Subject: [PATCH 019/215] notes(notes_effectivecpp): Add notes file --- resources/notes/notes_effectivecpp | 42 ++++++++++++++++++++++++++++++ 1 file changed, 42 insertions(+) create mode 100644 resources/notes/notes_effectivecpp diff --git a/resources/notes/notes_effectivecpp b/resources/notes/notes_effectivecpp new file mode 100644 index 0000000..d07f0ce --- /dev/null +++ b/resources/notes/notes_effectivecpp @@ -0,0 +1,42 @@ +------- [GENERAL] ----------- + +[1] It is preferable to use the compiler instead of the preprocessor. +use static/const instead of defines because: + 1 - They are easier to debug. + 2 - They occupy less memory. + +------- [OOP] ----------- + +[1] Liskov substitution principle +If D is a derived class of B (sub-class of B) then objects of D maybe replaced with B without breaking the program + +Upholding the Liskov Substitution Principle (LSP) is important for several key reasons, especially in the context of object-oriented programming and system design: + +Maintains Polymorphism: + +Correctness: The primary reason for LSP is to ensure that a derived class can stand in for its base class without altering the correctness and expected behavior of the program. This is fundamental to polymorphism, allowing objects of different classes to be treated interchangeably. +Flexibility: By adhering to LSP, you can write more flexible and reusable code. Functions and systems that operate on base class references can seamlessly work with any subclass, leading to code that's easier to extend and maintain. +Improves Code Quality and Integrity: + +Reliability: Upholding LSP means that changes in the derived classes won't introduce unexpected bugs or behaviors in the parts of the code that use the base class. This makes the system more reliable and robust. +Understandability: When LSP is upheld, other developers can have clear expectations of the class hierarchy and how different classes relate and behave. This makes the code easier to understand, use, and debug. +Facilitates Refactoring and Extension: + +Easier Refactoring: Adhering to LSP makes it easier to refactor and improve the system without worrying about breaking existing functionality. You can introduce new subclasses or modify existing ones with the confidence that the overall system behavior remains consistent. +Easier Extension: If you want to extend the system by adding new subclasses or behaviors, LSP ensures that these extensions will integrate smoothly without requiring changes to the existing client code. +Reduces Tight Coupling: + +Decoupling: LSP encourages a design where classes are less tightly coupled and more independent in their behavior. This decoupling means that changes in one part of the system are less likely to require changes in other parts, reducing the ripple effect of modifications. +Supports Good Design Principles: + +Support for Other Principles: LSP is not just an isolated principle but supports and is supported by other key principles of object-oriented design like the Open/Closed Principle (classes should be open for extension but closed for modification) and the Single Responsibility Principle (a class should have only one reason to change). Together, these principles lead to a more robust, maintainable, and scalable system. +In summary, upholding the Liskov Substitution Principle is crucial for creating flexible, maintainable, and reliable software systems. It ensures that inheritance, a fundamental aspect of object-oriented programming, is used correctly to create hierarchies that behave predictably and intuitively. Without adherence to LSP, systems can become brittle, confusing, and prone to errors, making development and maintenance more difficult and risky. + +[2] Avoid name hiding +Function overrides (use "using foo;" in inherited class to also inherit overrided functions) + +- Names in derived classes hide names in base classes. Under public +inheritance, THIS IS NEVER DESIRABLE. + +-To make hidden names visible again, employ using declarations or +forwarding functions. From efcadc21aa21de89c172b30d7b48277f4fb20b89 Mon Sep 17 00:00:00 2001 From: Samih Date: Sat, 6 Jan 2024 04:06:21 +0400 Subject: [PATCH 020/215] build(Makefile): Add `test_server` and `TEST_main.cpp` - Add unit tester files for server part --- ver-01.1/Makefile | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/ver-01.1/Makefile b/ver-01.1/Makefile index bfea5ae..36dd684 100644 --- a/ver-01.1/Makefile +++ b/ver-01.1/Makefile @@ -11,6 +11,7 @@ SRCS:= Socket.cpp TCPSocket.cpp Server.cpp # tester mains TEST_SOCK:= $(SRCS_DIR)/SOCKET_main.cpp +TEST_SERVER:= $(SRCS_DIR)/SERVER_main.cpp OBJS_DIR:= objs OBJS:= $(SRCS:%.cpp=$(OBJS_DIR)/%.o) @@ -38,14 +39,18 @@ $(OBJS_DIR): test_socket: $(TEST_SOCK) debug $(CXX) $(CXXFLAGS) $(INCLUDES) -fsanitize=address $(TEST_SOCK) $(NAME) -o $@ +test_server: $(TEST_SOCK) debug + $(CXX) $(CXXFLAGS) $(INCLUDES) -fsanitize=address $(TEST_SERVER) $(NAME) -o $@ + clean: $(RM) $(OBJS_DIR) fclean: clean $(RM) $(NAME) $(RM) test_socket + $(RM) test_server re: fclean all -.PHONY: clean fclean all re test_socket +.PHONY: clean fclean all re test_socket test_server From 832a3ab1ff5c679109c8d122f84a3b26187cddd5 Mon Sep 17 00:00:00 2001 From: Samih Date: Sat, 6 Jan 2024 04:07:29 +0400 Subject: [PATCH 021/215] feat(Server.hpp): Add function prototypes - Moved the recv, send, and getpeer function prototypes to be part of the server's implementation --- ver-01.1/includes/Server.hpp | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/ver-01.1/includes/Server.hpp b/ver-01.1/includes/Server.hpp index 3d2baf0..7b9a97b 100644 --- a/ver-01.1/includes/Server.hpp +++ b/ver-01.1/includes/Server.hpp @@ -1,4 +1,4 @@ -#include +#include #include #ifndef SERVER_HPP @@ -8,7 +8,6 @@ // simple singleton implementation class Server { - protected: Server(){}; Server(const Server &){}; @@ -22,10 +21,16 @@ class Server // when its first created static Server &getInstance(); // void start(); - ~Server(); + ~Server(){}; + // member functions + // void recv(const char *buff); + // void send(const char *msg); + // void getpeer(struct sockaddr &address); + + + TCPSocket listener; private: - // Socket listener; int status; std::vector conn; }; From d03a82a04641995fbbf1a85214eb5c93461f1d27 Mon Sep 17 00:00:00 2001 From: Samih Date: Sat, 6 Jan 2024 04:10:37 +0400 Subject: [PATCH 022/215] feat(TCPSocket.hpp): Add static constant variables, and set_port() - Add famliy and type static constant variable members, to TCPSocket these are used to pass to Socket base class constructor, in order to create an appropriate type socket. - The set_port() functionality could be removed later on, as it doesn't adhere to LSP, for now it's used to set a specific port for later bind() calls. --- ver-01.1/includes/TCPSocket.hpp | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/ver-01.1/includes/TCPSocket.hpp b/ver-01.1/includes/TCPSocket.hpp index 7ab4bdc..1ce28b0 100644 --- a/ver-01.1/includes/TCPSocket.hpp +++ b/ver-01.1/includes/TCPSocket.hpp @@ -1,19 +1,26 @@ #include #include +// is-a inheritance relationship, every TCPSocket is a Socket #ifndef TCPSOCKET_HPP #define TCPSOCKET_HPP +// a non-blocking SOCK_STREAM, TCP(IP4) socket bound to port class TCPSocket : public Socket { public: TCPSocket(); + void set_port(int port) throw(); ~TCPSocket(); private: TCPSocket(const TCPSocket &); TCPSocket &operator=(const TCPSocket &); + + // TCPSocket parameters + static const int family = AF_INET; + static const int type = SOCK_STREAM; }; #endif // TCPSOCKET_HPP From c7860642917c6b0f256bc514209b172f36f70d4c Mon Sep 17 00:00:00 2001 From: Samih Date: Sat, 6 Jan 2024 04:15:04 +0400 Subject: [PATCH 023/215] feat(TCPSocket.cpp): Add member function implementations - Add default constructor implementations, that preps the sockaddr_in struct, with the pre-defined constant variables for the TCPSocket class - Add set_port() function implementation --- ver-01.1/srcs/TCPSocket.cpp | 27 ++++++++++++++++++++++++--- 1 file changed, 24 insertions(+), 3 deletions(-) diff --git a/ver-01.1/srcs/TCPSocket.cpp b/ver-01.1/srcs/TCPSocket.cpp index 803f471..51d8a65 100644 --- a/ver-01.1/srcs/TCPSocket.cpp +++ b/ver-01.1/srcs/TCPSocket.cpp @@ -1,10 +1,31 @@ #include "TCPSocket.hpp" +#include +#include TCPSocket::TCPSocket() - : Socket(AF_INET, SOCK_STREAM, 0, SOCK_NONBLOCK) -{} + : Socket(family, type, 0, SOCK_NONBLOCK) +{ + // zero out the sockaddr struct before copying + std::memset(&address, 0, sizeof(address)); + struct sockaddr_in addr; + + // prep up the struct + addr.sin_addr.s_addr = htonl(INADDR_ANY); + addr.sin_family = family; + std::memcpy(&address, &addr, sizeof(addr)); +} + +void TCPSocket::set_port(int port) throw() +{ + std::memset(&address, 0, sizeof(address)); + struct sockaddr_in addr; + addr.sin_port = htons(port); + std::memcpy(&address, &addr, sizeof(addr)); +} TCPSocket::~TCPSocket() { - // destructor code +#ifdef __DEBUG__ + std::cerr << "TCPSocket closed!!\n"; +#endif // __DEBUG__ } From 5046e75c87fed941a2ce814efaa0bb100632b64b Mon Sep 17 00:00:00 2001 From: Samih Date: Sat, 6 Jan 2024 04:18:51 +0400 Subject: [PATCH 024/215] chore(Socket.hpp): Modify TODO list --- ver-01.1/includes/Socket.hpp | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/ver-01.1/includes/Socket.hpp b/ver-01.1/includes/Socket.hpp index 34dd3f9..ebb5987 100644 --- a/ver-01.1/includes/Socket.hpp +++ b/ver-01.1/includes/Socket.hpp @@ -10,12 +10,11 @@ // TODO // [P]artially implemented, needs [I]mprovement, [X] done // -// [ ] Derived TCP class to lock domain, type .. combinations // [ ] split-up function implementations into their own files +// [I] make a unit-tester main // [ ] add shutdown functionality (block recv, block send, close()) -// [P] make a unit-tester main -// [X] error checking functions for domain, type, protocol ... etc -// [X] better error messages, and error handling,custom exception class +// [ ] fix the get_fd functionality is it really necessary +// [ ] set_port function in TCP makes it not a is-a relation-ship #ifndef SOCKET_HPP #define SOCKET_HPP From e1ec0cbc1c71951e61165685ac1c1a977eedaada Mon Sep 17 00:00:00 2001 From: Samih Date: Sat, 6 Jan 2024 04:19:42 +0400 Subject: [PATCH 025/215] fix(Socket.hpp): Fix compose_msg() output - Fixed compose_msg() to only show ": " if `errno` was set. - Add some more error messages constants --- ver-01.1/includes/Socket.hpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/ver-01.1/includes/Socket.hpp b/ver-01.1/includes/Socket.hpp index ebb5987..127039f 100644 --- a/ver-01.1/includes/Socket.hpp +++ b/ver-01.1/includes/Socket.hpp @@ -35,7 +35,10 @@ static std::string ERR_NULL("Socket: null ptr error"); static std::string ERR_CREAT("Socket: creation failed"); static std::string ERR_BIND("Socket: binding failed"); +static std::string ERR_NBIND("Socket: not bound to a port"); static std::string ERR_LIST("Socket: listen failed"); +static std::string ERR_NLIST("Socket: not listeing"); +static std::string ERR_ACCP("Socket: accept failed"); // socket_descriptor type typedef int file_descriptor; @@ -82,7 +85,8 @@ class Socket static std::string compose_msg(const std::string &message) { std::stringstream _msg; - _msg << message << (errno ? std::strerror(errno) : ""); + _msg << message + << (errno ? ": " + std::string(std::strerror(errno)) : ""); return _msg.str(); } const char *what() const throw() From f1d0358ae29c1b53f070657c12ecefd36acc27e6 Mon Sep 17 00:00:00 2001 From: Samih Date: Sat, 6 Jan 2024 04:21:37 +0400 Subject: [PATCH 026/215] fix(Socket.hpp): Change Socket class interface - Add struct sockaddr as a member - Move send(), recv(), and getpeer() functions to Server class - Add state checks bool, is_connected, and is_listening - remove type and family variables to derived class TCP --- ver-01.1/includes/Socket.hpp | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/ver-01.1/includes/Socket.hpp b/ver-01.1/includes/Socket.hpp index 127039f..19ee3be 100644 --- a/ver-01.1/includes/Socket.hpp +++ b/ver-01.1/includes/Socket.hpp @@ -49,10 +49,11 @@ class Socket protected: // protected constructors only in derived classes /* [CONSTRUCTORS] */ - Socket(int domain, int type, int protocol, int flags); + Socket(int family, int type, int protocol, int flags); // maybe not necessary - Socket(int domain, int type, const char *protocol_name, int flags); - + Socket(int family, int type, const char *protocol_name, int flags); + // only used by inherited class + struct sockaddr address; // type casted and set based on type of socket public: /* [DESTRUCTOR] */ @@ -60,14 +61,12 @@ class Socket /* [INTERFACE] */ - void bind(int port); - // void connect(); - void listen(int backlog); - // void accept(); - // void send(const char *msg); - // void recv(const char *buff); - // void getpeer(struct sockaddr &address); + void bind() const; // item36: never re-define an inherited non-virtual function + void listen(int backlog) const; + file_descriptor accept(); + file_descriptor get_fd() const; // void shutdown(int option); + // void connect(); // is something you do on a client /* [ERROR HANDLING] */ @@ -100,8 +99,9 @@ class Socket static const int invalid_file_descriptor = -1; file_descriptor socket_descriptor; - int family; // domain of communicatoin - int type; // type of socket + // state checks + mutable bool is_bound; + mutable bool is_listening; // deleted but can't cause is 98 maguy Socket(const Socket &){}; From 66ba935efa0318822febd12a16df992d5939c6d1 Mon Sep 17 00:00:00 2001 From: Samih Date: Sat, 6 Jan 2024 04:24:04 +0400 Subject: [PATCH 027/215] feat(ClientTest.cpp): Add a simple Client for testing purposes --- ver-01.1/srcs/ClientTest.cpp | 58 ++++++++++++++++++++++++++++++++++++ 1 file changed, 58 insertions(+) create mode 100644 ver-01.1/srcs/ClientTest.cpp diff --git a/ver-01.1/srcs/ClientTest.cpp b/ver-01.1/srcs/ClientTest.cpp new file mode 100644 index 0000000..5e76389 --- /dev/null +++ b/ver-01.1/srcs/ClientTest.cpp @@ -0,0 +1,58 @@ +#include +#include +#include +#include +#include +#include +#include +#include + +int main() +{ + int sockfd = socket(AF_INET, SOCK_STREAM, 0); + if (sockfd == -1) + { + std::cerr << "Failed to create socket. errno: " << errno << std::endl; + exit(EXIT_FAILURE); + } + + sockaddr_in sockaddr; + memset(&sockaddr, 0, sizeof(sockaddr)); + sockaddr.sin_family = AF_INET; + sockaddr.sin_port = htons(8080); // Connecting to port 8080 + if (inet_pton(AF_INET, "127.0.0.1", &sockaddr.sin_addr) <= 0) + { + std::cerr << "Invalid address/ Address not supported" << std::endl; + exit(EXIT_FAILURE); + } + + // Connect to the server + if (connect(sockfd, (struct sockaddr *)&sockaddr, sizeof(sockaddr)) < 0) + { + std::cerr << "Connection Failed. errno: " << errno << std::endl; + exit(EXIT_FAILURE); + } + + // Send a message to the server + const char *message = "Hello from the client!"; + if (send(sockfd, message, strlen(message), 0) < 0) + { + std::cerr << "Failed to send the message. errno: " << errno << std::endl; + exit(EXIT_FAILURE); + } + std::cout << "Message sent to server successfully." << std::endl; + + // Receive a response back from the server + char buffer[1024] = { 0 }; + ssize_t bytesReceived = recv(sockfd, buffer, sizeof(buffer), 0); + if (bytesReceived < 0) + { + std::cerr << "Failed to receive the message. errno: " << errno << std::endl; + exit(EXIT_FAILURE); + } + std::cout << "Server's response: " << std::string(buffer, bytesReceived) << std::endl; + + // Close the connection + close(sockfd); + return 0; +} From cbf545ac0cd8c3b636ee42a52fa4254d5eb14ca5 Mon Sep 17 00:00:00 2001 From: Samih Date: Sat, 6 Jan 2024 04:24:33 +0400 Subject: [PATCH 028/215] feat(SERVER_main.cpp): Add unit test file `Server` --- ver-01.1/srcs/SERVER_main.cpp | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 ver-01.1/srcs/SERVER_main.cpp diff --git a/ver-01.1/srcs/SERVER_main.cpp b/ver-01.1/srcs/SERVER_main.cpp new file mode 100644 index 0000000..81044f7 --- /dev/null +++ b/ver-01.1/srcs/SERVER_main.cpp @@ -0,0 +1,6 @@ +#include + +int main() +{ + std::cout << "hello world!"; +} From 1d8fb03dd61eda51af7736e6aecc2e89553a75a5 Mon Sep 17 00:00:00 2001 From: Samih Date: Sat, 6 Jan 2024 04:25:29 +0400 Subject: [PATCH 029/215] feat(SOCKET_main): Simple server implementation - To test socket functionalities --- ver-01.1/srcs/SOCKET_main.cpp | 65 +++++++++++++++++++++++++++++++---- 1 file changed, 59 insertions(+), 6 deletions(-) diff --git a/ver-01.1/srcs/SOCKET_main.cpp b/ver-01.1/srcs/SOCKET_main.cpp index 69bc284..0c63c27 100644 --- a/ver-01.1/srcs/SOCKET_main.cpp +++ b/ver-01.1/srcs/SOCKET_main.cpp @@ -1,18 +1,71 @@ #include "TCPSocket.hpp" +#include #include #include #include // Socket tester main add test cases here to test the behaviour of the // class + +#include + +#if 1 int main() { - try - { - TCPSocket a; - } - catch (std::exception &e) + // make a listening socket + TCPSocket a; + Socket *b = &a; + // prep it to accept connections on port 8080 + a.set_port(8080); // oh-o !!! + b->bind(); + + // set it to listen with backlog 25 + b->listen(5); + + fd_set read_fds; + int fdmax = b->get_fd(); + + while (true) { - std::cerr << e.what(); + + std::cout << "---------- Server is up and waiting!!! ----------------" + << std::endl; + FD_ZERO(&read_fds); + FD_SET(b->get_fd(), &read_fds); + + if (select(fdmax + 1, &read_fds, NULL, NULL, NULL) == -1) + { + std::cerr << "Error with select" << std::endl; + continue; + } + + if (FD_ISSET(b->get_fd(), &read_fds)) + { + // accept if a connection happens + file_descriptor peer = b->accept(); + std::cout << "peer is connected on port " << peer << "\n"; + + // receive data from the connected peer + char buffer[1024]; + ssize_t bytesRead = recv(peer, buffer, sizeof(buffer), 0); + if (bytesRead == -1) + { + std::cerr << "Error receiving data from peer" << std::endl; + continue; + } + + // process the received data + std::string receivedData(buffer, bytesRead); + std::cout << "Received data from peer: " << receivedData << std::endl; + + // send a response back to the peer + std::string response = "Hello from the server!"; + ssize_t bytesSent = send(peer, response.c_str(), response.length(), 0); + if (bytesSent == -1) + { + std::cerr << "Error sending"; + } + } } } +#endif // TCPSocket From 366ffec0396180cb901a5ba46613ab2ebf21472f Mon Sep 17 00:00:00 2001 From: Samih Date: Sat, 6 Jan 2024 04:30:51 +0400 Subject: [PATCH 030/215] feat(Socket.cpp): Add bool checks - Add is_bound and is_listening checks to function implementations --- ver-01.1/srcs/Socket.cpp | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/ver-01.1/srcs/Socket.cpp b/ver-01.1/srcs/Socket.cpp index 01f2215..171bddb 100644 --- a/ver-01.1/srcs/Socket.cpp +++ b/ver-01.1/srcs/Socket.cpp @@ -1,4 +1,5 @@ #include "Socket.hpp" +#include #include #include #include /* superset of previous */ @@ -10,8 +11,8 @@ Socket::Socket(int family, int type, int protocol, int flags) : socket_descriptor(invalid_file_descriptor) - , family(family) - , type(type) + , is_bound(false) + , is_listening(false) { socket_descriptor = socket(family, type | flags, protocol); @@ -27,6 +28,8 @@ Socket::Socket(int family, int type, int protocol, int flags) /* Call protocol by name */ Socket::Socket(int family, int type, const char *protocol_name, int flags) : socket_descriptor(invalid_file_descriptor) + , is_bound(false) + , is_listening(false) { if (!protocol_name) throw Socket::Exception(Exception::compose_msg(ERR_NULL)); @@ -92,12 +95,20 @@ void Socket::bind(int port) int status = ::bind(socket_descriptor, (struct sockaddr *)&addr, sizeof(addr)); if (status == -1) throw Socket::Exception(Exception::compose_msg(ERR_BIND)); + is_bound = true; +#ifdef __DEBUG__ + std::cerr << "Socket was bound successfully to port[" + << ntohs(((struct sockaddr_in *)&address)->sin_port) << "]\n"; +#endif // __DEBUG__ } void Socket::listen(int backlog) { + if (!is_bound) + throw Socket::Exception(Exception::compose_msg(ERR_NBIND)); // global namespace to avoid conflict int status = ::listen(socket_descriptor, backlog); if (status == -1) throw Socket::Exception(Exception::compose_msg(ERR_LIST)); + is_listening = true; } From 6cde8ceb3c25578f21742ee2d93a433dcea94335 Mon Sep 17 00:00:00 2001 From: Samih Date: Sat, 6 Jan 2024 04:32:08 +0400 Subject: [PATCH 031/215] feat(Socket.cpp): Add get_fd() function --- ver-01.1/srcs/Socket.cpp | 13 +++---------- 1 file changed, 3 insertions(+), 10 deletions(-) diff --git a/ver-01.1/srcs/Socket.cpp b/ver-01.1/srcs/Socket.cpp index 171bddb..fb08dbf 100644 --- a/ver-01.1/srcs/Socket.cpp +++ b/ver-01.1/srcs/Socket.cpp @@ -80,17 +80,10 @@ Socket::~Socket() /* [INTERFACE] */ -void Socket::bind(int port) +file_descriptor Socket::get_fd() const { - // this has to be created based on the type of socket - struct sockaddr_in addr; - - // zero out the sockaddr struct - memset(&addr, 0, sizeof(addr)); - // same for these filled they are determined based on the family type - addr.sin_addr.s_addr = htonl(INADDR_ANY); - addr.sin_family = family; - addr.sin_port = htons(port); + return socket_descriptor; +} int status = ::bind(socket_descriptor, (struct sockaddr *)&addr, sizeof(addr)); if (status == -1) From 277fa83755efab544de1ed0c7fca3ad3d59b1127 Mon Sep 17 00:00:00 2001 From: Samih Date: Sat, 6 Jan 2024 04:34:00 +0400 Subject: [PATCH 032/215] fix(Socket.cpp): output debug messages to cerr --- ver-01.1/srcs/Socket.cpp | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/ver-01.1/srcs/Socket.cpp b/ver-01.1/srcs/Socket.cpp index fb08dbf..3af2268 100644 --- a/ver-01.1/srcs/Socket.cpp +++ b/ver-01.1/srcs/Socket.cpp @@ -19,9 +19,10 @@ Socket::Socket(int family, int type, int protocol, int flags) // On success, a file descriptor for the new socket is returned. if (socket_descriptor == invalid_file_descriptor) throw Socket::Exception(Exception::compose_msg(ERR_CREAT)); + #ifdef __DEBUG__ else - std::cout << "Socket was created successfully fd[" << socket_descriptor << "]\n"; + std::cerr << "Socket was created successfully fd[" << socket_descriptor << "]\n"; #endif // __DEBUG__ } @@ -46,7 +47,7 @@ Socket::Socket(int family, int type, const char *protocol_name, int flags) throw Socket::Exception(Exception::compose_msg(ERR_NULL)); #ifdef __DEBUG__ - std::cout << "protocol official name is [" << protocol->p_name << "]\n"; + std::cerr << "protocol official name is [" << protocol->p_name << "]\n"; #endif // __DEBUG__ socket_descriptor = socket(family, type | flags, protocol->p_proto); @@ -57,7 +58,7 @@ Socket::Socket(int family, int type, const char *protocol_name, int flags) #ifdef __DEBUG__ else - std::cout << "Socket was created successfully fd[" << socket_descriptor << "]\n"; + std::cerr << "Socket was created successfully fd[" << socket_descriptor << "]\n"; #endif // __DEBUG__ } @@ -65,16 +66,15 @@ Socket::Socket(int family, int type, const char *protocol_name, int flags) Socket::~Socket() { +#ifdef __DEBUG__ + std::cerr << "socket fd[" << socket_descriptor << "] closed!!\n"; +#endif // __DEBUG__ if (socket_descriptor != invalid_file_descriptor) { close(socket_descriptor); // invalidate the filedescriptor socket_descriptor = invalid_file_descriptor; } -#ifdef __DEBUG__ - else - std::cerr << "socket fd[" << socket_descriptor << "] closed!!\n"; -#endif // __DEBUG__ } From 30a0b2a69aca6c8c1b7ab89e801b020a6befb18e Mon Sep 17 00:00:00 2001 From: Samih Date: Sat, 6 Jan 2024 04:36:33 +0400 Subject: [PATCH 033/215] fix(Socket.cpp): Add const modifier to listen and bind --- ver-01.1/srcs/Socket.cpp | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/ver-01.1/srcs/Socket.cpp b/ver-01.1/srcs/Socket.cpp index 3af2268..ca4c239 100644 --- a/ver-01.1/srcs/Socket.cpp +++ b/ver-01.1/srcs/Socket.cpp @@ -85,7 +85,9 @@ file_descriptor Socket::get_fd() const return socket_descriptor; } - int status = ::bind(socket_descriptor, (struct sockaddr *)&addr, sizeof(addr)); +void Socket::bind() const +{ + int status = ::bind(socket_descriptor, (struct sockaddr *)&address, sizeof(address)); if (status == -1) throw Socket::Exception(Exception::compose_msg(ERR_BIND)); is_bound = true; @@ -95,7 +97,7 @@ file_descriptor Socket::get_fd() const #endif // __DEBUG__ } -void Socket::listen(int backlog) +void Socket::listen(int backlog) const { if (!is_bound) throw Socket::Exception(Exception::compose_msg(ERR_NBIND)); @@ -104,4 +106,11 @@ void Socket::listen(int backlog) if (status == -1) throw Socket::Exception(Exception::compose_msg(ERR_LIST)); is_listening = true; + +#ifdef __DEBUG__ + std::cerr << "Socket listen was successful, [" << socket_descriptor + << "] is now ready to accept max backlog of [" << backlog + << "] connections\n"; +#endif // __DEBUG__ +} } From 1bf0928db36a7072c48ab1edaeb9835bd5389b50 Mon Sep 17 00:00:00 2001 From: Samih Date: Sat, 6 Jan 2024 04:37:43 +0400 Subject: [PATCH 034/215] feat(Socket.cpp): Add accept function - Function to accept incoming connections, returns a new socket specifically for the established connection --- ver-01.1/srcs/Socket.cpp | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/ver-01.1/srcs/Socket.cpp b/ver-01.1/srcs/Socket.cpp index ca4c239..42f9063 100644 --- a/ver-01.1/srcs/Socket.cpp +++ b/ver-01.1/srcs/Socket.cpp @@ -113,4 +113,35 @@ void Socket::listen(int backlog) const << "] connections\n"; #endif // __DEBUG__ } + + +file_descriptor Socket::accept() +{ + // check if socket is listening + if (!is_listening) + throw Socket::Exception(Exception::compose_msg(ERR_NLIST)); + // This structure is filled in with the address of the peer socket, + // as known to the communications layer. + struct sockaddr peer_info; // does this need to be stored? + socklen_t peer_length = sizeof(peer_info); + // The accept() system call is used with connection-based socket types (SOCK_STREAM, + // SOCK_SEQPACKET). + // it extracts the first pending connection request in the backlog que form listen. + // creates a new connected socket, and returns a new file descriptor + file_descriptor connected_socket; + connected_socket = ::accept(socket_descriptor, &peer_info, &peer_length); + if (connected_socket == invalid_file_descriptor) + { + // if set to non_blocking it returns EAGAIN or EWOULDBLOCK if no connection + if (errno != EAGAIN && errno != EWOULDBLOCK) + throw Socket::Exception(Exception::compose_msg(ERR_ACCP)); +#ifdef __DEBUG__ + else + std::cerr << "Socket has no incoming connections \n"; +#endif // __DEBUG__ + } +#ifdef __DEBUG__ + std::cerr << "Socket accepted a connection from \n"; +#endif // __DEBUG__ + return connected_socket; } From efc71894e159f63180f18f7d0966f3dc5eb4289c Mon Sep 17 00:00:00 2001 From: Samih Date: Sat, 6 Jan 2024 04:39:33 +0400 Subject: [PATCH 035/215] fix(Socket.cpp): Zero out the sockaddr struct in constructor --- ver-01.1/srcs/Socket.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/ver-01.1/srcs/Socket.cpp b/ver-01.1/srcs/Socket.cpp index 42f9063..eb98a40 100644 --- a/ver-01.1/srcs/Socket.cpp +++ b/ver-01.1/srcs/Socket.cpp @@ -24,6 +24,9 @@ Socket::Socket(int family, int type, int protocol, int flags) else std::cerr << "Socket was created successfully fd[" << socket_descriptor << "]\n"; #endif // __DEBUG__ + + // zero out the sockaddr struct + memset(&address, 0, sizeof(address)); } /* Call protocol by name */ @@ -60,6 +63,9 @@ Socket::Socket(int family, int type, const char *protocol_name, int flags) else std::cerr << "Socket was created successfully fd[" << socket_descriptor << "]\n"; #endif // __DEBUG__ + + // zero out the sockaddr struct + memset(&address, 0, sizeof(address)); } /* [DESTRUCTOR] */ From 91ceb434b29a00e63f3a28be5d57159ad7049662 Mon Sep 17 00:00:00 2001 From: Samih Date: Sat, 6 Jan 2024 05:05:35 +0400 Subject: [PATCH 036/215] notes(RFCGuide): Add a guide to important pages on the RFC --- resources/notes/notes_RFCguide | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) create mode 100644 resources/notes/notes_RFCguide diff --git a/resources/notes/notes_RFCguide b/resources/notes/notes_RFCguide new file mode 100644 index 0000000..67a724d --- /dev/null +++ b/resources/notes/notes_RFCguide @@ -0,0 +1,32 @@ +Networking Basics: +1 Sockets Programming Documentation: Direct Implementation +2 RFC 791 - Internet Protocol (IP): Basic Understanding +3 RFC 793 - Transmission Control Protocol (TCP): Basic Understanding + +HTTP Core: +1 RFC 7230 - Hypertext Transfer Protocol (HTTP/1.1): Message Syntax and Routing: Direct Implementation +2 RFC 7231 - Hypertext Transfer Protocol (HTTP/1.1): Semantics and Content: Direct Implementation + +CGI (Common Gateway Interface): +1 RFC 3875 - The Common Gateway Interface (CGI) Version 1.1: Direct Implementation + +Advanced HTTP Features: +1 RFC 7232 - HTTP/1.1: Conditional Requests: Extra Understanding +2 RFC 7233 - HTTP/1.1: Range Requests: Extra Understanding +3 RFC 7234 - HTTP/1.1: Caching: Extra Understanding +4 RFC 7235 - HTTP/1.1: Authentication: Extra Understanding + +HTTP/2: +1 RFC 7540 - Hypertext Transfer Protocol Version 2 (HTTP/2): Direct Implementation +2 RFC 7541 - HPACK: Header Compression for HTTP/2: Extra Understanding + +Security (HTTPS): +1 RFC 8446 - The Transport Layer Security (TLS) Protocol Version 1.3: Basic Understanding + +Supporting Technologies: +1 RFC 2616 - MIME Part Two: Media Types: Basic Understanding +2 RFC 6265 - HTTP State Management Mechanism (Cookies): Extra Understanding +3 SSL/TLS Library Documentation (e.g., OpenSSL): Direct Implementation + +WebSockets (if needed): +1 RFC 6455 - The WebSocket Protocol: Extra Understanding From c6155c1195f7ed78cf790c4bac835c097a45a7a6 Mon Sep 17 00:00:00 2001 From: Samih Date: Sat, 6 Jan 2024 21:57:25 +0400 Subject: [PATCH 037/215] notes: Add IP notes and editing --- resources/notes/notes_RFC7230 | 2 +- resources/notes/notes_RFC791 | 76 ++++++++++++++++++++++++++++ resources/notes/notes_effectivecpp | 14 +++-- resources/notes/notes_starting_steps | 0 4 files changed, 86 insertions(+), 6 deletions(-) create mode 100644 resources/notes/notes_RFC791 delete mode 100644 resources/notes/notes_starting_steps diff --git a/resources/notes/notes_RFC7230 b/resources/notes/notes_RFC7230 index 20a8dc7..0411ae3 100644 --- a/resources/notes/notes_RFC7230 +++ b/resources/notes/notes_RFC7230 @@ -1,4 +1,4 @@ -k MESSAGE SYNTAX AND ROUTING + MESSAGE SYNTAX AND ROUTING The HTTP protocol is defined in 6 RFC entries 7230-7235 diff --git a/resources/notes/notes_RFC791 b/resources/notes/notes_RFC791 new file mode 100644 index 0000000..5ce8d38 --- /dev/null +++ b/resources/notes/notes_RFC791 @@ -0,0 +1,76 @@ + INTERNET PROTOCOL + +The internet protocol is specifically limited in scope to provide the functions necessary to deliver a +package from a source to destination (datagrams). IP capitalizes on supporting network services to provide +other mechanisms for quality (reliability, flow control, sequencing ... etc).[TCP for example] + +---- [TAGS] ----- +(UNDERSTAND) : the ultimate goal +(REMEMBER) : good to remember aids understanding +(TODO) : incorporate this in project +----------------- + +(UNDERSTAND) Where it fits in the model? +A TCP module would call on internet module to take a TCP segment (packet of data after TCP added its headers) +this would become the data portion of an internet datagram. TCP would provide the address and other parameters +as arguments to the call to internet module. Internet module would then create a datagram and call the local network +interface to transmit the internet datagram. + + +------+ +-----+ +-----+ +-----+ + |Telnet| | FTP | | TFTP| ... | ... | + +------+ +-----+ +-----+ +-----+ + | | | | + +-----+ +-----+ +-----+ + | TCP | | UDP | ... | ... | + +-----+ +-----+ +-----+ + | | | + +--------------------------+----+ + | Internet Protocol & ICMP | + +--------------------------+----+ + | + +---------------------------+ + | Local Network Protocol | + +---------------------------+ + + +(REMEMBER) IP provides 2 basic functions: addressing and fragmentation + +(UNDERSTAND) Address is used to determine the destination. +Routing is how it gets there (determined by the next layer in the network). + +Internet modules, use fields in the IP header to fragment and reassembe datagrams when necessary. + +(UNDERSTAND) reconciling independance with fragmentation: +By independance here it means that each datagram (even if fragmented) travels to a destination independently, +might even take a different route. (each fragment contains fully formed header and can travel alone) +Fragmentation mechanisms means that the header implements mechanisms to +"put-back" those datagrams whenever its needed. + +IP uses four mechanisms in providing its services: + - Type of service: service choice provided in networks used to select transmission parameters, next network + when routing. + - Time to live: upper bound on the lifetime of a datagram. (self destruct timer) + - Options: timestamps, security, special routing (unnecessary for most common communications) + - Header Checksum: verification that header is correct, + note: for routing, destination ... etc not the data it self. + +(UNDERSTAND) The internet protocol does not provide a reliable communication facility. +There are no acknowledgments either end-to-end or hop-by-hop. +There is no error control for data, only a header checksum. +There are no retransmissions. +There is no flow control. + +(UNDERSTAND) A sample transmission path + +Application Application + Program Program + \ / + Internet Module Internet Module Internet Module + \ / \ / + LNI-1 LNI-1 LNI-2 LNI-2 + \ / \ / + Local Network 1 Local Network 2 + + + + diff --git a/resources/notes/notes_effectivecpp b/resources/notes/notes_effectivecpp index d07f0ce..558bde7 100644 --- a/resources/notes/notes_effectivecpp +++ b/resources/notes/notes_effectivecpp @@ -10,19 +10,24 @@ use static/const instead of defines because: [1] Liskov substitution principle If D is a derived class of B (sub-class of B) then objects of D maybe replaced with B without breaking the program -Upholding the Liskov Substitution Principle (LSP) is important for several key reasons, especially in the context of object-oriented programming and system design: +Upholding the Liskov Substitution Principle (LSP) is important for several key reasons: -Maintains Polymorphism: +*** MAINTAINS POLYMORPHISM *** + +Correctness: The primary reason is to ensure that a derived class can stand in for its base class without altering the correctness and expected behavior of the program. +This is fundamental to polymorphism, allowing objects of different classes to be treated interchangeably. -Correctness: The primary reason for LSP is to ensure that a derived class can stand in for its base class without altering the correctness and expected behavior of the program. This is fundamental to polymorphism, allowing objects of different classes to be treated interchangeably. Flexibility: By adhering to LSP, you can write more flexible and reusable code. Functions and systems that operate on base class references can seamlessly work with any subclass, leading to code that's easier to extend and maintain. -Improves Code Quality and Integrity: + +*** IMPROVES CODE QUALITY AND INTEGRITY *** Reliability: Upholding LSP means that changes in the derived classes won't introduce unexpected bugs or behaviors in the parts of the code that use the base class. This makes the system more reliable and robust. + Understandability: When LSP is upheld, other developers can have clear expectations of the class hierarchy and how different classes relate and behave. This makes the code easier to understand, use, and debug. Facilitates Refactoring and Extension: Easier Refactoring: Adhering to LSP makes it easier to refactor and improve the system without worrying about breaking existing functionality. You can introduce new subclasses or modify existing ones with the confidence that the overall system behavior remains consistent. + Easier Extension: If you want to extend the system by adding new subclasses or behaviors, LSP ensures that these extensions will integrate smoothly without requiring changes to the existing client code. Reduces Tight Coupling: @@ -30,7 +35,6 @@ Decoupling: LSP encourages a design where classes are less tightly coupled and m Supports Good Design Principles: Support for Other Principles: LSP is not just an isolated principle but supports and is supported by other key principles of object-oriented design like the Open/Closed Principle (classes should be open for extension but closed for modification) and the Single Responsibility Principle (a class should have only one reason to change). Together, these principles lead to a more robust, maintainable, and scalable system. -In summary, upholding the Liskov Substitution Principle is crucial for creating flexible, maintainable, and reliable software systems. It ensures that inheritance, a fundamental aspect of object-oriented programming, is used correctly to create hierarchies that behave predictably and intuitively. Without adherence to LSP, systems can become brittle, confusing, and prone to errors, making development and maintenance more difficult and risky. [2] Avoid name hiding Function overrides (use "using foo;" in inherited class to also inherit overrided functions) diff --git a/resources/notes/notes_starting_steps b/resources/notes/notes_starting_steps deleted file mode 100644 index e69de29..0000000 From 6c252b1bd0a94ee97e70c6869f82c4c2e18f026f Mon Sep 17 00:00:00 2001 From: Samih Date: Tue, 9 Jan 2024 09:16:40 +0400 Subject: [PATCH 038/215] fix(Server): Update the server interface --- ver-01.1/includes/Server.hpp | 12 ++++++------ ver-01.1/srcs/SERVER_main.cpp | 5 +++-- ver-01.1/srcs/Server.cpp | 25 ++++++++++++++----------- ver-01.1/srcs/TCPSocket.cpp | 6 +++++- 4 files changed, 28 insertions(+), 20 deletions(-) diff --git a/ver-01.1/includes/Server.hpp b/ver-01.1/includes/Server.hpp index 7b9a97b..57b9f27 100644 --- a/ver-01.1/includes/Server.hpp +++ b/ver-01.1/includes/Server.hpp @@ -9,7 +9,7 @@ class Server { protected: - Server(){}; + explicit Server(file_descriptor listener_port, int backlog); Server(const Server &){}; Server &operator=(const Server &) { @@ -19,7 +19,7 @@ class Server public: // this function needs to be static, as there won't be an instance of a Server // when its first created - static Server &getInstance(); + static Server &getInstance(file_descriptor listener_port, int backlog); // void start(); ~Server(){}; // member functions @@ -28,11 +28,11 @@ class Server // void getpeer(struct sockaddr &address); - TCPSocket listener; - private: - int status; - std::vector conn; + static file_descriptor listener_port; + TCPSocket listener; + int status; + std::vector conn; }; #endif // SERVER_HPP diff --git a/ver-01.1/srcs/SERVER_main.cpp b/ver-01.1/srcs/SERVER_main.cpp index 81044f7..b4c9048 100644 --- a/ver-01.1/srcs/SERVER_main.cpp +++ b/ver-01.1/srcs/SERVER_main.cpp @@ -1,6 +1,7 @@ -#include +#include int main() { - std::cout << "hello world!"; + Server &webserv = Server::getInstance(80, 10); + (void)webserv; } diff --git a/ver-01.1/srcs/Server.cpp b/ver-01.1/srcs/Server.cpp index 2332be1..dcfc4c4 100644 --- a/ver-01.1/srcs/Server.cpp +++ b/ver-01.1/srcs/Server.cpp @@ -1,6 +1,7 @@ #include "Server.hpp" #include #include +#include #include #include #include @@ -13,21 +14,22 @@ #include #endif // __DEBUG -Server &Server::getInstance() +Server &Server::getInstance(file_descriptor listener_port, int backlog) { // avoid creating another one - static Server instance; + static Server instance(listener_port, backlog); return instance; } -// // default constructor -// Server::Server() -// : listener{ -// Socket(AF_INET, SOCK_STREAM, IPPROTO_TCP, SOCK_NONBLOCK)) // start the -// listener -// , status(WS_OK) -// {} -// +// default constructor +Server::Server(int listener_port, int backlog) +{ + // setup the Server + listener.set_port(listener_port); + listener.bind(); + listener.listen(backlog); +} + // Server::~Server() // { // close(listener); @@ -62,7 +64,8 @@ Server &Server::getInstance() // struct sockaddr_storage clientAddr; // socklen_t clientAddrSize = sizeof(clientAddr); // int clientSocket = -// accept(listener, (struct sockaddr *)&clientAddr, &clientAddrSize); +// accept(listener, (struct sockaddr *)&clientAddr, +// &clientAddrSize); // if (clientSocket == -1) // { // std::stringstream errorMessage; diff --git a/ver-01.1/srcs/TCPSocket.cpp b/ver-01.1/srcs/TCPSocket.cpp index 51d8a65..48bb77f 100644 --- a/ver-01.1/srcs/TCPSocket.cpp +++ b/ver-01.1/srcs/TCPSocket.cpp @@ -2,6 +2,7 @@ #include #include +#include TCPSocket::TCPSocket() : Socket(family, type, 0, SOCK_NONBLOCK) { @@ -13,11 +14,14 @@ TCPSocket::TCPSocket() addr.sin_addr.s_addr = htonl(INADDR_ANY); addr.sin_family = family; std::memcpy(&address, &addr, sizeof(addr)); +#ifdef __DEBUG__ + std::cerr << "TCPSocket created successfully\n"; +#endif // __DEBUG__ } void TCPSocket::set_port(int port) throw() { - std::memset(&address, 0, sizeof(address)); + // std::memset(&address, 0, sizeof(address)); struct sockaddr_in addr; addr.sin_port = htons(port); std::memcpy(&address, &addr, sizeof(addr)); From 543cef2141c94668225cabe2c6ed3b5360e8e3a4 Mon Sep 17 00:00:00 2001 From: Samih Abdelrahman Date: Tue, 9 Jan 2024 15:01:08 +0400 Subject: [PATCH 039/215] build(Makefile): Add conditional compilation - Add optional compilation for linux and MAC --- ver-01.1/Makefile | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/ver-01.1/Makefile b/ver-01.1/Makefile index 36dd684..8102b05 100644 --- a/ver-01.1/Makefile +++ b/ver-01.1/Makefile @@ -2,12 +2,18 @@ CXX:= c++ CXXFLAGS:= -Wall -Werror -Wextra -std=c++98 DEBUGFLAGS:= -ggdb3 -fsanitize=address -D__DEBUG__ +ifeq ($(shell uname), Linux) + CXXFLAGS += -D__LINUX__ +else ifeq ($(shell uname), Darwin) + CXXFLAGS += -D__MAC__ +endif + RM:= rm -rf INCLUDES:= -I./includes SRCS_DIR:= srcs -SRCS:= Socket.cpp TCPSocket.cpp Server.cpp +SRCS:= Socket.cpp TCPSocket.cpp Server.cpp # tester mains TEST_SOCK:= $(SRCS_DIR)/SOCKET_main.cpp @@ -26,7 +32,7 @@ run: re debug: CXXFLAGS += $(DEBUGFLAGS) debug: all -$(NAME): $(OBJS) +$(NAME): $(OBJS) ar rcs $(NAME) $(OBJS) $(OBJS_DIR)/%.o: $(SRCS_DIR)/%.cpp | $(OBJS_DIR) @@ -36,10 +42,10 @@ $(OBJS_DIR): @mkdir -p objs # tests -test_socket: $(TEST_SOCK) debug +test_socket: $(TEST_SOCK) debug $(CXX) $(CXXFLAGS) $(INCLUDES) -fsanitize=address $(TEST_SOCK) $(NAME) -o $@ -test_server: $(TEST_SOCK) debug +test_server: $(TEST_SOCK) debug $(CXX) $(CXXFLAGS) $(INCLUDES) -fsanitize=address $(TEST_SERVER) $(NAME) -o $@ clean: From 98d733683c4ce0a583835c3696f74e7b2e291cdc Mon Sep 17 00:00:00 2001 From: Samih Abdelrahman Date: Tue, 9 Jan 2024 15:14:22 +0400 Subject: [PATCH 040/215] fix(Socket): Incorporate linux and mac conditionals - Add conditional fcntl defined macro O_NONBLOCK for compiling on mac this was done due to the linux way of passing SOCK_NONBLOCK as an or to type doesn't compile on mac the macro is not defined --- ver-01.1/srcs/Socket.cpp | 7 ++++++- ver-01.1/srcs/TCPSocket.cpp | 7 ++++++- 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/ver-01.1/srcs/Socket.cpp b/ver-01.1/srcs/Socket.cpp index eb98a40..dea3ac5 100644 --- a/ver-01.1/srcs/Socket.cpp +++ b/ver-01.1/srcs/Socket.cpp @@ -5,7 +5,7 @@ #include /* superset of previous */ #include #include /* See NOTES */ - +#include /* [CONSTRUCTORS] */ @@ -14,7 +14,12 @@ Socket::Socket(int family, int type, int protocol, int flags) , is_bound(false) , is_listening(false) { +#if defined(__LINUX__) socket_descriptor = socket(family, type | flags, protocol); +#elif defined(__MAC__) + socket_descriptor = socket(family, type , protocol); + fcntl(socket_descriptor, F_SETFL, flags); +#endif // // On success, a file descriptor for the new socket is returned. if (socket_descriptor == invalid_file_descriptor) diff --git a/ver-01.1/srcs/TCPSocket.cpp b/ver-01.1/srcs/TCPSocket.cpp index 48bb77f..b7e1e52 100644 --- a/ver-01.1/srcs/TCPSocket.cpp +++ b/ver-01.1/srcs/TCPSocket.cpp @@ -1,10 +1,15 @@ #include "TCPSocket.hpp" #include #include - +#include #include + TCPSocket::TCPSocket() +#if defined(__LINUX__) : Socket(family, type, 0, SOCK_NONBLOCK) +#elif defined(__MAC__) + : Socket(family, type, 0, O_NONBLOCK) +#endif { // zero out the sockaddr struct before copying std::memset(&address, 0, sizeof(address)); From 705da4ef001dd6278b540e086e9944a62fa46327 Mon Sep 17 00:00:00 2001 From: Samih Abdelrahman Date: Tue, 9 Jan 2024 17:26:58 +0400 Subject: [PATCH 041/215] fix(TCPSocket.cpp): Correctly copy port into address - Issue was happening with over-writing other `struct sockaddr` fields when attempting to memcpy the port --- ver-01.1/srcs/TCPSocket.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/ver-01.1/srcs/TCPSocket.cpp b/ver-01.1/srcs/TCPSocket.cpp index b7e1e52..4db6f72 100644 --- a/ver-01.1/srcs/TCPSocket.cpp +++ b/ver-01.1/srcs/TCPSocket.cpp @@ -26,10 +26,11 @@ TCPSocket::TCPSocket() void TCPSocket::set_port(int port) throw() { - // std::memset(&address, 0, sizeof(address)); struct sockaddr_in addr; + + int port_offset = offsetof(struct sockaddr_in, sin_port); addr.sin_port = htons(port); - std::memcpy(&address, &addr, sizeof(addr)); + std::memcpy(&address + port_offset, &addr, sizeof(addr.sin_port)); } TCPSocket::~TCPSocket() From 70e731fc074bcbe6bd19f7574dcb0633588146f6 Mon Sep 17 00:00:00 2001 From: Samih Abdelrahman Date: Fri, 12 Jan 2024 12:39:06 +0400 Subject: [PATCH 042/215] fix(Server.hpp): Change `int` to `file_descriptor` --- ver-01.1/includes/Server.hpp | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/ver-01.1/includes/Server.hpp b/ver-01.1/includes/Server.hpp index 57b9f27..40e1341 100644 --- a/ver-01.1/includes/Server.hpp +++ b/ver-01.1/includes/Server.hpp @@ -1,4 +1,4 @@ -#include +#include "TCPSocket.hpp" #include #ifndef SERVER_HPP @@ -9,7 +9,8 @@ class Server { protected: - explicit Server(file_descriptor listener_port, int backlog); + Server(file_descriptor _listener_port, int _backlog); + // deleted Server(const Server &){}; Server &operator=(const Server &) { @@ -20,8 +21,8 @@ class Server // this function needs to be static, as there won't be an instance of a Server // when its first created static Server &getInstance(file_descriptor listener_port, int backlog); - // void start(); - ~Server(){}; + void start(); + ~Server(); // member functions // void recv(const char *buff); // void send(const char *msg); @@ -29,10 +30,10 @@ class Server private: - static file_descriptor listener_port; - TCPSocket listener; - int status; - std::vector conn; + TCPSocket listener; + file_descriptor listener_port; + int status; + // std::vector conn; }; #endif // SERVER_HPP From 61ae4d9d7fb5b8efe86a9d94c56c53aa85789f72 Mon Sep 17 00:00:00 2001 From: Samih Abdelrahman Date: Sat, 13 Jan 2024 11:43:36 +0400 Subject: [PATCH 043/215] fix(Socket.hpp): Set socket_descritpor to private - This was done to allow inherited class to access it during the call to bind --- ver-01.1/includes/Socket.hpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/ver-01.1/includes/Socket.hpp b/ver-01.1/includes/Socket.hpp index 19ee3be..72201f6 100644 --- a/ver-01.1/includes/Socket.hpp +++ b/ver-01.1/includes/Socket.hpp @@ -10,11 +10,11 @@ // TODO // [P]artially implemented, needs [I]mprovement, [X] done // -// [ ] split-up function implementations into their own files // [I] make a unit-tester main // [ ] add shutdown functionality (block recv, block send, close()) // [ ] fix the get_fd functionality is it really necessary // [ ] set_port function in TCP makes it not a is-a relation-ship +// [ ] split-up function implementations into their own files #ifndef SOCKET_HPP #define SOCKET_HPP @@ -95,9 +95,10 @@ class Socket }; ; + + file_descriptor socket_descriptor; private: static const int invalid_file_descriptor = -1; - file_descriptor socket_descriptor; // state checks mutable bool is_bound; From 134756e7734eddb2f40715a8b259d489dbcb01aa Mon Sep 17 00:00:00 2001 From: Samih Abdelrahman Date: Sat, 13 Jan 2024 11:47:57 +0400 Subject: [PATCH 044/215] chore(TCPSocket.hpp): Rename `#include` files to hpp --- ver-01.1/includes/TCPSocket.hpp | 4 ++-- ver-01.1/srcs/ClientTest.cpp | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/ver-01.1/includes/TCPSocket.hpp b/ver-01.1/includes/TCPSocket.hpp index 1ce28b0..913d049 100644 --- a/ver-01.1/includes/TCPSocket.hpp +++ b/ver-01.1/includes/TCPSocket.hpp @@ -1,4 +1,4 @@ -#include +#include "Socket.hpp" #include // is-a inheritance relationship, every TCPSocket is a Socket @@ -11,7 +11,7 @@ class TCPSocket : public Socket public: TCPSocket(); - void set_port(int port) throw(); + void set_port(uint port) throw(); ~TCPSocket(); private: diff --git a/ver-01.1/srcs/ClientTest.cpp b/ver-01.1/srcs/ClientTest.cpp index 5e76389..47d78be 100644 --- a/ver-01.1/srcs/ClientTest.cpp +++ b/ver-01.1/srcs/ClientTest.cpp @@ -29,7 +29,7 @@ int main() // Connect to the server if (connect(sockfd, (struct sockaddr *)&sockaddr, sizeof(sockaddr)) < 0) { - std::cerr << "Connection Failed. errno: " << errno << std::endl; + std::cerr << "Connection Failed. errno: " << strerror(errno) << std::endl; exit(EXIT_FAILURE); } From 3d0aed47c03767996d80bb97e50a7a251b3cd7f1 Mon Sep 17 00:00:00 2001 From: Samih Abdelrahman Date: Sat, 13 Jan 2024 11:49:40 +0400 Subject: [PATCH 045/215] chore(SOCKET_test.cpp): Slight modifications to tester --- ver-01.1/srcs/SOCKET_main.cpp | 26 ++++++++++++++++---------- 1 file changed, 16 insertions(+), 10 deletions(-) diff --git a/ver-01.1/srcs/SOCKET_main.cpp b/ver-01.1/srcs/SOCKET_main.cpp index 0c63c27..829d79e 100644 --- a/ver-01.1/srcs/SOCKET_main.cpp +++ b/ver-01.1/srcs/SOCKET_main.cpp @@ -1,5 +1,5 @@ -#include "TCPSocket.hpp" -#include +#include "../includes/TCPSocket.hpp" +#include "../includes/Server.hpp" #include #include #include @@ -9,21 +9,27 @@ #include +#if 0 +int main() +{ + TCPSocket b; + b.set_port(89); +} +#endif + #if 1 int main() { // make a listening socket TCPSocket a; - Socket *b = &a; // prep it to accept connections on port 8080 a.set_port(8080); // oh-o !!! - b->bind(); + a.bind(); // set it to listen with backlog 25 - b->listen(5); - + a.listen(25); fd_set read_fds; - int fdmax = b->get_fd(); + int fdmax = a.get_fd(); while (true) { @@ -31,7 +37,7 @@ int main() std::cout << "---------- Server is up and waiting!!! ----------------" << std::endl; FD_ZERO(&read_fds); - FD_SET(b->get_fd(), &read_fds); + FD_SET(a.get_fd(), &read_fds); if (select(fdmax + 1, &read_fds, NULL, NULL, NULL) == -1) { @@ -39,10 +45,10 @@ int main() continue; } - if (FD_ISSET(b->get_fd(), &read_fds)) + if (FD_ISSET(a.get_fd(), &read_fds)) { // accept if a connection happens - file_descriptor peer = b->accept(); + file_descriptor peer = a.accept(); std::cout << "peer is connected on port " << peer << "\n"; // receive data from the connected peer From c8312d4a7cf4b40a9b1193d52cf9b4def60a6377 Mon Sep 17 00:00:00 2001 From: Samih Abdelrahman Date: Sat, 13 Jan 2024 11:51:03 +0400 Subject: [PATCH 046/215] chore(Server.cpp): Add status variable initialization to constructor --- ver-01.1/srcs/Server.cpp | 37 +++++++++++++------------------------ 1 file changed, 13 insertions(+), 24 deletions(-) diff --git a/ver-01.1/srcs/Server.cpp b/ver-01.1/srcs/Server.cpp index dcfc4c4..3ab9587 100644 --- a/ver-01.1/srcs/Server.cpp +++ b/ver-01.1/srcs/Server.cpp @@ -1,10 +1,5 @@ -#include "Server.hpp" -#include -#include -#include +#include "../includes/Server.hpp" #include -#include -#include #include #include #include @@ -22,7 +17,9 @@ Server &Server::getInstance(file_descriptor listener_port, int backlog) } // default constructor -Server::Server(int listener_port, int backlog) +Server::Server(int _listener_port, int backlog) + : listener_port(_listener_port) + , status(0) { // setup the Server listener.set_port(listener_port); @@ -30,25 +27,17 @@ Server::Server(int listener_port, int backlog) listener.listen(backlog); } -// Server::~Server() -// { -// close(listener); -// } -// -// Server::Server(const __attribute__((unused)) Server &other) -// {} -// -// Server &Server::operator=(const __attribute__((unused)) Server &other) -// { -// return *this; -// } -// -// +Server::~Server() +{ + ::close(listener.socket_descriptor); +} + + // void Server::start() // { // int backlog = 0; // int status = 0; -// + // // bind the socket // while (true) // { @@ -59,7 +48,7 @@ Server::Server(int listener_port, int backlog) // errorMessage << SOCKET_ERR << ": " << strerror(errno); // throw std::runtime_error(errorMessage.str()); // } -// + // // accept a connection on a socket // struct sockaddr_storage clientAddr; // socklen_t clientAddrSize = sizeof(clientAddr); @@ -72,7 +61,7 @@ Server::Server(int listener_port, int backlog) // errorMessage << SOCKET_ERR << ": " << strerror(errno); // throw std::runtime_error(errorMessage.str()); // } -// + // // handle the connection // handleConnection(clientSocket); // } From fa1d97f3fc1e12f6010e28adcdfac96560bfa92c Mon Sep 17 00:00:00 2001 From: Samih Abdelrahman Date: Sat, 13 Jan 2024 11:51:45 +0400 Subject: [PATCH 047/215] fix(Socket.cpp): Add the GET_FL line to fcntl for MAC --- ver-01.1/srcs/Socket.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/ver-01.1/srcs/Socket.cpp b/ver-01.1/srcs/Socket.cpp index dea3ac5..c76d5c8 100644 --- a/ver-01.1/srcs/Socket.cpp +++ b/ver-01.1/srcs/Socket.cpp @@ -1,4 +1,4 @@ -#include "Socket.hpp" +#include "../includes/Socket.hpp" #include #include #include @@ -18,6 +18,7 @@ Socket::Socket(int family, int type, int protocol, int flags) socket_descriptor = socket(family, type | flags, protocol); #elif defined(__MAC__) socket_descriptor = socket(family, type , protocol); + flags |= fcntl(socket_descriptor, F_GETFL, 0); fcntl(socket_descriptor, F_SETFL, flags); #endif // From 097a1434cf78324d319dc834e6e999946f36d650 Mon Sep 17 00:00:00 2001 From: Samih Abdelrahman Date: Sat, 13 Jan 2024 11:54:55 +0400 Subject: [PATCH 048/215] fix(TCPSocket.cpp): Remove the memset 0 call --- ver-01.1/srcs/TCPSocket.cpp | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/ver-01.1/srcs/TCPSocket.cpp b/ver-01.1/srcs/TCPSocket.cpp index 4db6f72..6d391fe 100644 --- a/ver-01.1/srcs/TCPSocket.cpp +++ b/ver-01.1/srcs/TCPSocket.cpp @@ -1,8 +1,11 @@ -#include "TCPSocket.hpp" +#include "../includes/TCPSocket.hpp" +#include #include #include -#include + +#ifdef __DEBUG__ #include +#endif // __DEBUG__ TCPSocket::TCPSocket() #if defined(__LINUX__) @@ -11,26 +14,22 @@ TCPSocket::TCPSocket() : Socket(family, type, 0, O_NONBLOCK) #endif { - // zero out the sockaddr struct before copying - std::memset(&address, 0, sizeof(address)); struct sockaddr_in addr; // prep up the struct addr.sin_addr.s_addr = htonl(INADDR_ANY); addr.sin_family = family; std::memcpy(&address, &addr, sizeof(addr)); + #ifdef __DEBUG__ std::cerr << "TCPSocket created successfully\n"; #endif // __DEBUG__ + } -void TCPSocket::set_port(int port) throw() +void TCPSocket::set_port(uint port) throw() { - struct sockaddr_in addr; - - int port_offset = offsetof(struct sockaddr_in, sin_port); - addr.sin_port = htons(port); - std::memcpy(&address + port_offset, &addr, sizeof(addr.sin_port)); + ((struct sockaddr_in *)(&address))->sin_port = htons(port); } TCPSocket::~TCPSocket() From 2b771b13ef0b8bd47622deca397da3c871e80482 Mon Sep 17 00:00:00 2001 From: Samih Abdelrahman Date: Sat, 13 Jan 2024 12:01:08 +0400 Subject: [PATCH 049/215] chore: Delete compile-json --- ver-01.1/compile_commands.json | 19 ------------------- ver-01.1/srcs/SERVER_main.cpp | 2 +- 2 files changed, 1 insertion(+), 20 deletions(-) delete mode 100644 ver-01.1/compile_commands.json diff --git a/ver-01.1/compile_commands.json b/ver-01.1/compile_commands.json deleted file mode 100644 index b49a889..0000000 --- a/ver-01.1/compile_commands.json +++ /dev/null @@ -1,19 +0,0 @@ -[ - { - "arguments": [ - "/usr/bin/c++", - "-Wall", - "-Werror", - "-Wextra", - "-std=c++98", - "-I./includes", - "-c", - "-o", - "objs/Server.o", - "srcs/Server.cpp" - ], - "directory": "/home/eva001/42/webserv/ver-01.1", - "file": "/home/eva001/42/webserv/ver-01.1/srcs/Server.cpp", - "output": "/home/eva001/42/webserv/ver-01.1/objs/Server.o" - } -] diff --git a/ver-01.1/srcs/SERVER_main.cpp b/ver-01.1/srcs/SERVER_main.cpp index b4c9048..f0e424c 100644 --- a/ver-01.1/srcs/SERVER_main.cpp +++ b/ver-01.1/srcs/SERVER_main.cpp @@ -1,4 +1,4 @@ -#include +#include "../includes/Server.hpp" int main() { From 1a7aa22756976581cbd87d084ef36ed8f11fab6e Mon Sep 17 00:00:00 2001 From: Samih Abdelrahman Date: Sat, 13 Jan 2024 15:47:29 +0400 Subject: [PATCH 050/215] fix(TCP/Socket): Define SOCK_FLAG for conditional compilation - Refactor the conditional compilation step of Socket constructor to SOCK_FLAG variable instead --- ver-01.1/includes/Socket.hpp | 6 ++++++ ver-01.1/includes/TCPSocket.hpp | 4 ++-- ver-01.1/srcs/Socket.cpp | 12 ++++++++---- ver-01.1/srcs/TCPSocket.cpp | 21 ++++++++++----------- 4 files changed, 26 insertions(+), 17 deletions(-) diff --git a/ver-01.1/includes/Socket.hpp b/ver-01.1/includes/Socket.hpp index 72201f6..485de4d 100644 --- a/ver-01.1/includes/Socket.hpp +++ b/ver-01.1/includes/Socket.hpp @@ -16,6 +16,12 @@ // [ ] set_port function in TCP makes it not a is-a relation-ship // [ ] split-up function implementations into their own files +#if defined(__LINUX__) +#define SOCK_FLAG SOCK_NONBLOCK +#elif defined(__MAC__) +#define SOCK_FLAG O_NONBLOCK +#endif + #ifndef SOCKET_HPP #define SOCKET_HPP // DEBUG BUILD diff --git a/ver-01.1/includes/TCPSocket.hpp b/ver-01.1/includes/TCPSocket.hpp index 913d049..590587c 100644 --- a/ver-01.1/includes/TCPSocket.hpp +++ b/ver-01.1/includes/TCPSocket.hpp @@ -5,8 +5,8 @@ #ifndef TCPSOCKET_HPP #define TCPSOCKET_HPP -// a non-blocking SOCK_STREAM, TCP(IP4) socket bound to port -class TCPSocket : public Socket +// a non-blocking SOCK_STREAM, TCP(IP4) socket +class TCPSocket: public Socket { public: diff --git a/ver-01.1/srcs/Socket.cpp b/ver-01.1/srcs/Socket.cpp index c76d5c8..e5f1b60 100644 --- a/ver-01.1/srcs/Socket.cpp +++ b/ver-01.1/srcs/Socket.cpp @@ -1,11 +1,11 @@ #include "../includes/Socket.hpp" #include +#include #include #include #include /* superset of previous */ #include #include /* See NOTES */ -#include /* [CONSTRUCTORS] */ @@ -17,9 +17,9 @@ Socket::Socket(int family, int type, int protocol, int flags) #if defined(__LINUX__) socket_descriptor = socket(family, type | flags, protocol); #elif defined(__MAC__) - socket_descriptor = socket(family, type , protocol); - flags |= fcntl(socket_descriptor, F_GETFL, 0); - fcntl(socket_descriptor, F_SETFL, flags); + socket_descriptor = socket(family, type, protocol); + flags |= fcntl(socket_descriptor, F_GETFL, 0); + fcntl(socket_descriptor, F_SETFL, flags); #endif // // On success, a file descriptor for the new socket is returned. @@ -132,10 +132,12 @@ file_descriptor Socket::accept() // check if socket is listening if (!is_listening) throw Socket::Exception(Exception::compose_msg(ERR_NLIST)); + // This structure is filled in with the address of the peer socket, // as known to the communications layer. struct sockaddr peer_info; // does this need to be stored? socklen_t peer_length = sizeof(peer_info); + // The accept() system call is used with connection-based socket types (SOCK_STREAM, // SOCK_SEQPACKET). // it extracts the first pending connection request in the backlog que form listen. @@ -147,6 +149,7 @@ file_descriptor Socket::accept() // if set to non_blocking it returns EAGAIN or EWOULDBLOCK if no connection if (errno != EAGAIN && errno != EWOULDBLOCK) throw Socket::Exception(Exception::compose_msg(ERR_ACCP)); + #ifdef __DEBUG__ else std::cerr << "Socket has no incoming connections \n"; @@ -155,5 +158,6 @@ file_descriptor Socket::accept() #ifdef __DEBUG__ std::cerr << "Socket accepted a connection from \n"; #endif // __DEBUG__ + return connected_socket; } diff --git a/ver-01.1/srcs/TCPSocket.cpp b/ver-01.1/srcs/TCPSocket.cpp index 6d391fe..38a5de3 100644 --- a/ver-01.1/srcs/TCPSocket.cpp +++ b/ver-01.1/srcs/TCPSocket.cpp @@ -7,12 +7,10 @@ #include #endif // __DEBUG__ +/* [CONSTRUCTORS] */ + TCPSocket::TCPSocket() -#if defined(__LINUX__) - : Socket(family, type, 0, SOCK_NONBLOCK) -#elif defined(__MAC__) - : Socket(family, type, 0, O_NONBLOCK) -#endif + : Socket(family, type, 0, SOCK_FLAG) { struct sockaddr_in addr; @@ -20,17 +18,13 @@ TCPSocket::TCPSocket() addr.sin_addr.s_addr = htonl(INADDR_ANY); addr.sin_family = family; std::memcpy(&address, &addr, sizeof(addr)); - + #ifdef __DEBUG__ std::cerr << "TCPSocket created successfully\n"; #endif // __DEBUG__ - } -void TCPSocket::set_port(uint port) throw() -{ - ((struct sockaddr_in *)(&address))->sin_port = htons(port); -} +/* [DESTRUCTOR] */ TCPSocket::~TCPSocket() { @@ -38,3 +32,8 @@ TCPSocket::~TCPSocket() std::cerr << "TCPSocket closed!!\n"; #endif // __DEBUG__ } + +void TCPSocket::set_port(uint port) throw() +{ + ((struct sockaddr_in *)(&address))->sin_port = htons(port); +} From 822d302a4a380959ead80b5847cb8b549091b872 Mon Sep 17 00:00:00 2001 From: Samih Abdelrahman Date: Sat, 13 Jan 2024 16:32:45 +0400 Subject: [PATCH 051/215] fix(Socket): Add port check assert for invalid port numbers - Add a range check between 0 and 65535 --- ver-01.1/includes/Socket.hpp | 2 ++ ver-01.1/includes/TCPSocket.hpp | 2 +- ver-01.1/srcs/SOCKET_main.cpp | 11 ++++++----- ver-01.1/srcs/Socket.cpp | 1 + ver-01.1/srcs/TCPSocket.cpp | 3 ++- 5 files changed, 12 insertions(+), 7 deletions(-) diff --git a/ver-01.1/includes/Socket.hpp b/ver-01.1/includes/Socket.hpp index 485de4d..ead8033 100644 --- a/ver-01.1/includes/Socket.hpp +++ b/ver-01.1/includes/Socket.hpp @@ -20,6 +20,8 @@ #define SOCK_FLAG SOCK_NONBLOCK #elif defined(__MAC__) #define SOCK_FLAG O_NONBLOCK +#else +#define SOCK_FLAG #endif #ifndef SOCKET_HPP diff --git a/ver-01.1/includes/TCPSocket.hpp b/ver-01.1/includes/TCPSocket.hpp index 590587c..65c91da 100644 --- a/ver-01.1/includes/TCPSocket.hpp +++ b/ver-01.1/includes/TCPSocket.hpp @@ -11,7 +11,7 @@ class TCPSocket: public Socket public: TCPSocket(); - void set_port(uint port) throw(); + void set_port(int port) throw(); ~TCPSocket(); private: diff --git a/ver-01.1/srcs/SOCKET_main.cpp b/ver-01.1/srcs/SOCKET_main.cpp index 829d79e..4f0ae13 100644 --- a/ver-01.1/srcs/SOCKET_main.cpp +++ b/ver-01.1/srcs/SOCKET_main.cpp @@ -1,23 +1,24 @@ #include "../includes/TCPSocket.hpp" #include "../includes/Server.hpp" -#include #include #include +#include + // Socket tester main add test cases here to test the behaviour of the // class -#include -#if 0 +#if 1 int main() { TCPSocket b; - b.set_port(89); + b.set_port(-1); + b.bind(); } #endif -#if 1 +#if 0 int main() { // make a listening socket diff --git a/ver-01.1/srcs/Socket.cpp b/ver-01.1/srcs/Socket.cpp index e5f1b60..9e9b14f 100644 --- a/ver-01.1/srcs/Socket.cpp +++ b/ver-01.1/srcs/Socket.cpp @@ -103,6 +103,7 @@ void Socket::bind() const if (status == -1) throw Socket::Exception(Exception::compose_msg(ERR_BIND)); is_bound = true; + #ifdef __DEBUG__ std::cerr << "Socket was bound successfully to port[" << ntohs(((struct sockaddr_in *)&address)->sin_port) << "]\n"; diff --git a/ver-01.1/srcs/TCPSocket.cpp b/ver-01.1/srcs/TCPSocket.cpp index 38a5de3..341c360 100644 --- a/ver-01.1/srcs/TCPSocket.cpp +++ b/ver-01.1/srcs/TCPSocket.cpp @@ -33,7 +33,8 @@ TCPSocket::~TCPSocket() #endif // __DEBUG__ } -void TCPSocket::set_port(uint port) throw() +void TCPSocket::set_port(int port) throw() { + DEBUGASSERT(port >= 0 && port <= 65535); // could be an exception ((struct sockaddr_in *)(&address))->sin_port = htons(port); } From 60e8b1d1fbf7616944771b8b46d89580171df76b Mon Sep 17 00:00:00 2001 From: Samih Abdelrahman Date: Sat, 13 Jan 2024 22:58:40 +0400 Subject: [PATCH 052/215] chore(Socket): Modify tester --- ver-01.1/includes/Socket.hpp | 47 ++++++++++++++++++++++++++---- ver-01.1/includes/TCPSocket.hpp | 4 +-- ver-01.1/srcs/SOCKET_main.cpp | 51 ++++++++++++++++++++++++++------- ver-01.1/srcs/TCPSocket.cpp | 5 ++-- 4 files changed, 88 insertions(+), 19 deletions(-) diff --git a/ver-01.1/includes/Socket.hpp b/ver-01.1/includes/Socket.hpp index ead8033..560bb66 100644 --- a/ver-01.1/includes/Socket.hpp +++ b/ver-01.1/includes/Socket.hpp @@ -16,16 +16,52 @@ // [ ] set_port function in TCP makes it not a is-a relation-ship // [ ] split-up function implementations into their own files +#ifndef SOCKET_HPP +#define SOCKET_HPP + +/* --------------------------------- colors --------------------------------- */ +#define SET_COLOR(color) (std::cout << (color)) +#define RE_COLOR (std::cout << RE) + +#define RE "\001\033[0;39m\002" // reset +#define L "\001\033[1;92m\002" // green light +#define Y "\001\033[1;93m\002" // yellow +#define M "\001\033[1;95m\002" // magenta +#define R "\001\033[1;91m\002" // red +#define B "\001\033[1;94m\002" // blue +#define C "\001\033[1;96m\002" // cyan +#define W "\001\033[1;97m\002" // white +#define D "\001\033[1;30m\002" // gray +#define O "\001\033[1;33m\002" // orange + +/* ------------------------------- DEBUG MACRO ------------------------------ */ +#ifndef __DEBUG__ +#define DEBUG_MSG(message, color) +#else +#define DEBUG_MSG(message, color) \ + do \ + { \ + std::cerr << (color); \ + std::cerr << (message); \ + std::cerr << std::endl; \ + std::cerr << RE; \ + std::cerr.flush (); \ + } \ + while (0) +#endif // __DEBUG__ + + +// SOCK_FLAG +// prefer the compiler over pre-processor #if defined(__LINUX__) -#define SOCK_FLAG SOCK_NONBLOCK +static const int SOCK_FLAG = SOCK_NONBLOCK; #elif defined(__MAC__) -#define SOCK_FLAG O_NONBLOCK +#include +static const int SOCK_FLAG = O_NONBLOCK; #else -#define SOCK_FLAG +static const int SOCK_FLAG = 0; #endif -#ifndef SOCKET_HPP -#define SOCKET_HPP // DEBUG BUILD #ifdef __DEBUG__ #include @@ -105,6 +141,7 @@ class Socket file_descriptor socket_descriptor; + private: static const int invalid_file_descriptor = -1; diff --git a/ver-01.1/includes/TCPSocket.hpp b/ver-01.1/includes/TCPSocket.hpp index 65c91da..8153c0f 100644 --- a/ver-01.1/includes/TCPSocket.hpp +++ b/ver-01.1/includes/TCPSocket.hpp @@ -5,13 +5,13 @@ #ifndef TCPSOCKET_HPP #define TCPSOCKET_HPP -// a non-blocking SOCK_STREAM, TCP(IP4) socket +// a non-blocking SOCK_STREAM, TCP(IP4) socket class TCPSocket: public Socket { public: TCPSocket(); - void set_port(int port) throw(); + void set_port(int port)const; ~TCPSocket(); private: diff --git a/ver-01.1/srcs/SOCKET_main.cpp b/ver-01.1/srcs/SOCKET_main.cpp index 4f0ae13..ca8691c 100644 --- a/ver-01.1/srcs/SOCKET_main.cpp +++ b/ver-01.1/srcs/SOCKET_main.cpp @@ -1,5 +1,6 @@ -#include "../includes/TCPSocket.hpp" #include "../includes/Server.hpp" +#include "../includes/TCPSocket.hpp" +#include #include #include #include @@ -9,15 +10,7 @@ // class -#if 1 -int main() -{ - TCPSocket b; - b.set_port(-1); - b.bind(); -} -#endif - +// simple server #if 0 int main() { @@ -76,3 +69,41 @@ int main() } } #endif // TCPSocket + + +// set_port +#if 1 + +// Define the X macro for test cases +#define TEST_CASES \ + X(0) \ + X(-1) \ + X(-INT_MAX) \ + X(INT_MAX) \ + X(INT_MIN) \ + X('a') \ + X(8080) \ + X(99) + +int main() +{ +#define X(test_case) \ + do \ + { \ + std::cout << "---- Case[" << test_case << "] -----\n"; \ + TCPSocket socket; \ + try { \ + socket.set_port(test_case); \ + socket.bind(); \ + } \ + catch (Socket::Exception &se) { \ + std::cerr << "Error in port number"; \ + } \ + } while (false); + TEST_CASES +#undef X // Clean up the macro definition + + return 0; +} + +#endif diff --git a/ver-01.1/srcs/TCPSocket.cpp b/ver-01.1/srcs/TCPSocket.cpp index 341c360..7883348 100644 --- a/ver-01.1/srcs/TCPSocket.cpp +++ b/ver-01.1/srcs/TCPSocket.cpp @@ -33,8 +33,9 @@ TCPSocket::~TCPSocket() #endif // __DEBUG__ } -void TCPSocket::set_port(int port) throw() +void TCPSocket::set_port(int port) const { - DEBUGASSERT(port >= 0 && port <= 65535); // could be an exception + if (port >= 0 && port <= 65535) + throw Socket::Exception("Invalid Socket descriptor\n"); ((struct sockaddr_in *)(&address))->sin_port = htons(port); } From 7e538497e58ef55dcc47c8853898a94edbf18307 Mon Sep 17 00:00:00 2001 From: samih713 Date: Sun, 14 Jan 2024 23:59:32 +0400 Subject: [PATCH 053/215] chore(Socket): Replace debug messages with macro --- ver-01.1/srcs/Socket.cpp | 47 ++++++++++++++-------------------------- 1 file changed, 16 insertions(+), 31 deletions(-) diff --git a/ver-01.1/srcs/Socket.cpp b/ver-01.1/srcs/Socket.cpp index 9e9b14f..6979887 100644 --- a/ver-01.1/srcs/Socket.cpp +++ b/ver-01.1/srcs/Socket.cpp @@ -26,10 +26,7 @@ Socket::Socket(int family, int type, int protocol, int flags) if (socket_descriptor == invalid_file_descriptor) throw Socket::Exception(Exception::compose_msg(ERR_CREAT)); -#ifdef __DEBUG__ - else - std::cerr << "Socket was created successfully fd[" << socket_descriptor << "]\n"; -#endif // __DEBUG__ + DEBUG_MSG("Socket was created successfully fd[" << socket_descriptor << "]", Y); // zero out the sockaddr struct memset(&address, 0, sizeof(address)); @@ -55,9 +52,7 @@ Socket::Socket(int family, int type, const char *protocol_name, int flags) if (!protocol) throw Socket::Exception(Exception::compose_msg(ERR_NULL)); -#ifdef __DEBUG__ - std::cerr << "protocol official name is [" << protocol->p_name << "]\n"; -#endif // __DEBUG__ + DEBUG_MSG("protocol official name is [" << protocol->p_name << "]", Y); socket_descriptor = socket(family, type | flags, protocol->p_proto); @@ -65,10 +60,7 @@ Socket::Socket(int family, int type, const char *protocol_name, int flags) if (socket_descriptor == invalid_file_descriptor) throw Socket::Exception(Exception::compose_msg(ERR_CREAT)); -#ifdef __DEBUG__ - else - std::cerr << "Socket was created successfully fd[" << socket_descriptor << "]\n"; -#endif // __DEBUG__ + DEBUG_MSG("Socket was created successfully fd[" << socket_descriptor << "]", Y); // zero out the sockaddr struct memset(&address, 0, sizeof(address)); @@ -78,9 +70,8 @@ Socket::Socket(int family, int type, const char *protocol_name, int flags) Socket::~Socket() { -#ifdef __DEBUG__ - std::cerr << "socket fd[" << socket_descriptor << "] closed!!\n"; -#endif // __DEBUG__ + DEBUG_MSG("socket fd[" << socket_descriptor << "] closed!!", R); + if (socket_descriptor != invalid_file_descriptor) { close(socket_descriptor); @@ -104,10 +95,9 @@ void Socket::bind() const throw Socket::Exception(Exception::compose_msg(ERR_BIND)); is_bound = true; -#ifdef __DEBUG__ - std::cerr << "Socket was bound successfully to port[" - << ntohs(((struct sockaddr_in *)&address)->sin_port) << "]\n"; -#endif // __DEBUG__ + DEBUG_MSG("Socket was bound successfully to port[" + << ntohs(((struct sockaddr_in *)&address)->sin_port) << "]\n", + B); } void Socket::listen(int backlog) const @@ -120,11 +110,10 @@ void Socket::listen(int backlog) const throw Socket::Exception(Exception::compose_msg(ERR_LIST)); is_listening = true; -#ifdef __DEBUG__ - std::cerr << "Socket listen was successful, [" << socket_descriptor - << "] is now ready to accept max backlog of [" << backlog - << "] connections\n"; -#endif // __DEBUG__ + DEBUG_MSG("Socket listen was successful, [" + << socket_descriptor << "] is now ready to accept max backlog of [" + << backlog << "] connections\n", + M); } @@ -133,7 +122,7 @@ file_descriptor Socket::accept() // check if socket is listening if (!is_listening) throw Socket::Exception(Exception::compose_msg(ERR_NLIST)); - + // This structure is filled in with the address of the peer socket, // as known to the communications layer. struct sockaddr peer_info; // does this need to be stored? @@ -151,14 +140,10 @@ file_descriptor Socket::accept() if (errno != EAGAIN && errno != EWOULDBLOCK) throw Socket::Exception(Exception::compose_msg(ERR_ACCP)); -#ifdef __DEBUG__ - else - std::cerr << "Socket has no incoming connections \n"; -#endif // __DEBUG__ + DEBUG_MSG("Socket has no incoming connections", D); } -#ifdef __DEBUG__ - std::cerr << "Socket accepted a connection from \n"; -#endif // __DEBUG__ + + DEBUG_MSG("Socket accepted a connection from", W); return connected_socket; } From 6c0fb2c0fc74ac0230b8327df4ebf8a7e5516490 Mon Sep 17 00:00:00 2001 From: samih713 Date: Mon, 15 Jan 2024 00:00:34 +0400 Subject: [PATCH 054/215] chore(Socket): Add debug macro --- ver-01.1/includes/Socket.hpp | 43 ++++++++++++++++++------------------ 1 file changed, 21 insertions(+), 22 deletions(-) diff --git a/ver-01.1/includes/Socket.hpp b/ver-01.1/includes/Socket.hpp index 560bb66..e01983d 100644 --- a/ver-01.1/includes/Socket.hpp +++ b/ver-01.1/includes/Socket.hpp @@ -21,33 +21,34 @@ /* --------------------------------- colors --------------------------------- */ #define SET_COLOR(color) (std::cout << (color)) -#define RE_COLOR (std::cout << RE) +#define RE_COLOR (std::cout << RE) #define RE "\001\033[0;39m\002" // reset -#define L "\001\033[1;92m\002" // green light -#define Y "\001\033[1;93m\002" // yellow -#define M "\001\033[1;95m\002" // magenta -#define R "\001\033[1;91m\002" // red -#define B "\001\033[1;94m\002" // blue -#define C "\001\033[1;96m\002" // cyan -#define W "\001\033[1;97m\002" // white -#define D "\001\033[1;30m\002" // gray -#define O "\001\033[1;33m\002" // orange +#define L "\001\033[1;92m\002" // green light +#define Y "\001\033[1;93m\002" // yellow +#define M "\001\033[1;95m\002" // magenta +#define R "\001\033[1;91m\002" // red +#define B "\001\033[1;94m\002" // blue +#define C "\001\033[1;96m\002" // cyan +#define W "\001\033[1;97m\002" // white +#define D "\001\033[1;30m\002" // gray +#define O "\001\033[1;33m\002" // orange /* ------------------------------- DEBUG MACRO ------------------------------ */ #ifndef __DEBUG__ #define DEBUG_MSG(message, color) #else -#define DEBUG_MSG(message, color) \ - do \ - { \ - std::cerr << (color); \ - std::cerr << (message); \ - std::cerr << std::endl; \ - std::cerr << RE; \ - std::cerr.flush (); \ - } \ - while (0) +#include +#include +#define DEBUG_MSG(message, color) \ + do \ + { \ + std::cerr << (color); \ + std::cerr << message; \ + std::cerr << std::endl; \ + std::cerr << RE; \ + std::cerr.flush(); \ + } while (0) #endif // __DEBUG__ @@ -64,8 +65,6 @@ static const int SOCK_FLAG = 0; // DEBUG BUILD #ifdef __DEBUG__ -#include -#include #define DEBUGASSERT(x) assert(x) #else #define DEBUGASSERT(x) \ From 7de7d10f94b98f8aaac85f3e1a7ed1c9c25fdf3d Mon Sep 17 00:00:00 2001 From: samih713 Date: Mon, 15 Jan 2024 00:02:05 +0400 Subject: [PATCH 055/215] chore: Format clean-up --- ver-01.1/srcs/SOCKET_main.cpp | 2 +- ver-01.1/srcs/TCPSocket.cpp | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/ver-01.1/srcs/SOCKET_main.cpp b/ver-01.1/srcs/SOCKET_main.cpp index ca8691c..7160021 100644 --- a/ver-01.1/srcs/SOCKET_main.cpp +++ b/ver-01.1/srcs/SOCKET_main.cpp @@ -97,7 +97,7 @@ int main() socket.bind(); \ } \ catch (Socket::Exception &se) { \ - std::cerr << "Error in port number"; \ + std::cerr << "Error in port number\n"; \ } \ } while (false); TEST_CASES diff --git a/ver-01.1/srcs/TCPSocket.cpp b/ver-01.1/srcs/TCPSocket.cpp index 7883348..41a3c1f 100644 --- a/ver-01.1/srcs/TCPSocket.cpp +++ b/ver-01.1/srcs/TCPSocket.cpp @@ -10,7 +10,7 @@ /* [CONSTRUCTORS] */ TCPSocket::TCPSocket() - : Socket(family, type, 0, SOCK_FLAG) + : Socket(family, type, 0, SOCK_FLAG) { struct sockaddr_in addr; @@ -35,7 +35,7 @@ TCPSocket::~TCPSocket() void TCPSocket::set_port(int port) const { - if (port >= 0 && port <= 65535) - throw Socket::Exception("Invalid Socket descriptor\n"); + if (port >= 0 && port <= 65535) + throw Socket::Exception("Invalid Socket descriptor\n"); ((struct sockaddr_in *)(&address))->sin_port = htons(port); } From a6daf40adffc889bb9e1ff22cd8700d9160d4a6b Mon Sep 17 00:00:00 2001 From: samih713 Date: Mon, 15 Jan 2024 00:09:15 +0400 Subject: [PATCH 056/215] fix(TCPSocket): Error check condition - As the the if condition was changed from an assertion to an `if` throw the condition needed to be flipped --- ver-01.1/srcs/TCPSocket.cpp | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/ver-01.1/srcs/TCPSocket.cpp b/ver-01.1/srcs/TCPSocket.cpp index 41a3c1f..fc90261 100644 --- a/ver-01.1/srcs/TCPSocket.cpp +++ b/ver-01.1/srcs/TCPSocket.cpp @@ -19,23 +19,19 @@ TCPSocket::TCPSocket() addr.sin_family = family; std::memcpy(&address, &addr, sizeof(addr)); -#ifdef __DEBUG__ - std::cerr << "TCPSocket created successfully\n"; -#endif // __DEBUG__ + DEBUG_MSG("TCPSocket created successfully", G); } /* [DESTRUCTOR] */ TCPSocket::~TCPSocket() { -#ifdef __DEBUG__ - std::cerr << "TCPSocket closed!!\n"; -#endif // __DEBUG__ + DEBUG_MSG("TCPSocket closed!!\n", R); } void TCPSocket::set_port(int port) const { - if (port >= 0 && port <= 65535) + if (port < 0 || port > 65535) throw Socket::Exception("Invalid Socket descriptor\n"); ((struct sockaddr_in *)(&address))->sin_port = htons(port); } From c19dc8075a0e4d20823b349bb5ace93157ec5409 Mon Sep 17 00:00:00 2001 From: samih713 Date: Mon, 15 Jan 2024 15:49:08 +0400 Subject: [PATCH 057/215] fix(Socket): Add the `set_port` function to Socket base class - Moved it form TCP derived class to the parent class --- ver-01.1/includes/Socket.hpp | 9 ++++++--- ver-01.1/includes/TCPSocket.hpp | 1 - ver-01.1/srcs/Socket.cpp | 14 +++++++++++--- ver-01.1/srcs/TCPSocket.cpp | 11 +++-------- 4 files changed, 20 insertions(+), 15 deletions(-) diff --git a/ver-01.1/includes/Socket.hpp b/ver-01.1/includes/Socket.hpp index e01983d..1fa30b2 100644 --- a/ver-01.1/includes/Socket.hpp +++ b/ver-01.1/includes/Socket.hpp @@ -13,8 +13,8 @@ // [I] make a unit-tester main // [ ] add shutdown functionality (block recv, block send, close()) // [ ] fix the get_fd functionality is it really necessary -// [ ] set_port function in TCP makes it not a is-a relation-ship // [ ] split-up function implementations into their own files +// [ ] make a seperate error header #ifndef SOCKET_HPP #define SOCKET_HPP @@ -86,6 +86,7 @@ static std::string ERR_ACCP("Socket: accept failed"); // socket_descriptor type typedef int file_descriptor; + class Socket { @@ -100,14 +101,16 @@ class Socket public: /* [DESTRUCTOR] */ + virtual ~Socket(); /* [INTERFACE] */ - void bind() const; // item36: never re-define an inherited non-virtual function + void set_port(int port); + file_descriptor const get_fd() const throw(); + void bind() const; void listen(int backlog) const; file_descriptor accept(); - file_descriptor get_fd() const; // void shutdown(int option); // void connect(); // is something you do on a client diff --git a/ver-01.1/includes/TCPSocket.hpp b/ver-01.1/includes/TCPSocket.hpp index 8153c0f..8dd3055 100644 --- a/ver-01.1/includes/TCPSocket.hpp +++ b/ver-01.1/includes/TCPSocket.hpp @@ -11,7 +11,6 @@ class TCPSocket: public Socket public: TCPSocket(); - void set_port(int port)const; ~TCPSocket(); private: diff --git a/ver-01.1/srcs/Socket.cpp b/ver-01.1/srcs/Socket.cpp index 6979887..cdb9b5a 100644 --- a/ver-01.1/srcs/Socket.cpp +++ b/ver-01.1/srcs/Socket.cpp @@ -29,7 +29,7 @@ Socket::Socket(int family, int type, int protocol, int flags) DEBUG_MSG("Socket was created successfully fd[" << socket_descriptor << "]", Y); // zero out the sockaddr struct - memset(&address, 0, sizeof(address)); + std::memset(&address, 0, sizeof(address)); } /* Call protocol by name */ @@ -63,7 +63,7 @@ Socket::Socket(int family, int type, const char *protocol_name, int flags) DEBUG_MSG("Socket was created successfully fd[" << socket_descriptor << "]", Y); // zero out the sockaddr struct - memset(&address, 0, sizeof(address)); + std::memset(&address, 0, sizeof(address)); } /* [DESTRUCTOR] */ @@ -83,7 +83,15 @@ Socket::~Socket() /* [INTERFACE] */ -file_descriptor Socket::get_fd() const +// throws execpetions +void Socket::set_port(int port) +{ + if (port < 0 || port > 65535) + throw Socket::Exception("Invalid Socket descriptor\n"); + ((struct sockaddr_in *)(&address))->sin_port = htons(port); +} + +file_descriptor const Socket::get_fd() const throw() { return socket_descriptor; } diff --git a/ver-01.1/srcs/TCPSocket.cpp b/ver-01.1/srcs/TCPSocket.cpp index fc90261..68af721 100644 --- a/ver-01.1/srcs/TCPSocket.cpp +++ b/ver-01.1/srcs/TCPSocket.cpp @@ -19,19 +19,14 @@ TCPSocket::TCPSocket() addr.sin_family = family; std::memcpy(&address, &addr, sizeof(addr)); - DEBUG_MSG("TCPSocket created successfully", G); + DEBUG_MSG("TCPSocket created successfully", C); } /* [DESTRUCTOR] */ TCPSocket::~TCPSocket() { - DEBUG_MSG("TCPSocket closed!!\n", R); + DEBUG_MSG("TCPSocket closed!!", R); } -void TCPSocket::set_port(int port) const -{ - if (port < 0 || port > 65535) - throw Socket::Exception("Invalid Socket descriptor\n"); - ((struct sockaddr_in *)(&address))->sin_port = htons(port); -} + From ad4d3fd878d4d17f72771e541325c548d54bc184 Mon Sep 17 00:00:00 2001 From: samih713 Date: Tue, 16 Jan 2024 10:02:15 +0400 Subject: [PATCH 058/215] feat(Server): Update `start()` in Server --- ver-01.1/includes/Server.hpp | 24 +++++--- ver-01.1/includes/Socket.hpp | 2 +- ver-01.1/srcs/SERVER_main.cpp | 10 ++- ver-01.1/srcs/Server.cpp | 112 ++++++++++++++++++++++------------ ver-01.1/srcs/Socket.cpp | 11 ++-- 5 files changed, 102 insertions(+), 57 deletions(-) diff --git a/ver-01.1/includes/Server.hpp b/ver-01.1/includes/Server.hpp index 40e1341..c75dfc0 100644 --- a/ver-01.1/includes/Server.hpp +++ b/ver-01.1/includes/Server.hpp @@ -1,21 +1,18 @@ #include "TCPSocket.hpp" +#include #include #ifndef SERVER_HPP #define SERVER_HPP +static const std::string wait_message("Server is now waiting for connections...\n"); + // simple singleton implementation class Server { protected: Server(file_descriptor _listener_port, int _backlog); - // deleted - Server(const Server &){}; - Server &operator=(const Server &) - { - return *this; - }; public: // this function needs to be static, as there won't be an instance of a Server @@ -30,10 +27,17 @@ class Server private: - TCPSocket listener; - file_descriptor listener_port; - int status; - // std::vector conn; + TCPSocket listener; + int listenerPort; + int status; + std::vector connections; + + // deleted + Server(const Server &){}; + Server &operator=(const Server &) + { + return *this; + }; }; #endif // SERVER_HPP diff --git a/ver-01.1/includes/Socket.hpp b/ver-01.1/includes/Socket.hpp index 1fa30b2..c7cb1a9 100644 --- a/ver-01.1/includes/Socket.hpp +++ b/ver-01.1/includes/Socket.hpp @@ -107,7 +107,7 @@ class Socket /* [INTERFACE] */ void set_port(int port); - file_descriptor const get_fd() const throw(); + file_descriptor get_fd() const throw(); void bind() const; void listen(int backlog) const; file_descriptor accept(); diff --git a/ver-01.1/srcs/SERVER_main.cpp b/ver-01.1/srcs/SERVER_main.cpp index f0e424c..7d331c5 100644 --- a/ver-01.1/srcs/SERVER_main.cpp +++ b/ver-01.1/srcs/SERVER_main.cpp @@ -1,7 +1,13 @@ #include "../includes/Server.hpp" +#include int main() { - Server &webserv = Server::getInstance(80, 10); - (void)webserv; + try + { + Server &webserv = Server::getInstance(8080, 10); + webserv.start(); + } + catch (const Socket::Exception &e) + {std::cerr << e.what();} } diff --git a/ver-01.1/srcs/Server.cpp b/ver-01.1/srcs/Server.cpp index 3ab9587..6503b90 100644 --- a/ver-01.1/srcs/Server.cpp +++ b/ver-01.1/srcs/Server.cpp @@ -1,28 +1,40 @@ #include "../includes/Server.hpp" +#include +#include +#include +#include #include +#include #include #include #include +#include #include -#ifdef __DEBUG +// TODO // [P]artially implemented, needs [I]mprovement, [X] done +// +// [ ] Handle Socket exceptions here? +// [ ] Implement select + + +#ifdef __DEBUG__ #include -#endif // __DEBUG +#endif // __DEBUG__ -Server &Server::getInstance(file_descriptor listener_port, int backlog) +Server &Server::getInstance(int listenerPort, int backlog) { // avoid creating another one - static Server instance(listener_port, backlog); + static Server instance(listenerPort, backlog); return instance; } // default constructor -Server::Server(int _listener_port, int backlog) - : listener_port(_listener_port) +Server::Server(int listenerPort, int backlog) + : listenerPort(listenerPort) , status(0) { // setup the Server - listener.set_port(listener_port); + listener.set_port(listenerPort); listener.bind(); listener.listen(backlog); } @@ -33,36 +45,56 @@ Server::~Server() } -// void Server::start() -// { -// int backlog = 0; -// int status = 0; - -// // bind the socket -// while (true) -// { -// if (status) // an error has occured -// { -// // If a connection request arrives when the queue is full -// std::stringstream errorMessage; -// errorMessage << SOCKET_ERR << ": " << strerror(errno); -// throw std::runtime_error(errorMessage.str()); -// } - -// // accept a connection on a socket -// struct sockaddr_storage clientAddr; -// socklen_t clientAddrSize = sizeof(clientAddr); -// int clientSocket = -// accept(listener, (struct sockaddr *)&clientAddr, -// &clientAddrSize); -// if (clientSocket == -1) -// { -// std::stringstream errorMessage; -// errorMessage << SOCKET_ERR << ": " << strerror(errno); -// throw std::runtime_error(errorMessage.str()); -// } - -// // handle the connection -// handleConnection(clientSocket); -// } -// } +void Server::start() +{ + + // wait duration before displaying a wait message, needs lpthread and 11 + // only for testing + auto _duration(std::chrono::seconds(5)); + + // making 2 fd_sets because select is destructive? + fd_set current_sockets; + fd_set ready_sockets; + + // zero out the current_sockets + FD_ZERO(¤t_sockets); + + // adds the listener socket to the set of current sockets + FD_SET(listener.get_fd(), ¤t_sockets); + + while (true) + { + DEBUG_MSG(wait_message, R); + + ready_sockets = current_sockets; + + if (select(FD_SETSIZE, &ready_sockets, NULL, NULL, NULL) < 0) + throw std::runtime_error(strerror(errno)); + + for (int i = 0; i < FD_SETSIZE; i++) + { + if (FD_ISSET(i, &ready_sockets)) + { + // if its our listener, then we got a new connection + if (i == listener.get_fd()) + { + // we accept the new connection + file_descriptor client_socket = listener.accept(); + // add the new socket to the watched list of currenct sockets + FD_SET(client_socket, ¤t_sockets); + } + // its an exisiting connections that is ready for reading + else + { + // handle the connection + DEBUG_MSG( "reading from connection", M); + // remove it from there once its done + FD_CLR(i, ¤t_sockets); + } + } + } + + // forced sleep + std::this_thread::sleep_for(_duration); + } +} diff --git a/ver-01.1/srcs/Socket.cpp b/ver-01.1/srcs/Socket.cpp index cdb9b5a..4348f53 100644 --- a/ver-01.1/srcs/Socket.cpp +++ b/ver-01.1/srcs/Socket.cpp @@ -3,9 +3,9 @@ #include #include #include -#include /* superset of previous */ +#include #include -#include /* See NOTES */ +#include /* [CONSTRUCTORS] */ @@ -88,10 +88,12 @@ void Socket::set_port(int port) { if (port < 0 || port > 65535) throw Socket::Exception("Invalid Socket descriptor\n"); + + // set the port number in address struct ((struct sockaddr_in *)(&address))->sin_port = htons(port); } -file_descriptor const Socket::get_fd() const throw() +file_descriptor Socket::get_fd() const throw() { return socket_descriptor; } @@ -112,8 +114,9 @@ void Socket::listen(int backlog) const { if (!is_bound) throw Socket::Exception(Exception::compose_msg(ERR_NBIND)); - // global namespace to avoid conflict + int status = ::listen(socket_descriptor, backlog); + if (status == -1) throw Socket::Exception(Exception::compose_msg(ERR_LIST)); is_listening = true; From 60569f6d5ff1e76cc9c7dd9e7f159e3d8900f514 Mon Sep 17 00:00:00 2001 From: samih713 Date: Tue, 16 Jan 2024 10:09:12 +0400 Subject: [PATCH 059/215] chore(Makefile): Now uses c++11 and links with - this is only done for the wait in start function remove later --- ver-01.1/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ver-01.1/Makefile b/ver-01.1/Makefile index 8102b05..74b7ef2 100644 --- a/ver-01.1/Makefile +++ b/ver-01.1/Makefile @@ -1,5 +1,5 @@ CXX:= c++ -CXXFLAGS:= -Wall -Werror -Wextra -std=c++98 +CXXFLAGS:= -Wall -Werror -Wextra -std=c++11 -lpthread DEBUGFLAGS:= -ggdb3 -fsanitize=address -D__DEBUG__ ifeq ($(shell uname), Linux) From 3eaf1e96e5dff9ccd4b0dadf00fe02f0dd909fbd Mon Sep 17 00:00:00 2001 From: Tanvir Ahmed Anas Date: Wed, 17 Jan 2024 14:38:24 +0400 Subject: [PATCH 060/215] chore(Socket.hpp, error.hpp): - Moved error/debug related macros, functions and variables into error.hpp --- ver-01.1/includes/Socket.hpp | 66 ++---------------------------------- ver-01.1/includes/error.hpp | 53 +++++++++++++++++++++++++++++ 2 files changed, 56 insertions(+), 63 deletions(-) create mode 100644 ver-01.1/includes/error.hpp diff --git a/ver-01.1/includes/Socket.hpp b/ver-01.1/includes/Socket.hpp index c7cb1a9..cc64f5d 100644 --- a/ver-01.1/includes/Socket.hpp +++ b/ver-01.1/includes/Socket.hpp @@ -7,6 +7,7 @@ #include #include #include +#include "error.hpp" // TODO // [P]artially implemented, needs [I]mprovement, [X] done // @@ -14,44 +15,10 @@ // [ ] add shutdown functionality (block recv, block send, close()) // [ ] fix the get_fd functionality is it really necessary // [ ] split-up function implementations into their own files -// [ ] make a seperate error header #ifndef SOCKET_HPP #define SOCKET_HPP -/* --------------------------------- colors --------------------------------- */ -#define SET_COLOR(color) (std::cout << (color)) -#define RE_COLOR (std::cout << RE) - -#define RE "\001\033[0;39m\002" // reset -#define L "\001\033[1;92m\002" // green light -#define Y "\001\033[1;93m\002" // yellow -#define M "\001\033[1;95m\002" // magenta -#define R "\001\033[1;91m\002" // red -#define B "\001\033[1;94m\002" // blue -#define C "\001\033[1;96m\002" // cyan -#define W "\001\033[1;97m\002" // white -#define D "\001\033[1;30m\002" // gray -#define O "\001\033[1;33m\002" // orange - -/* ------------------------------- DEBUG MACRO ------------------------------ */ -#ifndef __DEBUG__ -#define DEBUG_MSG(message, color) -#else -#include -#include -#define DEBUG_MSG(message, color) \ - do \ - { \ - std::cerr << (color); \ - std::cerr << message; \ - std::cerr << std::endl; \ - std::cerr << RE; \ - std::cerr.flush(); \ - } while (0) -#endif // __DEBUG__ - - // SOCK_FLAG // prefer the compiler over pre-processor #if defined(__LINUX__) @@ -63,33 +30,11 @@ static const int SOCK_FLAG = O_NONBLOCK; static const int SOCK_FLAG = 0; #endif -// DEBUG BUILD -#ifdef __DEBUG__ -#define DEBUGASSERT(x) assert(x) -#else -#define DEBUGASSERT(x) \ - do \ - { \ - } while (0) -#endif // __DEBUG__ -// DEBUG BUILD - -// [ERROR MESSAGES] -static std::string ERR_NULL("Socket: null ptr error"); -static std::string ERR_CREAT("Socket: creation failed"); -static std::string ERR_BIND("Socket: binding failed"); -static std::string ERR_NBIND("Socket: not bound to a port"); -static std::string ERR_LIST("Socket: listen failed"); -static std::string ERR_NLIST("Socket: not listeing"); -static std::string ERR_ACCP("Socket: accept failed"); - // socket_descriptor type typedef int file_descriptor; - class Socket { - protected: // protected constructors only in derived classes /* [CONSTRUCTORS] */ @@ -139,8 +84,6 @@ class Socket return error_message.c_str(); } }; - ; - file_descriptor socket_descriptor; @@ -152,11 +95,8 @@ class Socket mutable bool is_listening; // deleted but can't cause is 98 maguy - Socket(const Socket &){}; - Socket &operator=(const Socket &) - { - return *this; - }; + Socket(const Socket &) {}; + Socket &operator=(const Socket &) { return *this; }; }; #endif // SOCKET_HPP diff --git a/ver-01.1/includes/error.hpp b/ver-01.1/includes/error.hpp new file mode 100644 index 0000000..a73ccc5 --- /dev/null +++ b/ver-01.1/includes/error.hpp @@ -0,0 +1,53 @@ +#ifndef ERROR_HPP +# define ERROR_HPP + +/* --------------------------------- COLORS --------------------------------- */ +# define SET_COLOR(color) (std::cout << (color)) +# define RE_COLOR (std::cout << RE) + +# define RE "\001\033[0;39m\002" // reset +# define L "\001\033[1;92m\002" // green light +# define Y "\001\033[1;93m\002" // yellow +# define M "\001\033[1;95m\002" // magenta +# define R "\001\033[1;91m\002" // red +# define B "\001\033[1;94m\002" // blue +# define C "\001\033[1;96m\002" // cyan +# define W "\001\033[1;97m\002" // white +# define D "\001\033[1;30m\002" // gray +# define O "\001\033[1;33m\002" // orange + +/* ------------------------------- DEBUG MACRO ------------------------------ */ +# ifndef __DEBUG__ +# define DEBUG_MSG(message, color) +# else +# include +# include +# define DEBUG_MSG(message, color) \ + do { \ + std::cerr << (color); \ + std::cerr << message; \ + std::cerr << std::endl; \ + std::cerr << RE; \ + std::cerr.flush(); \ + } while (0) +# endif // __DEBUG__ + +/* ------------------------------- DEBUG BUILD ------------------------------ */ +# ifdef __DEBUG__ +# define DEBUGASSERT(x) assert(x) +# else +# define DEBUGASSERT(x) do {} while (0) +# endif // __DEBUG__ + +/* ----------------------------- ERROR MESSAGES ----------------------------- */ +# include +static std::string ERR_NULL("Socket: null ptr error"); +static std::string ERR_CREAT("Socket: creation failed"); +static std::string ERR_BIND("Socket: binding failed"); +static std::string ERR_NBIND("Socket: not bound to a port"); +static std::string ERR_LIST("Socket: listen failed"); +static std::string ERR_NLIST("Socket: not listeing"); +static std::string ERR_ACCP("Socket: accept failed"); + + +#endif From 0d826f90a1177acd1e80102632d4406c7cccf610 Mon Sep 17 00:00:00 2001 From: Tanvir Ahmed Anas Date: Wed, 17 Jan 2024 15:32:46 +0400 Subject: [PATCH 061/215] build(Makefile): Removed `-lpthread` from CXXFLAGS --- ver-01.1/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ver-01.1/Makefile b/ver-01.1/Makefile index 74b7ef2..a15aeda 100644 --- a/ver-01.1/Makefile +++ b/ver-01.1/Makefile @@ -1,5 +1,5 @@ CXX:= c++ -CXXFLAGS:= -Wall -Werror -Wextra -std=c++11 -lpthread +CXXFLAGS:= -Wall -Werror -Wextra -std=c++11 DEBUGFLAGS:= -ggdb3 -fsanitize=address -D__DEBUG__ ifeq ($(shell uname), Linux) From 6bb414d9703593a84c4b01720d59587604f8dd1a Mon Sep 17 00:00:00 2001 From: Tanvir Ahmed Anas Date: Wed, 17 Jan 2024 15:34:53 +0400 Subject: [PATCH 062/215] chore(Server.cpp): Removed repeated include --- ver-01.1/srcs/Server.cpp | 5 ----- 1 file changed, 5 deletions(-) diff --git a/ver-01.1/srcs/Server.cpp b/ver-01.1/srcs/Server.cpp index 6503b90..5bda884 100644 --- a/ver-01.1/srcs/Server.cpp +++ b/ver-01.1/srcs/Server.cpp @@ -16,11 +16,6 @@ // [ ] Handle Socket exceptions here? // [ ] Implement select - -#ifdef __DEBUG__ -#include -#endif // __DEBUG__ - Server &Server::getInstance(int listenerPort, int backlog) { // avoid creating another one From de425cafd1b649804b84dcfbdd8660b37f7b34d4 Mon Sep 17 00:00:00 2001 From: Tanvir Ahmed Anas Date: Wed, 17 Jan 2024 16:06:29 +0400 Subject: [PATCH 063/215] style(Server.(cpp|hpp): Changed style of variables - Member variables listener, listenerPort, connections now start with an '_' - Fixed the implementation of Server constructor - Removed status since it was unused --- ver-01.1/includes/Server.hpp | 16 ++++++---------- ver-01.1/srcs/Server.cpp | 19 +++++++++---------- 2 files changed, 15 insertions(+), 20 deletions(-) diff --git a/ver-01.1/includes/Server.hpp b/ver-01.1/includes/Server.hpp index c75dfc0..14e0ae2 100644 --- a/ver-01.1/includes/Server.hpp +++ b/ver-01.1/includes/Server.hpp @@ -12,7 +12,7 @@ static const std::string wait_message("Server is now waiting for connections...\ class Server { protected: - Server(file_descriptor _listener_port, int _backlog); + Server(file_descriptor listenerport, int backlog); public: // this function needs to be static, as there won't be an instance of a Server @@ -27,17 +27,13 @@ class Server private: - TCPSocket listener; - int listenerPort; - int status; - std::vector connections; + TCPSocket _listener; + int _listenerPort; + std::vector _connections; // deleted - Server(const Server &){}; - Server &operator=(const Server &) - { - return *this; - }; + Server(const Server &) {}; + Server &operator=(const Server &) { return *this; }; }; #endif // SERVER_HPP diff --git a/ver-01.1/srcs/Server.cpp b/ver-01.1/srcs/Server.cpp index 5bda884..95cfb48 100644 --- a/ver-01.1/srcs/Server.cpp +++ b/ver-01.1/srcs/Server.cpp @@ -24,19 +24,18 @@ Server &Server::getInstance(int listenerPort, int backlog) } // default constructor -Server::Server(int listenerPort, int backlog) - : listenerPort(listenerPort) - , status(0) +Server::Server(file_descriptor listenerPort, int backlog) + : _listenerPort(listenerPort) { // setup the Server - listener.set_port(listenerPort); - listener.bind(); - listener.listen(backlog); + _listener.set_port(_listenerPort); + _listener.bind(); + _listener.listen(backlog); } Server::~Server() { - ::close(listener.socket_descriptor); + ::close(_listener.socket_descriptor); } @@ -55,7 +54,7 @@ void Server::start() FD_ZERO(¤t_sockets); // adds the listener socket to the set of current sockets - FD_SET(listener.get_fd(), ¤t_sockets); + FD_SET(_listener.get_fd(), ¤t_sockets); while (true) { @@ -71,10 +70,10 @@ void Server::start() if (FD_ISSET(i, &ready_sockets)) { // if its our listener, then we got a new connection - if (i == listener.get_fd()) + if (i == _listener.get_fd()) { // we accept the new connection - file_descriptor client_socket = listener.accept(); + file_descriptor client_socket = _listener.accept(); // add the new socket to the watched list of currenct sockets FD_SET(client_socket, ¤t_sockets); } From 9b49f47f54e3331edf36255f780774ccb65297b3 Mon Sep 17 00:00:00 2001 From: Taanviir <66136914+Taanviir@users.noreply.github.com> Date: Thu, 18 Jan 2024 01:28:35 +0400 Subject: [PATCH 064/215] testing ci/cd --- test.txt | 0 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 test.txt diff --git a/test.txt b/test.txt new file mode 100644 index 0000000..e69de29 From 4eb4446eb236c73ea59337f48f5dcd9a10c5b430 Mon Sep 17 00:00:00 2001 From: Taanviir <66136914+Taanviir@users.noreply.github.com> Date: Thu, 18 Jan 2024 02:07:31 +0400 Subject: [PATCH 065/215] testing CI/CD workflow --- test.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/test.txt b/test.txt index e69de29..038d718 100644 --- a/test.txt +++ b/test.txt @@ -0,0 +1 @@ +testing From 558e26e0e6a888ec671a84a7369f68085d52287d Mon Sep 17 00:00:00 2001 From: Taanviir <66136914+Taanviir@users.noreply.github.com> Date: Thu, 18 Jan 2024 11:59:29 +0400 Subject: [PATCH 066/215] testing CI/CD again --- test.txt | 1 - 1 file changed, 1 deletion(-) delete mode 100644 test.txt diff --git a/test.txt b/test.txt deleted file mode 100644 index 038d718..0000000 --- a/test.txt +++ /dev/null @@ -1 +0,0 @@ -testing From 0e07f72fdf037a6708277d227a808744bfcd7b01 Mon Sep 17 00:00:00 2001 From: Taanviir <66136914+Taanviir@users.noreply.github.com> Date: Thu, 18 Jan 2024 12:03:10 +0400 Subject: [PATCH 067/215] testing CI/CD once again --- cicd.txt | 1 + 1 file changed, 1 insertion(+) create mode 100644 cicd.txt diff --git a/cicd.txt b/cicd.txt new file mode 100644 index 0000000..9daeafb --- /dev/null +++ b/cicd.txt @@ -0,0 +1 @@ +test From afbe5ca85e49748af31b73e513802b5d957fb3bd Mon Sep 17 00:00:00 2001 From: Tanvir Ahmed Anas Date: Thu, 18 Jan 2024 12:53:39 +0400 Subject: [PATCH 068/215] build(compile-check.yml): Added github action to branch --- .github/workflows/compile-check.yml | 24 ++++++++++++++++++++++++ cicd.txt | 1 - 2 files changed, 24 insertions(+), 1 deletion(-) create mode 100644 .github/workflows/compile-check.yml delete mode 100644 cicd.txt diff --git a/.github/workflows/compile-check.yml b/.github/workflows/compile-check.yml new file mode 100644 index 0000000..1b413b1 --- /dev/null +++ b/.github/workflows/compile-check.yml @@ -0,0 +1,24 @@ +name: Compilation Check + +on: + push: + branches: + - server/ver-01.1 + +jobs: + build: + runs-on: ubuntu-latest + + steps: + - name: Checkout repository + uses: actions/checkout@v3 + + - name: Set up C++ environment + uses: aminya/setup-cpp@v1 + with: + compiler: gcc + + - name: Build project + run: | + cd ver-01.1 + make \ No newline at end of file diff --git a/cicd.txt b/cicd.txt deleted file mode 100644 index 9daeafb..0000000 --- a/cicd.txt +++ /dev/null @@ -1 +0,0 @@ -test From 5025a10a58048bfa78af715445fb4f5a8f5b292c Mon Sep 17 00:00:00 2001 From: Tanvir Ahmed Anas Date: Thu, 18 Jan 2024 14:05:20 +0400 Subject: [PATCH 069/215] new branch (config-parser): first commit --- .github/workflows/compile-check.yml | 2 +- ver-01.1/Makefile => Makefile | 0 {ver-01.1/includes => includes}/Server.hpp | 0 {ver-01.1/includes => includes}/Socket.hpp | 0 {ver-01.1/includes => includes}/TCPSocket.hpp | 0 {ver-01.1/includes => includes}/error.hpp | 0 .../C++ Network Programming Volume 1.pdf | Bin 5854262 -> 0 bytes resources/C++Networkprogramming_ppt.pdf | Bin 4006735 -> 0 bytes resources/code_examples/CURLCode.cpp | 131 - resources/code_examples/README.md | 101 - resources/code_examples/mprintf.c | 1213 -- resources/code_examples/strcase.c | 204 - resources/notes/notes_RFC7230 | 95 - resources/notes/notes_RFC791 | 76 - resources/notes/notes_RFCguide | 32 - resources/notes/notes_design_considerations | 30 - resources/notes/notes_effectivecpp | 46 - .../notes/notes_network_programming_main.c | 351 - resources/notes/notes_websockets | 9 - resources/notes/ports_list.txt | 13920 ---------------- {ver-01.1/srcs => srcs}/ClientTest.cpp | 0 {ver-01.1/srcs => srcs}/SERVER_main.cpp | 0 {ver-01.1/srcs => srcs}/SOCKET_main.cpp | 0 {ver-01.1/srcs => srcs}/Server.cpp | 0 {ver-01.1/srcs => srcs}/Socket.cpp | 0 {ver-01.1/srcs => srcs}/TCPSocket.cpp | 0 ver-01.1/.clang-format | 223 - 27 files changed, 1 insertion(+), 16432 deletions(-) rename ver-01.1/Makefile => Makefile (100%) rename {ver-01.1/includes => includes}/Server.hpp (100%) rename {ver-01.1/includes => includes}/Socket.hpp (100%) rename {ver-01.1/includes => includes}/TCPSocket.hpp (100%) rename {ver-01.1/includes => includes}/error.hpp (100%) delete mode 100644 resources/C++ Network Programming Volume 1.pdf delete mode 100644 resources/C++Networkprogramming_ppt.pdf delete mode 100644 resources/code_examples/CURLCode.cpp delete mode 100644 resources/code_examples/README.md delete mode 100644 resources/code_examples/mprintf.c delete mode 100644 resources/code_examples/strcase.c delete mode 100644 resources/notes/notes_RFC7230 delete mode 100644 resources/notes/notes_RFC791 delete mode 100644 resources/notes/notes_RFCguide delete mode 100644 resources/notes/notes_design_considerations delete mode 100644 resources/notes/notes_effectivecpp delete mode 100644 resources/notes/notes_network_programming_main.c delete mode 100644 resources/notes/notes_websockets delete mode 100644 resources/notes/ports_list.txt rename {ver-01.1/srcs => srcs}/ClientTest.cpp (100%) rename {ver-01.1/srcs => srcs}/SERVER_main.cpp (100%) rename {ver-01.1/srcs => srcs}/SOCKET_main.cpp (100%) rename {ver-01.1/srcs => srcs}/Server.cpp (100%) rename {ver-01.1/srcs => srcs}/Socket.cpp (100%) rename {ver-01.1/srcs => srcs}/TCPSocket.cpp (100%) delete mode 100644 ver-01.1/.clang-format diff --git a/.github/workflows/compile-check.yml b/.github/workflows/compile-check.yml index 1b413b1..b282a11 100644 --- a/.github/workflows/compile-check.yml +++ b/.github/workflows/compile-check.yml @@ -3,7 +3,7 @@ name: Compilation Check on: push: branches: - - server/ver-01.1 + - config-parser jobs: build: diff --git a/ver-01.1/Makefile b/Makefile similarity index 100% rename from ver-01.1/Makefile rename to Makefile diff --git a/ver-01.1/includes/Server.hpp b/includes/Server.hpp similarity index 100% rename from ver-01.1/includes/Server.hpp rename to includes/Server.hpp diff --git a/ver-01.1/includes/Socket.hpp b/includes/Socket.hpp similarity index 100% rename from ver-01.1/includes/Socket.hpp rename to includes/Socket.hpp diff --git a/ver-01.1/includes/TCPSocket.hpp b/includes/TCPSocket.hpp similarity index 100% rename from ver-01.1/includes/TCPSocket.hpp rename to includes/TCPSocket.hpp diff --git a/ver-01.1/includes/error.hpp b/includes/error.hpp similarity index 100% rename from ver-01.1/includes/error.hpp rename to includes/error.hpp diff --git a/resources/C++ Network Programming Volume 1.pdf b/resources/C++ Network Programming Volume 1.pdf deleted file mode 100644 index 4c4c51f4a25f4fc6b2818a4a28a520424d13863e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5854262 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