diff options
author | vdrfan <vdrfan@svn> | 2010-01-30 15:47:15 +0000 |
---|---|---|
committer | vdrfan <vdrfan@svn> | 2010-01-30 15:47:15 +0000 |
commit | 5cf5faa518890513bca598ffff79939baa31c41b (patch) | |
tree | 9f01dae80e940b2b1c5136bda8064238f89b311a | |
parent | 3f21a9613dc998abcb54536ceea1c2b5420148a9 (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.cpp | 5 | ||||
-rw-r--r-- | xbmc/utils/Network.cpp | 115 | ||||
-rw-r--r-- | xbmc/utils/Network.h | 3 |
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; |