#include <stdio.h>
#include <string.h>
#include <time.h>
#if defined(_WIN32)
#include <windows.h>
#endif
#include "hymma/hlm.h"
#include "hlm_sntp.h"
void hlm_sntp_build_request(uint8_t pkt[HLM_SNTP_PACKET_SIZE])
{
memset(pkt, 0, HLM_SNTP_PACKET_SIZE);
pkt[0] = 0x1B;
}
int hlm_sntp_parse_reply(const uint8_t pkt[HLM_SNTP_PACKET_SIZE],
int64_t *epoch_out)
{
uint32_t secs = ((uint32_t)pkt[40] << 24) | ((uint32_t)pkt[41] << 16) |
((uint32_t)pkt[42] << 8) | (uint32_t)pkt[43];
if (secs == 0) return -1;
*epoch_out = (int64_t)secs +
((secs & 0x80000000u) ? 0 : 4294967296LL) - 2208988800LL;
return 0;
}
hlm_net_failure hlm_net_failure_from_winhttp(unsigned long error)
{
switch (error) {
case 12007:
case 11001:
case 11002:
case 11004:
return HLM_NET_NAME_RESOLUTION;
case 12037:
case 12038:
case 12044:
case 12045:
case 12057:
case 12157:
case 12169:
case 12170:
case 12175:
case 12179:
case 12185:
case 12186:
return HLM_NET_SECURE_CONNECTION;
case 12166:
case 12167:
case 12178:
case 12180:
return HLM_NET_PROXY;
case 12002:
case 10060:
return HLM_NET_TIMEOUT;
case 12029:
case 12030:
case 12152:
case 10054:
case 10061:
return HLM_NET_CONNECTION;
default:
return HLM_NET_UNKNOWN;
}
}
hlm_net_failure hlm_net_failure_from_curl(int curl_code)
{
switch (curl_code) {
case 6:
return HLM_NET_NAME_RESOLUTION;
case 35:
case 51:
case 53:
case 54:
case 58:
case 59:
case 60:
case 77:
case 80:
case 82:
case 83:
case 90:
case 91:
return HLM_NET_SECURE_CONNECTION;
case 5:
case 97:
return HLM_NET_PROXY;
case 28:
return HLM_NET_TIMEOUT;
case 7:
case 52:
case 55:
case 56:
return HLM_NET_CONNECTION;
default:
return HLM_NET_UNKNOWN;
}
}
static int64_t clock_now(void *user)
{
(void)user;
return (int64_t)time(NULL);
}
hlm_clock hlm_clock_system(void)
{
hlm_clock c;
c.now = clock_now;
c.user = 0;
return c;
}
static int file_read(void *user, char *buf, size_t cap)
{
hlm_storage_file_cfg *cfg = (hlm_storage_file_cfg *)user;
FILE *f;
size_t n;
f = fopen(cfg->path, "rb");
if (f == NULL) return 0;
n = fread(buf, 1, cap, f);
if (ferror(f)) {
fclose(f);
return HLM_E_STORAGE;
}
if (!feof(f) && n == cap) {
fclose(f);
return HLM_E_BUFFER;
}
fclose(f);
return (int)n;
}
static int file_write(void *user, const char *data, size_t len)
{
hlm_storage_file_cfg *cfg = (hlm_storage_file_cfg *)user;
char tmp[576];
FILE *f;
size_t n;
if (snprintf(tmp, sizeof(tmp), "%s.tmp", cfg->path) >= (int)sizeof(tmp))
return HLM_E_STORAGE;
f = fopen(tmp, "wb");
if (f == NULL) return HLM_E_STORAGE;
n = fwrite(data, 1, len, f);
if (fclose(f) != 0 || n != len) {
remove(tmp);
return HLM_E_STORAGE;
}
#if defined(_WIN32)
if (!MoveFileExA(tmp, cfg->path, MOVEFILE_REPLACE_EXISTING)) {
remove(tmp);
return HLM_E_STORAGE;
}
#else
if (rename(tmp, cfg->path) != 0) {
remove(tmp);
return HLM_E_STORAGE;
}
#endif
return HLM_OK;
}
hlm_storage hlm_storage_file(hlm_storage_file_cfg *cfg)
{
hlm_storage s;
s.read = file_read;
s.write = file_write;
s.user = cfg;
return s;
}