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; }
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; }
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; }
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; }
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; }
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; }
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; }
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; }
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; }
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; }
} 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;
// 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; }
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); }