Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Contribute to GitLab
Sign in
Toggle navigation
N
noVNC
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
rasky
noVNC
Commits
56d9aa81
Commit
56d9aa81
authored
Dec 28, 2010
by
Joel Martin
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
wswrapper: interpose on poll/ppoll also.
poll/ppoll interposer builds but is untested.
parent
64dbc6bb
Changes
1
Show whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
155 additions
and
36 deletions
+155
-36
wswrapper.c
utils/wswrapper.c
+155
-36
No files found.
utils/wswrapper.c
View file @
56d9aa81
...
@@ -13,8 +13,8 @@
...
@@ -13,8 +13,8 @@
* - programs using ppoll or epoll will not work correctly
* - programs using ppoll or epoll will not work correctly
*/
*/
#define DO_DEBUG 1
//
#define DO_DEBUG 1
#define DO_TRACE 1
//
#define DO_TRACE 1
#include <stdio.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdlib.h>
...
@@ -23,6 +23,7 @@
...
@@ -23,6 +23,7 @@
#include <dlfcn.h>
#include <dlfcn.h>
#include <poll.h>
#include <poll.h>
#include <sys/poll.h>
#include <fcntl.h>
#include <fcntl.h>
#include <errno.h>
#include <errno.h>
#include <string.h>
#include <string.h>
...
@@ -49,7 +50,7 @@ _WS_connection *_WS_connections[65536];
...
@@ -49,7 +50,7 @@ _WS_connection *_WS_connections[65536];
* Subtract the `struct timeval' values X and Y, storing the
* Subtract the `struct timeval' values X and Y, storing the
* result in RESULT. If TS is set then RESULT and X are really
* result in RESULT. If TS is set then RESULT and X are really
* type-cast `struct timespec` so scale them appropriately.
* type-cast `struct timespec` so scale them appropriately.
* Return 1 if the difference is negative, otherwise 0.
* Return 1 if the difference is negative
or 0
, otherwise 0.
*/
*/
int
_WS_subtract_time
(
result
,
x
,
y
,
ts
)
int
_WS_subtract_time
(
result
,
x
,
y
,
ts
)
struct
timeval
*
result
,
*
x
,
*
y
;
struct
timeval
*
result
,
*
x
,
*
y
;
...
@@ -72,8 +73,8 @@ int _WS_subtract_time (result, x, y, ts)
...
@@ -72,8 +73,8 @@ int _WS_subtract_time (result, x, y, ts)
result
->
tv_sec
=
x
->
tv_sec
-
y
->
tv_sec
;
result
->
tv_sec
=
x
->
tv_sec
-
y
->
tv_sec
;
result
->
tv_usec
=
x
->
tv_usec
-
(
y
->
tv_usec
*
scale
);
result
->
tv_usec
=
x
->
tv_usec
-
(
y
->
tv_usec
*
scale
);
/* Return 1 if result is negative. */
/* Return 1 if result is negative
or 0
. */
return
x
->
tv_sec
<
y
->
tv_sec
;
return
x
->
tv_sec
<
=
y
->
tv_sec
;
}
}
...
@@ -580,6 +581,17 @@ ssize_t _WS_send(int sendf, int sockfd, const void *buf,
...
@@ -580,6 +581,17 @@ ssize_t _WS_send(int sendf, int sockfd, const void *buf,
return
(
ssize_t
)
retlen
;
return
(
ssize_t
)
retlen
;
}
}
/*
* Interpose select/pselect/poll.
*
* WebSocket descriptors are not ready until we have received a frame start
* ('\x00') and at least 4 bytes of base64 encoded data. In addition we may
* have carry-over data from the last 4 bytes of base64 data in which case the
* WebSockets socket is ready even though there might not be data in the raw
* socket itself.
*/
/* Interpose on select (mode==0) and pselect (mode==1) */
int
_WS_select
(
int
mode
,
int
nfds
,
fd_set
*
readfds
,
int
_WS_select
(
int
mode
,
int
nfds
,
fd_set
*
readfds
,
fd_set
*
writefds
,
fd_set
*
exceptfds
,
fd_set
*
writefds
,
fd_set
*
exceptfds
,
void
*
timeptr
,
const
sigset_t
*
sigmask
)
void
*
timeptr
,
const
sigset_t
*
sigmask
)
...
@@ -588,8 +600,8 @@ int _WS_select(int mode, int nfds, fd_set *readfds,
...
@@ -588,8 +600,8 @@ int _WS_select(int mode, int nfds, fd_set *readfds,
fd_set
carryfds
,
savefds
;
fd_set
carryfds
,
savefds
;
/* Assumes timeptr is two longs whether timeval or timespec */
/* Assumes timeptr is two longs whether timeval or timespec */
struct
timeval
savetv
,
starttv
,
nowtv
,
difftv
;
struct
timeval
savetv
,
starttv
,
nowtv
,
difftv
;
int
carrycnt
=
0
;
int
carrycnt
=
0
,
less
=
0
;
int
ret
,
less
,
i
,
ready
,
fd
;
int
ret
,
i
,
ready
,
fd
;
static
void
*
(
*
func0
)(),
*
(
*
func1
)();
static
void
*
(
*
func0
)(),
*
(
*
func1
)();
if
(
!
func0
)
func0
=
(
void
*
(
*
)())
dlsym
(
RTLD_NEXT
,
"select"
);
if
(
!
func0
)
func0
=
(
void
*
(
*
)())
dlsym
(
RTLD_NEXT
,
"select"
);
if
(
!
func1
)
func1
=
(
void
*
(
*
)())
dlsym
(
RTLD_NEXT
,
"pselect"
);
if
(
!
func1
)
func1
=
(
void
*
(
*
)())
dlsym
(
RTLD_NEXT
,
"pselect"
);
...
@@ -597,15 +609,15 @@ int _WS_select(int mode, int nfds, fd_set *readfds,
...
@@ -597,15 +609,15 @@ int _WS_select(int mode, int nfds, fd_set *readfds,
if
((
_WS_listen_fd
==
-
1
)
||
(
_WS_nfds
==
0
))
{
if
((
_WS_listen_fd
==
-
1
)
||
(
_WS_nfds
==
0
))
{
if
(
mode
==
0
)
{
if
(
mode
==
0
)
{
ret
=
(
int
)
func0
(
nfds
,
readfds
,
writefds
,
exceptfds
,
ret
=
(
int
)
func0
(
nfds
,
readfds
,
writefds
,
exceptfds
,
(
struct
timeval
*
)
timeptr
);
timeptr
);
}
else
if
(
mode
==
1
)
{
}
else
if
(
mode
==
1
)
{
ret
=
(
int
)
func1
(
nfds
,
readfds
,
writefds
,
exceptfds
,
ret
=
(
int
)
func1
(
nfds
,
readfds
,
writefds
,
exceptfds
,
(
struct
timespec
*
)
timeptr
,
sigmask
);
timeptr
,
sigmask
);
}
}
return
ret
;
return
ret
;
}
}
TRACE
(
">> _WS_select(%d, %d, _, _, _, _)
called
\n
"
,
mode
,
nfds
);
TRACE
(
">> _WS_select(%d, %d, _, _, _, _)
\n
"
,
mode
,
nfds
);
memcpy
(
&
savetv
,
timeptr
,
sizeof
(
savetv
));
memcpy
(
&
savetv
,
timeptr
,
sizeof
(
savetv
));
gettimeofday
(
&
starttv
,
NULL
);
gettimeofday
(
&
starttv
,
NULL
);
...
@@ -641,10 +653,10 @@ int _WS_select(int mode, int nfds, fd_set *readfds,
...
@@ -641,10 +653,10 @@ int _WS_select(int mode, int nfds, fd_set *readfds,
((
struct
timeval
*
)
timeptr
)
->
tv_usec
);
((
struct
timeval
*
)
timeptr
)
->
tv_usec
);
if
(
mode
==
0
)
{
if
(
mode
==
0
)
{
ret
=
(
int
)
func0
(
nfds
,
readfds
,
writefds
,
exceptfds
,
ret
=
(
int
)
func0
(
nfds
,
readfds
,
writefds
,
exceptfds
,
(
struct
timeval
*
)
timeptr
);
timeptr
);
}
else
if
(
mode
==
1
)
{
}
else
if
(
mode
==
1
)
{
ret
=
(
int
)
func1
(
nfds
,
readfds
,
writefds
,
exceptfds
,
ret
=
(
int
)
func1
(
nfds
,
readfds
,
writefds
,
exceptfds
,
(
struct
timespec
*
)
timeptr
,
sigmask
);
timeptr
,
sigmask
);
}
}
if
(
!
readfds
)
{
if
(
!
readfds
)
{
break
;
break
;
...
@@ -670,17 +682,16 @@ int _WS_select(int mode, int nfds, fd_set *readfds,
...
@@ -670,17 +682,16 @@ int _WS_select(int mode, int nfds, fd_set *readfds,
}
}
errno
=
0
;
/* errno could be set by _WS_ready */
errno
=
0
;
/* errno could be set by _WS_ready */
if
(
ret
==
0
)
{
/*
/*
* If all the ready readfds were WebSockets, but none of
* If all the ready readfds were WebSockets, but none of
* them were really ready (empty frames) then we select again.
* them were really ready (empty frames) then we select again. But
* first restore original values less passage of time.
*/
*/
if
(
ret
==
0
)
{
/* Restore original values less passage of time */
memcpy
(
readfds
,
&
savefds
,
sizeof
(
savefds
));
memcpy
(
readfds
,
&
savefds
,
sizeof
(
savefds
));
gettimeofday
(
&
nowtv
,
NULL
);
gettimeofday
(
&
nowtv
,
NULL
);
/* Amount of time that has passed */
/* Amount of time that has passed */
_WS_subtract_time
(
&
difftv
,
&
nowtv
,
&
starttv
,
mode
);
_WS_subtract_time
(
&
difftv
,
&
nowtv
,
&
starttv
,
0
);
/* Subtract from original timout */
/* Subtract from original timout */
less
=
_WS_subtract_time
((
struct
timeval
*
)
timeptr
,
less
=
_WS_subtract_time
((
struct
timeval
*
)
timeptr
,
&
savetv
,
&
difftv
,
mode
);
&
savetv
,
&
difftv
,
mode
);
...
@@ -702,20 +713,124 @@ int _WS_select(int mode, int nfds, fd_set *readfds,
...
@@ -702,20 +713,124 @@ int _WS_select(int mode, int nfds, fd_set *readfds,
return
ret
;
return
ret
;
}
}
/*
/* Interpose on poll (mode==0) and ppoll (mode==1) */
* Overload (LD_PRELOAD) standard library network routines
int
_WS_poll
(
int
mode
,
struct
pollfd
*
fds
,
nfds_t
nfds
,
int
timeout
,
struct
timespec
*
ptimeout
,
sigset_t
*
sigmask
)
{
_WS_connection
*
ws
;
int
savetimeout
;
struct
timespec
savets
;
struct
timeval
starttv
,
nowtv
,
difftv
;
struct
pollfd
*
pfd
;
int
carrycnt
=
0
,
less
=
0
;
int
ret
,
i
,
ready
,
fd
;
static
void
*
(
*
func0
)(),
*
(
*
func1
)();
if
(
!
func0
)
func0
=
(
void
*
(
*
)())
dlsym
(
RTLD_NEXT
,
"poll"
);
if
(
!
func1
)
func1
=
(
void
*
(
*
)())
dlsym
(
RTLD_NEXT
,
"ppoll"
);
if
((
_WS_listen_fd
==
-
1
)
||
(
_WS_nfds
==
0
))
{
if
(
mode
==
0
)
{
ret
=
(
int
)
func0
(
fds
,
nfds
,
timeout
);
}
else
if
(
mode
==
1
)
{
ret
=
(
int
)
func1
(
fds
,
nfds
,
ptimeout
,
sigmask
);
}
return
ret
;
}
TRACE
(
">> _WS_poll(%d, %ld, _, _, _, _)
\n
"
,
mode
,
nfds
);
if
(
mode
==
0
)
{
savetimeout
=
timeout
;
}
else
if
(
mode
==
1
)
{
memcpy
(
&
savets
,
ptimeout
,
sizeof
(
savets
));
}
gettimeofday
(
&
starttv
,
NULL
);
do
{
TRACE
(
" _WS_poll(%d, %ld, _, _, _, _) tv/ts: %ld:%ld
\n
"
,
mode
,
nfds
,
ptimeout
->
tv_sec
,
ptimeout
->
tv_nsec
);
if
(
mode
==
0
)
{
ret
=
(
int
)
func0
(
fds
,
nfds
,
timeout
);
}
else
if
(
mode
==
1
)
{
ret
=
(
int
)
func1
(
fds
,
nfds
,
ptimeout
,
sigmask
);
}
if
(
ret
<=
0
)
{
break
;
}
for
(
i
=
0
;
i
<
nfds
;
i
++
)
{
pfd
=
&
fds
[
i
];
if
(
!
(
pfd
->
events
&
POLLIN
))
{
continue
;
}
ws
=
_WS_connections
[
pfd
->
fd
];
if
(
!
ws
)
{
continue
;
}
if
(
ws
->
rcarry_cnt
)
{
if
(
!
(
pfd
->
revents
&
POLLIN
))
{
pfd
->
revents
|=
POLLIN
;
ret
++
;
}
}
else
if
(
pfd
->
revents
&
POLLIN
)
{
ready
=
_WS_ready
(
pfd
->
fd
,
1
);
if
(
ready
==
0
)
{
/* 0 means EOF which is also a ready condition */
DEBUG
(
"_WS_poll: detected %d is closed
\n
"
,
fd
);
}
else
if
(
ready
<
0
)
{
DEBUG
(
"_WS_poll: not enough to decode
\n
"
,
fd
);
pfd
->
revents
-=
POLLIN
;
ret
--
;
}
}
}
errno
=
0
;
/* errno could be set by _WS_ready */
if
(
ret
==
0
)
{
/*
* If all the ready readfds were WebSockets, but none of
* them were really ready (empty frames) then we select again. But
* first restore original values less passage of time.
*/
*/
gettimeofday
(
&
nowtv
,
NULL
);
/* Amount of time that has passed */
_WS_subtract_time
(
&
difftv
,
&
nowtv
,
&
starttv
,
0
);
if
(
mode
==
0
)
{
if
(
timeout
<
0
)
{
/* Negative timeout means infinite */
continue
;
}
timeout
-=
difftv
.
tv_sec
*
1000
+
difftv
.
tv_usec
/
1000
;
if
(
timeout
<=
0
)
{
less
=
1
;
}
}
else
if
(
mode
==
1
)
{
/* Subtract from original timout */
less
=
_WS_subtract_time
((
struct
timeval
*
)
ptimeout
,
(
struct
timeval
*
)
&
savets
,
&
difftv
,
1
);
}
if
(
less
)
{
/* Timer has expired */
TRACE
(
" _WS_poll expired timer
\n
"
,
mode
,
nfds
);
break
;
}
}
}
while
(
ret
==
0
);
/*
/* Restore original time value for pselect glibc does */
int socket(int domain, int type, int protocol)
if
(
mode
==
1
)
{
{
memcpy
(
ptimeout
,
&
savets
,
sizeof
(
savets
));
static void * (*func)();
}
if (!func) func = (void *(*)()) dlsym(RTLD_NEXT, "socket");
DEBUG("socket(_, %d, _) called\n", type);
return (int) func(domain, type, protocol);
TRACE
(
"<< _WS_poll(%d, %ld, _, _, _, _) ret %d, errno %d
\n
"
,
mode
,
nfds
,
ret
,
errno
);
return
ret
;
}
}
*/
/*
* Overload (LD_PRELOAD) standard library network routines
*/
int
bind
(
int
sockfd
,
const
struct
sockaddr
*
addr
,
socklen_t
addrlen
)
int
bind
(
int
sockfd
,
const
struct
sockaddr
*
addr
,
socklen_t
addrlen
)
{
{
...
@@ -724,7 +839,7 @@ int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen)
...
@@ -724,7 +839,7 @@ int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen)
char
*
WSWRAP_PORT
,
*
end
;
char
*
WSWRAP_PORT
,
*
end
;
int
ret
,
envport
,
bindport
=
htons
(
addr_in
->
sin_port
);
int
ret
,
envport
,
bindport
=
htons
(
addr_in
->
sin_port
);
if
(
!
func
)
func
=
(
void
*
(
*
)())
dlsym
(
RTLD_NEXT
,
"bind"
);
if
(
!
func
)
func
=
(
void
*
(
*
)())
dlsym
(
RTLD_NEXT
,
"bind"
);
TRACE
(
">> bind(%d, _, %d)
called
\n
"
,
sockfd
,
addrlen
);
TRACE
(
">> bind(%d, _, %d)
\n
"
,
sockfd
,
addrlen
);
ret
=
(
int
)
func
(
sockfd
,
addr
,
addrlen
);
ret
=
(
int
)
func
(
sockfd
,
addr
,
addrlen
);
...
@@ -763,7 +878,7 @@ int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen)
...
@@ -763,7 +878,7 @@ int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen)
int
fd
,
ret
,
envfd
;
int
fd
,
ret
,
envfd
;
static
void
*
(
*
func
)();
static
void
*
(
*
func
)();
if
(
!
func
)
func
=
(
void
*
(
*
)())
dlsym
(
RTLD_NEXT
,
"accept"
);
if
(
!
func
)
func
=
(
void
*
(
*
)())
dlsym
(
RTLD_NEXT
,
"accept"
);
TRACE
(
"<< accept(%d, _, _)
called
\n
"
,
sockfd
);
TRACE
(
"<< accept(%d, _, _)
\n
"
,
sockfd
);
fd
=
(
int
)
func
(
sockfd
,
addr
,
addrlen
);
fd
=
(
int
)
func
(
sockfd
,
addr
,
addrlen
);
...
@@ -882,9 +997,13 @@ int pselect(int nfds, fd_set *readfds, fd_set *writefds,
...
@@ -882,9 +997,13 @@ int pselect(int nfds, fd_set *readfds, fd_set *writefds,
int
poll
(
struct
pollfd
*
fds
,
nfds_t
nfds
,
int
timeout
)
int
poll
(
struct
pollfd
*
fds
,
nfds_t
nfds
,
int
timeout
)
{
{
//TRACE("poll(_, %d, _) called\n", nfds
);
TRACE
(
"poll(_, %ld, %d) called
\n
"
,
nfds
,
timeout
);
static
void
*
(
*
func
)(
);
return
_WS_poll
(
0
,
fds
,
nfds
,
timeout
,
NULL
,
NULL
);
if
(
!
func
)
func
=
(
void
*
(
*
)())
dlsym
(
RTLD_NEXT
,
"poll"
);
}
return
(
int
)
func
(
fds
,
nfds
,
timeout
);
int
ppoll
(
struct
pollfd
*
fds
,
nfds_t
nfds
,
const
struct
timespec
*
timeout
,
const
sigset_t
*
sigmask
)
{
TRACE
(
"ppoll(_, %ld, _, _) called
\n
"
,
nfds
);
return
_WS_poll
(
0
,
fds
,
nfds
,
0
,
timeout
,
sigmask
);
}
}
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment