| /* |
| * libwebsockets - small server side websockets and web server implementation |
| * |
| * Copyright (C) 2020 Andy Green <andy@warmcat.com> |
| * |
| * Permission is hereby granted, free of charge, to any person obtaining a copy |
| * of this software and associated documentation files (the "Software"), to |
| * deal in the Software without restriction, including without limitation the |
| * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or |
| * sell copies of the Software, and to permit persons to whom the Software is |
| * furnished to do so, subject to the following conditions: |
| * |
| * The above copyright notice and this permission notice shall be included in |
| * all copies or substantial portions of the Software. |
| * |
| * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
| * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
| * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |
| * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
| * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING |
| * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS |
| * IN THE SOFTWARE. |
| * |
| * C++ classes for Secure Streams - file transaction |
| */ |
| |
| #include <libwebsockets.hxx> |
| |
| #include <stdlib.h> |
| #include <fcntl.h> |
| #include <unistd.h> |
| |
| static lws_ss_state_return_t |
| lssfile_rx(void *userobj, const uint8_t *buf, size_t len, int flags) |
| { |
| lssFile *lf = (lssFile *)userobj_to_lss(userobj); |
| |
| return lf->write(buf, len, flags); |
| } |
| |
| static lws_ss_state_return_t |
| lssfile_tx(void *userobj, lws_ss_tx_ordinal_t ord,uint8_t *buf, size_t *len, |
| int *flags) |
| { |
| /* |
| * TODO: we don't know how to send things yet |
| */ |
| return LWSSSSRET_TX_DONT_SEND; |
| } |
| |
| static lws_ss_state_return_t |
| lssfile_state(void *userobj, void *h_src, lws_ss_constate_t state, |
| lws_ss_tx_ordinal_t ack) |
| { |
| lssFile *lf = (lssFile *)userobj_to_lss(userobj); |
| |
| lwsl_info("%s: state %s\n", __func__, lws_ss_state_name(state)); |
| |
| switch (state) { |
| |
| /* |
| * These reflect some kind of final disposition for the transaction, |
| * that we want to report along with the completion. If no other chance |
| * we'll report DESTROYING |
| */ |
| |
| case LWSSSCS_DESTROYING: |
| case LWSSSCS_ALL_RETRIES_FAILED: |
| case LWSSSCS_QOS_ACK_REMOTE: |
| case LWSSSCS_QOS_NACK_REMOTE: |
| lf->call_completion(state); |
| |
| if (state == LWSSSCS_DESTROYING) { |
| /* |
| * we get DESTROYING because we are already in the |
| * middle of destroying the m_ss, unlink the C++ lss |
| * from the ss handle so it won't recursively try to |
| * destroy it |
| */ |
| lf->m_ss = NULL; |
| delete lf; |
| } |
| |
| break; |
| } |
| |
| return LWSSSSRET_OK; |
| } |
| |
| lws_ss_state_return_t lssFile::write(const uint8_t *buf, size_t len, int flags) |
| { |
| if (fd == LWS_INVALID_FILE) { |
| |
| fd = open(path.c_str(), O_WRONLY | O_CREAT | O_TRUNC, 0640); |
| if (fd == LWS_INVALID_FILE) |
| return LWSSSSRET_DESTROY_ME; |
| } |
| |
| if (::write(fd, buf, len) != len) { |
| close(fd); |
| fd = LWS_INVALID_FILE; |
| |
| return LWSSSSRET_DESTROY_ME; |
| } |
| |
| rxlen += len; |
| |
| if (flags & LWSSS_FLAG_EOM) { |
| close(fd); |
| fd = LWS_INVALID_FILE; |
| } |
| |
| return LWSSSSRET_OK; |
| } |
| |
| lssFile::lssFile(lws_ctx_t ctx, std::string uri, std::string _path, |
| lsscomp_t comp, bool _psh) : |
| lss(ctx, uri, comp, _psh, lssfile_rx, lssfile_tx, lssfile_state) |
| { |
| path = _path; |
| push = _psh; |
| fd = LWS_INVALID_FILE; |
| } |
| |
| lssFile::~lssFile() |
| { |
| if (fd == LWS_INVALID_FILE) |
| return; |
| |
| close(fd); |
| fd = LWS_INVALID_FILE; |
| } |