Пример #1
0
int websocket_recv(int socket, unsigned char *data, size_t maxsize, struct sockaddr_in *sockaddrbuf, size_t fromLen)
{
	libwebsocket_context *context = contexts[socket].context;
	if(context == NULL)
		return -1;
	int n = libwebsocket_service(context, 0);
	if(n < 0)
		return n;
	context_data *ctx_data = (context_data *)libwebsocket_context_user(context);
	websocket_chunk *chunk = (websocket_chunk *)ctx_data->recv_buffer.First();
	if(chunk == 0)
		return 0;
	if(maxsize >= chunk->size - chunk->read)
	{
		int len = chunk->size - chunk->read;
		memcpy(data, &chunk->data[chunk->read], len);
		memcpy(sockaddrbuf, &chunk->addr, fromLen);
		ctx_data->recv_buffer.PopFirst();
		return len;
	}
	else
	{
		memcpy(data, &chunk->data[chunk->read], maxsize);
		memcpy(sockaddrbuf, &chunk->addr, fromLen);
		chunk->read += maxsize;
		return maxsize;
	}
}
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;
}
 static int onSocketCallback(struct libwebsocket_context *ctx,
                             struct libwebsocket *wsi,
                             enum libwebsocket_callback_reasons reason,
                             void *user, void *in, size_t len)
 {
     // Gets the user data from context. We know that it's a 'WebSocket' instance.
     WebSocket* wsInstance = (WebSocket*)libwebsocket_context_user(ctx);
     if (wsInstance)
     {
         return wsInstance->onSocketCallback(ctx, wsi, reason, user, in, len);
     }
     return 0;
 }
Пример #4
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; 
}
Пример #5
0
int server_socket_callback(
    struct libwebsocket_context* lws_context,
    struct libwebsocket* wsi,
    enum libwebsocket_callback_reasons reason,
    void* user,
    void* in,
    size_t len)
{
    char* buffer;
    int bytes_sent;
    server_context* context = (server_context*)libwebsocket_context_user(lws_context);

    switch (reason)
    {
    case LWS_CALLBACK_ESTABLISHED:
        printf("Client connection established.\n");
        break;

    case LWS_CALLBACK_PROTOCOL_DESTROY:
        printf("Client connection closed.\n");
        break;

    case LWS_CALLBACK_SERVER_WRITEABLE:
        if (context->send_buffer != NULL)
        {
            buffer = (char*)malloc(LWS_SEND_BUFFER_PRE_PADDING + context->send_length + LWS_SEND_BUFFER_POST_PADDING);
            memset(buffer, 0, LWS_SEND_BUFFER_PRE_PADDING + context->send_length + LWS_SEND_BUFFER_POST_PADDING);
            memcpy(buffer + LWS_SEND_BUFFER_PRE_PADDING, context->send_buffer, context->send_length);

            bytes_sent = libwebsocket_write(wsi, buffer + LWS_SEND_BUFFER_PRE_PADDING, context->send_length, LWS_WRITE_TEXT);
            free(buffer);

            if (bytes_sent < context->send_length)
            {
                printf("Error writing to client socket.\n");
                return -1;
            }
        }

        break;

    case LWS_CALLBACK_RECEIVE:
        printf("Received client data\n");
        break;
    }

    return 0;
}
Пример #6
0
int FWebSocket::unreal_networking_server
(
    struct libwebsocket_context *Context,
    struct libwebsocket *Wsi,
    enum libwebsocket_callback_reasons Reason,
    void *User,
    void *In,
    size_t Len
)
{
    PerSessionDataServer* BufferInfo = (PerSessionDataServer*)User;
    FWebSocketServer* Server = (FWebSocketServer*)libwebsocket_context_user(Context);

    switch (Reason)
    {
    case LWS_CALLBACK_ESTABLISHED:
    {
        BufferInfo->Socket = new FWebSocket(Context, Wsi);
        Server->ConnectedCallBack.ExecuteIfBound(BufferInfo->Socket);
        libwebsocket_set_timeout(Wsi, NO_PENDING_TIMEOUT, 0);
    }
    break;

    case LWS_CALLBACK_RECEIVE:
    {
        BufferInfo->Socket->OnRawRecieve(In, Len);
        libwebsocket_set_timeout(Wsi, NO_PENDING_TIMEOUT, 0);
    }
    break;

    case LWS_CALLBACK_SERVER_WRITEABLE:
    {
        BufferInfo->Socket->OnRawWebSocketWritable(Wsi);
        libwebsocket_set_timeout(Wsi, NO_PENDING_TIMEOUT, 0);
    }
    break;
    case LWS_CALLBACK_CLIENT_CONNECTION_ERROR:
    {
        BufferInfo->Socket->ErrorCallBack.ExecuteIfBound();
    }
    break;
    }

    return 0;
}
Пример #7
0
int websocket_fd_set(int socket, fd_set *set)
{
	libwebsocket_context *context = contexts[socket].context;
	if(context == NULL)
		return -1;
	context_data *ctx_data = (context_data *)libwebsocket_context_user(context);
	int max = 0;
	for(int i = 0; i < WS_CLIENTS; i++)
	{
		per_session_data *pss = ctx_data->port_map[i];
		if(pss == NULL)
			continue;
		int fd = libwebsocket_get_socket_fd(pss->wsi);
		if(fd > max)
			max = fd;
		FD_SET(fd, set);
	}
	return max;
}
Пример #8
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;
}
Пример #9
0
static int Websocket_callback(struct libwebsocket_context *context,
                              struct libwebsocket *websocket,
                              enum libwebsocket_callback_reasons reason,
                              void *user, void *inputData, size_t inputDataSize)
{
    WebSocketOpcode *self = libwebsocket_context_user(context);
    CSOUND *csound = self->csound;
    void *messageBuffer =
      (void *)&self->webSocket->messageBuffer[LWS_SEND_BUFFER_PRE_PADDING];

    switch (reason) {

    case LWS_CALLBACK_ESTABLISHED: {

      const struct libwebsocket_protocols *protocol =
        libwebsockets_get_protocol(websocket);
      csound->Message(csound,
                      Str("websocket: connection established for %s\n"),
                      protocol->name);
      break;
    }
    case LWS_CALLBACK_SERVER_WRITEABLE: {

      WebSocketOpcode_handleServerWritable(websocket, self, csound, messageBuffer);
      break;
    }
    case LWS_CALLBACK_RECEIVE: {

      WebSocketOpcode_handleReceive(websocket, self, csound,
                                    inputDataSize, inputData);
      break;
    }
    default: {

      break;
    }
    }

    return OK;
}
Пример #10
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;
}
Пример #11
0
    int WebSocketQueue::callback(libwebsocket_context *context, libwebsocket *wsi,
                                 LibWebsocketsCallbackReasonBoxed const& reasonBoxed,
                                 void *user, void *in, size_t len)
    {
        WebSocketQueue *self = (WebSocketQueue*)libwebsocket_context_user(context);
        PerSession *perSession = (PerSession*)user;
        libwebsocket_callback_reasons reason = reasonBoxed.value;

        // reason for callback
        switch (reason) {
        case LWS_CALLBACK_FILTER_NETWORK_CONNECTION: {
            if (self->sessions_.size() >= self->maxSessionCount_) {
                GATEY_LOG("not accepting connection because already connected");
                return -1;
            }
            break;
        }
        case LWS_CALLBACK_ESTABLISHED:
            *perSession = PerSession(self->nextUniqueSessionId_);
            self->nextUniqueSessionId_++;
            self->sessions_.insert(perSession->sessionId);
            if (self->sessions_.size() > self->maxSessionCount_) {
                GATEY_LOG("connection established but will be canceled" + std::to_string(perSession->sessionId));
                return -1;
            }

            GATEY_LOG("connection established" + std::to_string(perSession->sessionId));
            break;
        case LWS_CALLBACK_RECEIVE: {
            char const* bytes = (char const*)in;
            InMessage inMessage(perSession->sessionId, bytes, len);
            self->inMessages_.push_back(std::move(inMessage));

            GATEY_LOG("received message");
            break;
        }
        case LWS_CALLBACK_SERVER_WRITEABLE: {
            //Send messages from the queue
            auto found = self->firstMessageWithDestination(perSession->sessionId);
            if (found == self->outMessages_.end())
                break;
            
            OutMessage& message = *found;
            libwebsocket_write(wsi, (unsigned char*)&message.buffer_[LWS_SEND_BUFFER_PRE_PADDING], message.len_, LWS_WRITE_TEXT);
            
            message.removeDestination(perSession->sessionId);
            self->messageSent_ = true;
            break;
        }
        case LWS_CALLBACK_CLOSED: {
            self->sessions_.erase(perSession->sessionId);
            for(OutMessage& outMessage : self->outMessages_) {
                outMessage.removeDestination(perSession->sessionId);
            }
            
            //TODO: Remove already received messages? no
//            std::remove_if(self->inMessages_.begin(), self->inMessages_.end(),
//                           [sessionId](InMessage const& message)
//            {
//                return message.sessionId_ == sessionId;
//            });
            
            GATEY_LOG("connection closed" + std::to_string(perSession->sessionId));
            break;
        }

        default: break;
        }

        return 0;
    }
