Skip to content
Projects
Groups
Snippets
Help
Loading...
Sign in / Register
Toggle navigation
M
mongoose
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
Packages
Packages
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
submodule
mongoose
Commits
ed24afd1
Commit
ed24afd1
authored
9 years ago
by
Sergey Lyubka
Committed by
rojer
9 years ago
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Connect timeouts for resolving connections
PUBLISHED_FROM=068b6f75550b10913d7f13106f9a7f7dce5babec
parent
714556de
Show whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
84 additions
and
7 deletions
+84
-7
mongoose.c
mongoose.c
+45
-6
mongoose.h
mongoose.h
+39
-1
No files found.
mongoose.c
View file @
ed24afd1
...
...
@@ -2488,11 +2488,13 @@ void mg_if_connect_cb(struct mg_connection *nc, int err) {
* either failure (and dealloc the connection)
* or success (and proceed with connect()
*/
static
void
resolve_cb
(
struct
mg_dns_message
*
msg
,
void
*
data
)
{
static
void
resolve_cb
(
struct
mg_dns_message
*
msg
,
void
*
data
,
enum
mg_resolve_err
e
)
{
struct
mg_connection
*
nc
=
(
struct
mg_connection
*
)
data
;
int
i
;
int
failure
=
-
1
;
nc
->
flags
&=
~
MG_F_RESOLVING
;
if
(
msg
!=
NULL
)
{
/*
* Take the first DNS A answer and run...
...
...
@@ -2512,6 +2514,11 @@ static void resolve_cb(struct mg_dns_message *msg, void *data) {
}
}
if
(
e
==
MG_RESOLVE_TIMEOUT
)
{
double
now
=
time
(
NULL
);
mg_call
(
nc
,
NULL
,
MG_EV_TIMER
,
&
now
);
}
/*
* If we get there was no MG_DNS_A_RECORD in the answer
*/
...
...
@@ -2557,12 +2564,18 @@ struct mg_connection *mg_connect_opt(struct mg_mgr *mgr, const char *address,
* DNS resolution is required for host.
* mg_parse_address() fills port in nc->sa, which we pass to resolve_cb()
*/
if
(
mg_resolve_async
(
nc
->
mgr
,
host
,
MG_DNS_A_RECORD
,
resolve_cb
,
nc
)
!=
0
)
{
struct
mg_connection
*
dns_conn
=
NULL
;
struct
mg_resolve_async_opts
o
;
memset
(
&
o
,
0
,
sizeof
(
o
));
o
.
dns_conn
=
&
dns_conn
;
if
(
mg_resolve_async_opt
(
nc
->
mgr
,
host
,
MG_DNS_A_RECORD
,
resolve_cb
,
nc
,
o
)
!=
0
)
{
MG_SET_PTRPTR
(
opts
.
error_string
,
"cannot schedule DNS lookup"
);
mg_destroy_conn
(
nc
);
return
NULL
;
}
nc
->
priv_2
=
dns_conn
;
nc
->
flags
|=
MG_F_RESOLVING
;
return
nc
;
#else
MG_SET_PTRPTR
(
opts
.
error_string
,
"Resolver is disabled"
);
...
...
@@ -2700,6 +2713,21 @@ void mg_forward(struct mg_connection *from, struct mg_connection *to) {
mg_send
(
to
,
from
->
recv_mbuf
.
buf
,
from
->
recv_mbuf
.
len
);
mbuf_remove
(
&
from
->
recv_mbuf
,
from
->
recv_mbuf
.
len
);
}
double
mg_set_timer
(
struct
mg_connection
*
c
,
double
timestamp
)
{
double
result
=
c
->
ev_timer_time
;
c
->
ev_timer_time
=
timestamp
;
/*
* If this connection is resolving, it's not in the list of active
* connections, so not processed yet. It has a DNS resolver connection
* linked to it. Set up a timer for the DNS connection.
*/
DBG
((
"%p %p %d"
,
c
,
c
->
priv_2
,
c
->
flags
&
MG_F_RESOLVING
));
if
((
c
->
flags
&
MG_F_RESOLVING
)
&&
c
->
priv_2
!=
NULL
)
{
((
struct
mg_connection
*
)
c
->
priv_2
)
->
ev_timer_time
=
timestamp
;
}
return
result
;
}
#ifdef NS_MODULE_LINES
#line 1 "src/net_if_socket.c"
/**/
...
...
@@ -7835,6 +7863,7 @@ struct mg_resolve_async_request {
void
*
data
;
time_t
timeout
;
int
max_retries
;
enum
mg_resolve_err
err
;
/* state */
time_t
last_time
;
...
...
@@ -7964,6 +7993,7 @@ static void mg_resolve_async_eh(struct mg_connection *nc, int ev, void *data) {
case
MG_EV_CONNECT
:
case
MG_EV_POLL
:
if
(
req
->
retries
>
req
->
max_retries
)
{
req
->
err
=
MG_RESOLVE_EXCEEDED_RETRY_COUNT
;
nc
->
flags
|=
MG_F_CLOSE_IMMEDIATELY
;
break
;
}
...
...
@@ -7977,9 +8007,11 @@ static void mg_resolve_async_eh(struct mg_connection *nc, int ev, void *data) {
msg
=
(
struct
mg_dns_message
*
)
MG_MALLOC
(
sizeof
(
*
msg
));
if
(
mg_parse_dns
(
nc
->
recv_mbuf
.
buf
,
*
(
int
*
)
data
,
msg
)
==
0
&&
msg
->
num_answers
>
0
)
{
req
->
callback
(
msg
,
req
->
data
);
req
->
callback
(
msg
,
req
->
data
,
MG_RESOLVE_OK
);
nc
->
user_data
=
NULL
;
MG_FREE
(
req
);
}
else
{
req
->
err
=
MG_RESOLVE_NO_ANSWERS
;
}
MG_FREE
(
msg
);
nc
->
flags
|=
MG_F_CLOSE_IMMEDIATELY
;
...
...
@@ -7992,10 +8024,14 @@ static void mg_resolve_async_eh(struct mg_connection *nc, int ev, void *data) {
nc
->
flags
&=
~
MG_F_CLOSE_IMMEDIATELY
;
mbuf_remove
(
&
nc
->
send_mbuf
,
nc
->
send_mbuf
.
len
);
break
;
case
MG_EV_TIMER
:
req
->
err
=
MG_RESOLVE_TIMEOUT
;
nc
->
flags
|=
MG_F_CLOSE_IMMEDIATELY
;
break
;
case
MG_EV_CLOSE
:
/* If we got here with request still not done, fire an error callback. */
if
(
req
!=
NULL
)
{
req
->
callback
(
NULL
,
req
->
data
);
req
->
callback
(
NULL
,
req
->
data
,
req
->
err
);
nc
->
user_data
=
NULL
;
MG_FREE
(
req
);
}
...
...
@@ -8017,7 +8053,7 @@ int mg_resolve_async_opt(struct mg_mgr *mgr, const char *name, int query,
struct
mg_connection
*
dns_nc
;
const
char
*
nameserver
=
opts
.
nameserver_url
;
DBG
((
"%s %d
"
,
name
,
query
));
DBG
((
"%s %d
%p"
,
name
,
query
,
opts
.
dns_conn
));
/* resolve with DNS */
req
=
(
struct
mg_resolve_async_request
*
)
MG_CALLOC
(
1
,
sizeof
(
*
req
));
...
...
@@ -8050,6 +8086,9 @@ int mg_resolve_async_opt(struct mg_mgr *mgr, const char *name, int query,
return
-
1
;
}
dns_nc
->
user_data
=
req
;
if
(
opts
.
dns_conn
!=
NULL
)
{
*
opts
.
dns_conn
=
dns_nc
;
}
return
0
;
}
...
...
This diff is collapsed.
Click to expand it.
mongoose.h
View file @
ed24afd1
...
...
@@ -1063,6 +1063,35 @@ enum v7_err mg_enable_javascript(struct mg_mgr *m, struct v7 *v7,
const
char
*
init_js_file_name
);
#endif
/*
* Schedule MG_EV_TIMER event to be delivered at `timestamp` time.
* `timestamp` is a UNIX time (a number of seconds since Epoch). It is
* `double` instead of `time_t` to allow for sub-second precision.
* Return the old timer value.
*
* Example: set connect timeout to 1.5 seconds:
*
* ```
* c = mg_connect(&mgr, "cesanta.com", ev_handler);
* mg_set_timer(c, time(NULL) + 1.5);
* ...
*
* void ev_handler(struct mg_connection *c, int ev, void *ev_data) {
* switch (ev) {
* case MG_EV_CONNECT:
* mg_set_timer(c, 0); // Clear connect timer
* break;
* case MG_EV_TIMER:
* log("Connect timeout");
* c->flags |= MG_F_CLOSE_IMMEDIATELY;
* break;
```
*
* NOTE: sub-second precision is not implemented yet, current granularity
* is 1 second.
*/
double
mg_set_timer
(
struct
mg_connection
*
c
,
double
timestamp
);
#ifdef __cplusplus
}
#endif
/* __cplusplus */
...
...
@@ -2556,7 +2585,15 @@ void mg_dns_send_reply(struct mg_connection *, struct mg_dns_reply *);
extern
"C"
{
#endif
/* __cplusplus */
typedef
void
(
*
mg_resolve_callback_t
)(
struct
mg_dns_message
*
,
void
*
);
enum
mg_resolve_err
{
MG_RESOLVE_OK
=
0
,
MG_RESOLVE_NO_ANSWERS
=
1
,
MG_RESOLVE_EXCEEDED_RETRY_COUNT
=
2
,
MG_RESOLVE_TIMEOUT
=
3
};
typedef
void
(
*
mg_resolve_callback_t
)(
struct
mg_dns_message
*
dns_message
,
void
*
user_data
,
enum
mg_resolve_err
);
/* Options for `mg_resolve_async_opt`. */
struct
mg_resolve_async_opts
{
...
...
@@ -2565,6 +2602,7 @@ struct mg_resolve_async_opts {
int
timeout
;
/* in seconds; defaults to 5 if zero */
int
accept_literal
;
/* pseudo-resolve literal ipv4 and ipv6 addrs */
int
only_literal
;
/* only resolves literal addrs; sync cb invocation */
struct
mg_connection
**
dns_conn
;
/* return DNS connection */
};
/* See `mg_resolve_async_opt()` */
...
...
This diff is collapsed.
Click to expand it.
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