aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorvdrfan <vdrfan@svn>2010-01-30 15:47:15 +0000
committervdrfan <vdrfan@svn>2010-01-30 15:47:15 +0000
commit5cf5faa518890513bca598ffff79939baa31c41b (patch)
tree9f01dae80e940b2b1c5136bda8064238f89b311a
parent3f21a9613dc998abcb54536ceea1c2b5420148a9 (diff)
added: wakeonlan builtin command. See http://xbmc.org/wiki/?title=List_of_Built_In_Functions for more information.
git-svn-id: https://xbmc.svn.sourceforge.net/svnroot/xbmc/trunk@27296 568bbfeb-2a22-0410-94d2-cc84cf5bfa90
-rw-r--r--xbmc/utils/Builtins.cpp5
-rw-r--r--xbmc/utils/Network.cpp115
-rw-r--r--xbmc/utils/Network.h3
3 files changed, 122 insertions, 1 deletions
diff --git a/xbmc/utils/Builtins.cpp b/xbmc/utils/Builtins.cpp
index 4c32c123d6..27f8b37786 100644
--- a/xbmc/utils/Builtins.cpp
+++ b/xbmc/utils/Builtins.cpp
@@ -177,6 +177,7 @@ const BUILT_IN commands[] = {
{ "LoadProfile", true, "Load the specified profile (note; if locks are active it won't work)" },
{ "SetProperty", true, "Sets a window property for the current window (key,value)" },
{ "PlayWith", true, "Play the selected item with the specified core" },
+ { "WakeOnLan", true, "Sends the wake-up packet to the broadcast address for the specified MAC address" },
#if defined(HAS_LIRC) || defined(HAS_IRSERVERSUITE)
{ "LIRC.Stop", false, "Removes XBMC as LIRC client" },
{ "LIRC.Start", false, "Adds XBMC as LIRC client" },
@@ -1272,6 +1273,10 @@ int CBuiltins::Execute(const CStdString& execString)
if (window)
window->SetProperty(params[0],params[1]);
}
+ else if (execute.Equals("wakeonlan"))
+ {
+ g_application.getNetwork().WakeOnLan((char*)params[0].c_str());
+ }
#if defined(HAS_LIRC) || defined(HAS_IRSERVERSUITE)
else if (execute.Equals("lirc.stop"))
{
diff --git a/xbmc/utils/Network.cpp b/xbmc/utils/Network.cpp
index 9caf84e1e0..bedb216c6d 100644
--- a/xbmc/utils/Network.cpp
+++ b/xbmc/utils/Network.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2005-2008 Team XBMC
+ * Copyright (C) 2005-2010 Team XBMC
* http://www.xbmc.org
*
* This Program is free software; you can redistribute it and/or modify
@@ -29,6 +29,62 @@
using namespace std;
+/* slightly modified in_ether taken from the etherboot project (http://sourceforge.net/projects/etherboot) */
+bool in_ether (char *bufp, unsigned char *addr)
+{
+ if (strlen(bufp) != 17)
+ return false;
+
+ char c, *orig;
+ unsigned char *ptr = addr;
+ unsigned val;
+
+ int i = 0;
+ orig = bufp;
+
+ while ((*bufp != '\0') && (i < 6))
+ {
+ val = 0;
+ c = *bufp++;
+
+ if (isdigit(c))
+ val = c - '0';
+ else if (c >= 'a' && c <= 'f')
+ val = c - 'a' + 10;
+ else if (c >= 'A' && c <= 'F')
+ val = c - 'A' + 10;
+ else
+ return false;
+
+ val <<= 4;
+ c = *bufp;
+ if (isdigit(c))
+ val |= c - '0';
+ else if (c >= 'a' && c <= 'f')
+ val |= c - 'a' + 10;
+ else if (c >= 'A' && c <= 'F')
+ val |= c - 'A' + 10;
+ else if (c == ':' || c == '-' || c == 0)
+ val >>= 4;
+ else
+ return false;
+
+ if (c != 0)
+ bufp++;
+
+ *ptr++ = (unsigned char) (val & 0377);
+ i++;
+
+ if (*bufp == ':' || *bufp == '-')
+ bufp++;
+ }
+
+ if (bufp - orig != 17)
+ return false;
+
+ return true;
+}
+
CNetwork::CNetwork()
{
g_application.getApplicationMessenger().NetworkMessage(SERVICES_UP, 0);
@@ -149,6 +205,63 @@ void CNetwork::NetworkMessage(EMESSAGE message, int param)
}
}
+bool CNetwork::WakeOnLan(char* mac)
+{
+ int i, j, packet;
+ unsigned char ethaddr[8];
+ unsigned char buf [128];
+ unsigned char *ptr;
+
+ // Fetch the hardware address
+ if (!in_ether(mac, ethaddr))
+ {
+ CLog::Log(LOGERROR, "%s - Invalid hardware address specified (%s)", __FUNCTION__, mac);
+ return false;
+ }
+
+ // Setup the socket
+ if ((packet = socket (AF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0)
+ {
+ CLog::Log(LOGERROR, "%s - Unable to create socket (%s)", __FUNCTION__, strerror (errno));
+ return false;
+ }
+
+ // Set socket options
+ struct sockaddr_in saddr;
+ saddr.sin_family = AF_INET;
+ saddr.sin_addr.s_addr = htonl(INADDR_BROADCAST);
+ saddr.sin_port = htons(60000);
+
+ unsigned int value = 1;
+ if (setsockopt (packet, SOL_SOCKET, SO_BROADCAST, (char*) &value, sizeof( unsigned int ) ) == SOCKET_ERROR)
+ {
+ CLog::Log(LOGERROR, "%s - Unable to set socket options (%s)", __FUNCTION__, strerror (errno));
+ close (packet);
+ return false;
+ }
+
+ // Build the magic packet (6 x 0xff + 16 x MAC address)
+ ptr = buf;
+ for (i = 0; i < 6; i++)
+ *ptr++ = 0xff;
+
+ for (j = 0; j < 16; j++)
+ for (i = 0; i < 6; i++)
+ *ptr++ = ethaddr[i];
+
+ // Send the magic packet
+ if (sendto (packet, (char *)buf, 102, 0, (struct sockaddr *)&saddr, sizeof (saddr)) < 0)
+ {
+ CLog::Log(LOGERROR, "%s - Unable to send magic packet (%s)", __FUNCTION__, strerror (errno));
+ close (packet);
+ return false;
+ }
+
+ close (packet);
+ CLog::Log(LOGINFO, "%s - Magic packet send to '%s'", __FUNCTION__, mac);
+ return true;
+}
+
void CNetwork::StartServices()
{
#ifdef HAS_TIME_SERVER
diff --git a/xbmc/utils/Network.h b/xbmc/utils/Network.h
index 3d901fa7f4..3aa3d09909 100644
--- a/xbmc/utils/Network.h
+++ b/xbmc/utils/Network.h
@@ -103,6 +103,9 @@ public:
// Return true if there's at least one interface which is connected
bool IsConnected(void);
+ // Return true if the magic packet was send
+ bool WakeOnLan(char *mac);
+
// Get/set the nameserver(s)
virtual std::vector<CStdString> GetNameServers(void) = 0;
virtual void SetNameServers(std::vector<CStdString> nameServers) = 0;