Пример #12
0
static int callback_http(struct libwebsocket_context *context,
#endif
		struct libwebsocket *wsi,
		enum libwebsocket_callback_reasons reason,
		void *user,
		void *in,
		size_t len)
{
	struct libws_http_data *u = (struct libws_http_data *)user;
	struct libws_mqtt_hack *hack;
	char *http_dir;
	size_t buflen;
	size_t wlen;
	char *filename_canonical;
	unsigned char buf[4096];
	struct stat filestat;
	struct mosquitto_db *db = &int_db;
	struct mosquitto *mosq;
	struct lws_pollargs *pollargs = (struct lws_pollargs *)in;

	/* FIXME - ssl cert verification is done here. */

	switch (reason) {
		case LWS_CALLBACK_HTTP:
			if(!u){
				return -1;
			}

#if defined(LWS_LIBRARY_VERSION_NUMBER)
			hack = (struct libws_mqtt_hack *)lws_context_user(lws_get_context(wsi));
#else
			hack = (struct libws_mqtt_hack *)libwebsocket_context_user(context);
#endif
			if(!hack){
				return -1;
			}
			http_dir = hack->http_dir;

			if(!http_dir){
				/* http disabled */
				return -1;
			}

			/* Forbid POST */
			if(lws_hdr_total_length(wsi, WSI_TOKEN_POST_URI)){
				libwebsockets_return_http_status(context, wsi, HTTP_STATUS_METHOD_NOT_ALLOWED, NULL);
				return -1;
			}

#if defined(LWS_LIBRARY_VERSION_NUMBER)
			filename_canonical = http__canonical_filename(wsi, (char *)in, http_dir);
#else
			filename_canonical = http__canonical_filename(context, wsi, (char *)in, http_dir);
#endif
			if(!filename_canonical) return -1;

			u->fptr = fopen(filename_canonical, "rb");
			if(!u->fptr){
				free(filename_canonical);
				libwebsockets_return_http_status(context, wsi, HTTP_STATUS_NOT_FOUND, NULL);
				return -1;
			}
			if(fstat(fileno(u->fptr), &filestat) < 0){
				free(filename_canonical);
				libwebsockets_return_http_status(context, wsi, HTTP_STATUS_INTERNAL_SERVER_ERROR, NULL);
				fclose(u->fptr);
				u->fptr = NULL;
				return -1;
			}


			if((filestat.st_mode & S_IFDIR) == S_IFDIR){
				fclose(u->fptr);
				u->fptr = NULL;
				free(filename_canonical);

				/* FIXME - use header functions from lws 2.x */
				buflen = snprintf((char *)buf, 4096, "HTTP/1.0 302 OK\r\n"
												"Location: %s/\r\n\r\n",
												(char *)in);
				return libwebsocket_write(wsi, buf, buflen, LWS_WRITE_HTTP);
			}

			if((filestat.st_mode & S_IFREG) != S_IFREG){
				libwebsockets_return_http_status(context, wsi, HTTP_STATUS_FORBIDDEN, NULL);
				fclose(u->fptr);
				u->fptr = NULL;
				free(filename_canonical);
				return -1;
			}

			log__printf(NULL, MOSQ_LOG_DEBUG, "http serving file \"%s\".", filename_canonical);
			free(filename_canonical);
			/* FIXME - use header functions from lws 2.x */
			buflen = snprintf((char *)buf, 4096, "HTTP/1.0 200 OK\r\n"
												"Server: mosquitto\r\n"
												"Content-Length: %u\r\n\r\n",
												(unsigned int)filestat.st_size);
            if(libwebsocket_write(wsi, buf, buflen, LWS_WRITE_HTTP) < 0){
				fclose(u->fptr);
				u->fptr = NULL;
				return -1;
			}
			libwebsocket_callback_on_writable(context, wsi);
			break;

		case LWS_CALLBACK_HTTP_BODY:
			/* For extra POST data? */
			return -1;

		case LWS_CALLBACK_HTTP_BODY_COMPLETION:
			/* For end of extra POST data? */
			return -1;

		case LWS_CALLBACK_FILTER_HTTP_CONNECTION:
			/* Access control here */
			return 0;

		case LWS_CALLBACK_HTTP_WRITEABLE:
			/* Send our data here */
			if(u && u->fptr){
				do{
					buflen = fread(buf, 1, sizeof(buf), u->fptr);
					if(buflen < 1){
						fclose(u->fptr);
						u->fptr = NULL;
						return -1;
					}
					wlen = libwebsocket_write(wsi, buf, buflen, LWS_WRITE_HTTP);
					if(wlen < buflen){
						if(fseek(u->fptr, buflen-wlen, SEEK_CUR) < 0){
							fclose(u->fptr);
							u->fptr = NULL;
							return -1;
						}
					}else{
						if(buflen < sizeof(buf)){
							fclose(u->fptr);
							u->fptr = NULL;
						}
					}
				}while(u->fptr && !lws_send_pipe_choked(wsi));
				libwebsocket_callback_on_writable(context, wsi);
			}else{
				return -1;
			}
			break;

		case LWS_CALLBACK_CLOSED:
		case LWS_CALLBACK_CLOSED_HTTP:
		case LWS_CALLBACK_HTTP_FILE_COMPLETION:
			if(u && u->fptr){
				fclose(u->fptr);
				u->fptr = NULL;
			}
			break;

		case LWS_CALLBACK_ADD_POLL_FD:
		case LWS_CALLBACK_DEL_POLL_FD:
		case LWS_CALLBACK_CHANGE_MODE_POLL_FD:
			HASH_FIND(hh_sock, db->contexts_by_sock, &pollargs->fd, sizeof(pollargs->fd), mosq);
			if(mosq && (pollargs->events & POLLOUT)){
				mosq->ws_want_write = true;
			}
			break;

#ifdef WITH_TLS
		case LWS_CALLBACK_OPENSSL_PERFORM_CLIENT_CERT_VERIFICATION:
			if(!len || (SSL_get_verify_result((SSL*)in) != X509_V_OK)){
				return 1;
			}
			break;
#endif

		default:
			return 0;
	}

	return 0;
}
Пример #13
0
}

