3 changed files with 263 additions and 2 deletions
@ -0,0 +1,122 @@ |
|||||
|
#!/usr/bin/python -OO |
||||
|
# Copyright 2008-2010 The SABnzbd-Team <team@sabnzbd.org> |
||||
|
# |
||||
|
# This program is free software; you can redistribute it and/or |
||||
|
# modify it under the terms of the GNU General Public License |
||||
|
# as published by the Free Software Foundation; either version 2 |
||||
|
# of the License, or (at your option) any later version. |
||||
|
# |
||||
|
# This program is distributed in the hope that it will be useful, |
||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||||
|
# GNU General Public License for more details. |
||||
|
# |
||||
|
# You should have received a copy of the GNU General Public License |
||||
|
# along with this program; if not, write to the Free Software |
||||
|
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. |
||||
|
|
||||
|
import sys |
||||
|
if sys.version_info < (2,4): |
||||
|
print "Sorry, requires Python 2.4 or higher." |
||||
|
sys.exit(1) |
||||
|
|
||||
|
import logging |
||||
|
import logging.handlers |
||||
|
import os |
||||
|
import getopt |
||||
|
import signal |
||||
|
import glob |
||||
|
import socket |
||||
|
import platform |
||||
|
import time |
||||
|
import subprocess |
||||
|
|
||||
|
#------------------------------------------------------------------------------ |
||||
|
try: |
||||
|
import win32api, win32file |
||||
|
import win32serviceutil, win32evtlogutil, win32event, win32service, pywintypes |
||||
|
except ImportError: |
||||
|
if sabnzbd.WIN32: |
||||
|
print "Sorry, requires Python module PyWin32." |
||||
|
sys.exit(1) |
||||
|
|
||||
|
from sabnzbd.utils.mailslot import MailSlot |
||||
|
|
||||
|
#------------------------------------------------------------------------------ |
||||
|
|
||||
|
WIN_SERVICE = None |
||||
|
|
||||
|
#------------------------------------------------------------------------------ |
||||
|
def main(): |
||||
|
|
||||
|
mail = MailSlot() |
||||
|
if not mail.create(200): |
||||
|
return '- Cannot create Mailslot' |
||||
|
|
||||
|
while True: |
||||
|
msg = mail.receive() |
||||
|
if msg == 'restart': |
||||
|
time.sleep(1.0) |
||||
|
res = subprocess.Popen('net start SABnzbd', stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True).stdout.read() |
||||
|
rc = win32event.WaitForMultipleObjects((WIN_SERVICE.hWaitStop, |
||||
|
WIN_SERVICE.overlapped.hEvent), 0, 500) |
||||
|
if rc == win32event.WAIT_OBJECT_0: |
||||
|
mail.disconnect() |
||||
|
return '' |
||||
|
|
||||
|
|
||||
|
##################################################################### |
||||
|
# |
||||
|
# Windows Service Support |
||||
|
# |
||||
|
import servicemanager |
||||
|
class SABnzbdHelper(win32serviceutil.ServiceFramework): |
||||
|
""" Win32 Service Handler """ |
||||
|
|
||||
|
_svc_name_ = 'SABnzbdHelper' |
||||
|
_svc_display_name_ = 'SABnzbd Binary Newsreader (Helper)' |
||||
|
_svc_deps_ = ["EventLog", "Tcpip"] |
||||
|
_svc_description_ = 'Automated downloading from Usenet. ' \ |
||||
|
'This service helps SABnzbd to restart itself.' |
||||
|
|
||||
|
def __init__(self, args): |
||||
|
global WIN_SERVICE |
||||
|
win32serviceutil.ServiceFramework.__init__(self, args) |
||||
|
|
||||
|
self.hWaitStop = win32event.CreateEvent(None, 0, 0, None) |
||||
|
self.overlapped = pywintypes.OVERLAPPED() |
||||
|
self.overlapped.hEvent = win32event.CreateEvent(None, 0, 0, None) |
||||
|
WIN_SERVICE = self |
||||
|
|
||||
|
def SvcDoRun(self): |
||||
|
msg = 'SABnzbdHelper-service' |
||||
|
self.Logger(servicemanager.PYS_SERVICE_STARTED, msg + ' has started') |
||||
|
res = main() |
||||
|
self.Logger(servicemanager.PYS_SERVICE_STOPPED, msg + ' has stopped' + res) |
||||
|
|
||||
|
def SvcStop(self): |
||||
|
self.ReportServiceStatus(win32service.SERVICE_STOP_PENDING) |
||||
|
win32event.SetEvent(self.hWaitStop) |
||||
|
|
||||
|
def Logger(self, state, msg): |
||||
|
win32evtlogutil.ReportEvent(self._svc_display_name_, |
||||
|
state, 0, |
||||
|
servicemanager.EVENTLOG_INFORMATION_TYPE, |
||||
|
(self._svc_name_, unicode(msg))) |
||||
|
|
||||
|
def ErrLogger(self, msg, text): |
||||
|
win32evtlogutil.ReportEvent(self._svc_display_name_, |
||||
|
servicemanager.PYS_SERVICE_STOPPED, 0, |
||||
|
servicemanager.EVENTLOG_ERROR_TYPE, |
||||
|
(self._svc_name_, unicode(msg)), |
||||
|
unicode(text)) |
||||
|
|
||||
|
|
||||
|
|
||||
|
##################################################################### |
||||
|
# |
||||
|
# Platform specific startup code |
||||
|
# |
||||
|
if __name__ == '__main__': |
||||
|
|
||||
|
win32serviceutil.HandleCommandLine(SABnzbdHelper, argv=sys.argv) |
@ -0,0 +1,130 @@ |
|||||
|
#!/usr/bin/python -OO |
||||
|
# Copyright 2008-2010 The SABnzbd-Team <team@sabnzbd.org> |
||||
|
# |
||||
|
# This program is free software; you can redistribute it and/or |
||||
|
# modify it under the terms of the GNU General Public License |
||||
|
# as published by the Free Software Foundation; either version 2 |
||||
|
# of the License, or (at your option) any later version. |
||||
|
# |
||||
|
# This program is distributed in the hope that it will be useful, |
||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||||
|
# GNU General Public License for more details. |
||||
|
# |
||||
|
# You should have received a copy of the GNU General Public License |
||||
|
# along with this program; if not, write to the Free Software |
||||
|
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. |
||||
|
|
||||
|
""" |
||||
|
sabnzbd.mailslot - Mailslot communication |
||||
|
""" |
||||
|
|
||||
|
import os |
||||
|
from win32file import GENERIC_WRITE, FILE_SHARE_READ, \ |
||||
|
OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL |
||||
|
from ctypes import c_uint, c_buffer, byref, sizeof, windll |
||||
|
|
||||
|
# Win32API Shortcuts |
||||
|
CreateFile = windll.kernel32.CreateFileA |
||||
|
ReadFile = windll.kernel32.ReadFile |
||||
|
WriteFile = windll.kernel32.WriteFile |
||||
|
CloseHandle = windll.kernel32.CloseHandle |
||||
|
CreateMailslot = windll.kernel32.CreateMailslotA |
||||
|
|
||||
|
|
||||
|
class MailSlot(object): |
||||
|
""" Simple Windows Mailslot communication |
||||
|
""" |
||||
|
slotname = r'mailslot\SABnzbd\ServiceSlot' |
||||
|
|
||||
|
def __init__(self): |
||||
|
self.handle = -1 |
||||
|
|
||||
|
def create(self, timeout): |
||||
|
""" Create the Mailslot, after this only receiving is possible |
||||
|
timeout is the read timeout used for receive calls. |
||||
|
""" |
||||
|
slot = r'\\.\%s' % MailSlot.slotname |
||||
|
self.handle = CreateMailslot(slot, 50, timeout, None) |
||||
|
|
||||
|
return self.handle != -1 |
||||
|
|
||||
|
def connect(self): |
||||
|
""" Connect to existing Mailslot so that writing is possible |
||||
|
""" |
||||
|
slot = r'\\%s\%s' % (os.environ['COMPUTERNAME'], MailSlot.slotname) |
||||
|
self.handle = CreateFile(slot, GENERIC_WRITE, FILE_SHARE_READ, 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0) |
||||
|
return self.handle != -1 |
||||
|
|
||||
|
def disconnect(self): |
||||
|
""" Disconnect from Mailslot |
||||
|
""" |
||||
|
if self.handle != -1: |
||||
|
CloseHandle(self.handle) |
||||
|
self.handle = -1 |
||||
|
return True |
||||
|
|
||||
|
def send(self, command): |
||||
|
""" Send one message to Mailslot |
||||
|
""" |
||||
|
if self.handle == -1: |
||||
|
return False |
||||
|
w = c_uint() |
||||
|
return bool(WriteFile(self.handle, command, len(command), byref(w), 0)) |
||||
|
|
||||
|
def receive(self): |
||||
|
""" Receive one message from Mailslot |
||||
|
""" |
||||
|
r = c_uint() |
||||
|
buf = c_buffer(1024) |
||||
|
if ReadFile(self.handle, buf, sizeof(buf), byref(r), 0): |
||||
|
return buf.value |
||||
|
else: |
||||
|
return None |
||||
|
|
||||
|
|
||||
|
#------------------------------------------------------------------------------ |
||||
|
# Simple test |
||||
|
# |
||||
|
# First start "mailslot.py server" in one process, |
||||
|
# Then start "mailslot.py client" in another. |
||||
|
# Five "restart" and one "stop" will be send from client to server. |
||||
|
# The server will stop after receiving "stop" |
||||
|
|
||||
|
if __name__ == '__main__': |
||||
|
import sys |
||||
|
from time import sleep |
||||
|
|
||||
|
if not __debug__: |
||||
|
print 'Run this test in non-optimized mode' |
||||
|
exit(1) |
||||
|
|
||||
|
if len(sys.argv) > 1 and 'server' in sys.argv[1]: |
||||
|
|
||||
|
recv = MailSlot() |
||||
|
ret = recv.create(2) |
||||
|
assert ret, 'Failed to create' |
||||
|
while True: |
||||
|
data = recv.receive() |
||||
|
if data is not None: |
||||
|
print data |
||||
|
if data.startswith('stop'): |
||||
|
break |
||||
|
sleep(2.0) |
||||
|
recv.disconnect() |
||||
|
|
||||
|
elif len(sys.argv) > 1 and 'client' in sys.argv[1]: |
||||
|
|
||||
|
send = MailSlot() |
||||
|
ret = send.connect() |
||||
|
assert ret, 'Failed to connect' |
||||
|
for n in xrange(5): |
||||
|
ret = send.send('restart') |
||||
|
assert ret, 'Failed to send' |
||||
|
sleep(2.0) |
||||
|
send.send('stop') |
||||
|
assert ret, 'Failed to send' |
||||
|
send.disconnect() |
||||
|
|
||||
|
else: |
||||
|
print 'Usage: mailslot.py server|client' |
Loading…
Reference in new issue