ruby-staci 2.2.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.yardopts +14 -0
- data/COPYING +30 -0
- data/COPYING_old +64 -0
- data/ChangeLog +3826 -0
- data/Makefile +92 -0
- data/NEWS +1194 -0
- data/README.md +66 -0
- data/dist-files +113 -0
- data/docs/bind-array-to-in_cond.md +38 -0
- data/docs/conflicts-local-connections-and-processes.md +98 -0
- data/docs/hanging-after-inactivity.md +63 -0
- data/docs/install-binary-package.md +44 -0
- data/docs/install-full-client.md +111 -0
- data/docs/install-instant-client.md +194 -0
- data/docs/install-on-osx.md +133 -0
- data/docs/ldap-auth-and-function-interposition.md +123 -0
- data/docs/number-type-mapping.md +79 -0
- data/docs/osx-install-dev-tools.png +0 -0
- data/docs/platform-specific-issues.md +164 -0
- data/docs/report-installation-issue.md +50 -0
- data/docs/timeout-parameters.md +94 -0
- data/ext/oci8/.document +18 -0
- data/ext/oci8/MANIFEST +18 -0
- data/ext/oci8/apiwrap.c.tmpl +178 -0
- data/ext/oci8/apiwrap.h.tmpl +61 -0
- data/ext/oci8/apiwrap.rb +96 -0
- data/ext/oci8/apiwrap.yml +1322 -0
- data/ext/oci8/attr.c +57 -0
- data/ext/oci8/bind.c +838 -0
- data/ext/oci8/connection_pool.c +216 -0
- data/ext/oci8/encoding.c +196 -0
- data/ext/oci8/env.c +139 -0
- data/ext/oci8/error.c +385 -0
- data/ext/oci8/extconf.rb +219 -0
- data/ext/oci8/hook_funcs.c +407 -0
- data/ext/oci8/lob.c +1278 -0
- data/ext/oci8/metadata.c +279 -0
- data/ext/oci8/object.c +919 -0
- data/ext/oci8/oci8.c +1058 -0
- data/ext/oci8/oci8.h +556 -0
- data/ext/oci8/oci8lib.c +704 -0
- data/ext/oci8/ocidatetime.c +506 -0
- data/ext/oci8/ocihandle.c +852 -0
- data/ext/oci8/ocinumber.c +1922 -0
- data/ext/oci8/oraconf.rb +1145 -0
- data/ext/oci8/oradate.c +670 -0
- data/ext/oci8/oranumber_util.c +352 -0
- data/ext/oci8/oranumber_util.h +24 -0
- data/ext/oci8/plthook.h +66 -0
- data/ext/oci8/plthook_elf.c +702 -0
- data/ext/oci8/plthook_osx.c +505 -0
- data/ext/oci8/plthook_win32.c +391 -0
- data/ext/oci8/post-config.rb +5 -0
- data/ext/oci8/stmt.c +448 -0
- data/ext/oci8/thread_util.c +81 -0
- data/ext/oci8/thread_util.h +18 -0
- data/ext/oci8/util.c +71 -0
- data/ext/oci8/win32.c +117 -0
- data/lib/.document +1 -0
- data/lib/dbd/STACI.rb +591 -0
- data/lib/oci8/.document +8 -0
- data/lib/oci8/bindtype.rb +333 -0
- data/lib/oci8/check_load_error.rb +146 -0
- data/lib/oci8/compat.rb +117 -0
- data/lib/oci8/connection_pool.rb +179 -0
- data/lib/oci8/cursor.rb +605 -0
- data/lib/oci8/datetime.rb +605 -0
- data/lib/oci8/encoding-init.rb +45 -0
- data/lib/oci8/encoding.yml +537 -0
- data/lib/oci8/metadata.rb +2148 -0
- data/lib/oci8/object.rb +641 -0
- data/lib/oci8/oci8.rb +756 -0
- data/lib/oci8/ocihandle.rb +591 -0
- data/lib/oci8/oracle_version.rb +153 -0
- data/lib/oci8/properties.rb +196 -0
- data/lib/oci8/version.rb +3 -0
- data/lib/ruby-staci.rb +1 -0
- data/lib/staci.rb +190 -0
- data/metaconfig +142 -0
- data/pre-distclean.rb +7 -0
- data/ruby-aci.gemspec +83 -0
- data/setup.rb +1342 -0
- data/test/README.md +37 -0
- data/test/config.rb +201 -0
- data/test/setup_test_object.sql +199 -0
- data/test/setup_test_package.sql +59 -0
- data/test/test_all.rb +56 -0
- data/test/test_appinfo.rb +62 -0
- data/test/test_array_dml.rb +333 -0
- data/test/test_bind_array.rb +70 -0
- data/test/test_bind_boolean.rb +99 -0
- data/test/test_bind_integer.rb +47 -0
- data/test/test_bind_raw.rb +45 -0
- data/test/test_bind_string.rb +105 -0
- data/test/test_bind_time.rb +177 -0
- data/test/test_break.rb +124 -0
- data/test/test_clob.rb +86 -0
- data/test/test_connection_pool.rb +124 -0
- data/test/test_connstr.rb +220 -0
- data/test/test_datetime.rb +585 -0
- data/test/test_dbi.rb +365 -0
- data/test/test_dbi_clob.rb +53 -0
- data/test/test_encoding.rb +103 -0
- data/test/test_error.rb +87 -0
- data/test/test_metadata.rb +2674 -0
- data/test/test_object.rb +546 -0
- data/test/test_oci8.rb +624 -0
- data/test/test_oracle_version.rb +68 -0
- data/test/test_oradate.rb +255 -0
- data/test/test_oranumber.rb +786 -0
- data/test/test_package_type.rb +981 -0
- data/test/test_properties.rb +17 -0
- data/test/test_rowid.rb +32 -0
- metadata +158 -0
@@ -0,0 +1,407 @@
|
|
1
|
+
/* -*- c-file-style: "ruby"; indent-tabs-mode: nil -*- */
|
2
|
+
/*
|
3
|
+
* hook.c
|
4
|
+
*
|
5
|
+
* Copyright (C) 2015-2018 Kubo Takehiro <kubo@jiubao.org>
|
6
|
+
*/
|
7
|
+
#if defined(_WIN32) || defined(__CYGWIN__)
|
8
|
+
#define WINDOWS
|
9
|
+
#include <winsock2.h>
|
10
|
+
#endif
|
11
|
+
#include "oci8.h"
|
12
|
+
#include "plthook.h"
|
13
|
+
#ifdef __CYGWIN__
|
14
|
+
#undef boolean /* boolean defined in oratypes.h coflicts with that in windows.h */
|
15
|
+
#define stricmp strcasecmp
|
16
|
+
#define strnicmp strncasecmp
|
17
|
+
#endif
|
18
|
+
#ifdef WINDOWS
|
19
|
+
#include <windows.h>
|
20
|
+
#include <mstcpip.h>
|
21
|
+
#include <tlhelp32.h>
|
22
|
+
#else
|
23
|
+
#include <unistd.h>
|
24
|
+
#include <sys/socket.h>
|
25
|
+
#include <netinet/in.h>
|
26
|
+
#include <netinet/tcp.h>
|
27
|
+
#include <dlfcn.h>
|
28
|
+
#endif
|
29
|
+
|
30
|
+
#ifdef WINDOWS
|
31
|
+
static CRITICAL_SECTION lock;
|
32
|
+
#define LOCK(lock) EnterCriticalSection(lock)
|
33
|
+
#define UNLOCK(lock) LeaveCriticalSection(lock)
|
34
|
+
typedef int socklen_t;
|
35
|
+
#else
|
36
|
+
static pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
|
37
|
+
#define LOCK(lock) pthread_mutex_lock(lock)
|
38
|
+
#define UNLOCK(lock) pthread_mutex_unlock(lock)
|
39
|
+
#define SOCKET int
|
40
|
+
#define INVALID_SOCKET (-1)
|
41
|
+
#define WSAAPI
|
42
|
+
#endif
|
43
|
+
|
44
|
+
#if defined(__APPLE__) && defined(TCP_KEEPALIVE) /* macOS */
|
45
|
+
#define USE_TCP_KEEPALIVE
|
46
|
+
#define SUPPORT_TCP_KEEPALIVE_TIME
|
47
|
+
#elif defined(__sun) && defined(TCP_KEEPALIVE_THRESHOLD) /* Solaris */
|
48
|
+
#define USE_TCP_KEEPALIVE_THRESHOLD
|
49
|
+
#define SUPPORT_TCP_KEEPALIVE_TIME
|
50
|
+
#elif defined(TCP_KEEPIDLE) /* Linux, etc */
|
51
|
+
#define USE_TCP_KEEPIDLE
|
52
|
+
#define SUPPORT_TCP_KEEPALIVE_TIME
|
53
|
+
#elif defined(WINDOWS)
|
54
|
+
#define SUPPORT_TCP_KEEPALIVE_TIME
|
55
|
+
#endif
|
56
|
+
|
57
|
+
int oci8_cancel_read_at_exit = 0;
|
58
|
+
|
59
|
+
#ifdef SUPPORT_TCP_KEEPALIVE_TIME
|
60
|
+
int oci8_tcp_keepalive_time = 0;
|
61
|
+
static int WSAAPI hook_setsockopt(SOCKET sockfd, int level, int optname, const void *optval, socklen_t optlen);
|
62
|
+
#else
|
63
|
+
int oci8_tcp_keepalive_time = -1;
|
64
|
+
#endif
|
65
|
+
|
66
|
+
static char hook_errmsg[512];
|
67
|
+
|
68
|
+
typedef struct {
|
69
|
+
const char *func_name;
|
70
|
+
void *func_addr;
|
71
|
+
void *old_func_addr;
|
72
|
+
} hook_func_entry_t;
|
73
|
+
|
74
|
+
typedef struct socket_entry {
|
75
|
+
struct socket_entry *next;
|
76
|
+
struct socket_entry *prev;
|
77
|
+
SOCKET sock;
|
78
|
+
} socket_entry_t;
|
79
|
+
|
80
|
+
static socket_entry_t sockets_in_use = {
|
81
|
+
&sockets_in_use, &sockets_in_use, INVALID_SOCKET,
|
82
|
+
};
|
83
|
+
|
84
|
+
static void socket_entry_set(socket_entry_t *entry, SOCKET sock)
|
85
|
+
{
|
86
|
+
LOCK(&lock);
|
87
|
+
entry->next = sockets_in_use.next;
|
88
|
+
entry->prev = &sockets_in_use;
|
89
|
+
sockets_in_use.next->prev = entry;
|
90
|
+
sockets_in_use.next = entry;
|
91
|
+
entry->sock = sock;
|
92
|
+
UNLOCK(&lock);
|
93
|
+
}
|
94
|
+
|
95
|
+
static void socket_entry_clear(socket_entry_t *entry)
|
96
|
+
{
|
97
|
+
LOCK(&lock);
|
98
|
+
entry->next->prev = entry->prev;
|
99
|
+
entry->prev->next = entry->next;
|
100
|
+
UNLOCK(&lock);
|
101
|
+
}
|
102
|
+
|
103
|
+
static int replace_functions(void *addr, const char *file, hook_func_entry_t *functions)
|
104
|
+
{
|
105
|
+
plthook_t *ph;
|
106
|
+
int i;
|
107
|
+
int rv = 0;
|
108
|
+
|
109
|
+
if (plthook_open_by_address(&ph, addr) != 0) {
|
110
|
+
strncpy(hook_errmsg, plthook_error(), sizeof(hook_errmsg) - 1);
|
111
|
+
hook_errmsg[sizeof(hook_errmsg) - 1] = '\0';
|
112
|
+
return -1;
|
113
|
+
}
|
114
|
+
|
115
|
+
/* install hooks */
|
116
|
+
for (i = 0; functions[i].func_name != NULL ; i++) {
|
117
|
+
hook_func_entry_t *function = &functions[i];
|
118
|
+
rv = plthook_replace(ph, function->func_name, function->func_addr, &function->old_func_addr);
|
119
|
+
if (rv != 0) {
|
120
|
+
strncpy(hook_errmsg, plthook_error(), sizeof(hook_errmsg) - 1);
|
121
|
+
hook_errmsg[sizeof(hook_errmsg) - 1] = '\0';
|
122
|
+
while (--i >= 0) {
|
123
|
+
/*restore hooked fuction address */
|
124
|
+
plthook_replace(ph, functions[i].func_name, functions[i].old_func_addr, NULL);
|
125
|
+
}
|
126
|
+
snprintf(hook_errmsg, sizeof(hook_errmsg), "Could not replace function %s in %s", function->func_name, file);
|
127
|
+
break;
|
128
|
+
}
|
129
|
+
}
|
130
|
+
plthook_close(ph);
|
131
|
+
return rv;
|
132
|
+
}
|
133
|
+
|
134
|
+
#ifdef WINDOWS
|
135
|
+
|
136
|
+
#ifndef _MSC_VER
|
137
|
+
/* setsockopt() in ws2_32.dll */
|
138
|
+
#define setsockopt rboci_setsockopt
|
139
|
+
typedef int (WSAAPI *setsockopt_t)(SOCKET, int, int, const void *, int);
|
140
|
+
static setsockopt_t setsockopt;
|
141
|
+
#endif
|
142
|
+
|
143
|
+
/* system-wide keepalive interval */
|
144
|
+
static DWORD keepalive_interval;
|
145
|
+
|
146
|
+
static int locK_is_initialized;
|
147
|
+
|
148
|
+
static int WSAAPI hook_WSARecv(SOCKET s, LPWSABUF lpBuffers, DWORD dwBufferCount, LPDWORD lpNumberOfBytesRecvd, LPDWORD lpFlags, LPWSAOVERLAPPED lpOverlapped, LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine);
|
149
|
+
|
150
|
+
static hook_func_entry_t tcp_functions[] = {
|
151
|
+
{"WSARecv", (void*)hook_WSARecv, NULL},
|
152
|
+
{"setsockopt", (void*)hook_setsockopt, NULL},
|
153
|
+
{NULL, NULL, NULL},
|
154
|
+
};
|
155
|
+
|
156
|
+
/* WSARecv() is used for TCP connections */
|
157
|
+
static int WSAAPI hook_WSARecv(SOCKET s, LPWSABUF lpBuffers, DWORD dwBufferCount, LPDWORD lpNumberOfBytesRecvd, LPDWORD lpFlags, LPWSAOVERLAPPED lpOverlapped, LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine)
|
158
|
+
{
|
159
|
+
socket_entry_t entry;
|
160
|
+
int enable_cancel = oci8_cancel_read_at_exit;
|
161
|
+
int rv;
|
162
|
+
|
163
|
+
if (enable_cancel > 0) {
|
164
|
+
socket_entry_set(&entry, s);
|
165
|
+
}
|
166
|
+
rv = WSARecv(s, lpBuffers, dwBufferCount, lpNumberOfBytesRecvd, lpFlags, lpOverlapped, lpCompletionRoutine);
|
167
|
+
if (enable_cancel > 0) {
|
168
|
+
socket_entry_clear(&entry);
|
169
|
+
}
|
170
|
+
return rv;
|
171
|
+
}
|
172
|
+
|
173
|
+
void oci8_install_hook_functions()
|
174
|
+
{
|
175
|
+
static int hook_functions_installed = 0;
|
176
|
+
HKEY hKey;
|
177
|
+
DWORD type;
|
178
|
+
DWORD data;
|
179
|
+
DWORD cbData = sizeof(data);
|
180
|
+
const char *reg_key = "SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters";
|
181
|
+
HANDLE hSnapshot;
|
182
|
+
MODULEENTRY32 me;
|
183
|
+
BOOL module_found = FALSE;
|
184
|
+
|
185
|
+
if (hook_functions_installed) {
|
186
|
+
return;
|
187
|
+
}
|
188
|
+
|
189
|
+
InitializeCriticalSectionAndSpinCount(&lock, 5000);
|
190
|
+
locK_is_initialized = 1;
|
191
|
+
|
192
|
+
#ifndef _MSC_VER
|
193
|
+
/* Get setsockopt in ws2_32.dll.
|
194
|
+
* setsockopt used by mingw compiler isn't same with that in ws2_32.dll.
|
195
|
+
*/
|
196
|
+
setsockopt = (setsockopt_t)GetProcAddress(GetModuleHandleA("WS2_32.DLL"), "setsockopt");
|
197
|
+
if (setsockopt == NULL){
|
198
|
+
rb_raise(rb_eRuntimeError, "setsockopt isn't found in WS2_32.DLL");
|
199
|
+
}
|
200
|
+
#endif
|
201
|
+
|
202
|
+
/* Get system-wide keepalive interval parameter.
|
203
|
+
* https://technet.microsoft.com/en-us/library/cc957548.aspx
|
204
|
+
*/
|
205
|
+
if (RegOpenKeyExA(HKEY_LOCAL_MACHINE, reg_key, 0, KEY_QUERY_VALUE, &hKey) != 0) {
|
206
|
+
rb_raise(rb_eRuntimeError, "failed to open the registry key HKLM\\%s", reg_key);
|
207
|
+
}
|
208
|
+
keepalive_interval = 1000; /* default value when the following entry isn't found. */
|
209
|
+
if (RegQueryValueEx(hKey, "KeepAliveInterval", NULL, &type, (LPBYTE)&data, &cbData) == 0) {
|
210
|
+
if (type == REG_DWORD) {
|
211
|
+
keepalive_interval = data;
|
212
|
+
}
|
213
|
+
}
|
214
|
+
RegCloseKey(hKey);
|
215
|
+
|
216
|
+
hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, GetCurrentProcessId());
|
217
|
+
me.dwSize = sizeof(me);
|
218
|
+
if (Module32First(hSnapshot, &me)) {
|
219
|
+
do {
|
220
|
+
const char *p = NULL;
|
221
|
+
if (strnicmp(me.szModule, "orantcp", 7) == 0) { // ORACLE_HOME-based client
|
222
|
+
p = me.szModule + 7;
|
223
|
+
} else if (strnicmp(me.szModule, "oraociei", 8) == 0) { // instant client basic
|
224
|
+
p = me.szModule + 8;
|
225
|
+
} else if (strnicmp(me.szModule, "oraociicus", 10) == 0) { // instant client basic lite
|
226
|
+
p = me.szModule + 10;
|
227
|
+
}
|
228
|
+
if (p != NULL && ('1' <= *p && *p <= '9') && ('0' <= *(p + 1) && *(p + 1) <= '9')
|
229
|
+
&& stricmp(p + 2, ".dll") == 0) {
|
230
|
+
if (GetProcAddress((HMODULE)me.modBaseAddr, "nttini") != NULL) {
|
231
|
+
module_found = TRUE;
|
232
|
+
if (replace_functions(me.modBaseAddr, me.szExePath, tcp_functions) != 0) {
|
233
|
+
CloseHandle(hSnapshot);
|
234
|
+
rb_raise(rb_eRuntimeError, "Hook error: %s", hook_errmsg);
|
235
|
+
}
|
236
|
+
}
|
237
|
+
}
|
238
|
+
} while (Module32Next(hSnapshot, &me));
|
239
|
+
}
|
240
|
+
CloseHandle(hSnapshot);
|
241
|
+
if (!module_found) {
|
242
|
+
rb_raise(rb_eRuntimeError, "No DLL is found to hook.");
|
243
|
+
}
|
244
|
+
hook_functions_installed = 1;
|
245
|
+
}
|
246
|
+
|
247
|
+
static void shutdown_socket(socket_entry_t *entry)
|
248
|
+
{
|
249
|
+
/* This is dangerous. But I don't know how to cancel WSARecv().
|
250
|
+
* This technique is usable only at the process termination.
|
251
|
+
* Otherwise, Oracle client library may close sockets used by
|
252
|
+
* others.
|
253
|
+
*/
|
254
|
+
closesocket(entry->sock);
|
255
|
+
}
|
256
|
+
|
257
|
+
#else
|
258
|
+
static ssize_t hook_read(int fd, void *buf, size_t count);
|
259
|
+
|
260
|
+
#ifdef __APPLE__
|
261
|
+
#define SO_EXT "dylib"
|
262
|
+
#else
|
263
|
+
#define SO_EXT "so"
|
264
|
+
#endif
|
265
|
+
|
266
|
+
static hook_func_entry_t functions[] = {
|
267
|
+
{"read", (void*)hook_read, NULL},
|
268
|
+
#ifdef SUPPORT_TCP_KEEPALIVE_TIME
|
269
|
+
{"setsockopt", (void*)hook_setsockopt, NULL},
|
270
|
+
#endif
|
271
|
+
{NULL, NULL, NULL},
|
272
|
+
};
|
273
|
+
|
274
|
+
static ssize_t hook_read(int fd, void *buf, size_t count)
|
275
|
+
{
|
276
|
+
socket_entry_t entry;
|
277
|
+
int enable_cancel = oci8_cancel_read_at_exit;
|
278
|
+
ssize_t rv;
|
279
|
+
|
280
|
+
if (enable_cancel > 0) {
|
281
|
+
socket_entry_set(&entry, fd);
|
282
|
+
}
|
283
|
+
rv = read(fd, buf, count);
|
284
|
+
if (enable_cancel > 0) {
|
285
|
+
socket_entry_clear(&entry);
|
286
|
+
}
|
287
|
+
return rv;
|
288
|
+
}
|
289
|
+
|
290
|
+
static void *ocifunc_addr(void *dlsym_handle, const char **file)
|
291
|
+
{
|
292
|
+
void *addr = dlsym(dlsym_handle, "ACIEnvCreate");
|
293
|
+
Dl_info dli;
|
294
|
+
|
295
|
+
if (addr == NULL) {
|
296
|
+
return NULL;
|
297
|
+
}
|
298
|
+
if (dladdr(addr, &dli) == 0) {
|
299
|
+
return NULL;
|
300
|
+
}
|
301
|
+
if (strstr(dli.dli_fname, "/libclntsh." SO_EXT) == NULL) {
|
302
|
+
return NULL;
|
303
|
+
}
|
304
|
+
*file = dli.dli_fname;
|
305
|
+
return addr;
|
306
|
+
}
|
307
|
+
|
308
|
+
#ifdef __linux__
|
309
|
+
#include <link.h>
|
310
|
+
static void *ocifunc_addr_linux(const char **file)
|
311
|
+
{
|
312
|
+
struct link_map *lm;
|
313
|
+
for (lm = _r_debug.r_map; lm != NULL; lm = lm->l_next) {
|
314
|
+
if (strstr(lm->l_name, "/libclntsh." SO_EXT) != NULL) {
|
315
|
+
*file = lm->l_name;
|
316
|
+
return (void*)lm->l_addr;
|
317
|
+
}
|
318
|
+
}
|
319
|
+
return NULL;
|
320
|
+
}
|
321
|
+
#endif
|
322
|
+
|
323
|
+
void oci8_install_hook_functions(void)
|
324
|
+
{
|
325
|
+
static int hook_functions_installed = 0;
|
326
|
+
void *addr;
|
327
|
+
const char *file;
|
328
|
+
|
329
|
+
if (hook_functions_installed) {
|
330
|
+
return;
|
331
|
+
}
|
332
|
+
addr = ocifunc_addr(RTLD_DEFAULT, &file);
|
333
|
+
if (addr == NULL) {
|
334
|
+
/* OCI symbols may be hooked by LD_PRELOAD. */
|
335
|
+
addr = ocifunc_addr(RTLD_NEXT, &file);
|
336
|
+
}
|
337
|
+
#ifdef __linux__
|
338
|
+
if (addr == NULL) {
|
339
|
+
addr = ocifunc_addr_linux(&file);
|
340
|
+
}
|
341
|
+
#endif
|
342
|
+
if (addr == NULL) {
|
343
|
+
rb_raise(rb_eRuntimeError, "No shared library is found to hook.");
|
344
|
+
}
|
345
|
+
if (replace_functions(addr, file, functions) != 0) {
|
346
|
+
rb_raise(rb_eRuntimeError, "Hook error: %s", hook_errmsg);
|
347
|
+
}
|
348
|
+
hook_functions_installed = 1;
|
349
|
+
}
|
350
|
+
|
351
|
+
static void shutdown_socket(socket_entry_t *entry)
|
352
|
+
{
|
353
|
+
shutdown(entry->sock, SHUT_RDWR);
|
354
|
+
}
|
355
|
+
#endif
|
356
|
+
|
357
|
+
#ifdef SUPPORT_TCP_KEEPALIVE_TIME
|
358
|
+
static int WSAAPI hook_setsockopt(SOCKET sockfd, int level, int optname, const void *optval, socklen_t optlen)
|
359
|
+
{
|
360
|
+
int rv = setsockopt(sockfd, level, optname, optval, optlen);
|
361
|
+
|
362
|
+
if (rv == 0 && level == SOL_SOCKET && optname == SO_KEEPALIVE
|
363
|
+
&& optlen == sizeof(int) && *(const int*)optval != 0) {
|
364
|
+
/* If Oracle client libraries enables keepalive by (ENABLE=BROKEN),
|
365
|
+
* set per-connection keepalive socket options to overwrite
|
366
|
+
* system-wide setting.
|
367
|
+
*/
|
368
|
+
if (oci8_tcp_keepalive_time > 0) {
|
369
|
+
#if defined(USE_TCP_KEEPALIVE) /* macOS */
|
370
|
+
setsockopt(sockfd, IPPROTO_TCP, TCP_KEEPALIVE, &oci8_tcp_keepalive_time, sizeof(int));
|
371
|
+
#elif defined(USE_TCP_KEEPALIVE_THRESHOLD) /* Solaris */
|
372
|
+
unsigned int millisec = oci8_tcp_keepalive_time * 1000;
|
373
|
+
setsockopt(sockfd, IPPROTO_TCP, TCP_KEEPALIVE_THRESHOLD, &millisec, sizeof(millisec));
|
374
|
+
#elif defined(USE_TCP_KEEPIDLE) /* Linux, etc */
|
375
|
+
setsockopt(sockfd, IPPROTO_TCP, TCP_KEEPIDLE, &oci8_tcp_keepalive_time, sizeof(int));
|
376
|
+
#elif defined(WINDOWS)
|
377
|
+
struct tcp_keepalive vals;
|
378
|
+
DWORD dummy;
|
379
|
+
|
380
|
+
vals.onoff = 1;
|
381
|
+
vals.keepalivetime = oci8_tcp_keepalive_time * 1000;
|
382
|
+
vals.keepaliveinterval = keepalive_interval;
|
383
|
+
WSAIoctl(sockfd, SIO_KEEPALIVE_VALS, &vals, sizeof(vals), NULL, 0,
|
384
|
+
&dummy, NULL, NULL);
|
385
|
+
#endif
|
386
|
+
}
|
387
|
+
}
|
388
|
+
return rv;
|
389
|
+
}
|
390
|
+
#endif
|
391
|
+
|
392
|
+
void oci8_shutdown_sockets(void)
|
393
|
+
{
|
394
|
+
socket_entry_t *entry;
|
395
|
+
|
396
|
+
#ifdef WINDOWS
|
397
|
+
if (!locK_is_initialized) {
|
398
|
+
return;
|
399
|
+
}
|
400
|
+
#endif
|
401
|
+
|
402
|
+
LOCK(&lock);
|
403
|
+
for (entry = sockets_in_use.next; entry != &sockets_in_use; entry = entry->next) {
|
404
|
+
shutdown_socket(entry);
|
405
|
+
}
|
406
|
+
UNLOCK(&lock);
|
407
|
+
}
|