cjdns.py 3.1 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394
  1. # You may redistribute this program and/or modify it under the terms of
  2. # the GNU General Public License as published by the Free Software Foundation,
  3. # either version 3 of the License, or (at your option) any later version.
  4. #
  5. # This program is distributed in the hope that it will be useful,
  6. # but WITHOUT ANY WARRANTY; without even the implied warranty of
  7. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  8. # GNU General Public License for more details.
  9. #
  10. # You should have received a copy of the GNU General Public License
  11. # along with this program. If not, see <http://www.gnu.org/licenses/>.
  12. import sys;
  13. import socket;
  14. import hashlib;
  15. from bencode import *;
  16. BUFFER_SIZE = 1024;
  17. def callfunc(cjdns, funcName, password, args):
  18. sock = cjdns.socket;
  19. sock.send('d1:q6:cookiee');
  20. data = sock.recv(BUFFER_SIZE);
  21. benc = bdecode(data);
  22. cookie = benc['cookie'];
  23. req = {
  24. 'q': 'auth',
  25. 'aq': funcName,
  26. 'hash': hashlib.sha256(password + cookie).hexdigest(),
  27. 'cookie' : cookie,
  28. 'args': args
  29. };
  30. reqBenc = bencode(req);
  31. req['hash'] = hashlib.sha256(reqBenc).hexdigest();
  32. reqBenc = bencode(req);
  33. sock.send(reqBenc);
  34. data = sock.recv(BUFFER_SIZE);
  35. return bdecode(data);
  36. def cjdns_connect(ipAddr, port, password):
  37. sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM);
  38. sock.connect((ipAddr, port));
  39. # Make sure it pongs.
  40. sock.send('d1:q4:pinge');
  41. data = sock.recv(BUFFER_SIZE);
  42. if (data != 'd1:q4:ponge'):
  43. raise Exception("Looks like " + ipAddr + ":" + port + " is to a non-cjdns socket.");
  44. # Get the functions and make the object
  45. sock.send('d1:q7:invalide');
  46. data = sock.recv(BUFFER_SIZE);
  47. benc = bdecode(data);
  48. cc = ("class Cjdns:\n"
  49. + " def __init__(self, socket):\n"
  50. + " self.socket = socket;\n"
  51. + " def disconnect(self):\n"
  52. + " self.socket.close();\n");
  53. for func in benc['availableFunctions']:
  54. funcDict = benc['availableFunctions'][func];
  55. cc += " def " + func + "(self";
  56. for arg in funcDict:
  57. cc += ", " + arg;
  58. cc += ("):\n"
  59. + " args = {");
  60. for arg in funcDict:
  61. cc += "\"" + arg + "\": " + arg + ", ";
  62. cc += ("};\n"
  63. + " return callfunc(self, \"" + func + "\", \"" + password + "\", args);\n");
  64. exec cc;
  65. cjdns = Cjdns(sock);
  66. # Check our password.
  67. ret = callfunc(cjdns, "ping", password, {});
  68. if ('error' in ret):
  69. raise Exception("Connect failed, incorrect admin password?\n" + ret);
  70. cjdns.functions = "";
  71. nl = "";
  72. for func in benc['availableFunctions']:
  73. funcDict = benc['availableFunctions'][func];
  74. cjdns.functions += nl + func + "(";
  75. nl = "\n";
  76. sep = "";
  77. for arg in funcDict:
  78. cjdns.functions += sep;
  79. sep = ", ";
  80. argDict = funcDict[arg];
  81. if (argDict['required'] == 1):
  82. cjdns.functions += "required ";
  83. cjdns.functions += argDict['type'] + " " + arg;
  84. cjdns.functions += ")";
  85. return cjdns;