Code Monkey home page Code Monkey logo

team07's Introduction

Welcome to our Simple Robust Webserver!
- Anant Mahajan, Gabriel Pawlowsky, Nikhil Shridhar


What is this project?
- It's a simple webserver that has configurable parameters that are fed in via and Nginx-like config file. Currently, the server can handle file and echo requests.


Code Layout and Design? What's where?

Server Functionality:

1) Our server functionality can be found in the file server.cpp. In this file, we have two classes, Server and Connection. As their names suggest, 
a) The Server class handles set up of the server, including using our config parser to parse the given config and then setting up the server on the appropriate port, socket, etc, and then scans for any incoming connections.
b) Once a connection is accepted, the connection class reads the request, and obtains a formatted version via a call to the request parser. It then invokes the required request handler, and handles writing to the socket for the current connection. More information about the request parser and connection handlers can be found below.

2) The request parser can be found in request.cpp, and is inspired from Boost documentation. More information can be found here: http://www.boost.org/doc/libs/1_60_0/doc/html/boost_asio/example/cpp03/http/server/request_parser.cpp

3) Now, we have a few different types of request handlers.
a) 404 handler - When our webserver detects a request that cannot be found on our server, we use a 404 handler to return an appropriate response.
b) echo handler - When the user decides to access the echo functionality of our server (using server/echo), our echo handler is invoked which simply echos the request received.
c) file handler- When a client requests a file, from one of our preset paths, this handler is invoked to serve the appropriate file.
Our handlers can be found in file_handler.cpp, echo_handler.cpp and 404_handler.cpp.
d) status handler - When a client requests the status of our server, this handler serves the types of handlers present in our server and their usage since the starting of the server.

4) Lastly, to make the functionality of the above classes a little easier, we have two helpful data structure classes that we use named Request and Response, which are based off Boost's Request and Reply structures. As their name suggests, they hold information about the requests and responses used in the server. These structures form convenient ways to format and store request and response parameters, and examples of their usage can be seen in the connection class, as well as in our conenction handlers.


Config Parsing:

1) A majority of our parsing takes place in the file config_parser.cc, which is inspired by https://github.com/fatiherikli/nginxparser. This parses our files into tokens and statements.

2) Secondary parsing to evaluate the content of the file takes place in the file config.cc, which reads the port number to create the server on, as well as any path mappings specified in the config file.


Testing Requirements:

1) We have gtest functionality available in testing files thanks to to googletest subdirectory available on this repo. (Includes code from googletest-1.7.0. See https://code.google.com/p/googletest/)

2) Each .cpp or .cc file has (or should have) a unit test file labeled file_name_test.cpp. Please let us know if you find a file without a corresponding test file so we can update this!

3) We have an integration test in the form of a shell script called integration.sh, that needs to be updated when new functionality is added. Please update this file if you choose to contribute to our project. 


Build and Usage Instructions

Our webserver comes with a Makefile with a few preconfigured build options that we think are useful.

1) make - compiles the webserver files.
2) ./webserver - after compiling you can use this executable to run our server. Please be advised that this call must be followed by a config file of valid format. See our file labeled 'config' for an example of a valid format.
3) make test && make run_coverage - compiles all webserver files and runs all unit and integration tests, as well as scans for test converage of our code. 
4) make clean - removes any intermediary compile related files and executables, cleaning up your directory.
5) make run - compiles the webserver files, and then runs the webserver using our default configuration from the file 'config'.

Once the server is up and running, it can be accessed through a browser, or via the command line with curl requests.


How to contribute to our project?

1) Fork our repo. 

2) Make any changes that you feel are necessary or a good addition to our server.

3) If your changes included the creation of new files, please write unit tests in a new file that has the name file_name_test.cpp, where file_name is your newly created file.

4) Update our Integration test at integration.sh if your update changes any user-side functionality.

5) Add your changed files to our makefile, and run the server. Also test it to make sure your unit tests are passing.

6) Create a pull request, and we'll review your code. If we think it's a useful addition, we'll add it to our code and credit you on this README doc!