void st_websocket_free(STWebSocket ws)
{
    free(ws);
}

static int _ws_callback(
        struct libwebsocket_context *this,
        struct libwebsocket *wsi,
        enum libwebsocket_callback_reasons reason,
        void *user,
        void *in,
        size_t len)
{
    STWebSocket ws = (STWebSocket)libwebsocket_context_user(this);
    switch (reason)
    {
        case LWS_CALLBACK_CLIENT_ESTABLISHED:
        {
            fprintf(stderr, "ws_callback: LWS_CALLBACK_CLIENT_ESTABLISHED\n");
            libwebsocket_callback_on_writable(this, wsi);
#if 0
            CanopyEventDetails_t eventDetails;
            fprintf(stderr, "ws_callback: LWS_CALLBACK_CLIENT_ESTABLISHED\n");
            libwebsocket_callback_on_writable(this, wsi);

            /* Call event callback */
            eventDetails.ctx = canopy;
            eventDetails.eventType = CANOPY_EVENT_CONNECTION_ESTABLISHED;
            eventDetails.userData = canopy->cbExtra;
Пример #14
0
// This static function handles all callbacks coming in and when context is services via libwebsocket_service
// return value of -1, closes the connection.
int FNetworkFileServerHttp::CallBack_HTTP(	
			struct libwebsocket_context *Context, 
			struct libwebsocket *Wsi, 
			enum libwebsocket_callback_reasons Reason, 
			void *User, 
			void *In, 
			size_t Len)
{
	PerSessionData* BufferInfo = (PerSessionData*)User;
	FNetworkFileServerHttp* Server = (FNetworkFileServerHttp*)libwebsocket_context_user(Context); 

	switch (Reason)
	{

	case LWS_CALLBACK_HTTP: 

		// hang on to socket even if there's no data for atleast 60 secs. 
		libwebsocket_set_timeout(Wsi, NO_PENDING_TIMEOUT, 60);

		/* if it was not legal POST URL, let it continue and accept data */
		if (!lws_hdr_total_length(Wsi, WSI_TOKEN_POST_URI))
		{
			char *requested_uri = (char *) In;

			// client request the base page. e.g  http://unrealfileserver:port/ 
			// just return a banner, probably add some more information, e,g Version, Config, Game. etc. 
			if ( FCString::Strcmp(ANSI_TO_TCHAR(requested_uri), TEXT("/")) == 0 )
			{
				TCHAR Buffer[1024]; 
				TCHAR ServerBanner[] = TEXT("<HTML>This is Unreal File Server</HTML>");
				int x  = FCString::Sprintf(
					Buffer,
					TEXT("HTTP/1.0 200 OK\x0d\x0a")
					TEXT("Server: Unreal File Server\x0d\x0a")
					TEXT("Connection: close\x0d\x0a") 
					TEXT("Content-Type: text/html; charset=utf-8\x0d\x0a")
					TEXT("Content-Length: %u\x0d\x0a\x0d\x0a%s"), 
					FCString::Strlen(ServerBanner),
					ServerBanner
					);

				// very small data being sent, its fine to just send.  
				libwebsocket_write(Wsi,(unsigned char*)TCHAR_TO_ANSI(Buffer),FCStringAnsi::Strlen(TCHAR_TO_ANSI(Buffer)), LWS_WRITE_HTTP);
			}
			else
			{
				// client has asked for a file. ( only html/js files are served.) 
					
				// what type is being served. 
				FString FilePath = FPaths::GameDir() / TEXT("Binaries/HTML5") +  FString((ANSICHAR*)In); 
				TCHAR Mime[512];

				
				if ( FilePath.Contains(".js"))
				{
                    FCStringWide::Strcpy(Mime,TEXT("application/javascript;charset=UTF-8"));
				}
				else
				{
					 FCStringWide::Strcpy(Mime,TEXT("text/html;charset=UTF-8"));
				}

				UE_LOG(LogFileServer, Warning, TEXT("HTTP Serving file %s with mime %s "), *FilePath, (Mime));

				FString AbsoluteFilePath = FPaths::ConvertRelativePathToFull(FilePath);
				AbsoluteFilePath.ReplaceInline(TEXT("/"),TEXT("\\"));

				// we are going to read the complete file in memory and then serve it in batches. 
				// rather than reading and sending in batches because Unreal NFS servers are not running in memory 
				// constrained env and the added complexity is not worth it. 


				TArray<uint8> FileData; 
				FFileHelper::LoadFileToArray(FileData, *AbsoluteFilePath, FILEREAD_Silent);
					
				if (FileData.Num() == 0)
				{
					// umm. we didn't find file, we should tell the client that we couldn't find it. 
					// send 404.
					char Header[]= 	"HTTP/1.1 404 Not Found\x0d\x0a"
									"Server: Unreal File Server\x0d\x0a"
									"Connection: close\x0d\x0a";

					libwebsocket_write(Wsi,(unsigned char*)Header,FCStringAnsi::Strlen(Header), LWS_WRITE_HTTP);
					// chug along, client will close the  connection. 
					break; 
				}

				// file up the header. 
				TCHAR Header[1024];
				int Length  = FCString::Sprintf(Header,
					TEXT("HTTP/1.1 200 OK\x0d\x0a")
					TEXT("Server: Unreal File Server\x0d\x0a")
					TEXT("Connection: close\x0d\x0a")
					TEXT("Content-Type: %s \x0d\x0a")
					TEXT("Content-Length: %u\x0d\x0a\x0d\x0a"),
					Mime,FileData.Num());

				// make space for the whole file in our out buffer. 
				BufferInfo->Out.Append((uint8*)TCHAR_TO_ANSI(Header),Length); 
				BufferInfo->Out.Append(FileData);
				// we need to write back to the client, queue up a write callback. 
				libwebsocket_callback_on_writable(Context, Wsi);
			}
		}
		else
		{
			// we got a post request!,  queue up a write callback. 
			libwebsocket_callback_on_writable(Context, Wsi);
		}

		break;
	case LWS_CALLBACK_HTTP_BODY: 
		{
			// post data is coming in, push it on to our incoming buffer.  
			UE_LOG(LogFileServer, Log, TEXT("Incoming HTTP Partial Body Size %d, total size  %d"),Len, Len+ BufferInfo->In.Num());
			BufferInfo->In.Append((uint8*)In,Len);
			// we received some data - update time out.
			libwebsocket_set_timeout(Wsi, NO_PENDING_TIMEOUT, 60);
		}
		break;
	case LWS_CALLBACK_HTTP_BODY_COMPLETION: 
		{
			// we have all the post data from the client. 
			// create archives and process them. 
			UE_LOG(LogFileServer, Log, TEXT("Incoming HTTP total size  %d"), BufferInfo->In.Num());
			FMemoryReader Reader(BufferInfo->In);
			TArray<uint8> Writer;

			FNetworkFileServerHttp::Process(Reader,Writer,Server);

			// even if we have 0 data to push, tell the client that we don't any data. 
			ANSICHAR Header[1024];
			int Length  = FCStringAnsi::Sprintf(
				(ANSICHAR*)Header,
				"HTTP/1.1 200 OK\x0d\x0a"
				"Server: Unreal File Server\x0d\x0a"
				"Connection: close\x0d\x0a"
				"Content-Type: application/octet-stream \x0d\x0a"
				"Content-Length: %u\x0d\x0a\x0d\x0a", 
				Writer.Num()
				);

			// Add Http Header 
			BufferInfo->Out.Append((uint8*)Header,Length); 
			// Add Binary Data.  
			BufferInfo->Out.Append(Writer);

			// we have enqueued data increase timeout and push a writable callback. 
			libwebsocket_set_timeout(Wsi, NO_PENDING_TIMEOUT, 60);
			libwebsocket_callback_on_writable(Context, Wsi);

		}
		break;
	case LWS_CALLBACK_CLOSED_HTTP: 
		// client went away or 
		//clean up. 
		BufferInfo->In.Empty();
		BufferInfo->Out.Empty(); 

		break;

	case LWS_CALLBACK_PROTOCOL_DESTROY: 
		// we are going away. 

		break; 

	case LWS_CALLBACK_HTTP_WRITEABLE: 

		// get rid of superfluous write  callbacks.
		if ( BufferInfo == NULL )
			break;

		// we have data o send out.
		if (BufferInfo->Out.Num())
		{
			int SentSize = libwebsocket_write(Wsi,(unsigned char*)BufferInfo->Out.GetData(),BufferInfo->Out.Num(), LWS_WRITE_HTTP);
			// get rid of the data that has been sent. 
			BufferInfo->Out.RemoveAt(0,SentSize); 
		}

		break;

	default:
		break;
	}

	return 0; 
}
Пример #15
0
static int callback_nyx_websockets(struct libwebsocket_context *context,struct libwebsocket *wsi,enum libwebsocket_callback_reasons reason, void *user,void *in,size_t len)
{
  struct per_session_data_nyx *pss =(struct per_session_data_nyx*)user;
  int n;

  node *wsd_state = (node*)libwebsocket_context_user(context);
  //node *daemon = (node*)libwebsocket_context_user(context);
  //node *wsd_state = node_GetNode(get_value(daemon));
  node *found_prot = NULL;
  node *state = NULL;
  node *block = NULL;
  //node *daemon = NULL;
  node *daemon_obj = NULL;
  node *session_uid = NULL;
  long lsession_uid = 0;
  node *sessions_num = NULL;
  node *sessions = NULL;
  long lsessions_num = 0;
  
  if(wsd_state)
  {
    state = node_GetItem(wsd_state,0);
    block = node_GetItem(wsd_state,1);
    //daemon = node_GetItem(wsd_state,2);
    node *protocols = node_GetItem(wsd_state,3);
    session_uid = node_GetItem(wsd_state,4);
    node *session_uid_value = node_GetItemByKey(session_uid,"value");
    lsession_uid = node_GetSint32(session_uid_value);
    sessions_num = node_GetItem(wsd_state,5);
    sessions = node_GetItem(wsd_state,6);
    node *sessions_num_value = node_GetItemByKey(sessions_num,"value");
    lsessions_num = node_GetSint32(sessions_num_value);
    daemon_obj = node_GetItem(wsd_state,9);
    if(wsi)
    {
      node *protocols_items = node_GetItemByKey(protocols,"items");
      const struct libwebsocket_protocols *prot = libwebsockets_get_protocol(wsi);
      if(prot && prot->name)
      {
        node_ItemIterationReset(protocols_items);
        while(node_ItemIterationUnfinished(protocols_items))
        {
          node *proto = node_ItemIterate(protocols_items);
          if(!strcmp(get_obj_name(proto),prot->name))
          {
            found_prot = proto;
          }
        }
      }
    }
  }

  switch(reason) 
  {

    //case LWS_CALLBACK_SERVER_NEW_CLIENT_INSTANTIATED:
    case LWS_CALLBACK_CLIENT_ESTABLISHED:
      printf("new session created:%d, num:%d\n",lsession_uid,lsessions_num);
      pss->session = NULL;
      break;

    case LWS_CALLBACK_HTTP:
      if(len < 1)
      {
        libwebsockets_return_http_status(context,wsi,HTTP_STATUS_BAD_REQUEST,NULL);
        return(-1);
      }
      if(lws_hdr_total_length(wsi,WSI_TOKEN_POST_URI))
        return(0);

      if(found_prot)
      {
        //printf("found prot in http callback : uid:%d,num:%d (sess:%x)\n",lsession_uid+1,lsessions_num,pss->session);
        if(!pss->session)
        {
          lsession_uid++;
          node *session_uid_value = node_GetItemByKey(session_uid,"value");
          node_SetSint32(session_uid_value,lsession_uid);
          lsessions_num++;
          node *sessions_num_value = node_GetItemByKey(sessions_num,"value");
          node_SetSint32(sessions_num_value,lsessions_num);
          pss->session = create_session(state,sessions,lsession_uid,get_obj_name(found_prot));
          node *session_privates = node_GetItemByKey(pss->session,"privates");
          set_obj_int(session_privates,"is_http",1);
          //printf("created new session :%d actual sessions num:%d\n",lsession_uid,lsessions_num);
        }
        

        node *parameters = create_obj("parameters");
        node *base_class = get_base_class(state);
        node *prot_value = create_class_instance(base_class);
        set_obj_string(prot_value,"name","protocol");
        set_obj_string(prot_value,"value",get_obj_name(found_prot));
        node_AddItem(parameters,prot_value);
        inc_obj_refcount(prot_value);
        char *url = str_CreateEmpty();
        url = str_AddChars(url,in,len);
        node *url_value = create_class_instance(base_class);
        set_obj_string(url_value,"name","url");
        set_obj_string(url_value,"value",url);
        node_AddItem(parameters,url_value);
        inc_obj_refcount(url_value);
        free(url);
        node_AddItem(parameters,pss->session);
        inc_obj_refcount(pss->session);
        //node_AddItem(parameters,daemon_obj);
        node_AddItem(parameters,sessions);
        inc_obj_refcount(sessions);
        node *tmp_parent = node_GetParent(found_prot);
        node *bmembers = node_GetItemByKey(block,"members");
        node_SetParent(found_prot,bmembers);
        node *ret_obj = execute_obj(state,found_prot,block,parameters,True,False);//,True);resolve
        node_SetParent(found_prot,tmp_parent);
        //dec_obj_refcount(msg_value);
        dec_obj_refcount(prot_value);
        //add_garbage(state,msg_value);//TODO check if "just survives"
        add_garbage(state,prot_value);
        dec_obj_refcount(url_value);
        add_garbage(state,url_value);
        dec_obj_refcount(pss->session);
        dec_obj_refcount(sessions);
 
        node *ret_obj_value = node_GetItemByKey(ret_obj,"value");
        if( (node_GetType(ret_obj_value)==NODE_TYPE_STRING && strlen(node_GetString(ret_obj_value))) || (node_GetType(ret_obj_value)==NODE_TYPE_BINARY && node_GetBinaryLength(ret_obj_value)) )
        {
          //printf("returning http message: [%s] :%d\n",node_GetString(ret_obj_value),strlen(node_GetString(ret_obj_value)));
          //node *ret_obj_copy = node_CopyTree(ret_obj,True,True);
          node *ret_obj_copy = copy_class(ret_obj);
          //reset_obj_refcount(ret_obj_copy);
          set_obj_string(ret_obj_copy,"name","message");
          add_member(pss->session,ret_obj_copy);
          inc_obj_refcount(ret_obj_copy);
        }
        libwebsocket_callback_on_writable(context, wsi);
      }
      break;

    case LWS_CALLBACK_HTTP_BODY_COMPLETION:
      if(found_prot)
      {
        printf("found prot in http body complete : %d,num:%d\n",lsession_uid,lsessions_num);
        if(daemon_obj)
        {
          printf("body: found daemon_obj\n");
        }
      }
      else
        printf("body closed: prot not found\n");
      //lwsl_notice("LWS_CALLBACK_HTTP_BODY_COMPLETION\n");
      libwebsockets_return_http_status(context,wsi,HTTP_STATUS_OK,NULL);
     return(-1);

    case LWS_CALLBACK_HTTP_FILE_COMPLETION:
      if(found_prot)
     {
        //printf("found prot in http file complete : %d,num:%d\n",lsession_uid,lsessions_num);
        lsessions_num--;
        node *sessions_num_value = node_GetItemByKey(sessions_num,"value");
        node_SetSint32(sessions_num_value,lsessions_num);
        delete_session(state,sessions,pss->session);
        pss->session = NULL;
        if(daemon_obj)
        {
          printf("http: found daemon_obj\n");
        }
      }
      else
        printf("file closed: prot not found\n");
      return(-1);

    case LWS_CALLBACK_FILTER_PROTOCOL_CONNECTION:
      if(found_prot)
      {
      int n;
      static const char *token_names[] = 
      {
        /*[WSI_TOKEN_GET_URI]   =*/ "GET URI",
        /*[WSI_TOKEN_POST_URI]    =*/ "POST URI",
        /*[WSI_TOKEN_OPTIONS]    =*/ "Options",
        /*[WSI_TOKEN_HOST]    =*/ "Host",
        /*[WSI_TOKEN_CONNECTION]  =*/ "Connection",
        /*[WSI_TOKEN_KEY1]    =*/ "key 1",
        /*[WSI_TOKEN_KEY2]    =*/ "key 2",
        /*[WSI_TOKEN_PROTOCOL]    =*/ "Protocol",
        /*[WSI_TOKEN_UPGRADE]   =*/ "Upgrade",
        /*[WSI_TOKEN_ORIGIN]    =*/ "Origin",
        /*[WSI_TOKEN_DRAFT]   =*/ "Draft",
        /*[WSI_TOKEN_CHALLENGE]   =*/ "Challenge",
        /* new for 04 */
        /*[WSI_TOKEN_KEY]   =*/ "Key",
        /*[WSI_TOKEN_VERSION]   =*/ "Version",
        /*[WSI_TOKEN_SWORIGIN]    =*/ "Sworigin",
        /* new for 05 */
        /*[WSI_TOKEN_EXTENSIONS]  =*/ "Extensions",
        /* client receives these */
        /*[WSI_TOKEN_ACCEPT]    =*/ "Accept",
        /*[WSI_TOKEN_NONCE]   =*/ "Nonce",
        /*[WSI_TOKEN_HTTP]    =*/ "Http",
        "Accept:",
        "Accept_Request_Headers:",
        "If-None-Match:",
        "If-Modified-Since:",
        "Accept-Encoding:",
        "Accept-Language:",
        "Pragma:",
        "Cache-Control:",
        "Authorization:",
        "Cookie:",
        "Content-Length:",
        "Content-Type:",
        "Date:",
        "Range:",
        "Referer:",
        "Uri-Args:",
        /*[WSI_TOKEN_MUXURL]  =*/ "MuxURL",
      };

      //printf("found prot in http filter callback : uid:%d,num:%d (sess:%x)\n",lsession_uid+1,lsessions_num,pss->session);
      if(!pss->session)
      {
        lsession_uid++;
        node *session_uid_value = node_GetItemByKey(session_uid,"value");
        node_SetSint32(session_uid_value,lsession_uid);
        lsessions_num++;
        node *sessions_num_value = node_GetItemByKey(sessions_num,"value");
        node_SetSint32(sessions_num_value,lsessions_num);
        pss->session = create_session(state,sessions,lsession_uid,get_obj_name(found_prot));
        //node *session_privates = node_GetItemByKey(pss->session,"privates");
        //set_obj_int(session_privates,"is_http",1);
      }
      //printf("filter sess:%x\n",pss->session);


      for(n=0;n<(int)(sizeof(token_names)/sizeof(token_names[0]));n++) 
      {
        if (!lws_hdr_total_length(wsi, n))
          continue;
        char *cookies = (char*)malloc(512);
        memset(cookies,0,512);
        lws_hdr_copy(wsi,cookies,511,n);
        //printf("header:%s = [%s]\n",token_names[n],cookies);
        //fflush(stdout);
        if(pss->session && !strcmp("Cookie:",token_names[n]))
        {
          //printf("cookie found:%s = [%s]\n",token_names[n],cookies);
          //fflush(stdout);
          node *base_class = get_base_class(state);
          node *cookie_value = create_class_instance(base_class);
          set_obj_string(cookie_value,"name","cookie");
          set_obj_string(cookie_value,"value",cookies);
          add_member(pss->session,cookie_value);
          inc_obj_refcount(cookie_value);
        }
        free(cookies);
      }
      }
    break;

    case LWS_CALLBACK_HTTP_WRITEABLE: 
    case LWS_CALLBACK_SERVER_WRITEABLE:
      {
        //node_PrintTree(pss->session);
        node *message = get_member(pss->session,"message");
        node *session_privates = node_GetItemByKey(pss->session,"privates");
        node *http_only = node_GetItemByKey(session_privates,"is_http");

        while(message)
        {
          //node *session_id = get_member(pss->session,"id");
          //node *session_id_value = node_GetItemByKey(session_id,"value");
          node *message_value = node_GetItemByKey(message,"value");
          unsigned char *me = NULL;
          unsigned long me_len = 0;
          if(node_GetType(message_value)==NODE_TYPE_STRING)
          {
            me = (unsigned char*)node_GetString(message_value);
            me_len = strlen((char*)me);
          }
          else if(node_GetType(message_value)==NODE_TYPE_BINARY)
          {
            me = (unsigned char*)node_GetBinary(message_value);
            me_len = node_GetBinaryLength(message_value);
          }
          //printf("sending message now: [%s] to: %d\n",me,node_GetSint32(session_id_value));
          //fflush(stdout);
          unsigned char *buf = (unsigned char*)malloc(LWS_SEND_BUFFER_PRE_PADDING + me_len + LWS_SEND_BUFFER_POST_PADDING);
          memcpy(buf+LWS_SEND_BUFFER_PRE_PADDING,me,me_len);

          if(http_only)
            //n = libwebsocket_write(wsi, me, me_len, LWS_WRITE_HTTP);
            n = libwebsocket_write(wsi,buf+LWS_SEND_BUFFER_PRE_PADDING,me_len,LWS_WRITE_HTTP);
          else
            //n = libwebsocket_write(wsi, me, me_len, LWS_WRITE_TEXT);
            n = libwebsocket_write(wsi,buf+LWS_SEND_BUFFER_PRE_PADDING,me_len,LWS_WRITE_TEXT);
          free(buf);
          if(n<0)
          {
            printf("ERROR %d writing to socket, hanging up\n", n);
            return(1);
          }
          if(n<(long)me_len)
          {
            printf("Partial write\n");
            return(-1);
          }
          //node_FreeTree(pss->message);
          remove_member(pss->session,message);
          dec_obj_refcount(message);
          //printf("removing message from queue:%x (%d)\n",message,get_obj_refcount(message));
          add_garbage(state,message);
          message = get_member(pss->session,"message");          
        }
        if(http_only)
        {
          //if(lws_http_transaction_completed(wsi))
          //{
            //printf("removing http session num:%d\n",lsessions_num);
            lsessions_num--;
            node *sessions_num_value = node_GetItemByKey(sessions_num,"value");
            node_SetSint32(sessions_num_value,lsessions_num);
            delete_session(state,sessions,pss->session);
            pss->session = NULL;
            //printf("removed http\n");
              return -1;
            //return(-1);
          //}
          //else
          //  libwebsocket_callback_on_writable(context, wsi);
        }
      }
      break;

    case LWS_CALLBACK_ESTABLISHED:
      if(found_prot)
      {
        //printf("found prot in establish callback : uid:%d,num:%d (sess:%x)\n",lsession_uid+1,lsessions_num,pss->session);
        if(!pss->session)
        {
          lsession_uid++;
          node *session_uid_value = node_GetItemByKey(session_uid,"value");
          node_SetSint32(session_uid_value,lsession_uid);
          lsessions_num++;
          node *sessions_num_value = node_GetItemByKey(sessions_num,"value");
          node_SetSint32(sessions_num_value,lsessions_num);
          pss->session = create_session(state,sessions,lsession_uid,get_obj_name(found_prot));
        }
        if(daemon_obj)
        {
          node *connect_handler = get_member(daemon_obj,"connect_handler");
          if(connect_handler)
          {
            connect_handler = resolve_object(state,connect_handler);
            node *parameters = create_obj("parameters");
            node *base_class = get_base_class(state);
      
            node *prot_value = create_class_instance(base_class);
            set_obj_string(prot_value,"name","protocol");
            set_obj_string(prot_value,"value",get_obj_name(found_prot));
            node_AddItem(parameters,prot_value);
            inc_obj_refcount(prot_value);

            node_AddItem(parameters,pss->session);
            inc_obj_refcount(pss->session);
            node_AddItem(parameters,sessions);
            inc_obj_refcount(sessions);
            node *tmp_parent = node_GetParent(connect_handler);
            node *bmembers = node_GetItemByKey(block,"members");
            node_SetParent(connect_handler,bmembers);
            node *ret_obj = execute_obj(state,connect_handler,block,parameters,True,False);//,True);resolve
            node_SetParent(connect_handler,tmp_parent);
            dec_obj_refcount(prot_value);
            add_garbage(state,prot_value);
            dec_obj_refcount(pss->session);
            dec_obj_refcount(sessions);
            node *ret_obj_value = node_GetItemByKey(ret_obj,"value");
            if(node_GetType(ret_obj_value)==NODE_TYPE_STRING && strlen(node_GetString(ret_obj_value)))
            {
            }
          }
        }
      }
      break;

    case LWS_CALLBACK_CLOSED_HTTP:
    break;
    
    case LWS_CALLBACK_CLOSED:
    case LWS_CALLBACK_CLIENT_CONNECTION_ERROR:
      if(found_prot)
      {
        //printf("found prot in closed callback : uid:%d,num:%d (sess:%x)\n",lsession_uid,lsessions_num,pss->session);
        if(daemon_obj)
        {
        //printf("closed: found daemon_obj\n");
          node *disconnect_handler = get_member(daemon_obj,"disconnect_handler");
          if(disconnect_handler)
          {
            //printf("disc found\n");
            disconnect_handler = resolve_object(state,disconnect_handler);
            node *parameters = create_obj("parameters");
            node *base_class = get_base_class(state);
      
            node *prot_value = create_class_instance(base_class);
            set_obj_string(prot_value,"name","protocol");
            set_obj_string(prot_value,"value",get_obj_name(found_prot));
            node_AddItem(parameters,prot_value);
            inc_obj_refcount(prot_value);

            node_AddItem(parameters,pss->session);
            inc_obj_refcount(pss->session);
            node_AddItem(parameters,sessions);
            inc_obj_refcount(sessions);
            node *tmp_parent = node_GetParent(disconnect_handler);
            node *bmembers = node_GetItemByKey(block,"members");
            node_SetParent(disconnect_handler,bmembers);
            node *ret_obj = execute_obj(state,disconnect_handler,block,parameters,True,False);//,True);resolve
            node_SetParent(disconnect_handler,tmp_parent);
            dec_obj_refcount(prot_value);
            add_garbage(state,prot_value);
            dec_obj_refcount(pss->session);
            dec_obj_refcount(sessions);
            node *ret_obj_value = node_GetItemByKey(ret_obj,"value");
            if(node_GetType(ret_obj_value)==NODE_TYPE_STRING && strlen(node_GetString(ret_obj_value)))
            {
            }
          }
        }
        lsessions_num--;
        node *sessions_num_value = node_GetItemByKey(sessions_num,"value");
        node_SetSint32(sessions_num_value,lsessions_num);
        delete_session(state,sessions,pss->session);
        pss->session = NULL;
        //printf("disconnected\n");
      }
      else 
      {
        printf("closed connection without prot found\n");
        if(pss->session)
          printf("but a session was found\n");
      }
      break;

    case LWS_CALLBACK_RECEIVE:
      if(len>1024) 
      { //TODO use some variable
      lwsl_err("Server received packet bigger than %u, hanging up\n", 1024);
      return(1);
      }
      if(found_prot)
      {
      node *parameters = create_obj("parameters");
      node *base_class = get_base_class(state);
      
      node *prot_value = create_class_instance(base_class);
      set_obj_string(prot_value,"name","protocol");
      set_obj_string(prot_value,"value",get_obj_name(found_prot));
      node_AddItem(parameters,prot_value);
      inc_obj_refcount(prot_value);

      char *msg = str_CreateEmpty();
      msg = str_AddChars(msg,in,len);
      node *msg_value = create_class_instance(base_class);
      set_obj_string(msg_value,"name","message");
      set_obj_string(msg_value,"value",msg);
      node_AddItem(parameters,msg_value);
      inc_obj_refcount(msg_value);
      free(msg);

      /*node *session_value = create_class_instance(base_class);
      reset_obj_refcount(session_value);
      add_garbage(state,session_value);
      set_obj_string(session_value,"name","session_id");
      set_obj_int(session_value,"value",lsession_uid);
      set_obj_int(session_value,"item_index",2);
      node_AddItem(parameters,session_value);
      */
      node_AddItem(parameters,pss->session);
      inc_obj_refcount(pss->session);
      //node_AddItem(parameters,daemon_obj);
      //inc_obj_refcount(daemon_obj);

      node_AddItem(parameters,sessions);
      inc_obj_refcount(sessions);

      //printf("recv callback\n");
      //fflush(stdout);
      node *tmp_parent = node_GetParent(found_prot);
      node *bmembers = node_GetItemByKey(block,"members");
      node_SetParent(found_prot,bmembers);

      node *ret_obj = execute_obj(state,found_prot,block,parameters,True,False);//,True);resolve
      node_SetParent(found_prot,tmp_parent);
      //printf("recv callback finished\n");
      //fflush(stdout);

      dec_obj_refcount(msg_value);
      dec_obj_refcount(prot_value);
      add_garbage(state,msg_value);//TODO check if "just survives"
      add_garbage(state,prot_value);

      dec_obj_refcount(pss->session);
      dec_obj_refcount(sessions);
      //dec_obj_refcount(daemon_obj);
      //printf("recv gc\n");
      //fflush(stdout);
      //node *ret_obj_value = node_GetItemByKey(ret_obj,"value");
      //char *me = node_GetString(ret_obj_value);
      //printf("returned string:[%s]\n",me);
      node *ret_obj_value = node_GetItemByKey(ret_obj,"value");
      if(node_GetType(ret_obj_value)==NODE_TYPE_STRING && strlen(node_GetString(ret_obj_value)))
      {
        //printf("returning message: [%s] :%d\n",node_GetString(ret_obj_value),strlen(node_GetString(ret_obj_value)));
        //node *ret_obj_copy = node_CopyTree(ret_obj,True,True);
        node *ret_obj_copy = copy_class(ret_obj);
        //reset_obj_refcount(ret_obj_copy);
        set_obj_string(ret_obj_copy,"name","message");
        add_member(pss->session,ret_obj_copy);
        inc_obj_refcount(ret_obj_copy);
        //set_obj_string(ret_obj,"name","message");
        //add_member(pss->session,ret_obj);
        //inc_obj_refcount(ret_obj);
      }
      libwebsocket_callback_on_writable(context, wsi);
      }
      break;
    default:
      break;
  }

  return(0);
}