Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Contribute to GitLab
Sign in
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
Wiki
Wiki
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
esp
mongoose
Commits
9e517fde
Commit
9e517fde
authored
8 years ago
by
Alexander Alashkin
Committed by
Cesanta Bot
8 years ago
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Implement SNTP client
PUBLISHED_FROM=ac54bcbc81a9ee688e8b90e261172be76a9fbacd
parent
1ff61837
Changes
4
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
406 additions
and
0 deletions
+406
-0
Makefile
examples/sntp_client/Makefile
+3
-0
sntp_client.c
examples/sntp_client/sntp_client.c
+51
-0
mongoose.c
mongoose.c
+292
-0
mongoose.h
mongoose.h
+60
-0
No files found.
examples/sntp_client/Makefile
0 → 100644
View file @
9e517fde
PROG
=
sntp_client
MODULE_CFLAGS
=
-DMG_ENABLE_SNTP
include
../examples.mk
This diff is collapsed.
Click to expand it.
examples/sntp_client/sntp_client.c
0 → 100644
View file @
9e517fde
/*
* Copyright (c) 2016 Cesanta Software Limited
* All rights reserved
*/
#include "mongoose.h"
static
int
s_exit_flag
=
0
;
static
const
char
*
s_default_server
=
"pool.ntp.org"
;
static
void
ev_handler
(
struct
mg_connection
*
c
,
int
ev
,
void
*
ev_data
)
{
struct
mg_sntp_message
*
sm
=
(
struct
mg_sntp_message
*
)
ev_data
;
time_t
t
;
(
void
)
c
;
switch
(
ev
)
{
case
MG_SNTP_REPLY
:
t
=
time
(
NULL
);
fprintf
(
stdout
,
"Local time: %s"
,
ctime
(
&
t
));
t
=
(
time_t
)
sm
->
time
;
fprintf
(
stdout
,
"Time from %s: %s"
,
s_default_server
,
ctime
(
&
t
));
s_exit_flag
=
1
;
break
;
case
MG_SNTP_FAILED
:
fprintf
(
stderr
,
"Failed to get time
\n
"
);
s_exit_flag
=
1
;
break
;
}
}
int
main
()
{
struct
mg_mgr
mgr
;
struct
mg_connection
*
c
;
mg_mgr_init
(
&
mgr
,
NULL
);
c
=
mg_sntp_get_time
(
&
mgr
,
ev_handler
,
s_default_server
);
if
(
c
==
NULL
)
{
fprintf
(
stderr
,
"Failed to connect to %s
\n
"
,
s_default_server
);
return
-
1
;
}
while
(
s_exit_flag
==
0
)
{
mg_mgr_poll
(
&
mgr
,
1000
);
}
mg_mgr_free
(
&
mgr
);
return
0
;
}
This diff is collapsed.
Click to expand it.
mongoose.c
View file @
9e517fde
...
...
@@ -165,6 +165,16 @@ MG_INTERNAL int mg_get_errno(void);
MG_INTERNAL
void
mg_close_conn
(
struct
mg_connection
*
conn
);
MG_INTERNAL
int
mg_http_common_url_parse
(
const
char
*
url
,
const
char
*
schema
,
const
char
*
schema_tls
,
int
*
use_ssl
,
char
**
user
,
char
**
pass
,
char
**
addr
,
int
*
port_i
,
const
char
**
path
);
#if MG_ENABLE_SNTP
MG_INTERNAL
int
mg_sntp_parse_reply
(
const
char
*
buf
,
int
len
,
struct
mg_sntp_message
*
msg
);
#endif
#endif
/* CS_MONGOOSE_SRC_INTERNAL_H_ */
#ifdef MG_MODULE_LINES
#line 1 "common/cs_dbg.h"
...
...
@@ -11463,6 +11473,288 @@ void mg_tun_send_frame(struct mg_connection *ws, uint32_t stream_id,
#endif
/* MG_ENABLE_TUN */
#ifdef MG_MODULE_LINES
#line 1 "mongoose/src/sntp.c"
#endif
/*
* Copyright (c) 2016 Cesanta Software Limited
* All rights reserved
*/
/* Amalgamated: #include "mongoose/src/internal.h" */
/* Amalgamated: #include "mongoose/src/sntp.h" */
/* Amalgamated: #include "mongoose/src/util.h" */
#if MG_ENABLE_SNTP
#define SNTP_TIME_OFFSET 2208988800
#ifndef SNTP_TIMEOUT
#define SNTP_TIMEOUT 10
#endif
#ifndef SNTP_ATTEMPTS
#define SNTP_ATTEMPTS 3
#endif
static
uint64_t
mg_get_sec
(
uint64_t
val
)
{
return
(
val
&
0xFFFFFFFF00000000
)
>>
32
;
}
static
uint64_t
mg_get_usec
(
uint64_t
val
)
{
uint64_t
tmp
=
(
val
&
0x00000000FFFFFFFF
);
tmp
*=
1000000
;
tmp
>>=
32
;
return
tmp
;
}
static
void
mg_ntp_to_tv
(
uint64_t
val
,
struct
timeval
*
tv
)
{
uint64_t
tmp
;
tmp
=
mg_get_sec
(
val
);
tmp
-=
SNTP_TIME_OFFSET
;
tv
->
tv_sec
=
tmp
;
tv
->
tv_usec
=
mg_get_usec
(
val
);
}
static
void
mg_get_ntp_ts
(
const
char
*
ntp
,
uint64_t
*
val
)
{
uint32_t
tmp
;
memcpy
(
&
tmp
,
ntp
,
sizeof
(
tmp
));
tmp
=
ntohl
(
tmp
);
*
val
=
(
uint64_t
)
tmp
<<
32
;
memcpy
(
&
tmp
,
ntp
+
4
,
sizeof
(
tmp
));
tmp
=
ntohl
(
tmp
);
*
val
|=
tmp
;
}
void
mg_sntp_send_request
(
struct
mg_connection
*
c
)
{
char
buf
[
48
]
=
{
0
};
/*
* header - 8 bit:
* LI (2 bit) - 3 (not in sync), VN (3 bit) - 4 (version),
* mode (3 bit) - 3 (client)
*/
buf
[
0
]
=
(
3
<<
6
)
|
(
4
<<
3
)
|
3
;
/*
* Next fields should be empty in client request
* stratum, 8 bit
* poll interval, 8 bit
* rrecision, 8 bit
* root delay, 32 bit
* root dispersion, 32 bit
* ref id, 32 bit
* ref timestamp, 64 bit
* originate Timestamp, 64 bit
* receive Timestamp, 64 bit
*/
/*
* convert time to sntp format (sntp starts from 00:00:00 01.01.1900)
* according to rfc868 it is 2208988800L sec
* this information is used to correct roundtrip delay
* but if local clock is absolutely broken (and doesn't work even
* as simple timer), it is better to disable it
*/
#ifndef MG_SNMP_NO_DELAY_CORRECTION
uint32_t
sec
;
sec
=
htonl
(
mg_time
()
+
SNTP_TIME_OFFSET
);
memcpy
(
&
buf
[
40
],
&
sec
,
sizeof
(
sec
));
#endif
mg_send
(
c
,
buf
,
sizeof
(
buf
));
}
#ifndef MG_SNMP_NO_DELAY_CORRECTION
static
uint64_t
mg_calculate_delay
(
uint64_t
t1
,
uint64_t
t2
,
uint64_t
t3
)
{
/* roundloop delay = (T4 - T1) - (T3 - T2) */
uint64_t
d1
=
((
mg_time
()
+
SNTP_TIME_OFFSET
)
*
1000000
)
-
(
mg_get_sec
(
t1
)
*
1000000
+
mg_get_usec
(
t1
));
uint64_t
d2
=
(
mg_get_sec
(
t3
)
*
1000000
+
mg_get_usec
(
t3
))
-
(
mg_get_sec
(
t2
)
*
1000000
+
mg_get_usec
(
t2
));
return
(
d1
>
d2
)
?
d1
-
d2
:
0
;
}
#endif
MG_INTERNAL
int
mg_sntp_parse_reply
(
const
char
*
buf
,
int
len
,
struct
mg_sntp_message
*
msg
)
{
uint8_t
hdr
;
uint64_t
orig_ts_T1
,
recv_ts_T2
,
trsm_ts_T3
,
delay
=
0
;
int
mode
;
struct
timeval
tv
;
(
void
)
orig_ts_T1
;
(
void
)
recv_ts_T2
;
if
(
len
<
48
)
{
return
-
1
;
}
hdr
=
buf
[
0
];
if
((
hdr
&
0x38
)
>>
3
!=
4
)
{
/* Wrong version */
return
-
1
;
}
mode
=
hdr
&
0x7
;
if
(
mode
!=
4
&&
mode
!=
5
)
{
/* Not a server reply */
return
-
1
;
}
memset
(
msg
,
0
,
sizeof
(
*
msg
));
msg
->
kiss_of_death
=
(
buf
[
1
]
==
0
);
/* Server asks to not send requests */
mg_get_ntp_ts
(
&
buf
[
40
],
&
trsm_ts_T3
);
#ifndef MG_SNMP_NO_DELAY_CORRECTION
mg_get_ntp_ts
(
&
buf
[
24
],
&
orig_ts_T1
);
mg_get_ntp_ts
(
&
buf
[
32
],
&
recv_ts_T2
);
delay
=
mg_calculate_delay
(
orig_ts_T1
,
recv_ts_T2
,
trsm_ts_T3
);
#endif
mg_ntp_to_tv
(
trsm_ts_T3
,
&
tv
);
msg
->
time
=
(
double
)
tv
.
tv_sec
+
(((
double
)
tv
.
tv_usec
+
delay
)
/
1000000
.
0
);
return
0
;
}
static
void
mg_sntp_handler
(
struct
mg_connection
*
c
,
int
ev
,
void
*
ev_data
)
{
struct
mbuf
*
io
=
&
c
->
recv_mbuf
;
struct
mg_sntp_message
msg
;
c
->
handler
(
c
,
ev
,
ev_data
);
switch
(
ev
)
{
case
MG_EV_RECV
:
{
if
(
mg_sntp_parse_reply
(
io
->
buf
,
io
->
len
,
&
msg
)
<
0
)
{
DBG
((
"Invalid SNTP packet received (%d)"
,
(
int
)
io
->
len
));
c
->
handler
(
c
,
MG_SNTP_MALFORMED_REPLY
,
NULL
);
}
else
{
c
->
handler
(
c
,
MG_SNTP_REPLY
,
(
void
*
)
&
msg
);
}
mbuf_remove
(
io
,
io
->
len
);
break
;
}
}
}
int
mg_set_protocol_sntp
(
struct
mg_connection
*
c
)
{
if
((
c
->
flags
&
MG_F_UDP
)
==
0
)
{
return
-
1
;
}
c
->
proto_handler
=
mg_sntp_handler
;
return
0
;
}
struct
mg_connection
*
mg_sntp_connect
(
struct
mg_mgr
*
mgr
,
mg_event_handler_t
event_handler
,
const
char
*
sntp_server_name
)
{
struct
mg_connection
*
c
=
NULL
;
char
url
[
100
],
*
p_url
=
url
;
const
char
*
proto
=
""
,
*
port
=
""
,
*
tmp
;
/* If port is not specified, use default (123) */
tmp
=
strchr
(
sntp_server_name
,
':'
);
if
(
tmp
!=
NULL
&&
*
(
tmp
+
1
)
==
'/'
)
{
tmp
=
strchr
(
tmp
+
1
,
':'
);
}
if
(
tmp
==
NULL
)
{
port
=
":123"
;
}
/* Add udp:// if needed */
if
(
strncmp
(
sntp_server_name
,
"udp://"
,
6
)
!=
0
)
{
proto
=
"udp://"
;
}
mg_asprintf
(
&
p_url
,
sizeof
(
url
),
"%s%s%s"
,
proto
,
sntp_server_name
,
port
);
c
=
mg_connect
(
mgr
,
p_url
,
event_handler
);
if
(
c
==
NULL
)
{
goto
cleanup
;
}
mg_set_protocol_sntp
(
c
);
cleanup:
if
(
p_url
!=
url
)
{
MG_FREE
(
p_url
);
}
return
c
;
}
struct
sntp_data
{
mg_event_handler_t
hander
;
int
count
;
};
static
void
mg_sntp_util_ev_handler
(
struct
mg_connection
*
c
,
int
ev
,
void
*
ev_data
)
{
struct
sntp_data
*
sd
=
(
struct
sntp_data
*
)
c
->
user_data
;
switch
(
ev
)
{
case
MG_EV_CONNECT
:
if
(
*
(
int
*
)
ev_data
!=
0
)
{
mg_call
(
c
,
sd
->
hander
,
MG_SNTP_FAILED
,
NULL
);
break
;
}
/* fallthrough */
case
MG_EV_TIMER
:
if
(
sd
->
count
<=
SNTP_ATTEMPTS
)
{
mg_sntp_send_request
(
c
);
mg_set_timer
(
c
,
mg_time
()
+
10
);
sd
->
count
++
;
}
else
{
mg_call
(
c
,
sd
->
hander
,
MG_SNTP_FAILED
,
NULL
);
c
->
flags
|=
MG_F_CLOSE_IMMEDIATELY
;
}
break
;
case
MG_SNTP_MALFORMED_REPLY
:
mg_call
(
c
,
sd
->
hander
,
MG_SNTP_FAILED
,
NULL
);
c
->
flags
|=
MG_F_CLOSE_IMMEDIATELY
;
break
;
case
MG_SNTP_REPLY
:
mg_call
(
c
,
sd
->
hander
,
MG_SNTP_REPLY
,
ev_data
);
c
->
flags
|=
MG_F_CLOSE_IMMEDIATELY
;
break
;
case
MG_EV_CLOSE
:
MG_FREE
(
c
->
user_data
);
c
->
user_data
=
NULL
;
break
;
}
}
struct
mg_connection
*
mg_sntp_get_time
(
struct
mg_mgr
*
mgr
,
mg_event_handler_t
event_handler
,
const
char
*
sntp_server_name
)
{
struct
mg_connection
*
c
;
struct
sntp_data
*
sd
=
(
struct
sntp_data
*
)
MG_CALLOC
(
1
,
sizeof
(
*
sd
));
if
(
sd
==
NULL
)
{
return
NULL
;
}
c
=
mg_sntp_connect
(
mgr
,
mg_sntp_util_ev_handler
,
sntp_server_name
);
if
(
c
==
NULL
)
{
MG_FREE
(
sd
);
return
NULL
;
}
sd
->
hander
=
event_handler
;
c
->
user_data
=
sd
;
return
c
;
}
#endif
/* MG_ENABLE_SNTP */
#ifdef MG_MODULE_LINES
#line 1 "common/platforms/cc3200/cc3200_libc.c"
#endif
/*
...
...
This diff is collapsed.
Click to expand it.
mongoose.h
View file @
9e517fde
...
...
@@ -2812,6 +2812,10 @@ struct { \
#define MG_ENABLE_TUN MG_ENABLE_HTTP_WEBSOCKET
#endif
#ifndef MG_ENABLE_SNTP
#define MG_ENABLE_SNTP 0
#endif
#endif
/* CS_MONGOOSE_SRC_FEATURES_H_ */
#ifdef MG_MODULE_LINES
#line 1 "mongoose/src/net_if.h"
...
...
@@ -5591,3 +5595,59 @@ uint32_t mg_coap_compose(struct mg_coap_message *cm, struct mbuf *io);
#endif
/* MG_ENABLE_COAP */
#endif
/* CS_MONGOOSE_SRC_COAP_H_ */
#ifdef MG_MODULE_LINES
#line 1 "mongoose/src/sntp.h"
#endif
/*
* Copyright (c) 2016 Cesanta Software Limited
* All rights reserved
*/
#ifndef CS_MONGOOSE_SRC_SNTP_H_
#define CS_MONGOOSE_SRC_SNTP_H_
#if MG_ENABLE_SNTP
#define MG_SNTP_EVENT_BASE 500
/*
* Received reply from time server. Event handler parameter contains
* pointer to mg_sntp_message structure
*/
#define MG_SNTP_REPLY (MG_SNTP_EVENT_BASE + 1)
/* Received malformed SNTP packet */
#define MG_SNTP_MALFORMED_REPLY (MG_SNTP_EVENT_BASE + 2)
/* Failed to get time from server (timeout etc) */
#define MG_SNTP_FAILED (MG_SNTP_EVENT_BASE + 3)
struct
mg_sntp_message
{
/* if server sends this flags, user should not send requests to it */
int
kiss_of_death
;
/* usual mg_time */
double
time
;
};
/* Establishes connection to given sntp server */
struct
mg_connection
*
mg_sntp_connect
(
struct
mg_mgr
*
mgr
,
mg_event_handler_t
event_handler
,
const
char
*
sntp_server_name
);
/* Sends time request to given connection */
void
mg_sntp_send_request
(
struct
mg_connection
*
c
);
/*
* Helper function
* Establishes connection to time server, tries to send request
* repeats sending SNTP_ATTEMPTS times every SNTP_TIMEOUT sec
* (if needed)
* See sntp_client example
*/
struct
mg_connection
*
mg_sntp_get_time
(
struct
mg_mgr
*
mgr
,
mg_event_handler_t
event_handler
,
const
char
*
sntp_server_name
);
#endif
#endif
/* CS_MONGOOSE_SRC_SNTP_H_ */
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