Synchronet now requires the libarchive development package (e.g. libarchive-dev on Debian-based Linux distros, libarchive.org for more info) to build successfully.

...
 
Commits (2)
This diff is collapsed.
......@@ -683,6 +683,7 @@ long sbbs_t::js_execfile(const char *cmd, const char* startup_dir, JSObject* sco
}
js_PrepareToExecute(js_cx, js_glob, path, startup_dir, js_scope);
JS_ExecuteScript(js_cx, js_scope, js_script, &rval);
js_handle_events(js_cx, &js_callback, &terminated);
sys_status &=~ SS_ABORT;
JS_GetProperty(js_cx, js_scope, "exit_code", &rval);
......
......@@ -1998,6 +1998,21 @@ js_getlines(JSContext *cx, uintN argc, jsval *arglist)
return(JS_TRUE);
}
void
js_do_lock_input(JSContext *cx, JSBool lock)
{
sbbs_t* sbbs;
if ((sbbs = (sbbs_t*)JS_GetContextPrivate(cx)) == NULL)
return;
if(lock) {
pthread_mutex_lock(&sbbs->input_thread_mutex);
} else {
pthread_mutex_unlock(&sbbs->input_thread_mutex);
}
}
static JSBool
js_lock_input(JSContext *cx, uintN argc, jsval *arglist)
{
......@@ -2109,6 +2124,136 @@ js_term_updated(JSContext *cx, uintN argc, jsval *arglist)
return JS_TRUE;
}
size_t
js_cx_input_pending(JSContext *cx)
{
sbbs_t* sbbs;
if ((sbbs = (sbbs_t*)JS_GetContextPrivate(cx)) == NULL)
return 0;
return sbbs->keybuf_level() + RingBufFull(&sbbs->inbuf);
}
static JSBool
js_install_event(JSContext *cx, uintN argc, jsval *arglist, BOOL once)
{
jsval *argv=JS_ARGV(cx, arglist);
js_callback_t* cb;
JSObject *obj=JS_THIS_OBJECT(cx, arglist);
JSFunction *ecb;
char operation[16];
enum js_event_type et;
size_t slen;
struct js_event_list *ev;
sbbs_t *sbbs;
if((sbbs=(sbbs_t*)js_GetClassPrivate(cx, JS_THIS_OBJECT(cx, arglist), &js_console_class))==NULL)
return(JS_FALSE);
if (argc != 2) {
JS_ReportError(cx, "console.on() and console.once() require exactly two parameters");
return JS_FALSE;
}
ecb = JS_ValueToFunction(cx, argv[1]);
if (ecb == NULL) {
return JS_FALSE;
}
JSVALUE_TO_STRBUF(cx, argv[0], operation, sizeof(operation), &slen);
HANDLE_PENDING(cx, NULL);
if (strcmp(operation, "read") == 0) {
if (once)
et = JS_EVENT_CONSOLE_INPUT_ONCE;
else
et = JS_EVENT_CONSOLE_INPUT;
}
else {
JS_ReportError(cx, "event parameter must be 'read'");
return JS_FALSE;
}
cb = &sbbs->js_callback;
if (cb == NULL) {
return JS_FALSE;
}
if (!cb->events_supported) {
JS_ReportError(cx, "events not supported");
return JS_FALSE;
}
ev = (struct js_event_list *)malloc(sizeof(*ev));
if (ev == NULL) {
JS_ReportError(cx, "error allocating %lu bytes", sizeof(*ev));
return JS_FALSE;
}
ev->prev = NULL;
ev->next = cb->events;
if (ev->next)
ev->next->prev = ev;
ev->type = et;
ev->cx = obj;
JS_AddObjectRoot(cx, &ev->cx);
ev->cb = ecb;
ev->id = cb->next_eid++;
ev->data.sock = sbbs->client_socket;
cb->events = ev;
JS_SET_RVAL(cx, arglist, INT_TO_JSVAL(ev->id));
return JS_TRUE;
}
static JSBool
js_clear_console_event(JSContext *cx, uintN argc, jsval *arglist, BOOL once)
{
jsval *argv=JS_ARGV(cx, arglist);
enum js_event_type et;
char operation[16];
size_t slen;
if (argc != 2) {
JS_ReportError(cx, "console.clearOn() and console.clearOnce() require exactly two parameters");
return JS_FALSE;
}
JSVALUE_TO_STRBUF(cx, argv[0], operation, sizeof(operation), &slen);
HANDLE_PENDING(cx, NULL);
if (strcmp(operation, "read") == 0) {
if (once)
et = JS_EVENT_CONSOLE_INPUT_ONCE;
else
et = JS_EVENT_CONSOLE_INPUT;
}
else {
JS_SET_RVAL(cx, arglist, JSVAL_VOID);
return JS_TRUE;
}
return js_clear_event(cx, argc, arglist, et);
}
static JSBool
js_once(JSContext *cx, uintN argc, jsval *arglist)
{
return js_install_event(cx, argc, arglist, TRUE);
}
static JSBool
js_clearOnce(JSContext *cx, uintN argc, jsval *arglist)
{
return js_clear_console_event(cx, argc, arglist, TRUE);
}
static JSBool
js_on(JSContext *cx, uintN argc, jsval *arglist)
{
return js_install_event(cx, argc, arglist, FALSE);
}
static JSBool
js_clearOn(JSContext *cx, uintN argc, jsval *arglist)
{
return js_clear_console_event(cx, argc, arglist, TRUE);
}
static jsSyncMethodSpec js_console_functions[] = {
{"inkey", js_inkey, 0, JSTYPE_STRING, JSDOCSTR("[mode=<tt>K_NONE</tt>] [,timeout=<tt>0</tt>]")
,JSDOCSTR("get a single key with optional <i>timeout</i> in milliseconds (defaults to 0, for no wait).<br>"
......@@ -2362,6 +2507,22 @@ static jsSyncMethodSpec js_console_functions[] = {
,JSDOCSTR("scroll all current mouse hot-spots by the specific number of rows")
,31800
},
{"on", js_on, 2, JSTYPE_NUMBER, JSDOCSTR("type, callback")
,JSDOCSTR("calls callback whenever the condition type specifies is possible. Currently, only 'read' is supported for type. Returns an id suitable for use with clearOn")
,31802
},
{"once", js_once, 2, JSTYPE_NUMBER, JSDOCSTR("type, callback")
,JSDOCSTR("calls callback the first time the condition type specifies is possible. Currently, only 'read' is supported for type. Returns an id suitable for use with clearOnce")
,31802
},
{"clearOn", js_clearOn, 2, JSTYPE_VOID, JSDOCSTR("type, id")
,JSDOCSTR("removes a callback installed by on")
,31802
},
{"clearOnce", js_clearOnce, 2, JSTYPE_VOID, JSDOCSTR("type, id")
,JSDOCSTR("removes a callback installed by once")
,31802
},
{0}
};
......
This diff is collapsed.
This diff is collapsed.
......@@ -25,6 +25,7 @@ typedef struct
char peeked_byte;
BOOL peeked;
uint16_t local_port;
js_callback_t *js_cb;
} js_socket_private_t;
#ifdef __cplusplus
......
......@@ -103,8 +103,9 @@ enum {
,SYS_PROP_TEMP_PATH
,SYS_PROP_CMD_SHELL
/* last */
,SYS_PROP_LOCAL_HOSTNAME
/* last */
,SYS_PROP_NAME_SERVERS
};
static JSBool js_system_get(JSContext *cx, JSObject *obj, jsid id, jsval *vp)
......@@ -116,6 +117,10 @@ static JSBool js_system_get(JSContext *cx, JSObject *obj, jsid id, jsval *vp)
JSString* js_str;
ulong val;
jsrefcount rc;
JSObject *robj;
jsval jval;
str_list_t list;
int i;
js_system_private_t* sys;
if((sys = (js_system_private_t*)js_GetClassPrivate(cx,obj,&js_system_class))==NULL)
......@@ -321,6 +326,23 @@ static JSBool js_system_get(JSContext *cx, JSObject *obj, jsid id, jsval *vp)
JS_RESUMEREQUEST(cx, rc);
p=str;
break;
case SYS_PROP_NAME_SERVERS:
rc=JS_SUSPENDREQUEST(cx);
robj = JS_NewArrayObject(cx, 0, NULL);
if (robj == NULL)
return JS_FALSE;
*vp = OBJECT_TO_JSVAL(robj);
list = getNameServerList();
if (list != NULL) {
for (i = 0; list[i]; i++) {
jval = STRING_TO_JSVAL(JS_NewStringCopyZ(cx, list[i]));
if (!JS_SetElement(cx, robj, i, &jval))
break;
}
}
freeNameServerList(list);
JS_RESUMEREQUEST(cx, rc);
break;
}
if(p!=NULL) { /* string property */
......@@ -440,8 +462,9 @@ static jsSyncPropertySpec js_system_properties[] = {
{ "clock_ticks_per_second", SYS_PROP_CLOCK_PER_SEC ,SYSOBJ_FLAGS, 311 },
{ "timer", SYS_PROP_TIMER ,SYSOBJ_FLAGS, 314 },
/* last */
{ "local_host_name", SYS_PROP_LOCAL_HOSTNAME ,SYSOBJ_FLAGS, 311 },
{ "name_servers", SYS_PROP_NAME_SERVERS,SYSOBJ_FLAGS, 31802 },
/* last */
{0}
};
......@@ -515,8 +538,9 @@ static char* sys_prop_desc[] = {
,"number of clock ticks per second"
,"high-resolution timer, in seconds (fractional seconds supported)"
/* INSERT new tabled properties here */
,"private host name that uniquely identifies this system on the local network"
,"array of nameservers in use by the system"
/* INSERT new tabled properties here */
/* Manually created (non-tabled) properties */
,"public host name that uniquely identifies this system on the Internet (usually the same as <i>system.inet_addr</i>)"
......
......@@ -53,6 +53,16 @@
scfg_t scfg;
void js_do_lock_input(JSContext *cx, JSBool lock)
{
return;
}
size_t js_cx_input_pending(JSContext *cx)
{
return 0;
}
void* DLLCALL js_GetClassPrivate(JSContext *cx, JSObject *obj, JSClass* cls)
{
void *ret = JS_GetInstancePrivate(cx, obj, cls, NULL);
......
......@@ -1078,7 +1078,11 @@ long js_exec(const char *fname, const char* buf, char** args)
if (abort) {
result = EXIT_FAILURE;
} else {
cb.keepGoing = FALSE;
cb.events_supported = TRUE;
exec_result = JS_ExecuteScript(js_cx, js_glob, js_script, &rval);
js_handle_events(js_cx, &cb, &terminated);
char *p;
if(buf != NULL) {
JSVALUE_TO_MSTRING(js_cx, rval, p, NULL);
......@@ -1213,6 +1217,7 @@ int main(int argc, char **argv, char** env)
cb.yield_interval=JAVASCRIPT_YIELD_INTERVAL;
cb.gc_interval=JAVASCRIPT_GC_INTERVAL;
cb.auto_terminate=TRUE;
cb.events = NULL;
DESCRIBE_COMPILER(compiler);
......
......@@ -1285,6 +1285,7 @@ JSContext* sbbs_t::js_init(JSRuntime** runtime, JSObject** glob, const char* des
js_callback.yield_interval = startup->js.yield_interval;
js_callback.terminated = &terminated;
js_callback.auto_terminate = TRUE;
js_callback.events_supported = TRUE;
bool success=false;
bool rooted=false;
......@@ -1887,16 +1888,9 @@ void input_thread(void *arg)
while(sbbs->online && sbbs->client_socket!=INVALID_SOCKET
&& node_socket[sbbs->cfg.node_num-1]!=INVALID_SOCKET) {
if(pthread_mutex_lock(&sbbs->input_thread_mutex)!=0)
sbbs->errormsg(WHERE,ERR_LOCK,"input_thread_mutex",0);
#ifdef _WIN32 // No spy sockets
if (!socket_readable(sbbs->client_socket, 1000)) {
if(pthread_mutex_unlock(&sbbs->input_thread_mutex)!=0)
sbbs->errormsg(WHERE,ERR_UNLOCK,"input_thread_mutex",0);
YIELD(); /* This kludge is necessary on some Linux distros */
continue; /* to allow other threads to lock the input_thread_mutex */
}
if (!socket_readable(sbbs->client_socket, 1000))
continue;
#else
#ifdef PREFER_POLL
fds[0].fd = sbbs->client_socket;
......@@ -1910,22 +1904,15 @@ void input_thread(void *arg)
nfds++;
}
if (poll(fds, nfds, 1000) < 1) {
if(pthread_mutex_unlock(&sbbs->input_thread_mutex)!=0)
sbbs->errormsg(WHERE,ERR_UNLOCK,"input_thread_mutex",0);
YIELD(); /* This kludge is necessary on some Linux distros */
continue; /* to allow other threads to lock the input_thread_mutex */
}
if (poll(fds, nfds, 1000) < 1)
continue;
#else
#error Spy sockets without poll() was removed in commit 3971ef4dcc3db19f400a648b6110718e56a64cf3
#endif
#endif
if(sbbs->client_socket==INVALID_SOCKET) {
if(pthread_mutex_unlock(&sbbs->input_thread_mutex)!=0)
sbbs->errormsg(WHERE,ERR_UNLOCK,"input_thread_mutex",0);
if(sbbs->client_socket==INVALID_SOCKET)
break;
}
/* ^ ^
* \______ ______/
......@@ -1949,22 +1936,17 @@ void input_thread(void *arg)
close_socket(uspy_socket[sbbs->cfg.node_num-1]);
lprintf(LOG_NOTICE,"Closing local spy socket: %d",uspy_socket[sbbs->cfg.node_num-1]);
uspy_socket[sbbs->cfg.node_num-1]=INVALID_SOCKET;
if(pthread_mutex_unlock(&sbbs->input_thread_mutex)!=0)
sbbs->errormsg(WHERE,ERR_UNLOCK,"input_thread_mutex",0);
continue;
}
sock=uspy_socket[sbbs->cfg.node_num-1];
}
else {
if(pthread_mutex_unlock(&sbbs->input_thread_mutex)!=0)
sbbs->errormsg(WHERE,ERR_UNLOCK,"input_thread_mutex",0);
continue;
}
#else
#error Spy sockets without poll() was removed in commit 3971ef4dcc3db19f400a648b6110718e56a64cf3
#endif
#endif
rd=RingBufFree(&sbbs->inbuf);
if(rd==0) { // input buffer full
......@@ -1974,16 +1956,16 @@ void input_thread(void *arg)
while((rd=RingBufFree(&sbbs->inbuf))==0 && time(NULL)-start<5) {
YIELD();
}
if(rd==0) { /* input buffer still full */
if(pthread_mutex_unlock(&sbbs->input_thread_mutex)!=0)
sbbs->errormsg(WHERE,ERR_UNLOCK,"input_thread_mutex",0);
if(rd==0) /* input buffer still full */
continue;
}
}
if(rd > (int)sizeof(inbuf))
rd=sizeof(inbuf);
if(pthread_mutex_lock(&sbbs->input_thread_mutex)!=0)
sbbs->errormsg(WHERE,ERR_LOCK,"input_thread_mutex",0);
#ifdef USE_CRYPTLIB
if(sbbs->ssh_mode && sock==sbbs->client_socket) {
int err;
......@@ -2015,6 +1997,9 @@ void input_thread(void *arg)
if(pthread_mutex_unlock(&sbbs->input_thread_mutex)!=0)
sbbs->errormsg(WHERE,ERR_UNLOCK,"input_thread_mutex",0);
if (rd == 0 && !socket_recvdone(sock, 0))
continue;
if(rd == SOCKET_ERROR)
{
#ifdef __unix__
......@@ -2163,10 +2148,8 @@ void passthru_thread(void* arg)
thread_up(FALSE /* setuid */);
while(sbbs->online && sbbs->passthru_socket!=INVALID_SOCKET && !terminate_server) {
if (!socket_readable(sbbs->passthru_socket, 1000)) {
YIELD(); /* This kludge is necessary on some Linux distros */
continue; /* to allow other threads to lock the input_thread_mutex */
}
if (!socket_readable(sbbs->passthru_socket, 1000))
continue;
if(sbbs->passthru_socket==INVALID_SOCKET)
break;
......
......@@ -297,6 +297,82 @@ extern int thread_suid_broken; /* NPTL is no longer broken */
#include "getmail.h"
#include "msg_id.h"
#if defined(JAVASCRIPT)
enum js_event_type {
JS_EVENT_SOCKET_READABLE_ONCE,
JS_EVENT_SOCKET_READABLE,
JS_EVENT_SOCKET_WRITABLE_ONCE,
JS_EVENT_SOCKET_WRITABLE,
JS_EVENT_SOCKET_CONNECT,
JS_EVENT_INTERVAL,
JS_EVENT_TIMEOUT,
JS_EVENT_CONSOLE_INPUT_ONCE,
JS_EVENT_CONSOLE_INPUT
};
struct js_event_interval {
uint64_t last; // The tick the last event should have triggered at
uint64_t period;
};
struct js_event_timeout {
uint64_t end; // Time the timeout expires
};
struct js_event_connect {
SOCKET sv[2];
SOCKET sock;
};
struct js_event_list {
struct js_event_list *prev;
struct js_event_list *next;
JSFunction *cb;
JSObject *cx;
union {
SOCKET sock;
struct js_event_connect connect;
struct js_event_interval interval;
struct js_event_timeout timeout;
} data;
int32 id;
enum js_event_type type;
};
struct js_runq_entry {
JSFunction *func;
JSObject *cx;
struct js_runq_entry *next;
};
struct js_listener_entry {
char *name;
JSFunction *func;
int32 id;
struct js_listener_entry *next;
};
typedef struct js_callback {
struct js_event_list *events;
struct js_runq_entry *rq_head;
struct js_runq_entry *rq_tail;
struct js_listener_entry *listeners;
volatile BOOL* terminated;
struct js_callback *parent_cb;
uint32_t counter;
uint32_t limit;
uint32_t yield_interval;
uint32_t gc_interval;
uint32_t gc_attempts;
uint32_t offline_counter;
int32 next_eid;
BOOL auto_terminate;
BOOL keepGoing;
BOOL bg;
BOOL events_supported;
} js_callback_t;
#endif
/* Synchronet Node Instance class definition */
#if defined(__cplusplus) && defined(JAVASCRIPT)
......@@ -1305,6 +1381,8 @@ extern "C" {
DLLEXPORT void DLLCALL js_EvalOnExit(JSContext*, JSObject*, js_callback_t*);
DLLEXPORT void DLLCALL js_PrepareToExecute(JSContext*, JSObject*, const char *filename, const char* startup_dir, JSObject *);
DLLEXPORT char* DLLCALL js_getstring(JSContext *cx, JSString *str);
DLLEXPORT JSBool js_handle_events(JSContext *cx, js_callback_t *cb, volatile int *terminated);
DLLEXPORT JSBool js_clear_event(JSContext *cx, uintN argc, jsval *arglist, enum js_event_type et);
/* js_system.c */
DLLEXPORT JSObject* DLLCALL js_CreateSystemObject(JSContext* cx, JSObject* parent
......@@ -1379,6 +1457,8 @@ extern "C" {
/* js_console.cpp */
JSObject* js_CreateConsoleObject(JSContext* cx, JSObject* parent);
DLLEXPORT size_t js_cx_input_pending(JSContext *cx);
DLLEXPORT void js_do_lock_input(JSContext *cx, JSBool lock);
/* js_bbs.cpp */
JSObject* js_CreateBbsObject(JSContext* cx, JSObject* parent);
......
......@@ -68,20 +68,6 @@
#define JAVASCRIPT_LOAD_PATH_LIST "load_path_list"
#define JAVASCRIPT_OPTIONS 0x810 // JSOPTION_JIT | JSOPTION_COMPILE_N_GO
struct js_callback;
typedef struct js_callback {
uint32_t counter;
uint32_t limit;
uint32_t yield_interval;
uint32_t gc_interval;
uint32_t gc_attempts;
uint32_t offline_counter;
BOOL auto_terminate;
volatile BOOL* terminated;
BOOL bg;
struct js_callback *parent_cb;
} js_callback_t;
#define JSVAL_NULL_OR_VOID(val) (JSVAL_IS_NULL(val) || JSVAL_IS_VOID(val))
#ifndef MAX
......
......@@ -1147,9 +1147,11 @@ static void js_service_thread(void* arg)
if(service->log_level >= LOG_ERR)
lprintf(LOG_ERR,"%04d !JavaScript FAILED to compile script (%s)",socket,spath);
} else {
service_client.callback.events_supported = TRUE;
js_PrepareToExecute(js_cx, js_glob, spath, /* startup_dir */NULL, js_glob);
JS_SetOperationCallback(js_cx, js_OperationCallback);
JS_ExecuteScript(js_cx, js_glob, js_script, &rval);
js_handle_events(js_cx, &service_client.callback, &terminated);
js_EvalOnExit(js_cx, js_glob, &service_client.callback);
}
JS_RemoveObjectRoot(js_cx, &js_glob);
......@@ -1259,8 +1261,10 @@ static void js_static_service_thread(void* arg)
break;
}
service_client.callback.events_supported = TRUE;
js_PrepareToExecute(js_cx, js_glob, spath, /* startup_dir */NULL, js_glob);
JS_ExecuteScript(js_cx, js_glob, js_script, &rval);
js_handle_events(js_cx, &service_client.callback, &terminated);
js_EvalOnExit(js_cx, js_glob, &service_client.callback);
JS_RemoveObjectRoot(js_cx, &js_glob);
JS_ENDREQUEST(js_cx);
......
......@@ -7157,6 +7157,7 @@ void DLLCALL web_server(void* arg)
session->js_callback.limit=startup->js.time_limit;
session->js_callback.gc_interval=startup->js.gc_interval;
session->js_callback.yield_interval=startup->js.yield_interval;
session->js_callback.events_supported = FALSE;
pthread_mutex_unlock(&session->struct_filled);
session=NULL;
served++;
......
......@@ -733,3 +733,81 @@ DLLEXPORT int xp_inet_pton(int af, const char *src, void *dst)
freeaddrinfo(res);
return 1;
}
#ifdef _WIN32
DLLEXPORT int
socketpair(int domain, int type, int protocol, SOCKET *sv)
{
union xp_sockaddr la = {0};
const int ra = 1;
SOCKET ls;
SOCKET *check;
fd_set rfd;
struct timeval tv;
size_t sa_len;
sv[0] = sv[1] = INVALID_SOCKET;
ls = socket(domain, type, protocol);
if (ls == INVALID_SOCKET)
goto fail;
switch (domain) {
case PF_INET:
if (inet_ptoaddr("127.0.0.1", &la, sizeof(la)) == NULL)
goto fail;
sa_len = sizeof(la.in);
break;
case PF_INET6:
if (inet_ptoaddr("::1", &la, sizeof(la)) == NULL)
goto fail;
sa_len = sizeof(la.in6);
break;
default:
goto fail;
}
inet_setaddrport(&la, 0);
if (setsockopt(ls, SOL_SOCKET, SO_REUSEADDR, (const char *)&ra, sizeof(ra)) == -1)
goto fail;
if (bind(ls, &la.addr, sa_len) == -1)
goto fail;
if (getsockname(ls, &la.addr, &sa_len) == -1)
goto fail;
if (listen(ls, 1) == -1)
goto fail;
sv[0] = socket(la.addr.sa_family, type, protocol);
if (sv[0] == INVALID_SOCKET)
goto fail;
if (connect(sv[0], &la.addr, sa_len) == -1)
goto fail;
sv[1] = accept(ls, NULL, NULL);
if (sv[1] == INVALID_SOCKET)
goto fail;
closesocket(ls);
ls = INVALID_SOCKET;
if (send(sv[1], (const char *)&sv, sizeof(sv), 0) != sizeof(sv))
goto fail;
tv.tv_sec = 0;
tv.tv_usec = 50000;
FD_ZERO(&rfd);
FD_SET(sv[0], &rfd);
if (select(sv[0] + 1, &rfd, NULL, NULL, &tv) != 1)
goto fail;
if (recv(sv[0], (char *)&check, sizeof(check), 0) != sizeof(check))
goto fail;
if (check != sv)
goto fail;
return 0;
fail:
if (ls != INVALID_SOCKET)
closesocket(ls);
if (sv[0] != INVALID_SOCKET)
closesocket(sv[0]);
sv[0] = INVALID_SOCKET;
if (sv[1] != INVALID_SOCKET)
closesocket(sv[1]);
sv[1] = INVALID_SOCKET;
return -1;
}
#endif
......@@ -230,6 +230,7 @@ DLLEXPORT void set_socket_errno(int);
DLLEXPORT int xp_inet_pton(int af, const char *src, void *dst);
#if defined(_WIN32) // mingw and WinXP's WS2_32.DLL don't have inet_pton():
#define inet_pton xp_inet_pton
DLLEXPORT int socketpair(int domain, int type, int protocol, SOCKET *sv);
#endif
/*
......