Пример #1
0
static int callback_brogue(struct libwebsocket_context *context, struct libwebsocket *wsi,
        enum libwebsocket_callback_reasons reason, void *user, void *in, size_t len) {
    struct sessionData *pss = (struct sessionData *)user;
    int n;
    switch (reason) {
        case LWS_CALLBACK_ESTABLISHED:
            puts("client connected");
            /* start triggering callbacks */
            libwebsocket_callback_on_writable(context, wsi);
            break;

        case LWS_CALLBACK_SERVER_WRITEABLE:
            puts("checking for deliverable data");
            if (needs_websocket_update) {
                puts("delivering data");
                needs_websocket_update = false;
                n = libwebsocket_write(wsi, &consoleJSON[LWS_SEND_BUFFER_PRE_PADDING],
                        strlen(consoleJSON + LWS_SEND_BUFFER_PRE_PADDING), LWS_WRITE_TEXT);
                if (n < 0) {
                    lwsl_err("ERROR %d writing to socket, hanging up\n", n);
                    return 1;
                }
                if (n < (int)pss->len) {
                    lwsl_err("Partial write\n");
                    return -1;
                }
            }
            libwebsocket_callback_on_writable(context, wsi);
            break;

        case LWS_CALLBACK_RECEIVE:
                //memcpy(&pss->buf[LWS_SEND_BUFFER_PRE_PADDING], in, len);
                //pss->len = (uint32)len;
                //puts(pss->buf[LWS_SEND_BUFFER_PRE_PADDING]);
                printf("received: %s\n", in);
                /* FIXME: key queue */
                cJSON *message = cJSON_Parse(in);
                int jsKeycode = cJSON_GetObjectItem(message, "keycode")->valueint;
                memset(&bufferedKey, 0, sizeof(TCOD_key_t));
                bufferedKey.vk = parse_js_keycode(jsKeycode);
                if (bufferedKey.vk == TCODK_CHAR) {
                    bufferedKey.c = jsKeycode;
                }
                bufferedKey.shift = cJSON_GetObjectItem(message, "shift")->valueint;
                bufferedKey.lctrl = bufferedKey.rctrl =
                    cJSON_GetObjectItem(message, "ctrl")->valueint;
                printf("key received: %c shift: %i, ctrl: %i\n", bufferedKey.c,
                        bufferedKey.shift, bufferedKey.rctrl);
                cJSON_Delete(message);
                libwebsocket_callback_on_writable(context, wsi);
            break;
        default:
            break;
    }
    return 0;
}
static int callback_ws( struct libwebsocket_context *context,
								  struct libwebsocket *wsi,
								  enum libwebsocket_callback_reasons reason,
								  void *user,
								  void *in,
								  size_t len )
{
	json_spirit::mObject Obj;
	std::string jsonString;
	
	Obj[ "name" ] = json_spirit::mValue( "Calvin" );	

	jsonString = json_spirit::write( Obj );

	switch ( reason )
	{
		case LWS_CALLBACK_PROTOCOL_INIT:
			printf( "Received the protocol init callback.\n" );
			break;
		case LWS_CALLBACK_ESTABLISHED:
			printf( "Received LWS_CALLBACK_ESTABLISHED.\n" );
			libwebsocket_callback_on_writable(context, wsi);
			break;
		case LWS_CALLBACK_CLOSED:
			printf( "Received LWS_CALLBACK_CLOSED.\n" );
			break;
		case LWS_CALLBACK_SERVER_WRITEABLE:
			{
			printf( "Sending Data.\n" );
			char *universal_response = "Hello, World!\n";
//			libwebsocket_write( wsi, ( unsigned char * ) universal_response,
//									  strlen( ( const char * ) universal_response ), LWS_WRITE_TEXT );
			libwebsocket_write( wsi, ( unsigned char * ) jsonString.c_str(),
									  jsonString.size(), LWS_WRITE_TEXT );
			libwebsocket_callback_on_writable(context, wsi);
			}
			break;
		case LWS_CALLBACK_RECEIVE:
//			printf( "Received LWS_CALLBACK_RECEIVE.\n" );
			break;
		default:
			printf( "Unhandled callback.\n" );
			printf( "Reason: %d\n", reason );
			break;
	}
	
	return 0;
}
Пример #3
0
	~Connection()
	{
		assert(wsi != NULL);
		if (readyState == Connecting || readyState == Open) {
			// game-initiated close, tell libwebsockets to close it
		libwebsocket_callback_on_writable(wsState->websocketContext, wsi);
			setReadyState(Closed);
		}

		auto wsiIt = wsState->wsiLookup.find(wsi);
		assert(wsiIt != wsState->wsiLookup.end());
		wsState->wsiLookup.erase(wsiIt);

		bool hasData = !recvBuffer.empty();
		if (hasData) {
			auto pendingIt = wsState->pendingData.find(this);
			assert(pendingIt != wsState->pendingData.end());
			wsState->pendingData.erase(pendingIt);
		} else {
			// no data in buffer, must not be in pendingData
			assert(wsState->pendingData.find(this) == wsState->pendingData.end());
		}

		wsi = NULL;
		// since it's no longer in the hash map, next callback should close it
	}
