Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions src/main/c/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ set(SEASOCKS_SOURCE_FILES
sha1/sha1.h
StringUtil.cpp
util/CrackedUri.cpp
util/FileResponse.cpp
util/Json.cpp
util/PathHandler.cpp
util/RootPageHandler.cpp
Expand Down
3 changes: 3 additions & 0 deletions src/main/c/Connection.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -600,6 +600,9 @@ void Connection::sendHybi(uint8_t opcode, const uint8_t* webSocketResponse, size

zlibContext.deflate(webSocketResponse, messageLength, compressed);

// Remove 4-byte tail end prior to transmission (see RFC 7692, section 7.2.1)
compressed.resize(compressed.size() - 4);

LS_DEBUG(_logger, "Compression result: " << messageLength << " bytes -> " << compressed.size() << " bytes");
sendHybiData(compressed.data(), compressed.size());
} else {
Expand Down
5 changes: 5 additions & 0 deletions src/main/c/Response.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
// POSSIBILITY OF SUCH DAMAGE.

#include "internal/ConcreteResponse.h"
#include "seasocks/util/FileResponse.h"

#include "seasocks/Response.h"

Expand Down Expand Up @@ -69,4 +70,8 @@ std::shared_ptr<Response> Response::htmlResponse(const std::string& response) {
SynchronousResponse::Headers(), true);
}

std::shared_ptr<Response> Response::fileResponse(const Request &request, const std::string &filePath, const std::string &contentType, bool allowCompression, bool allowCaching) {
return std::make_shared<FileResponse>(request, filePath, contentType, allowCompression, allowCaching);
}

}
10 changes: 10 additions & 0 deletions src/main/c/StringUtil.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
#include <cstddef>
#include <cstdio>
#include <cstring>
#include <ctime>

namespace seasocks {

Expand Down Expand Up @@ -125,6 +126,15 @@ std::string webtime(time_t time) {
return buf;
}

time_t webtime(std::string time) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Const-Ref here?

struct tm tm;
if (strptime(time.c_str(), "%a, %d %b %Y %H:%M:%S %Z", &tm) == nullptr) {
return -1;
}
tm.tm_isdst = -1;
return timegm(&tm);
}

std::string now() {
return webtime(time(nullptr));
}
Expand Down
2 changes: 2 additions & 0 deletions src/main/c/seasocks/Response.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@

#pragma once

#include "seasocks/Request.h"
#include "seasocks/ResponseCode.h"

#include <map>
Expand Down Expand Up @@ -52,6 +53,7 @@ class Response {
static std::shared_ptr<Response> textResponse(const std::string& response);
static std::shared_ptr<Response> jsonResponse(const std::string& response);
static std::shared_ptr<Response> htmlResponse(const std::string& response);
static std::shared_ptr<Response> fileResponse(const Request &request, const std::string &filePath, const std::string &contentType, bool allowCompression, bool allowCaching);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is a forward declaration possible here (to avoid the inclusion of Request.h)?

};

}
3 changes: 3 additions & 0 deletions src/main/c/seasocks/ResponseCodeDefs.h
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,9 @@ SEASOCKS_DEFINE_RESPONSECODE(402, PaymentRequired, "Payment Required")
SEASOCKS_DEFINE_RESPONSECODE(403, Forbidden, "Forbidden")
SEASOCKS_DEFINE_RESPONSECODE(404, NotFound, "Not Found")
SEASOCKS_DEFINE_RESPONSECODE(405, MethodNotAllowed, "Method Not Allowed")
SEASOCKS_DEFINE_RESPONSECODE(412, PreconditionFailed, "Precondition Failed")
SEASOCKS_DEFINE_RESPONSECODE(416, RangeNotSatisfiable, "Range Not Satisfiable")

// more here...

SEASOCKS_DEFINE_RESPONSECODE(500, InternalServerError, "Internal Server Error")
Expand Down
2 changes: 2 additions & 0 deletions src/main/c/seasocks/StringUtil.h
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,8 @@ void replace(std::string& string, const std::string& find, const std::string& re
bool caseInsensitiveSame(const std::string &lhs, const std::string &rhs);

std::string webtime(time_t time);
// Returns -1 on error
time_t webtime(std::string time);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is it reasonable to throw an exception in case of an error here?


std::string now();

Expand Down
5 changes: 1 addition & 4 deletions src/main/c/seasocks/ZlibContext.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -95,9 +95,6 @@ struct ZlibContext::Impl {

output.insert(output.end(), buffer, buffer + sizeof(buffer) - deflateStream.avail_out);
} while (deflateStream.avail_out == 0);

// Remove 4-byte tail end prior to transmission (see RFC 7692, section 7.2.1)
output.resize(output.size() - 4);
}

bool inflate(std::vector<uint8_t> &input, std::vector<uint8_t> &output, int &zlibError) {
Expand Down Expand Up @@ -142,4 +139,4 @@ bool ZlibContext::inflate(std::vector<uint8_t> &input, std::vector<uint8_t> &out
return _impl->inflate(input, output, zlibError);
}

}
}
71 changes: 71 additions & 0 deletions src/main/c/seasocks/util/FileResponse.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
// Copyright (c) 2018, Joe Balough
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@scallopedllama / @mattgodbolt does this require an user to handle two licenses – the default text and this one?

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm no lawyer, but I don't think the copyright affects the license. In other projects I have the author put their name, as long as the license remains intact below

// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// Redistributions of source code must retain the above copyright notice, this
// list of conditions and the following disclaimer.
//
// Redistributions in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.

#pragma once

#include <memory>

#include "seasocks/Response.h"
#include "seasocks/ResponseWriter.h"
#include "seasocks/Request.h"
#include "seasocks/util/PathHandler.h"

namespace seasocks {

class FileResponse : public Response
{
public:
/// Supports returning file data back to a client supporting deflate compression on the fly.
/// If compression is disabled, file resuming is supported.
/// If compression is enabled, files resumption is disabled and file size is not provided to the client.
/// These are only determinable if the file is compressed before transmission, which this Response does not do.
/// @param request Incoming request
/// @param filePath Path to file to return to client in filesystem
/// @param contentType Content-Type header value for file
/// @param allowCompression Whether to support compressing the file on the fly with deflate during transmission (disables resuming and content length)
/// @param allowCaching Whether the file contents are allowed to be cached
explicit FileResponse(const Request &request, const std::string &filePath, const std::string &contentType, bool allowCompression, bool allowCaching);

virtual void handle(std::shared_ptr<ResponseWriter> writer) override;

/// Same as handle but does not spawn a thread
void respond(std::shared_ptr<ResponseWriter> writer);

virtual void cancel() override;


private:

ResponseCode parseHeaders(const off_t fileSize, const time_t fileLastModified, bool sendCompressedData, off_t& fileTransferStart, off_t& fileTransferEnd) const;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If possible avoid out-parameters and eg. return a tuple.


const Request &_request;
std::string _path;
std::string _contentType;
bool _allowCompression;
bool _allowCaching;
bool _cancelled;
};

}
Loading