guac_socket* guac_socket_nest(guac_socket* parent, int index) { /* Allocate socket and associated data */ guac_socket* socket = guac_socket_alloc(); __guac_socket_nest_data* data = malloc(sizeof(__guac_socket_nest_data)); /* Store file descriptor as socket data */ data->parent = parent; socket->data = data; /* Set write handler */ socket->write_handler = __guac_socket_nest_write_handler; return socket; }
guac_socket* guac_socket_open(int fd) { /* Allocate socket and associated data */ guac_socket* socket = guac_socket_alloc(); __guac_socket_fd_data* data = malloc(sizeof(__guac_socket_fd_data)); /* Store file descriptor as socket data */ data->fd = fd; socket->data = data; /* Set read/write handlers */ socket->read_handler = __guac_socket_fd_read_handler; socket->write_handler = __guac_socket_fd_write_handler; socket->select_handler = __guac_socket_fd_select_handler; return socket; }
guac_socket* guac_socket_open_secure(SSL_CTX* context, int fd) { /* Create new SSL structure */ SSL* ssl = SSL_new(context); if (ssl == NULL) return NULL; /* Allocate socket and associated data */ guac_socket* socket = guac_socket_alloc(); guac_socket_ssl_data* data = malloc(sizeof(guac_socket_ssl_data)); /* Init SSL */ data->context = context; data->ssl = ssl; SSL_set_fd(data->ssl, fd); /* Accept SSL connection, handle errors */ if (SSL_accept(ssl) <= 0) { guac_error = GUAC_STATUS_INTERNAL_ERROR; guac_error_message = "SSL accept failed"; free(data); guac_socket_free(socket); SSL_free(ssl); return NULL; } /* Store file descriptor as socket data */ data->fd = fd; socket->data = data; /* Set read/write handlers */ socket->read_handler = __guac_socket_ssl_read_handler; socket->write_handler = __guac_socket_ssl_write_handler; socket->select_handler = __guac_socket_ssl_select_handler; socket->free_handler = __guac_socket_ssl_free_handler; return socket; }
guac_client* guac_client_alloc() { int i; pthread_rwlockattr_t lock_attributes; /* Allocate new client */ guac_client* client = malloc(sizeof(guac_client)); if (client == NULL) { guac_error = GUAC_STATUS_NO_MEMORY; guac_error_message = "Could not allocate memory for client"; return NULL; } /* Init new client */ memset(client, 0, sizeof(guac_client)); client->state = GUAC_CLIENT_RUNNING; client->last_sent_timestamp = guac_timestamp_current(); /* Generate ID */ client->connection_id = guac_generate_id(GUAC_CLIENT_ID_PREFIX); if (client->connection_id == NULL) { free(client); return NULL; } /* Allocate buffer and layer pools */ client->__buffer_pool = guac_pool_alloc(GUAC_BUFFER_POOL_INITIAL_SIZE); client->__layer_pool = guac_pool_alloc(GUAC_BUFFER_POOL_INITIAL_SIZE); /* Allocate stream pool */ client->__stream_pool = guac_pool_alloc(0); /* Initialize streams */ client->__output_streams = malloc(sizeof(guac_stream) * GUAC_CLIENT_MAX_STREAMS); for (i=0; i<GUAC_CLIENT_MAX_STREAMS; i++) { client->__output_streams[i].index = GUAC_CLIENT_CLOSED_STREAM_INDEX; } /* Init locks */ pthread_rwlockattr_init(&lock_attributes); pthread_rwlockattr_setpshared(&lock_attributes, PTHREAD_PROCESS_SHARED); pthread_rwlock_init(&(client->__users_lock), &lock_attributes); /* Set up socket to broadcast to all users */ guac_socket* socket = guac_socket_alloc(); client->socket = socket; socket->data = client; socket->read_handler = __guac_socket_broadcast_read_handler; socket->write_handler = __guac_socket_broadcast_write_handler; socket->select_handler = __guac_socket_broadcast_select_handler; socket->flush_handler = __guac_socket_broadcast_flush_handler; socket->lock_handler = __guac_socket_broadcast_lock_handler; socket->unlock_handler = __guac_socket_broadcast_unlock_handler; return client; }