• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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