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