2 * ws protocol handler plugin for "POST demo"
4 * Copyright (C) 2010-2016 Andy Green <andy@warmcat.com>
6 * This file is made available under the Creative Commons CC0 1.0
7 * Universal Public Domain Dedication.
9 * The person who associated a work with this deed has dedicated
10 * the work to the public domain by waiving all of his or her rights
11 * to the work worldwide under copyright law, including all related
12 * and neighboring rights, to the extent allowed by law. You can copy,
13 * modify, distribute and perform the work, even for commercial purposes,
14 * all without asking permission.
16 * These test plugins are intended to be adapted for use in your code, which
17 * may be proprietary. So unlike the library itself, they are licensed
21 #if !defined (LWS_PLUGIN_STATIC)
24 #include "../lib/libwebsockets.h"
29 #include <sys/types.h>
36 struct per_session_data__post_demo {
38 char result[LWS_PRE + 512];
43 #if !defined(LWS_WITH_ESP8266)
48 static const char * const param_names[] = {
55 enum enum_param_names {
63 file_upload_cb(void *data, const char *name, const char *filename,
64 char *buf, int len, enum lws_spa_fileupload_states state)
66 struct per_session_data__post_demo *pss =
67 (struct per_session_data__post_demo *)data;
72 strncpy(pss->filename, filename, sizeof(pss->filename) - 1);
73 /* we get the original filename in @filename arg, but for
74 * simple demo use a fixed name so we don't have to deal with
76 #if !defined(LWS_WITH_ESP8266)
77 pss->fd = (lws_filefd_type)open("/tmp/post-file",
78 O_CREAT | O_TRUNC | O_RDWR, 0600);
81 case LWS_UFS_FINAL_CONTENT:
84 pss->file_length += len;
86 /* if the file length is too big, drop it */
87 if (pss->file_length > 100000)
90 #if !defined(LWS_WITH_ESP8266)
91 n = write((int)pss->fd, buf, len);
92 lwsl_notice("%s: write %d says %d\n", __func__, len, n);
94 lwsl_notice("%s: Received chunk size %d\n", __func__, len);
97 if (state == LWS_UFS_CONTENT)
99 #if !defined(LWS_WITH_ESP8266)
101 pss->fd = LWS_INVALID_FILE;
110 callback_post_demo(struct lws *wsi, enum lws_callback_reasons reason,
111 void *user, void *in, size_t len)
113 struct per_session_data__post_demo *pss =
114 (struct per_session_data__post_demo *)user;
115 unsigned char *buffer;
116 unsigned char *p, *start, *end;
120 case LWS_CALLBACK_HTTP_BODY:
121 /* create the POST argument parser if not already existing */
123 pss->spa = lws_spa_create(wsi, param_names,
124 ARRAY_SIZE(param_names), 1024,
125 file_upload_cb, pss);
129 pss->filename[0] = '\0';
130 pss->file_length = 0;
133 /* let it parse the POST data */
134 if (lws_spa_process(pss->spa, in, len))
138 case LWS_CALLBACK_HTTP_BODY_COMPLETION:
139 lwsl_debug("LWS_CALLBACK_HTTP_BODY_COMPLETION\n");
140 /* call to inform no more payload data coming */
141 lws_spa_finalize(pss->spa);
143 p = (unsigned char *)pss->result + LWS_PRE;
144 end = p + sizeof(pss->result) - LWS_PRE - 1;
145 p += sprintf((char *)p,
146 "<html><body><h1>Form results (after urldecoding)</h1>"
147 "<table><tr><td>Name</td><td>Length</td><td>Value</td></tr>");
149 for (n = 0; n < ARRAY_SIZE(param_names); n++)
150 p += lws_snprintf((char *)p, end - p,
151 "<tr><td><b>%s</b></td><td>%d</td><td>%s</td></tr>",
153 lws_spa_get_length(pss->spa, n),
154 lws_spa_get_string(pss->spa, n));
156 p += lws_snprintf((char *)p, end - p, "</table><br><b>filename:</b> %s, <b>length</b> %ld",
157 pss->filename, pss->file_length);
159 p += lws_snprintf((char *)p, end - p, "</body></html>");
160 pss->result_len = p - (unsigned char *)(pss->result + LWS_PRE);
164 p = buffer + LWS_PRE;
166 end = p + n - LWS_PRE - 1;
168 if (lws_add_http_header_status(wsi, HTTP_STATUS_OK, &p, end))
171 if (lws_add_http_header_by_token(wsi, WSI_TOKEN_HTTP_CONTENT_TYPE,
172 (unsigned char *)"text/html", 9, &p, end))
174 if (lws_add_http_header_content_length(wsi, pss->result_len, &p, end))
176 if (lws_finalize_http_header(wsi, &p, end))
179 n = lws_write(wsi, start, p - start, LWS_WRITE_HTTP_HEADERS);
184 lws_callback_on_writable(wsi);
187 case LWS_CALLBACK_HTTP_WRITEABLE:
188 lwsl_debug("LWS_CALLBACK_HTTP_WRITEABLE: sending %d\n",
190 n = lws_write(wsi, (unsigned char *)pss->result + LWS_PRE,
191 pss->result_len, LWS_WRITE_HTTP);
196 case LWS_CALLBACK_HTTP_DROP_PROTOCOL:
197 /* called when our wsi user_space is going to be destroyed */
199 lws_spa_destroy(pss->spa);
216 if (lws_http_transaction_completed(wsi))
222 #define LWS_PLUGIN_PROTOCOL_POST_DEMO \
224 "protocol-post-demo", \
225 callback_post_demo, \
226 sizeof(struct per_session_data__post_demo), \
230 #if !defined (LWS_PLUGIN_STATIC)
232 static const struct lws_protocols protocols[] = {
233 LWS_PLUGIN_PROTOCOL_POST_DEMO
236 LWS_EXTERN LWS_VISIBLE int
237 init_protocol_post_demo(struct lws_context *context,
238 struct lws_plugin_capability *c)
240 if (c->api_magic != LWS_PLUGIN_API_MAGIC) {
241 lwsl_err("Plugin API %d, library API %d", LWS_PLUGIN_API_MAGIC,
246 c->protocols = protocols;
247 c->count_protocols = ARRAY_SIZE(protocols);
248 c->extensions = NULL;
249 c->count_extensions = 0;
254 LWS_EXTERN LWS_VISIBLE int
255 destroy_protocol_post_demo(struct lws_context *context)