Пример #4
0
void _ortc_send_message(ortc_context *context, char *message){
  pthread_mutex_lock(&context->mutex_msg);
  _ortc_dlist_insert(context->messagesToSend, message, NULL, NULL, 0, NULL);
  pthread_mutex_unlock(&context->mutex_msg);
  free(message);
  libwebsocket_callback_on_writable(context->lws_context, context->wsi);
}
Пример #5
0
int
_libwebsocket_rx_flow_control(struct libwebsocket *wsi)
{
    struct libwebsocket_context *context = wsi->protocol->owning_server;

    /* there is no pending change */
    if (!(wsi->u.ws.rxflow_change_to & LWS_RXFLOW_PENDING_CHANGE))
        return 0;

    /* stuff is still buffered, not ready to really accept new input */
    if (wsi->u.ws.rxflow_buffer) {
        /* get ourselves called back to deal with stashed buffer */
        libwebsocket_callback_on_writable(context, wsi);
        return 0;
    }

    /* pending is cleared, we can change rxflow state */

    wsi->u.ws.rxflow_change_to &= ~LWS_RXFLOW_PENDING_CHANGE;

    lwsl_info("rxflow: wsi %p change_to %d\n", wsi,
              wsi->u.ws.rxflow_change_to & LWS_RXFLOW_ALLOW);

    /* adjust the pollfd for this wsi */

    if (wsi->u.ws.rxflow_change_to & LWS_RXFLOW_ALLOW) {
        if (lws_change_pollfd(wsi, 0, LWS_POLLIN)) {
            lwsl_info("%s: fail\n", __func__);
            return -1;
        }
    } else if (lws_change_pollfd(wsi, LWS_POLLIN, 0))
        return -1;

    return 0;
}
Пример #6
0
int janus_websockets_send_message(void *transport, void *request_id, gboolean admin, json_t *message) {
	if(message == NULL)
		return -1;
	if(transport == NULL) {
		g_free(message);
		return -1;
	}
	/* Make sure this is not related to a closed /freed WebSocket session */
	janus_mutex_lock(&old_wss_mutex);
	janus_websockets_client *client = (janus_websockets_client *)transport;
	if(g_list_find(old_wss, client) != NULL) {
		g_free(message);
		message = NULL;
		transport = NULL;
	} else if(!client->context || !client->wsi) {
		g_free(message);
		message = NULL;
	}
	if(message == NULL) {
		janus_mutex_unlock(&old_wss_mutex);
		return -1;
	}
	janus_mutex_lock(&client->mutex);
	/* Convert to string and enqueue */
	char *payload = json_dumps(message, JSON_INDENT(3) | JSON_PRESERVE_ORDER);
	g_async_queue_push(client->messages, payload);
	libwebsocket_callback_on_writable(client->context, client->wsi);
	janus_mutex_unlock(&client->mutex);
	janus_mutex_unlock(&old_wss_mutex);
	json_decref(message);
	return 0;
}
	virtual void FeedBack(const char* text)
	{
		if (*m_valid)
		{
			m_queue->push(text);
			libwebsocket_callback_on_writable (m_context, m_wsi);	
		}
	}
Пример #8
0
static void send_command(server_command_t command) {
    int count = vector_count(sessions);
    for (int i = 0; i < count; i++) {
        server_session_t *s = vector_get(sessions, i);
        if (s != NULL) {
            s->next_command = command;
            libwebsocket_callback_on_writable(context, s->wsi);
        }
    }
}
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;
}
Пример #10
0
void lws_set_protocol_write_pending(struct libwebsocket_context *context,
				    struct libwebsocket *wsi,
				    enum lws_pending_protocol_send pend)
{
	lwsl_info("setting pps %d\n", pend);
	
