1 /* Licensed to the Apache Software Foundation (ASF) under one or more 2 * contributor license agreements. See the NOTICE file distributed with 3 * this work for additional information regarding copyright ownership. 4 * The ASF licenses this file to You under the Apache License, Version 2.0 5 * (the "License"); you may not use this file except in compliance with 6 * the License. You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 #ifndef TCN_H 18 #define TCN_H 19 20 #include "apr.h" 21 #include "apr_general.h" 22 #include "apr_lib.h" 23 #include "apr_pools.h" 24 #include "apr_portable.h" 25 #include "apr_network_io.h" 26 #include "apr_poll.h" 27 #include "apr_ring.h" 28 #include "apr_strings.h" 29 30 #if !APR_HAS_THREADS 31 #error "Missing threading support from APR." 32 #endif 33 34 #if defined(DEBUG) || defined(_DEBUG) 35 /* On -DDEBUG use the statistics */ 36 #ifndef TCN_DO_STATISTICS 37 #define TCN_DO_STATISTICS 38 #endif 39 #endif 40 #include <stdio.h> 41 #include <stdlib.h> 42 #if defined(_WIN32) && !defined(__CYGWIN__) 43 #include <process.h> 44 #else 45 #include <unistd.h> 46 #endif 47 48 #include "tcn_api.h" 49 50 51 #if defined(_DEBUG) || defined(DEBUG) 52 #include <assert.h> 53 #define TCN_ASSERT(x) assert((x)) 54 #else 55 #define TCN_ASSERT(x) (void)0 56 #endif 57 58 #ifndef APR_MAX_IOVEC_SIZE 59 #define APR_MAX_IOVEC_SIZE 1024 60 #endif 61 62 #define TCN_TIMEUP APR_OS_START_USERERR + 1 63 #define TCN_EAGAIN APR_OS_START_USERERR + 2 64 #define TCN_EINTR APR_OS_START_USERERR + 3 65 #define TCN_EINPROGRESS APR_OS_START_USERERR + 4 66 #define TCN_ETIMEDOUT APR_OS_START_USERERR + 5 67 68 #define TCN_LOG_EMERG 1 69 #define TCN_LOG_ERROR 2 70 #define TCN_LOG_NOTICE 3 71 #define TCN_LOG_WARN 4 72 #define TCN_LOG_INFO 5 73 #define TCN_LOG_DEBUG 6 74 75 #define TCN_ERROR_WRAP(E) \ 76 if (APR_STATUS_IS_TIMEUP(E)) \ 77 (E) = TCN_TIMEUP; \ 78 else if (APR_STATUS_IS_EAGAIN(E)) \ 79 (E) = TCN_EAGAIN; \ 80 else if (APR_STATUS_IS_EINTR(E)) \ 81 (E) = TCN_EINTR; \ 82 else if (APR_STATUS_IS_EINPROGRESS(E)) \ 83 (E) = TCN_EINPROGRESS; \ 84 else if (APR_STATUS_IS_ETIMEDOUT(E)) \ 85 (E) = TCN_ETIMEDOUT; \ 86 else \ 87 (E) = (E) 88 89 #define TCN_CLASS_PATH "org/apache/tomcat/jni/" 90 #define TCN_FINFO_CLASS TCN_CLASS_PATH "FileInfo" 91 #define TCN_AINFO_CLASS TCN_CLASS_PATH "Sockaddr" 92 #define TCN_ERROR_CLASS TCN_CLASS_PATH "Error" 93 #define TCN_PARENT_IDE "TCN_PARENT_ID" 94 95 #define UNREFERENCED(P) (P) = (P) 96 #define UNREFERENCED_STDARGS e = e; o = o 97 #ifdef WIN32 98 #define LLT(X) (X) 99 #else 100 #define LLT(X) ((long)(X)) 101 #endif 102 #define P2J(P) ((jlong)LLT(P)) 103 #define J2P(P, T) ((T)LLT((jlong)P)) 104 /* On stack buffer size */ 105 #define TCN_BUFFER_SZ 8192 106 #define TCN_STDARGS JNIEnv *e, jobject o 107 #define TCN_IMPARGS JNIEnv *e, jobject o, void *sock 108 #define TCN_IMPCALL(X) e, o, X->opaque 109 110 #define TCN_IMPLEMENT_CALL(RT, CL, FN) \ 111 JNIEXPORT RT JNICALL Java_org_apache_tomcat_jni_##CL##_##FN 112 113 #define TCN_IMPLEMENT_METHOD(RT, FN) \ 114 static RT method_##FN 115 116 #define TCN_GETNET_METHOD(FN) method_##FN 117 118 #define TCN_SOCKET_UNKNOWN 0 119 #define TCN_SOCKET_APR 1 120 #define TCN_SOCKET_SSL 2 121 #define TCN_SOCKET_UNIX 3 122 #define TCN_SOCKET_NTPIPE 4 123 124 #define TCN_SOCKET_GET_POOL 0 125 #define TCN_SOCKET_GET_IMPL 1 126 #define TCN_SOCKET_GET_APRS 2 127 #define TCN_SOCKET_GET_TYPE 3 128 129 typedef struct { 130 int type; 131 apr_status_t (*cleanup)(void *); 132 apr_status_t (APR_THREAD_FUNC *close) (apr_socket_t *); 133 apr_status_t (APR_THREAD_FUNC *shutdown) (apr_socket_t *, apr_shutdown_how_e); 134 apr_status_t (APR_THREAD_FUNC *opt_get)(apr_socket_t *, apr_int32_t, apr_int32_t *); 135 apr_status_t (APR_THREAD_FUNC *opt_set)(apr_socket_t *, apr_int32_t, apr_int32_t); 136 apr_status_t (APR_THREAD_FUNC *timeout_get)(apr_socket_t *, apr_interval_time_t *); 137 apr_status_t (APR_THREAD_FUNC *timeout_set)(apr_socket_t *, apr_interval_time_t); 138 apr_status_t (APR_THREAD_FUNC *send) (apr_socket_t *, const char *, apr_size_t *); 139 apr_status_t (APR_THREAD_FUNC *sendv)(apr_socket_t *, const struct iovec *, apr_int32_t, apr_size_t *); 140 apr_status_t (APR_THREAD_FUNC *recv) (apr_socket_t *, char *, apr_size_t *); 141 } tcn_nlayer_t; 142 143 typedef struct tcn_socket_t tcn_socket_t; 144 typedef struct tcn_pfde_t tcn_pfde_t; 145 146 struct tcn_pfde_t { 147 APR_RING_ENTRY(tcn_pfde_t) link; 148 apr_pollfd_t fd; 149 }; 150 151 struct tcn_socket_t { 152 apr_pool_t *pool; 153 apr_pool_t *child; 154 apr_socket_t *sock; 155 void *opaque; 156 char *jsbbuff; 157 char *jrbbuff; 158 tcn_nlayer_t *net; 159 tcn_pfde_t *pe; 160 apr_time_t last_active; 161 apr_interval_time_t timeout; 162 }; 163 164 /* Private helper functions */ 165 void tcn_Throw(JNIEnv *, const char *, ...); 166 void tcn_ThrowException(JNIEnv *, const char *); 167 void tcn_ThrowMemoryException(JNIEnv *, const char *, int, const char *); 168 void tcn_ThrowAPRException(JNIEnv *, apr_status_t); 169 jstring tcn_new_string(JNIEnv *, const char *); 170 jstring tcn_new_stringn(JNIEnv *, const char *, size_t); 171 jbyteArray tcn_new_arrayb(JNIEnv *, const unsigned char *, size_t); 172 jobjectArray tcn_new_arrays(JNIEnv *env, size_t len); 173 char *tcn_get_string(JNIEnv *, jstring); 174 char *tcn_strdup(JNIEnv *, jstring); 175 char *tcn_pstrdup(JNIEnv *, jstring, apr_pool_t *); 176 apr_status_t tcn_load_finfo_class(JNIEnv *, jclass); 177 apr_status_t tcn_load_ainfo_class(JNIEnv *, jclass); 178 unsigned long tcn_get_thread_id(void); 179 180 #define J2S(V) c##V 181 #define J2L(V) p##V 182 183 #define J2T(T) (apr_time_t)((T)) 184 185 #define TCN_BEGIN_MACRO if (1) { 186 #define TCN_END_MACRO } else (void)(0) 187 188 #define TCN_ALLOC_CSTRING(V) \ 189 const char *c##V = V ? (const char *)((*e)->GetStringUTFChars(e, V, 0)) : NULL 190 191 #define TCN_FREE_CSTRING(V) \ 192 if (c##V) (*e)->ReleaseStringUTFChars(e, V, c##V) 193 194 #define TCN_ALLOC_JSTRING(V) \ 195 char *c##V = tcn_get_string(e, (V)) 196 197 #define AJP_TO_JSTRING(V) (*e)->NewStringUTF((e), (V)) 198 199 #define TCN_FREE_JSTRING(V) \ 200 TCN_BEGIN_MACRO \ 201 if (c##V) \ 202 free(c##V); \ 203 TCN_END_MACRO 204 205 #define TCN_CHECK_ALLOCATED(x) \ 206 if (x == NULL) { \ 207 tcn_ThrowMemoryException(e, __FILE__, __LINE__, \ 208 "APR memory allocation failed"); \ 209 goto cleanup; \ 210 } else (void)(0) 211 212 #define TCN_THROW_IF_ERR(x, r) \ 213 TCN_BEGIN_MACRO \ 214 apr_status_t R = (x); \ 215 if (R != APR_SUCCESS) { \ 216 tcn_ThrowAPRException(e, R); \ 217 (r) = 0; \ 218 goto cleanup; \ 219 } \ 220 TCN_END_MACRO 221 222 #define TCN_THROW_OS_ERROR(E) \ 223 tcn_ThrowAPRException((E), apr_get_os_error()) 224 225 #define TCN_LOAD_CLASS(E, C, N, R) \ 226 TCN_BEGIN_MACRO \ 227 jclass _##C = (*(E))->FindClass((E), N); \ 228 if (_##C == NULL) { \ 229 (*(E))->ExceptionClear((E)); \ 230 return R; \ 231 } \ 232 C = (*(E))->NewGlobalRef((E), _##C); \ 233 (*(E))->DeleteLocalRef((E), _##C); \ 234 TCN_END_MACRO 235 236 #define TCN_UNLOAD_CLASS(E, C) \ 237 (*(E))->DeleteGlobalRef((E), (C)) 238 239 #define TCN_IS_NULL(E, O) \ 240 ((*(E))->IsSameObject((E), (O), NULL) == JNI_TRUE) 241 242 #define TCN_GET_METHOD(E, C, M, N, S, R) \ 243 TCN_BEGIN_MACRO \ 244 M = (*(E))->GetMethodID((E), C, N, S); \ 245 if (M == NULL) { \ 246 return R; \ 247 } \ 248 TCN_END_MACRO 249 250 #define TCN_MAX_METHODS 8 251 252 typedef struct { 253 jobject obj; 254 jmethodID mid[TCN_MAX_METHODS]; 255 void *opaque; 256 } tcn_callback_t; 257 258 #define TCN_MIN(a, b) ((a) < (b) ? (a) : (b)) 259 #define TCN_MAX(a, b) ((a) > (b) ? (a) : (b)) 260 261 #ifdef WIN32 262 #define TCN_ALLOC_WSTRING(V) \ 263 jsize wl##V = (*e)->GetStringLength(e, V); \ 264 const jchar *ws##V = V ? (const jchar *)((*e)->GetStringChars(e, V, 0)) : NULL; \ 265 jchar *w##V = NULL 266 267 #define TCN_INIT_WSTRING(V) \ 268 w##V = (jchar *)malloc((wl##V + 1) * sizeof(jchar)); \ 269 wcsncpy(w##V, ws##V, wl##V); \ 270 w##V[wl##V] = 0 271 272 #define TCN_FREE_WSTRING(V) \ 273 if (ws##V) (*e)->ReleaseStringChars(e, V, ws##V); \ 274 if (ws##V) free (w##V) 275 276 #define J2W(V) w##V 277 278 #endif 279 280 #if !APR_HAVE_IPV6 281 #define APR_INET6 APR_INET 282 #endif 283 284 #define GET_S_FAMILY(T, F) \ 285 if (F == 0) T = APR_UNSPEC; \ 286 else if (F == 1) T = APR_INET; \ 287 else if (F == 2) T = APR_INET6; \ 288 else T = F 289 290 #define GET_S_TYPE(T, F) \ 291 if (F == 0) T = SOCK_STREAM; \ 292 else if (F == 1) T = SOCK_DGRAM; \ 293 else T = F 294 295 #define TCN_NO_SOCKET_TIMEOUT -2 296 297 #endif /* TCN_H */ 298