2 * Copyright (c) 2016 Cisco and/or its affiliates.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at:
7 * http://www.apache.org/licenses/LICENSE-2.0
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
17 * This is a temporary helper library to seamlessly run against
18 * the current API as exposed by libpneum.
19 * In the future once the sync API is exposed as well as
20 * a way to free the received data, this can go away.
31 pthread_mutex_t *cb_lock = &mut;
33 void *pneum_handle = NULL;
35 typedef void* (*arbitrary)();
37 int (*orig_pneum_connect)(char *name, char *chroot_prefix) = NULL;
38 int (*orig_pneum_connect_sync)(char *name, char *chroot_prefix) = NULL;
39 int (*orig_pneum_disconnect)(void) = NULL;
40 int (*orig_pneum_read)(char **data, int *l) = NULL;
41 int (*orig_pneum_write)(char *data, int len) = NULL;
42 int (*orig_pneum_has_data)(void) = NULL;
43 int (*orig_pneum_data_free)(char *data) = NULL;
45 arbitrary my_function = NULL;
50 u8 *cough_read_buffer;
51 u32 cough_read_buffer_size = 1000000;
52 u32 cough_read_head = 0;
53 u32 cough_read_lock_start = 0; /* lock_start till head is busy memory */
54 u32 cough_read_tail = 0;
57 int wrap_pneum_callback(char *data, int len) {
58 // printf("Cough callback! with %d bytes\n", len);
59 pthread_mutex_lock(cb_lock);
60 if(cough_read_lock_start == cough_read_head) {
61 // printf("Reset read head!\n");
64 cough_read_lock_start = 0;
67 memcpy(cough_read_buffer + cough_read_head, &store_len, sizeof(u32));
68 cough_read_head += sizeof(u32);
69 memcpy(cough_read_buffer + cough_read_head, data, len);
70 cough_read_head += len;
71 pthread_mutex_unlock(cb_lock);
75 int cough_pneum_attach(char *pneum_fname, char *cough_fname) {
76 /* this is needed to make the pneum aware of the wrap_pneum_callback */
77 pneum_handle = dlopen(cough_fname, RTLD_NOW|RTLD_GLOBAL);
78 /* now let's try to load pneum itself */
79 pneum_handle = dlopen(pneum_fname, RTLD_NOW|RTLD_GLOBAL);
81 *(void**)(&orig_pneum_connect) = dlsym(pneum_handle,"pneum_connect");
82 *(void**)(&orig_pneum_connect_sync) = dlsym(pneum_handle,"pneum_connect_sync");
83 *(void**)(&orig_pneum_disconnect) = dlsym(pneum_handle,"pneum_disconnect");
84 *(void**)(&orig_pneum_read) = dlsym(pneum_handle,"pneum_read");
85 *(void**)(&orig_pneum_write) = dlsym(pneum_handle,"pneum_write");
86 *(void**)(&orig_pneum_has_data) = dlsym(pneum_handle,"pneum_has_data");
87 *(void**)(&orig_pneum_data_free) = dlsym(pneum_handle,"pneum_data_free");
88 // If you uncomment the below line we pretend we have an async-only libpneum
89 orig_pneum_connect_sync = NULL;
90 cough_read_buffer = malloc(cough_read_buffer_size);
92 printf("Could not get cough handle\n");
93 printf("Error: %s", dlerror());
97 *(void**)(&my_function) = dlsym(pneum_handle,"something");
101 int pneum_connect(char *name, char *chroot_prefix) {
102 if(orig_pneum_connect) {
103 return(orig_pneum_connect(name, chroot_prefix));
105 printf("COUGH: pneum_connect\n");
109 int pneum_connect_sync(char *name, char *chroot_prefix) {
110 if(orig_pneum_connect_sync) {
111 int ret = (orig_pneum_connect_sync(name, chroot_prefix));
114 return(orig_pneum_connect(name, chroot_prefix));
119 int pneum_disconnect(void) {
120 if(orig_pneum_disconnect) {
121 return orig_pneum_disconnect();
123 printf("COUGH: pneum_disconnect\n");
128 int pneum_has_data(void) {
129 if (orig_pneum_connect_sync) {
130 /* always return 1 in a pass-through case */
133 // printf("COUGH: pneum_has_data\n");
134 return (cough_read_head != cough_read_tail);
139 int pneum_read(char **data, int *l) {
140 if(orig_pneum_connect_sync) {
141 return orig_pneum_read(data, l);
143 while(!pneum_has_data());
145 pthread_mutex_lock(cb_lock);
146 memcpy(&n_bytes, cough_read_buffer + cough_read_tail, sizeof(u32));
147 cough_read_tail += sizeof(u32);
148 void * dataptr = (void *) (cough_read_buffer + cough_read_tail);
150 cough_read_tail += n_bytes;
152 pthread_mutex_unlock(cb_lock);
157 int pneum_write(char *data, int len) {
158 if(orig_pneum_write) {
159 return(orig_pneum_write(data, len));
161 printf("COUGH: pneum_write\n");
166 void pneum_data_free(char *data) {
167 if (orig_pneum_connect_sync) {
168 if(orig_pneum_data_free) {
169 orig_pneum_data_free(data);
171 printf("COUGH: pneum_data_free\n");
175 uint32_t index = ((u8*)data) - cough_read_buffer;
176 pthread_mutex_lock(cb_lock);
177 if ((index < cough_read_head) && (index > cough_read_lock_start)) {
178 len = (void *)(data - sizeof(u32));
179 cough_read_lock_start = index + *len;
181 pthread_mutex_unlock(cb_lock);