	if (wsi->pps)
		lwsl_err("pps overwrite\n");
	wsi->pps = pend;
	libwebsocket_rx_flow_control(wsi, 0);
	libwebsocket_callback_on_writable(context, wsi);
}
Пример #11
0
void FWebSocket::Flush()
{
	while (OutgoingBuffer.Num() > 0 && !IsServerSide)
	{
#if !PLATFORM_HTML5
		if (Protocols)
			libwebsocket_callback_on_writable_all_protocol(&Protocols[0]);
		else
			libwebsocket_callback_on_writable(Context, Wsi);
#endif
		HandlePacket();
	};
}
Пример #12
0
int _mosquitto_packet_queue(struct mosquitto *mosq, struct _mosquitto_packet *packet)
{
#ifndef WITH_BROKER
	char sockpair_data = 0;
#endif
	assert(mosq);
	assert(packet);

	packet->pos = 0;
	packet->to_process = packet->packet_length;

	packet->next = NULL;
	pthread_mutex_lock(&mosq->out_packet_mutex);
	if(mosq->out_packet){
		mosq->out_packet_last->next = packet;
	}else{
		mosq->out_packet = packet;
	}
	mosq->out_packet_last = packet;
	pthread_mutex_unlock(&mosq->out_packet_mutex);
#ifdef WITH_BROKER
#  ifdef WITH_WEBSOCKETS
	if(mosq->wsi){
		libwebsocket_callback_on_writable(mosq->ws_context, mosq->wsi);
		return 0;
	}else{
		return _mosquitto_packet_write(mosq);
	}
#  else
	return _mosquitto_packet_write(mosq);
#  endif
#else

	/* Write a single byte to sockpairW (connected to sockpairR) to break out
	 * of select() if in threaded mode. */
	if(mosq->sockpairW != INVALID_SOCKET){
#ifndef WIN32
		if(write(mosq->sockpairW, &sockpair_data, 1)){
		}
#else
		send(mosq->sockpairW, &sockpair_data, 1, 0);
#endif
	}

	if(mosq->in_callback == false && mosq->threaded == false){
		return _mosquitto_packet_write(mosq);
	}else{
		return MOSQ_ERR_SUCCESS;
	}
#endif
}
Пример #13
0
int FWebSocket::unreal_networking_client(
		struct libwebsocket_context *Context, 
		struct libwebsocket *Wsi, 
		enum libwebsocket_callback_reasons Reason, 
		void *User, 
		void *In, 
		size_t Len)
{
	FWebSocket* Socket = (FWebSocket*)libwebsocket_context_user(Context);;
	switch (Reason)
	{
	case LWS_CALLBACK_CLIENT_ESTABLISHED:
		{
			Socket->ConnectedCallBack.ExecuteIfBound();
			libwebsocket_set_timeout(Wsi, NO_PENDING_TIMEOUT, 0);
			check(Socket->Wsi == Wsi);
		}
		break;
	case LWS_CALLBACK_CLIENT_CONNECTION_ERROR:
		{
			Socket->ErrorCallBack.ExecuteIfBound();
			return -1;
		}
		break;
	case LWS_CALLBACK_CLIENT_RECEIVE:
		{
			// push it on the socket. 
			Socket->OnRawRecieve(In, (uint32)Len); 
			check(Socket->Wsi == Wsi);
			libwebsocket_set_timeout(Wsi, NO_PENDING_TIMEOUT, 0);
			break;
		}
	case LWS_CALLBACK_CLIENT_WRITEABLE:
		{
			check(Socket->Wsi == Wsi);
			Socket->OnRawWebSocketWritable(Wsi); 
			libwebsocket_callback_on_writable(Context, Wsi);
			libwebsocket_set_timeout(Wsi, NO_PENDING_TIMEOUT, 0);
			break; 
		}
	case LWS_CALLBACK_CLOSED:
		{
			Socket->ErrorCallBack.ExecuteIfBound();
			return -1;
		}
	}

	return 0; 
}
Пример #14
0
void janus_websockets_session_over(void *transport, guint64 session_id, gboolean timeout) {
	if(transport == NULL || !timeout)
		return;
	/* We only care if it's a timeout: if so, close the connection */
	janus_websockets_client *client = (janus_websockets_client *)transport;
	/* Make sure this is not related to a closed WebSocket session */
	janus_mutex_lock(&old_wss_mutex);
	if(g_list_find(old_wss, client) == NULL && client->context && client->wsi){
		janus_mutex_lock(&client->mutex);
		client->session_timeout = 1;
		libwebsocket_callback_on_writable(client->context, client->wsi);
		janus_mutex_unlock(&client->mutex);
	}
	janus_mutex_unlock(&old_wss_mutex);
}
Пример #15
0
int _mosquitto_socket_close(struct mosquitto *mosq)
#endif
{
	int rc = 0;

	assert(mosq);
#ifdef WITH_TLS
	if(mosq->ssl){
		SSL_shutdown(mosq->ssl);
		SSL_free(mosq->ssl);
		mosq->ssl = NULL;
	}
	if(mosq->ssl_ctx){
		SSL_CTX_free(mosq->ssl_ctx);
		mosq->ssl_ctx = NULL;
	}
#endif

	if((int)mosq->sock >= 0){
#ifdef WITH_BROKER
		HASH_DELETE(hh_sock, db->contexts_by_sock, mosq);
#endif
		rc = COMPAT_CLOSE(mosq->sock);
		_mosquitto_log_printf(NULL,MOSQ_LOG_INFO,"net_mosq.c:mosquitto_socket_close:  socket(%d) closed .... ",mosq->sock);
		mosq->sock = INVALID_SOCKET;
#ifdef WITH_WEBSOCKETS
	}else if(mosq->sock == WEBSOCKET_CLIENT){
		if(mosq->state != mosq_cs_disconnecting){
			mosq->state = mosq_cs_disconnect_ws;
		}
		if(mosq->wsi){
			libwebsocket_callback_on_writable(mosq->ws_context, mosq->wsi);
		}
		mosq->sock = INVALID_SOCKET;
#endif
	}

#ifdef WITH_BROKER
	if(mosq->listener){
		mosq->listener->client_count--;
		assert(mosq->listener->client_count >= 0);
		mosq->listener = NULL;
	}
#endif

	return rc;
}
Пример #16
0
LWS_VISIBLE int
libwebsocket_callback_on_writable_all_protocol(
				  const struct libwebsocket_protocols *protocol)
{
	struct libwebsocket_context *context = protocol->owning_server;
	int n;
	struct libwebsocket *wsi;

	for (n = 0; n < context->fds_count; n++) {
		wsi = wsi_from_fd(context,context->fds[n].fd);
		if (!wsi)
			continue;
		if (wsi->protocol == protocol)
			libwebsocket_callback_on_writable(context, wsi);
	}

	return 0;
}
Пример #17
0
void FJavascriptWebSocket::Flush()
{
	auto PendingMesssages = OutgoingBuffer.Num();
	while (OutgoingBuffer.Num() > 0 && !IsServerSide)
	{
#if !PLATFORM_HTML5
		if (Protocols)
			libwebsocket_callback_on_writable_all_protocol(&Protocols[0]);
		else
			libwebsocket_callback_on_writable(Context, Wsi);
#endif
		HandlePacket();
		if (PendingMesssages >= OutgoingBuffer.Num()) 
		{
			UE_LOG(LogWebsocket, Warning, TEXT("Unable to flush all of OutgoingBuffer in FJavascriptWebSocket."));
			break;
		}
	};
}
Пример #18
0
int websocket_send(int socket, const unsigned char *data, size_t size, int port)
{
	libwebsocket_context *context = contexts[socket].context;
	if(context == NULL)
		return -1;
	context_data *ctx_data = (context_data *)libwebsocket_context_user(context);
	struct per_session_data *pss = ctx_data->port_map[port];
	if(pss == NULL)
		return -1;
	websocket_chunk *chunk = (websocket_chunk *)pss->send_buffer.Allocate(size + sizeof(websocket_chunk) + LWS_SEND_BUFFER_PRE_PADDING + LWS_SEND_BUFFER_POST_PADDING);
	if(chunk == NULL)
		return -1;
	chunk->size = size;
	chunk->read = 0;
	memcpy(&chunk->addr, &pss->addr, sizeof(sockaddr_in));
	memcpy(&chunk->data[LWS_SEND_BUFFER_PRE_PADDING], data, size);
	libwebsocket_callback_on_writable(context, pss->wsi);
	return size;
}
Пример #19
0
void WebSocketOpcode_handleServerWritable(struct libwebsocket *websocket,
                                          WebSocketOpcode *self,
                                          CSOUND *csound, void *messageBuffer)
{
    const struct libwebsocket_protocols *protocol =
      libwebsockets_get_protocol(websocket);

    // If it's an output argument just return
    if (protocol->protocol_index < self->outputArgumentCount) {

      usleep(100);
      return;
    }

    int inputIndex = protocol->protocol_index - self->outputArgumentCount;
    OpcodeArgument *argument = &self->inputArguments[inputIndex];

    int readItems = 0;

    if (argument->bytesWritten == 0) {

      readItems =
        csoundReadCircularBuffer(csound, argument->circularBuffer,
                                 argument->readBuffer, argument->itemsCount);
    }
    if (readItems != 0 || argument->bytesWritten != 0) {

      WebSocketOpcode_writeMessage(self, argument, messageBuffer, websocket);

      if (argument->argumentType == IRATE_VAR ||
          argument->argumentType == IRATE_ARRAY) {

        argument->iRateVarSent = true;
      }
    }

    usleep(100);

    if (argument->iRateVarSent == false) {

      libwebsocket_callback_on_writable(self->webSocket->context, websocket);
    }
}
Пример #20
0
static int dotbot_stream_callback(struct libwebsocket_context *context,
        struct libwebsocket *wsi,
        enum libwebsocket_callback_reasons reason,
        void *user, void *in, size_t len) {

    int n = 0, m;
    const char *in_buf = (const char *)in;
    unsigned char buf[LWS_SEND_BUFFER_PRE_PADDING + 512 + LWS_SEND_BUFFER_POST_PADDING];
    unsigned char *p = &buf[LWS_SEND_BUFFER_PRE_PADDING];
    struct per_session_data *data = (struct per_session_data*)user;

    switch (reason) {
        /* New connection; initialize a game for them. */
        case LWS_CALLBACK_ESTABLISHED:
            lwsl_info("dotbot_stream_callback: LWS_CALLBACK_ESTABLISHED\n");
            init_session_data(data);
            break;
        /* Calculate a move, update the board, and send back the results. */
        case LWS_CALLBACK_SERVER_WRITEABLE:
            tick(&n, (char *)p, data);
            if (n) {
                m = libwebsocket_write(wsi, p, n, LWS_WRITE_TEXT);
                if (m < n) {
                    lwsl_info("client disconnected\n");
                    return -1;
                }
            }
            break;
        case LWS_CALLBACK_RECEIVE:
            if (len == 4 && strncmp(in_buf, "next", len) == 0) {
                libwebsocket_callback_on_writable(context, wsi);
            }
            if (strncmp(in_buf, "setGrid:", 8) == 0) {
                set_grid(data, in_buf + 8);
            }
            break;
        default:
            break;
    }

    return 0;
}
Пример #21
0
static std::unique_ptr<Connection> createConnection(const netadr_t &to) {
	assert(wsState);

	char addrBuf[3 * 4 + 5];
	snprintf(addrBuf, sizeof(addrBuf), "%u.%u.%u.%u", to.ip[0], to.ip[1], to.ip[2], to.ip[3]);
	struct libwebsocket *newWsi = libwebsocket_client_connect(wsState->websocketContext, addrBuf, ntohs(to.port), 0, "/", addrBuf, addrBuf, "quake2", -1);
	if (newWsi == NULL) {
		STUBBED("TODO: log connection create failure");
		return std::unique_ptr<Connection>();
	}
	libwebsocket_callback_on_writable(wsState->websocketContext, newWsi);

	STUBBED("TODO: unnecessary(?) libwebsocket_service");
	libwebsocket_service(wsState->websocketContext, 0);

	std::unique_ptr<Connection> conn(new Connection(to, newWsi));

	wsState->wsiLookup.emplace(newWsi, conn.get());

	return conn;
}
Пример #22
0
bool Connection::sendPacket(const char *data, size_t length) {
	assert(wsi);
	assert(readyState == Open);
	assert(length < 16384);
	uint16_t l16 = length;
	memcpy(&sendBuf[LWS_SEND_BUFFER_PRE_PADDING], &l16, 2);
	memcpy(&sendBuf[LWS_SEND_BUFFER_PRE_PADDING + 2], data, length);

	// TODO: too many calls to libwebsocket_service here
	libwebsocket_service(wsState->websocketContext, 0);

	if (!writable) {
		// track socket writable status, only write when would not block
	// TODO: buffer or drop?
		return false;
	}

	int retval = libwebsocket_write(wsi, &sendBuf[LWS_SEND_BUFFER_PRE_PADDING], length + 2, LWS_WRITE_BINARY);
	if (retval < 0) {
		return false;
	}

	writable = false;
	libwebsocket_callback_on_writable(wsState->websocketContext, wsi);

	libwebsocket_service(wsState->websocketContext, 0);

	if (retval < length) {
		// partial send
		// TODO: handle this better, try to resend rest later
		STUBBED("resend");
		return false;
	}

	return true;
}
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_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;
}
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

	switch (reason) {
	case LWS_CALLBACK_HTTP:

		dump_handshake_info(wsi);

		if (len < 1) {
			libwebsockets_return_http_status(context, wsi,
						HTTP_STATUS_BAD_REQUEST, NULL);
			return -1;
		}

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

		/* 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;

#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.
			 */

			p += sprintf((char *)p,
				"HTTP/1.0 200 OK\x0d\x0a"
				"Server: libwebsockets\x0d\x0a"
				"Content-Type: image/jpeg\x0d\x0a"
					"Content-Length: %u\x0d\x0a\x0d\x0a",
					(unsigned int)stat_buf.st_size);

			/*
			 * 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)
			 */

			n = libwebsocket_write(wsi, buffer,
				   p - buffer, LWS_WRITE_HTTP);

			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;
		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);
			sprintf(b64, "LWS_%u_%u_COOKIE",
				(unsigned int)tv.tv_sec,
				(unsigned int)tv.tv_usec);

			sprintf(leaf_path,
				"Set-Cookie: test=LWS_%u_%u_COOKIE;Max-Age=360000\x0d\x0a",
			    (unsigned int)tv.tv_sec, (unsigned int)tv.tv_usec);
			other_headers = leaf_path;
			lwsl_err(other_headers);
		}

		if (libwebsockets_serve_http_file(context, wsi, buf,
						mimetype, other_headers))
			return -1; /* through completion or error, 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 arried, close the connection */
		libwebsockets_return_http_status(context, wsi,
						HTTP_STATUS_OK, NULL);

		return -1;

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

	case LWS_CALLBACK_HTTP_WRITEABLE:
		/*
		 * we can send more of whatever it is we were sending
		 */

		do {
			n = read(pss->fd, buffer, sizeof buffer);
			/* problem reading, close conn */
			if (n < 0)
				goto bail;
			/* sent it all, close conn */
			if (n == 0)
				goto flush_bail;
			/*
			 * because it's HTTP and not websocket, don't need to take
			 * care about pre and postamble
			 */
			m = libwebsocket_write(wsi, buffer, n, LWS_WRITE_HTTP);
			if (m < 0)
				/* write failed, close conn */
				goto bail;
			if (m != n)
				/* partial write, adjust */
				lseek(pss->fd, m - n, SEEK_CUR);

			if (m) /* while still active, extend timeout */
				libwebsocket_set_timeout(wsi,
					PENDING_TIMEOUT_HTTP_CONTENT, 5);

		} while (!lws_send_pipe_choked(wsi));
		libwebsocket_callback_on_writable(context, wsi);
		break;
