Page Menu
Home
Phorge
Search
Configure Global Search
Log In
Files
F4404895
net.c
No One
Temporary
Actions
Download File
Edit File
Delete File
View Transforms
Subscribe
Flag For Later
Award Token
Size
35 KB
Referenced Files
None
Subscribers
None
net.c
View Options
#include
<compat.h>
// IWYU pragma: keep
#include
<stdbool.h>
#include
<stdint.h>
#include
<stdlib.h>
#include
<string.h>
#ifdef _WIN32
#include
<winsock2.h>
#include
<ws2tcpip.h>
#else
#include
<arpa/inet.h>
#endif
#include
"ant.h"
#include
"ptr.h"
#include
"errors.h"
#include
"internal.h"
#include
"gc/roots.h"
#include
"gc/modules.h"
#include
"net/listener.h"
#include
"silver/engine.h"
#include
"modules/buffer.h"
#include
"modules/events.h"
#include
"modules/net.h"
#include
"modules/symbol.h"
typedef
struct
net_server_s
net_server_t
;
typedef
struct
net_socket_s
net_socket_t
;
typedef
struct
net_listen_args_s
net_listen_args_t
;
typedef
struct
net_write_args_s
net_write_args_t
;
struct
net_socket_s
{
ant_t
*
js
;
ant_value_t
obj
;
ant_conn_t
*
conn
;
net_server_t
*
server
;
ant_value_t
encoding
;
struct
net_socket_s
*
next_active
;
struct
net_socket_s
*
next_in_server
;
bool
allow_half_open
;
bool
destroyed
;
bool
had_error
;
};
struct
net_server_s
{
ant_t
*
js
;
ant_value_t
obj
;
ant_listener_t
listener
;
net_socket_t
*
sockets
;
struct
net_server_s
*
next_active
;
char
*
host
;
char
*
path
;
int
port
;
int
backlog
;
int
max_connections
;
bool
listening
;
bool
closing
;
bool
allow_half_open
;
bool
pause_on_connect
;
bool
no_delay
;
bool
keep_alive
;
unsigned
int
keep_alive_initial_delay_secs
;
};
struct
net_listen_args_s
{
const
char
*
host
;
const
char
*
path
;
int
port
;
int
backlog
;
ant_value_t
callback
;
ant_value_t
error
;
};
struct
net_write_args_s
{
const
uint8_t
*
bytes
;
size_t
len
;
ant_value_t
callback
;
ant_value_t
error
;
};
static
ant_value_t
g_net_server_proto
=
0
;
static
ant_value_t
g_net_socket_proto
=
0
;
static
ant_value_t
g_net_server_ctor
=
0
;
static
ant_value_t
g_net_socket_ctor
=
0
;
static
net_server_t
*
g_active_servers
=
NULL
;
static
net_socket_t
*
g_active_sockets
=
NULL
;
static
bool
g_default_auto_select_family
=
true
;
static
double
g_default_auto_select_family_attempt_timeout
=
250.0
;
enum
{
NET_SERVER_NATIVE_TAG
=
0x4e455453u
,
// NETS
NET_SOCKET_NATIVE_TAG
=
0x4e45544bu
,
// NETK
};
static
ant_value_t
net_not_implemented
(
ant_t
*
js
,
const
char
*
what
);
static
net_server_t
*
net_server_data
(
ant_value_t
value
)
{
if
(
!
js_check_native_tag
(
value
,
NET_SERVER_NATIVE_TAG
))
return
NULL
;
return
(
net_server_t
*
)
js_get_native_ptr
(
value
);
}
static
net_socket_t
*
net_socket_data
(
ant_value_t
value
)
{
if
(
!
js_check_native_tag
(
value
,
NET_SOCKET_NATIVE_TAG
))
return
NULL
;
return
(
net_socket_t
*
)
js_get_native_ptr
(
value
);
}
static
void
net_add_active_server
(
net_server_t
*
server
)
{
server
->
next_active
=
g_active_servers
;
g_active_servers
=
server
;
}
static
void
net_remove_active_server
(
net_server_t
*
server
)
{
net_server_t
**
it
=
NULL
;
for
(
it
=
&
g_active_servers
;
*
it
;
it
=
&
(
*
it
)
->
next_active
)
{
if
(
*
it
==
server
)
{
*
it
=
server
->
next_active
;
server
->
next_active
=
NULL
;
return
;
}}
}
static
void
net_add_active_socket
(
net_socket_t
*
socket
)
{
socket
->
next_active
=
g_active_sockets
;
g_active_sockets
=
socket
;
}
static
void
net_remove_active_socket
(
net_socket_t
*
socket
)
{
net_socket_t
**
it
=
NULL
;
for
(
it
=
&
g_active_sockets
;
*
it
;
it
=
&
(
*
it
)
->
next_active
)
{
if
(
*
it
==
socket
)
{
*
it
=
socket
->
next_active
;
socket
->
next_active
=
NULL
;
return
;
}}
}
static
ant_value_t
net_call_value
(
ant_t
*
js
,
ant_value_t
fn
,
ant_value_t
this_val
,
ant_value_t
*
args
,
int
nargs
)
{
ant_value_t
saved_this
=
js
->
this_val
;
ant_value_t
result
=
js_mkundef
();
js
->
this_val
=
this_val
;
if
(
vtype
(
fn
)
==
T_CFUNC
)
result
=
js_as_cfunc
(
fn
)(
js
,
args
,
nargs
);
else
result
=
sv_vm_call
(
js
->
vm
,
js
,
fn
,
this_val
,
args
,
nargs
,
NULL
,
false
);
js
->
this_val
=
saved_this
;
return
result
;
}
static
bool
net_emit
(
ant_t
*
js
,
ant_value_t
target
,
const
char
*
event
,
ant_value_t
*
args
,
int
nargs
)
{
return
eventemitter_emit_args
(
js
,
target
,
event
,
args
,
nargs
);
}
static
bool
net_add_listener
(
ant_t
*
js
,
ant_value_t
target
,
const
char
*
event
,
ant_value_t
listener
,
bool
once
)
{
return
eventemitter_add_listener
(
js
,
target
,
event
,
listener
,
once
);
}
static
net_server_t
*
net_require_server
(
ant_t
*
js
,
ant_value_t
this_val
)
{
net_server_t
*
server
=
net_server_data
(
this_val
);
if
(
!
server
)
{
js
->
thrown_exists
=
true
;
js
->
thrown_value
=
js_mkerr_typed
(
js
,
JS_ERR_TYPE
,
"Invalid net.Server"
);
return
NULL
;
}
return
server
;
}
static
net_socket_t
*
net_require_socket
(
ant_t
*
js
,
ant_value_t
this_val
)
{
net_socket_t
*
socket
=
net_socket_data
(
this_val
);
if
(
!
socket
)
{
js
->
thrown_exists
=
true
;
js
->
thrown_value
=
js_mkerr_typed
(
js
,
JS_ERR_TYPE
,
"Invalid net.Socket"
);
return
NULL
;
}
return
socket
;
}
static
bool
net_parse_write_args
(
ant_t
*
js
,
ant_value_t
*
args
,
int
nargs
,
net_write_args_t
*
out
)
{
ant_value_t
value
=
0
;
if
(
!
out
)
return
false
;
memset
(
out
,
0
,
sizeof
(
*
out
));
out
->
callback
=
js_mkundef
();
out
->
error
=
js_mkundef
();
if
(
nargs
<
1
||
vtype
(
args
[
0
])
==
T_UNDEF
||
vtype
(
args
[
0
])
==
T_NULL
)
return
true
;
value
=
args
[
0
];
if
(
!
buffer_source_get_bytes
(
js
,
value
,
&
out
->
bytes
,
&
out
->
len
))
{
size_t
slen
=
0
;
ant_value_t
str_val
=
js_tostring_val
(
js
,
value
);
const
char
*
str
=
NULL
;
if
(
is_err
(
str_val
))
{
out
->
error
=
str_val
;
return
false
;
}
str
=
js_getstr
(
js
,
str_val
,
&
slen
);
if
(
!
str
)
{
out
->
error
=
js_mkerr_typed
(
js
,
JS_ERR_TYPE
,
"Invalid socket write data"
);
return
false
;
}
out
->
bytes
=
(
const
uint8_t
*
)
str
;
out
->
len
=
slen
;
}
if
(
nargs
>
1
&&
is_callable
(
args
[
1
]))
out
->
callback
=
args
[
1
];
else
if
(
nargs
>
2
&&
is_callable
(
args
[
2
]))
out
->
callback
=
args
[
2
];
return
true
;
}
static
bool
net_parse_listen_args
(
ant_t
*
js
,
ant_value_t
*
args
,
int
nargs
,
net_listen_args_t
*
out
)
{
if
(
!
out
)
return
false
;
memset
(
out
,
0
,
sizeof
(
*
out
));
out
->
host
=
"0.0.0.0"
;
out
->
backlog
=
511
;
out
->
callback
=
js_mkundef
();
out
->
error
=
js_mkundef
();
if
(
nargs
==
0
)
return
true
;
if
(
vtype
(
args
[
0
])
==
T_NUM
)
{
out
->
port
=
(
int
)
js_getnum
(
args
[
0
]);
if
(
nargs
>
1
&&
vtype
(
args
[
1
])
==
T_STR
)
{
size_t
len
=
0
;
out
->
host
=
js_getstr
(
js
,
args
[
1
],
&
len
);
}
if
(
nargs
>
2
&&
vtype
(
args
[
2
])
==
T_NUM
)
out
->
backlog
=
(
int
)
js_getnum
(
args
[
2
]);
if
(
nargs
>
3
&&
is_callable
(
args
[
3
]))
out
->
callback
=
args
[
3
];
else
if
(
nargs
>
2
&&
is_callable
(
args
[
2
]))
out
->
callback
=
args
[
2
];
else
if
(
nargs
>
1
&&
is_callable
(
args
[
1
]))
out
->
callback
=
args
[
1
];
return
true
;
}
if
(
vtype
(
args
[
0
])
==
T_OBJ
)
{
ant_value_t
value
=
js_get
(
js
,
args
[
0
],
"path"
);
if
(
vtype
(
value
)
==
T_STR
)
{
out
->
path
=
js_getstr
(
js
,
value
,
NULL
);
}
value
=
js_get
(
js
,
args
[
0
],
"port"
);
if
(
vtype
(
value
)
==
T_NUM
)
out
->
port
=
(
int
)
js_getnum
(
value
);
value
=
js_get
(
js
,
args
[
0
],
"host"
);
if
(
vtype
(
value
)
==
T_STR
)
{
size_t
len
=
0
;
out
->
host
=
js_getstr
(
js
,
value
,
&
len
);
}
value
=
js_get
(
js
,
args
[
0
],
"backlog"
);
if
(
vtype
(
value
)
==
T_NUM
)
out
->
backlog
=
(
int
)
js_getnum
(
value
);
if
(
nargs
>
1
&&
is_callable
(
args
[
1
]))
out
->
callback
=
args
[
1
];
return
true
;
}
if
(
vtype
(
args
[
0
])
==
T_STR
)
{
out
->
path
=
js_getstr
(
js
,
args
[
0
],
NULL
);
if
(
nargs
>
1
&&
vtype
(
args
[
1
])
==
T_NUM
)
out
->
backlog
=
(
int
)
js_getnum
(
args
[
1
]);
if
(
nargs
>
2
&&
is_callable
(
args
[
2
]))
out
->
callback
=
args
[
2
];
else
if
(
nargs
>
1
&&
is_callable
(
args
[
1
]))
out
->
callback
=
args
[
1
];
return
true
;
}
if
(
is_callable
(
args
[
0
]))
{
out
->
callback
=
args
[
0
];
return
true
;
}
return
true
;
}
static
ant_value_t
net_make_buffer_chunk
(
ant_t
*
js
,
const
char
*
data
,
size_t
len
)
{
ArrayBufferData
*
ab
=
create_array_buffer_data
(
len
);
if
(
!
ab
)
return
js_mkerr_typed
(
js
,
JS_ERR_TYPE
,
"Out of memory"
);
if
(
len
>
0
&&
data
)
memcpy
(
ab
->
data
,
data
,
len
);
return
create_typed_array
(
js
,
TYPED_ARRAY_UINT8
,
ab
,
0
,
len
,
"Buffer"
);
}
static
void
net_socket_sync_state
(
net_socket_t
*
socket
)
{
ant_value_t
obj
=
0
;
const
char
*
ready_state
=
"open"
;
if
(
!
socket
)
return
;
obj
=
socket
->
obj
;
if
(
!
is_object_type
(
obj
))
return
;
if
(
socket
->
destroyed
)
ready_state
=
"closed"
;
js_set
(
socket
->
js
,
obj
,
"destroyed"
,
js_bool
(
socket
->
destroyed
));
js_set
(
socket
->
js
,
obj
,
"pending"
,
js_bool
(
socket
->
conn
==
NULL
&&
!
socket
->
destroyed
));
js_set
(
socket
->
js
,
obj
,
"connecting"
,
js_false
);
js_set
(
socket
->
js
,
obj
,
"readyState"
,
js_mkstr
(
socket
->
js
,
ready_state
,
strlen
(
ready_state
)));
js_set
(
socket
->
js
,
obj
,
"bytesRead"
,
js_mknum
((
double
)(
socket
->
conn
?
ant_conn_bytes_read
(
socket
->
conn
)
:
0
)));
js_set
(
socket
->
js
,
obj
,
"bytesWritten"
,
js_mknum
((
double
)(
socket
->
conn
?
ant_conn_bytes_written
(
socket
->
conn
)
:
0
)));
js_set
(
socket
->
js
,
obj
,
"timeout"
,
js_mknum
((
double
)(
socket
->
conn
?
ant_conn_timeout_ms
(
socket
->
conn
)
:
0
)));
}
static
void
net_server_sync_state
(
net_server_t
*
server
)
{
if
(
!
server
||
!
is_object_type
(
server
->
obj
))
return
;
js_set
(
server
->
js
,
server
->
obj
,
"listening"
,
js_bool
(
server
->
listening
));
js_set
(
server
->
js
,
server
->
obj
,
"maxConnections"
,
js_mknum
((
double
)
server
->
max_connections
));
js_set
(
server
->
js
,
server
->
obj
,
"dropMaxConnection"
,
js_false
);
}
static
int
net_server_socket_count
(
net_server_t
*
server
)
{
int
count
=
0
;
net_socket_t
*
socket
=
NULL
;
for
(
socket
=
server
?
server
->
sockets
:
NULL
;
socket
;
socket
=
socket
->
next_in_server
)
count
++
;
return
count
;
}
static
void
net_server_maybe_finish_close
(
net_server_t
*
server
)
{
if
(
!
server
||
!
server
->
closing
)
return
;
if
(
!
ant_listener_is_closed
(
&
server
->
listener
))
return
;
if
(
server
->
sockets
)
return
;
server
->
closing
=
false
;
server
->
listening
=
false
;
net_server_sync_state
(
server
);
net_emit
(
server
->
js
,
server
->
obj
,
"close"
,
NULL
,
0
);
net_remove_active_server
(
server
);
}
static
void
net_socket_detach
(
net_socket_t
*
socket
)
{
if
(
!
socket
)
return
;
if
(
socket
->
server
)
{
net_socket_t
**
it
=
NULL
;
for
(
it
=
&
socket
->
server
->
sockets
;
*
it
;
it
=
&
(
*
it
)
->
next_in_server
)
{
if
(
*
it
==
socket
)
{
*
it
=
socket
->
next_in_server
;
break
;
}
}
socket
->
next_in_server
=
NULL
;
}
net_remove_active_socket
(
socket
);
if
(
is_object_type
(
socket
->
obj
))
{
js_set_native_ptr
(
socket
->
obj
,
NULL
);
js_set_native_tag
(
socket
->
obj
,
0
);
}
net_server_maybe_finish_close
(
socket
->
server
);
free
(
socket
);
}
static
void
net_socket_emit_error
(
net_socket_t
*
socket
,
const
char
*
message
)
{
ant_value_t
arg
=
js_mkerr_typed
(
socket
->
js
,
JS_ERR_TYPE
,
"%s"
,
message
);
socket
->
had_error
=
true
;
net_emit
(
socket
->
js
,
socket
->
obj
,
"error"
,
&
arg
,
1
);
}
static
net_socket_t
*
net_socket_create
(
ant_t
*
js
,
bool
allow_half_open
)
{
ant_value_t
obj
=
js_mkobj
(
js
);
ant_value_t
proto
=
js_instance_proto_from_new_target
(
js
,
g_net_socket_proto
);
net_socket_t
*
socket
=
calloc
(
1
,
sizeof
(
*
socket
));
if
(
!
socket
)
return
NULL
;
if
(
is_object_type
(
proto
))
js_set_proto_init
(
obj
,
proto
);
socket
->
js
=
js
;
socket
->
obj
=
obj
;
socket
->
encoding
=
js_mkundef
();
socket
->
allow_half_open
=
allow_half_open
;
js_set_native_ptr
(
obj
,
socket
);
js_set_native_tag
(
obj
,
NET_SOCKET_NATIVE_TAG
);
js_set
(
js
,
obj
,
"remoteAddress"
,
js_mkundef
());
js_set
(
js
,
obj
,
"remotePort"
,
js_mkundef
());
js_set
(
js
,
obj
,
"remoteFamily"
,
js_mkundef
());
js_set
(
js
,
obj
,
"localAddress"
,
js_mkundef
());
js_set
(
js
,
obj
,
"localPort"
,
js_mkundef
());
js_set
(
js
,
obj
,
"localFamily"
,
js_mkundef
());
net_socket_sync_state
(
socket
);
return
socket
;
}
static
void
net_socket_attach_conn
(
net_socket_t
*
socket
,
ant_conn_t
*
conn
)
{
if
(
!
socket
||
!
conn
)
return
;
socket
->
conn
=
conn
;
ant_conn_set_user_data
(
conn
,
socket
);
if
(
ant_conn_has_remote_addr
(
conn
))
{
js_set
(
socket
->
js
,
socket
->
obj
,
"remoteAddress"
,
js_mkstr
(
socket
->
js
,
ant_conn_remote_addr
(
conn
),
strlen
(
ant_conn_remote_addr
(
conn
))));
js_set
(
socket
->
js
,
socket
->
obj
,
"remotePort"
,
js_mknum
(
ant_conn_remote_port
(
conn
)));
js_set
(
socket
->
js
,
socket
->
obj
,
"remoteFamily"
,
js_mkstr
(
socket
->
js
,
ant_conn_remote_family
(
conn
),
strlen
(
ant_conn_remote_family
(
conn
))));
}
if
(
ant_conn_has_local_addr
(
conn
))
{
js_set
(
socket
->
js
,
socket
->
obj
,
"localAddress"
,
js_mkstr
(
socket
->
js
,
ant_conn_local_addr
(
conn
),
strlen
(
ant_conn_local_addr
(
conn
))));
js_set
(
socket
->
js
,
socket
->
obj
,
"localPort"
,
js_mknum
(
ant_conn_local_port
(
conn
)));
js_set
(
socket
->
js
,
socket
->
obj
,
"localFamily"
,
js_mkstr
(
socket
->
js
,
ant_conn_local_family
(
conn
),
strlen
(
ant_conn_local_family
(
conn
))));
}
net_socket_sync_state
(
socket
);
}
static
net_server_t
*
net_server_create
(
ant_t
*
js
)
{
ant_value_t
obj
=
js_mkobj
(
js
);
ant_value_t
proto
=
js_instance_proto_from_new_target
(
js
,
g_net_server_proto
);
net_server_t
*
server
=
calloc
(
1
,
sizeof
(
*
server
));
if
(
!
server
)
return
NULL
;
if
(
is_object_type
(
proto
))
js_set_proto_init
(
obj
,
proto
);
server
->
js
=
js
;
server
->
obj
=
obj
;
server
->
host
=
strdup
(
"0.0.0.0"
);
server
->
backlog
=
511
;
if
(
!
server
->
host
)
{
free
(
server
);
return
NULL
;
}
js_set_native_ptr
(
obj
,
server
);
js_set_native_tag
(
obj
,
NET_SERVER_NATIVE_TAG
);
net_server_sync_state
(
server
);
return
server
;
}
static
ant_value_t
net_not_implemented
(
ant_t
*
js
,
const
char
*
what
)
{
return
js_mkerr_typed
(
js
,
JS_ERR_TYPE
,
"%s is not implemented yet"
,
what
);
}
static
ant_value_t
net_isIP
(
ant_t
*
js
,
ant_value_t
*
args
,
int
nargs
)
{
size_t
len
=
0
;
const
char
*
host
=
NULL
;
struct
in_addr
addr4
;
struct
in6_addr
addr6
;
if
(
nargs
<
1
)
return
js_mknum
(
0
);
host
=
js_getstr
(
js
,
args
[
0
],
&
len
);
if
(
!
host
)
return
js_mknum
(
0
);
if
(
inet_pton
(
AF_INET
,
host
,
&
addr4
)
==
1
)
return
js_mknum
(
4
);
if
(
inet_pton
(
AF_INET6
,
host
,
&
addr6
)
==
1
)
return
js_mknum
(
6
);
return
js_mknum
(
0
);
}
static
ant_value_t
net_isIPv4
(
ant_t
*
js
,
ant_value_t
*
args
,
int
nargs
)
{
if
(
js_getnum
(
net_isIP
(
js
,
args
,
nargs
))
==
4.0
)
return
js_true
;
return
js_false
;
}
static
ant_value_t
net_isIPv6
(
ant_t
*
js
,
ant_value_t
*
args
,
int
nargs
)
{
if
(
js_getnum
(
net_isIP
(
js
,
args
,
nargs
))
==
6.0
)
return
js_true
;
return
js_false
;
}
static
void
net_server_apply_options
(
ant_t
*
js
,
net_server_t
*
server
,
ant_value_t
options
)
{
ant_value_t
value
=
0
;
if
(
!
server
||
vtype
(
options
)
!=
T_OBJ
)
return
;
value
=
js_get
(
js
,
options
,
"allowHalfOpen"
);
if
(
vtype
(
value
)
!=
T_UNDEF
)
server
->
allow_half_open
=
js_truthy
(
js
,
value
);
value
=
js_get
(
js
,
options
,
"pauseOnConnect"
);
if
(
vtype
(
value
)
!=
T_UNDEF
)
server
->
pause_on_connect
=
js_truthy
(
js
,
value
);
value
=
js_get
(
js
,
options
,
"noDelay"
);
if
(
vtype
(
value
)
!=
T_UNDEF
)
server
->
no_delay
=
js_truthy
(
js
,
value
);
value
=
js_get
(
js
,
options
,
"keepAlive"
);
if
(
vtype
(
value
)
!=
T_UNDEF
)
server
->
keep_alive
=
js_truthy
(
js
,
value
);
value
=
js_get
(
js
,
options
,
"keepAliveInitialDelay"
);
if
(
vtype
(
value
)
==
T_NUM
&&
js_getnum
(
value
)
>
0
)
server
->
keep_alive_initial_delay_secs
=
(
unsigned
int
)(
js_getnum
(
value
)
/
1000.0
);
value
=
js_get
(
js
,
options
,
"backlog"
);
if
(
vtype
(
value
)
==
T_NUM
&&
js_getnum
(
value
)
>
0
)
server
->
backlog
=
(
int
)
js_getnum
(
value
);
}
static
void
net_socket_on_read
(
ant_conn_t
*
conn
,
ssize_t
nread
,
void
*
user_data
)
{
net_socket_t
*
socket
=
(
net_socket_t
*
)
ant_conn_get_user_data
(
conn
);
const
char
*
buffer
=
NULL
;
ant_value_t
chunk
=
0
;
size_t
total
=
0
;
size_t
offset
=
0
;
if
(
!
socket
||
!
conn
||
nread
<=
0
)
return
;
total
=
ant_conn_buffer_len
(
conn
);
if
((
size_t
)
nread
>
total
)
return
;
offset
=
total
-
(
size_t
)
nread
;
buffer
=
ant_conn_buffer
(
conn
)
+
offset
;
if
(
vtype
(
socket
->
encoding
)
==
T_STR
)
chunk
=
js_mkstr
(
socket
->
js
,
buffer
,
(
size_t
)
nread
);
else
chunk
=
net_make_buffer_chunk
(
socket
->
js
,
buffer
,
(
size_t
)
nread
);
ant_conn_consume
(
conn
,
total
);
net_socket_sync_state
(
socket
);
net_emit
(
socket
->
js
,
socket
->
obj
,
"data"
,
&
chunk
,
1
);
}
static
void
net_socket_on_end
(
ant_conn_t
*
conn
,
void
*
user_data
)
{
net_socket_t
*
socket
=
(
net_socket_t
*
)
ant_conn_get_user_data
(
conn
);
if
(
!
socket
)
return
;
net_emit
(
socket
->
js
,
socket
->
obj
,
"end"
,
NULL
,
0
);
if
(
!
socket
->
allow_half_open
&&
socket
->
conn
)
ant_conn_shutdown
(
socket
->
conn
);
}
static
void
net_socket_on_error
(
ant_conn_t
*
conn
,
int
status
,
void
*
user_data
)
{
net_socket_t
*
socket
=
(
net_socket_t
*
)
ant_conn_get_user_data
(
conn
);
if
(
!
socket
)
return
;
socket
->
had_error
=
true
;
{
ant_value_t
err
=
js_mkerr_typed
(
socket
->
js
,
JS_ERR_TYPE
,
"%s"
,
uv_strerror
(
status
));
net_emit
(
socket
->
js
,
socket
->
obj
,
"error"
,
&
err
,
1
);
}
}
static
void
net_socket_on_timeout
(
ant_conn_t
*
conn
,
void
*
user_data
)
{
net_socket_t
*
socket
=
(
net_socket_t
*
)
ant_conn_get_user_data
(
conn
);
if
(
!
socket
)
return
;
net_emit
(
socket
->
js
,
socket
->
obj
,
"timeout"
,
NULL
,
0
);
}
static
void
net_server_on_conn_close
(
ant_conn_t
*
conn
,
void
*
user_data
)
{
net_socket_t
*
socket
=
(
net_socket_t
*
)
ant_conn_get_user_data
(
conn
);
ant_value_t
arg
=
0
;
if
(
!
socket
)
return
;
arg
=
js_bool
(
socket
->
had_error
);
socket
->
conn
=
NULL
;
socket
->
destroyed
=
true
;
net_socket_sync_state
(
socket
);
net_emit
(
socket
->
js
,
socket
->
obj
,
"close"
,
&
arg
,
1
);
ant_conn_set_user_data
(
conn
,
NULL
);
net_socket_detach
(
socket
);
}
static
void
net_server_on_listener_close
(
ant_listener_t
*
listener
,
void
*
user_data
)
{
net_server_maybe_finish_close
((
net_server_t
*
)
user_data
);
}
static
void
net_server_on_accept
(
ant_listener_t
*
listener
,
ant_conn_t
*
conn
,
void
*
user_data
)
{
net_server_t
*
server
=
(
net_server_t
*
)
user_data
;
net_socket_t
*
socket
=
NULL
;
ant_value_t
arg
=
0
;
if
(
!
server
||
!
conn
)
return
;
if
(
server
->
max_connections
>
0
&&
net_server_socket_count
(
server
)
>=
server
->
max_connections
)
{
ant_conn_close
(
conn
);
return
;
}
socket
=
net_socket_create
(
server
->
js
,
server
->
allow_half_open
);
if
(
!
socket
)
{
ant_conn_close
(
conn
);
return
;
}
socket
->
server
=
server
;
socket
->
next_in_server
=
server
->
sockets
;
server
->
sockets
=
socket
;
net_add_active_socket
(
socket
);
net_socket_attach_conn
(
socket
,
conn
);
if
(
server
->
no_delay
)
ant_conn_set_no_delay
(
conn
,
true
);
if
(
server
->
keep_alive
)
ant_conn_set_keep_alive
(
conn
,
true
,
server
->
keep_alive_initial_delay_secs
);
if
(
server
->
pause_on_connect
)
ant_conn_pause_read
(
conn
);
arg
=
socket
->
obj
;
net_emit
(
server
->
js
,
server
->
obj
,
"connection"
,
&
arg
,
1
);
}
static
bool
net_server_parse_host
(
const
char
*
input
,
const
char
**
out
)
{
if
(
!
input
||
!*
input
)
{
*
out
=
"0.0.0.0"
;
return
true
;
}
*
out
=
input
;
return
true
;
}
static
ant_value_t
js_net_socket_ctor
(
ant_t
*
js
,
ant_value_t
*
args
,
int
nargs
)
{
net_socket_t
*
socket
=
NULL
;
bool
allow_half_open
=
false
;
if
(
nargs
>
0
&&
vtype
(
args
[
0
])
==
T_OBJ
)
{
ant_value_t
value
=
js_get
(
js
,
args
[
0
],
"allowHalfOpen"
);
allow_half_open
=
js_truthy
(
js
,
value
);
}
socket
=
net_socket_create
(
js
,
allow_half_open
);
if
(
!
socket
)
return
js_mkerr_typed
(
js
,
JS_ERR_TYPE
,
"Out of memory"
);
return
socket
->
obj
;
}
static
ant_value_t
js_net_socket_address
(
ant_t
*
js
,
ant_value_t
*
args
,
int
nargs
)
{
net_socket_t
*
socket
=
net_require_socket
(
js
,
js_getthis
(
js
));
ant_value_t
out
=
js_mkobj
(
js
);
if
(
!
socket
)
return
js
->
thrown_value
;
if
(
!
socket
||
!
socket
->
conn
||
!
ant_conn_has_local_addr
(
socket
->
conn
))
return
out
;
js_set
(
js
,
out
,
"address"
,
js_mkstr
(
js
,
ant_conn_local_addr
(
socket
->
conn
),
strlen
(
ant_conn_local_addr
(
socket
->
conn
))));
js_set
(
js
,
out
,
"port"
,
js_mknum
(
ant_conn_local_port
(
socket
->
conn
)));
js_set
(
js
,
out
,
"family"
,
js_mkstr
(
js
,
ant_conn_local_family
(
socket
->
conn
),
strlen
(
ant_conn_local_family
(
socket
->
conn
))));
return
out
;
}
static
ant_value_t
js_net_socket_pause
(
ant_t
*
js
,
ant_value_t
*
args
,
int
nargs
)
{
net_socket_t
*
socket
=
net_require_socket
(
js
,
js_getthis
(
js
));
if
(
!
socket
)
return
js
->
thrown_value
;
if
(
socket
&&
socket
->
conn
)
ant_conn_pause_read
(
socket
->
conn
);
return
js_getthis
(
js
);
}
static
ant_value_t
js_net_socket_resume
(
ant_t
*
js
,
ant_value_t
*
args
,
int
nargs
)
{
net_socket_t
*
socket
=
net_require_socket
(
js
,
js_getthis
(
js
));
if
(
!
socket
)
return
js
->
thrown_value
;
if
(
socket
&&
socket
->
conn
)
ant_conn_resume_read
(
socket
->
conn
);
return
js_getthis
(
js
);
}
static
ant_value_t
js_net_socket_setEncoding
(
ant_t
*
js
,
ant_value_t
*
args
,
int
nargs
)
{
net_socket_t
*
socket
=
net_require_socket
(
js
,
js_getthis
(
js
));
if
(
!
socket
)
return
js
->
thrown_value
;
socket
->
encoding
=
nargs
>
0
&&
vtype
(
args
[
0
])
!=
T_UNDEF
?
js_tostring_val
(
js
,
args
[
0
])
:
js_mkundef
();
return
js_getthis
(
js
);
}
static
ant_value_t
js_net_socket_setTimeout
(
ant_t
*
js
,
ant_value_t
*
args
,
int
nargs
)
{
net_socket_t
*
socket
=
net_require_socket
(
js
,
js_getthis
(
js
));
double
timeout
=
0
;
if
(
!
socket
)
return
js
->
thrown_value
;
if
(
nargs
>
0
&&
vtype
(
args
[
0
])
==
T_NUM
)
timeout
=
js_getnum
(
args
[
0
]);
if
(
socket
->
conn
)
ant_conn_set_timeout_ms
(
socket
->
conn
,
timeout
>
0
?
(
uint64_t
)
timeout
:
0
);
net_socket_sync_state
(
socket
);
if
(
nargs
>
1
&&
is_callable
(
args
[
1
]))
net_add_listener
(
js
,
socket
->
obj
,
"timeout"
,
args
[
1
],
true
);
return
js_getthis
(
js
);
}
static
ant_value_t
js_net_socket_setNoDelay
(
ant_t
*
js
,
ant_value_t
*
args
,
int
nargs
)
{
net_socket_t
*
socket
=
net_require_socket
(
js
,
js_getthis
(
js
));
bool
enable
=
nargs
==
0
||
js_truthy
(
js
,
args
[
0
]);
if
(
!
socket
)
return
js
->
thrown_value
;
if
(
socket
&&
socket
->
conn
)
ant_conn_set_no_delay
(
socket
->
conn
,
enable
);
return
js_getthis
(
js
);
}
static
ant_value_t
js_net_socket_setKeepAlive
(
ant_t
*
js
,
ant_value_t
*
args
,
int
nargs
)
{
net_socket_t
*
socket
=
net_require_socket
(
js
,
js_getthis
(
js
));
bool
enable
=
nargs
>
0
&&
js_truthy
(
js
,
args
[
0
]);
unsigned
int
delay
=
nargs
>
1
&&
vtype
(
args
[
1
])
==
T_NUM
?
(
unsigned
int
)(
js_getnum
(
args
[
1
])
/
1000.0
)
:
0
;
if
(
!
socket
)
return
js
->
thrown_value
;
if
(
socket
&&
socket
->
conn
)
ant_conn_set_keep_alive
(
socket
->
conn
,
enable
,
delay
);
return
js_getthis
(
js
);
}
static
ant_value_t
js_net_socket_ref
(
ant_t
*
js
,
ant_value_t
*
args
,
int
nargs
)
{
net_socket_t
*
socket
=
net_require_socket
(
js
,
js_getthis
(
js
));
if
(
!
socket
)
return
js
->
thrown_value
;
if
(
socket
&&
socket
->
conn
)
ant_conn_ref
(
socket
->
conn
);
return
js_getthis
(
js
);
}
static
ant_value_t
js_net_socket_unref
(
ant_t
*
js
,
ant_value_t
*
args
,
int
nargs
)
{
net_socket_t
*
socket
=
net_require_socket
(
js
,
js_getthis
(
js
));
if
(
!
socket
)
return
js
->
thrown_value
;
if
(
socket
&&
socket
->
conn
)
ant_conn_unref
(
socket
->
conn
);
return
js_getthis
(
js
);
}
static
ant_value_t
js_net_socket_write
(
ant_t
*
js
,
ant_value_t
*
args
,
int
nargs
)
{
net_socket_t
*
socket
=
net_require_socket
(
js
,
js_getthis
(
js
));
net_write_args_t
parsed
;
char
*
copy
=
NULL
;
if
(
!
socket
)
return
js
->
thrown_value
;
if
(
!
socket
->
conn
)
return
js_false
;
if
(
!
net_parse_write_args
(
js
,
args
,
nargs
,
&
parsed
))
return
parsed
.
error
;
if
(
parsed
.
len
==
0
)
return
js_true
;
copy
=
malloc
(
parsed
.
len
);
if
(
!
copy
)
return
js_mkerr_typed
(
js
,
JS_ERR_TYPE
,
"Out of memory"
);
memcpy
(
copy
,
parsed
.
bytes
,
parsed
.
len
);
if
(
ant_conn_write
(
socket
->
conn
,
copy
,
parsed
.
len
,
NULL
,
NULL
)
!=
0
)
return
js_false
;
GC_ROOT_SAVE
(
root_mark
,
js
);
GC_ROOT_PIN
(
js
,
parsed
.
callback
);
net_socket_sync_state
(
socket
);
if
(
is_callable
(
parsed
.
callback
))
net_call_value
(
js
,
parsed
.
callback
,
js_mkundef
(),
NULL
,
0
);
GC_ROOT_RESTORE
(
js
,
root_mark
);
return
js_true
;
}
static
ant_value_t
js_net_socket_end
(
ant_t
*
js
,
ant_value_t
*
args
,
int
nargs
)
{
net_socket_t
*
socket
=
net_require_socket
(
js
,
js_getthis
(
js
));
net_write_args_t
parsed
;
ant_value_t
result
=
js_getthis
(
js
);
if
(
!
socket
)
return
js
->
thrown_value
;
if
(
!
socket
->
conn
)
return
result
;
if
(
!
net_parse_write_args
(
js
,
args
,
nargs
,
&
parsed
))
return
parsed
.
error
;
GC_ROOT_SAVE
(
root_mark
,
js
);
GC_ROOT_PIN
(
js
,
parsed
.
callback
);
if
(
parsed
.
len
>
0
)
{
ant_value_t
write_result
=
js_net_socket_write
(
js
,
args
,
nargs
);
if
(
is_err
(
write_result
))
{
GC_ROOT_RESTORE
(
js
,
root_mark
);
return
write_result
;
}}
ant_conn_shutdown
(
socket
->
conn
);
if
(
is_callable
(
parsed
.
callback
))
net_call_value
(
js
,
parsed
.
callback
,
js_mkundef
(),
NULL
,
0
);
GC_ROOT_RESTORE
(
js
,
root_mark
);
return
result
;
}
static
ant_value_t
js_net_socket_destroy
(
ant_t
*
js
,
ant_value_t
*
args
,
int
nargs
)
{
net_socket_t
*
socket
=
net_require_socket
(
js
,
js_getthis
(
js
));
if
(
!
socket
)
return
js
->
thrown_value
;
if
(
nargs
>
0
&&
vtype
(
args
[
0
])
!=
T_UNDEF
&&
vtype
(
args
[
0
])
!=
T_NULL
)
{
ant_value_t
err
=
args
[
0
];
socket
->
had_error
=
true
;
net_emit
(
js
,
socket
->
obj
,
"error"
,
&
err
,
1
);
}
if
(
socket
->
conn
)
ant_conn_close
(
socket
->
conn
);
return
js_getthis
(
js
);
}
static
ant_value_t
js_net_socket_connect
(
ant_t
*
js
,
ant_value_t
*
args
,
int
nargs
)
{
return
net_not_implemented
(
js
,
"net.Socket.connect"
);
}
static
ant_value_t
js_net_server_ctor
(
ant_t
*
js
,
ant_value_t
*
args
,
int
nargs
)
{
net_server_t
*
server
=
net_server_create
(
js
);
if
(
!
server
)
return
js_mkerr_typed
(
js
,
JS_ERR_TYPE
,
"Out of memory"
);
if
(
nargs
>
0
&&
vtype
(
args
[
0
])
==
T_OBJ
)
net_server_apply_options
(
js
,
server
,
args
[
0
]);
if
(
nargs
>
0
&&
is_callable
(
args
[
0
]))
net_add_listener
(
js
,
server
->
obj
,
"connection"
,
args
[
0
],
false
);
else
if
(
nargs
>
1
&&
is_callable
(
args
[
1
]))
net_add_listener
(
js
,
server
->
obj
,
"connection"
,
args
[
1
],
false
);
return
server
->
obj
;
}
static
ant_value_t
net_server_bind_listener
(
ant_t
*
js
,
net_server_t
*
server
,
const
net_listen_args_t
*
parsed
,
const
ant_listener_callbacks_t
*
callbacks
)
{
uv_loop_t
*
loop
=
uv_default_loop
();
int
rc
=
0
;
if
(
parsed
->
path
)
{
server
->
path
=
strdup
(
parsed
->
path
);
if
(
!
server
->
path
)
return
js_mkerr_typed
(
js
,
JS_ERR_TYPE
,
"Out of memory"
);
rc
=
ant_listener_listen_pipe
(
&
server
->
listener
,
loop
,
server
->
path
,
server
->
backlog
,
0
,
callbacks
,
server
);
}
else
{
const
char
*
host
=
parsed
->
host
;
net_server_parse_host
(
host
,
&
host
);
free
(
server
->
host
);
server
->
host
=
strdup
(
host
?
host
:
"0.0.0.0"
);
if
(
!
server
->
host
)
return
js_mkerr_typed
(
js
,
JS_ERR_TYPE
,
"Out of memory"
);
rc
=
ant_listener_listen_tcp
(
&
server
->
listener
,
loop
,
server
->
host
,
parsed
->
port
,
server
->
backlog
,
0
,
callbacks
,
server
);
}
if
(
rc
!=
0
)
return
js_mkerr_typed
(
js
,
JS_ERR_TYPE
,
"%s"
,
uv_strerror
(
rc
));
return
js_mkundef
();
}
static
ant_value_t
js_net_server_listen
(
ant_t
*
js
,
ant_value_t
*
args
,
int
nargs
)
{
net_server_t
*
server
=
net_require_server
(
js
,
js_getthis
(
js
));
ant_listener_callbacks_t
callbacks
=
{
0
};
net_listen_args_t
parsed
;
if
(
!
server
)
return
js
->
thrown_value
;
if
(
server
->
listening
)
return
js_mkerr_typed
(
js
,
JS_ERR_TYPE
,
"Server is already listening"
);
if
(
!
net_parse_listen_args
(
js
,
args
,
nargs
,
&
parsed
))
return
parsed
.
error
;
free
(
server
->
path
);
server
->
path
=
NULL
;
server
->
port
=
parsed
.
port
;
server
->
backlog
=
parsed
.
backlog
>
0
?
parsed
.
backlog
:
server
->
backlog
;
callbacks
.
on_accept
=
net_server_on_accept
;
callbacks
.
on_read
=
net_socket_on_read
;
callbacks
.
on_end
=
net_socket_on_end
;
callbacks
.
on_error
=
net_socket_on_error
;
callbacks
.
on_timeout
=
net_socket_on_timeout
;
callbacks
.
on_conn_close
=
net_server_on_conn_close
;
callbacks
.
on_listener_close
=
net_server_on_listener_close
;
GC_ROOT_SAVE
(
root_mark
,
js
);
GC_ROOT_PIN
(
js
,
parsed
.
callback
);
ant_value_t
bind_result
=
net_server_bind_listener
(
js
,
server
,
&
parsed
,
&
callbacks
);
if
(
is_err
(
bind_result
))
{
GC_ROOT_RESTORE
(
js
,
root_mark
);
return
bind_result
;
}
server
->
port
=
ant_listener_port
(
&
server
->
listener
);
server
->
listening
=
true
;
server
->
closing
=
false
;
net_server_sync_state
(
server
);
net_add_active_server
(
server
);
if
(
is_callable
(
parsed
.
callback
))
net_call_value
(
js
,
parsed
.
callback
,
js_mkundef
(),
NULL
,
0
);
net_emit
(
js
,
server
->
obj
,
"listening"
,
NULL
,
0
);
GC_ROOT_RESTORE
(
js
,
root_mark
);
return
js_getthis
(
js
);
}
static
ant_value_t
js_net_server_close
(
ant_t
*
js
,
ant_value_t
*
args
,
int
nargs
)
{
net_server_t
*
server
=
net_require_server
(
js
,
js_getthis
(
js
));
if
(
!
server
)
return
js
->
thrown_value
;
if
(
nargs
>
0
&&
is_callable
(
args
[
0
]))
net_add_listener
(
js
,
server
->
obj
,
"close"
,
args
[
0
],
true
);
if
(
!
server
->
listening
&&
!
server
->
closing
)
{
if
(
nargs
>
0
&&
is_callable
(
args
[
0
]))
{
ant_value_t
err
=
js_mkerr_typed
(
js
,
JS_ERR_TYPE
,
"Server is not running"
);
net_call_value
(
js
,
args
[
0
],
js_mkundef
(),
&
err
,
1
);
}
return
js_getthis
(
js
);
}
server
->
closing
=
true
;
ant_listener_stop
(
&
server
->
listener
,
false
);
net_server_maybe_finish_close
(
server
);
return
js_getthis
(
js
);
}
static
ant_value_t
js_net_server_address
(
ant_t
*
js
,
ant_value_t
*
args
,
int
nargs
)
{
net_server_t
*
server
=
net_require_server
(
js
,
js_getthis
(
js
));
ant_value_t
out
=
js_mknull
();
if
(
!
server
)
return
js
->
thrown_value
;
if
(
!
server
||
!
server
->
listening
)
return
out
;
if
(
server
->
path
)
return
js_mkstr
(
js
,
server
->
path
,
strlen
(
server
->
path
));
struct
sockaddr_storage
saddr
;
int
saddr_len
=
sizeof
(
saddr
);
if
(
uv_tcp_getsockname
(
&
server
->
listener
.
handle
.
tcp
,
(
struct
sockaddr
*
)
&
saddr
,
&
saddr_len
)
==
0
)
{
char
addr_str
[
INET6_ADDRSTRLEN
]
=
{
0
};
const
char
*
family
=
"IPv4"
;
int
port
=
server
->
port
;
if
(
saddr
.
ss_family
==
AF_INET
)
{
struct
sockaddr_in
*
sa
=
(
struct
sockaddr_in
*
)
&
saddr
;
inet_ntop
(
AF_INET
,
&
sa
->
sin_addr
,
addr_str
,
sizeof
(
addr_str
));
port
=
ntohs
(
sa
->
sin_port
);
}
else
if
(
saddr
.
ss_family
==
AF_INET6
)
{
struct
sockaddr_in6
*
sa6
=
(
struct
sockaddr_in6
*
)
&
saddr
;
inet_ntop
(
AF_INET6
,
&
sa6
->
sin6_addr
,
addr_str
,
sizeof
(
addr_str
));
port
=
ntohs
(
sa6
->
sin6_port
);
family
=
"IPv6"
;
}
out
=
js_mkobj
(
js
);
js_set
(
js
,
out
,
"port"
,
js_mknum
((
double
)
port
));
js_set
(
js
,
out
,
"family"
,
js_mkstr
(
js
,
family
,
strlen
(
family
)));
js_set
(
js
,
out
,
"address"
,
js_mkstr
(
js
,
addr_str
,
strlen
(
addr_str
)));
return
out
;
}
struct
in6_addr
addr6
;
out
=
js_mkobj
(
js
);
js_set
(
js
,
out
,
"port"
,
js_mknum
(
server
->
port
));
if
(
server
->
host
&&
inet_pton
(
AF_INET6
,
server
->
host
,
&
addr6
)
==
1
)
{
char
normalized
[
INET6_ADDRSTRLEN
];
inet_ntop
(
AF_INET6
,
&
addr6
,
normalized
,
sizeof
(
normalized
));
js_set
(
js
,
out
,
"family"
,
js_mkstr
(
js
,
"IPv6"
,
4
));
js_set
(
js
,
out
,
"address"
,
js_mkstr
(
js
,
normalized
,
strlen
(
normalized
)));
}
else
{
const
char
*
h
=
server
->
host
?
server
->
host
:
"0.0.0.0"
;
js_set
(
js
,
out
,
"family"
,
js_mkstr
(
js
,
"IPv4"
,
4
));
js_set
(
js
,
out
,
"address"
,
js_mkstr
(
js
,
h
,
strlen
(
h
)));
}
return
out
;
}
static
ant_value_t
js_net_server_getConnections
(
ant_t
*
js
,
ant_value_t
*
args
,
int
nargs
)
{
net_server_t
*
server
=
net_require_server
(
js
,
js_getthis
(
js
));
ant_value_t
cb
=
nargs
>
0
?
args
[
0
]
:
js_mkundef
();
ant_value_t
argv
[
2
]
=
{
js_mknull
(),
js_mknum
((
double
)
net_server_socket_count
(
server
))
};
if
(
!
server
)
return
js
->
thrown_value
;
if
(
is_callable
(
cb
))
net_call_value
(
js
,
cb
,
js_mkundef
(),
argv
,
2
);
return
js_getthis
(
js
);
}
static
ant_value_t
js_net_server_ref
(
ant_t
*
js
,
ant_value_t
*
args
,
int
nargs
)
{
net_server_t
*
server
=
net_require_server
(
js
,
js_getthis
(
js
));
if
(
!
server
)
return
js
->
thrown_value
;
if
(
server
)
ant_listener_ref
(
&
server
->
listener
);
return
js_getthis
(
js
);
}
static
ant_value_t
js_net_server_unref
(
ant_t
*
js
,
ant_value_t
*
args
,
int
nargs
)
{
net_server_t
*
server
=
net_require_server
(
js
,
js_getthis
(
js
));
if
(
!
server
)
return
js
->
thrown_value
;
if
(
server
)
ant_listener_unref
(
&
server
->
listener
);
return
js_getthis
(
js
);
}
static
ant_value_t
js_net_createServer
(
ant_t
*
js
,
ant_value_t
*
args
,
int
nargs
)
{
return
js_net_server_ctor
(
js
,
args
,
nargs
);
}
static
ant_value_t
js_net_createConnection
(
ant_t
*
js
,
ant_value_t
*
args
,
int
nargs
)
{
return
net_not_implemented
(
js
,
"net.createConnection"
);
}
static
ant_value_t
js_net_connect
(
ant_t
*
js
,
ant_value_t
*
args
,
int
nargs
)
{
return
js_net_createConnection
(
js
,
args
,
nargs
);
}
static
ant_value_t
js_net_getDefaultAutoSelectFamily
(
ant_t
*
js
,
ant_value_t
*
args
,
int
nargs
)
{
return
js_bool
(
g_default_auto_select_family
);
}
static
ant_value_t
js_net_setDefaultAutoSelectFamily
(
ant_t
*
js
,
ant_value_t
*
args
,
int
nargs
)
{
if
(
nargs
>
0
)
g_default_auto_select_family
=
js_truthy
(
js
,
args
[
0
]);
return
js_mkundef
();
}
static
ant_value_t
js_net_getDefaultAutoSelectFamilyAttemptTimeout
(
ant_t
*
js
,
ant_value_t
*
args
,
int
nargs
)
{
return
js_mknum
(
g_default_auto_select_family_attempt_timeout
);
}
static
ant_value_t
js_net_setDefaultAutoSelectFamilyAttemptTimeout
(
ant_t
*
js
,
ant_value_t
*
args
,
int
nargs
)
{
if
(
nargs
>
0
&&
vtype
(
args
[
0
])
==
T_NUM
)
{
double
value
=
js_getnum
(
args
[
0
]);
if
(
value
>
0
&&
value
<
10
)
value
=
10
;
if
(
value
>
0
)
g_default_auto_select_family_attempt_timeout
=
value
;
}
return
js_mkundef
();
}
static
void
net_init_constructors
(
ant_t
*
js
)
{
ant_value_t
events
=
0
;
ant_value_t
ee_ctor
=
0
;
ant_value_t
ee_proto
=
0
;
if
(
g_net_server_ctor
&&
g_net_socket_ctor
)
return
;
events
=
events_library
(
js
);
ee_ctor
=
js_get
(
js
,
events
,
"EventEmitter"
);
ee_proto
=
js_get
(
js
,
ee_ctor
,
"prototype"
);
g_net_socket_proto
=
js_mkobj
(
js
);
js_set_proto_init
(
g_net_socket_proto
,
ee_proto
);
js_set
(
js
,
g_net_socket_proto
,
"address"
,
js_mkfun
(
js_net_socket_address
));
js_set
(
js
,
g_net_socket_proto
,
"pause"
,
js_mkfun
(
js_net_socket_pause
));
js_set
(
js
,
g_net_socket_proto
,
"resume"
,
js_mkfun
(
js_net_socket_resume
));
js_set
(
js
,
g_net_socket_proto
,
"setEncoding"
,
js_mkfun
(
js_net_socket_setEncoding
));
js_set
(
js
,
g_net_socket_proto
,
"setTimeout"
,
js_mkfun
(
js_net_socket_setTimeout
));
js_set
(
js
,
g_net_socket_proto
,
"setNoDelay"
,
js_mkfun
(
js_net_socket_setNoDelay
));
js_set
(
js
,
g_net_socket_proto
,
"setKeepAlive"
,
js_mkfun
(
js_net_socket_setKeepAlive
));
js_set
(
js
,
g_net_socket_proto
,
"write"
,
js_mkfun
(
js_net_socket_write
));
js_set
(
js
,
g_net_socket_proto
,
"end"
,
js_mkfun
(
js_net_socket_end
));
js_set
(
js
,
g_net_socket_proto
,
"destroy"
,
js_mkfun
(
js_net_socket_destroy
));
js_set
(
js
,
g_net_socket_proto
,
"connect"
,
js_mkfun
(
js_net_socket_connect
));
js_set
(
js
,
g_net_socket_proto
,
"ref"
,
js_mkfun
(
js_net_socket_ref
));
js_set
(
js
,
g_net_socket_proto
,
"unref"
,
js_mkfun
(
js_net_socket_unref
));
js_set_sym
(
js
,
g_net_socket_proto
,
get_toStringTag_sym
(),
js_mkstr
(
js
,
"Socket"
,
6
));
g_net_socket_ctor
=
js_make_ctor
(
js
,
js_net_socket_ctor
,
g_net_socket_proto
,
"Socket"
,
6
);
g_net_server_proto
=
js_mkobj
(
js
);
js_set_proto_init
(
g_net_server_proto
,
ee_proto
);
js_set
(
js
,
g_net_server_proto
,
"listen"
,
js_mkfun
(
js_net_server_listen
));
js_set
(
js
,
g_net_server_proto
,
"close"
,
js_mkfun
(
js_net_server_close
));
js_set
(
js
,
g_net_server_proto
,
"address"
,
js_mkfun
(
js_net_server_address
));
js_set
(
js
,
g_net_server_proto
,
"getConnections"
,
js_mkfun
(
js_net_server_getConnections
));
js_set
(
js
,
g_net_server_proto
,
"ref"
,
js_mkfun
(
js_net_server_ref
));
js_set
(
js
,
g_net_server_proto
,
"unref"
,
js_mkfun
(
js_net_server_unref
));
js_set_sym
(
js
,
g_net_server_proto
,
get_toStringTag_sym
(),
js_mkstr
(
js
,
"Server"
,
6
));
g_net_server_ctor
=
js_make_ctor
(
js
,
js_net_server_ctor
,
g_net_server_proto
,
"Server"
,
6
);
}
ant_value_t
net_library
(
ant_t
*
js
)
{
ant_value_t
lib
=
js_mkobj
(
js
);
net_init_constructors
(
js
);
js_set
(
js
,
lib
,
"Server"
,
g_net_server_ctor
);
js_set
(
js
,
lib
,
"Socket"
,
g_net_socket_ctor
);
js_set
(
js
,
lib
,
"createServer"
,
js_mkfun
(
js_net_createServer
));
js_set
(
js
,
lib
,
"createConnection"
,
js_mkfun
(
js_net_createConnection
));
js_set
(
js
,
lib
,
"connect"
,
js_mkfun
(
js_net_connect
));
js_set
(
js
,
lib
,
"isIP"
,
js_mkfun
(
net_isIP
));
js_set
(
js
,
lib
,
"isIPv4"
,
js_mkfun
(
net_isIPv4
));
js_set
(
js
,
lib
,
"isIPv6"
,
js_mkfun
(
net_isIPv6
));
js_set
(
js
,
lib
,
"getDefaultAutoSelectFamily"
,
js_mkfun
(
js_net_getDefaultAutoSelectFamily
));
js_set
(
js
,
lib
,
"setDefaultAutoSelectFamily"
,
js_mkfun
(
js_net_setDefaultAutoSelectFamily
));
js_set
(
js
,
lib
,
"getDefaultAutoSelectFamilyAttemptTimeout"
,
js_mkfun
(
js_net_getDefaultAutoSelectFamilyAttemptTimeout
));
js_set
(
js
,
lib
,
"setDefaultAutoSelectFamilyAttemptTimeout"
,
js_mkfun
(
js_net_setDefaultAutoSelectFamilyAttemptTimeout
));
js_set
(
js
,
lib
,
"default"
,
lib
);
js_set_sym
(
js
,
lib
,
get_toStringTag_sym
(),
js_mkstr
(
js
,
"net"
,
3
));
return
lib
;
}
void
gc_mark_net
(
ant_t
*
js
,
gc_mark_fn
mark
)
{
net_server_t
*
server
=
NULL
;
net_socket_t
*
socket
=
NULL
;
if
(
g_net_server_proto
)
mark
(
js
,
g_net_server_proto
);
if
(
g_net_socket_proto
)
mark
(
js
,
g_net_socket_proto
);
if
(
g_net_server_ctor
)
mark
(
js
,
g_net_server_ctor
);
if
(
g_net_socket_ctor
)
mark
(
js
,
g_net_socket_ctor
);
for
(
server
=
g_active_servers
;
server
;
server
=
server
->
next_active
)
mark
(
js
,
server
->
obj
);
for
(
socket
=
g_active_sockets
;
socket
;
socket
=
socket
->
next_active
)
{
mark
(
js
,
socket
->
obj
);
if
(
vtype
(
socket
->
encoding
)
!=
T_UNDEF
)
mark
(
js
,
socket
->
encoding
);
}
}
File Metadata
Details
Attached
Mime Type
text/x-c
Expires
Fri, May 1, 5:25 PM (2 d)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
541580
Default Alt Text
net.c (35 KB)
Attached To
Mode
rANT Ant
Attached
Detach File
Event Timeline
Log In to Comment