Initial Commit
This commit is contained in:
288
source/ntcp.cpp.meh
Normal file
288
source/ntcp.cpp.meh
Normal file
@@ -0,0 +1,288 @@
|
||||
/* This is free and unencumbered software released into the public domain.
|
||||
|
||||
Anyone is free to copy, modify, publish, use, compile, sell, or
|
||||
distribute this software, either in source code form or as a compiled
|
||||
binary, for any purpose, commercial or non-commercial, and by any
|
||||
means.
|
||||
|
||||
In jurisdictions that recognize copyright laws, the author or authors
|
||||
of this software dedicate any and all copyright interest in the
|
||||
software to the public domain. We make this dedication for the benefit
|
||||
of the public at large and to the detriment of our heirs and
|
||||
successors. We intend this dedication to be an overt act of
|
||||
relinquishment in perpetuity of all present and future rights to this
|
||||
software under copyright law.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
|
||||
OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
||||
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
For more information, please refer to <http://unlicense.org>
|
||||
|
||||
Additionally, the ntp_packet struct uses code licensed under the BSD 3-clause.*/
|
||||
/* This homebrew uses code from https://github.com/lettier/ntpclient under the following license:
|
||||
|
||||
BSD 3-Clause License
|
||||
|
||||
Copyright (c) 2014, David Lettier
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice, this
|
||||
list of conditions and the following disclaimer.
|
||||
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
|
||||
* Neither the name of the copyright holder nor the names of its
|
||||
contributors may be used to endorse or promote products derived from
|
||||
this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
// This code comes from https://github.com/thedax/NX-ntpc, thank you for your work
|
||||
|
||||
#include "ntcp.hpp"
|
||||
|
||||
#include <cstring>
|
||||
#include <sstream>
|
||||
#include <time.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
#include <netdb.h>
|
||||
#include <errno.h>
|
||||
#include <stdarg.h>
|
||||
#include <string>
|
||||
|
||||
#include <switch.h>
|
||||
|
||||
#define NTP_TIMESTAMP_DELTA 2208988800ull
|
||||
|
||||
/* ------------- BEGIN BSD 3-CLAUSE LICENSED CODE-------------------- */
|
||||
// https://www.cisco.com/c/en/us/about/press/internet-protocol-journal/back-issues/table-contents-58/154-ntp.html
|
||||
// Struct adapted from https://github.com/lettier/ntpclient , see LICENSE-THIRD-PARTY for more information.
|
||||
typedef struct
|
||||
{
|
||||
uint8_t li_vn_mode; // li: two bits, leap indicator. vn: three bits, protocol version number. mode: three bits, client mode.
|
||||
|
||||
uint8_t stratum; // Stratum level of the local clock.
|
||||
uint8_t poll; // Maximum interval between successive messages.
|
||||
uint8_t precision; // Precision of the local clock.
|
||||
|
||||
uint32_t rootDelay; // Total round trip delay time.
|
||||
uint32_t rootDispersion; // Max error allowed from primary clock source.
|
||||
uint32_t refId; // Reference clock identifier.
|
||||
|
||||
uint32_t refTm_s; // Reference time-stamp seconds.
|
||||
uint32_t refTm_f; // Reference time-stamp fraction of a second.
|
||||
|
||||
uint32_t origTm_s; // Originate time-stamp seconds.
|
||||
uint32_t origTm_f; // Originate time-stamp fraction of a second.
|
||||
|
||||
uint32_t rxTm_s; // Received time-stamp seconds.
|
||||
uint32_t rxTm_f; // Received time-stamp fraction of a second.
|
||||
|
||||
uint32_t txTm_s; // Transmit time-stamp seconds.
|
||||
uint32_t txTm_f; // Transmit time-stamp fraction of a second.
|
||||
} ntp_packet;
|
||||
/* ------------- END BSD 3-CLAUSE LICENSED CODE-------------------- */
|
||||
|
||||
void serviceCleanup(void)
|
||||
{
|
||||
nifmExit();
|
||||
setsysExit();
|
||||
timeExit();
|
||||
}
|
||||
|
||||
void print(const std::string& msg)
|
||||
{
|
||||
puts(msg);
|
||||
consoleUpdate(NULL);
|
||||
}
|
||||
|
||||
void printWithArgs(const std::string& msg, ...)
|
||||
{
|
||||
va_list args;
|
||||
va_start(args, msg);
|
||||
vprintf(msg, args);
|
||||
va_end(args);
|
||||
consoleUpdate(NULL);
|
||||
}
|
||||
|
||||
// We need system service access, not just user (the default)
|
||||
|
||||
std::string syncTime()
|
||||
{
|
||||
const std::string& server_name = "0.pool.ntp.org";
|
||||
const uint16_t port = 123;
|
||||
int sockfd = -1;
|
||||
std::stringstream out;
|
||||
|
||||
int res = 0;
|
||||
time_t tim;
|
||||
|
||||
Result rs = timeInitialize();
|
||||
if(R_FAILED(rs))
|
||||
{
|
||||
//printWithArgs("Failed to init time services, error code %x\n", rs);
|
||||
out << "Failed to init time services, error code " << rs << std::endl;
|
||||
goto done;
|
||||
}
|
||||
|
||||
rs = nifmInitialize(NifmServiceType_User);
|
||||
if(R_FAILED(rs))
|
||||
{
|
||||
//printWithArgs("Failed to init nifm services, with error code %x\n", rs);
|
||||
out << "Failed to init nifm services, with error code " << rs << std::endl;
|
||||
goto done;
|
||||
}
|
||||
|
||||
NifmInternetConnectionStatus nifmICS;
|
||||
rs = nifmGetInternetConnectionStatus(NULL, NULL, &nifmICS);
|
||||
if(R_FAILED(rs))
|
||||
{
|
||||
//printWithArgs("Failed to get internet connection status, with error code %x\nPlease ensure your console is connected to the internet, and try again.\n", rs);
|
||||
out << "Failed to get internet connection status, with error code " << res << ". Please ensure your console is connected to the internet, and try again." << std::endl;
|
||||
goto done;
|
||||
}
|
||||
|
||||
if(nifmICS != NifmInternetConnectionStatus_Connected)
|
||||
{
|
||||
//print("You're not connected to the internet. Please run this application again after connecting.");
|
||||
out << "You're not connected to the internet. Please run this application again after connecting." << std::endl;
|
||||
goto done;
|
||||
}
|
||||
|
||||
ntp_packet packet;
|
||||
memset(&packet, 0, sizeof(ntp_packet));
|
||||
|
||||
packet.li_vn_mode = (0 << 6) | (4 << 3) | 3; // LI 0 | Client version 4 | Mode 3
|
||||
|
||||
packet.txTm_s = htonl(NTP_TIMESTAMP_DELTA + time(NULL)); // Current networktime on the console
|
||||
|
||||
struct sockaddr_in serv_addr;
|
||||
struct hostent *server;
|
||||
|
||||
sockfd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
|
||||
if(sockfd < 0)
|
||||
{
|
||||
//printWithArgs("Failed to open socket with error code %x\n", errno);
|
||||
out << "Failed to open socket with error code " << errno << std::endl;
|
||||
goto done;
|
||||
}
|
||||
|
||||
//print("Opened socket");
|
||||
//printWithArgs("Attempting to connect to %s\n", server_name);
|
||||
errno = 0;
|
||||
if((server = gethostbyname(server_name)) == NULL)
|
||||
{
|
||||
//printWithArgs("Gethostbyname failed: %x\n", errno);
|
||||
out << "Gethostbyname failed: " << errno << std::endl;
|
||||
goto done;
|
||||
}
|
||||
|
||||
memset(&serv_addr, 0, sizeof(struct sockaddr_in));
|
||||
|
||||
serv_addr.sin_family = AF_INET;
|
||||
|
||||
memcpy((char *)&serv_addr.sin_addr.s_addr, (char *)server->h_addr_list[0], 4);
|
||||
|
||||
serv_addr.sin_port = htons(port);
|
||||
|
||||
errno = 0;
|
||||
if((res = connect(sockfd, (struct sockaddr *)&serv_addr, sizeof(serv_addr))) < 0)
|
||||
{
|
||||
//printWithArgs("Connect failed: %x %x\n", res, errno);
|
||||
out << "Connect failed: " << res << " " << errno << std::endl;
|
||||
goto done;
|
||||
}
|
||||
|
||||
errno = 0;
|
||||
if((res = send(sockfd, (char *)&packet, sizeof(ntp_packet), 0)) < 0)
|
||||
{
|
||||
//printWithArgs("Error writing to socket: %x %x\n", res, errno);
|
||||
out << "Error writing to socket: " << res << " " << errno << std::endl;
|
||||
goto done;
|
||||
}
|
||||
|
||||
printWithArgs("Sent time request with result: %x %x, waiting for response...\n", res, errno);
|
||||
|
||||
errno = 0;
|
||||
if((res = recv(sockfd, (char *)&packet, sizeof(ntp_packet), 0)) < sizeof(ntp_packet))
|
||||
{
|
||||
//printWithArgs("Error reading from socket: %x %x\n", res, errno);
|
||||
out << "Error reading from socket: " << res << " " << errno << std::endl;
|
||||
goto done;
|
||||
}
|
||||
|
||||
packet.txTm_s = ntohl(packet.txTm_s);
|
||||
|
||||
tim = (time_t) (packet.txTm_s - NTP_TIMESTAMP_DELTA);
|
||||
|
||||
rs = timeSetCurrentTime(TimeType_NetworkSystemClock, (uint64_t)tim);
|
||||
if(R_FAILED(rs))
|
||||
{
|
||||
//printWithArgs("Failed to set NetworkSystemClock, %x\n", rs);
|
||||
out << "Failed to set NetworkSystemClock " << rs << std::endl;
|
||||
}
|
||||
else
|
||||
out << "Successfully set NetworkSystemClock" << std::endl;
|
||||
|
||||
rs = setsysInitialize();
|
||||
if(R_FAILED(rs))
|
||||
{
|
||||
//printWithArgs("setsysInitialize failed, %x\n", rs);
|
||||
out << "setsysInitialize failed, " << rs << std::endl;
|
||||
goto done;
|
||||
}
|
||||
|
||||
bool internetTimeSync;
|
||||
|
||||
rs = setsysIsUserSystemClockAutomaticCorrectionEnabled(&internetTimeSync);
|
||||
if(R_FAILED(rs) || internetTimeSync == false)
|
||||
{
|
||||
//printWithArgs("Unable to detect if internet time sync is enabled, %x\n", rs);
|
||||
out << "Note: internet time sync is not enabled (enabling it will correct the time on the home screen)" << std::endl;
|
||||
goto done;
|
||||
}
|
||||
|
||||
/* if(internetTimeSync == false)
|
||||
{
|
||||
print("Internet time sync is not enabled (enabling it will correct the time on the home screen, and this prompt will not appear again).\nPress A to enable internet time sync (and restart the console), or PLUS to quit.");
|
||||
rs = setsysSetUserSystemClockAutomaticCorrectionEnabled(true);
|
||||
if(R_SUCCEEDED(rs))
|
||||
{
|
||||
serviceCleanup();
|
||||
bpcInitialize();
|
||||
bpcRebootSystem();
|
||||
bpcExit();
|
||||
}
|
||||
} */
|
||||
|
||||
done:
|
||||
|
||||
cleanup:
|
||||
if(sockfd != -1)
|
||||
close(sockfd);
|
||||
serviceCleanup();
|
||||
return out.str();
|
||||
}
|
||||
Reference in New Issue
Block a user