io.c (4748B)
1/* 2 * Licensed to the Apache Software Foundation (ASF) under one 3 * or more contributor license agreements. See the NOTICE file 4 * distributed with this work for additional information 5 * regarding copyright ownership. The ASF licenses this file 6 * to you under the Apache License, Version 2.0 (the 7 * "License"); you may not use this file except in compliance 8 * with the License. You may obtain a copy of the License at 9 * 10 * http://www.apache.org/licenses/LICENSE-2.0 11 * 12 * Unless required by applicable law or agreed to in writing, 13 * software distributed under the License is distributed on an 14 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 * KIND, either express or implied. See the License for the 16 * specific language governing permissions and limitations 17 * under the License. 18 */ 19 20#include "kubernetes.h" 21#include "terminal/terminal.h" 22 23#include <guacamole/client.h> 24#include <libwebsockets.h> 25 26#include <pthread.h> 27#include <stdbool.h> 28#include <string.h> 29 30void guac_kubernetes_receive_data(guac_client* client, 31 const char* buffer, size_t length) { 32 33 guac_kubernetes_client* kubernetes_client = 34 (guac_kubernetes_client*) client->data; 35 36 /* Strip channel index from beginning of buffer */ 37 int channel = *(buffer++); 38 length--; 39 40 switch (channel) { 41 42 /* Write STDOUT / STDERR directly to terminal as output */ 43 case GUAC_KUBERNETES_CHANNEL_STDOUT: 44 case GUAC_KUBERNETES_CHANNEL_STDERR: 45 guac_terminal_write(kubernetes_client->term, buffer, length); 46 break; 47 48 /* Ignore data on other channels */ 49 default: 50 guac_client_log(client, GUAC_LOG_DEBUG, "Received %i bytes along " 51 "channel %i.", length, channel); 52 53 } 54 55} 56 57void guac_kubernetes_send_message(guac_client* client, 58 int channel, const char* data, int length) { 59 60 guac_kubernetes_client* kubernetes_client = 61 (guac_kubernetes_client*) client->data; 62 63 pthread_mutex_lock(&(kubernetes_client->outbound_message_lock)); 64 65 /* Add message to buffer if space is available */ 66 if (kubernetes_client->outbound_messages_waiting 67 < GUAC_KUBERNETES_MAX_OUTBOUND_MESSAGES) { 68 69 /* Calculate storage position of next message */ 70 int index = (kubernetes_client->outbound_messages_top 71 + kubernetes_client->outbound_messages_waiting) 72 % GUAC_KUBERNETES_MAX_OUTBOUND_MESSAGES; 73 74 /* Obtain pointer to message slot at calculated position */ 75 guac_kubernetes_message* message = 76 &(kubernetes_client->outbound_messages[index]); 77 78 /* Copy details of message into buffer */ 79 message->channel = channel; 80 memcpy(message->data, data, length); 81 message->length = length; 82 83 /* One more message is now waiting */ 84 kubernetes_client->outbound_messages_waiting++; 85 86 /* Notify libwebsockets that we need a callback to send pending 87 * messages */ 88 lws_callback_on_writable(kubernetes_client->wsi); 89 lws_cancel_service(kubernetes_client->context); 90 91 } 92 93 /* Warn if data has to be dropped */ 94 else 95 guac_client_log(client, GUAC_LOG_WARNING, "Send buffer could not be " 96 "flushed in time to handle additional data. Outbound " 97 "message dropped."); 98 99 pthread_mutex_unlock(&(kubernetes_client->outbound_message_lock)); 100 101} 102 103bool guac_kubernetes_write_pending_message(guac_client* client) { 104 105 bool messages_remain; 106 guac_kubernetes_client* kubernetes_client = 107 (guac_kubernetes_client*) client->data; 108 109 pthread_mutex_lock(&(kubernetes_client->outbound_message_lock)); 110 111 /* Send one message from top of buffer */ 112 if (kubernetes_client->outbound_messages_waiting > 0) { 113 114 /* Obtain pointer to message at top */ 115 int top = kubernetes_client->outbound_messages_top; 116 guac_kubernetes_message* message = 117 &(kubernetes_client->outbound_messages[top]); 118 119 /* Write message including channel index */ 120 lws_write(kubernetes_client->wsi, 121 ((unsigned char*) message) + LWS_PRE, 122 message->length + 1, LWS_WRITE_BINARY); 123 124 /* Advance top to next message */ 125 kubernetes_client->outbound_messages_top++; 126 kubernetes_client->outbound_messages_top %= 127 GUAC_KUBERNETES_MAX_OUTBOUND_MESSAGES; 128 129 /* One less message is waiting */ 130 kubernetes_client->outbound_messages_waiting--; 131 132 } 133 134 /* Record whether messages remained at time of completion */ 135 messages_remain = (kubernetes_client->outbound_messages_waiting > 0); 136 137 pthread_mutex_unlock(&(kubernetes_client->outbound_message_lock)); 138 139 return messages_remain; 140 141} 142 143