Exemplo n.º 1
0
static void
esp8266_cb_sent(void *arg)
{
	struct espconn *conn = arg;
	struct lws *wsi = conn->reverse;
	struct lws_context_per_thread *pt = &wsi->context->pt[(int)wsi->tsi];

//	lwsl_err("%s: wsi %p (psc %d) wsi->position_in_fds_table=%d\n", __func__, wsi, wsi->pending_send_completion, wsi->position_in_fds_table);

	wsi->pending_send_completion--;
	if (wsi->close_is_pending_send_completion &&
	    !wsi->pending_send_completion &&
	    !lws_partial_buffered(wsi)) {
		lwsl_notice("doing delayed close\n");
		lws_close_free_wsi(wsi, LWS_CLOSE_STATUS_NOSTATUS);
	}

	if (pt->fds[wsi->position_in_fds_table].events & LWS_POLLOUT) {
		struct lws_pollfd pollfd;

	        pollfd.fd = arg;
	        pollfd.events = LWS_POLLOUT;
	        pollfd.revents = LWS_POLLOUT;

//	        lwsl_notice("informing POLLOUT\n");

	        lws_service_fd(lws_get_context(wsi), &pollfd);
	}
}
static int
callback_Play(struct libwebsocket_context *context,
			struct libwebsocket *wsi,
			enum libwebsocket_callback_reasons reason,
					       void *user, void *in, size_t len)
{
	HostStuff* phoststuff=(HostStuff*)libwebsocket_context_user(context);
	
	switch (reason) 
	{
		case LWS_CALLBACK_ESTABLISHED:
			{
				((PlayBackData*)user)->p_queue=0;
				break;
			}
		case LWS_CALLBACK_CLOSED:
			{
				queue<string> * _queue = ((PlayBackData*)user)->p_queue;
				delete _queue;
				((PlayBackData*)user)->p_queue=0;
				WebSocketFeedBackSession* se=((PlayBackData*)user)->p_se;
				se->close();
				delete se;
				break;
			}
		case LWS_CALLBACK_RECEIVE:
			{
				queue<string> * _queue = ((PlayBackData*)user)->p_queue;
				delete _queue;
				
				_queue = ((PlayBackData*)user)->p_queue=new queue<string>;
				WebSocketFeedBackSession* se=((PlayBackData*)user)->p_se=new WebSocketFeedBackSession(context, wsi, _queue);
				IncomingSession(phoststuff, (char*)in, se);
				break;
			}
		case LWS_CALLBACK_SERVER_WRITEABLE:
			{
				queue<string> * _queue = *((queue<string> **)user);
				
				unsigned char buf[LWS_SEND_BUFFER_PRE_PADDING + 1024 +
								  LWS_SEND_BUFFER_POST_PADDING];
				unsigned char *p = &buf[LWS_SEND_BUFFER_PRE_PADDING];						
				if (!_queue->empty() && lws_partial_buffered (wsi)!=1) 
				{
					string s=_queue->front();
					_queue->pop();
					int n = sprintf((char *)p, s.data());
					libwebsocket_write(wsi, p, n, LWS_WRITE_TEXT);			
				}
				if (!_queue->empty()) libwebsocket_callback_on_writable (context, wsi);
				break;
			}
	}
	return 0;
}
Exemplo n.º 3
0
static int
callback_lws_mirror(struct libwebsocket_context *context,
			struct libwebsocket *wsi,
			enum libwebsocket_callback_reasons reason,
					       void *user, void *in, size_t len)
{
	int n;
	struct per_session_data__lws_mirror *pss = (struct per_session_data__lws_mirror *)user;

	switch (reason) {

	case LWS_CALLBACK_ESTABLISHED:
		lwsl_info("callback_lws_mirror: LWS_CALLBACK_ESTABLISHED\n");
		pss->ringbuffer_tail = ringbuffer_head;
		pss->wsi = wsi;
		break;

	case LWS_CALLBACK_PROTOCOL_DESTROY:
		lwsl_notice("mirror protocol cleaning up\n");
		for (n = 0; n < sizeof ringbuffer / sizeof ringbuffer[0]; n++)
			if (ringbuffer[n].payload)
				free(ringbuffer[n].payload);
		break;

	case LWS_CALLBACK_SERVER_WRITEABLE:
		if (close_testing)
			break;
		while (pss->ringbuffer_tail != ringbuffer_head) {

			n = libwebsocket_write(wsi, (unsigned char *)
				   ringbuffer[pss->ringbuffer_tail].payload +
				   LWS_SEND_BUFFER_PRE_PADDING,
				   ringbuffer[pss->ringbuffer_tail].len,
								LWS_WRITE_TEXT);
			if (n < 0) {
				lwsl_err("ERROR %d writing to mirror socket\n", n);
				return -1;
			}
			if (n < ringbuffer[pss->ringbuffer_tail].len)
				lwsl_err("mirror partial write %d vs %d\n",
				       n, ringbuffer[pss->ringbuffer_tail].len);

			if (pss->ringbuffer_tail == (MAX_MESSAGE_QUEUE - 1))
				pss->ringbuffer_tail = 0;
			else
				pss->ringbuffer_tail++;

			if (((ringbuffer_head - pss->ringbuffer_tail) &
				  (MAX_MESSAGE_QUEUE - 1)) == (MAX_MESSAGE_QUEUE - 15))
				libwebsocket_rx_flow_allow_all_protocol(
					       libwebsockets_get_protocol(wsi));

			// lwsl_debug("tx fifo %d\n", (ringbuffer_head - pss->ringbuffer_tail) & (MAX_MESSAGE_QUEUE - 1));

			if (lws_partial_buffered(wsi) || lws_send_pipe_choked(wsi)) {
				libwebsocket_callback_on_writable(context, wsi);
				break;
			}
			/*
			 * for tests with chrome on same machine as client and
			 * server, this is needed to stop chrome choking
			 */
#ifdef _WIN32
			Sleep(1);
#else
			usleep(1);
#endif
		}
		break;

	case LWS_CALLBACK_RECEIVE:

		if (((ringbuffer_head - pss->ringbuffer_tail) &
				  (MAX_MESSAGE_QUEUE - 1)) == (MAX_MESSAGE_QUEUE - 1)) {
			lwsl_err("dropping!\n");
			goto choke;
		}

		if (ringbuffer[ringbuffer_head].payload)
			free(ringbuffer[ringbuffer_head].payload);

		ringbuffer[ringbuffer_head].payload =
				malloc(LWS_SEND_BUFFER_PRE_PADDING + len +
						  LWS_SEND_BUFFER_POST_PADDING);
		ringbuffer[ringbuffer_head].len = len;
		memcpy((char *)ringbuffer[ringbuffer_head].payload +
					  LWS_SEND_BUFFER_PRE_PADDING, in, len);
		if (ringbuffer_head == (MAX_MESSAGE_QUEUE - 1))
			ringbuffer_head = 0;
		else
			ringbuffer_head++;

		if (((ringbuffer_head - pss->ringbuffer_tail) &
				  (MAX_MESSAGE_QUEUE - 1)) != (MAX_MESSAGE_QUEUE - 2))
			goto done;

choke:
		lwsl_debug("LWS_CALLBACK_RECEIVE: throttling %p\n", wsi);
		libwebsocket_rx_flow_control(wsi, 0);

//		lwsl_debug("rx fifo %d\n", (ringbuffer_head - pss->ringbuffer_tail) & (MAX_MESSAGE_QUEUE - 1));
done:
		libwebsocket_callback_on_writable_all_protocol(
					       libwebsockets_get_protocol(wsi));
		break;

	/*
	 * this just demonstrates how to use the protocol filter. If you won't
	 * study and reject connections based on header content, you don't need
	 * to handle this callback
	 */

	case LWS_CALLBACK_FILTER_PROTOCOL_CONNECTION:
		dump_handshake_info(wsi);
		/* you could return non-zero here and kill the connection */
		break;

	default:
		break;
	}

	return 0;
}
Exemplo n.º 4
0
static int callback_http(struct libwebsocket_context *context,
		struct libwebsocket *wsi,
		enum libwebsocket_callback_reasons reason, void *user,
							   void *in, size_t len)
{
#if 0
	char client_name[128];
	char client_ip[128];
#endif
	char buf[256];
	char leaf_path[1024];
	char b64[64];
	struct timeval tv;
	int n, m;
	unsigned char *p;
	char *other_headers;
	static unsigned char buffer[4096];
	struct stat stat_buf;
	struct per_session_data__http *pss =
			(struct per_session_data__http *)user;
	const char *mimetype;
#ifdef EXTERNAL_POLL
	struct libwebsocket_pollargs *pa = (struct libwebsocket_pollargs *)in;
#endif
	unsigned char *end;
	switch (reason) {
	case LWS_CALLBACK_HTTP:

		dump_handshake_info(wsi);

		if (len < 1) {
			libwebsockets_return_http_status(context, wsi,
						HTTP_STATUS_BAD_REQUEST, NULL);
			goto try_to_reuse;
		}

		/* this example server has no concept of directories */
		if (strchr((const char *)in + 1, '/')) {
			libwebsockets_return_http_status(context, wsi,
						HTTP_STATUS_FORBIDDEN, NULL);
			goto try_to_reuse;
		}

		/* if a legal POST URL, let it continue and accept data */
		if (lws_hdr_total_length(wsi, WSI_TOKEN_POST_URI))
			return 0;

		/* check for the "send a big file by hand" example case */

		if (!strcmp((const char *)in, "/leaf.jpg")) {
			if (strlen(resource_path) > sizeof(leaf_path) - 10)
				return -1;
			sprintf(leaf_path, "%s/leaf.jpg", resource_path);

			/* well, let's demonstrate how to send the hard way */

			p = buffer + LWS_SEND_BUFFER_PRE_PADDING;
			end = p + sizeof(buffer) - LWS_SEND_BUFFER_PRE_PADDING;
#ifdef WIN32
			pss->fd = open(leaf_path, O_RDONLY | _O_BINARY);
#else
			pss->fd = open(leaf_path, O_RDONLY);
#endif

			if (pss->fd < 0)
				return -1;

			fstat(pss->fd, &stat_buf);

			/*
			 * we will send a big jpeg file, but it could be
			 * anything.  Set the Content-Type: appropriately
			 * so the browser knows what to do with it.
			 * 
			 * Notice we use the APIs to build the header, which
			 * will do the right thing for HTTP 1/1.1 and HTTP2
			 * depending on what connection it happens to be working
			 * on
			 */
			if (lws_add_http_header_status(context, wsi, 200, &p, end))
				return 1;
			if (lws_add_http_header_by_token(context, wsi, WSI_TOKEN_HTTP_SERVER, (unsigned char *)"libwebsockets", 13, &p, end))
				return 1;
			if (lws_add_http_header_by_token(context, wsi, WSI_TOKEN_HTTP_CONTENT_TYPE, (unsigned char *)"image/jpeg", 10, &p, end))
				return 1;
			if (lws_add_http_header_content_length(context, wsi,stat_buf.st_size, &p, end))
				return 1;
			if (lws_finalize_http_header(context, wsi, &p, end))
				return 1;

			/*
			 * send the http headers...
			 * this won't block since it's the first payload sent
			 * on the connection since it was established
			 * (too small for partial)
			 * 
			 * Notice they are sent using LWS_WRITE_HTTP_HEADERS
			 * which also means you can't send body too in one step,
			 * this is mandated by changes in HTTP2
			 */

			n = libwebsocket_write(wsi,
					       buffer + LWS_SEND_BUFFER_PRE_PADDING,
					       p - (buffer + LWS_SEND_BUFFER_PRE_PADDING),
					       LWS_WRITE_HTTP_HEADERS);

			if (n < 0) {
				close(pss->fd);
				return -1;
			}
			/*
			 * book us a LWS_CALLBACK_HTTP_WRITEABLE callback
			 */
			libwebsocket_callback_on_writable(context, wsi);
			break;
		}

		/* if not, send a file the easy way */
		strcpy(buf, resource_path);
		if (strcmp(in, "/")) {
			if (*((const char *)in) != '/')
				strcat(buf, "/");
			strncat(buf, in, sizeof(buf) - strlen(resource_path));
		} else /* default file to serve */
			strcat(buf, "/test.html");
		buf[sizeof(buf) - 1] = '\0';

		/* refuse to serve files we don't understand */
		mimetype = get_mimetype(buf);
		if (!mimetype) {
			lwsl_err("Unknown mimetype for %s\n", buf);
			libwebsockets_return_http_status(context, wsi,
				      HTTP_STATUS_UNSUPPORTED_MEDIA_TYPE, NULL);
			return -1;
		}

		/* demostrates how to set a cookie on / */

		other_headers = NULL;
		n = 0;
		if (!strcmp((const char *)in, "/") &&
			   !lws_hdr_total_length(wsi, WSI_TOKEN_HTTP_COOKIE)) {
			/* this isn't very unguessable but it'll do for us */
			gettimeofday(&tv, NULL);
			n = sprintf(b64, "test=LWS_%u_%u_COOKIE;Max-Age=360000",
				(unsigned int)tv.tv_sec,
				(unsigned int)tv.tv_usec);

			p = (unsigned char *)leaf_path;

			if (lws_add_http_header_by_name(context, wsi, (unsigned char *)"set-cookie:", (unsigned char *)b64, n, &p, (unsigned char *)leaf_path + sizeof(leaf_path)))
				return 1;
			n = (char *)p - leaf_path;
			other_headers = leaf_path;
		}

		n = libwebsockets_serve_http_file(context, wsi, buf,
						mimetype, other_headers, n);
		if (n < 0 || ((n > 0) && lws_http_transaction_completed(wsi)))
			return -1; /* error or can't reuse connection: close the socket */

		/*
		 * notice that the sending of the file completes asynchronously,
		 * we'll get a LWS_CALLBACK_HTTP_FILE_COMPLETION callback when
		 * it's done
		 */

		break;

	case LWS_CALLBACK_HTTP_BODY:
		strncpy(buf, in, 20);
		buf[20] = '\0';
		if (len < 20)
			buf[len] = '\0';

		lwsl_notice("LWS_CALLBACK_HTTP_BODY: %s... len %d\n",
				(const char *)buf, (int)len);

		break;

	case LWS_CALLBACK_HTTP_BODY_COMPLETION:
		lwsl_notice("LWS_CALLBACK_HTTP_BODY_COMPLETION\n");
		/* the whole of the sent body arrived, close or reuse the connection */
		libwebsockets_return_http_status(context, wsi,
						HTTP_STATUS_OK, NULL);
		goto try_to_reuse;

	case LWS_CALLBACK_HTTP_FILE_COMPLETION:
//		lwsl_info("LWS_CALLBACK_HTTP_FILE_COMPLETION seen\n");
		/* kill the connection after we sent one file */
		goto try_to_reuse;

	case LWS_CALLBACK_HTTP_WRITEABLE:
		/*
		 * we can send more of whatever it is we were sending
		 */
lwsl_info("LWS_CALLBACK_HTTP_WRITEABLE\n");
		do {
			lwsl_info("a\n");
			n = read(pss->fd, buffer + LWS_SEND_BUFFER_PRE_PADDING,
				 sizeof (buffer) - LWS_SEND_BUFFER_PRE_PADDING);
			/* problem reading, close conn */
			if (n < 0)
				goto bail;
			/* sent it all, close conn */
			if (n == 0)
				goto flush_bail;
			lwsl_info("b\n");
			/*
			 * To support HTTP2, must take care about preamble space
			 * and identify when we send the last frame
			 */
			m = libwebsocket_write(wsi,
					       buffer + LWS_SEND_BUFFER_PRE_PADDING,
					       n, LWS_WRITE_HTTP);
			if (m < 0)
				/* write failed, close conn */
				goto bail;
						lwsl_info("c\n");
			/*
			 * http2 won't do this
			 */
			if (m != n)
				/* partial write, adjust */
				lseek(pss->fd, m - n, SEEK_CUR);
			lwsl_info("d\n");
			if (m) /* while still active, extend timeout */
				libwebsocket_set_timeout(wsi,
					PENDING_TIMEOUT_HTTP_CONTENT, 5);
			
			/* if he has indigestion, let him clear it before eating more */
			if (lws_partial_buffered(wsi))
				break;

		} while (!lws_send_pipe_choked(wsi));
					lwsl_info("e\n");
		libwebsocket_callback_on_writable(context, wsi);
					lwsl_info("f\n");
		break;
flush_bail:
		/* true if still partial pending */
		if (lws_partial_buffered(wsi)) {
			libwebsocket_callback_on_writable(context, wsi);
			break;
		}
		close(pss->fd);
		goto try_to_reuse;

bail:
		close(pss->fd);
		return -1;

	/*
	 * callback for confirming to continue with client IP appear in
	 * protocol 0 callback since no websocket protocol has been agreed
	 * yet.  You can just ignore this if you won't filter on client IP
	 * since the default uhandled callback return is 0 meaning let the
	 * connection continue.
	 */

	case LWS_CALLBACK_FILTER_NETWORK_CONNECTION:
#if 0
		libwebsockets_get_peer_addresses(context, wsi, (int)(long)in, client_name,
			     sizeof(client_name), client_ip, sizeof(client_ip));

		fprintf(stderr, "Received network connect from %s (%s)\n",
							client_name, client_ip);
#endif
		/* if we returned non-zero from here, we kill the connection */
		break;

#ifdef EXTERNAL_POLL
	/*
	 * callbacks for managing the external poll() array appear in
	 * protocol 0 callback
	 */

	case LWS_CALLBACK_LOCK_POLL:
		/*
		 * lock mutex to protect pollfd state
		 * called before any other POLL related callback
		 */
		break;

	case LWS_CALLBACK_UNLOCK_POLL:
		/*
		 * unlock mutex to protect pollfd state when
		 * called after any other POLL related callback
		 */
		break;

	case LWS_CALLBACK_ADD_POLL_FD:

		if (count_pollfds >= max_poll_elements) {
			lwsl_err("LWS_CALLBACK_ADD_POLL_FD: too many sockets to track\n");
			return 1;
		}

		fd_lookup[pa->fd] = count_pollfds;
		pollfds[count_pollfds].fd = pa->fd;
		pollfds[count_pollfds].events = pa->events;
		pollfds[count_pollfds++].revents = 0;
		break;

	case LWS_CALLBACK_DEL_POLL_FD:
		if (!--count_pollfds)
			break;
		m = fd_lookup[pa->fd];
		/* have the last guy take up the vacant slot */
		pollfds[m] = pollfds[count_pollfds];
		fd_lookup[pollfds[count_pollfds].fd] = m;
		break;

	case LWS_CALLBACK_CHANGE_MODE_POLL_FD:
	        pollfds[fd_lookup[pa->fd]].events = pa->events;
		break;

#endif

	case LWS_CALLBACK_GET_THREAD_ID:
		/*
		 * if you will call "libwebsocket_callback_on_writable"
		 * from a different thread, return the caller thread ID
		 * here so lws can use this information to work out if it
		 * should signal the poll() loop to exit and restart early
		 */

		/* return pthread_getthreadid_np(); */

		break;

	default:
		break;
	}

	return 0;
	
try_to_reuse:
	if (lws_http_transaction_completed(wsi))
		return -1;

	return 0;
}
Exemplo n.º 5
0
int callback_jittertrap(struct lws *wsi, enum lws_callback_reasons reason,
                        void *user, void *in,
                        size_t len __attribute__((unused)))
{
	unsigned char buf[LWS_SEND_BUFFER_PRE_PADDING + MAX_JSON_MSG_LEN +
	                  LWS_SEND_BUFFER_POST_PADDING];
	unsigned char *p = &buf[LWS_SEND_BUFFER_PRE_PADDING];
	struct per_session_data__jittertrap *pss =
	    (struct per_session_data__jittertrap *)user;

	int err, cb_err;
	struct cb_data cbd = { wsi, p };

	/* run jt init, stats producer, etc. */
	jt_server_tick();

	switch (reason) {
	case LWS_CALLBACK_CLOSED:
		err = jt_ws_mq_consumer_unsubscribe(pss->consumer_id);
		if (err) {
			lwsl_err("mq consumer unsubscribe failed.\n");
		}
		break;

	case LWS_CALLBACK_ESTABLISHED:
		lwsl_info("callback_jt: "
		          "LWS_CALLBACK_ESTABLISHED\n");
		err = jt_ws_mq_consumer_subscribe(&(pss->consumer_id));
		if (err) {
			lwsl_err("mq consumer subscription failed.\n");
		}
		jt_srv_send_iface_list();
		jt_srv_send_select_iface();
		jt_srv_send_netem_params();
		jt_srv_send_sample_period();
		break;

	case LWS_CALLBACK_SERVER_WRITEABLE:
		do {
			err = jt_ws_mq_consume(pss->consumer_id, lws_writer,
			                       &cbd, &cb_err);
			if (lws_partial_buffered(wsi) ||
			    lws_send_pipe_choked(wsi)) {
				lws_callback_on_writable(wsi);
				break;
			}
		} while (!err);

		if (-JT_WS_MQ_EMPTY != err) {
			return err;
		}
		break;

	case LWS_CALLBACK_RECEIVE:
		jt_server_msg_receive(in);
		break;

	/*
	 * this just demonstrates how to use the protocol filter. If you won't
	 * study and reject connections based on header content, you don't need
	 * to handle this callback
	 */
	case LWS_CALLBACK_FILTER_PROTOCOL_CONNECTION:
		dump_handshake_info(wsi);
		/* you could return non-zero here and kill the connection */
		break;

	default:
		break;
	}

	return 0;
}
Exemplo n.º 6
0
int callback_http(struct lws *webSocketInstance, enum lws_callback_reasons reason, void *user, void *in, size_t len) {
    struct per_session_data__http *pss = (struct per_session_data__http *) user;
    struct timeval tv;
    unsigned long amount, file_len;
    const char *contentType;
    static unsigned char buffer4096[4096];
    char buffer256[256];
    char buffer64[64];
    char leaf_path[1024];
    char *other_headers;
    unsigned char *end;
    unsigned char *p;
    int n, m, headerIndex = 0;
    
#ifdef EXTERNAL_POLL
    struct lws_pollargs *pa = (struct lws_pollargs *)in;
#endif
    
    switch (reason) {
        case LWS_CALLBACK_HTTP:
            /* SS_Server_DumpHandShake(webSocketInstance); */
            
            /* dump the individual URI Arg parameters */
            while (lws_hdr_copy_fragment(webSocketInstance, buffer256, sizeof(buffer256),
                                         WSI_TOKEN_HTTP_URI_ARGS, headerIndex) > 0) {
                lwsl_info("URI Arg %d: %s\n", ++headerIndex, buffer256);
            }
            
            if (len < 1) {
                lws_return_http_status(webSocketInstance, HTTP_STATUS_BAD_REQUEST, NULL);
                goto try_to_reuse;
            }
            /* if a legal POST URL, let it continue and accept data */
            if (lws_hdr_total_length(webSocketInstance, WSI_TOKEN_POST_URI)) {
                return 0;
            }
            if(strchr((const char*)in + 1, '/')) {
                if (strcmp(in, "/")) {
                    if (*((const char *)in) != '/') {
                        strcat(buffer256, "/");
                    }
                    strncat(buffer256, in, sizeof(buffer256) - strlen(RESOURCE_PATH));
                } 
                else { /* default file to serve */
                    strcat(buffer256, in);
                }

                buffer256[sizeof(buffer256) - 1] = '\0';
                sprintf(leaf_path, "%s%s", RESOURCE_PATH, buffer256);
                p = buffer4096 + LWS_PRE;
                end = p + sizeof(buffer4096) - LWS_PRE;
                pss->fd = lws_plat_file_open(webSocketInstance, leaf_path, &file_len, LWS_O_RDONLY);
                contentType = get_mimetype(buffer256);

                if (!contentType) {
                    lwsl_err("Unknown content-type for %s\n", buffer256);
                    lws_return_http_status(webSocketInstance, HTTP_STATUS_UNSUPPORTED_MEDIA_TYPE, NULL);
                    return -1;
                }
                if (pss->fd == LWS_INVALID_FILE) {
                        return -1;
                }
                if (lws_add_http_header_status(webSocketInstance, 200, &p, end)) {
                    return 1;
                }
                if (lws_add_http_header_by_token(webSocketInstance, WSI_TOKEN_HTTP_SERVER,
                                                 (unsigned char *)"libwebsockets", 13, &p, end)) {
                    return 1;
                }
                if(strncmp(contentType, "*/*", 3) == 0) {
                    if (lws_add_http_header_by_token(webSocketInstance, WSI_TOKEN_HTTP_CONTENT_TYPE,
                                                     (unsigned char *)contentType, 4, &p, end)) {
                        return 1;
                    }
                } else {
                    if(strncmp(contentType, "application/x-javascript", 24) == 0)
                    {
                        if (lws_add_http_header_by_token(webSocketInstance, WSI_TOKEN_HTTP_CONTENT_TYPE,
                                                         (unsigned char *)contentType, 24, &p, end)) {
                            return 1;
                        }
                    }
                    else
                    {
                        if (lws_add_http_header_by_token(webSocketInstance, WSI_TOKEN_HTTP_CONTENT_TYPE,
                                     (unsigned char *)contentType, 9, &p, end)) {
                            return 1;
                        }
                    }
                }
                if (lws_add_http_header_content_length(webSocketInstance, file_len, &p, end)) {
                    return 1;
                }
                if (lws_finalize_http_header(webSocketInstance, &p, end)) {
                    return 1;
                }
                n = lws_write(webSocketInstance, buffer4096 + LWS_PRE, p - (buffer4096 + LWS_PRE), LWS_WRITE_HTTP_HEADERS);
                if (n < 0) {
                    lws_plat_file_close(webSocketInstance, pss->fd);
                    return -1;
                }
                lws_callback_on_writable(webSocketInstance);
                break;
                printf("%s",buffer256);
                other_headers = NULL;
                n = 0;
                if (!strcmp((const char *)in, "/") && !lws_hdr_total_length(webSocketInstance, WSI_TOKEN_HTTP_COOKIE)) {
                    /* this isn't very unguessable but it'll do for us */
                    gettimeofday(&tv, NULL);
                    n = sprintf(buffer64, "test=SOUNDSHIELD_%u_%u_COOKIE;Max-Age=360000",
                                (unsigned int)tv.tv_sec, (unsigned int)tv.tv_usec);
                    p = (unsigned char *)buffer256;
                    if (lws_add_http_header_by_name(webSocketInstance, (unsigned char *)"set-cookie:",
                                                    (unsigned char *)buffer64, n, &p,
                                                    (unsigned char *)buffer256 + sizeof(buffer256))) {
                        return 1;
                    }
                    n = (char *)p - buffer256;
                    other_headers = buffer256;
                }
                n = lws_serve_http_file(webSocketInstance, buffer256, contentType, other_headers, n);
                if (n < 0 || ((n > 0) && lws_http_transaction_completed(webSocketInstance))) {
                    return -1; /* error or can't reuse connection: close the socket */
                }
                break;
            }
            /* if not, send a file the easy way */
            strcpy(buffer256, RESOURCE_PATH);
            if (strcmp(in, "/")) {
                if (*((const char *)in) != '/') {
                    strcat(buffer256, "/");
                }
                strncat(buffer256, in, sizeof(buffer256) - strlen(RESOURCE_PATH));
            } else { /* default file to serve */
                strcat(buffer256, "/index.html");
            }
            buffer256[sizeof(buffer256) - 1] = '\0';
            /* refuse to serve files we don't understand */
            contentType = get_mimetype(buffer256);
            if (!contentType) {
                lwsl_err("Unknown content-type for %s\n", buffer256);
                lws_return_http_status(webSocketInstance, HTTP_STATUS_UNSUPPORTED_MEDIA_TYPE, NULL);
                return -1;
            }
            /* demonstrates how to set a cookie on / */
            other_headers = NULL;
            n = 0;
            if (!strcmp((const char *)in, "/") && !lws_hdr_total_length(webSocketInstance, WSI_TOKEN_HTTP_COOKIE)) {
                /* this isn't very unguessable but it'll do for us */
                gettimeofday(&tv, NULL);
                n = sprintf(buffer64, "test=LWS_%u_%u_COOKIE;Max-Age=360000", (unsigned int)tv.tv_sec, (unsigned int)tv.tv_usec);
                p = (unsigned char *)leaf_path;
                if (lws_add_http_header_by_name(webSocketInstance, (unsigned char *)"set-cookie:",
                                                (unsigned char *)buffer64, n, &p,
                                                (unsigned char *)leaf_path + sizeof(leaf_path))) {
                    return 1;
                }
                n = (char *)p - leaf_path;
                other_headers = leaf_path;
            }
            n = lws_serve_http_file(webSocketInstance, buffer256, contentType, other_headers, n);
            if (n < 0 || ((n > 0) && lws_http_transaction_completed(webSocketInstance))) {
                return -1; /* error or can't reuse connection: close the socket */
            }
            /*
             * notice that the sending of the file completes asynchronously,
             * we'll get a LWS_CALLBACK_HTTP_FILE_COMPLETION callback when
             * it's done
             */
            break;
        case LWS_CALLBACK_HTTP_BODY:
            strncpy(buffer256, in, 20);
            buffer256[20] = '\0';
            if (len < 20) {
                buffer256[len] = '\0';
            }
            lwsl_notice("LWS_CALLBACK_HTTP_BODY: %s... len %d\n", (const char *)buffer256, (int)len);
            break;
        case LWS_CALLBACK_HTTP_BODY_COMPLETION:
            lwsl_notice("LWS_CALLBACK_HTTP_BODY_COMPLETION\n");
            /* the whole of the sent body arrived, close or reuse the connection */
            lws_return_http_status(webSocketInstance, HTTP_STATUS_OK, NULL);
            goto try_to_reuse;
        case LWS_CALLBACK_HTTP_FILE_COMPLETION:
            goto try_to_reuse;
        case LWS_CALLBACK_HTTP_WRITEABLE:
            /*
             * we can send more of whatever it is we were sending
             */
            do {
                /* we'd like the send this much */
                n = sizeof(buffer4096) - LWS_PRE;
                /* but if the peer told us he wants less, we can adapt */
                m = lws_get_peer_write_allowance(webSocketInstance);
                /* -1 means not using a protocol that has this info */
                if (m == 0) {
                /* right now, peer can't handle anything */
                    goto later;
                }
                if (m != -1 && m < n) {
                /* he couldn't handle that much */
                    n = m;
                }
                n = lws_plat_file_read(webSocketInstance, pss->fd, &amount, buffer4096 + LWS_PRE, n);
                /* problem reading, close conn */
                if (n < 0) { 
                    goto bail;
                }
                n = (int)amount;
                /* sent it all, close conn */
                if (n == 0) {
                    goto flush_bail;
                }
                /*
                 * To support HTTP2, must take care about preamble space
                 *
                 * identification of when we send the last payload frame
                 * is handled by the library itself if you sent a
                 * content-length header
                 */
                m = lws_write(webSocketInstance, buffer4096 + LWS_PRE, n, LWS_WRITE_HTTP);
                if (m < 0) {
                /* write failed, close conn */
                    goto bail;
                }
                /*
                 * http2 won't do this
                 */
                if (m != n) {
                /* partial write, adjust */
                    if (lws_plat_file_seek_cur(webSocketInstance, pss->fd, m - n) == (unsigned long)-1)
                        goto bail;
                }
                if (m) { /* while still active, extend timeout */
                    lws_set_timeout(webSocketInstance, PENDING_TIMEOUT_HTTP_CONTENT, 5);
                }
                /* if we have indigestion, let him clear it
                 * before eating more */
                if (lws_partial_buffered(webSocketInstance)) break;      
            } while (!lws_send_pipe_choked(webSocketInstance));
        later:
            lws_callback_on_writable(webSocketInstance);
            break;
        flush_bail:
            /* true if still partial pending */
            if (lws_partial_buffered(webSocketInstance)) {
                lws_callback_on_writable(webSocketInstance);
                break;
            }
            lws_plat_file_close(webSocketInstance, pss->fd);
            goto try_to_reuse;
        bail:
            lws_plat_file_close(webSocketInstance, pss->fd);
            return -1;
            /*
             * callback for confirming to continue with client IP appear in
             * protocol 0 callback since no websocket protocol has been agreed
             * yet.  You can just ignore this if you won't filter on client IP
             * since the default uhandled callback return is 0 meaning let the
             * connection continue.
             */
        case LWS_CALLBACK_FILTER_NETWORK_CONNECTION:
            /* if we returned non-zero from here, we kill the connection */
            break;
            /*
             * callbacks for managing the external poll() array appear in
             * protocol 0 callback
             */
            
        case LWS_CALLBACK_LOCK_POLL:
            /*
             * lock mutex to protect pollfd state
             * called before any other POLL related callback
             * if protecting wsi lifecycle change, len == 1
             */
            test_server_lock(len);
            break;
        case LWS_CALLBACK_UNLOCK_POLL:
            /*
             * unlock mutex to protect pollfd state when
             * called after any other POLL related callback
             * if protecting wsi lifecycle change, len == 1
             */
            test_server_unlock(len);
            break;
#ifdef EXTERNAL_POLL
        case LWS_CALLBACK_ADD_POLL_FD:
            if (count_pollfds >= max_poll_elements) {
                lwsl_err("LWS_CALLBACK_ADD_POLL_FD: too many sockets to track\n");
                return 1;
            }
            fd_lookup[pa->fd] = count_pollfds;
            pollfds[count_pollfds].fd = pa->fd;
            pollfds[count_pollfds].events = pa->events;
            pollfds[count_pollfds++].revents = 0;
            break;
        case LWS_CALLBACK_DEL_POLL_FD:
            if (!--count_pollfds) {
                break;
            }
            m = fd_lookup[pa->fd];
            /* have the last guy take up the vacant slot */
            pollfds[m] = pollfds[count_pollfds];
            fd_lookup[pollfds[count_pollfds].fd] = m;
            break;
        case LWS_CALLBACK_CHANGE_MODE_POLL_FD:
            pollfds[fd_lookup[pa->fd]].events = pa->events;
            break;
#endif
        case LWS_CALLBACK_GET_THREAD_ID:
            /*
             * if you will call "lws_callback_on_writable"
             * from a different thread, return the caller thread ID
             * here so lws can use this information to work out if it
             * should signal the poll() loop to exit and restart early
             */
            /* return pthread_getthreadid_np(); */
            break;
        default:
            break;
    }
    return 0;
    /* if we're on HTTP1.1 or 2.0, will keep the idle connection alive */
try_to_reuse:
    if (lws_http_transaction_completed(webSocketInstance)) {
        return -1;
    }
    return 0;
}