7) If you have any questions regarding functionality, please email [email protected] (I'll typically respond within a day or two). 


Thanks for checking us out, and I hope you contribute to our project!

team07's People

Contributors

creator23 avatar nikhilshridhar avatar jfarrell468 avatar foucher avatar gabpaw987 avatar

Watchers

Jason Yoon avatar alex waz avatar

team07's Issues

Segfaulting when checking URIs for known prefixes

While implementing a reverse proxy handler, we found that while the browser was performing additional requests for css files, images, etc. that the server would return the html and then crash, throwing a length_error.

Using gdb, we found that the issue was occurring in server.cpp on line 58.

cur_prefix.erase(cur_prefix.end() - pathIt->string().length(), cur_prefix.end());

It seems to attempt to erase before the prefix beginning, causing the server to crash. In the meantime, we added an if statement to check this:

if (pathIt->string().length() < cur_prefix.length()) { ... }
else { /* print error and problematic string, then break loop */ }

However, when we test this and open up the Status Handler, we get a lot of 404 Errors. We think this is because if the Request URI doesn't match any of the predefined prefixes, it throws a 404, when in this case it should not be.

The backtrace from gdb:

#0  0x00007ffff6bf3c37 in __GI_raise (sig=sig@entry=6) at ../nptl/sysdeps/unix/sysv/linux/raise.c:56
#1  0x00007ffff6bf7028 in __GI_abort () at abort.c:89
#2  0x00007ffff771c535 in __gnu_cxx::__verbose_terminate_handler() () from /usr/lib/x86_64-linux-gnu/libstdc++.so.6
#3  0x00007ffff771a6d6 in ?? () from /usr/lib/x86_64-linux-gnu/libstdc++.so.6
#4  0x00007ffff771a703 in std::terminate() () from /usr/lib/x86_64-linux-gnu/libstdc++.so.6
#5  0x00007ffff771a922 in __cxa_throw () from /usr/lib/x86_64-linux-gnu/libstdc++.so.6
#6  0x00007ffff776c3a7 in std::__throw_length_error(char const*) () from /usr/lib/x86_64-linux-gnu/libstdc++.so.6
#7  0x00007ffff7776262 in std::string::_Rep::_S_create(unsigned long, unsigned long, std::allocator<char> const&) () from /usr/lib/x86_64-linux-gnu/libstdc++.so.6
#8  0x00007ffff77763d6 in std::string::_M_mutate(unsigned long, unsigned long, unsigned long) () from /usr/lib/x86_64-linux-gnu/libstdc++.so.6
#9  0x00007ffff77767a9 in std::string::erase(__gnu_cxx::__normal_iterator<char*, std::string>, __gnu_cxx::__normal_iterator<char*, std::string>) ()
   from /usr/lib/x86_64-linux-gnu/libstdc++.so.6
#10 0x0000000000408b93 in operator() (__closure=<optimized out>, bytes=<optimized out>, ec=...) at server.cpp:58
#11 operator() (this=<optimized out>) at /usr/include/boost/asio/detail/bind_handler.hpp:127
#12 asio_handler_invoke<boost::asio::detail::binder2<http::server::connection::do_read()::__lambda0, boost::system::error_code, long unsigned int> > (function=...)
       at /usr/include/boost/asio/handler_invoke_hook.hpp:64
#13 invoke<boost::asio::detail::binder2<http::server::connection::do_read()::__lambda0, boost::system::error_code, long unsigned int>, http::server::connection::do_read()::__lambda0> (context=..., function=...) at /usr/include/boost/asio/detail/handler_invoke_helpers.hpp:37
#14 boost::asio::detail::reactive_socket_recv_op<boost::asio::mutable_buffers_1, http::server::connection::do_read()::__lambda0>::do_complete(boost::asio::detail::io_service_impl *, boost::asio::detail::operation *, const boost::system::error_code &, std::size_t) (owner=<optimized out>, base=<optimized out>)
           at /usr/include/boost/asio/detail/reactive_socket_recv_op.hpp:110
#15 0x000000000040e174 in complete (bytes_transferred=<optimized out>, ec=..., owner=..., this=0x62ea40) at /usr/include/boost/asio/detail/task_io_service_operation.hpp:37
#16 do_run_one (ec=..., this_thread=..., lock=..., this=0x62dd10) at /usr/include/boost/asio/detail/impl/task_io_service.ipp:384
#17 boost::asio::detail::task_io_service::run (this=0x62dd10, ec=...) at /usr/include/boost/asio/detail/impl/task_io_service.ipp:153
#18 0x00000000004074c5 in run (this=0x7fffffffe450) at /usr/include/boost/asio/impl/io_service.ipp:59
#19 http::server::server::run (this=this@entry=0x7fffffffe450) at server.cpp:148
#20 0x0000000000406cfd in main (argc=<optimized out>, argv=<optimized out>) at main.cpp:16

UNRESOLVED: Buffer Overflow backtrace request.cpp on line 13.

#0  0x00007ffff6bf3c37 in __GI_raise (sig=sig@entry=6) at ../nptl/sysdeps/unix/sysv/linux/raise.c:56
#1  0x00007ffff6bf7028 in __GI_abort () at abort.c:89
#2  0x00007ffff6c302a4 in __libc_message (do_abort=do_abort@entry=2, fmt=fmt@entry=0x7ffff6d3c113 "*** %s ***: %s terminated\n") at ../sysdeps/posix/libc_fatal.c:175
#3  0x00007ffff6cc7bbc in __GI___fortify_fail (msg=<optimized out>, msg@entry=0x7ffff6d3c0aa "buffer overflow detected") at fortify_fail.c:38
#4  0x00007ffff6cc6a90 in __GI___chk_fail () at chk_fail.c:28
#5  0x0000000000412723 in memcpy (__len=<optimized out>, __src=<optimized out>, __dest=0x7fffffffa100) at /usr/include/x86_64-linux-gnu/bits/string3.h:51
#6  http::server::Request::Parse (
    raw_request="GET /css/style.css HTTP/1.1\r\nHost: localhost:8081\r\nUser-Agent: Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:51.0) Gecko/20100101 Firefox/51.0\r\nAccept: text/css,*/*;q=0.1\r\nAccept-Language: en-US,en;q=0.5"...) at request.cpp:13
