1 /*
2 * libwebsockets - small server side websockets and web server implementation
3 *
4 * Copyright (C) 2020 Andy Green <andy@warmcat.com>
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 * of this software and associated documentation files (the "Software"), to
8 * deal in the Software without restriction, including without limitation the
9 * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
10 * sell copies of the Software, and to permit persons to whom the Software is
11 * furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice shall be included in
14 * all copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
22 * IN THE SOFTWARE.
23 *
24 * C++ classes for Secure Streams - file transaction
25 */
26
27 #include <libwebsockets.hxx>
28
29 #include <stdlib.h>
30 #include <fcntl.h>
31 #include <unistd.h>
32
33 static lws_ss_state_return_t
lssfile_rx(void * userobj,const uint8_t * buf,size_t len,int flags)34 lssfile_rx(void *userobj, const uint8_t *buf, size_t len, int flags)
35 {
36 lssFile *lf = (lssFile *)userobj_to_lss(userobj);
37
38 return lf->write(buf, len, flags);
39 }
40
41 static lws_ss_state_return_t
lssfile_tx(void * userobj,lws_ss_tx_ordinal_t ord,uint8_t * buf,size_t * len,int * flags)42 lssfile_tx(void *userobj, lws_ss_tx_ordinal_t ord,uint8_t *buf, size_t *len,
43 int *flags)
44 {
45 /*
46 * TODO: we don't know how to send things yet
47 */
48 return LWSSSSRET_TX_DONT_SEND;
49 }
50
51 static lws_ss_state_return_t
lssfile_state(void * userobj,void * h_src,lws_ss_constate_t state,lws_ss_tx_ordinal_t ack)52 lssfile_state(void *userobj, void *h_src, lws_ss_constate_t state,
53 lws_ss_tx_ordinal_t ack)
54 {
55 lssFile *lf = (lssFile *)userobj_to_lss(userobj);
56
57 lwsl_info("%s: state %s\n", __func__, lws_ss_state_name(state));
58
59 switch (state) {
60
61 /*
62 * These reflect some kind of final disposition for the transaction,
63 * that we want to report along with the completion. If no other chance
64 * we'll report DESTROYING
65 */
66
67 case LWSSSCS_DESTROYING:
68 case LWSSSCS_ALL_RETRIES_FAILED:
69 case LWSSSCS_QOS_ACK_REMOTE:
70 case LWSSSCS_QOS_NACK_REMOTE:
71 lf->call_completion(state);
72
73 if (state == LWSSSCS_DESTROYING) {
74 /*
75 * we get DESTROYING because we are already in the
76 * middle of destroying the m_ss, unlink the C++ lss
77 * from the ss handle so it won't recursively try to
78 * destroy it
79 */
80 lf->m_ss = NULL;
81 delete lf;
82 }
83
84 break;
85 }
86
87 return LWSSSSRET_OK;
88 }
89
write(const uint8_t * buf,size_t len,int flags)90 lws_ss_state_return_t lssFile::write(const uint8_t *buf, size_t len, int flags)
91 {
92 if (fd == LWS_INVALID_FILE) {
93
94 fd = open(path.c_str(), O_WRONLY | O_CREAT | O_TRUNC, 0640);
95 if (fd == LWS_INVALID_FILE)
96 return LWSSSSRET_DESTROY_ME;
97 }
98
99 if (::write(fd, buf, len) != len) {
100 close(fd);
101 fd = LWS_INVALID_FILE;
102
103 return LWSSSSRET_DESTROY_ME;
104 }
105
106 rxlen += len;
107
108 if (flags & LWSSS_FLAG_EOM) {
109 close(fd);
110 fd = LWS_INVALID_FILE;
111 }
112
113 return LWSSSSRET_OK;
114 }
115
lssFile(lws_ctx_t ctx,std::string uri,std::string _path,lsscomp_t comp,bool _psh)116 lssFile::lssFile(lws_ctx_t ctx, std::string uri, std::string _path,
117 lsscomp_t comp, bool _psh) :
118 lss(ctx, uri, comp, _psh, lssfile_rx, lssfile_tx, lssfile_state)
119 {
120 path = _path;
121 push = _psh;
122 fd = LWS_INVALID_FILE;
123 }
124
~lssFile()125 lssFile::~lssFile()
126 {
127 if (fd == LWS_INVALID_FILE)
128 return;
129
130 close(fd);
131 fd = LWS_INVALID_FILE;
132 }
133