flush_bail:
		/* true if still partial pending */
		if (lws_send_pipe_choked(wsi)) {
			libwebsocket_callback_on_writable(context, wsi);
			break;
		}

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;
}
Пример #25
0
static int
callback_echo(struct libwebsocket_context *context,
		struct libwebsocket *wsi,
		enum libwebsocket_callback_reasons reason, void *user,
							   void *in, size_t len)
{
	struct per_session_data__echo *pss = (struct per_session_data__echo *)user;
	int n;

	switch (reason) {

#ifndef LWS_NO_SERVER
	/* when the callback is used for server operations --> */

	case LWS_CALLBACK_SERVER_WRITEABLE:
do_tx:
		n = libwebsocket_write(wsi, &pss->buf[LWS_SEND_BUFFER_PRE_PADDING], pss->len, LWS_WRITE_TEXT);
		if (n < 0) {
			lwsl_err("ERROR %d writing to socket, hanging up\n", n);
			return 1;
		}
		if (n < (int)pss->len) {
			lwsl_err("Partial write\n");
			return -1;
		}
		break;

	case LWS_CALLBACK_RECEIVE:
do_rx:
		if (len > MAX_ECHO_PAYLOAD) {
			lwsl_err("Server received packet bigger than %u, hanging up\n", MAX_ECHO_PAYLOAD);
			return 1;
		}
		memcpy(&pss->buf[LWS_SEND_BUFFER_PRE_PADDING], in, len);
		pss->len = (unsigned int)len;
		libwebsocket_callback_on_writable(context, wsi);
		break;
#endif

#ifndef LWS_NO_CLIENT
	/* when the callback is used for client operations --> */

	case LWS_CALLBACK_CLOSED:
	case LWS_CALLBACK_CLIENT_CONNECTION_ERROR:
		lwsl_info("closed\n");
		state = 0;
		break;

	case LWS_CALLBACK_CLIENT_ESTABLISHED:
		lwsl_notice("Client has connected\n");
		pss->index = 0;
		state = 2;
		break;

	case LWS_CALLBACK_CLIENT_RECEIVE:
#ifndef LWS_NO_SERVER
		if (versa)
			goto do_rx;
#endif
		lwsl_notice("Client RX: %s", (char *)in);
		break;

	case LWS_CALLBACK_CLIENT_WRITEABLE:
#ifndef LWS_NO_SERVER
		if (versa)
			goto do_tx;
#endif
		/* we will send our packet... */
		pss->len = sprintf((char *)&pss->buf[LWS_SEND_BUFFER_PRE_PADDING], "hello from libwebsockets-test-echo client pid %d index %d\n", getpid(), pss->index++);
		lwsl_notice("Client TX: %s", &pss->buf[LWS_SEND_BUFFER_PRE_PADDING]);
		n = libwebsocket_write(wsi, &pss->buf[LWS_SEND_BUFFER_PRE_PADDING], pss->len, LWS_WRITE_TEXT);
		if (n < 0) {
			lwsl_err("ERROR %d writing to socket, hanging up\n", n);
			return -1;
		}
		if (n < (int)pss->len) {
			lwsl_err("Partial write\n");
			return -1;
		}
		break;
	case LWS_CALLBACK_OPENSSL_LOAD_EXTRA_CLIENT_VERIFY_CERTS:
		
		break;
#endif
	default:
		break;
	}

	return 0;
}
Пример #26
0
static int websocket_callback(struct libwebsocket_context *context, struct libwebsocket *wsi, enum libwebsocket_callback_reasons reason, void *user, void *in, size_t len)
{
	struct per_session_data *pss = (struct per_session_data *)user;
	context_data *ctx_data = (context_data *)libwebsocket_context_user(context);

	switch(reason)
	{

	case LWS_CALLBACK_ESTABLISHED:
	{
		int port = -1;
		for(int i = 0; i < WS_CLIENTS; i++)
		{
			int j = (ctx_data->last_used_port + i + 1) % WS_CLIENTS;
			if(ctx_data->port_map[j] == NULL)
			{
				port = j;
				break;
			}
		}
		if(port == -1)
		{
			dbg_msg("websockets", "no free ports, dropping");
			pss->port = -1;
			return -1;
		}
		ctx_data->last_used_port = port;
		pss->wsi = wsi;
		int fd = libwebsocket_get_socket_fd(wsi);
		socklen_t addr_size = sizeof(pss->addr);
		getpeername(fd, (struct sockaddr *)&pss->addr, &addr_size);
		int orig_port = ntohs(pss->addr.sin_port);
		pss->addr.sin_port = htons(port);
		pss->send_buffer.Init();
		pss->port = port;
		ctx_data->port_map[port] = pss;
		char addr_str[NETADDR_MAXSTRSIZE];
		inet_ntop(AF_INET, &pss->addr.sin_addr, addr_str, sizeof(addr_str));
		dbg_msg("websockets", "connection established with %s:%d , assigned fake port %d", addr_str, orig_port, port);
	}
	break;

	case LWS_CALLBACK_CLOSED:
	{
		dbg_msg("websockets", "connection with fake port %d closed", pss->port);
		if (pss->port > -1) {
			unsigned char close_packet[] = { 0x10, 0x0e, 0x00, 0x04 };
			receive_chunk(ctx_data, pss, &close_packet, sizeof(close_packet));
			pss->wsi = 0;
			ctx_data->port_map[pss->port] = NULL;
		}
	}
	break;

	case LWS_CALLBACK_SERVER_WRITEABLE:
	{
		websocket_chunk *chunk = (websocket_chunk *)pss->send_buffer.First();
		if(chunk == NULL)
			break;
		int len = chunk->size - chunk->read;
		int n = libwebsocket_write(wsi, &chunk->data[LWS_SEND_BUFFER_PRE_PADDING + chunk->read], chunk->size - chunk->read, LWS_WRITE_BINARY);
		if(n < 0)
			return 1;
		if(n < len)
		{
			chunk->read += n;
			libwebsocket_callback_on_writable(context, wsi);
			break;
		}
		pss->send_buffer.PopFirst();
		libwebsocket_callback_on_writable(context, wsi);
	}
	break;

	case LWS_CALLBACK_RECEIVE:
		if(pss->port == -1)
			return -1;
		if(!receive_chunk(ctx_data, pss, in, len))
			return 1;
		break;

	default:
		break;
	}

	return 0;
}
Пример #27
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 = user;

	switch (reason) {

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

	case LWS_CALLBACK_SERVER_WRITEABLE:
		if (close_testing)
			break;
		if (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) {
				fprintf(stderr, "ERROR writing to socket");
				exit(1);
			}

			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) < (MAX_MESSAGE_QUEUE - 15))
				libwebsocket_rx_flow_control(wsi, 1);

			libwebsocket_callback_on_writable(context, wsi);

		}
		break;

	case LWS_CALLBACK_BROADCAST:
		n = libwebsocket_write(wsi, in, len, LWS_WRITE_TEXT);
		if (n < 0)
			fprintf(stderr, "mirror write failed\n");
		break;

	case LWS_CALLBACK_RECEIVE:

		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) > (MAX_MESSAGE_QUEUE - 10))
			libwebsocket_rx_flow_control(wsi, 0);

		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((struct lws_tokens *)(long)user);
		/* you could return non-zero here and kill the connection */
		break;

	default:
		break;
	}

	return 0;
}
Пример #28
0
int
lws_issue_raw_ext_access(struct libwebsocket *wsi,
						 unsigned char *buf, size_t len)
{
	int ret;
	struct lws_tokens eff_buf;
	int m;
	int n;

	eff_buf.token = (char *)buf;
	eff_buf.token_len = len;

	/*
	 * while we have original buf to spill ourselves, or extensions report
	 * more in their pipeline
	 */

	ret = 1;
	while (ret == 1) {

		/* default to nobody has more to spill */

		ret = 0;

		/* show every extension the new incoming data */

		for (n = 0; n < wsi->count_active_extensions; n++) {
			m = wsi->active_extensions[n]->callback(
					wsi->protocol->owning_server,
					wsi->active_extensions[n], wsi,
					LWS_EXT_CALLBACK_PACKET_TX_PRESEND,
				   wsi->active_extensions_user[n], &eff_buf, 0);
			if (m < 0) {
				lwsl_ext("Extension: fatal error\n");
				return -1;
			}
			if (m)
				/*
				 * at least one extension told us he has more
				 * to spill, so we will go around again after
				 */
				ret = 1;
		}

		/* assuming they left us something to send, send it */

		if (eff_buf.token_len) {
			n = lws_issue_raw(wsi, (unsigned char *)eff_buf.token,
							    eff_buf.token_len);
			if (n < 0)
				return -1;
			/*
			 * Keep amount spilled small to minimize chance of this
			 */
			if (n != eff_buf.token_len) {
				lwsl_err("Unable to spill ext %d vs %s\n",
							  eff_buf.token_len, n);
				return -1;
			}

		}

		lwsl_parser("written %d bytes to client\n", eff_buf.token_len);

		/* no extension has more to spill */

		if (!ret)
			break;

		/* we used up what we had */

		eff_buf.token = NULL;
		eff_buf.token_len = 0;

		/*
		 * Did that leave the pipe choked?
		 */

		if (!lws_send_pipe_choked(wsi))
			/* no we could add more */
			continue;

		lwsl_debug("choked\n");

		/*
		 * Yes, he's choked.  Don't spill the rest now get a callback
		 * when he is ready to send and take care of it there
		 */
		libwebsocket_callback_on_writable(
					     wsi->protocol->owning_server, wsi);
		wsi->extension_data_pending = 1;
		ret = 0;
	}

	return len;
}
Пример #29
0
/* lws-mirror_protocol 回调函数*/
static int
callback_DTS2B_mirror(struct libwebsocket_context *context,
			struct libwebsocket *wsi,
			enum libwebsocket_callback_reasons reason,
					       void *user, void *in, size_t len)
{
	
		
		int n;
		int num;
		json_object *get_obj;
	switch (reason) {

	//when the websocket session ends
	case LWS_CALLBACK_CLOSED:
		fprintf(stderr, "mirror: LWS_CALLBACK_CLOSED mirror_lifetime=%d\n", mirror_lifetime);
		wsi_mirror = NULL;
		was_closed = 1;
		break;
	//after your client connection completed a handshake with the remote server 
	case LWS_CALLBACK_CLIENT_ESTABLISHED:
	
		fprintf(stderr, "LWS_CALLBACK_CLIENT_ESTABLISHED\n");

		/*
		 * start the ball rolling,
		 * LWS_CALLBACK_CLIENT_WRITEABLE will come next service
		 */

		libwebsocket_callback_on_writable(context, wsi);
		break;
	//data has appeared from the server for the client connection, it can be found at *in and is len bytes long 
	case LWS_CALLBACK_CLIENT_RECEIVE://接收服务端信息
		((char *)in)[len] = '\0';
		fprintf(stderr, "Received %d '%s'\n", (int)len, (char *)in); //打印接收到的数据
		get_obj=json_tokener_parse((char *)in);//将接收到的字符串转换为json object
		Process_json(get_obj);//解析处理接收到的数据
		break;
	/*

	If you call libwebsocket_callback_on_writable on a connection, 
	you will get one of these callbacks coming when the connection socket is able to accept another write packet without blocking. 
	If it already was able to take another packet without blocking, 
	you'll get this callback at the next call to the service loop function. 
	Notice that CLIENTs get LWS_CALLBACK_CLIENT_WRITEABLE and servers get LWS_CALLBACK_SERVER_WRITEABLE.

	*/
	//向服务端写数据
	case LWS_CALLBACK_CLIENT_WRITEABLE:

		
		num=strlen(text_send_test());//求数据长度

		n = libwebsocket_write(wsi,text_send_test(), num,LWS_WRITE_TEXT);//发送文本测试
		//n = libwebsocket_write(wsi,json_text_test(), num,  LWS_WRITE_TEXT);//发送JSON 测试数据
		//n = libwebsocket_write(wsi,reportDeviceLog(), num,LWS_WRITE_TEXT);//发送DTS日志
		//n = libwebsocket_write(wsi,reportDeviceStatus(), num,LWS_WRITE_TEXT);//发送DTS状态
		//n = libwebsocket_write(wsi,reportDeviceRuntimeInfo(), num,LWS_WRITE_TEXT);//上报DTS运行信息
		//n = libwebsocket_write(wsi,requestActiveDtsDevice(), num,LWS_WRITE_TEXT);//激活DTS设备
		//n = libwebsocket_write(wsi,reportDtsRfidCheckOnData(), num,LWS_WRITE_TEXT);//上报RFID 刷卡考勤
		//n = libwebsocket_write(wsi,RequestSyncDtsAllConfigOptions(), num,LWS_WRITE_TEXT);//请求同步DTS配置
		//n = libwebsocket_write(wsi,RequestSyncDtsAllRfidPermission(), num,LWS_WRITE_TEXT);//请求同步RFID权限
		
		printf("Send success %s\n", text_send_test());//打印发送信息
		if (n < 0)
		return -1;

		/* get notified as soon as we can write again */
		libwebsocket_callback_on_writable(context, wsi);
		sleep(3);//每隔3秒发送一次数据
		//was_closed = 1;//关闭websocket通讯
		break;

	default:
		break;
	}

	return 0;
}
Пример #30
0
int lws_client_socket_service(struct libwebsocket_context *context,
		struct libwebsocket *wsi, struct libwebsocket_pollfd *pollfd)
{
	int n;
	char *p = (char *)&context->service_buffer[0];
	int len;
	unsigned char c;