#7  0x00000000004089dc in operator() (__closure=<optimized out>, bytes=<optimized out>, ec=...) at server.cpp:48
#8  operator() (this=<optimized out>) at /usr/include/boost/asio/detail/bind_handler.hpp:127
#9  asio_handler_invoke<boost::asio::detail::binder2<http::server::connection::do_read()::__lambda0, boost::system::error_code, long unsigned int> > (function=...)
    at /usr/include/boost/asio/handler_invoke_hook.hpp:64
#10 invoke<boost::asio::detail::binder2<http::server::connection::do_read()::__lambda0, boost::system::error_code, long unsigned int>, http::server::connection::do_read()::__lambda0> (context=..., function=...) at /usr/include/boost/asio/detail/handler_invoke_helpers.hpp:37
#11 boost::asio::detail::reactive_socket_recv_op<boost::asio::mutable_buffers_1, http::server::connection::do_read()::__lambda0>::do_complete(boost::asio::detail::io_service_impl *, boost::asio::detail::operation *, const boost::system::error_code &, std::size_t) (owner=0x62ed10, base=<optimized out>)
    at /usr/include/boost/asio/detail/reactive_socket_recv_op.hpp:110
#12 0x000000000040e454 in complete (bytes_transferred=<optimized out>, ec=..., owner=..., this=0x630750) at /usr/include/boost/asio/detail/task_io_service_operation.hpp:37
#13 do_run_one (ec=..., this_thread=..., lock=..., this=0x62ed10) at /usr/include/boost/asio/detail/impl/task_io_service.ipp:384
#14 boost::asio::detail::task_io_service::run (this=0x62ed10, ec=...) at /usr/include/boost/asio/detail/impl/task_io_service.ipp:153
#15 0x00000000004075a5 in run (this=0x7fffffffe450) at /usr/include/boost/asio/impl/io_service.ipp:59
#16 http::server::server::run (this=this@entry=0x7fffffffe450) at server.cpp:157
#17 0x0000000000406ddd in main (argc=<optimized out>, argv=<optimized out>) at main.cpp:16

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.