Fix issues reported by coverity
[vpp.git] / vpp-api / lua / cough.c
1 /*
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:
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
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.
14  */
15
16 /* 
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.
21  */
22
23 #include <dlfcn.h>
24 #include <stdio.h>
25 #include <string.h>
26 #include <stdint.h>
27 #include <stdlib.h>
28 #include <pthread.h>
29
30 pthread_mutex_t mut;
31 pthread_mutex_t *cb_lock = &mut;
32
33 void *pneum_handle = NULL;
34
35 typedef void* (*arbitrary)();
36
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;
44
45 arbitrary my_function = NULL;
46
47 typedef uint8_t u8;
48 typedef uint32_t u32;
49
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;
55
56
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");
62     cough_read_head = 0;
63     cough_read_tail = 0;
64     cough_read_lock_start = 0;
65   }
66   u32 store_len = len;
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);
72   return len;
73 }
74
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);
80   if (pneum_handle) {
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);
91   } else {
92     printf("Could not get cough handle\n");
93     printf("Error: %s", dlerror());
94     return -1;
95   }
96
97   *(void**)(&my_function) = dlsym(pneum_handle,"something");
98 }
99
100
101 int pneum_connect(char *name, char *chroot_prefix) {
102   if(orig_pneum_connect) {
103     return(orig_pneum_connect(name, chroot_prefix));
104   } else {
105     printf("COUGH: pneum_connect\n");
106     return -1;
107   }
108 }
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));
112     return ret;
113   } else {
114     return(orig_pneum_connect(name, chroot_prefix));
115   }
116 }
117
118
119 int pneum_disconnect(void) {
120   if(orig_pneum_disconnect) {
121     return orig_pneum_disconnect();
122   } else {
123     printf("COUGH: pneum_disconnect\n");
124     return -1;
125   }
126 }
127
128 int pneum_has_data(void) {
129   if (orig_pneum_connect_sync) {
130     /* always return 1 in a pass-through case */
131     return 1;
132   } else {
133     // printf("COUGH: pneum_has_data\n");
134     return (cough_read_head != cough_read_tail);
135   }
136 }
137
138
139 int pneum_read(char **data, int *l) {
140   if(orig_pneum_connect_sync) {
141     return orig_pneum_read(data, l);
142   } else { 
143     while(!pneum_has_data());
144     u32 n_bytes;
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);
149     *data = dataptr;
150     cough_read_tail += n_bytes;
151     *l = n_bytes;
152     pthread_mutex_unlock(cb_lock);
153     return n_bytes; 
154   }
155 }
156
157 int pneum_write(char *data, int len) {
158   if(orig_pneum_write) {
159     return(orig_pneum_write(data, len));
160   } else {
161     printf("COUGH: pneum_write\n");
162     return -1;
163   }
164 }
165
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);
170     } else {
171       printf("COUGH: pneum_data_free\n");
172     }
173   } else {
174     u32 *len;
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;
180     }
181     pthread_mutex_unlock(cb_lock);
182   }
183 }