	switch (wsi->mode) {

	case LWS_CONNMODE_WS_CLIENT_WAITING_CONNECT:

		/*
		 * we are under PENDING_TIMEOUT_SENT_CLIENT_HANDSHAKE
		 * timeout protection set in client-handshake.c
		 */

               if (libwebsocket_client_connect_2(context, wsi) == NULL) {
			/* closed */
			lwsl_client("closed\n");
			return -1;
		}

		/* either still pending connection, or changed mode */
		return 0;

	case LWS_CONNMODE_WS_CLIENT_WAITING_PROXY_REPLY:

		/* handle proxy hung up on us */

		if (pollfd->revents & LWS_POLLHUP) {

			lwsl_warn("Proxy connection %p (fd=%d) dead\n",
				(void *)wsi, pollfd->fd);

			libwebsocket_close_and_free_session(context, wsi,
						     LWS_CLOSE_STATUS_NOSTATUS);
			return 0;
		}

		n = recv(wsi->sock, context->service_buffer,
					sizeof(context->service_buffer), 0);
		if (n < 0) {
			
			if (LWS_ERRNO == LWS_EAGAIN) {
				lwsl_debug(
						   "Proxy read returned EAGAIN... retrying\n");
				return 0;
			}
			
			libwebsocket_close_and_free_session(context, wsi,
						     LWS_CLOSE_STATUS_NOSTATUS);
			lwsl_err("ERROR reading from proxy socket\n");
			return 0;
		}

		context->service_buffer[13] = '\0';
		if (strcmp((char *)context->service_buffer, "HTTP/1.0 200 ")) {
			libwebsocket_close_and_free_session(context, wsi,
						     LWS_CLOSE_STATUS_NOSTATUS);
			lwsl_err("ERROR proxy: %s\n", context->service_buffer);
			return 0;
		}

		/* clear his proxy connection timeout */

		libwebsocket_set_timeout(wsi, NO_PENDING_TIMEOUT, 0);

		/* fallthru */

	case LWS_CONNMODE_WS_CLIENT_ISSUE_HANDSHAKE:

		/*
		 * we are under PENDING_TIMEOUT_SENT_CLIENT_HANDSHAKE
		 * timeout protection set in client-handshake.c
		 */

		/*
		 * take care of our libwebsocket_callback_on_writable
		 * happening at a time when there's no real connection yet
		 */
		if (lws_change_pollfd(wsi, LWS_POLLOUT, 0))
			return -1;

#ifdef LWS_OPENSSL_SUPPORT
		/* we can retry this... just cook the SSL BIO the first time */

		if (wsi->use_ssl && !wsi->ssl) {
#if defined(CYASSL_SNI_HOST_NAME) || defined(SSL_CTRL_SET_TLSEXT_HOSTNAME)
			const char *hostname = lws_hdr_simple_ptr(wsi,
						_WSI_TOKEN_CLIENT_PEER_ADDRESS);
#endif

			wsi->ssl = SSL_new(context->ssl_client_ctx);
#ifndef USE_CYASSL
			SSL_set_mode(wsi->ssl,
					SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER);
#endif
			/*
			 * use server name indication (SNI), if supported,
			 * when establishing connection
			 */
#ifdef USE_CYASSL
#ifdef CYASSL_SNI_HOST_NAME
			CyaSSL_UseSNI(wsi->ssl, CYASSL_SNI_HOST_NAME,
				hostname, strlen(hostname));
#endif
#else
#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
			SSL_set_tlsext_host_name(wsi->ssl, hostname);
#endif
#endif

#ifdef USE_CYASSL
			/*
			 * CyaSSL does certificate verification differently
			 * from OpenSSL.
			 * If we should ignore the certificate, we need to set
			 * this before SSL_new and SSL_connect is called.
			 * Otherwise the connect will simply fail with error
			 * code -155
			 */
			if (wsi->use_ssl == 2)
				CyaSSL_set_verify(wsi->ssl,
							SSL_VERIFY_NONE, NULL);
#endif /* USE_CYASSL */

			wsi->client_bio =
				BIO_new_socket(wsi->sock, BIO_NOCLOSE);
			SSL_set_bio(wsi->ssl, wsi->client_bio, wsi->client_bio);

#ifdef USE_CYASSL
			CyaSSL_set_using_nonblock(wsi->ssl, 1);
#else
			BIO_set_nbio(wsi->client_bio, 1); /* nonblocking */
#endif

			SSL_set_ex_data(wsi->ssl,
					openssl_websocket_private_data_index,
								       context);
		}

		if (wsi->use_ssl) {
			lws_latency_pre(context, wsi);
			n = SSL_connect(wsi->ssl);
			lws_latency(context, wsi,
			  "SSL_connect LWS_CONNMODE_WS_CLIENT_ISSUE_HANDSHAKE",
								      n, n > 0);

			if (n < 0) {
				n = SSL_get_error(wsi->ssl, n);

				if (n == SSL_ERROR_WANT_READ ||
					n == SSL_ERROR_WANT_WRITE) {
					/*
					 * wants us to retry connect due to
					 * state of the underlying ssl layer...
					 * but since it may be stalled on
					 * blocked write, no incoming data may
					 * arrive to trigger the retry.
					 * Force (possibly many times if the SSL
					 * state persists in returning the
					 * condition code, but other sockets
					 * are getting serviced inbetweentimes)
					 * us to get called back when writable.
					 */

					lwsl_info(
					     "SSL_connect WANT_... retrying\n");
					libwebsocket_callback_on_writable(
								  context, wsi);
					
					wsi->mode = LWS_CONNMODE_WS_CLIENT_WAITING_SSL;
					
					return 0; /* no error */
				}
				n = -1;
			}

			if (n <= 0) {
				/*
				 * retry if new data comes until we
				 * run into the connection timeout or win
				 */
				
				n = ERR_get_error();
				if (n != SSL_ERROR_NONE) {
					lwsl_err("SSL connect error %lu: %s\n",
						n,
						ERR_error_string(n,
							  (char *)context->service_buffer));
					return 0;
				}
			}
		} else
			wsi->ssl = NULL;

		/* fallthru */
			
	case LWS_CONNMODE_WS_CLIENT_WAITING_SSL:
			
		if (wsi->use_ssl) {
				
			if (wsi->mode == LWS_CONNMODE_WS_CLIENT_WAITING_SSL) {
				lws_latency_pre(context, wsi);
				n = SSL_connect(wsi->ssl);
				lws_latency(context, wsi,
							"SSL_connect LWS_CONNMODE_WS_CLIENT_WAITING_SSL",
							n, n > 0);
				
				if (n < 0) {
					n = SSL_get_error(wsi->ssl, n);
					
					if (n == SSL_ERROR_WANT_READ ||
						n == SSL_ERROR_WANT_WRITE) {
						/*
						 * wants us to retry connect due to
						 * state of the underlying ssl layer...
						 * but since it may be stalled on
						 * blocked write, no incoming data may
						 * arrive to trigger the retry.
						 * Force (possibly many times if the SSL
						 * state persists in returning the
						 * condition code, but other sockets
						 * are getting serviced inbetweentimes)
						 * us to get called back when writable.
						 */
						
						lwsl_info(
								  "SSL_connect WANT_... retrying\n");
						libwebsocket_callback_on_writable(
														  context, wsi);
						
						wsi->mode = LWS_CONNMODE_WS_CLIENT_WAITING_SSL;
						
						return 0; /* no error */
					}
					n = -1;
				}
				
				if (n <= 0) {
					/*
					 * retry if new data comes until we
					 * run into the connection timeout or win
					 */
					n = ERR_get_error();
					if (n != SSL_ERROR_NONE) {
						lwsl_err("SSL connect error %lu: %s\n",
								 n,
								 ERR_error_string(n,
												  (char *)context->service_buffer));
						return 0;
					}
				}
			}
			
			#ifndef USE_CYASSL
			/*
			 * See comment above about CyaSSL certificate
			 * verification
			 */
			lws_latency_pre(context, wsi);
			n = SSL_get_verify_result(wsi->ssl);
			lws_latency(context, wsi,
				"SSL_get_verify_result LWS_CONNMODE..HANDSHAKE",
								      n, n > 0);

			if (n != X509_V_OK) {
				if((n == X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT || n == X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN) && wsi->use_ssl == 2) {
					lwsl_notice("accepting self-signed certificate\n");
				} else {
					lwsl_err(
						"server's cert didn't look good %d\n", n);
					libwebsocket_close_and_free_session(context,
							wsi, LWS_CLOSE_STATUS_NOSTATUS);
					return 0;
				}
			}
#endif /* USE_CYASSL */
		} else
			wsi->ssl = NULL;
#endif
		
		wsi->mode = LWS_CONNMODE_WS_CLIENT_ISSUE_HANDSHAKE2;
		libwebsocket_set_timeout(wsi,
				PENDING_TIMEOUT_AWAITING_CLIENT_HS_SEND,
							      AWAITING_TIMEOUT);

		/* fallthru */

	case LWS_CONNMODE_WS_CLIENT_ISSUE_HANDSHAKE2:
		p = libwebsockets_generate_client_handshake(context, wsi, p);
		if (p == NULL) {
			lwsl_err("Failed to generate handshake for client\n");
			libwebsocket_close_and_free_session(context, wsi,
						     LWS_CLOSE_STATUS_NOSTATUS);
			return 0;
		}

		/* send our request to the server */

		lws_latency_pre(context, wsi);

		n = lws_ssl_capable_write(wsi, context->service_buffer, p - (char *)context->service_buffer);
		lws_latency(context, wsi, "send lws_issue_raw", n, n == p - (char *)context->service_buffer);
		switch (n) {
		case LWS_SSL_CAPABLE_ERROR:
			lwsl_debug("ERROR writing to client socket\n");
			libwebsocket_close_and_free_session(context, wsi,
						     LWS_CLOSE_STATUS_NOSTATUS);
			return 0;
		case LWS_SSL_CAPABLE_MORE_SERVICE:
			libwebsocket_callback_on_writable(context, wsi);
			break;
		}

		wsi->u.hdr.parser_state = WSI_TOKEN_NAME_PART;
		wsi->u.hdr.lextable_pos = 0;
		wsi->mode = LWS_CONNMODE_WS_CLIENT_WAITING_SERVER_REPLY;
		libwebsocket_set_timeout(wsi,
				PENDING_TIMEOUT_AWAITING_SERVER_RESPONSE,
							      AWAITING_TIMEOUT);
		break;

	case LWS_CONNMODE_WS_CLIENT_WAITING_SERVER_REPLY:

		/* handle server hung up on us */

		if (pollfd->revents & LWS_POLLHUP) {

			lwsl_debug("Server connection %p (fd=%d) dead\n",
				(void *)wsi, pollfd->fd);

			goto bail3;
		}

		if (!(pollfd->revents & LWS_POLLIN))
			break;

		/* interpret the server response */

		/*
		 *  HTTP/1.1 101 Switching Protocols
		 *  Upgrade: websocket
		 *  Connection: Upgrade
		 *  Sec-WebSocket-Accept: me89jWimTRKTWwrS3aRrL53YZSo=
		 *  Sec-WebSocket-Nonce: AQIDBAUGBwgJCgsMDQ4PEC==
		 *  Sec-WebSocket-Protocol: chat
		 */

		/*
		 * we have to take some care here to only take from the
		 * socket bytewise.  The browser may (and has been seen to
		 * in the case that onopen() performs websocket traffic)
		 * coalesce both handshake response and websocket traffic
		 * in one packet, since at that point the connection is
		 * definitively ready from browser pov.
		 */
		len = 1;
		while (wsi->u.hdr.parser_state != WSI_PARSING_COMPLETE &&
								      len > 0) {
			n = lws_ssl_capable_read(context, wsi, &c, 1);
			lws_latency(context, wsi, "send lws_issue_raw", n, n == 1);
			switch (n) {
			case LWS_SSL_CAPABLE_ERROR:
				goto bail3;
			case LWS_SSL_CAPABLE_MORE_SERVICE:
				return 0;
			}

			if (libwebsocket_parse(context, wsi, c)) {
				lwsl_warn("problems parsing header\n");
				goto bail3;
			}
		}

		/*
		 * hs may also be coming in multiple packets, there is a 5-sec
		 * libwebsocket timeout still active here too, so if parsing did
		 * not complete just wait for next packet coming in this state
		 */

		if (wsi->u.hdr.parser_state != WSI_PARSING_COMPLETE)
			break;

		/*
		 * otherwise deal with the handshake.  If there's any
		 * packet traffic already arrived we'll trigger poll() again
		 * right away and deal with it that way
		 */

		return lws_client_interpret_server_handshake(context, wsi);

bail3:
		lwsl_info(
			"closing connection at LWS_CONNMODE...SERVER_REPLY\n");
		libwebsocket_close_and_free_session(context, wsi,
						    LWS_CLOSE_STATUS_NOSTATUS);
		return -1;

	case LWS_CONNMODE_WS_CLIENT_WAITING_EXTENSION_CONNECT:
		lwsl_ext("LWS_CONNMODE_WS_CLIENT_WAITING_EXTENSION_CONNECT\n");
		break;

	case LWS_CONNMODE_WS_CLIENT_PENDING_CANDIDATE_CHILD:
		lwsl_ext("LWS_CONNMODE_WS_CLIENT_PENDING_CANDIDATE_CHILD\n");
		break;
	default:
		break;
	}

	return 0;
}