52
52
#include <netinet/in.h>
53
53
#include <netinet/ip.h>
54
54
#include <arpa/inet.h>
55
+ #include <poll.h>
55
56
#define __USE_XOPEN2K // for addrinfo
56
57
#include <netdb.h>
57
58
@@ -1618,6 +1619,9 @@ static const JSCFunctionListEntry js_std_error_props[] = {
1618
1619
DEF (EPERM ),
1619
1620
DEF (EPIPE ),
1620
1621
DEF (EBADF ),
1622
+ DEF (EAGAIN ),
1623
+ DEF (EINPROGRESS ),
1624
+ DEF (EWOULDBLOCK ),
1621
1625
#undef DEF
1622
1626
};
1623
1627
@@ -2401,7 +2405,7 @@ static int handle_posted_message(JSRuntime *rt, JSContext *ctx,
2401
2405
2402
2406
#if defined(_WIN32 )
2403
2407
2404
- static int js_os_poll (JSContext * ctx )
2408
+ static int js_os_event_poll (JSContext * ctx )
2405
2409
{
2406
2410
JSRuntime * rt = JS_GetRuntime (ctx );
2407
2411
JSThreadState * ts = JS_GetRuntimeOpaque (rt );
@@ -2496,7 +2500,7 @@ static int js_os_poll(JSContext *ctx)
2496
2500
2497
2501
#else
2498
2502
2499
- static int js_os_poll (JSContext * ctx )
2503
+ static int js_os_event_poll (JSContext * ctx )
2500
2504
{
2501
2505
JSRuntime * rt = JS_GetRuntime (ctx );
2502
2506
JSThreadState * ts = JS_GetRuntimeOpaque (rt );
@@ -3410,7 +3414,7 @@ static JSValue js_os_dup2(JSContext *ctx, JSValueConst this_val,
3410
3414
3411
3415
#endif /* !_WIN32 */
3412
3416
3413
- static int JS_toSockaddrStruct (JSContext * ctx , JSValue addr ,
3417
+ static int JS_ToSockaddrStruct (JSContext * ctx , JSValue addr ,
3414
3418
struct sockaddr_in * sockaddr )
3415
3419
{
3416
3420
JSValue val ;
@@ -3438,13 +3442,13 @@ static int JS_toSockaddrStruct(JSContext *ctx, JSValue addr,
3438
3442
val = JS_GetPropertyStr (ctx , addr , "port" );
3439
3443
ret = JS_ToUint32 (ctx , & port , val );
3440
3444
JS_FreeValue (ctx , val );
3441
- if (ret )
3445
+ if (ret )
3442
3446
return -1 ;
3443
3447
sockaddr -> sin_port = htons (port );
3444
3448
return 0 ;
3445
3449
}
3446
3450
3447
- static JSValue js_toSockaddrObj (JSContext * ctx , struct sockaddr_in * sockaddr )
3451
+ static JSValue JS_ToSockaddrObj (JSContext * ctx , struct sockaddr_in * sockaddr )
3448
3452
{
3449
3453
JSValue obj , prop ;
3450
3454
char ip_str [INET_ADDRSTRLEN ];
@@ -3481,7 +3485,10 @@ static JSValue js_os_socket(JSContext *ctx, JSValueConst this_val,
3481
3485
return JS_EXCEPTION ;
3482
3486
if (argc >= 3 && JS_ToInt32 (ctx , & protocol , argv [2 ]))
3483
3487
return JS_EXCEPTION ;
3484
- ret = js_get_errno (socket (domain , type , protocol ));
3488
+ ret = js_get_errno (socket (domain , type & ~SOCK_NONBLOCK , protocol ));
3489
+ if (ret >=0 && (type & SOCK_NONBLOCK )) {
3490
+ fcntl (ret , F_SETFL , fcntl (ret , F_GETFL , 0 ) | O_NONBLOCK );
3491
+ }
3485
3492
return JS_NewInt32 (ctx , ret );
3486
3493
}
3487
3494
@@ -3526,13 +3533,13 @@ static JSValue js_os_getaddrinfo(JSContext *ctx, JSValueConst this_val,
3526
3533
goto fail ;
3527
3534
3528
3535
ret = js_get_errno (getaddrinfo (node , service , NULL , & ai ));
3529
- if (ret )
3536
+ if (ret )
3530
3537
goto fail ;
3531
3538
3532
3539
obj = JS_NewArray (ctx );
3533
3540
for (objLen = 0 , it = ai ; it ; it = it -> ai_next ) {
3534
3541
for (len = 0 ; len < it -> ai_addrlen ; len ++ ) {
3535
- addrObj = js_toSockaddrObj (ctx ,(struct sockaddr_in * )& it -> ai_addr [len ]);
3542
+ addrObj = JS_ToSockaddrObj (ctx ,(struct sockaddr_in * )& it -> ai_addr [len ]);
3536
3543
JS_SetPropertyUint32 (ctx ,obj ,objLen ++ ,addrObj );
3537
3544
}
3538
3545
}
@@ -3554,7 +3561,7 @@ static JSValue js_os_bind(JSContext *ctx, JSValueConst this_val,
3554
3561
3555
3562
if (JS_ToInt32 (ctx , & sockfd , argv [0 ]))
3556
3563
return JS_EXCEPTION ;
3557
- if (JS_toSockaddrStruct (ctx , argv [1 ], & saddr ))
3564
+ if (JS_ToSockaddrStruct (ctx , argv [1 ], & saddr ))
3558
3565
return JS_EXCEPTION ;
3559
3566
ret = js_get_errno (bind (sockfd , (struct sockaddr * )& saddr , sizeof (saddr )));
3560
3567
return JS_NewInt32 (ctx , ret );
@@ -3586,7 +3593,7 @@ static JSValue js_os_accept(JSContext *ctx, JSValueConst this_val,
3586
3593
return JS_EXCEPTION ;
3587
3594
ret = js_get_errno (accept (sockfd , (struct sockaddr * )& client_addr , & addr_len ));
3588
3595
3589
- sockaddr_obj = js_toSockaddrObj (ctx , & client_addr );
3596
+ sockaddr_obj = JS_ToSockaddrObj (ctx , & client_addr );
3590
3597
if (JS_IsException (sockaddr_obj ))
3591
3598
return sockaddr_obj ; // shall we return ?
3592
3599
@@ -3598,6 +3605,7 @@ static JSValue js_os_accept(JSContext *ctx, JSValueConst this_val,
3598
3605
JS_DefinePropertyValueUint32 (ctx , arr , 1 , sockaddr_obj , JS_PROP_C_W_E );
3599
3606
return arr ;
3600
3607
}
3608
+
3601
3609
static JSValue js_os_connect (JSContext * ctx , JSValueConst this_val ,
3602
3610
int argc , JSValueConst * argv )
3603
3611
{
@@ -3608,14 +3616,80 @@ static JSValue js_os_connect(JSContext *ctx, JSValueConst this_val,
3608
3616
if (JS_ToInt32 (ctx , & sockfd , argv [0 ]))
3609
3617
return JS_EXCEPTION ;
3610
3618
3611
- if (JS_toSockaddrStruct (ctx , argv [1 ], & client_addr ) < 0 )
3619
+ if (JS_ToSockaddrStruct (ctx , argv [1 ], & client_addr ) < 0 )
3612
3620
return JS_EXCEPTION ;
3613
3621
3614
3622
ret = js_get_errno (connect (sockfd , (struct sockaddr * )& client_addr , client_len ));
3615
3623
3616
3624
return JS_NewInt32 (ctx , ret );
3617
3625
}
3618
3626
3627
+
3628
+ static JSValue js_os_poll (JSContext * ctx , JSValueConst this_val ,
3629
+ int argc , JSValueConst * argv )
3630
+ {
3631
+ JSValue val , prop ;
3632
+ struct pollfd pfds [32 ] = {}; // XXX: use js_mallocz() ?
3633
+ uint32_t i , nbfd , events ;
3634
+ int ret , timeoutms = -1 ; // infinite timeout by default
3635
+
3636
+ val = JS_GetPropertyStr (ctx , argv [0 ], "length" );
3637
+ if (JS_IsException (val ))
3638
+ return JS_EXCEPTION ;
3639
+ ret = JS_ToUint32 (ctx , & nbfd , val );
3640
+ JS_FreeValue (ctx , val );
3641
+ if (ret )
3642
+ return JS_EXCEPTION ;
3643
+ if (nbfd > sizeof (pfds )/sizeof (* pfds ))
3644
+ return JS_EXCEPTION ;
3645
+
3646
+ for (i = 0 ; i < nbfd ; i ++ ) {
3647
+ val = JS_GetPropertyUint32 (ctx , argv [0 ], i );
3648
+ if (JS_IsException (val )) {
3649
+ return JS_EXCEPTION ;
3650
+ }
3651
+ prop = JS_GetPropertyStr (ctx , val , "fd" );
3652
+ if (JS_IsException (prop )) {
3653
+ JS_FreeValue (ctx , val );
3654
+ return JS_EXCEPTION ;
3655
+ }
3656
+ ret = JS_ToInt32 (ctx , & pfds [i ].fd , prop );
3657
+ JS_FreeValue (ctx , prop );
3658
+ if (ret ) {
3659
+ JS_FreeValue (ctx , val );
3660
+ return JS_EXCEPTION ;
3661
+ }
3662
+ prop = JS_GetPropertyStr (ctx , val , "events" );
3663
+ if (JS_IsException (prop )) {
3664
+ return JS_EXCEPTION ;
3665
+ }
3666
+ ret = JS_ToUint32 (ctx , & events , prop );
3667
+ JS_FreeValue (ctx , prop );
3668
+ if (ret ) {
3669
+ JS_FreeValue (ctx , val );
3670
+ return JS_EXCEPTION ;
3671
+ }
3672
+ pfds [i ].events = events ;
3673
+ JS_FreeValue (ctx , val );
3674
+ }
3675
+
3676
+ if (argc >= 2 && JS_ToInt32 (ctx , & timeoutms , argv [1 ]))
3677
+ return JS_EXCEPTION ;
3678
+
3679
+ if (poll (pfds , nbfd , timeoutms ) <= 0 )
3680
+ return JS_EXCEPTION ;
3681
+
3682
+ val = JS_NewArray (ctx );
3683
+ if (JS_IsException (val ))
3684
+ return val ;
3685
+
3686
+ for (i = 0 ; i < nbfd ; i ++ ) {
3687
+ JS_DefinePropertyValueUint32 (ctx , val , i , JS_NewInt32 (ctx , pfds [i ].revents ), JS_PROP_C_W_E );
3688
+ }
3689
+
3690
+ return val ;
3691
+ }
3692
+
3619
3693
static JSValue js_os_recv_send (JSContext * ctx , JSValueConst this_val ,
3620
3694
int argc , JSValueConst * argv , int magic )
3621
3695
{
@@ -3634,35 +3708,49 @@ static JSValue js_os_recv_send(JSContext *ctx, JSValueConst this_val,
3634
3708
buf = JS_GetArrayBuffer (ctx , & size , argv [1 ]);
3635
3709
if (!buf )
3636
3710
return JS_EXCEPTION ;
3637
- if (JS_ToIndex (ctx , & len , argv [2 ]))
3711
+ if (argc <= 2 )
3712
+ len = size ;
3713
+ else if (JS_ToIndex (ctx , & len , argv [2 ]))
3638
3714
return JS_EXCEPTION ;
3639
3715
if (len > size )
3640
3716
return JS_ThrowRangeError (ctx , "recv/send array buffer overflow" );
3641
- if ((magic == 2 || magic == 3 ) && JS_toSockaddrStruct (ctx , argv [1 ], & saddr ))
3717
+ if ((magic == 2 || magic == 3 ) && JS_ToSockaddrStruct (ctx , argv [1 ], & saddr ))
3642
3718
return JS_EXCEPTION ;
3643
-
3644
3719
if (magic == 0 )
3645
- ret = js_get_errno (send (fd , buf , len , 0 ));
3646
- if (magic == 1 )
3647
3720
ret = js_get_errno (recv (fd , buf , len , 0 ));
3648
- if (magic == 2 )
3649
- ret = js_get_errno (sendto (fd , buf , len , 0 , ( const struct sockaddr * ) & saddr , saddrlen ));
3650
- if (magic == 3 ) { // recvfrom returns recvLen + sockaddrRecvFrom
3721
+ if (magic == 1 )
3722
+ ret = js_get_errno (send (fd , buf , len , 0 ));
3723
+ if (magic == 2 ) { // recvfrom returns recvLen + sockaddrRecvFrom
3651
3724
ret = js_get_errno (recvfrom (fd , buf , len , 0 , (struct sockaddr * )& saddr , & saddrlen ));
3652
- addr = js_toSockaddrObj (ctx , & saddr );
3725
+ addr = JS_ToSockaddrObj (ctx , & saddr );
3653
3726
if (JS_IsException (addr ))
3654
3727
return addr ; // shall we return ?
3655
3728
addr_ret = JS_NewArray (ctx );
3656
3729
if (JS_IsException (addr_ret ))
3657
3730
return addr_ret ;
3658
- JS_DefinePropertyValueUint32 (ctx , addr_ret , 0 , addr , JS_PROP_C_W_E );
3659
- JS_DefinePropertyValueUint32 (ctx , addr_ret , 1 , JS_NewInt64 (ctx , ret ),
3660
- JS_PROP_C_W_E );
3731
+ JS_DefinePropertyValueUint32 (ctx , addr_ret , 0 , JS_NewInt64 (ctx , ret ), JS_PROP_C_W_E );
3732
+ JS_DefinePropertyValueUint32 (ctx , addr_ret , 1 , addr , JS_PROP_C_W_E );
3661
3733
return addr_ret ;
3662
3734
}
3735
+ if (magic == 3 )
3736
+ ret = js_get_errno (sendto (fd , buf , len , 0 , (const struct sockaddr * )& saddr , saddrlen ));
3663
3737
return JS_NewInt64 (ctx , ret );
3664
3738
}
3665
3739
3740
+ static JSValue js_os_shutdown (JSContext * ctx , JSValueConst this_val ,
3741
+ int argc , JSValueConst * argv )
3742
+ {
3743
+ int sockfd , how , ret ;
3744
+
3745
+ if (JS_ToInt32 (ctx , & sockfd , argv [0 ]))
3746
+ return JS_EXCEPTION ;
3747
+ if (JS_ToInt32 (ctx , & how , argv [1 ]))
3748
+ return JS_EXCEPTION ;
3749
+
3750
+ ret = js_get_errno (shutdown (sockfd , how ));
3751
+ return JS_NewInt32 (ctx , ret );
3752
+ }
3753
+
3666
3754
#ifdef USE_WORKER
3667
3755
3668
3756
/* Worker */
@@ -4204,25 +4292,38 @@ static const JSCFunctionListEntry js_os_funcs[] = {
4204
4292
JS_CFUNC_MAGIC_DEF ("setsockopt" , 3 , js_os_get_setsockopt , 1 ),
4205
4293
JS_CFUNC_DEF ("getaddrinfo" , 2 , js_os_getaddrinfo ),
4206
4294
JS_CFUNC_DEF ("bind" , 2 , js_os_bind ),
4295
+ JS_CFUNC_DEF ("poll" , 2 , js_os_poll ),
4207
4296
JS_CFUNC_DEF ("listen" , 1 , js_os_listen ),
4208
4297
JS_CFUNC_DEF ("accept" , 1 , js_os_accept ),
4209
4298
JS_CFUNC_DEF ("connect" , 1 , js_os_connect ),
4210
- JS_CFUNC_MAGIC_DEF ("recv" , 4 , js_os_recv_send , 0 ),
4211
- JS_CFUNC_MAGIC_DEF ("send" , 4 , js_os_recv_send , 1 ),
4299
+ JS_CFUNC_MAGIC_DEF ("recv" , 3 , js_os_recv_send , 0 ),
4300
+ JS_CFUNC_MAGIC_DEF ("send" , 3 , js_os_recv_send , 1 ),
4212
4301
JS_CFUNC_MAGIC_DEF ("recvfrom" , 4 , js_os_recv_send , 2 ),
4213
4302
JS_CFUNC_MAGIC_DEF ("sendto" , 4 , js_os_recv_send , 3 ),
4303
+ JS_CFUNC_DEF ("shutdown" , 2 , js_os_shutdown ),
4214
4304
OS_FLAG (AF_INET ),
4215
4305
OS_FLAG (AF_INET6 ),
4216
4306
OS_FLAG (SOCK_STREAM ),
4217
4307
OS_FLAG (SOCK_DGRAM ),
4218
4308
OS_FLAG (SOCK_RAW ),
4309
+ OS_FLAG (SOCK_NONBLOCK ),
4219
4310
OS_FLAG (SO_REUSEADDR ),
4220
4311
OS_FLAG (SO_RCVBUF ),
4312
+ OS_FLAG (SO_ERROR ),
4313
+ OS_FLAG (SHUT_RD ),
4314
+ OS_FLAG (SHUT_WR ),
4315
+ OS_FLAG (SHUT_RDWR ),
4316
+ OS_FLAG (POLLIN ),
4317
+ OS_FLAG (POLLPRI ),
4318
+ OS_FLAG (POLLOUT ),
4319
+ OS_FLAG (POLLERR ),
4320
+ OS_FLAG (POLLHUP ),
4321
+ OS_FLAG (POLLNVAL ),
4221
4322
};
4222
4323
4223
4324
static int js_os_init (JSContext * ctx , JSModuleDef * m )
4224
4325
{
4225
- os_poll_func = js_os_poll ;
4326
+ os_poll_func = js_os_event_poll ;
4226
4327
4227
4328
#ifdef USE_WORKER
4228
4329
{
0 commit comments